DEV Community

Docat
Docat

Posted on

I Made Claude Talk to Any GraphQL API — Zero Code, One Command

You have a GraphQL API. You want Claude (or any AI) to use it. The usual path: write wrapper functions, map types, handle auth, deal with pagination...

Or: one command.

npx graphql-to-mcp https://countries.trevorblades.com/graphql
Enter fullscreen mode Exit fullscreen mode

That's it. Every query and mutation becomes an MCP tool. Claude can now search countries, filter by continent, look up languages — all from the schema it just introspected.

The Problem

GraphQL is great for developers. Typed schemas, introspection, nested queries — powerful stuff.

But LLMs hate nested input objects. Give Claude a mutation like this:

mutation CreateUser($input: CreateUserInput!) {
  createUser(input: $input) { id name }
}
Enter fullscreen mode Exit fullscreen mode

Where CreateUserInput is:

input CreateUserInput {
  name: String!
  email: String!
  address: AddressInput
}

input AddressInput {
  street: String
  city: String
  country: String
}
Enter fullscreen mode Exit fullscreen mode

The LLM has to construct:

{
  "input": {
    "name": "Alice",
    "email": "alice@example.com",
    "address": {
      "street": "123 Main St",
      "city": "Portland",
      "country": "US"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This fails constantly. LLMs hallucinate extra nesting, miss required fields, or get the structure wrong. Deeply nested JSON is the #1 cause of tool-calling failures.

The Solution: Flat Schemas

graphql-to-mcp flattens every InputObject into simple key-value parameters:

Parameter Type Required
input_name string yes
input_email string yes
input_address_street string no
input_address_city string no
input_address_country string no

The LLM fills flat fields. The tool reconstructs the nested GraphQL variables automatically.

Result: near-perfect accuracy, even with complex mutations.

Setup in 30 Seconds

Claude Desktop / Cursor

Add to your MCP config:

{
  "mcpServers": {
    "my-api": {
      "command": "npx",
      "args": ["-y", "graphql-to-mcp", "https://your-api.com/graphql"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

With Auth

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": [
        "-y", "graphql-to-mcp",
        "https://api.github.com/graphql",
        "--bearer", "ghp_your_token",
        "--prefix", "github"
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Filter Operations

Only expose what you need:

{
  "args": [
    "-y", "graphql-to-mcp",
    "https://api.example.com/graphql",
    "--include", "get*",
    "--exclude", "internal*"
  ]
}
Enter fullscreen mode Exit fullscreen mode

What Happens Under the Hood

  1. Introspect — Fetches the full GraphQL schema via introspection query
  2. Flatten — Every InputObject type gets flattened into simple parameters
  3. Generate — Each query/mutation becomes an MCP tool with a JSON Schema
  4. Execute — When the LLM calls a tool, flat args → nested GraphQL variables → POST to your endpoint
  5. Truncate — Large responses get smart-truncated (arrays sliced to 20, depth pruned to 5 levels)

Smart Truncation

GraphQL can return massive payloads. A listUsers with 10K results would blow up any LLM context window.

graphql-to-mcp handles this automatically:

  • Arrays → sliced to 20 items, with _meta: "… 9980 more items (10000 total)"
  • Deep nesting → pruned at 5 levels, with "[Object(12 keys)]" summaries
  • Hard safety net at 50K characters

No configuration needed. The LLM gets enough data to understand the response without drowning in tokens.

Built-in Resilience

  • Retry logic — automatic retries on 429/5xx with exponential backoff
  • Timeout — configurable request timeout (default 30s)
  • Partial errors — GraphQL partial errors are surfaced alongside data

Why Not Just Use [existing-tool]?

There are a few GraphQL MCP tools out there. Here's why this one is different:

Feature graphql-to-mcp Others
Flat schemas Yes — nested inputs flattened No — raw nested JSON
Auto-introspection Yes Some
Smart truncation Yes — array + depth pruning No — raw or hard cut
Include/exclude filters Yes — glob patterns Rare
Retry on 429/5xx Yes — exponential backoff No
Zero config Yes — just an endpoint URL Most need config

Try It Now

npx graphql-to-mcp https://countries.trevorblades.com/graphql
Enter fullscreen mode Exit fullscreen mode

Then ask Claude: "What countries are in Europe?"

It just works.


Links:

Top comments (0)