---
title: 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.

## Define GraphQL operations for tools

### From operation files

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

<CodeColumns cols={2}>

```graphql title="Example operation GetForecast"
query GetForecast($coordinate: InputCoordinate!) {
  forecast(coordinate: $coordinate) {
    detailed
  }
}
```

```graphql title="Example operation GetWeatherData"
query GetAllWeatherData($coordinate: InputCoordinate!, $state: String!) {
  forecast(coordinate: $coordinate) {
    detailed
  }
  alerts(state: $state) {
    severity
    description
    instruction
  }
}
```

</CodeColumns>

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](/graphos/platform/explorer/operation-collections).

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 title="Example config file for using a GraphOS operation collection"
operations:
  source: collection
  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.

#### 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
query GetProduct($productId: ID!) {
  product(id: $productId) {
    id
    description
  }
}
```

And the Variables panel has `productId` set to `1234`:

```json
{
  "productId": "1234"
}
```

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](/graphos/platform/security/persisted-queries#manifest-format) 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](https://github.com/apollographql/apollo-mcp-server/tree/main/graphql/weather/persisted_queries).

```yaml title="Example config for using persisted query manifest"
operations:
  source: manifest
  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](/graphos/platform/schema-management/delivery/contracts/overview) with a persisted query list associated with that variant, so you can control what AI can consume from your graph. [Learn more](/apollo-mcp-server/best-practices#use-contract-variants-to-control-ai-access-to-graphs).

</Tip>

```yaml title="Example config using GraphOS-managed persisted queries"
operations:
  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 title="Example config using GraphOS-managed persisted queries" {1-2}
headers:
  "apollographql-client-name": "my-web-app"
operations:
  source: uplink
```

## 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 title="operations/GetAlerts.graphql" {1}
# Get active weather alerts for a US state
query GetAlerts($state: String!) {
  alerts(state: $state) {
    severity
    description
    instruction
  }
}
```
**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 title="persisted-queries-manifest.json" {7}
{
  "format": "apollo-persisted-query-manifest",
  "version": 1,
  "operations": [
    {
      "id": "f4d7c9e3...",
      "body": "# Get active weather alerts for a US state\nquery GetAlerts($state: String!) { alerts(state: $state) { severity description instruction } }"
    }
  ]
}
```

### 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 title="Config with tool descriptions" {4-6}
operations:
  source: local
  paths: [./operations]
overrides:
  descriptions:
    GetAlerts: "Get active weather alerts for a US state by its two-letter abbreviation"
    GetForecast: "Get a detailed weather forecast for a geographic coordinate"
```

Config-level descriptions take priority over comment-based descriptions when both are present for the same operation.

### 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](/apollo-mcp-server/auth#per-operation-scope-requirements) for details.

```yaml title="Config with per-operation scope requirements" {4-9}
operations:
  source: local
  paths: [./operations]
overrides:
  required_scopes:
    GetAlerts: []         # No extra scopes needed
    CreateAlert:
      - alerts:write
    DeleteAlert:
      - alerts:write
      - admin
```

### 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 title="Config with tool annotations" {4-10}
operations:
  source: local
  paths: [./operations]
overrides:
  annotations:
    GetAlerts:
      open_world_hint: false
    CreateUser:
      destructive_hint: false
      idempotent_hint: true
      title: "Create a new user account"
```

| Field              | Type     | Description                                                        |
| :----------------- | :------- | :----------------------------------------------------------------- |
| `title`            | `String` | A human-readable title for the tool                                  |
| `read_only_hint`   | `bool`   | If `true`, the tool does not modify its environment                  |
| `destructive_hint` | `bool`   | If `true`, the tool performs destructive updates                     |
| `idempotent_hint`  | `bool`   | If `true`, calling the tool repeatedly has no additional effect      |
| `open_world_hint`  | `bool`   | If `true`, the tool interacts with systems outside its own domain    |

For more details on MCP tool annotations, see the [MCP specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools).

## 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 schema without executing it. This allows AI models to verify that their operations are syntactically correct and conform to the schema before execution, preventing unintended side effects. Operations should be validated prior to calling the `execute` tool.
- `execute`: executes an operation on 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.

### 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
type User {
  id: ID!
  name: String
  email: String!
  posts: [Post]
}
```

**Minified output:**

```
T:User:id:d!,name:s,email:s!,posts:[Post]
```

<Tip>

Use a [contract variant](/graphos/platform/schema-management/delivery/contracts/overview) so you can control the parts of your graph that AI can introspect. [Learn more](/apollo-mcp-server/best-practices#use-contract-variants-to-control-ai-access-to-graphs)

</Tip>

```yaml title="Example config using introspection"
introspection:
  execute:
    enabled: true
  introspect:
    enabled: true
    minify: true
  search:
    enabled: true
    minify: true
    index_memory_bytes: 50000000
    leaf_depth: 1
  validate:
    enabled: true
```