Define MCP Tools


You can manually define the GraphQL operations that are exposed by Apollo MCP Server as MCP tools. You can define these operations using:

  • Local operation files

  • Operation collections

  • Persisted query manifests

  • GraphOS-managed persisted queries

Alternatively, you can let an AI model read your graph schema via GraphQL introspection and have it determine the available operations.

caution
Apollo MCP Server loads local .graphql operation files and persisted query manifest bodies verbatim. Environment variable expansion using ${env.VAR} applies only to the YAML configuration file. Always store credentials in environment variables rather than embedding them in operation content.

Understand execution and validation boundaries

For each predefined operation tool, Apollo MCP Server parses a single named GraphQL operation and stores its document separately from the model-facing tool metadata. A predefined call must match an operation in the server's current catalog by name; the server rejects unknown tool names. For a match, the server sends the stored document to the upstream GraphQL endpoint. Changing only the tool description or generated input schema doesn't change the stored document.

Apollo MCP Server derives the tool's JSON inputSchema from the operation variables and configured GraphQL schema. This schema guides MCP clients and AI models, but the server doesn't independently enforce it for predefined operation calls. The server also doesn't validate a predefined operation against the configured GraphQL schema before exposing the operation as a tool. The upstream GraphQL endpoint performs GraphQL document and variable validation during execution, so test and review your predefined operations before deploying them.

The optional validate tool validates an agent-supplied operation against the current schema; it isn't an automatic prerequisite for execute and doesn't prevalidate predefined operation tools.

Define GraphQL operations for tools

From operation files

An operation file is a .graphql file containing a single GraphQL operation.

GraphQL
Example operation GetForecast
1query GetForecast($coordinate: InputCoordinate!) {
2  forecast(coordinate: $coordinate) {
3    detailed
4  }
5}
GraphQL
Example operation GetWeatherData
1query GetAllWeatherData($coordinate: InputCoordinate!, $state: String!) {
2  forecast(coordinate: $coordinate) {
3    detailed
4  }
5  alerts(state: $state) {
6    severity
7    description
8    instruction
9  }
10}

Use the operations option to provide the MCP Server with a list of operation files. For each operation file you provide, the MCP Server creates an MCP tool that calls the corresponding GraphQL operation.

You can also use the operations option to specify a directory. The server then loads all files with a .graphql extension in that directory as operations.

Files and directories specified with operations are hot reloaded. When you specify a file, the MCP tool is updated when the file contents are modified. When you specify a directory, operations exposed as MCP tools are updated when files are added, modified, or removed from the directory.

From operation collections

For graphs managed by GraphOS, Apollo MCP Server can retrieve operations from an operation collection.

Use GraphOS Studio Explorer to create and manage operation collections.

Configuring the MCP Server to use a GraphOS operation collection

To use a GraphOS operation collection, you must set your graph credentials (APOLLO_GRAPH_REF and APOLLO_KEY) as environment variables.

Each graph variant has its own default MCP Tools Collection, but you can specify any shared collection by using operations.source: collection.

Specify the collection to use with the operations.id option. To view the ID of a collection, click the ••• button next to its entry, select View details, and copy the Collection ID.

Each graph variant has its own default collection called Default MCP Tools. To use this default collection, specify operations.id: default. Apollo MCP Server automatically fetches the default collection if no ID is specified.

YAML
Example config file for using a GraphOS operation collection
1operations:
2  source: collection
3  id: default

MCP Server supports hot reloading of the GraphOS operation collection, so it picks up changes from GraphOS without restarting. MCP Server polls GraphOS for changes periodically, so expect up to 60 seconds before new or modified operations appear as tools.

note
Apollo MCP Server polls operation collections containing up to 100 operations. The server loads a collection with more than 100 operations, but disables subsequent polling. If a later update increases the collection beyond 100 operations, the server applies that update and stops polling.

Setting operation collection variables

When saving operation collections, remove any dynamic variables from the Variables panel of Explorer. This enables the LLM to modify the variables when calling the operation.

Any variables set to any valid value (even null) in the Variables panel of a saved operation are used as a hardcoded override for that operation's variable.

For example, if you create the following operation for an operation collection:

GraphQL
1query GetProduct($productId: ID!) {
2  product(id: $productId) {
3    id
4    description
5  }
6}

And the Variables panel has productId set to 1234:

JSON
1{
2  "productId": "1234"
3}

Then, every time the LLM calls the GetProduct operation, the productId variable is always set to 1234. The same is true if productId is set to null.

If you want to use dynamic variables that the LLM can modify, remove any variables from the Variables panel and save that operation to the collection.

From persisted query manifests

Apollo MCP Server supports reading GraphQL operations from Apollo-formatted persisted query manifest files.

Set the persisted query manifest file for the MCP Server with the operations option. The MCP Server supports hot reloading of persisted query manifests, so changes to manifests are applied without restarting.

An example manifest is available in the GitHub repo.

YAML
Example config for using persisted query manifest
1operations:
2  source: manifest
3  path: <PATH/TO/persisted-queries-manifest.json>

From GraphOS-managed persisted queries

For graphs managed by GraphOS, Apollo MCP Server can get operations by reading persisted queries from GraphOS. The MCP Server uses Apollo Uplink to access the persisted queries.

To use GraphOS persisted queries, you must set your graph credentials APOLLO_GRAPH_REF and APOLLO_KEY as environment variables.

Use the operations.source: uplink option to specify that tools should be loaded from GraphOS-managed persisted queries.

tip
Use a contract variant with a persisted query list associated with that variant, so you can control what AI can consume from your graph. Learn more.
YAML
Example config using GraphOS-managed persisted queries
1operations:
2  source: uplink

The MCP Server supports hot reloading of GraphOS-managed persisted queries, so it can automatically pick up changes from GraphOS without restarting.

If you register a persisted query with a specific client name instead of null, you must configure the MCP Server to send the necessary header indicating the client name to the router.

Use the headers option when running the MCP Server to pass the header to the router. The default name of the 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.

YAML
Example config using GraphOS-managed persisted queries
1headers:
2  "apollographql-client-name": "my-web-app"
3operations:
4  source: uplink
caution
Hot-reloaded operation and schema sources can change tool names, descriptions, inputs, and executable documents without an automatic security diff or approval step. Restrict source write access and review the live tool definitions after changes. For details, go to Protect tool definitions from poisoning.

Tool descriptions

Tool descriptions help AI models understand when and how to use each tool. If no custom description is provided, the MCP Server automatically generates a tool description using the GraphQL schema's field and type descriptions.

GraphQL comments in operation bodies

Embed # comments before the operation definition. MCP Server extracts leading comments and uses them as the tool description.

MCP Server ignores comments placed inside the operation body — for example, above or beside field selections.

In local .graphql files, add comments directly above the operation:

GraphQL
operations/GetAlerts.graphql
1# Get active weather alerts for a US state
2query GetAlerts($state: String!) {
3  alerts(state: $state) {
4    severity
5    description
6    instruction
7  }
8}

In GraphOS operation collections, add comments above the operation in the Explorer editor before saving to the collection.

In persisted query manifests, embed comments in the body field:

JSON
persisted-queries-manifest.json
1{
2  "format": "apollo-persisted-query-manifest",
3  "version": 1,
4  "operations": [
5    {
6      "id": "f4d7c9e3...",
7      "body": "# Get active weather alerts for a US state\nquery GetAlerts($state: String!) { alerts(state: $state) { severity description instruction } }"
8    }
9  ]
10}

GraphQL comments on operation variables

Add # comments before operation variable definitions to override their generated input property descriptions:

GraphQL
operations/GetAlerts.graphql
1query GetAlerts(
2  # Two-letter US state abbreviation
3  $state: String!
4) {
5  alerts(state: $state) {
6    severity
7  }
8}

Variable comments take priority over descriptions derived from GraphQL schema arguments. These input property descriptions remain model-facing text and aren't affected by overrides.descriptions.

Config-level descriptions

If you can't modify the operation source directly, add a descriptions map under the overrides config key to map operation names to tool descriptions. These descriptions override auto-generated descriptions for the matching operations, regardless of the operation source.

YAML
Config with tool descriptions
1operations:
2  source: local
3  paths: [./operations]
4overrides:
5  descriptions:
6    GetAlerts: "Get active weather alerts for a US state by its two-letter abbreviation"
7    GetForecast: "Get a detailed weather forecast for a geographic coordinate"

Config-level descriptions take priority over comment-based and schema-generated tool descriptions when both are present for the same operation. Keys must exactly match operation names. An unmatched or renamed operation uses its source-derived description, and the server doesn't warn about unmatched description keys.

overrides.descriptions controls only the top-level tool description. It doesn't change or pin the operation name, input property names, descriptions, annotations, or executable GraphQL document.

Config-level scope requirements

To restrict which OAuth scopes are required to call a specific tool, add a required_scopes map under the overrides config key. When a token lacks the required scopes, the server returns HTTP 403 and the client can re-authorize with the precise scopes needed. See Per-operation scope requirements for details.

YAML
Config with per-operation scope requirements
1operations:
2  source: local
3  paths: [./operations]
4overrides:
5  required_scopes:
6    GetAlerts: []         # No extra scopes needed
7    CreateAlert:
8      - alerts:write
9    DeleteAlert:
10      - alerts:write
11      - admin

Keys must exactly match the MCP tool name sent in tools/call. Only listed tools receive an additional scope check; an empty list or an absent entry leaves the tool solely governed by the global scope requirement. The server accepts unknown keys without warning, so review your map any time tools are added, removed, or renamed.

Config-level annotations

MCP tool annotations are hints that help AI clients understand tool behavior. Apollo MCP Server auto-detects these defaults:

  • Queries: read_only_hint: true, destructive_hint: false, idempotent_hint: true, and open_world_hint: true

  • Mutations: read_only_hint: false, destructive_hint: true, and open_world_hint: true

To customize those defaults, add an annotations map under the overrides config key. Specify only the fields you want to override.

YAML
Config with tool annotations
1operations:
2  source: local
3  paths: [./operations]
4overrides:
5  annotations:
6    GetAlerts:
7      open_world_hint: false
8    CreateUser:
9      destructive_hint: false
10      idempotent_hint: true
11      title: "Create a new user account"
FieldTypeDescription
titleStringA human-readable title for the tool
read_only_hintboolIf true, the tool does not modify its environment
destructive_hintboolIf true, the tool performs destructive updates
idempotent_hintboolIf true, calling the tool repeatedly has no additional effect
open_world_hintboolIf true, the tool interacts with systems outside its own domain

For more details on MCP tool annotations, see the MCP specification.

Introspection tools

In addition to defining specific tools for pre-defined GraphQL operations, Apollo MCP Server supports introspection tools that enable AI agents to explore the graph schema and execute operations dynamically.

You can enable the following introspection tools:

  • introspect: allows the AI model to introspect the schema of the GraphQL API by providing a specific type name to get information about, and a depth parameter to determine how deep to traverse the subtype hierarchy. The AI model can start the introspection by looking up the top-level Query or Mutation type.

  • search: allows the AI model to search for type information by providing a set of search terms. This can result in fewer tool calls than introspect, especially if the desired type is deep in the type hierarchy of the schema. Search results include all the parent type information needed to construct operations involving the matching type.

  • validate: validates a GraphQL operation against the configured schema without executing it. This checks schema conformance, not whether the operation matches the user's intent or is safe to run. Validate operations prior to calling the execute tool.

  • execute: Parses one ad hoc operation, applies the configured operation-type restrictions, and forwards it to the GraphQL endpoint.

The MCP client can use these tools to provide schema information to the model and its context window, and allow the model to execute GraphQL operations based on that schema.

caution
Unlike predefined operation tools, execute accepts the GraphQL document from each tool call and isn't pinned to a previously reviewed document. execute checks GraphQL syntax, rejects subscriptions, and applies mutation_mode but doesn't automatically validate fields, arguments, or variable types against the configured schema. Adopting validate doesn't force clients to call it before execute; instead, the upstream GraphQL endpoint validates any operation that is forwarded.Limit execute and mutation access to use-cases that need dynamic operations, and use authorization and demand controls at the GraphQL API. For more information, go to Operation validation and execution for the complete boundary.

Minification

Both the introspect and search tools support minification of their results through the minify option. These options help optimize context window usage for AI models.

  • Reduces context window usage: Minified GraphQL SDL takes up significantly less space in the AI model's context window, allowing for more complex schemas or additional context

  • Uses compact notation: Type definitions use prefixed compact syntax and common scalar types are shortened

  • Preserves functionality: All essential type information is retained, just in a more compact format

  • Includes legend in tool descriptions: When minify is enabled, the tool descriptions automatically include a legend explaining the notation

Minification format:

  • Type prefixes: T=type, I=input, E=enum, U=union, F=interface

  • Scalar abbreviations: s=String, i=Int, f=Float, b=Boolean, d=ID

  • Directive abbreviations: @D=deprecated

  • Type modifiers: !=required, []=list, <>=implements

Example comparison:

Regular output:

GraphQL
1type User {
2  id: ID!
3  name: String
4  email: String!
5  posts: [Post]
6}

Minified output:

Text
1T:User:id:d!,name:s,email:s!,posts:[Post]
tip
Use a contract variant so you can control the parts of your graph that AI can introspect. Learn more
YAML
Example config using introspection
1introspection:
2  execute:
3    enabled: true
4  introspect:
5    enabled: true
6    minify: true
7  search:
8    enabled: true
9    minify: true
10    index_memory_bytes: 50000000
11    leaf_depth: 1
12  validate:
13    enabled: true