Skip to content

New: AI agent integration via Model Context Protocol (MCP).Learn more

MCP endpoint

@evolve-framework/authoring-server mounts an opt-in /mcp route alongside the existing /chat route. Same tools, same auth, same session — different transport. Headless AI clients connect to it the way mcp-customer already does for the storefront’s commerce surface.

The tools the endpoint serves are not hardcoded in the package. The framework ships a small set of built-ins (page generation, image and video generation, block-path lookup) and the host project owns the GraphQL-backed ones via an authoring-operations.graphql file that gets compiled to typed MCP tools by @evolve-framework/mcp-core’s codegen.

Every Evolve project has a slightly different commerce schema, content model, and AI surface. Hardcoding the GraphQL queries in the package would force every customer onto the reference shape — and would mean shipping a new package version every time anyone wanted to extend the toolset.

Putting authoring-operations.graphql in the host service flips the ownership: the framework ships the tool runtime and the built-ins, the project ships its own queries. Codegen turns those queries into typed tool definitions at build time, so no GraphQL strings ride along in the published packages.

It’s the same pattern @evolve-platform/mcp-customer already uses for the storefront. The authoring layer now reuses @evolve-framework/mcp-core’s codegen pipeline directly — see mcp-core for the directive reference.

The 14 tools the authoring AI uses break down into two groups:

Side Tools Why
Framework built-ins generate-page, patch-page, find-block-path, generate-image, generate-video Pure functions on PageData or AI provider calls. No GraphQL, no customer schema.
Project-owned (codegen) search-products, search-categories, search-entries, search-assets, load-page, push-page, prepare-publish, publish-page, catalog Commerce/CMS schema is customer-specific. Each project tunes the queries to its own page types and content model.

The framework set is mounted via buildBuiltinAuthoringTools. The project set is mounted via createAuthoringToolFromGenerated over the codegen output.

graph LR
    Headless["Claude Desktop /<br/>Cursor / agents"] --> MCP
    Chrome["In-browser chat<br/>authoring-chrome"] --> Chat
    Chat["/chat — ai-sdk"] --> Tools["Shared tool runtime"]
    MCP["/mcp — mcp-core"] --> Tools
    Tools --> Gateway[GraphQL gateway]
    Tools --> AI[AI providers]

/chat and /mcp live side-by-side on the same Fastify host and share the same tool implementations. The chrome keeps using /chat (streaming SSE for the chat panel); headless clients use /mcp.

The project runs two codegen passes against the federation gateway’s supergraph. Both live in the host service (typically backend/services/authoring/):

  1. codegen.ts — produces typed documents and persisted-document hashes for every operation in authoring-operations.graphql. Uses the mcpToolTransform from @evolve-framework/mcp-core/codegen so the client-preset learns to read the @mcpTool directive and carry MCP metadata through to the next pass.
  2. codegen.tools.ts — reads the persisted-documents output of pass one and emits src/generated/authoring-tools.generated.ts with the generatedMcpTools array, ready to mount.
codegen.ts
import { mcpToolTransform } from "@evolve-framework/mcp-core/codegen";
import type { CodegenConfig } from "@graphql-codegen/cli";
export const documentPaths = ["./authoring-operations.graphql"];
export const schemaPaths = [
"../graphql-gateway/supergraph.generated.graphql",
"./node_modules/@evolve-framework/mcp-core/directives.graphql",
];
const config: CodegenConfig = {
schema: schemaPaths,
generates: {
"./src/generated/": {
documents: documentPaths,
preset: "client",
documentTransforms: [mcpToolTransform],
presetConfig: {
fragmentMasking: false,
persistedDocuments: {
mode: "embedHashInDocument",
hashPropertyName: "documentId",
},
},
},
},
};
export default config;
codegen.tools.ts
import type { CodegenConfig } from "@graphql-codegen/cli";
import { documentPaths, schemaPaths } from "./codegen.ts";
const config: CodegenConfig = {
schema: schemaPaths,
documents: documentPaths,
generates: {
"./src/generated/authoring-tools.generated.ts": {
plugins: ["@evolve-framework/mcp-core/codegen/tools"],
config: {
persistedDocumentsPath: "./src/generated/persisted-documents.json",
},
},
},
};
export default config;

Both passes run from pnpm codegen.

Every operation in authoring-operations.graphql becomes a typed MCP tool through two directives:

query SearchProducts(
$searchTerm: String
@mcpToolVariable(
description: "Search term, e.g. 'sneakers' or 'winter coat'."
)
$categoryId: String
@mcpToolVariable(
description: "Filter by category id. Call search-categories first for a valid id."
)
$pageSize: Int! = 8
)
@mcpTool(
description: "Search products in the commerce catalog. Use when a ProductBlock needs SKUs."
) {
productSearch(
searchTerm: $searchTerm
categoryId: $categoryId
pageSize: $pageSize
) {
total
results {
variant { sku name primaryImage { url } }
}
}
}

The framework ships an examples/authoring-operations.graphql with the standard Evolve toolset as a starting point. Copy it, prune the tools you don’t want, and tune the queries to your own content shape.

Mount the MCP route on the same Fastify host as the editor server, after mountAuthoringEditor so the session signer is ready:

import {
aiTextOneShot,
generateImageBytes,
generateVideoBytes,
} from "@evolve-framework/authoring-ai-providers";
import {
buildBuiltinAuthoringTools,
createAuthoringToolFromGenerated,
mountAuthoringEditor,
registerAuthoringMcp,
} from "@evolve-framework/authoring-server";
import { generatedMcpTools } from "./generated/authoring-tools.generated.ts";
await mountAuthoringEditor(app, { /* ...existing config */ });
registerAuthoringMcp(app, {
tools: [
...buildBuiltinAuthoringTools({
gatewayUrl: config.GATEWAY_URL,
locale: config.CONTENTFUL_LOCALE,
contentfulSpaceId: config.CONTENTFUL_SPACE_ID,
imageGenerator: generateImageBytes,
videoGenerator: generateVideoBytes,
aiText: aiTextOneShot,
}),
...generatedMcpTools.map((tool) =>
createAuthoringToolFromGenerated(tool, {
gatewayUrl: config.GATEWAY_URL,
locale: config.CONTENTFUL_LOCALE,
}),
),
],
gatewayEndpoint: config.GATEWAY_URL,
});

That’s it: the endpoint serves the built-ins, your project’s generated tools, and shares the session machinery /chat already uses.

/mcp accepts the same two credentials the rest of the authoring server understands:

  • __authoring_session cookie — the browser path. The MCP inspector and any in-page tooling pick this up automatically once the editor is signed in.
  • X-Authoring-Cms-Token header — the headless path. The value can be either an editor’s CMS OAuth token (paste once into the Claude Desktop config) or a service-account CMS management token (the same token the workflows addon uses for unattended runs).

No separate PAT infrastructure: the existing CMS token is the identity carrier. When it expires, the editor pastes a fresh one.

For Claude Desktop, point the MCP client at the authoring service’s /mcp URL with the CMS token as a header. Example fragment for claude_desktop_config.json against a local dev environment:

{
"mcpServers": {
"evolve-authoring": {
"url": "https://authoring.evolve.localhost/mcp",
"headers": {
"X-Authoring-Cms-Token": "<your CMS OAuth or management token>"
}
}
}
}

For local development the URL above lines up with the Portless setup that gives the authoring service a stable HTTPS hostname.

The existing /chat ai-sdk route is unchanged. The chrome continues to use it for the streaming chat panel because ai-sdk’s streaming contract is what the chrome’s transcript renderer consumes. /mcp is purely additive: turn it off (don’t call registerAuthoringMcp) and the chrome works exactly as before.

The two routes share the same underlying tool implementations through a small adapter layer, so a fix to a tool lands in both transports at once.

  • mcp-core — directive reference, type mapping, query-security model.
  • mcp-customer — the reference MCP service that uses the same codegen pipeline for storefront commerce tools.
  • Packagesauthoring-server API surface.