MCP server template for Umbraco add-ons using the @umbraco-cms/mcp-server-sdk.
npm installCopy .env.example to .env and fill in your Umbraco connection details:
cp .env.example .envIf you have an OpenAPI spec for your add-on:
- Update
orval.config.tsto point to your spec - Run the generator:
npm run generate# Build the server
npm run build
# Run tests
npm test
# Test with MCP Inspector
npm run inspect├── src/
│ ├── api/
│ │ ├── client.ts # API client configuration
│ │ └── generated/ # Orval-generated API code
│ ├── tools/
│ │ └── example/ # Example tool collection
│ │ ├── get/
│ │ ├── post/
│ │ └── index.ts
│ └── index.ts # Server entry point
├── scripts/
│ └── tunnels.sh # Cloudflare tunnels for remote MCP client testing
├── umbraco/
│ ├── McpOAuthComposer.cs # Self-hosted: OAuth client for your own Worker
│ ├── McpHostedClientsComposer.Cloud.cs # Cloud only (commented out): one or more hosted MCP clients (Editor / Dev / …) chosen via array
│ └── McpExternalLoginShortCircuitComposer.Cloud.cs # Cloud only (commented out): redirects to Umbraco SSO instead of dead-ending at /umbraco/login
├── __tests__/
│ └── example/ # Example tests
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── jest.config.ts
├── orval.config.ts
└── .env.example
- Create a new folder under
src/tools/for your tool collection - Create tool files following the example pattern:
get/for GET operationspost/for POST operationsput/for PUT operationsdelete/for DELETE operations
- Create an
index.tsthat exports the collection - Register the collection in
src/index.ts
import { z } from "zod";
import {
withStandardDecorators,
executeGetApiCall,
CAPTURE_RAW_HTTP_RESPONSE,
ToolDefinition,
} from "@umbraco-cms/mcp-server-sdk";
const inputSchema = {
id: z.string().uuid(),
};
const myTool: ToolDefinition<typeof inputSchema> = {
name: "my-tool",
description: "Does something useful",
inputSchema,
slices: ["read"],
annotations: { readOnlyHint: true },
handler: async ({ id }) => {
return executeGetApiCall((client) =>
client.getMyItem(id, CAPTURE_RAW_HTTP_RESPONSE)
);
},
};
export default withStandardDecorators(myTool);Tests use Jest with the MCP toolkit's testing helpers:
import {
setupTestEnvironment,
createSnapshotResult,
createMockRequestHandlerExtra,
} from "@umbraco-cms/mcp-server-sdk/testing";
describe("my-tool", () => {
setupTestEnvironment();
it("should do something", async () => {
const result = await myTool.handler({ id: "..." }, createMockRequestHandlerExtra());
expect(createSnapshotResult(result)).toMatchSnapshot();
});
});This project ships with a .mcp.json that registers the MCP server with Claude Code automatically. Once you have run init, discover, and npm run build, open the project directory in Claude Code and the server is available immediately — no manual claude mcp add required.
# One-time setup
npx @umbraco-cms/create-umbraco-mcp-server init # writes credentials to .env
npx @umbraco-cms/create-umbraco-mcp-server discover # generates API client
npm run build # compiles dist/index.js
# Open in Claude Code — .mcp.json is picked up automatically
claude .The server reads credentials from .env via node --env-file=.env ./dist/index.js, so no secrets are committed to source control.
- Update
package.jsonwith your package name and details - Build:
npm run build - Publish:
npm publish
MIT