Skip to main content
FITsociety MCP is designed so AI clients only receive the data and tool access that the right account explicitly approved. There are two access surfaces:
  • Company/coach grants are approved by a Manager or Admin coach.
  • Client AI grants are approved by the authenticated client and are bound to that one client. They require the client to be connected to the company and to have client AI access enabled for that relationship, with the company MCP integration feature enabled.

Company scoping

Every MCP credential maps to one CompanyMcpGrant. Tool execution is resolved from that grant’s company context, so the AI client cannot switch to another company by passing a different company ID. Client AI grants also store a client subject. The runtime passes subjectType: "client" and subjectClientId into the tool context, and client AI tools enforce that all reads and writes stay on that client.

Feature gates

All grants require the company MCP integration feature. Client AI grants additionally require client AI access for the client-company relationship and the company client MCP policy. If any of these gates is disabled later, the grant can still exist for audit and revocation, but tools/list and tools/call are blocked.

Grant owner checks

Each company/coach grant is owned by the coach who created the API key or approved the OAuth connection. At runtime, the backend verifies that the owner still has active company access and still holds a Manager or Admin role. If the owner is removed, deactivated, or demoted, the grant stops working. Client AI grants are not coach-owned; they are revoked by the client and are runtime-bound to the approved client subject.

Read-only default

MCP grants are read-only by default. Read-only grants can list, search, inspect, and summarize allowed data, but cannot create or update records.

Explicit write tools

Write access requires two separate choices:
  1. The grant must not be read-only.
  2. The specific write tool must be listed in allowedWriteTools.
Every approved write call must also include a unique params._meta.idempotencyKey. The runtime durably stores the completed result before responding, so an exact retry replays the stored result without applying the mutation twice. If the mutation succeeds but replay-result persistence fails, the call returns an error and the claimed key remains in processing state. It is not converted to a replayable failure, because doing so could hide a completed mutation and encourage a duplicate write. The current write-tool registry is documented on the Tools & Modules Registry page. It includes company/coach write tools such as:
  • create_client
  • create_booking
  • update_attendance
  • nutrition-plan and nutrition-log editing tools
  • recipe create/update/archive tools
  • Workout V2 assignment, session, performance, preset, and equipment tools
  • WOD create, update, publish, archive, and settings tools
It also includes client AI write tools such as client_ai_log_my_food, client_ai_log_my_measurement, client_ai_book_my_event, and client_ai_send_message_to_my_coach when the client approved those tools. Modules marked with health sensitivity require explicit health data consent. Without that consent, those modules are omitted from tools/list and cannot be called. Health-sensitive modules include:
  • company/coach modules: measurements, intake, checkups, habits, goals, documents, nutrition_logs, workout_v2, and wod
  • client AI modules: client_ai_nutrition, client_ai_measurements, client_ai_habits, client_ai_goals, client_ai_checkups, client_ai_workout_v2, and client_ai_wod
Modules marked with private_communication sensitivity require explicit private communication consent. Private communication modules include:
  • chats
  • client_notes
  • client_ai_documents
  • client_ai_messages

Audit logging

Every authenticated runtime request is logged for review. The audit record must be durably persisted before the runtime response is sent. If that persistence fails, the request fails closed instead of returning an unaudited result. The audit log stores generic execution metadata such as:
  • grant
  • tool name
  • status
  • error code
  • duration
  • request IP
  • user agent
  • argument key names
  • changed entity identifiers and linked domain-audit identifiers where available
Argument values, prompts, and tool result payloads are not stored in the MCP audit log. Request and result summaries are generated from fixed metadata such as method, tool name, read/write type, and success state; caller-provided text is not copied into those summaries. General HTTP error telemetry applies the same boundary: MCP and Public API request bodies and query values are omitted from 4xx/5xx logs and Sentry context. Only the HTTP method and query-free route path remain available for diagnostics.

Transport and operational controls

The official @modelcontextprotocol/server v2 handler validates the request Host and, when present, Origin against allowlists. Runtime bearer credentials are accepted in the Authorization header only. Persistent fixed-window limits protect request IPs and bearer-key identifiers. Tool execution also uses a persistent per-grant query budget and persistent per-company/tool circuit state, so protections remain effective across multiple application instances. Required protection failures return an error rather than bypassing the control. Client IP resolution uses Express with a bounded, deployment-configured proxy hop count. Raw forwarded headers do not override the resolved Express IP.

Token expiration and revocation

Company MCP API keys expire according to their configured lifetime. OAuth grants act as the revocation anchor for issued OAuth tokens. OAuth access tokens expire after 1 hour. OAuth refresh tokens expire after 90 days and rotate when used. Reuse of an already rotated refresh token revokes every still-active token in that grant/client family. The OAuth approval grant expires after 365 days unless revoked sooner. When a grant is revoked, its static API key stops working and all active OAuth tokens for that grant are revoked.