mcp-graphql

edouard-claude/mcp-graphql

3.2

If you are the rightful owner of mcp-graphql and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

The MCP GraphQL Server is a Go-based server that facilitates the generation and execution of GraphQL queries through a standard MCP transport.

Tools
5
Resources
0
Prompts
0

MCP GraphQL Server

A Go-based MCP (Model Context Protocol) server that exposes tools allowing an LLM to generate and execute valid GraphQL queries via HTTP.

🚀 Features

  • Standard MCP transport: JSON-RPC 2.0 over stdio
  • GraphQL HTTP client: Uses only Go standard library
  • 5 MCP tools:
    • graphql.introspectSchema — GraphQL schema introspection
    • graphql.printSDL — SDL generation from introspection
    • graphql.execute — Query/mutation execution with variables
    • graphql.validate — Query validation against schema
    • graphql.listOperations — Operations and variables extraction
  • Header management: Automatic injection of x-api-key, optional Authorization
  • Security: Secret redaction in logs, timeouts, exponential retries
  • Schema cache: Configurable TTL with forceRefresh option

📦 Installation

Pre-compiled binaries

Download the binary for your platform from releases.

Build from source

git clone https://github.com/edouard-claude/mcp-graphql.git
cd mcp-graphql-server
make build

Docker

docker build -t mcp-graphql-server .
docker run -e GRAPHQL_ENDPOINT=https://api.example.com/graphql mcp-graphql-server

⚙️ Configuration

Environment variables

VariableDescriptionDefaultRequired
GRAPHQL_ENDPOINTGraphQL endpoint URL-
GRAPHQL_X_API_KEYAPI key for x-api-key header-
GRAPHQL_AUTH_BEARERDefault Bearer token-
HTTP_TIMEOUT_SECONDSHTTP timeout in seconds30
HTTP_MAX_RETRIESMaximum number of retries2
LOG_LEVELLog level (info, debug, error)info
HTTP_MAX_PAYLOAD_MBMaximum payload size in MB2
SCHEMA_CACHE_TTL_MINUTESSchema cache TTL in minutes10

Configuration file (optional)

Create a config.yaml or config.json file:

endpoint: "https://api.example.com/graphql"
defaultHeaders:
  x-api-key: "${GRAPHQL_X_API_KEY}"
retry:
  maxRetries: 2
  backoffMs: 300
httpTimeout: 30
httpMaxRetries: 2
logLevel: "info"
maxPayloadSize: 2097152
schemaCacheTTL: 10

Run with: ./mcp-graphql-server --config=config.yaml

🛠️ MCP Tools

1. graphql.introspectSchema

Introspects the GraphQL schema and returns the introspection result.

Parameters:

{
  "headers": { "Authorization": "Bearer xxx" },
  "withDescriptions": true,
  "forceRefresh": false
}

Example call:

echo '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "graphql.introspectSchema",
    "arguments": { "withDescriptions": true }
  }
}' | ./mcp-graphql-server

2. graphql.printSDL

Generates the GraphQL schema in SDL format.

Parameters:

{
  "headers": {},
  "preferFederation": false,
  "forceRefresh": false
}

Example call:

echo '{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "graphql.printSDL",
    "arguments": { "preferFederation": false }
  }
}' | ./mcp-graphql-server

3. graphql.execute

Executes a GraphQL query or mutation.

Parameters:

{
  "operationName": "GetUser",
  "query": "query GetUser($id: ID!) { user(id: $id) { id name } }",
  "variables": { "id": "123" },
  "headers": { "Authorization": "Bearer xxx" },
  "timeoutSeconds": 30
}

Example call:

echo '{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "graphql.execute",
    "arguments": {
      "operationName": "GetUser",
      "query": "query GetUser($id: ID!) { user(id: $id) { id name } }",
      "variables": { "id": "123" },
      "headers": { "Authorization": "Bearer XYZ" }
    }
  }
}' | ./mcp-graphql-server

4. graphql.validate

Validates a GraphQL query against the schema.

Parameters:

{
  "query": "query GetUser($id: ID!) { user(id: $id) { id name } }",
  "operationName": "GetUser",
  "headers": {}
}

Example call:

echo '{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "graphql.validate",
    "arguments": {
      "query": "query GetUser($id: ID!) { user(id: $id) { id name } }",
      "operationName": "GetUser"
    }
  }
}' | ./mcp-graphql-server

5. graphql.listOperations

Extracts all operations and their variables from a GraphQL document.

Parameters:

{
  "query": "query GetUser($id: ID!) { user(id: $id) { id name } } mutation CreateUser($name: String!) { createUser(name: $name) { id } }"
}

Example call:

echo '{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "graphql.listOperations",
    "arguments": {
      "query": "query GetUser($id: ID!) { user(id: $id) { id name } } mutation CreateUser($name: String!) { createUser(name: $name) { id } }"
    }
  }
}' | ./mcp-graphql-server

🔒 Security and Headers

Header merge order (increasing priority)

  1. Default headers (env/config): x-api-key, Authorization (if GRAPHQL_AUTH_BEARER)
  2. Tool parameter headers: Override defaults

Allowed headers

Only these headers can be passed via the headers parameter:

  • Authorization
  • x-api-key
  • x-request-id
  • x-tenant-id
  • content-type

Secure configuration example

export GRAPHQL_ENDPOINT="https://api.example.com/graphql"
export GRAPHQL_X_API_KEY="your-api-key"
export GRAPHQL_AUTH_BEARER="your-default-token"
export LOG_LEVEL="info"

📝 Complete examples

Complete workflow with jq

#!/bin/bash

# Configuration
ENDPOINT="https://api.example.com/graphql"
API_KEY="your-api-key"

# 1. List available tools
echo "=== Available tools ==="
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | \
  ./mcp-graphql-server | jq '.result.tools[].name'

# 2. Introspect schema
echo -e "\n=== Schema introspection ==="
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"graphql.introspectSchema","arguments":{"withDescriptions":true}}}' | \
  ./mcp-graphql-server | jq '.result.content[0].text' | jq '.introspection.queryType.name'

# 3. Generate SDL
echo -e "\n=== SDL generation ==="
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"graphql.printSDL","arguments":{}}}' | \
  ./mcp-graphql-server | jq -r '.result.content[0].text' | jq -r '.sdl' | head -20

# 4. List operations from a query
echo -e "\n=== Operations extraction ==="
QUERY='query GetUser($id: ID!) { user(id: $id) { id name email } } mutation CreateUser($name: String!, $email: String!) { createUser(name: $name, email: $email) { id } }'
echo "{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"tools/call\",\"params\":{\"name\":\"graphql.listOperations\",\"arguments\":{\"query\":\"$QUERY\"}}}" | \
  ./mcp-graphql-server | jq '.result.content[0].text' | jq '.operations[]'

# 5. Validate a query
echo -e "\n=== Query validation ==="
echo "{\"jsonrpc\":\"2.0\",\"id\":5,\"method\":\"tools/call\",\"params\":{\"name\":\"graphql.validate\",\"arguments\":{\"query\":\"$QUERY\",\"operationName\":\"GetUser\"}}}" | \
  ./mcp-graphql-server | jq '.result.content[0].text' | jq '.isValid'

# 6. Execute a query
echo -e "\n=== Query execution ==="
echo "{\"jsonrpc\":\"2.0\",\"id\":6,\"method\":\"tools/call\",\"params\":{\"name\":\"graphql.execute\",\"arguments\":{\"operationName\":\"GetUser\",\"query\":\"query GetUser(\$id: ID!) { user(id: \$id) { id name } }\",\"variables\":{\"id\":\"123\"}}}}}" | \
  ./mcp-graphql-server | jq '.result.content[0].text'

Example with curl and a public GraphQL server

# Use Rick and Morty GraphQL API as example
export GRAPHQL_ENDPOINT="https://rickandmortyapi.com/graphql"

# Introspection
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"graphql.introspectSchema","arguments":{"withDescriptions":true}}}' | \
  ./mcp-graphql-server | jq '.result.content[0].text' | jq '.introspection.queryType.name'

# Query execution
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"graphql.execute","arguments":{"query":"{ characters { results { name } } }"}}}' | \
  ./mcp-graphql-server | jq '.result.content[0].text'

# SDL generation
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"graphql.printSDL","arguments":{}}}' | \
  ./mcp-graphql-server | jq -r '.result.content[0].text' | jq -r '.sdl' | head -20

🧪 Tests

# Run all tests
make test

# Tests with coverage
make test-coverage

# Specific tests
go test -v ./internal/graphql/...
go test -v ./internal/util/...

🏗️ Development

Project structure

/cmd/mcp-graphql-server
  main.go                    # Entry point
/internal/mcp
  server.go                  # JSON-RPC server, tool registry
  tools.go                   # Tool definitions and handlers
  types.go                   # MCP request/response structures
/internal/graphql
  client.go                  # HTTP client, execution
  introspection.go           # Introspection request and cache
  sdl.go                     # SDL generation
  validate.go                # Basic schema validation
  ops.go                     # Operation and variable extraction
/internal/config
  config.go                  # Environment + file + flag configuration
/internal/logging
  logger.go                  # Logger with redaction
/internal/util
  redact.go                  # Secret redaction
  retry.go                   # Backoff/retry

Development commands

# Formatting and linting
make fmt vet

# Build and test
make all

# Run in development mode
make run-example

# Build for all platforms
make build-all

# Create a release
make release

📊 Monitoring and Logs

Log levels

  • debug: HTTP request details, cache, validation
  • info: Important operations, recoverable errors
  • error: Critical errors only

Example logs

2024-01-15T10:30:00Z INFO Starting MCP GraphQL server endpoint=https://api.example.com/graphql
2024-01-15T10:30:01Z DEBUG Executing GraphQL request endpoint=https://api.example.com/graphql operationName=GetUser headers=map[Authorization:**** x-api-key:****]
2024-01-15T10:30:01Z DEBUG GraphQL response received hasData=true errorCount=0

🐛 Troubleshooting

Common issues

  1. Error "GRAPHQL_ENDPOINT is required"

    export GRAPHQL_ENDPOINT="https://your-api.com/graphql"
    
  2. Timeout on requests

    export HTTP_TIMEOUT_SECONDS=60
    
  3. Authentication errors

    export GRAPHQL_X_API_KEY="your-api-key"
    # or
    export GRAPHQL_AUTH_BEARER="your-token"
    
  4. Stale schema cache Use "forceRefresh": true in tool parameters.

Debugging

# Enable detailed logs
export LOG_LEVEL=debug
./mcp-graphql-server

# Test connectivity
curl -X POST https://your-api.com/graphql \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-key" \
  -d '{"query":"{ __schema { queryType { name } } }"}'

📄 License

MIT License - see the file for details.

🤝 Contributing

  1. Fork the project
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📞 Support