@graphql2mcp/lib
Library for integrating GraphQL-to-MCP conversion into existing TypeScript MCP servers. Register GraphQL-backed tools on your own McpServer instance alongside your custom tools.
Install
npm install @graphql2mcp/libPeer dependency: @modelcontextprotocol/sdk (>= 1.27.1).
npm install @modelcontextprotocol/sdkUsage
Basic registration
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { registerGraphQLTools } from '@graphql2mcp/lib';
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
const result = registerGraphQLTools(server, {
source: 'schema.graphql',
endpoint: 'https://api.example.com/graphql'
});
console.log(`Registered ${result.count} tools`);
// result.tools contains metadata about each registered tool
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);Mix custom tools with GraphQL tools
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { z } from 'zod';
import { registerGraphQLTools } from '@graphql2mcp/lib';
const server = new McpServer({ name: 'hybrid-server', version: '1.0.0' });
// Your own custom tools
server.registerTool(
'ping',
{
title: 'Ping',
description: 'Health check',
inputSchema: { message: z.string().optional() }
},
({ message }) => ({
content: [{ type: 'text', text: `pong: ${message ?? ''}` }]
})
);
// Add GraphQL tools from an SDL string
registerGraphQLTools(server, {
source: `
type Query {
users(limit: Int): [User!]!
user(id: ID!): User
}
type User {
id: ID!
name: String!
email: String
}
`,
endpoint: 'https://api.example.com/graphql'
});
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);With authentication headers
registerGraphQLTools(server, {
source: 'schema.graphql',
endpoint: 'https://api.example.com/graphql',
headers: {
Authorization: 'Bearer YOUR_TOKEN',
'X-API-Key': 'your-api-key'
}
});From a pre-built schema
If you already have a GraphQLSchema object, pass it directly instead of a source string:
import { buildSchema } from 'graphql';
import { registerGraphQLTools } from '@graphql2mcp/lib';
const schema = buildSchema(`
type Query {
hello: String
}
`);
registerGraphQLTools(server, {
schema,
endpoint: 'https://api.example.com/graphql'
});Mutation configuration
// Expose all mutations
registerGraphQLTools(server, {
source: 'schema.graphql',
endpoint: 'https://api.example.com/graphql',
mutations: 'all'
});
// Expose no mutations (default)
registerGraphQLTools(server, {
source: 'schema.graphql',
endpoint: 'https://api.example.com/graphql',
mutations: 'none'
});
// Expose specific mutations only
registerGraphQLTools(server, {
source: 'schema.graphql',
endpoint: 'https://api.example.com/graphql',
mutations: { whitelist: ['createUser', 'updateUser'] }
});Options
| Option | Type | Default | Description |
|---|---|---|---|
source | string | undefined | SDL string, file path, glob, or introspection JSON path |
schema | GraphQLSchema | undefined | Pre-built GraphQL schema (alternative to source) |
endpoint | string | (required) | GraphQL execution endpoint URL |
headers | Record<string, string> | undefined | HTTP headers for runtime execution |
mutations | MutationMode | 'none' | Mutation exposure mode ('none', 'all', or { whitelist: [...] }) |
depth | number | 3 | Maximum depth for return type field selection |
include | string[] | undefined | Only include these operations |
exclude | string[] | undefined | Exclude these operations |
queryPrefix | string | 'query_' | Prefix for query tool names |
mutationPrefix | string | 'mutation_' | Prefix for mutation tool names |
customScalars | Record<string, z.ZodType> | undefined | Custom Zod schemas for GraphQL custom scalars |
timeout | number | 30000 | Request timeout in milliseconds |
Either source or schema must be provided. If both are given, schema takes precedence.
getGraphQLTools(options)
Generate tools with bound handlers without registering them on a server. Useful when you need full control over registration or want to inspect tools before adding them.
Both
getGraphQLToolsandregisterGraphQLToolsare re-exported from@graphql2mcp/core. If you depend on both packages, the functions and types are interchangeable.
import { getGraphQLTools } from '@graphql2mcp/lib';
const { tools, count } = getGraphQLTools({
source: 'schema.graphql',
endpoint: 'https://api.example.com/graphql',
mutations: 'all'
});
for (const tool of tools) {
console.log(tool.name, tool.operationType);
// tool.handler(args) executes the GraphQL operation
// tool.inputSchema, tool.annotations, tool.queryDocument, etc.
}Each GraphQLToolEntry includes:
| Property | Type | Description |
|---|---|---|
name | string | Tool name (e.g. "query_users") |
title | string | Human-readable title (e.g. "Query: users") |
description | string | Tool description |
inputSchema | Record<string, z.ZodType> | Zod shape for input parameters |
annotations | ToolAnnotations | MCP tool annotations (readOnlyHint, destructiveHint, etc.) |
handler | (args) => Promise<CallToolResult> | Async handler that executes the GraphQL operation |
operationType | 'query' | 'mutation' | Whether this tool wraps a query or mutation |
fieldName | string | The original GraphQL field name |
queryDocument | string | The GraphQL query/mutation document string sent at runtime |
Loading a schema from a live endpoint
Use loadSchemaFromUrl to introspect a live GraphQL endpoint:
import { loadSchemaFromUrl, registerGraphQLTools } from '@graphql2mcp/lib';
const schema = await loadSchemaFromUrl({
url: 'https://api.example.com/graphql',
headers: { Authorization: 'Bearer YOUR_TOKEN' }
});
registerGraphQLTools(server, {
schema,
endpoint: 'https://api.example.com/graphql',
headers: { Authorization: 'Bearer YOUR_TOKEN' }
});Return Value
registerGraphQLTools returns a RegisterGraphQLToolsResult:
interface RegisterGraphQLToolsResult {
tools: RegisteredToolInfo[];
count: number;
}
interface RegisteredToolInfo {
name: string; // e.g. "query_users"
title: string; // e.g. "Query: users"
operationType: 'query' | 'mutation';
fieldName: string; // original GraphQL field name
}License
MIT