Skip to main content

A framework for building Python GraphQL MCP servers.

Project description

GraphQL-MCP

PyPI version Python versions License: MIT

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.

Features

  • Universal Compatibility - Works with any GraphQL library that produces a graphql-core schema
  • 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

How It Works

GraphQL MCP automatically:

  • Analyzes your GraphQL schema
  • Generates MCP tools from queries and mutations
  • Maps GraphQL types to MCP tool schemas
  • Converts naming to snake_case (e.g., addBookadd_book)
  • Preserves all documentation and type information
  • Supports the @mcp directive 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 previous mcp_hidden directive has been removed. Replace @mcpHidden with @mcp(hidden: true) and the mcp_hidden Python export with mcp(hidden=True).

MCP Inspector

Built-in web interface for testing and debugging MCP tools:

MCP Inspector Interface

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

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graphql_mcp-2.0.0.tar.gz (503.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

graphql_mcp-2.0.0-py3-none-any.whl (47.6 kB view details)

Uploaded Python 3

File details

Details for the file graphql_mcp-2.0.0.tar.gz.

File metadata

  • Download URL: graphql_mcp-2.0.0.tar.gz
  • Upload date:
  • Size: 503.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","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}

File hashes

Hashes for graphql_mcp-2.0.0.tar.gz
Algorithm Hash digest
SHA256 88566eb96c8c71d4d11b8eee4743d6f9ced7da8035d68bcbdcc47f473380ffb7
MD5 344d144a1b16ad72ee1af4e5eb971be1
BLAKE2b-256 f59b199898a456d45107267b85ebc7bd484f036f1a2191a59941f355d8e71f16

See more details on using hashes here.

File details

Details for the file graphql_mcp-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: graphql_mcp-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 47.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","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}

File hashes

Hashes for graphql_mcp-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 491893ac53312c632477ee742c1f4788ac23383ac9f74faab17b9b6d9fa5cd29
MD5 020c546daef7456b056457410ed10ae4
BLAKE2b-256 855443f25ccd4698d9253f187df364ecd433585a1b1f37d56adde1fcc27c2d7b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page