# 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. ## 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 `: 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`: ```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. ## Next - [MCP quickstart](/docs/mcp/quickstart) - [Tool reference](/docs/mcp/tools) - [Keys and access](/docs/mcp/keys-and-access)