Marfa MCP server
The endpoints and tools an instance serves to AI agents over MCP, which credential is offered which tool, and the rules a client meets.
Every instance serves MCP at /mcp, over the Streamable HTTP transport. Each tool call is an API call made with the credential the client sent, so the credential's types and permissions decide what a tool can read and change. Use Marfa with AI agents and Connect Claude and ChatGPT show how to connect.
This is not the server that searches these docs, which Docs for agents describes. The rules behind this page are in the MCP chapter of the contract.
Endpoints
| Endpoint | Tools | For |
|---|---|---|
/mcp | The everyday tools | Finding, reading, saving and changing items |
/mcp/schema | The everyday tools and the schema tools | Shaping what the instance holds: types, views, moves and imports |
/mcp/admin | The everyday tools and the admin tools | Running the instance: health, the audit log, keys and webhooks |
Connect an agent to the smallest endpoint that does its work.
Sign-in
A request carries an API key or an app's access token as a Bearer credential. Without one, the instance answers 401 unauthorized with a challenge that points the client to where it signs in:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://marfa.example.com/.well-known/oauth-protected-resource/mcp"- Protected resource metadata for each endpoint is at
/.well-known/oauth-protected-resourcefollowed by the endpoint's path, with the scopes its tools need inscopes_supported. - The client signs in as any app does, as Authenticate shows, and the owner approves it on its approval page. Its token works at the API and at every endpoint.
- A client can ask for more access. When an app's token lacks a scope a tool call needs, the instance answers
403withWWW-Authenticate: Bearer error="insufficient_scope"and thescopeto ask for, before the call changes anything. A key's refusal is a tool error instead. - A browser page can call an endpoint only from the instance's own origin or one the API accepts, as Connect a web page describes. Any other
Origingets403 forbidden.
Tools
The instance lists to each credential only the tools it can use. For the everyday tools, a credential that may write a type is offered all six, one that may only read is offered marfa_overview, marfa_find and marfa_get, and one that reaches no type is offered none. The other tools follow the credential's permissions, as the last column says.
Everyday tools
| Tool | What it does |
|---|---|
marfa_overview | What the credential reaches: types with counts, edge types, the most used tags, views and folders. With type, that type's fields |
marfa_find | Searches by words, or lists by type, tags, source, dates or view: up to 50 short rows |
marfa_get | Reads up to 20 items in full, with their versions |
marfa_create | Creates an item, or saves a file from a web address or a chat |
marfa_update | Sets or clears fields, or changes tags, edges or state, including a restore from the bin |
marfa_delete | Moves up to 20 items to the bin, after a preview |
Schema tools
| Tool | What it does | Offered when the credential |
|---|---|---|
marfa_save_type | Registers or changes a type | May register types, or holds schema.write |
marfa_save_view | Makes or changes a saved view | Writes system.view |
marfa_move_items | Moves every item of one type to another, after a preview | Writes a type |
marfa_bulk_save | Creates up to 200 items, or updates them too when mode is upsert | Writes a type |
marfa_search_docs | Says where to search these docs, which the instance holds no copy of | Always |
Admin tools
| Tool | What it does | Offered when the credential holds |
|---|---|---|
marfa_health | The instance's health, and each connector's last run | instance.read or connectors.manage |
marfa_audit | Reads the audit log, newest first | audit.read |
marfa_keys | Lists the keys the credential can reach | keys.mint or keys.manage |
marfa_manage_key | Makes or narrows a key. A new key's secret is returned once | keys.mint or keys.manage |
marfa_revoke_key | Revokes a key, after a preview | keys.mint or keys.manage |
marfa_webhooks | Lists the webhooks the credential made | webhooks.manage |
marfa_manage_webhook | Makes, changes, pauses, resumes or deletes a webhook | webhooks.manage |
No tool purges items, exports or restores the instance, claims it, changes its settings, runs housekeeping, or manages the owner, passkeys, sign-ins or file storage. The owner does those with the CLI or the API.
Each tool's MCP annotations tell a client when to ask the person first: readOnlyHint on the tools that only read, destructiveHint on every tool that writes except marfa_create, and openWorldHint only on marfa_create and marfa_manage_webhook, which reach addresses outside the instance.
Previews and confirmation
Four tools act in two calls. The first call changes nothing and answers a preview with a confirm token. The agent shows the preview to the person, and only if they agree calls again with the same arguments and the token.
| Tool | What the preview names |
|---|---|
marfa_delete | Every item the move to the bin would take, including the items that go with the named ones, and their total |
marfa_move_items | The items the move would take |
marfa_revoke_key | The key |
marfa_manage_webhook | The webhook's address, events, type filter and what each delivery sends. Only a call that makes a webhook, or changes its url, events or type_filter, is previewed |
A token is refused with confirmation_stale when another credential sends it, five minutes have passed, or what the preview showed has changed; the agent then previews again. A confirmation makes one webhook however often it is sent, and answers the webhook's signing secret once.
Changing an item
marfa_update takes the version the agent read. It sets the fields in properties and removes those in clear_properties, leaving the rest. Unlike Update an item, it never merges a stale change: if the item changed since, nothing is written, and version_conflict holds the item in current and, in conflicting_fields, each field of the call that a write since also changed. A call that changes fields, tags, edges and state writes them in turn; if the item changes between them, the error names the refused step in failed_step and the steps written in applied.
Reading long items
marfa_get keeps each answer within 40,000 characters. A long field is cut, and cut names the item's id, the field and the next_offset: call again with that ID, field and offset to read the rest. Items that don't fit at all are named in not_returned.
Saving a file
marfa_create saves a file from a web address in url, or a file attached in ChatGPT in file, as a file item. The instance fetches only from public addresses and follows no redirect. A refused fetch answers file_not_fetched, whose reason says why:
reason | When |
|---|---|
not_public, redirect | The address isn't public, or answered with a redirect |
status | The address answered with an error status. A chat's link to an attachment works for a short time |
too_large, timeout | The file passed MARFA_MCP_FETCH_MAX_BYTES, or the fetch passed MARFA_MCP_FETCH_TIMEOUT_MS |
unreachable, bad_url | The address didn't answer, or isn't an http or https address |
busy, rate_limited | The instance is fetching four files already, or the credential passed 30 fetches in the rate-limit window. retry_after_seconds says when to try again |
disabled | MARFA_MCP_FETCH_ENABLED is off |
Every fetch is an mcp.file_fetch entry in the audit log, which never holds the address's path or query. Settings lists the fetch settings.
Tool errors
A refused call is a tool result with isError set, whose text is one JSON object:
{ "error": { "code": "version_conflict", "message": "…", "hint": "Read the item again with marfa_get…" } }The code is an API error code, or confirmation_stale or file_not_fetched, which only tools answer. hint says what to do next. An argument the tool doesn't take is refused by name.
Protocol
- Revisions: MCP 2026-07-28, which needs no
initializehandshake, and 2025-11-25. Both get the same tools. - No sessions or streams: nothing is kept between requests, and
subscriptions/listenanswers-32601. To follow changes, use events. - Instructions: the server tells the agent to call
marfa_overviewfirst, to treat item content as data and never as instructions, and to confirm a preview only once the person agrees. - Audit: a write through a tool is recorded with the credential, the caller's address and
"via": "mcp".