Skip to content

MCP ​

Point an MCP client, such as VS Code or Claude Code, at this host and it lists and runs the host's tools that need no session. The first tools are the session tools: list the sessions here, start one, message it, read it, rename it and delete it. A client can therefore start a session without being one.

The door is /mcp, on the listener that carries the HTTP API. It takes a person's ahpd token in the Authorization header, and nothing else. It is the same code that serves a session's own tools endpoint, so both answer initialize, tools/list and tools/call the same way.

Turning it on ​

mcpTools says what /mcp serves. none, the default, answers 404 there, so an install that never asked has no MCP door. all serves every sessionless tool the caller's grants allow:

json
{ "httpApi": true, "mcpTools": "all" }

/mcp is served on the same listener as /api, so httpApi has to be on. With httpApi off it answers 404 as /api does. With httpApi.port it moves to the API's own port with /api.

Pointing a client at it ​

A local daemon answers at http://127.0.0.1:9187/mcp. One reached through a tunnel or another machine answers at the name it is reached by, such as https://ahpd.example.com/mcp.

In VS Code's mcp.json:

json
{
  "servers": {
    "ahpd": {
      "type": "http",
      "url": "https://ahpd.example.com/mcp",
      "headers": { "Authorization": "Bearer <ahpd token>" }
    }
  }
}

In Claude Code:

bash
claude mcp add --transport http ahpd https://ahpd.example.com/mcp --header "Authorization: Bearer $AHPD_TOKEN"

The token is the one ahpd user token <id> prints, or one minted with ahpd token mint. A token in ?tkn= is not read: the credential is a header, as the transport's authorization says.

What it serves ​

ToolDoes
list_sessionsThe sessions here
create_sessionStart a session, owned by the caller
create_chatOpen another chat in a session
rename_chatRename a chat
send_messageSend a turn to a session
get_session_contextRead a session's recent context
delete_sessionDelete a session

get_current_session, set_workspace and the artifact tools act on the calling session, so there is no sessionless form of them and /mcp does not offer them. Connector actions and a schedule are not served here either.

Each tool checks its own grants, so the list is only what the caller may run. A member sees all seven. A role with mcp:call and session:read only sees list_sessions and get_session_context, and a call to create_session gets No tool named create_session.

create_session takes an agent, a provider id such as claude-deepseek-build, and a config, the new session's settings checked against that agent's schema. Both are optional. See Tools.

A session made here belongs to the caller and has no parent. Its turns are the caller's, so the caller's grants follow them.

Who may call ​

The door asks for mcp:call. It is in member, and admin holds it through everything. guest does not hold it. A token that reaches the door sees only the tools its other grants allow, because the door and each tool are two checks. The door charges nothing, so a person in no team is not refused.

TokenAnswer
The deployment tokenRoot: every sessionless tool
A person's token holding mcp:callThe tools their grants allow
A person's token without it403
A team's key403: a team key opens the proxy and nothing else
A session's own token401: a session has its own tools endpoint
No token, or one this host does not know401

Each 401 carries WWW-Authenticate: Bearer realm="ahpd", with error="invalid_token" when a token came that the door does not take.

OAuth is not served yet. A client that asks for it is told to use a bearer token.

What it does not do ​

Nothing is kept between requests. Each request names its caller again, so a token taken away stops the next call. The list a person sees is built for that request, from the grants they hold then.

No stream is opened. A GET answers 405, and a client finds a changed list on its next tools/list. That is enough for a client that re-lists when it needs to, and it is all a door with no state can promise.

A session's own server ​

Each session is offered its own endpoint at /ahp-mcp/<uuid>, with a token only that session holds. It serves the host's tools and the backend's client tools, and it stops answering when the session does. /mcp is for a person, and does not serve client tools. The two share one answer, so a session's endpoint answers exactly as it did before /mcp existed.