SuperAPI AI Directory

mcp-patterns

Agents & models

View repository

Updated 10-16 07:16

About this skill

MCP Development Patterns

This skill loads comprehensive patterns for building MCP tools using the @umbraco-cms/mcp-server-sdk.

When to Use

Use this skill when:

  • Starting to create new MCP tools
  • Needing a reference for tool patterns
  • Understanding how to use the toolkit helpers
  • Setting up a new MCP server project

Core Architecture

Tool Definition Pattern

All tools follow this structure:

import {
  withStandardDecorators,
  executeGetApiCall,
  executeVoidApiCall,
  createToolResult,
  CAPTURE_RAW_HTTP_RESPONSE,
  ToolDefinition,
} from "@umbraco-cms/mcp-server-sdk";

const MyTool = {
  name: "tool-name",
  description: "What the tool does",
  inputSchema: zodSchema.shape,
  outputSchema: responseSchema,  // For GET operations
  slices: ["read"],              // Categorization
  annotations: {
    readOnlyHint: true,          // For GET
    destructiveHint: true,       // For DELETE
    idempotentHint: true,        // For PUT
  },
  handler: async (params) => {
    // Implementation
  },
} satisfies ToolDefinition<...>;

export default withStandardDecorators(MyTool);

API Client Configuration

Configure once at server startup:

import { configureApiClient } from "@umbraco-cms/mcp-server-sdk";
import { getMyAPI } from "./api/generated/myApi.js";

configureApiClient(() => getMyAPI());

Helper Functions

executeGetApiCall

For GET operations that return data:

return executeGetApiCall<ReturnType<Client["method"]>, Client>(
  (client) => client.method(params, CAPTURE_RAW_HTTP_RESPONSE)
);

executeVoidApiCall

For DELETE/PUT operations that return void:

return executeVoidApiCall<Client>(
  (client) => client.deleteItem(id, CAPTURE_RAW_HTTP_RESPONSE)
);

createToolResult / createToolResultError

For custom responses (typically CREATE operations):

if (response.status === 201) {
  return createToolResult({ success: true, id: extractedId });
} else {
  return createToolResultError(response.data);
}

Slices (Tool Categorization)

Tools are categorized by operation type:

  • read - GET operations
  • create - POST create operations
  • update - PUT operations
  • delete - DELETE operations
  • search - Search/filter operations

Annotations Reference

Operation readOnlyHint destructiveHint idempotentHint
GET ✅ ❌ ❌
DELETE ❌ ✅ ❌
POST ❌ ❌ ❌
PUT ❌ ❌ ✅

Important: DELETE is NOT idempotent (2nd call returns 404).

Schema Flattening for Nested Reference Objects

Umbraco APIs wrap references to other entities in a nested object — most commonly parent: { id } or parent: { path }. Never expose that shape to the LLM: accept a flat scalar (parentId, path) and rebuild the nested object inside the handler. See references/schema-flattening.md for the full pattern, the when-to-apply matrix, and the rules.

Project Structure

src/
├── api/
│   ├── client.ts           # API client with mock support
│   ├── openapi.yaml        # OpenAPI spec
│   └── generated/          # Orval-generated client + Zod schemas
├── tools/
│   └── {entity}/
│       ├── get/
│       ├── post/
│       ├── put/
│       ├── delete/
│       └── index.ts        # Collection export
└── index.ts                # MCP server entry

Orval Code Generation

Generate client and Zod schemas from OpenAPI:

npm run generate

Configuration in orval.config.ts:

  • Generates TypeScript client (configurable via client option)
  • Generates Zod schemas for validation
  • Uses custom mutator for authentication

Best Practices

  1. Use Zod schemas from generated code for type safety
  2. Hide UUID generation - create internally, don't expect LLM to provide
  3. Clear descriptions - tools should be self-documenting
  4. Consistent naming - follow {action}-{entity} pattern
  5. Error handling - withStandardDecorators handles errors automatically
  6. Flatten nested reference objects - accept parentId / path, rebuild parent: { id } / parent: { path } in the handler (see Schema Flattening above, or references/schema-flattening.md for the full pattern)