graphql2mcp

@graphql2mcp/lib

Library for integrating GraphQL-to-MCP conversion into existing TypeScript MCP servers.

@graphql2mcp/lib

npm version

Documentation

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/lib

Peer dependency: @modelcontextprotocol/sdk (>= 1.27.1).

npm install @modelcontextprotocol/sdk

Usage

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

OptionTypeDefaultDescription
sourcestringundefinedSDL string, file path, glob, or introspection JSON path
schemaGraphQLSchemaundefinedPre-built GraphQL schema (alternative to source)
endpointstring(required)GraphQL execution endpoint URL
headersRecord<string, string>undefinedHTTP headers for runtime execution
mutationsMutationMode'none'Mutation exposure mode ('none', 'all', or { whitelist: [...] })
depthnumber3Maximum depth for return type field selection
includestring[]undefinedOnly include these operations
excludestring[]undefinedExclude these operations
queryPrefixstring'query_'Prefix for query tool names
mutationPrefixstring'mutation_'Prefix for mutation tool names
customScalarsRecord<string, z.ZodType>undefinedCustom Zod schemas for GraphQL custom scalars
timeoutnumber30000Request 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 getGraphQLTools and registerGraphQLTools are 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:

PropertyTypeDescription
namestringTool name (e.g. "query_users")
titlestringHuman-readable title (e.g. "Query: users")
descriptionstringTool description
inputSchemaRecord<string, z.ZodType>Zod shape for input parameters
annotationsToolAnnotationsMCP 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
fieldNamestringThe original GraphQL field name
queryDocumentstringThe 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

On this page