MCP Server
How the MCP server works
The Harny MCP server lets a coding assistant call Harny over one HTTP address, with the same limits as the REST API.
Copy page
Transport and the two doors
The MCP server uses Streamable HTTP at https://api.harny.ai/v1/mcp/mcp.
The address has two doors, decided by the Authorization header:
- No Authorization header: the server lists only
provision_app. Authorization: Bearer <key>: the server lists the tools that key may call.
A person's key starts with fsk_. The app key starts with fsa_. The server accepts bearer keys and sign-in tokens.
Sign-in
Sign-in is built. The app's owner signs in on the Harny console, picks or creates the app and approves a coding assistant. The assistant then holds a token that lasts an hour and renews, instead of a copied key. Its address is not published yet, so connect with a key until it is.
A sign-in token reaches what the app key reaches for that one app, except provision_app: describe, get_snippet, diagnose, provision_user, get_claim_link and get_setup_bundle. provision_user returns the person's id and never a key. A token never makes an owner-only change, such as a setting, a key or billing. It works only at the address it was issued for, and the owner can disconnect the assistant at any time, which ends the token.
How a key scopes calls
Every call is scoped to the key's user. The app key reaches provision_user, get_claim_link and get_setup_bundle. A person's key reaches that person's memory and connected accounts. Any key reaches describe, get_snippet and diagnose.
Calls follow the same limits and refusals as the REST routes they wrap. A call over the per-minute limit returns 429 with a Retry-After header.
The tools wrap REST routes
ingest_text wraps POST /v1/vault/ingest/text. assemble_context wraps POST /v1/context/assemble. provision_app makes a new app and its key, as POST /v1/auth/provision does. provision_user adds a person or returns the one that exists, as POST /v1/users does.
ingest_text is not for streaming conversation transcripts. It is subject to the app's ingest quotas.
For the Memory API routes under /v1/memory, see the Memory API docs.
Tool groups
| Group | Tools | Needs |
|---|---|---|
| Organization | describe, get_snippet, list_tools | describe and get_snippet take any key. list_tools takes a person's key. |
| Apps and keys | provision_app, get_claim_link, get_setup_bundle | provision_app needs no key. The others need the app key. |
| Memory | ingest_text, assemble_context, action_history | A person's key. |
| Members and access | provision_user, configure_oauth | provision_user needs the app key. configure_oauth needs a person's key. |
| Debugging | diagnose | Any key. |
describe is the first call an assistant should make. It returns what this key reaches, with the tool schemas.
provision_app returns the app key once. Put that key in your secret store and nowhere else.
Connect a client
In Claude Code, run:
claude mcp add --transport http harny https://api.harny.ai/v1/mcp/mcp --header "Authorization: Bearer $HARNY_USER_KEY"
In Cursor, add this to mcp.json:
{"mcpServers": {"harny": {"url": "https://api.harny.ai/v1/mcp/mcp", "headers": {"Authorization": "Bearer ${env:HARNY_USER_KEY}"}}}}Set up with a coding agent
If your coding agent can run commands, follow https://harny.ai/auth.md instead of provision_app. Its command never shows the key.