mit einem Klick
build-tools
// Build MCP tool collections from discovered API groups. Reads .discover.json and generates tools and collection registrations. Use after running 'npx @umbraco-cms/create-umbraco-mcp-server discover'.
// Build MCP tool collections from discovered API groups. Reads .discover.json and generates tools and collection registrations. Use after running 'npx @umbraco-cms/create-umbraco-mcp-server discover'.
Load MCP development patterns and best practices for building tools with the @umbraco-cms/mcp-server-sdk. Use when starting tool development or needing pattern reference.
Guide for configuring and running Umbraco MCP servers via the CLI. Use when the user wants to set up an MCP server for Claude Code, configure auth, filtering, dry-run, readonly mode, or use introspection commands to understand available tools.
Add or update an LLM eval test for a specific tool or collection. Creates a new eval scenario or updates an existing one to cover new tools. Use when adding eval coverage for new or modified tools.
Add an integration test for a specific tool in an existing collection. Creates a test file following the collection's established patterns. Use when adding tests for new or modified tools, or re-creating deleted tests.
Add a new tool to an existing MCP collection. Creates the tool file, updates the collection index, optionally adds integration tests and eval tests. Use when adding new API endpoints to collections already created by '/build-tools'.
Build LLM eval tests for MCP tool collections. Reads .discover.json and creates eval setup and scenario test files per collection. Use after running '/build-tools'.
| name | build-tools |
| description | Build MCP tool collections from discovered API groups. Reads .discover.json and generates tools and collection registrations. Use after running 'npx @umbraco-cms/create-umbraco-mcp-server discover'. |
| user_invocable | true |
Generate MCP tool collections from the API groups selected during discovery. This skill reads .discover.json and the swagger spec, then builds tool files one collection at a time.
IMPORTANT: This skill ONLY creates tool files, collection indexes, and registrations. Do NOT create any test files, test setup, test builders, test helpers, or __tests__/ directories. Testing is handled separately by the /build-tools-tests skill.
Before running, ensure:
npx @umbraco-cms/create-umbraco-mcp-server discover (.discover.json exists)src/umbraco-api/api/generated/ directory exists โ if not, run npm run generate).discover.json/build-tools form)This skill orchestrates the following agents โ use them for the relevant steps:
| Agent | When to use |
|---|---|
mcp-tool-creator | Creating each tool file (Step 3b) |
mcp-tool-description-writer | Writing tool descriptions (Step 3b) |
mcp-tool-reviewer | Reviewing tools for LLM-readiness (Step 4) |
Process one collection at a time. Complete each collection fully before starting the next.
Read .discover.json from the project root:
{
"apiName": "Umbraco Forms Management API",
"swaggerUrl": "https://localhost:44324/umbraco/swagger/forms-management/swagger.json",
"baseUrl": "https://localhost:44324",
"collections": ["form", "form-template", "field-type", "folder"]
}
If an argument was provided, filter to only that collection. If .discover.json doesn't exist, tell the user to run npx @umbraco-cms/create-umbraco-mcp-server discover first.
Check if src/umbraco-api/api/generated/ exists and contains .ts files. If not, run:
npm run generate
Then read the generated files to understand:
getFormsManagementAPI)*.zod.ts files)Fetch the swagger spec from the swaggerUrl in .discover.json using curl:
curl -sk {swaggerUrl}
For each collection, find operations where tags[0] matches the collection's original tag name (the tag before kebab-case conversion). Collect:
For each collection, skip if src/umbraco-api/tools/{collection}/index.ts already exists.
src/umbraco-api/tools/{collection}/
โโโ get/
โโโ post/
โโโ put/
โโโ delete/
Not every directory is needed โ only create subdirectories for HTTP methods that have operations.
CRITICAL: Create ONE tool file, then immediately compile. Fix any errors before creating the next tool. This prevents errors from cascading across files.
Create one file per operation. Map operations to files:
| HTTP Method | File pattern | Slice | Annotations |
|---|---|---|---|
| GET (single item by ID) | get/get-{entity}.ts | read | readOnlyHint: true |
| GET (list/collection) | get/list-{entities}.ts | list | readOnlyHint: true |
| GET (search) | get/search-{entities}.ts | search | readOnlyHint: true |
| POST | post/create-{entity}.ts | create | destructiveHint: false, idempotentHint: false |
| PUT/PATCH | put/update-{entity}.ts | update | idempotentHint: true |
| DELETE | delete/delete-{entity}.ts | delete | destructiveHint: true |
Each tool file follows this pattern:
import {
withStandardDecorators,
executeGetApiCall, // GET operations
executeVoidApiCall, // DELETE/PUT operations
createToolResult, // POST operations (manual handling)
getApiClient, // POST operations (manual handling)
UmbracoApiError, // POST operations (manual handling)
CAPTURE_RAW_HTTP_RESPONSE,
ToolDefinition,
} from "@umbraco-cms/mcp-server-sdk";
import type { getYourAPI } from "../../../api/generated/yourApi.js";
import { inputSchema, outputSchema } from "../../../api/generated/yourApi.zod.js";
type ApiClient = ReturnType<typeof getYourAPI>;
const tool: ToolDefinition<typeof inputSchema.shape, typeof outputSchema> = {
name: "action-entity",
description: "Clear description starting with action verb.",
inputSchema: inputSchema.shape,
outputSchema,
slices: ["read"],
annotations: { readOnlyHint: true },
handler: async (params) => {
return executeGetApiCall<ReturnType<ApiClient["method"]>, ApiClient>(
(client) => client.method(params, CAPTURE_RAW_HTTP_RESPONSE)
);
},
};
export default withStandardDecorators(tool);
Key rules:
*.zod.ts files for input/outputgetApiClient, extract ID from Location headerexecuteVoidApiCallexecuteGetApiCallAfter creating EACH tool file, run npm run compile. Fix any TypeScript errors in that file before creating the next one. Common issues:
*.zod.ts file for the exact export name)CAPTURE_RAW_HTTP_RESPONSE parameterimport { ToolCollectionExport } from "@umbraco-cms/mcp-server-sdk";
import getTool from "./get/get-entity.js";
import listTool from "./get/list-entities.js";
// ... other imports
const collection: ToolCollectionExport = {
metadata: {
name: "{collection-name}",
displayName: "{Display Name} Tools",
description: "Tools for managing {entity} resources",
},
tools: () => [getTool, listTool, /* ... */],
};
export default collection;
Add the collection import and registration to src/index.ts:
Add an import at the top with the other collection imports:
import {collection}Collection from "./tools/{collection}/index.js";
Add it to the collections array:
const collections = [existingCollection, {collection}Collection];
If configureApiClient still references the example/template API client, update it to use the correct generated client getter (e.g. getUmbracoEngageManagementAPI). Check the import from ./umbraco-api/api/generated/ and ensure it matches.
Do the same for src/collections.ts โ add the collection import and add it to the exported array.
npm run compile
Fix any TypeScript errors before proceeding. Common issues:
CAPTURE_RAW_HTTP_RESPONSE parametermcp-tool-reviewerAfter all tools are created for a collection, run the mcp-tool-reviewer agent on the collection. The agent will check each tool against the LLM-readiness checklist:
Flag any issues but continue to the next collection. The user can address review findings afterwards.
Repeat steps 3-4 for the next collection in .discover.json.
After all collections are built:
npm run compile # Full type check
Then run /count-mcp-tools to confirm all collections are covered. All collections from .discover.json should show tool count > 0. If any show "Not started", report which collections were missed.
Report what was generated:
Next step: Run /build-tools-tests to generate integration tests for the tool collections.