Zuplo
GraphQL

Your GraphQL endpoint, behind a real gateway

GraphQL hides behind one POST route, where most gateways go blind. Zuplo sees every operation: complexity limits, per-operation analytics, and a built-in MCP server.

GraphQL Playground
query {
  characters(page: 2) {
    info { count }
    results {
      name
    }
  }
}

Run the query

Hit the pink Run button to execute
and see the response

{  "data": {    "characters": {      "info": { "count": 107 },      "results": [        { "name": "Rick" },        { "name": "Morty" },        { "name": "Summer" }      ]    }  }}
Why this matters

An HTTP gateway can't see a GraphQL API

REST gives a gateway many routes and methods to reason about. GraphQL collapses everything into one POST endpoint, so a gateway built for HTTP is blind to the operations underneath. Security, analytics, and limits stop at the door.

×

A second gateway, just for GraphQL

Your REST traffic runs through one gateway. GraphQL gets a separate bespoke proxy with its own auth, limits, and dashboards. Two systems to secure and operate.

×

One endpoint, zero visibility

Everything is POST /graphql, so your HTTP analytics see one route doing all the work. No idea which query is slow or which mutation is failing.

×

Expensive queries reach your resolvers

A deeply nested query or a complexity bomb sails straight through to your origin. By the time your resolvers fall over, the request is already inside.

×

Introspection open in production

The introspection that powers your playground is a full schema map for an attacker. Left on in prod, it exposes every type, field, and mutation you have.

What you get

GraphQL as a first-class citizen of your gateway

One gateway, REST and GraphQL

Proxy your GraphQL upstream through a POST route and every Zuplo policy applies natively: auth, rate limiting, logging, custom TypeScript. No second gateway, no separate control plane.

Every operation is first-class

Zuplo parses each request into named operations. Analytics, limits, and logs work per query and per mutation, not flattened into a single endpoint.

Block the expensive query at the edge

Depth limiting, complexity analysis, and introspection control run before the request reaches your resolvers, across 300+ data centers. Your origin never feels it.

Operation-level security

Stop the expensive query before your resolvers do

A GraphQL route is just a POST route with a stack of policies. Depth and complexity analysis reject abusive queries at the edge; introspection controls keep your schema private. The expensive query never reaches your upstream.

JSONProxy your GraphQL upstream
{
  "/graphql": {
    "post": {
      "operationId": "graphql",
      "x-zuplo-route": {
        "handler": {
          "export": "urlRewriteHandler",
          "module": "$import(@zuplo/runtime)",
          "options": {
            "baseUrl": "${env.GRAPHQL_UPSTREAM}/graphql"
          }
        },
        "policies": {
          "inbound": [
            "api-key-inbound",
            "graphql-complexity-limit",
            "graphql-disable-introspection"
          ]
        }
      }
    }
  }
}
JSONLimit query depth and complexity
{
  "name": "graphql-complexity-limit",
  "policyType": "graphql-complexity-limit-inbound",
  "handler": {
    "export": "GraphQLComplexityLimitInboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "maxDepth": 7,
      "maxComplexity": 1000
    }
  }
}

// Over the limit? Rejected at the edge,
// before your GraphQL server parses it.
Query depth limiting
Complexity / cost analysis
Disable public introspection
Filter introspection responses
Per-consumer rate limiting
Any auth: API key, JWT, OAuth
Operation-aware analytics

See every operation, not one busy endpoint

A dedicated GraphQL section with metrics that understand operations, not just HTTP status codes. Find the slow query, the failing mutation, and whether latency lives in your resolvers or your policies.

Operations 1.24M this window
Success rate 99.2% error / success split
p95 latency 84ms resolver p95 31ms
Error classes 3 resolver · validation · auth
Operation types
  • Query 72%
  • Mutation 22%
  • Subscription 6%
Operations over time
Operation Volume Complexity p95
query query GetCharacters 612K 240 62ms
query query GetCharacterEpisodes 318K 910 148ms
mutation mutation CreateReview 94K 120 203ms
query query SearchLocations 71K 180 44ms
GraphQL → MCP

Turn your GraphQL API into an MCP server

GraphQL is a query language, so an LLM needs the schema before it can ask anything useful. Flag a route as GraphQL MCP and Zuplo generates two tools automatically: one to fetch the schema, one to run queries.

Route Designer Test Route
GraphQL endpoint GraphQL
POST /v1/graphql
MCP Server /mcp
POST /v1/graphql
GraphQL CORS ⚭ MCP Tool Shown in Docs
MCP GraphQL Type: GraphQL
Introspection tool Fetches the schema so the agent knows what to ask
Execute tool Runs queries through the gateway and your policies

Both tools generated automatically, with no hand-written definitions.

1

Agent calls introspection

It pulls your schema and learns which queries, mutations, and types exist.

2

Agent builds a valid query

Armed with the schema, the LLM constructs a query that asks exactly what it needs.

3

Execute runs it through the gateway

The query runs behind your auth, rate limits, and complexity policies, like any client.

What makes Zuplo different

GraphQL support, not a GraphQL bolt-on

Operation-level security

Complexity and depth limits reject abusive queries at the edge, and introspection controls keep your schema private in production. Garbage never reaches your server.

Operation-aware analytics

See operations, success rate, total-vs-resolver p95, and errors split into resolver, validation, and auth. A per-operation table ranks every query by volume, complexity, and latency.

GraphQL to MCP in one route

Flag a GraphQL route for MCP and Zuplo generates an introspection tool and an execute tool automatically. Agents discover your schema and run queries, behind your auth.

Schema-aware docs and playground

Your developer portal renders a browsable type reference and a live query playground straight from your schema. No separate GraphiQL to host or sync.

Real questions, real answers

What teams use this for

“We run REST and GraphQL and don't want two gateways to operate.”

Add a POST /graphql route pointing at your GraphQL server, alongside your REST routes. The same auth, rate limiting, logging, and GitOps deploys cover both. One gateway, one repo.

“Someone is sending 12-level-deep queries that melt resolvers.”

Add the complexity-limit policy and set depth and cost thresholds. Anything over the limit is rejected at the edge before it reaches your upstream. Pair it with per-consumer rate limiting.

“We need introspection for our MCP server but not the public endpoint.”

Keep introspection where the MCP server needs it and disable it on the public route, or filter it to expose only the types you want public. The schema map stays internal.

“Latency is up but we can't tell if it's our server or the gateway.”

Compare total p95 against resolver p95 in the GraphQL analytics tab. Low resolver but high total means the time is in parsing, validation, or auth at the gateway. The per-operation table shows which query regressed.

Frequently Asked Questions

Common questions about running GraphQL through Zuplo.

The gateway your GraphQL API deserves

Free Zuplo project, point a POST /graphql route at your endpoint, and get policies, analytics, and an MCP server today.