Use Brault from Claude.ai, Claude Code and Cursor
Connect Claude or any other MCP client to your brandspace, either by signing in to Brault or with an API key scoped to what the agent may do.
The Brault MCP server lets an AI agent work in your brandspace: search and read files, upload and import them, create folders, move, rename and tag assets, work with boards, comments and pages, manage shared links and send transfers.
No tool destroys content. Nothing deletes, trashes or restores a file, a version, a
folder, a library, a board, a page, a comment, a reply or a shared link — there is no tool
for any of that. Two tools cannot be undone, and they say so to your client, which may ask
you to confirm them: remove_file_from_board takes a file off a board and discards the
values that board holds for it, leaving the file itself untouched — members who could see
the file only through that board lose access to it — and expire_transfer ends a transfer
at once.
Some tools make content public. create_shared_link, update_shared_link,
publish_page, create_transfer, complete_transfer and update_transfer create or
change a link that works for anyone who holds it. Their descriptions tell the agent so, and
the ones that create a link or widen who can reach it tell the agent to confirm with you
first. Whether you are actually asked is up to your client. They need shares:write,
pages:write or transfers:write: leave those scopes out of a connection that must not
publish.
There are two ways to connect.
- Sign in. Claude.ai and Claude Code send you to a Brault page where you pick one brandspace and approve what the client asked for. You never create or paste a key.
- API key. Cursor, and any other client that takes a header, authenticates with a
bsk_key — see Get an API key.
Either way the address is the same, on the central host:
api.brault.app— this host is the same in every regionhttps://api.brault.app/mcpUse that host. The server also answers on a regional host such as us.api.brault.app, but
the discovery document a signing-in client reads always names the central host as the
resource it protects, so a client that dialled a regional URL is handed a resource that
does not match the URL it called and must refuse it (RFC 9728 § 3.3). A client using an API
key reaches the same server on either host, and has no reason to write the other one.
1. Connect Claude.ai
In Claude's settings open Connectors, add a custom connector and paste the URL above. Claude registers itself and opens the Brault consent page in your browser. Sign in if you are not already, then:
- Pick the brandspace. One connection covers one brandspace. A brandspace whose plan has no API access, or whose billing is blocked, cannot be picked.
- Approve the scopes. The page lists the scopes the client asked for; you can approve fewer, never more.
- Allow. If your account has two-factor authentication, Brault asks for a fresh factor before it creates the connection.
The page names the client and the host it will send you back to — claude.ai or
claude.com here — and never renders a logo the client supplied. The client's name is
chosen by whoever registered it, so read the name and that host before you allow.
Claude then holds a connection that acts as you, in that one brandspace, limited to the scopes you approved.
2. Connect Claude Code
Claude Code can sign in the same way — no key, no header:
api.brault.app— this host is the same in every regionclaude mcp add --transport http brault https://api.brault.app/mcpThen run /mcp inside Claude Code and authenticate brault. The same consent page opens,
and Claude Code is sent back to a loopback address on your own machine rather than to a
public host — the consent page says so.
To use a key instead — a shared machine, a script, CI — pass it as a header:
api.brault.app— this host is the same in every regionclaude mcp add --transport http brault https://api.brault.app/mcp \
--header "Authorization: Bearer $BRAULT_API_KEY"3. Connect Cursor
Cursor authenticates with an API key. Add to ~/.cursor/mcp.json:
api.brault.app— this host is the same in every region{
"mcpServers": {
"brault": {
"url": "https://api.brault.app/mcp",
"headers": { "Authorization": "Bearer <your key>" }
}
}
}What you are granting
A connection and a key both carry scopes, and they mean the same thing:
| To let the agent… | Scopes |
|---|---|
| Search, read and download files | files:read |
| Upload, import, move, rename and tag files, and create folders | files:write |
| Read or organize boards and properties | boards:read (+ boards:write to change them) |
| Read or write comments | comments:read, comments:write |
| Read, write, publish or unpublish pages | pages:read, pages:write |
| Read shared links, or create and change them | shares:read, shares:write |
| Read transfers, or send, change and expire them | transfers:read, transfers:write |
| See who is in the brandspace and what each role may do | members:read |
A write scope does not include the matching read scope, so keep both when the agent has to find something before it can change it. The agent only sees the tools its scopes allow.
A scope is a ceiling, not a grant. Every tool call is checked against your own live
permissions at the moment it runs, intersected with the scopes. Approving files:write for
a member who cannot write does not create write access; it creates a connection whose
writes are refused. If your permissions change later, the connection follows them.
Those thirteen scopes are the whole list a consent can ask for: they are the scopes at
least one MCP tool needs. webhooks:manage is never offered, so a connection can never
hold it. An API key still can, for the REST API.
A client that asks for no scope in particular is offered all thirteen. The consent page shows one row per scope, and you can approve fewer.
The tools
79 tools, grouped by what they work on. get_context and get_usage need no scope; every
other tool is shown to the agent only when its scope was granted.
| Area | Tools |
|---|---|
| Context | get_context, get_usage |
| Members and roles | list_members, get_member, list_roles |
| Libraries and folders | list_libraries, get_library, create_library, update_library, list_folders, get_folder, create_folder, update_folder, move_folder |
| Files | search, list_files, get_file, find_similar_files, update_file, move_file, copy_file, set_file_property, list_file_boards |
| Versions | list_file_versions, activate_file_version |
| Uploads and imports | start_upload, get_upload_part_urls, complete_upload, abort_upload, import_file_from_url, get_import_status |
| Downloads | get_download_link, start_zip_download, get_zip_download |
| Boards | list_boards, get_board, query_board, create_board, update_board, list_board_members, add_files_to_board, remove_file_from_board, set_board_file_property |
| Properties | list_properties, create_property, update_property, add_property_option, update_property_option, create_board_property, update_board_property, add_board_property_option, update_board_property_option |
| Comments | list_comments, get_comment, add_comment, update_comment, resolve_comment, reopen_comment, list_replies, reply_to_comment, update_reply |
| Pages | list_pages, get_page, create_page, append_page_blocks, publish_page, unpublish_page |
| Shared links | list_shared_links, get_shared_link, create_shared_link, update_shared_link |
| Transfers | create_transfer, get_transfer_upload_part_urls, complete_transfer_upload, complete_transfer, list_transfers, get_transfer, update_transfer, expire_transfer |
A few things the table does not show:
- Moves and copies go one item per call.
move_file,copy_fileandmove_foldereach take one file or folder. There is no tool to restore from the trash, and none to manage webhooks. - People appear as user ids in comments, replies and
list_board_members. The agent turns an id into a name withlist_membersorget_member, which needmembers:read. list_board_membersandlist_file_boardsshow at most 200 entries. They cannot be paged; past 200 the answer says how many were left out.- Only reads and
add_files_to_boardare safe to repeat. Every other tool that changes something takes effect again each time it is called, even with the same arguments.
Uploading a file
The bytes of a file never pass through the MCP server. An upload is three steps:
start_uploadreserves the file and answers with acurlcommand that sends its bytes to storage.- The client runs that command where the file is.
complete_uploadcreates the file in your brandspace.
A large file is sent in parts: get_upload_part_urls hands out one command per part.
abort_upload gives up an upload that was started. A transfer of files from your computer
works the same way, with create_transfer, get_transfer_upload_part_urls,
complete_transfer_upload and complete_transfer.
Step 2 needs a client that can run a command where the file is. Claude Code and Cursor
can. Claude.ai and other hosted clients cannot reach a file on your computer: there, give
the agent a public link to the file and it uses import_file_from_url.
The URL in that command allows writing that one file and nothing else, until the upload session expires. It is written into the conversation, so whoever can read the transcript can read the URL.
Disconnecting
- Your own connections — Settings → Security → Connected apps lists every app you connected, in every brandspace, with its scopes and when it was last used. Disconnect kills its tokens immediately, and the client has to be authorized again before it can do anything.
- Every connection in a brandspace — Developers → Connections lists them for all
members, with who created each one. Disconnecting someone else's needs the
developers.managepermission and, if your account has two-factor authentication, a fresh factor — the same step-up the consent page asks for. Disconnecting your own never asks for one. - A disconnected connection stays in both lists for 30 days, with the reason it ended, and then disappears.
Most reasons read plainly — you disconnected it, an admin did, or the client itself asked Brault to. Two are ours:
refresh_reuse— the client presented a refresh token it had already exchanged for a new one, so Brault ended the connection as a precaution.code_reuse— the one-time code from the sign-in was presented twice, so Brault ended the connection as a precaution.
Both mean a credential was replayed, which is what a stolen one looks like. Nothing in your brandspace is affected: connect again.
A connection can also stop working without anyone pressing anything:
- You leave the brandspace, or lose access to it. The connection is paused, and Brault emails the brandspace's owners and admins.
- The plan loses API access, or billing is blocked. Calls are refused until that is fixed.
- It goes unused for 30 days. The access token lives one hour and the client refreshes it silently; each refresh extends the connection by another 30 days. A connection that goes 30 days without one cannot be renewed — connect again. This is the one ending that shows nothing: the row stays active in both lists, with no reason beside it, for as long as it is listed. A connection that looks fine but has stopped working is usually this one.
- The client's registration expires after 90 days. The first time you connect an app it registers itself with Brault. A registration that holds no live token and goes 90 days unused is expired, and later deleted. The app registers again by itself on the next attempt — you only have to approve the connection once more.
Limits
-
20 active connections per member per brandspace — the default, and Brault can raise it. Disconnected ones do not count, even while they are still listed for their 30 days. Connections do not count against your plan's API-key limit and never appear in the API keys tab.
-
Every tool call is an ordinary API request made as you: it counts against the brandspace's rate limits and monthly quota, like any integration (see Plans and limits).
-
The MCP endpoint has three budgets a minute, charged in this order, and a request stops at the first one it exceeds:
Budget Limit Counts Per IP address 3000 every request, signed in or not Per credential 300 requests carrying a connection or a key Unauthenticated 60 requests carrying neither Past any of them the answer is
429withRetry-After. One agent turn is several requests, so the per-credential 300 is the one an individual agent tends to meet.The per-IP budget is the one worth knowing about, because it is the only one you share. Claude.ai reaches Brault from Anthropic's egress addresses, which every Brault customer connected through Claude.ai comes from — so a
429can land on a request you know was your first in a while. It is not your budget and nothing is wrong with your connection; wait out theRetry-Afterand carry on. It is per IP by design: budgeting only per credential would let a flood of made-up ones mint itself a fresh 300 every request. -
In the Developers request log and its CSV export, MCP calls carry the user agent
brault-mcp/<version> (<tool>), so you can tell which tool made each request, and a connection's requests are attributed to the member who approved it.
If you are writing your own MCP client
Nothing below is something a Claude.ai, Claude Code or Cursor user has to think about — those clients stay inside these bounds on their own. They matter if you are speaking the protocol yourself.
- A request body is capped at 1.25 MB. Over that the answer is
413with the JSON-RPC error-32600; a body that is not valid JSON is400with-32700. A single tool call carries about 1 MB at most in any case. - A batch carries at most 20 messages. A longer array is refused with
400and-32600, before the credential is read and before any tool runs. - A
401anywhere in a batch discards the whole batch. When a credential is dead or expired, the answer is the HTTP401challenge for the entire request rather than one message's result — it is what tells you to refresh — so it replaces the answers to every message in that batch, including the ones that had already succeeded. Re-authenticate and send the batch again. Replaying is only safe if the tools in it are, so batch reads freely and send writes one per request.