Subchapter 6.2
references/best-practices.mdMarkdown8 KBView on GitHub
GraphOS contract variants (opens in a new tab) deliver different subsets of a graph to different consumers. Use them to expose only the types and fields AI agents need.
Contract variants are strongly recommended when using:
operations.source: uplink)introspect, search)graphos:
apollo_key: ${env.APOLLO_KEY}
apollo_graph_ref: my-graph@ai-contract
schema:
source: uplinkKeep mutation_mode at its default (none) unless the use case requires GraphQL mutations.
| Mode | Predefined mutations | Ad hoc mutations (execute) |
|---|---|---|
none | Skipped | Rejected |
explicit | Exposed | Rejected |
all | Exposed | Allowed |
Security: mutation exposure. These modes are configuration gates, not per-invocation approval.
explicitdoes not mean the operation was reviewed or committed to version control. Hot-reloaded source changes can add or change mutations without an approval step.
explicit over all when you need predefined mutations but not ad-hoc onesmutation_mode: all unless execute must accept ad-hoc mutationsOWASP MCP06 (opens in a new tab) describes how instructions from retrieved context can steer an agent away from the user’s goal. Apollo MCP Server limits predefined calls to operations in its tool catalog but does not determine whether a proposed call aligns with the user’s intent.
Treat the exposed tool surface as impact limitation, not intent validation:
execute disabled unless the agent needs ad-hoc queries.MCP clients expose tool names, descriptions, and input property descriptions to AI models. Models use all of this text when selecting tools and arguments. Treat every operation and schema source as security-sensitive. See OWASP MCP03 (opens in a new tab).
Apollo MCP Server does not automatically scan tool metadata for hidden instructions or compare the live tool list with an approved snapshot. Establish these controls:
tools/list response after deployment. Store an approved snapshot using a consistent MCP protocol version and server configuration.overrides.descriptions controls only the top-level description of an exact operation-name match. It does not pin the operation name, input property names or descriptions, or executable document.
Before production deployment:
telemetry:
exporters:
tracing:
omitted_attributes:
- tool_arguments
- tool_result
- graphql_query
- graphql_responsesuccess=false in apollo.mcp.tool.count), unexpected usage patterns, and telemetry ingestion gaps.Metrics do not include per-request trace IDs. Use metrics for aggregate monitoring and traces plus correlated logs for request-level investigation.
Use global OAuth scopes as a server-wide baseline and overrides.required_scopes for tools that need additional permissions. Per-operation keys are matched exactly against MCP tool names.
required_scopes keys with the live tools/list response after deploymentexecute tool in required_scopes if you enable it (otherwise an ad-hoc query can reach data a scoped operation protects)A new or mismatched tool name remains governed only by the global scope requirement. The server does not reject or warn about unknown required_scopes keys.
Apollo MCP Server parses predefined and ad-hoc operation documents but does not automatically validate them against the configured schema before forwarding. The upstream GraphQL endpoint performs validation during execution.
validate tool validates an ad-hoc operation against the schema, but enabling it does not force a client to call it before execute.Security: confused deputy risk. Apollo MCP Server passes validated OAuth tokens to upstream GraphQL APIs by default. This can lead to audience confusion and confused deputy vulnerabilities.
Disable automatic passthrough when your GraphQL API does not require the caller’s token:
transport:
type: streamable_http
auth:
disable_auth_token_passthrough: trueWhen passthrough is disabled, Apollo MCP Server still validates tokens for MCP client authentication but does not forward them downstream.
disable_auth_token_passthrough and forward_headers togetherforward_headers contains authorization, the server still copies the incoming header even when passthrough is disabledauthorization headeraud claim)If you register a persisted query with a specific client name (not null), configure the server to send the client name header to the router:
headers:
"apollographql-client-name": "my-mcp-server"
operations:
source: uplinkThe default header expected by the router is apollographql-client-name. To use a different header name, configure telemetry.apollo.client_name_header in router YAML configuration.
required_scopes keys after any tool changeexecute with mutation_mode: all unless strictly requiredmutation_mode provides per-invocation approvalexecute for predictable behaviorexplicit mutation mode over all in shared environments