GraphQL-MCP
Documentation | PyPI | GitHub
Instantly expose any GraphQL API as MCP tools for AI agents and LLMs.
GraphQL MCP works with any Python GraphQL library—Strawberry, Ariadne, Graphene, graphql-core, or graphql-api. If you already have a GraphQL API, you can expose it as MCP tools in minutes.
Don't want to run anything? Bridge is a hosted MCP proxy built on graphql-mcp. Paste any public GraphQL URL into your MCP client and every query and mutation shows up as a tool — no code, no deploy.
Features
- Universal Compatibility - Works with any GraphQL library that produces a
graphql-coreschema - Automatic Tool Generation - GraphQL queries and mutations become MCP tools instantly
- Remote GraphQL Support - Connect to any existing GraphQL endpoint
- Type-Safe - Preserves GraphQL types and documentation
- Built-in Inspector - Web interface for testing MCP tools
- Multiple Transports - HTTP, SSE, and streamable-HTTP support
Installation
pip install graphql-mcp
Quick Start
With Strawberry (Popular)
Already using Strawberry? Expose it as MCP tools:
import strawberry
from graphql_mcp.server import GraphQLMCP
import uvicorn
@strawberry.type
class Query:
@strawberry.field
def hello(self, name: str = "World") -> str:
return f"Hello, {name}!"
schema = strawberry.Schema(query=Query)
# Expose as MCP tools
server = GraphQLMCP(schema=schema._schema, name="My API")
app = server.http_app()
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8002)
That's it! Your Strawberry GraphQL API is now available as MCP tools.
With Ariadne
Using Ariadne? Same simple integration:
from ariadne import make_executable_schema, QueryType
from graphql_mcp.server import GraphQLMCP
type_defs = """
type Query {
hello(name: String = "World"): String!
}
"""
query = QueryType()
@query.field("hello")
def resolve_hello(_, info, name="World"):
return f"Hello, {name}!"
schema = make_executable_schema(type_defs, query)
# Expose as MCP tools
server = GraphQLMCP(schema=schema, name="My API")
app = server.http_app()
With Graphene
Graphene user? Works seamlessly:
import graphene
from graphql_mcp.server import GraphQLMCP
class Query(graphene.ObjectType):
hello = graphene.String(name=graphene.String(default_value="World"))
def resolve_hello(self, info, name):
return f"Hello, {name}!"
schema = graphene.Schema(query=Query)
# Expose as MCP tools
server = GraphQLMCP(schema=schema.graphql_schema, name="My API")
app = server.http_app()
With graphql-api (Recommended)
For new projects, we recommend graphql-api for its decorator-based approach:
from graphql_api import GraphQLAPI, field
from graphql_mcp.server import GraphQLMCP
class API:
@field
def hello(self, name: str = "World") -> str:
return f"Hello, {name}!"
api = GraphQLAPI(root_type=API)
server = GraphQLMCP.from_api(api)
app = server.http_app()
Remote GraphQL APIs
Already have a GraphQL API running? Connect to it directly:
from graphql_mcp.server import GraphQLMCP
# Connect to any GraphQL endpoint
server = GraphQLMCP.from_remote_url(
url="https://api.github.com/graphql",
bearer_token="your_token",
name="GitHub API"
)
app = server.http_app()
Works with:
- GitHub GraphQL API
- Shopify GraphQL API
- Hasura
- Any public or private GraphQL endpoint
Examples
The examples/ directory contains four runnable servers:
| Example | What it demonstrates | Live |
|---|---|---|
| Hello World | Minimal MCP server with a single query | Try it |
| Task Manager | CRUD, enums, mutations, UUID/datetime scalars | Try it |
| Nested API | Nested tools, @mcp directive, Pydantic models, async resolvers |
Try it |
| Remote API | Wrap a public GraphQL API via from_remote_url() |
Try it |
See the examples documentation for detailed walkthroughs.
Documentation
Visit the official documentation for comprehensive guides, examples, and API reference.
Key Topics
- Getting Started - Quick introduction and basic usage
- Configuration - Configure your MCP server
- Remote APIs - Connect to existing GraphQL APIs
- Examples - Real-world usage examples
- API Reference - Complete API documentation
How It Works
GraphQL MCP automatically:
- Analyzes your GraphQL schema
- Generates MCP tools from queries and mutations
- Maps GraphQL types to MCP tool schemas: non-null arguments are required,
nullable arguments are optional and accept
null, and an omitted optional argument is left out of the operation so the server default applies - Converts naming to
snake_case(e.g.,addBook→add_book) - Preserves all documentation and type information
- Supports the
@mcpdirective to customize how fields and arguments are exposed to MCP — see below
Customizing MCP Exposure with @mcp
A unified @mcp directive lets schema authors override how each field or
argument surfaces as an MCP tool. It accepts three optional arguments:
| Arg | Type | Effect |
|---|---|---|
name |
String |
Override the MCP tool/argument name (replaces the default snake_case derivation). |
description |
String |
Override the MCP description (replaces the GraphQL field/argument description). |
hidden |
Boolean |
When true, skip the field or argument from MCP registration entirely. |
Valid on FIELD_DEFINITION and ARGUMENT_DEFINITION.
SDL example
directive @mcp(
name: String
description: String
hidden: Boolean
) on FIELD_DEFINITION | ARGUMENT_DEFINITION
type Query {
getUserById(
userId: ID! @mcp(name: "id", description: "User UUID")
debugToken: String @mcp(hidden: true)
): User @mcp(name: "fetch_user", description: "Fetch a user by ID.")
internalMetrics: Metrics @mcp(hidden: true)
}
Python (graphql-api) example
from typing import Annotated
from graphql_api import GraphQLAPI, field
from graphql_mcp import GraphQLMCP, mcp
class API:
@field
@mcp(name="fetch_user", description="Fetch a user by ID.")
def get_user_by_id(
self,
user_id: Annotated[str, mcp(name="id", description="User UUID")],
debug_token: Annotated[str, mcp(hidden=True)] = "",
) -> str:
return f"user:{user_id}"
@field
@mcp(hidden=True)
def internal_metrics(self) -> str:
return "secret"
api = GraphQLAPI(root_type=API, directives=[mcp])
server = GraphQLMCP.from_api(api)
When an argument is renamed, the MCP tool exposes the new name but the
outbound GraphQL query still uses the original argument name — translation
happens automatically. Two fields renamed to the same MCP name will raise a
ValueError at registration time.
Migrating from
@mcpHidden: the previousmcp_hiddendirective has been removed. Replace@mcpHiddenwith@mcp(hidden: true)and themcp_hiddenPython export withmcp(hidden=True).
MCP Inspector
Built-in web interface for testing and debugging MCP tools:
The inspector is enabled by default — visit /graphql in your browser. See the MCP Inspector documentation for details.
Compatibility
GraphQL MCP works with any Python GraphQL library that produces a graphql-core schema:
- Strawberry - Modern, type-hint based GraphQL
- Ariadne - Schema-first GraphQL
- Graphene - Code-first GraphQL
- graphql-api - Decorator-based GraphQL (recommended)
- graphql-core - Reference implementation
- Any GraphQL library using graphql-core schemas
Ecosystem Integration
- graphql-api - Recommended for building new GraphQL APIs
- graphql-db - For database-backed GraphQL APIs
- graphql-http - For HTTP serving alongside MCP
Configuration
# Full configuration example
server = GraphQLMCP(
schema=your_schema,
name="My API",
graphql_http=False, # Disable GraphQL HTTP endpoint (enabled by default)
allow_mutations=True, # Allow mutation tools (default)
)
# Serve with custom configuration
app = server.http_app(
transport="streamable-http", # or "http" (default) or "sse"
stateless_http=True, # Don't maintain client state
)
See the documentation for advanced configuration, authentication, and deployment guides.
License
MIT License - see LICENSE file for details.
Metadata
Release files for graphql-mcp 2.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| graphql_mcp-2.2.0.tar.gz | 544.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| graphql_mcp-2.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 598.9 kB
Release files / graphql_mcp-2.2.0.tar.gz
| Download URL | graphql_mcp-2.2.0.tar.gz |
|---|---|
| Size | 544.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
97d82a1055edcd9c6ab4dbd5c6960a395f628f1c230e22e801703f45b1cb84d8
|
|
BLAKE2b-256 checksum How to use checksums |
f1ee5cde341c345fe051f3380a924f0c9f61cfc9fdb1bed692db46251653bd6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / graphql_mcp-2.2.0-py3-none-any.whl
| Download URL | graphql_mcp-2.2.0-py3-none-any.whl |
|---|---|
| Size | 54.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4ad362524e1f29645de669d3da91e4192657e6ba6eb967ad842ed00f9b4c93c1
|
|
BLAKE2b-256 checksum How to use checksums |
862c05b4b5df56a113603c0473101f282596f4abb021542ef0ad2c242d62fd4d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|