Skip to main content

A framework for building Python GraphQL MCP servers.

Project description

graphql-mcp

A library for automatically generating FastMCP tools from a GraphQL schema.

This allows you to expose your GraphQL API as a set of tools that can be used by other systems, such as AI agents or other services that understand the MCP (Multi-Model-Protocol).

Features

  • Automatic Tool Generation: Converts GraphQL queries and mutations into callable Python functions.
  • Type-Safe: Maps GraphQL scalar types, enums, and input objects to corresponding Python types.
  • FastMCP Integration: Seamlessly adds the generated functions as tools to a FastMCP server instance.
  • Modern GraphQL Libraries: Works with modern, code-first GraphQL libraries like strawberry-graphql.
  • Asynchronous Support: While the tool generation is synchronous, the created tools execute GraphQL queries in a way that can be integrated into asynchronous applications.

Installation

You can install graphql-mcp using pip. To follow the usage example, you'll also need strawberry-graphql:

pip install graphql-mcp "strawberry-graphql[cli]"

Usage with Strawberry

Here's a simple example of how to use graphql-mcp to create tools from a strawberry-graphql schema.

# example.py
import asyncio
import strawberry
from fastmcp import FastMCP
from graphql_mcp.server import add_tools_from_schema

# 1. Define your GraphQL schema using Strawberry
@strawberry.type
class Query:
    @strawberry.field
    def hello(self, name: str = "World") -> str:
        """Returns a greeting."""
        return f"Hello, {name}!"

@strawberry.type
class Mutation:
    @strawberry.mutation
    def send_message(self, message: str) -> str:
        """Prints a message and returns a confirmation."""
        print(f"Received message: {message}")
        return f"Message '{message}' sent successfully."

# The strawberry.Schema object is compatible with graphql-core's GraphQLSchema
schema = strawberry.Schema(query=Query, mutation=Mutation)

# 2. Create a FastMCP server instance
server = FastMCP(name="MyGraphQLServer")

# 3. Add tools from the schema
# The `strawberry.Schema` object can be passed directly.
add_tools_from_schema(schema, server)

# 4. Use the generated tools
async def main():
    # You can inspect the tools
    print("Available tools:", server.get_tool_names())
    
    # You can also inspect a specific tool's signature
    print("Tool 'hello' signature:", server.get_tool_signature("hello"))

    # Call a query tool
    result = await server.acall_tool("hello", name="Bob")
    print("Query result:", result)

    # Call a mutation tool
    result = await server.acall_tool("send_message", message="This is a test")
    print("Mutation result:", result)

if __name__ == "__main__":
    asyncio.run(main())

When you run this script, you will see the following output:

Available tools: ['send_message', 'hello']
Tool 'hello' signature: (name: str = 'World') -> str
Query result: Hello, Bob!
Received message: This is a test
Mutation result: Message 'This is a test' sent successfully.

Alternative Usage: GraphQLMCPServer

For convenience, you can also use the GraphQLMCPServer class, which inherits from FastMCP and provides class methods to create a server directly from a schema.

From a GraphQLSchema object

You can use GraphQLMCPServer.from_schema() and pass any graphql-core-compatible GraphQLSchema object. This includes schemas created with strawberry-graphql.

# example_from_schema.py
import asyncio
import strawberry
from graphql_mcp.server import GraphQLMCPServer

# 1. Define your schema (e.g., with Strawberry)
@strawberry.type
class Query:
    @strawberry.field
    def hello(self, name: str = "World") -> str:
        return f"Hello, {name}!"

schema = strawberry.Schema(query=Query)

# 2. Create the server from the schema
server = GraphQLMCPServer.from_schema(schema, name="MyGraphQLServer")

# 3. Use the server
async def main():
    print("Available tools:", server.get_tool_names())
    result = await server.acall_tool("hello", name="From Schema")
    print("Query result:", result)

if __name__ == "__main__":
    asyncio.run(main())

From a graphql-api object

If you are using the graphql-api library, you can use the GraphQLMCPServer.from_api() method.

# example_from_api.py
import asyncio
from graphql_api import GraphQLAPI, field
from graphql_mcp.server import GraphQLMCPServer, HAS_GRAPHQL_API

# The .from_graphql_api() method is only available if `graphql-api` is installed.
if HAS_GRAPHQL_API:
    # 1. Define your API using `graphql-api`
    class MyAPI:
        @field
        def hello(self, name: str = "World") -> str:
            return f"Hello, {name}!"

    api = GraphQLAPI(roottype=MyAPI)

    # 2. Create the server from the API object
    server = GraphQLMCPServer.from_graphql_api(api)

    # 3. Use the server
    async def main():
        print("Available tools:", server.get_tool_names())
        result = await server.acall_tool("hello", name="From API")
        print("Query result:", result)

    if __name__ == "__main__":
        asyncio.run(main())

How It Works

graphql-mcp introspects your GraphQL schema's queries and mutations. For each field, it does the following:

  1. Creates a Python Function: A wrapper function is generated that has a signature matching the GraphQL field's arguments.
  2. Handles Type Conversion: It maps GraphQL types like String, Int, ID, and custom Enum types to their Python equivalents. Input objects are treated as dictionaries.
  3. Constructs a GraphQL Query: When the generated function is called, it dynamically constructs the appropriate GraphQL query or mutation string.
  4. Executes the Query: It uses graphql-sync to execute the query against the schema, passing in the provided arguments as variables.
  5. Returns the Result: The data from the GraphQL response is returned.

The tool names are converted from camelCase (GraphQL convention) to snake_case (Python convention). For example, a mutation sendMessage becomes a tool named send_message.

License

This project is licensed under the MIT License. See the 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-1.0.5.tar.gz (15.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-1.0.5-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: graphql_mcp-1.0.5.tar.gz
  • Upload date:
  • Size: 15.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for graphql_mcp-1.0.5.tar.gz
Algorithm Hash digest
SHA256 24badd64c80e28b021785c1534972a4ddbcc6e098cfe423e6107bef70cda3f54
MD5 edf7085fada775b3784a1ec1b053f2b5
BLAKE2b-256 49d59759c0f3491b348700102ef02d43df9c775eb21a4061c9201043daca7e7d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: graphql_mcp-1.0.5-py3-none-any.whl
  • Upload date:
  • Size: 13.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for graphql_mcp-1.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 694c79d7a0bef7a7f2d30ff71c6f57761534ff8040990929ac72e9473b38e8d2
MD5 2e97ab1f238e8c4bf91fac78c0e18d78
BLAKE2b-256 d4864b72f0417fb8ec72581b0b3f30495b0b627f9843994f0221663cdd259c38

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