Skip to content

@graphql2mcp/lib

npm version

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

bash
npm install @graphql2mcp/lib

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

bash
npm install @modelcontextprotocol/sdk

Usage

Basic registration

typescript
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

typescript
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

typescript
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:

typescript
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

typescript
// 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.

typescript
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:

typescript
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:

typescript
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

Released under the MIT License.