Skip to content

Examples

Runnable examples ship in the examples/ directory, each also deployed live at examples.graphql-mcp.com. The first four cover common use cases; a further five — under GraphQL Library Examples — demonstrate the same API across each popular GraphQL library.

Hello World

Minimal MCP server with a single query — the simplest possible starting point.

Source · Live demo

python
from graphql_api import GraphQLAPI, field
from graphql_mcp.server import GraphQLMCP


class HelloWorldAPI:

    @field
    def hello(self, name: str = "World") -> str:
        """Say hello to someone."""
        return f"Hello, {name}!"


api = GraphQLAPI(root_type=HelloWorldAPI)
server = GraphQLMCP.from_api(api)
app = server.http_app(transport="streamable-http", stateless_http=True)

Task Manager

Full CRUD with enums, mutations, UUID/datetime scalars, and in-memory state.

Source · Live demo

Demonstrates:

  • Dataclass types as GraphQL object types
  • Enums (Priority, Status)
  • Queries with optional filters
  • Mutations via @field(mutable=True)
  • UUID and datetime scalars
python
class TaskManagerAPI:

    @field
    def tasks(
        self,
        status: Optional[Status] = None,
        priority: Optional[Priority] = None,
    ) -> list[Task]:
        """List all tasks, optionally filtered by status or priority."""
        result = list(_tasks.values())
        if status is not None:
            result = [t for t in result if t.status == status]
        if priority is not None:
            result = [t for t in result if t.priority == priority]
        return result

    @field(mutable=True)
    def create_task(
        self,
        title: str,
        description: str = "",
        priority: Priority = Priority.MEDIUM,
        tags: Optional[list[str]] = None,
    ) -> Task:
        """Create a new task."""
        ...

    @field(mutable=True)
    def update_status(self, id: UUID, status: Status) -> Task:
        """Update a task's status. Automatically sets completed_at when done."""
        ...

    @field(mutable=True)
    def delete_task(self, id: UUID) -> bool:
        """Delete a task by ID. Returns true if the task existed."""
        ...

Nested API

Nested tools, @mcp directive, Pydantic models, and async resolvers.

Source · Live demo

Demonstrates:

  • Nested query paths that auto-generate MCP tools (categorycategory_articles)
  • @mcp(hidden=True) to hide arguments from MCP tools
  • Pydantic BaseModel types as GraphQL object types
  • Async resolvers
  • Separate query_type / mutation_type pattern
python
class Category:
    """A category containing articles."""

    @field
    async def articles(
        self,
        tag: Optional[str] = None,
        internal_score: Annotated[Optional[int], mcp(hidden=True)] = None,
    ) -> list[Article]:
        """List articles in this category, optionally filtered by tag.

        The internal_score argument is hidden from MCP tools via
        @mcp(hidden: true) but remains accessible through the GraphQL
        API directly.
        """
        ...

The internal_score parameter is visible in GraphiQL but hidden from MCP tools — useful for internal debugging arguments that AI agents shouldn't use.

The Annotated[..., mcp(hidden=True)] syntax shown here is graphql-api-specific. Users of Ariadne or graphql.build_schema apply the same directive inline in their SDL — see Configuration → @mcp directive for the per-library form.

Remote API

Wraps a public GraphQL API (Countries) as MCP tools via from_remote_url(). No Python schema needed.

Source · Live demo

python
from graphql_mcp.server import GraphQLMCP

server = GraphQLMCP.from_remote_url(
    "https://countries.trevorblades.com/graphql",
    allow_mutations=False,
)
app = server.http_app(transport="streamable-http", stateless_http=True)

That's the entire file. from_remote_url() introspects the remote schema and generates read-only MCP tools automatically.

GraphQL Library Examples

The same small "users" API, exposed through each popular GraphQL library — and each one demonstrating the @mcp directive (renaming a tool, renaming and hiding an argument, hiding a field). They're handy as copy-paste starting points for your own library.

Every example exposes the same MCP surface:

  • list_users — a normal tool
  • fetch_usergetUserById renamed via @mcp, with its userId argument exposed as id
  • a hidden internal_metrics field and a hidden debugToken argument
LibrarySourceLive demo
graphql-apisourcedemo
graphql-coresourcedemo
Ariadnesourcedemo
Strawberrysourcedemo
Graphenesourcedemo

Strawberry and Graphene apply @mcp a little differently from the SDL-based libraries — see Strawberry & Graphene if you need the specifics.

Running Locally

bash
cd examples
uv sync
uv run python hello_world.py   # or task_manager.py, nested_api.py, remote_api.py,
                               # or any of the library_*.py examples

Then open http://localhost:8002/graphql (port varies per example) to see GraphiQL and the MCP Inspector.