mcp-core
@evolve-packages/mcp-core is the core library for building MCP servers that
expose Evolve's GraphQL operations as AI-consumable tools. It handles transport,
sessions, authentication, code generation, and plugin orchestration.
Package entry points
The package provides several entry points for different use cases:
| Entry point | Purpose |
|---|---|
@evolve-packages/mcp-core | Main exports: server, sessions, config, types |
@evolve-packages/mcp-core/codegen | Code generation pipeline |
@evolve-packages/mcp-core/codegen/tools | GraphQL-to-MCP tool generation plugin |
@evolve-packages/mcp-core/codegen/persisted-queries | Persisted document generation |
@evolve-packages/mcp-core/plugins | Built-in plugins (customer-auth) |
Code generation
The core of mcp-core's developer experience is the code generation pipeline. You define tools using GraphQL directives, and the codegen generates TypeScript tool definitions with JSON schemas automatically.
GraphQL directives
Two directives control how operations become MCP tools:
# Mark an operation as an MCP tool
directive @mcpTool(description: String!) on QUERY | MUTATION
# Describe a variable for the tool's input schema
directive @mcpToolVariable(description: String) on VARIABLE_DEFINITION
Defining a tool
A tool is a GraphQL operation annotated with @mcpTool:
query GetProducts(
$query: String @mcpToolVariable(description: "Search query for products")
$limit: Int @mcpToolVariable(description: "Number of results to return")
$offset: Int @mcpToolVariable(description: "Pagination offset")
) @mcpTool(description: "Search for products by query, with pagination") {
products(query: $query, limit: $limit, offset: $offset) {
items {
name
slug
price {
centAmount
currencyCode
}
}
total
}
}
What gets generated
Running pnpm codegen produces two outputs:
mcp-tools.generated.ts, an array of tool definitions:
export const generatedTools: GeneratedMCPTool[] = [
{
name: "get_products",
description: "Search for products by query, with pagination",
inputSchema: {
type: "object",
properties: {
query: { type: "string", description: "Search query for products" },
limit: { type: "integer", description: "Number of results to return" },
offset: { type: "integer", description: "Pagination offset" },
},
},
documentId: "sha256:abc123...",
queryString: "query GetProducts($query: String, ...) { ... }",
},
// ...
];
persisted-documents.json, a mapping of document IDs (SHA-256 hashes)
to query strings. These are registered with GraphQL Hive at deploy time
and act as an allowlist. The gateway rejects any query not in this
registry. See Query security
for the full security model.
Type mapping
The codegen automatically maps GraphQL types to JSON Schema:
| GraphQL type | JSON Schema type |
|---|---|
String | string |
Int | integer |
Float | number |
Boolean | boolean |
ID | string |
| Enums | string with enum values |
| Input objects | object with properties |
| Lists | array with items |
| Non-null | Added to required array |
Configuration
MCP servers are configured through environment variables. The base configuration class provides sensible defaults:
| Variable | Default | Description |
|---|---|---|
HTTP_HOST | 0.0.0.0 | HTTP server bind address |
HTTP_PORT | 6000 | HTTP server port |
MCP_ENDPOINT_PATH | /mcp | MCP endpoint path |
GRAPHQL_GATEWAY_URL | http://localhost:4000 | GraphQL gateway URL |
JWT_ISSUER | http://localhost:4000 | Expected JWT issuer |
JWT_AUDIENCE | http://localhost:4000 | Expected JWT audience |
TOKEN_REFRESH_THRESHOLD_SECONDS | 300 | Refresh tokens this many seconds before expiry |
RATE_LIMIT_MAX | 100 | Max requests per window |
RATE_LIMIT_WINDOW_SECONDS | 60 | Rate limit window duration |
Built-in plugins
Customer auth plugin
The customer-auth plugin handles login and logout flows by intercepting the
customer_login and customer_logout tools. It manages session transitions
between guest and authenticated states, including:
- Executing login/logout mutations against the GraphQL gateway
- Storing new tokens in the session authentication context
- Creating a guest session automatically after logout
- Token refresh before expiry