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.

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-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.1.1.tar.gz (517.3 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.1.1-py3-none-any.whl (50.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: graphql_mcp-2.1.1.tar.gz
  • Upload date:
  • Size: 517.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","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.1.1.tar.gz
Algorithm Hash digest
SHA256 4a3463fddaec70736ee0bfb88a5881e9afb93c2735a901885c7c57d59990d906
MD5 43482ca012ad5bebbdd31e19877dde31
BLAKE2b-256 0d9ebf8dc226ab2f7a71e25c88c7639402eaeffcee9d6a01b15fe61f8b18e893

See more details on using hashes here.

File details

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

File metadata

  • Download URL: graphql_mcp-2.1.1-py3-none-any.whl
  • Upload date:
  • Size: 50.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","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.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e006cf8f3eac4f9d32b392b405f3cfdc209cae1b5f2f7e33607e9df12cd8d491
MD5 8c9f807d39147570103967e46705dbc9
BLAKE2b-256 b57698357553b98ed9454a74771c0f45fda8aa31db3bd53a2da51d8657b310fe

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