Creating an MCP service
This guide walks through creating a new MCP service using
@evolve-packages/mcp-core. The mcp-customer service serves as the reference
implementation.
This guide assumes that @evolve-packages/mcp-core is already installed in
your project. It is included in the Evolve platform by default.
1. Scaffold the service
Start by copying the existing mcp-customer service as a template:
cp -r backend/services/mcp-customer backend/services/mcp-my-service
Update package.json with your service name:
{
"name": "@evolve-platform/mcp-my-service",
"version": "1.0.0",
"description": "MCP server for my use case"
}
2. Configure the service
Update src/config.ts to set the component name and port:
import { MCPCoreConfig } from "@evolve-packages/mcp-core";
export class Config extends MCPCoreConfig {
override COMPONENT_NAME = "mcp-my-service";
override HTTP_PORT = 6001; // Use a unique port
}
3. Define your tools
Create or update operations.graphql with your GraphQL operations. Each
operation that should become an MCP tool needs the @mcpTool directive.
These operations must correspond to the supergraph schema: you can use
fewer fields than the supergraph exposes, but you cannot query fields
that don't exist in it. During code generation, your operations are
validated against the supergraph.
query GetProductDetailPage(
$slug: String! @mcpToolVariable(description: "The product slug to look up")
$skuId: String @mcpToolVariable(description: "Optional specific SKU ID")
) @mcpTool(description: "Get detailed product information by its URL slug") {
product(slug: $slug, skuId: $skuId) {
name
description
slug
variants {
sku
name
price {
centAmount
currencyCode
}
images {
url
}
availability {
isOnStock
}
}
}
}
Every variable should have an @mcpToolVariable(description: ...) annotation.
These descriptions are what AI clients see when deciding how to call the tool.
Clear, specific descriptions lead to better tool usage.
4. Configure code generation
Update codegen.ts to point at your operations and include any plugin
operations you need:
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "../../schema.graphql",
documents: [
"src/**/*.graphql",
// Include plugin operations if using customer-auth
"@evolve-packages/mcp-core/plugins/customer-auth/operations.graphql",
],
generates: {
// ... type generation config
},
};
export default config;
5. Set up the server
In src/create-server.ts, compose the server from mcp-core building blocks:
import {
createToolFromGenerated,
registerTools,
createCustomerAuthPlugin,
} from "@evolve-packages/mcp-core";
export async function createServer(config: Config) {
// Load generated tools
const generatedTools = await loadGeneratedTools(
"#generated/mcp-tools.generated.ts"
);
const tools = generatedTools.map(createToolFromGenerated);
// Set up plugins (optional)
const customerAuthPlugin = createCustomerAuthPlugin(
graphqlClient,
tokenConfig,
generatedTools
);
// Register tools with the MCP server
registerTools({
mcp,
tools,
graphqlClient,
getSessionContext,
setSessionAuth,
plugins: [customerAuthPlugin],
ensureRefreshTokens,
createGuestSession,
});
}
6. Generate and run
# Generate tool definitions from GraphQL operations
pnpm codegen
# Start with HTTP transport (for web clients)
pnpm dev
# Or start with stdio transport (for Claude Desktop)
pnpm dev:stdio
Testing your tools
You can test your MCP server using the MCP Inspector:
npx @modelcontextprotocol/inspector http://localhost:6001/mcp
Or connect it to Claude Desktop by adding it to your Claude Desktop configuration:
{
"mcpServers": {
"evolve": {
"command": "node",
"args": ["backend/services/mcp-my-service/dist/server.js"],
"transport": "stdio"
}
}
}