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.1.0.tar.gz (509.1 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.0-py3-none-any.whl (49.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: graphql_mcp-2.1.0.tar.gz
  • Upload date:
  • Size: 509.1 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.0.tar.gz
Algorithm Hash digest
SHA256 df9bc92fc2467e68ec25156c845a959c9753401c1f48c201100991331dc06188
MD5 40e96441be96b64eba631bc873865ce4
BLAKE2b-256 d7a8494d0ed460e756a176a54e6cacc05d2018cec0d03d391d4230d5f99b30d3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: graphql_mcp-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 49.0 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d9c0a48197e803aacb635c8debb97ebd86733371392b4fb89cdb9c29b02c3703
MD5 5b93b4b8c8d6e76d1f9fb42b17a7b541
BLAKE2b-256 21c317387e797629067ccd47b3641e5536e9ca09e759ce9f92e2e17f34ac48a7

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