From umbraco-mcp-skills
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'.
npx claudepluginhub umbraco/umbraco-mcp-base --plugin umbraco-mcp-skillsThis skill uses the workspace's default tool permissions.
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.
Applies Acme Corporation brand guidelines including colors, fonts, layouts, and messaging to generated PowerPoint, Excel, and PDF documents.
Builds DCF models with sensitivity analysis, Monte Carlo simulations, and scenario planning for investment valuation and risk assessment.
Calculates profitability (ROE, margins), liquidity (current ratio), leverage, efficiency, and valuation (P/E, EV/EBITDA) ratios from financial statements in CSV, JSON, text, or Excel for investment analysis.
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.