MCP Interface Guide
This guide walks through everything needed to let an agentic tool (Claude
Code, Claude Desktop, or any other MCP
client) talk to an Adapt server: creating an account, granting it
permissions, minting an API key, and pointing the client at /mcp/.
What Is the MCP Interface?
Adapt mounts a Model Context Protocol
server at /mcp/ on the same FastAPI app adapt serve already runs. It
exposes five tools — list_resources, get_schema, read_resource,
write_resource, and search — that wrap the exact same permission checks
and plugin methods the REST API and browser UI use. There is no separate API
surface and no separate process to run: if a user can read or write a
resource over /api/*, the same user can do it through MCP, and nothing
more.
Authentication is enforced when a tool executes, not during MCP initialization or tool discovery. MCP uses Adapt's shared authentication resolver, so a tool call can authenticate with either a session cookie or an API key. API keys are the supported and recommended mechanism for MCP clients. A client that sends a session cookie must also handle CSRF on its HTTP POST requests.
Prerequisites
- Adapt installed (
pip install adapt-server) and a docroot with at least one resource (see the Quick Start). - An MCP-capable client. This guide shows examples for the Claude Code CLI and a generic JSON config that works with most desktop MCP clients.
Step 1: Create a Superuser and Start the Server
adapt addsuperuser /path/to/docroot --username admin
adapt serve /path/to/docroot
Step 2: Create Permissions for Your Resources
This generates <resource>_readonly and <resource>_readwrite groups for
each discovered resource, so you can assign users without hand-building
permission rows:
adapt admin create-permissions /path/to/docroot __all__
adapt admin list-groups /path/to/docroot
Pass specific resource namespaces instead of __all__ if you only want
permissions generated for some resources. The command also creates combined
groups named read_resources_<selected-resource-suffix> and
all_resources_<selected-resource-suffix>. The suffix contains all selected
resource names in sorted order, joined with underscores.
Step 3: Create a User for the Agent and Grant Access
Give the agent its own account rather than reusing the superuser's — it keeps audit logs meaningful and lets you revoke access without touching anything else.
Successful write_resource calls create the same dataset audit records as
REST mutations.
adapt admin create-user /path/to/docroot --username agent --password <a-strong-password>
adapt admin add-to-group /path/to/docroot --username agent --group <resource>_readonly
Use the <resource>_readwrite group instead (or in addition) if the agent should
also be able to create/update/delete rows via write_resource. Repeat
add-to-group for every resource namespace the agent needs.
Step 4: Create an API Key
Sign in as agent at /auth/login, open /profile, and create an API key.
No superuser involvement is needed for a user to create their own key.
The raw API key is shown only once. Save it somewhere safe; only its hash is stored server-side.
A superuser can also mint (or revoke) a key on another user's behalf from
the admin UI (/admin/ → API Keys → Create, choosing the agent
user) — useful for provisioning an agent's key without sharing its password,
but it's an admin convenience, not a requirement.
Step 5: Verify the MCP Endpoint Is Reachable
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-X POST http://localhost:8000/mcp/ \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
A 200 OK with a JSON-RPC response body means the server is up. Initialization
does not authenticate the user. The configured credentials are checked when
the client executes a tool.
Step 6: Point an Agentic Tool at It
Claude Code (CLI)
claude mcp add --transport http adapt http://localhost:8000/mcp/ \
--header "X-API-Key: <key>"
Generic MCP Client Config (Claude Desktop and similar)
Most desktop clients that support remote/HTTP MCP servers accept a config block similar to this — check your client's docs for the exact key names:
{
"mcpServers": {
"adapt": {
"url": "http://localhost:8000/mcp/",
"headers": {
"X-API-Key": "<key>"
}
}
}
}
Use https:// and a certificate the client trusts once you're off
localhost — see Security for TLS setup.
Step 7: What the Agent Can Do
| Tool | Equivalent REST call | Notes |
|---|---|---|
list_resources |
GET / (JSON) |
Every namespace the agent may read, with its type. |
get_schema |
GET /schema/{resource}/ |
Columns and types for a dataset resource. |
read_resource |
GET /api/{resource}/ |
Accepts limit, offset, sort, order, filter for datasets. sort is the column name; order must be asc or desc. |
write_resource |
POST/PATCH/DELETE /api/{resource}/ |
action is "create", "update", or "delete"; see the mutation section. |
search |
GET /search |
Full-text search across every resource the agent may read. |
Once the client is connected, ask the agent something like "what data do you
have access to?" — it should call list_resources on its own — or "search
for parental leave policy" to exercise search.
To read products sorted by category ascending, pass MCP tool arguments like:
{
"resource": "products",
"sort": "category",
"order": "asc"
}
Troubleshooting
- "Authentication required" from every tool call — the
X-API-Keyheader is missing, misspelled, or the client isn't forwarding custom headers for HTTP MCP servers. Re-check Step 6. - "Permission denied: read/write on
<namespace>" — the agent's user isn't in a group with that permission. Revisit Step 3 andadapt admin list-groups. - "Unknown resource" — the namespace doesn't match what
list_resourcesreports; namespaces are the file's relative path without its extension (e.g.products, notproducts.csv), unless asub_namespace(Excel sheet name) applies. - "Server is in read-only mode" — the server was started with
--readonlyorreadonly: trueinconf.json;write_resourceis disabled entirely regardless of permissions. - No
/mcp/route at all — the server hasmcp_enabled: falsein.adapt/conf.jsonorADAPT_MCP_ENABLED=falseset. See Configuration.
Manual navigation: Previous: Security | Index | Next: Configuration