MCP server

Fitaio runs a remote Model Context Protocol server at https://fitaio.app/mcp. Point an MCP client at it with your API key and the assistant can read your workouts, body metrics, nutrition, plans and stats, and log new entries when the key has write scope.

The server is stateless Streamable HTTP. Every request carries your key; there are no sessions to keep alive and no server-initiated streams.

The endpoint

URL https://fitaio.app/mcp
Transport Streamable HTTP, POST only
Protocol versions 2025-11-25, 2025-06-18, 2025-03-26
Auth Authorization: Bearer fitaio_... header, or the key in the URL (below)
Limits Same as the REST API: 120 requests a minute per key, 300 per IP

Clients that send headers

Claude Code, Cursor and VS Code let you attach headers. Use the plain endpoint with a bearer token:

{
  "url": "https://fitaio.app/mcp",
  "headers": { "Authorization": "Bearer fitaio_YOUR_KEY" }
}

Clients that cannot send headers

Claude Desktop connectors and ChatGPT connectors take a URL only. Put the key in the path:

https://fitaio.app/mcp/k/fitaio_YOUR_KEY

Treat that URL like a password. Anyone who has it can use the key until you revoke it on the Developer screen in the app.

Set up your client

Tools

The server exposes 22 tools: 14 that read and 8 that write. Read tools work with any key; write tools need a key created with read and write scope. The tool reference lists every argument with an example call and result.

Good prompts

  • "What did I train this week, and which lifts moved up?"
  • "Log today's push workout: bench 4 sets of 8 at 82.5 kg, overhead press 3 sets of 8 at 50 kg."
  • "Compare my volume per muscle group over the last 30 days with the 30 before."
  • "Set a goal of 78 kg by 19 December and log 82.4 kg for this morning."
  • "Build me a four-day plan for a cut and make it active."

Protocol notes

  • initialize returns the server's protocol version and the tools capability. tools/list returns every tool with a JSON Schema for its arguments and annotations (readOnlyHint, destructiveHint, idempotentHint).
  • tools/call results carry the JSON in structuredContent and a one-line summary in content[0].text.
  • Errors from calling a tool (validation, not found, insufficient scope) come back as a tool result with isError: true and a plain-text explanation in content[0].text, not the REST API's structured error object; a failed tool call has no structuredContent. Errors in the request itself, such as an invalid or missing key, are HTTP-level responses that use the same { error: { code, message } } envelope as the REST API.
  • GET /mcp answers 405: there is no SSE stream to open.

Troubleshooting

Symptom Cause Fix
HTTP 401 with invalid_key The key is wrong, revoked, or the client did not send the header Check the Developer screen; for URL-only clients use the /mcp/k/ form
Tool call returns isError: true with a scope message A write tool was called with a read-only key Create a key with read and write scope
HTTP 429 rate_limited More than 120 calls in a minute Wait a minute; ask the assistant to batch reads
Tools list is empty in the client The client cached an old connection Remove and re-add the server