mcp-graphql-enhanced
mcp-graphql-enhanced
Улучшенный MCP-сервер (Model Context Protocol) для GraphQL, который решает реальные проблемы взаимодействия между LLM и GraphQL API.
Прямая замена для
mcp-graphql— с динамическими заголовками, надежным парсингом переменных и без критических изменений.
💬 Сообщество и поддержка
Присоединяйтесь к обсуждению! Если у вас есть вопросы об использовании этого моста с Neo4j, графами данных Discord или GraphQL в целом, заходите к нам:
Канал в Discord: #mcp-graphql-enhanced
Сервер: Официальный GraphQL Discord
Это лучшее место, чтобы поделиться своим мнением, сообщить о проблемах или предложить новые «улучшенные» функции для моста.
Related MCP server: mcp-graphql-schema
✨ Ключевые улучшения
✅ Встроенная IDE GraphiQL — Визуальная песочница по адресу http://localhost:MCP_PORT/ (или /graphiql) с предварительно настроенными заголовками.
✅ Двойной транспорт — Поддерживает как STDIO (для локальных CLI/клиентских инструментов), так и HTTP/JSON-RPC (для внешних/браузерных клиентов).
✅ Динамические заголовки — передавайте
Authorization,X-API-Keyи т.д. через аргументы инструментов (без перезагрузки конфигурации).✅ Надежный парсинг переменных — исправляет ошибку
“Query variables must be a null or an object”.✅ Фильтруемая интроспекция — запрашивайте только определенные типы (например,
typeNames: ["Query", "User"]) для уменьшения шума в контексте LLM.✅ Полная совместимость с MCP — работает с Claude Desktop, Cursor, Glama.
✅ Безопасность по умолчанию — мутации отключены, если не включены явно.
✅ Динамическая эволюция схемы — Умная диагностика и анализ пробелов для серверов, которые перегенерируют типы GraphQL «на лету» (например, Neo4j).
✅ Глубокая наблюдаемость — Автоматическое извлечение и очистка Cypher из расширений GraphQL.
🚀 Широковещательная рассылка на несколько эндпоинтов (Экспериментально в v3.9.0+)
Начиная с v3.9.0, сервер поддерживает одновременный запрос к нескольким GraphQL-эндпоинтам. Изначально это было разработано для синхронизации мутаций между различными средами (например, бэкендами на Node.js и Python), но это открывает мощные возможности для агрегации данных.
Никаких критических изменений: Если вы указываете один URL в
ENDPOINT, сервер ведет себя так же, как и раньше.Умная агрегация: Когда указано несколько URL через запятую, сервер транслирует запрос на все из них и объединяет полученные массивы.
Обход ограничений бесплатного тарифа: Идеально подходит для пользователей облачных баз данных с «бесплатным тарифом» (например, Neo4j Aura). Вы можете распределить свои данные по нескольким бесплатным экземплярам и использовать этот мост для запроса к ним как к единому унифицированному графу, эффективно обходя ограничения на количество сущностей.
Дедупликация: Мост автоматически удаляет дублирующиеся объекты на основе их уникальных полей, чтобы поддерживать чистоту контекстного окна ИИ.
⚠️ Используйте на свой страх и риск: Эта функция предполагает, что все эндпоинты используют одну и ту же (или очень похожую) схему GraphQL. Интроспекция выполняется по первому эндпоинту в списке.
💡 Вариант использования: Соединение WSL и Windows (PowerShell)
Распространенная проблема для разработчиков на Windows — сетевая изоляция между подсистемой Windows для Linux (WSL) и хостовой ОС. Эта функция позволяет объединить эти два мира в «Единую нервную систему».
Пример конфигурации для Claude Desktop:
{
"ENDPOINT": "http://DESKTOP-NAME.local:2311/graphql,http://127.0.0.1:4000/graphql"
}Гибридная экосистема: Беспрепятственно запрашивайте и агрегируйте данные между процессами Windows (PowerShell) и средами на базе Linux (WSL).
Поддержка mDNS: Используя адреса .local, мост автоматически разрешает IP хост-машины из среды WSL.
Прозрачная агрегация: ИИ-ассистент взаимодействует с единой унифицированной схемой, не подозревая, что данные извлекаются из разных операционных систем одновременно.
🔍 Продвинутая наблюдаемость и Cypher
Мост предоставляет глубокое понимание того, как LLM взаимодействует с вашей графовой базой данных.
🕸️ Автоматическое извлечение Cypher
Для реализаций GraphQL-серверов, которые возвращают планы выполнения запросов (например, @neo4j/graphql), мост автоматически:
Обнаруживает
extensions.cypherв ответе.Очищает вывод, удаляя внутренние заголовки (например,
CYPHER 5или пустыеPARAMS).Внедряет чистый блок Cypher непосредственно в вывод инструмента для анализа ИИ.
Примечание: Эта функция требует, чтобы ваш GraphQL-сервер был настроен на включение отладочной информации в расширениях ответа.
🎨 Визуальный командный центр (GraphiQL)
В отличие от стандартных MCP-серверов, этот предоставляет визуальный интерфейс для людей. При запуске с ENABLE_HTTP=true вы можете открыть полнофункциональную IDE GraphiQL в своем браузере.
Эндпоинт:
http://localhost:6274/(или/graphiql)Синхронизация заголовков: Любые заголовки, установленные в вашей среде (например, токены GitHub), автоматически внедряются во вкладку «Headers» GraphiQL для немедленного тестирования.
💻 HTTP / Двойной транспорт
Теперь этот сервер работает в режиме двойного транспорта, поддерживая как стандартную связь STDIO (используемую большинством MCP-клиентов), так и новый эндпоинт HTTP JSON-RPC на порту 6274.
Это позволяет внешним системам, веб-приложениям и прямым командам curl получать доступ к инструментам сервера с логированием запросов в реальном времени в вашем терминале (логи [HTTP-RPC]).
Эндпоинт | Метод | Описание |
|
| Интерфейс пользователя: Визуальная GraphQL IDE. |
|
| Основной эндпоинт JSON-RPC 2.0 для выполнения инструментов. |
|
| Простая проверка работоспособности, возвращает |
Автоматический выбор порта
Сервер по умолчанию использует порт 6274. Если вы столкнетесь с ошибкой EADDRINUSE, сервер автоматически найдет следующий доступный порт. Проверяйте логи сервера для определения конечного порта (например, [HTTP] Started server on http://localhost:6275).
Разрешение конфликтов портов (EADDRINUSE) и автоматический выбор порта
Сервер по умолчанию использует порт 6274. Если вы столкнетесь с ошибкой EADDRINUSE: address already in use :::6274 (часто встречается при локальной разработке из-за зависших процессов), сервер автоматически найдет следующий доступный порт (до 10 попыток, без запуска нескольких серверов).
Это гарантирует успешный запуск сервера, даже если порт по умолчанию занят. Всегда проверяйте логи сервера для определения конечного порта (например, [HTTP] Started server on http://localhost:6275), если ваш curl или клиентский инструмент выдает ошибку на порту 6274 по умолчанию.
Чтобы принудительно задать конкретный порт (например, для гарантированных настроек внешнего брандмауэра), вы все еще можете явно установить переменную окружения MCP_PORT:
Тестирование HTTP-эндпоинта
Вы можете протестировать эндпоинт с помощью curl, пока сервер запущен (например, через npm run dev):
# Test the health check (assuming the server bound to the default or found the next available port)
curl http://localhost:6274/health
# Example: Test the query tool via JSON-RPC (using port 6275 if 6274 was busy)
curl -X POST http://localhost:6275/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"query-graphql","params":{"query":"query { __typename }"},"id":1}'
## 🔍 Filtered Introspection
Avoid 50k-line schema dumps. Ask for only what you need:
`@introspect-schema typeNames ["Query", "User"]`
## 🔍 Debug & Inspect
Use the official MCP Inspector to test your server live:
```bash
npx @modelcontextprotocol/inspector \
-e ENDPOINT=https://api.example.com/graphql \
npx @letoribo/mcp-graphql-enhancedПеременные окружения (Критическое изменение в 1.0.0)
Примечание: Начиная с версии 1.0.0, аргументы командной строки были заменены переменными окружения.
Переменная окружения | Описание | По умолчанию |
| URL GraphQL-эндпоинта |
|
| JSON-строка, содержащая заголовки для запросов |
|
| Разрешить операции мутации (отключено по умолчанию) |
|
| Имя MCP-сервера |
|
| Путь к локальному файлу схемы GraphQL или URL | - |
| Порт для HTTP/JSON-RPC сервера. |
|
| Включить HTTP-транспорт: |
|
| Установите | - |
Примечание по |
auto(по умолчанию): Автоматически включает HTTP только при запуске в MCP Inspector...true: Всегда включать HTTP-серверfalse: Полностью отключить HTTP-сервер
Примеры
# Basic usage
ENDPOINT=http://localhost:3000/graphql npx @letoribo/mcp-graphql-enhanced
# With auth header
ENDPOINT=https://api.example.com/graphql \
HEADERS='{"Authorization":"Bearer xyz"}' \
npx @letoribo/mcp-graphql-enhanced
# Enable mutations
ENDPOINT=http://localhost:3000/graphql \
ALLOW_MUTATIONS=true \
npx @letoribo/mcp-graphql-enhanced
# Use local schema file
ENDPOINT=http://localhost:3000/graphql \
SCHEMA=./schema.graphql \
npx @letoribo/mcp-graphql-enhanced
# Change the HTTP port
MCP_PORT=8080 npx @letoribo/mcp-graphql-enhanced
# Disable HTTP transport (fastest, recommended for Claude Desktop)
ENABLE_HTTP=false npx @letoribo/mcp-graphql-enhanced
# Test the surgical precision and the IDE immediately:
ENDPOINT=https://api.github.com/graphql \
HEADERS='{"Authorization":"Bearer YOUR_GITHUB_TOKEN"}' \
ENABLE_HTTP=true \
npx @letoribo/mcp-graphql-enhanced
# Then visit http://localhost:6274/graphiql🖥️ Примеры конфигурации Claude Desktop
Вы можете подключить Claude Desktop к своему GraphQL API, используя либо пакет npx (рекомендуется для простоты), либо Docker-образ (идеально для воспроизводимости и изоляции).
✅ Вариант 1: Использование npx
{
"mcpServers": {
"mcp-graphql-enhanced": {
"command": "npx",
"args": ["@letoribo/mcp-graphql-enhanced"],
"env": {
"ENDPOINT": "https://your-api.com/graphql"
}
}
}
}🐳 Вариант 2: Использование Docker (поддерживается авто-pull)
{
"mcpServers": {
"mcp-graphql-enhanced": {
"command": "sh",
"args": [
"-c",
"docker run --rm -i -e ENDPOINT=$ENDPOINT -e HEADERS=$HEADERS -e ALLOW_MUTATIONS=$ALLOW_MUTATIONS ghcr.io/letoribo/mcp-graphql-enhanced:main"
],
"env": {
"ENDPOINT": "https://your-api.com/graphql",
"HEADERS": "{\"Authorization\": \"Bearer YOUR_TOKEN\"}",
"ALLOW_MUTATIONS": "false"
}
}
}
}🧪 Вариант 3: Использование node с локальной сборкой (для разработки)
Если вы клонировали репозиторий и собрали проект (npm run build → вывод в dist/):
{
"mcpServers": {
"mcp-graphql-enhanced": {
"command": "node",
"args": ["dist/index.js"],
"env": {
"ENDPOINT": "https://your-api.com/graphql",
"ALLOW_MUTATIONS": "true"
}
}
}
}Ресурсы
graphql-schema: Сервер предоставляет схему GraphQL как ресурс, к которому могут обращаться клиенты. Это либо локальный файл схемы, файл схемы, размещенный по URL, либо результат запроса интроспекции.
Доступные инструменты
Сервер предоставляет два основных инструмента:
introspect-schema: Этот инструмент извлекает схему GraphQL или отфильтрованное подмножество (через typeNames). Используйте его в первую очередь, если у вас нет доступа к схеме как к ресурсу. Он использует либо локальный файл схемы, файл схемы, размещенный по URL, либо запрос интроспекции. Фильтруемая интроспекция (typeNames) доступна только при использовании активного GraphQL-эндпоинта (не с файлом SCHEMA или URL).
query-graphql: Выполнение запросов GraphQL к эндпоинту. По умолчанию мутации отключены, если
ALLOW_MUTATIONSне установлено вtrue.
Вопросы безопасности
Мутации по умолчанию отключены для предотвращения непреднамеренных изменений данных. Всегда проверяйте входные данные HEADERS и SCHEMA в рабочей среде. По возможности используйте HTTPS-эндпоинты и краткосрочные токены.
Настройка для вашего собственного сервера
Это очень общая реализация, которая позволяет выполнять полную интроспекцию и дает пользователям возможность делать что угодно (включая мутации). Если вам нужна более специфическая реализация, я бы предложил создать свой собственный MCP и ограничить вызов инструментов для клиентов, чтобы они могли вводить только определенные поля запроса и/или переменные. Вы можете использовать это в качестве справочного материала.
Available Tools
2 toolsintrospect-schemaA
Retrieve GraphQL schema details or system manifest. READ-ONLY: Non-destructive metadata discovery. Usage: 1. If 'typeNames' is provided: Returns the full SDL (Schema Definition Language) for the requested types, including fields and relations. 2. If 'typeNames' is omitted: Returns a Federated Manifest—a high-level summary of connected nodes, their capabilities, and available domain entities (not the full schema). Use this to navigate the federated graph topology before executing queries.
| Name | Required | Description | Default |
|---|---|---|---|
| headers | No | JSON stringified object of extra HTTP headers for the introspection request (e.g. '{"Authorization": "Bearer token"}'). | |
| endpoint | No | Optional target GraphQL HTTP/HTTPS URL to dynamically switch endpoint before execution. | |
| typeDepth | No | Depth of nested fields to retrieve (default: 2) | |
| typeNames | No | List of specific GraphQL type names to introspect. If provided, returns the detailed SDL definitions for these types. If omitted, returns a system-wide Federated Manifest overview. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it explicitly declares 'READ-ONLY: Non-destructive metadata discovery.' It also discloses the two distinct behavioral outcomes based on typeNames and clarifies that the manifest is 'not the full schema,' which helps set expectations. It does not mention potential errors or how headers/endpoint affect behavior, but the core safety and conditional behavior are clearly communicated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear one-line summary, an explicit READ-ONLY safety cue, and a numbered list that front-loads the two usage modes. Every sentence contributes either to behavioral transparency or invocation guidance, with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a moderate-complexity tool with zero required parameters and no output schema, the description is largely complete: it covers both invocation modes, the manifest vs. SDL distinction, and the read-only nature. It could be more complete by explicitly routing query execution to query-graphql, but this is a minor gap given the clear 'before executing queries' framing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds meaningful behavior beyond the schema by explaining the conditional outcome for typeNames and clarifying that results include 'fields and relations.' This gives an agent a better mental model of what each parameter triggers, even though the schema already documents the parameters themselves.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as retrieving GraphQL schema details or a system manifest, with a specific verb and resource. It distinguishes between two modes—full SDL for requested types versus a Federated Manifest overview—and positions it as metadata discovery before executing queries, differentiating it from the sibling query-graphql tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit conditional guidance: use typeNames to get full SDL definitions, omit it to get a manifest for navigating the federated graph. It also states to use the manifest 'before executing queries,' providing clear context. However, it does not explicitly name or exclude the sibling tool query-graphql as the alternative for actual query execution.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query-graphqlA
Execute GraphQL operations (queries and mutations) against the federated system. WARNING: This tool performs remote operations. 'Mutation' operations will modify persistent state; execute these only when a state change is intended. Prerequisites: Verify schema structure using 'introspect-schema' before executing complex queries. Security: Inherits environment-based authentication. Returns: A JSON object containing the execution result ('data') or a list of 'errors' in case of failure.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The GraphQL query or mutation string. Example: 'query { guilds { id name } }'. | |
| headers | No | JSON stringified object of extra HTTP headers for the request. | |
| endpoint | No | Optional target GraphQL HTTP/HTTPS URL to dynamically switch endpoint before execution. | |
| variables | No | JSON stringified object of variables. Example: '{"id": "123"}'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does so well: it discloses that the tool performs remote operations, that mutations modify persistent state, that authentication is inherited from the environment, and that failures return an errors list. These are the key behavioral facts an agent needs beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into clear warning, prerequisite, security, and return-value statements with no filler. It is slightly longer than a minimal two-sentence description, but each section contributes a distinct piece of operational knowledge.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given four parameters and no output schema or annotations, the description covers the essential operating context: when to verify schema, mutation risk, authentication model, and expected return structure. No critical information needed to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description adds value by warning that the required query string may contain operations that mutate persistent state, and by noting the return shape. It does not repeat schema descriptions, but provides meaningful semantic context for the query parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action verb ('Execute') and target ('GraphQL operations ... against the federated system'), distinguishing this as the operation-execution tool while the sibling 'introspect-schema' is referenced only for schema verification. The clarification that it handles both queries and mutations further disambiguates its role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the sibling tool as a prerequisite step ('Verify schema structure using introspect-schema before executing complex queries'), and warns to execute mutations only when a state change is intended. This gives the agent clear when-to-use and when-not-to-use guidance for mutation operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v4.15.2- Changed
introspect-schema2 fields changed- added
Input schema / properties / endpointAdded value: +{ + "description": "Optional target GraphQL HTTP/HTTPS URL to dynamically switch endpoint before execution.", + "type": "string" +} - added
Input schema / properties / headersAdded value: +{ + "description": "JSON stringified object of extra HTTP headers for the introspection request (e.g. '{\"Authorization\": \"Bearer token\"}').", + "type": "string" +}
- Changed
query-graphql1 field changed- added
Input schema / properties / endpointAdded value: +{ + "description": "Optional target GraphQL HTTP/HTTPS URL to dynamically switch endpoint before execution.", + "type": "string" +}
1 tool update
v4.13.1- Added
introspect-schema
1 tool update
v4.12.0- Removed
introspect-schema
1 tool update
v4.9.2- Changed
introspect-schema1 field changed- removed
Input schema / properties / typeDepth / defaultRemoved value: -2
2 tool updates
v4.8.0- Changed
introspect-schema2 fields changed- added
Input schema / properties / typeDepthAdded value: +{ + "default": 2, + "description": "Depth of nested fields to retrieve (default: 2)", + "type": "number" +} - changed
Input schema / properties / typeNames / descriptionPrevious value: -"List of specific GraphQL type names to introspect. If omitted, the full schema is returned (use with caution on large APIs)."New value: +"List of specific GraphQL type names to introspect. If provided, returns the detailed SDL definitions for these types. If omitted, returns a system-wide Federated Manifest overview."
- Changed
query-graphql3 fields changed- changed
Input schema / properties / headers / descriptionPrevious value: -"JSON string of extra HTTP headers for the request."New value: +"JSON stringified object of extra HTTP headers for the request." - changed
Input schema / properties / query / descriptionPrevious value: -"The GraphQL query or mutation string."New value: +"The GraphQL query or mutation string. Example: 'query { guilds { id name } }'." - changed
Input schema / properties / variables / descriptionPrevious value: -"JSON string of variables for the operation."New value: +"JSON stringified object of variables. Example: '{\"id\": \"123\"}'."
2 tool updates
v4.2.0- Changed
introspect-schema1 field changed- changed
Input schema / properties / typeNames / descriptionPrevious value: -"List of type names to introspect"New value: +"List of specific GraphQL type names to introspect. If omitted, the full schema is returned (use with caution on large APIs)."
- Changed
query-graphql3 fields changed- changed
Input schema / properties / headers / descriptionPrevious value: -"JSON string of extra headers"New value: +"JSON string of extra HTTP headers for the request." - changed
Input schema / properties / query / descriptionPrevious value: -"The GraphQL query or mutation string"New value: +"The GraphQL query or mutation string." - changed
Input schema / properties / variables / descriptionPrevious value: -"JSON string of variables"New value: +"JSON string of variables for the operation."
2 tool updates
v3.9.3- Added
introspect-schema - Added
query-graphql
2 tool updates
v2.0.7- Removed
introspect-schema - Removed
query-graphql
2 tool updates
v1.0.0- Changed
introspect-schema3 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / typeNames / descriptionPrevious value: -"e.g., [\"Query\", \"User\"]"New value: +"A list of specific type names to filter the introspection."
- Changed
query-graphql2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - added
Input schema / additionalPropertiesAdded value: +false
TDQS
Scored across 2 tools
query-graphql handles all execution, including state-changing mutations, while introspect-schema is strictly read-only metadata discovery. Their purposes are sharply separated with no overlap.
Both tools follow the same verb-noun hyphenated pattern: query-graphql and introspect-schema. The naming is predictable and consistent.
Two tools is slightly below the typical 3-15 range, but it is a reasonable and well-scoped count for a GraphQL server: one execution tool and one schema-discovery tool. Each tool earns its place.
For a GraphQL-focused server, the pair covers the full interaction surface: schema/introspection discovery and arbitrary query/mutation execution. There are no obvious missing capabilities.
Maintenance
Related MCP Connectors
The official MCP Server for the Mux API
MCP server for the Seline Analytics API
The official MCP Server from Mia-Platform to interact with Mia-Platform Console
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
Related MCP Servers
- MIT
- AlicenseNot gradedqualityDmaintenanceA MCP server that exposes GraphQL schema information to LLMs like Claude. This server allows an LLM to explore and understand large GraphQL schemas through a set of specialized tools, without needing to load the whole schema into the context35 npm46MIT
- AlicenseAqualityDmaintenanceGraphQL MCP Server that acts as a bridge allowing MCP clients (like Cursor or Claude Desktop) to interact with target GraphQL APIs through standard tools for schema introspection and operation execution.213 npm3MIT
- AlicenseNot gradedqualityDmaintenanceMCP that can proxy any GraphQL API and expose graphql operations as mcp tools.13 npm18Apache 2.0