Connecting over MCP
Connect your AI
Add this address to your AI. It handles the setup and checks with you when it needs to.
https://stationzero.services/mcpRun this once in a terminal:
claude mcp add --transport http station-zero https://stationzero.services/mcpInstall with one click, or paste this into .cursor/mcp.json:
{ "mcpServers": { "station-zero": { "url": "https://stationzero.services/mcp" } } }Install with one click, or paste this into .vscode/mcp.json:
{ "servers": { "station-zero": { "type": "http", "url": "https://stationzero.services/mcp" } } }Paste this into your project's AGENTS.md or CLAUDE.md, or give it to your AI as an instruction:
## AI services at https://stationzero.services
This project's AI services are reached over MCP at https://stationzero.services/mcp.
- Your MCP client connects there. The first time, it asks your human to authorize it: they sign in, or create an account, and approve it in their browser. You then act for their organization. If the server is not in your client's configuration, ask your human to add it.
- Start with `help_explore` and no arguments: it says what the services are, which are on for your account, and lists the help pages. `services_describe` says what a service costs; where it offers a free trial, `services_enable` with `"trial": true` starts one at no cost.
- Anything that costs money is your human's decision: `wallet_top_up` returns a payment link to hand to them.
- The REST API takes an API key, not the MCP token. No key yet? POST https://stationzero.services/api/v1/signup with your human's email address as `operatorEmail` (the Authentication help page explains why): the 201 answer carries `apiKey`, shown once — keep it where you keep secrets and never commit it. Every call creates a new organization of its own, not your human's, and the key is not accepted at https://stationzero.services/mcp.For any client that reads an mcpServers file:
{ "mcpServers": { "station-zero": { "url": "https://stationzero.services/mcp" } } }No MCP client? One POST creates an organization and returns its API key:
curl -X POST https://stationzero.services/api/v1/signup \
-H 'Content-Type: application/json' \
-d '{"operatorEmail":"you@example.com"}'Not sure which to use? Give your AI the address and ask it to connect. It can read the setup instructions itself.
The first time it connects, you sign in (or create an account) and approve it.
How it works underneath
The block above is all most people need: give your AI the address and approve it when it asks. What follows is for anyone building or debugging an MCP client: where the server is, the credential it accepts, how a client finds out where to authorize, and how to test the connection.
The endpoint
The MCP server is at /mcp on the origin you are reading this from. It speaks
Streamable HTTP. POST /mcp carries the JSON-RPC messages; GET and DELETE
are answered with a JSON-RPC "method not allowed" error.
Reach exactly /mcp, with no trailing slash. A token is issued for that exact
resource, and its audience is checked against it.
The credential
/mcp accepts one credential: an OAuth access token issued for it, sent as
Authorization: Bearer <access-token>. An API key is not accepted here; it is
for the API.
A token issued for any other audience is refused, and no
token is passed through to anything else.
Discovery
A request with no token, or a token that is refused, is answered 401 with a
WWW-Authenticate header that points at the protected resource metadata
(RFC 9728):
WWW-Authenticate: Bearer resource_metadata="<origin>/.well-known/oauth-protected-resource/mcp"
A client follows it:
/.well-known/oauth-protected-resource/mcpnames the resource and the authorization server that issues tokens for it./.well-known/oauth-authorization-servernames that server's authorization, token and registration endpoints and its key set (RFC 8414).
Authorization: OAuth 2.1 with PKCE
A client that supports MCP authorization runs this on its own:
- Read the protected resource metadata, then the authorization server's.
- Register: by dynamic client registration, or with a client ID metadata document. Both are in authentication.
- Run the authorization-code flow with PKCE (
S256, required), with theresourceparameter (RFC 8707) set to the MCP endpoint, so the token is bound to it. - A person signs in, or signs up, and approves the client on the consent page.
- Exchange the code for an access token, and call
/mcpwith it. Use the refresh token when the access token expires.
A tool call that needs a scope the token lacks is answered 403 with an
insufficient_scope challenge naming the scopes. Authorize again asking for
them.
Calling the server
With a token, negotiate with initialize, list tools with tools/list and
call one with tools/call.
- Start with
help_exploreand no arguments. It returns the top help page: every service with its status for your account, a quick start for each one you have on, and a table of help pages with their ids. Call it again with{"helpPageId": "<id>"}from that table to read a page. An id you were not shown answers not found. services_listshows every service and whether it is on.services_enablewith"trial": truestarts a free trial.- A service's own tools are reached through toolsets:
toolsets_listshows the toolsets you have on,toolsets_opengives a toolset's tools and their schemas, and the call tool that a tool'scallWithnames calls it:toolsets_calltool_read,toolsets_calltool_writeortoolsets_calltool.
Testing the connection
List the tools with curl. Set ORIGIN to the origin you are reading this
from and TOKEN to an access token issued for /mcp:
curl -X POST "$ORIGIN/mcp" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }'
Without a token, the same call shows the 401 and its WWW-Authenticate
header. The MCP Inspector (npx @modelcontextprotocol/inspector) runs the
whole flow, from discovery to a tool call, against /mcp.