Skip to content

Releases: apollographql/apollo-mcp-server

1.13.0 (2026-04-22)

23 Apr 14:39

Choose a tag to compare

Features

Add MCP prompts support via Markdown files - @DaleSeo #715

Apollo MCP Server now supports MCP prompts. Prompts are reusable templates that guide AI models through multi-step workflows using your GraphQL tools.

Each prompt is a Markdown file in a prompts/ directory with YAML frontmatter for metadata (name, description, arguments) and a template body with {{argument}} placeholders. The server loads prompts at startup and serves them via the prompts/list and prompts/get MCP methods. No configuration changes are needed — the server automatically detects the prompts/ directory.

Add optional instructions for MCP initialize - @DaleSeo #722

Operators can set a top-level instructions value in the server configuration, or supply it through APOLLO_MCP_INSTRUCTIONS, to describe how models should use this server's tools and resources. The server returns that string in the MCP initialize response so clients can surface it to the model, consistent with the protocol's optional instructions field.

Add per-operation MCP tool annotation overrides - @DaleSeo #726

Users can now configure MCP tool annotations per operation via overrides.annotations in the config file. Each entry maps an operation name to annotation hints (title, read_only_hint, destructive_hint, idempotent_hint, open_world_hint) that are merged with auto-detected defaults. Additionally, idempotent_hint is now auto-set to true for queries and open_world_hint is auto-set to true for all operations.

Add trace_id to log output for distributed trace correlation - @DaleSeo #728

Log lines emitted within an OpenTelemetry-traced span now include a trace_id=<hex> prefix, allowing operators to correlate logs with distributed traces in observability tools such as Jaeger and Grafana. Startup messages and other events outside a span are unaffected.

Fixes

Fix aarch64 musl installer fallback - @DaleSeo #698

The install script previously blocked installation on aarch64 Linux systems with older glibc versions, even though a musl binary is now available for that target. This change removes the block, allowing ARM64 musl systems to fall back to the musl binary just like x86_64 systems.

The installer script is now testable via source without side effects, and a new test-install.sh validates architecture detection and download URL logic across OS, CPU, and libc combinations.

Fix config hot reload crashing server on invalid config - @DaleSeo #718

The config hot-reload feature was supposed to keep the server running when an invalid config file was saved, but instead the server would crash because it cancelled the running instance before validating the new config. The new config is now validated before the server is stopped, and if validation fails, the error is logged and the server continues running with the previous configuration.

Fix misleading error when APOLLO_KEY is missing - @DaleSeo #723

When APOLLO_KEY was not set, the server incorrectly reported "Missing environment variable: APOLLO_GRAPH_REF" instead of APOLLO_KEY. This was a copy-paste bug in GraphOSConfig::key() that referenced the wrong constant in its error path.

Accept the scp JWT claim for OAuth scope validation - @DaleSeo #729

Previously, the MCP server only read the RFC 9068 scope claim when validating OAuth tokens. Okta emits scopes as the non-standard scp claim, which caused otherwise-valid tokens from those providers to be rejected as having insufficient scopes. The server now falls back to scp when scope is absent.

1.12.0 (2026-04-01)

02 Apr 17:34
3ff9542

Choose a tag to compare

Features

Add config file hot reloading - @DaleSeo #709

The MCP server now automatically detects changes to its YAML configuration file and reloads without requiring a restart. When a configuration change is detected, the server re-reads the file, applies the updated settings, and continues serving with the new configuration.

Fixes

Fix server becoming unresponsive due to zombie peer lock starvation - @DaleSeo #712

The MCP server could become completely unresponsive to POST /mcp requests after hours of uptime while /health remained responsive. This occurred when a peer's transport entered a half-closed state (e.g., from an HTTP/2 RST_STREAM) and a subsequent schema or operations update tried to notify the zombie peer while holding the operations write lock — blocking all tool listing, tool calling, and session initialization indefinitely.

The operations write lock is now released before notifying peers, and each peer notification has a 5-second timeout. Unresponsive peers are dropped instead of blocking the server.

Fix unused import warning on Windows targets - @DaleSeo #719

The tracing::error macro was imported at the top level but only used inside a #[cfg(unix)] block, causing a build failure on Windows targets with --deny warnings.

1.11.0 (2026-03-23)

23 Mar 21:36
d9bc568

Choose a tag to compare

Features

Add hot reloading for Rhai scripts - @andrewmcgivery #705

Rhai scripts in the rhai/ directory are now automatically reloaded when changes are detected. You no longer need to restart the server after editing your Rhai hook scripts. Modifications to main.rhai or any file in the rhai/ directory, including subdirectories, are picked up automatically.

If a script fails to compile during a reload, the server logs the error and continues running with the previous version of your scripts.

Add Rhai HTTP module with Http::get and Http::post - @andrewmcgivery #701

You can now make HTTP requests from within your Rhai scripts using Http::get and Http::post. Both methods return a Promise that you can .wait() on to get the response.

Each method accepts an optional options map with support for headers, body, and timeout:

// Simple GET request
let response = Http::get("https://api.example.com/data").wait();
print(response.status);
print(response.text());

// GET with custom headers and a timeout
let response = Http::get("https://api.example.com/data", #{
    headers: #{
        "Authorization": "Bearer my-token"
    },
    timeout: 30
}).wait();

let data = response.json();
// POST with a JSON body
let response = Http::post("https://api.example.com/data", #{
    headers: #{
        "Content-Type": "application/json"
    },
    body: JSON::stringify(#{
        key: "value"
    })
}).wait();

print(response.status);

Expose tool_name in the on_execute_graphql_operation Rhai hook - @andrewmcgivery #704

The on_execute_graphql_operation lifecycle hook now includes a read-only tool_name property on the context object. This lets you customize request behavior based on which MCP tool triggered the GraphQL operation.

fn on_execute_graphql_operation(ctx) {
    if ctx.tool_name == "get_launch" {
        ctx.headers["x-priority"] = "high";
    }
}

Support extraOutputs on tools in manifest file - @andrewmcgivery #693

Tools can now provide an extraOutputs argument. The content of this property is written as-is to the extra property under structuredContent on tool responses.

Support @private in operations to hide parts of a query result from LLMs - @andrewmcgivery #684

In MCP Apps, you may have data that you want made available to your app but hidden from the LLM.

query ProductsQuery {
  topProducts {
    sku
    title
    meta @private {
      createdAt
      barcode
    }
  }
}

This will result in the non-private portions of the result being passed back in structuredContent as usual, and the entire result, including private portions, in _meta.structuredContent.

1.10.0 (2026-03-19)

19 Mar 17:23
babbf01

Choose a tag to compare

Features

Add allow_anonymous_mcp_discovery setting to allow unauthenticated access to MCP discovery methods (e.g. tools/list) when oauth is enabled - @andrewmcgivery #685

Example:

transport:
  auth:
    allow_anonymous_mcp_discovery: true

Add discovery_headers option to auth config - @andrewmcgivery #697

Add discovery_headers option to auth config for attaching custom headers to OIDC discovery and JWKS requests. This is useful when upstream OAuth servers or WAFs require headers like User-Agent.

transport:
  type: streamable_http
  auth:
    servers:
      - https://auth.example.com
    resource: https://mcp.example.com
    scopes:
      - read
    discovery_headers:
      User-Agent: apollo-mcp-server

New Rhai-based extensibility - @andrewmcgivery #681

With this release, we're introducing our first extensibility to the MCP Server. This utilizes Rhai as the script engine and allows you to hook into the MCP Server lifecycle.

For this release, we've introduced a single lifecycle hook:

fn on_execute_graphql_operation(context){

}

From within this hook you can do a number of things including:

  • Logging with print/debug
  • Get/set the graphql endpoint with context.endpoint
  • Get info about the incoming request with context.incoming_request.headers["authorization"]
  • Get environment variables with Env::get("MY_VARIABLE")
  • Sha256 hashes using Sha256::digest("my string")
  • Get/set outgoing headers using context.headers["x-my-header"] = "hello"
  • End requests early like throw ${ code: ErrorCode::INVALID_REQUEST, message: "I ended!" }
  • JSON with JSON::stringify(obj) and JSON::parse(json_string)
  • Regex operations like Regex::is_match("hello world", "hello"); and Regex::replace("foo bar foo", "foo", "baz"); and Regex::matches("abc 123 def 456", "\\d+");

We've got more hooks and functions that we're looking at introducing (E.g. on_startup hook, Http::get() method) but we'd love to hear feedback on what you'd like to see made available!

Implement Step-up Authorization Flow - @DaleSeo #672

Implements the step-up authorization flow from the MCP specification: when a client presents a valid token that lacks the scopes required for a specific operation, the server responds with HTTP 403 and a WWW-Authenticate: Bearer error="insufficient_scope", scope="..." header. The client can use this signal to re-authorize with elevated scopes and retry the request.

Fixes

Fix OTLP HTTP exporter failing to connect to HTTPS endpoints - @ochoav #695

When the workspace upgraded from reqwest 0.12 to 0.13, Cargo feature unification stopped applying the workspace's TLS features to the reqwest 0.12 still used internally by opentelemetry-otlp. This left the OTLP HTTP exporter's reqwest client with no TLS backend, causing "invalid URL, scheme is not http" errors when exporting to any https:// telemetry endpoint (e.g. Langfuse, New Relic). Adding the reqwest-rustls feature to opentelemetry-otlp restores TLS support for the internal reqwest 0.12 client.

1.9.0 (2026-03-10)

10 Mar 22:12
94dab50

Choose a tag to compare

Features

Add camelCase-aware search tokenization to schema index - @DaleSeo #667

Split camelCase and PascalCase identifiers into individual words before indexing and querying, so searching for "post" now matches types like PostAnalytics, CreatePostInput, and createPost. Uses heck::ToSnakeCase to split identifiers at word boundaries, matching Rover's existing behavior.

Fixes

Allow missing aud claim in access tokens for AWS Cognito compatibility - @mayorandrew #669

AWS Cognito access tokens omit the aud claim entirely unless resource binding with managed login is used. Previously, this caused JWT validation to fail with "missing field aud" even when allow_any_audience: true was configured. The aud claim is now optional during deserialization, and tokens without it are accepted when allow_any_audience is enabled. When allow_any_audience is false, tokens missing aud are still explicitly rejected.

Fix unbound variable in install script glibc check - @DaleSeo #687

The has_required_glibc function in the nix install script referenced an undefined _libc_version variable in its error message. Because the script runs with set -u, this caused a crash instead of printing the intended diagnostic on systems with glibc < 2.38 (e.g. Red Hat UBI9). The variable is now correctly referenced as _glibc_version.

Fix isError for partial-success GraphQL responses - @DaleSeo #675

When a GraphQL resolver fails at runtime, servers often return a response where errors is populated alongside a non-null data object (e.g. {"errors": [...], "data": {"createUsers": null}}). The execute tool was incorrectly treating these responses as successes because its isError logic required data to be absent or null. The check now only requires the presence of a non-null errors array, which is the correct signal per the GraphQL spec §7.1.6.

Fix path-aware OAuth protected resource metadata URL per RFC 9728 - @DaleSeo #664

The resource_metadata URL in the WWW-Authenticate header and the .well-known endpoint route were ignoring the path component of the configured resource URL. Per RFC 9728 Section 3, the well-known URI must be formed by inserting /.well-known/oauth-protected-resource between the host and path components. This fixes OAuth metadata discovery for MCP servers deployed behind reverse proxies with path-based routing, where clients like VS Code and Claude could not authenticate.

1.8.2 (2026-03-04)

04 Mar 00:21
e85ba28

Choose a tag to compare

Fixes

App resources will now only be listed when the "app" query param is present - @andrewmcgivery #673

Fixed a scenario where operation tool names could collide with apps tool names - @andrewmcgivery #674

1.8.1 (2026-03-02)

02 Mar 19:38
c113589

Choose a tag to compare

Fixes

Fix panic with multibyte UTF-8 characters in GraphQL schemas - @DaleSeo #666

Update apollo-compiler to 1.31.1, which upgrades the ariadne error reporting library from 0.5.1 to 0.6.0. This fixes a panic when handling GraphQL schemas containing CJK text or emoji in field names or descriptions, where byte-offset span calculations could land inside a multibyte character boundary.

Use openai/widgetPrefersBorder when prefersBorder setting is provided - @jerelmiller #668

Set _meta['openai/widgetPrefersBorder'] for the resource because ChatGPT ignores _meta.ui.prefersBorder at the moment.

1.8.0 (2026-02-26)

26 Feb 02:11
103678c

Choose a tag to compare

Features

Allow server "description" to be configured - @andrewmcgivery #650

Example:

server_info:
  name: "Acme Corp GraphQL Server"
  version: "2.0.0"
  title: "Acme MCP Server"
  website_url: "https://acme.com/mcp-docs"
  description: "MCP server for Acme Corp's GraphQL API"

Support custom tool descriptions for all operation sources - @DaleSeo #658

Users can now provide custom tool descriptions via the overrides.descriptions config, regardless of the operation source (manifest, uplink, collection, local files). This lets AI models better understand when and how to use each tool, without requiring changes to operation files or manifests.

overrides:
  descriptions:
    GetAlerts: "Get active weather alerts for a US state"
    GetForecast: "Get a detailed weather forecast for a coordinate"

Support for MCP Apps and OpenAI AppsSDK - @andrewmcgivery #652

This release includes support for MCP Apps and the OpenAI Apps SDK via our AI Apps Template utilizing the @apollo/client-ai-apps Apollo Client integration library.

This pattern enables serving AI Apps built with Apollo Client to platforms like ChatGPT, Goose, and others via Apollo MCP Server.

Fixes

Fix server crash on collection sync with invalid operations - @DaleSeo #637

A single operation with malformed variables JSON in a collection would crash the entire server. Invalid operations are now skipped with a warning, and the server continues serving with the remaining valid operations.

Fix JSON schema type mapping for GraphQL Int - @mitica #660

Map GraphQL Int to JSON schema { "type": "integer" } instead of { "type": "number" }. This tells MCP clients to send integer values rather than floats (e.g. 1234 instead of 1234.0), fixing input coercion errors on GraphQL servers that strictly validate Int inputs.

Gate outputSchema and structuredContent on negotiated MCP protocol version - @DaleSeo #657

When enable_output_schema is configured, the server now advertises MCP protocol version 2025-06-18 and only includes outputSchema in tools/list and structuredContent in tools/call responses when the client negotiates a protocol version that supports them (>= 2025-06-18). Previously, these fields were sent regardless of the negotiated version, which could cause errors in clients that don't recognize them.

1.8.0-experimental.3 (2026-02-25)

25 Feb 20:14

Choose a tag to compare

Pre-release

Features

Allow server "description" to be configured

Example:

server_info:
  name: "Acme Corp GraphQL Server"
  version: "2.0.0"
  title: "Acme MCP Server"
  website_url: "https://acme.com/mcp-docs"
  description: "MCP server for Acme Corp's GraphQL API"

Support custom tool descriptions for all operation sources

Users can now provide custom tool descriptions via the overrides.descriptions config, regardless of the operation source (manifest, uplink, collection, local files). This lets AI models better understand when and how to use each tool, without requiring changes to operation files or manifests.

overrides:
  descriptions:
    GetAlerts: "Get active weather alerts for a US state"
    GetForecast: "Get a detailed weather forecast for a coordinate"

Fixes

Fix server crash on collection sync with invalid operations

A single operation with malformed variables JSON in a collection would crash the entire server. Invalid operations are now skipped with a warning, and the server continues serving with the remaining valid operations.

Fix JSON schema type mapping for GraphQL Int

Map GraphQL Int to JSON schema { "type": "integer" } instead of { "type": "number" }. This tells MCP clients to send integer values rather than floats (e.g. 1234 instead of 1234.0), fixing input coercion errors on GraphQL servers that strictly validate Int inputs.

Gate outputSchema and structuredContent on negotiated MCP protocol version

When enable_output_schema is configured, the server now advertises MCP protocol version 2025-06-18 and only includes outputSchema in tools/list and structuredContent in tools/call responses when the client negotiates a protocol version that supports them (>= 2025-06-18). Previously, these fields were sent regardless of the negotiated version, which could cause errors in clients that don't recognize them.

1.8.0-experimental.2 (2026-02-23)

23 Feb 21:52

Choose a tag to compare

Pre-release

Features

Allow server "description" to be configured

Example:

server_info:
  name: "Acme Corp GraphQL Server"
  version: "2.0.0"
  title: "Acme MCP Server"
  website_url: "https://acme.com/mcp-docs"
  description: "MCP server for Acme Corp's GraphQL API"

Support custom tool descriptions for manifest operations

Users can now provide custom tool descriptions for operations loaded from persisted query manifests by adding a descriptions map to the operations config. This lets AI models better understand when and how to use each tool, without requiring changes to the standard manifest format.

operations:
  source: manifest
  path: ./manifest.json
  descriptions:
    GetAlerts: "Get active weather alerts for a US state"
    GetForecast: "Get a detailed weather forecast for a coordinate"

Fixes

Fix server crash on collection sync with invalid operations

A single operation with malformed variables JSON in a collection would crash the entire server. Invalid operations are now skipped with a warning, and the server continues serving with the remaining valid operations.