graphql-mcp


Namegraphql-mcp JSON
Version 1.1.2 PyPI version JSON
download
home_pagehttps://gitlab.com/parob/graphql-mcp
SummaryA framework for building Python GraphQL MCP servers.
upload_time2025-08-06 18:13:25
maintainerNone
docs_urlNone
authorRobert Parker
requires_pythonNone
licenseMIT
keywords graphql graphql-api graphqlapi server mcp multi-model-protocol
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # graphql-mcp

A library for automatically generating [FastMCP](https://pypi.org/project/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`:

```bash
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.

```python
# 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`.

```python
# 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.

```python
# 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](LICENSE) file for details.

            

Raw data

            {
    "_id": null,
    "home_page": "https://gitlab.com/parob/graphql-mcp",
    "name": "graphql-mcp",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "GraphQL, GraphQL-API, GraphQLAPI, Server, MCP, Multi-Model-Protocol",
    "author": "Robert Parker",
    "author_email": "rob@parob.com",
    "download_url": "https://files.pythonhosted.org/packages/20/22/43565479875d2ab6b46a060802e2945073869d15d3df2f0600916acb3e0a/graphql_mcp-1.1.2.tar.gz",
    "platform": null,
    "description": "# graphql-mcp\n\nA library for automatically generating [FastMCP](https://pypi.org/project/fastmcp/) tools from a GraphQL schema.\n\nThis 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).\n\n## Features\n\n- **Automatic Tool Generation**: Converts GraphQL queries and mutations into callable Python functions.\n- **Type-Safe**: Maps GraphQL scalar types, enums, and input objects to corresponding Python types.\n- **`FastMCP` Integration**: Seamlessly adds the generated functions as tools to a `FastMCP` server instance.\n- **Modern GraphQL Libraries**: Works with modern, code-first GraphQL libraries like `strawberry-graphql`.\n- **Asynchronous Support**: While the tool generation is synchronous, the created tools execute GraphQL queries in a way that can be integrated into asynchronous applications.\n\n## Installation\n\nYou can install `graphql-mcp` using pip. To follow the usage example, you'll also need `strawberry-graphql`:\n\n```bash\npip install graphql-mcp \"strawberry-graphql[cli]\"\n```\n\n## Usage with Strawberry\n\nHere's a simple example of how to use `graphql-mcp` to create tools from a `strawberry-graphql` schema.\n\n```python\n# example.py\nimport asyncio\nimport strawberry\nfrom fastmcp import FastMCP\nfrom graphql_mcp.server import add_tools_from_schema\n\n# 1. Define your GraphQL schema using Strawberry\n@strawberry.type\nclass Query:\n    @strawberry.field\n    def hello(self, name: str = \"World\") -> str:\n        \"\"\"Returns a greeting.\"\"\"\n        return f\"Hello, {name}!\"\n\n@strawberry.type\nclass Mutation:\n    @strawberry.mutation\n    def send_message(self, message: str) -> str:\n        \"\"\"Prints a message and returns a confirmation.\"\"\"\n        print(f\"Received message: {message}\")\n        return f\"Message '{message}' sent successfully.\"\n\n# The strawberry.Schema object is compatible with graphql-core's GraphQLSchema\nschema = strawberry.Schema(query=Query, mutation=Mutation)\n\n# 2. Create a FastMCP server instance\nserver = FastMCP(name=\"MyGraphQLServer\")\n\n# 3. Add tools from the schema\n# The `strawberry.Schema` object can be passed directly.\nadd_tools_from_schema(schema, server)\n\n# 4. Use the generated tools\nasync def main():\n    # You can inspect the tools\n    print(\"Available tools:\", server.get_tool_names())\n    \n    # You can also inspect a specific tool's signature\n    print(\"Tool 'hello' signature:\", server.get_tool_signature(\"hello\"))\n\n    # Call a query tool\n    result = await server.acall_tool(\"hello\", name=\"Bob\")\n    print(\"Query result:\", result)\n\n    # Call a mutation tool\n    result = await server.acall_tool(\"send_message\", message=\"This is a test\")\n    print(\"Mutation result:\", result)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\nWhen you run this script, you will see the following output:\n\n```\nAvailable tools: ['send_message', 'hello']\nTool 'hello' signature: (name: str = 'World') -> str\nQuery result: Hello, Bob!\nReceived message: This is a test\nMutation result: Message 'This is a test' sent successfully.\n```\n\n## Alternative Usage: `GraphQLMCPServer`\n\nFor convenience, you can also use the `GraphQLMCPServer` class, which inherits from `FastMCP` and provides class methods to create a server directly from a schema.\n\n### From a `GraphQLSchema` object\n\nYou can use `GraphQLMCPServer.from_schema()` and pass any `graphql-core`-compatible `GraphQLSchema` object. This includes schemas created with `strawberry-graphql`.\n\n```python\n# example_from_schema.py\nimport asyncio\nimport strawberry\nfrom graphql_mcp.server import GraphQLMCPServer\n\n# 1. Define your schema (e.g., with Strawberry)\n@strawberry.type\nclass Query:\n    @strawberry.field\n    def hello(self, name: str = \"World\") -> str:\n        return f\"Hello, {name}!\"\n\nschema = strawberry.Schema(query=Query)\n\n# 2. Create the server from the schema\nserver = GraphQLMCPServer.from_schema(schema, name=\"MyGraphQLServer\")\n\n# 3. Use the server\nasync def main():\n    print(\"Available tools:\", server.get_tool_names())\n    result = await server.acall_tool(\"hello\", name=\"From Schema\")\n    print(\"Query result:\", result)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n### From a `graphql-api` object\n\nIf you are using the `graphql-api` library, you can use the `GraphQLMCPServer.from_api()` method.\n\n```python\n# example_from_api.py\nimport asyncio\nfrom graphql_api import GraphQLAPI, field\nfrom graphql_mcp.server import GraphQLMCPServer, HAS_GRAPHQL_API\n\n# The .from_graphql_api() method is only available if `graphql-api` is installed.\nif HAS_GRAPHQL_API:\n    # 1. Define your API using `graphql-api`\n    class MyAPI:\n        @field\n        def hello(self, name: str = \"World\") -> str:\n            return f\"Hello, {name}!\"\n\n    api = GraphQLAPI(roottype=MyAPI)\n\n    # 2. Create the server from the API object\n    server = GraphQLMCPServer.from_graphql_api(api)\n\n    # 3. Use the server\n    async def main():\n        print(\"Available tools:\", server.get_tool_names())\n        result = await server.acall_tool(\"hello\", name=\"From API\")\n        print(\"Query result:\", result)\n\n    if __name__ == \"__main__\":\n        asyncio.run(main())\n```\n\n## How It Works\n\n`graphql-mcp` introspects your GraphQL schema's queries and mutations. For each field, it does the following:\n\n1.  **Creates a Python Function**: A wrapper function is generated that has a signature matching the GraphQL field's arguments.\n2.  **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.\n3.  **Constructs a GraphQL Query**: When the generated function is called, it dynamically constructs the appropriate GraphQL query or mutation string.\n4.  **Executes the Query**: It uses `graphql-sync` to execute the query against the schema, passing in the provided arguments as variables.\n5.  **Returns the Result**: The data from the GraphQL response is returned.\n\nThe tool names are converted from `camelCase` (GraphQL convention) to `snake_case` (Python convention). For example, a mutation `sendMessage` becomes a tool named `send_message`.\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A framework for building Python GraphQL MCP servers.",
    "version": "1.1.2",
    "project_urls": {
        "Download": "https://gitlab.com/parob/graphql-mcp/-/archive/v1.1.2/graphql_mcp-v1.1.2.tar.gz",
        "Homepage": "https://gitlab.com/parob/graphql-mcp"
    },
    "split_keywords": [
        "graphql",
        " graphql-api",
        " graphqlapi",
        " server",
        " mcp",
        " multi-model-protocol"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "63e41c93c991d44599c4abfe55f2bd956004c145ba7e15a6a561906c56f372e7",
                "md5": "215b875983ec18fe7f2aa8c566f802fd",
                "sha256": "a6529c8be1328fe50155bf2af5f9c0114169261dfb8db9f4e2fc0ae9facb13b1"
            },
            "downloads": -1,
            "filename": "graphql_mcp-1.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "215b875983ec18fe7f2aa8c566f802fd",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 14249,
            "upload_time": "2025-08-06T18:13:24",
            "upload_time_iso_8601": "2025-08-06T18:13:24.411340Z",
            "url": "https://files.pythonhosted.org/packages/63/e4/1c93c991d44599c4abfe55f2bd956004c145ba7e15a6a561906c56f372e7/graphql_mcp-1.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "202243565479875d2ab6b46a060802e2945073869d15d3df2f0600916acb3e0a",
                "md5": "c036b1b12efae9a2867e570dcbc89d58",
                "sha256": "d61b24310fe1a601af3b93dcaebab32dac86f792a3759cc858837303363f6b43"
            },
            "downloads": -1,
            "filename": "graphql_mcp-1.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "c036b1b12efae9a2867e570dcbc89d58",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 16033,
            "upload_time": "2025-08-06T18:13:25",
            "upload_time_iso_8601": "2025-08-06T18:13:25.228723Z",
            "url": "https://files.pythonhosted.org/packages/20/22/43565479875d2ab6b46a060802e2945073869d15d3df2f0600916acb3e0a/graphql_mcp-1.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-06 18:13:25",
    "github": false,
    "gitlab": true,
    "bitbucket": false,
    "codeberg": false,
    "gitlab_user": "parob",
    "gitlab_project": "graphql-mcp",
    "lcname": "graphql-mcp"
}
        
Elapsed time: 0.94121s