MCP server reference
Overview
Primer exposes a curated subset of its built-in tools to external MCP
clients at /v1/mcp. The endpoint speaks the MCP StreamableHTTP
transport. Operators control which tools are reachable via the
allowlist at PUT /v1/mcp_exposure.
Transport
| Property | Value |
|---|---|
| Path | /v1/mcp |
| Protocol | MCP StreamableHTTP (stateful sessions, SSE-based) |
| Auth | Bearer token (see Auth section below) |
The endpoint does not speak stdio. External clients must connect over
HTTP to the running primer api process.
Auth
Every request to /v1/mcp must carry a valid bearer token in the
Authorization header:
Authorization: Bearer <token>Anonymous requests receive 401 with WWW-Authenticate: Bearer realm="primer". Bearer tokens that lack the mcp scope receive
403 with {"code": "scope_required", "scope": "mcp"}.
Cookie sessions (operator console) pass the scope check without
restriction. Mint MCP-specific tokens from the console with the mcp
scope; grant only the scopes the remote agent actually needs.
Enabling exposure
Before any tools appear on tools/list, the operator must enable the
allowlist:
curl -X PUT http://localhost:8000/v1/mcp_exposure \
-H "Cookie: <session>" \
-H "Content-Type: application/json" \
-d '{"enabled": true, "allowed_tools": ["system__call_tool", "misc__uuid_v4"]}'PUT /v1/mcp_exposure is cookie-session-only; bearer tokens cannot
mutate the allowlist even with the mcp scope.
Tool naming
Tools are identified by their scoped id: <toolset_id>__<tool_id>
(double underscore separator). Examples: system__call_tool,
misc__uuid_v4, web__web_search.
Only tools from the reserved built-in toolsets can be exposed. Tools
from user-defined toolset rows are always denied with reason
not_system_toolset. Built-in toolset ids are: system, workspaces,
misc, web, harness, trigger, search, and workspace_ext
(though every workspace_ext tool is also caught by the yielding or
session floor below, so none are reachable in practice).
Additional constraints applied before a tool can be allowlisted:
- Yielding tools are denied (
yielding_unsupported). MCP v1 has no park/resume primitive. - Workspace tools that require an active agent session are denied
(
needs_session).
A tool whose effective approval policy is required can be
allowlisted, but it is refused at tools/call (MCP has no surface
to collect an approval), so calls against it fail as not exposed. To
make it callable over MCP, disable or delete the approval policy
first.
Listing tools
Connect an MCP client to /v1/mcp and issue tools/list:
# Using the MCP Inspector (example):
npx @modelcontextprotocol/inspector \
--url http://localhost:8000/v1/mcp \
--header "Authorization: Bearer <token>"The response lists only the tools present in the active allowlist and
not blocked by the safety floor. If exposure is disabled (enabled: false), the list is empty.
Calling a tool
Issue a tools/call request with the scoped tool id:
{
"method": "tools/call",
"params": {
"name": "misc__uuid_v4",
"arguments": {}
}
}Result envelope
Every tool result has the same shape regardless of success or error:
{
"isError": false,
"content": [
{ "type": "text", "text": "<tool output>" }
]
}When isError is true, content[0].text carries the error message.
A tool that is not in the allowlist returns a JSON-RPC
method-not-found error rather than an isError result.
Managing the allowlist
| Method | Path | Description |
|---|---|---|
GET |
/v1/mcp_exposure |
Read the singleton row (enabled flag + allowlist) |
PUT |
/v1/mcp_exposure |
Update enabled and/or allowed_tools (cookie session only) |
GET |
/v1/mcp_exposure/available |
All catalogue tools with exposability verdict |