GraphQL服务器工具

一个基于Go的MCP服务器,提供工具允许LLM通过HTTP生成和执行有效的GraphQL查询。

  • by edouard-claude
  • Go
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 edouard-claude/mcp-graphql

使用说明

MCP GraphQL服务器

一个基于Go的MCP(模型上下文协议)服务器,它公开了允许LLM通过HTTP生成和执行有效GraphQL查询的工具。

🚀 特性

  • 标准MCP传输:JSON-RPC 2.0通过标准输入
  • GraphQL HTTP客户端:仅使用Go标准库
  • 5个MCP工具:
    • graphql.introspectSchema --GraphQL模式自检
    • graphql.printSDL --从内省中生成SDL
    • graphql.execute --使用变量执行查询/变异
    • graphql.validate --根据架构进行查询验证
    • graphql.listOperations --操作和变量提取
  • 标题管理:自动注射 x-api-key,可选 Authorization
  • 安全:日志中的秘密编辑、超时、指数重试
  • 架构缓存:可配置TTL forceRefresh 选项

📦 安装

预编译二进制文件

从以下网址下载适用于您平台的二进制文件 发布.

从源代码构建

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

码头工人

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

⚙️ 配置

环境变量

变量 描述 默认值 必填
GRAPHQL_ENDPOINT GraphQL端点URL - ✅
GRAPHQL_X_API_KEY 的API密钥 x-api-key 头球❌
GRAPHQL_AUTH_BEARER 默认承载令牌 - ❌
HTTP_TIMEOUT_SECONDS HTTP超时(秒) 30 ❌
HTTP_MAX_RETRIES 最大重试次数 2 ❌
LOG_LEVEL 日志级别(info, debug, error) info ❌
HTTP_MAX_PAYLOAD_MB 最大有效载荷大小(MB) 2 ❌
SCHEMA_CACHE_TTL_MINUTES 架构缓存TTL(分钟) 10 ❌

配置文件(可选)

创建一个 config.yaml 或 config.json 文件:

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

运行方式: ./mcp-graphql-server --config=config.yaml

🛠️ MCP工具

1. graphql.introspectSchema

内省GraphQL模式并返回内省结果。

参数:

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

示例调用:

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

2. graphql.printSDL

生成SDL格式的GraphQL模式。

参数:

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

示例调用:

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

3. graphql.execute

执行GraphQL查询或变异。

参数:

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

示例调用:

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

根据架构验证GraphQL查询。

参数:

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

示例调用:

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

从GraphQL文档中提取所有操作及其变量。

参数:

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

示例调用:

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

🔒 安全和标题

标题合并顺序(优先级递增)

  1. 默认标题 (env/config): x-api-key, Authorization (如果 GRAPHQL_AUTH_BEARER)
  2. 工具参数标题:覆盖默认值

允许的标题

只有这些标头可以通过 headers 参数:

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

安全配置示例

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"

📝 完整示例

使用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'

使用curl和公共GraphQL服务器的示例

# 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

🧪 测试

# Run all tests
make test

# Tests with coverage
make test-coverage

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

🏗️ 发展

项目结构

/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

开发命令

# 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

📊 监控和日志

日志级别

  • debug:HTTP请求详细信息、缓存、验证
  • info:重要操作,可恢复错误
  • error:仅严重错误

日志示例

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

🐛 故障排除

常见问题

  1. 错误“GRAPHQL_ENDPOINT是必需的”

    export GRAPHQL_ENDPOINT="https://your-api.com/graphql"
    
  2. 请求超时

    export HTTP_TIMEOUT_SECONDS=60
    
  3. 身份验证错误

    export GRAPHQL_X_API_KEY="your-api-key"
    # or
    export GRAPHQL_AUTH_BEARER="your-token"
    
  4. 陈旧的架构缓存 使用 "forceRefresh": true 在刀具参数中。

调试

# 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 } } }"}'

📄 许可证

MIT许可证-请参阅 许可证 文件以获取详细信息。

🤝 贡献

  1. 分叉项目
  2. 创建要素分支(git checkout -b feature/amazing-feature)
  3. 提交您的更改(git commit -m 'Add amazing feature')
  4. 推到分支(git push origin feature/amazing-feature)
  5. 打开拉取请求

📞 支持