> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fitsociety.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Security & Privacy

> Business-readable security model for FITsociety MCP.

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](/mcp/tools) 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.

## Health data consent

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`

## Private communication consent

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.
