Skip to main content
Watch: Claude Code Just Killed After Effects

Agents & MCP

MCP Server Authoring

Use when building a Model Context Protocol server that exposes tools and resources to Claude or another MCP client. Covers designing a tool schema the model will call correctly, returning errors the model can act on, and testing locally over stdio. Also use when a tool is registered but the model never calls it, or a client reports the server as failed. If you are writing an MCP server, use this skill.

mcptoolsserverprotocolagents

1 file

Description

Use when building a Model Context Protocol server that exposes tools and resources to Claude or another MCP client. Covers designing a tool schema the model will call correctly, returning errors the model can act on, and testing locally over stdio. Also use when a tool is registered but the model never calls it, or a client reports the server as failed. If you are writing an MCP server, use this skill.

Install
SKILL.md

name: mcp-server-authoring description: Use when building a Model Context Protocol server to expose tools and resources to Claude or other MCP clients. Covers tool schema design, error handling, and local testing over stdio.

MCP Server Authoring

When to trigger

Creating an MCP server, adding a tool to one, or debugging why a client will not call your tool or gets a bad result.

Design the tools first

An MCP tool is a function the model chooses to call. The name and description are prompt engineering, not documentation.

  • Name tools by the action: search_orders, create_invoice. Not orders or invoiceTool.
  • Write the description for the model. State when to use the tool and when not to. One or two sentences.
  • Make the input schema strict. Required fields required, enums for closed sets, short descriptions per field. A loose schema causes bad calls.

Minimal server (TypeScript, stdio)

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "orders", version: "1.0.0" });

server.tool(
  "search_orders",
  "Find orders by customer email. Use when the user asks about a specific customer's purchases.",
  { email: z.string().email(), limit: z.number().int().max(50).default(10) },
  async ({ email, limit }) => {
    const rows = await db.orders.findByEmail(email, limit);
    return { content: [{ type: "text", text: JSON.stringify(rows) }] };
  }
);

await server.connect(new StdioServerTransport());

Error handling

Return errors as tool results the model can read, not thrown exceptions that kill the transport. On failure return { content: [{ type: "text", text: "No customer found for that email." }], isError: true } so the model can recover.

Testing

  • Test over stdio with the MCP inspector before wiring it to a client.
  • Log to stderr, never stdout. On a stdio transport, stdout is the protocol channel and any stray write corrupts the JSON-RPC stream.

Pitfalls

  • A console.log anywhere in a stdio server breaks it silently. Route all logging to stderr.
  • Returning huge blobs (a full table dump) blows the context budget. Paginate and summarize in the tool.
  • Vague tool descriptions are the top cause of a model never calling your tool. Rewrite the description before adding retries.
AI Development Stack

Get Smarter About AI Dev

New tutorials, open-source projects, and deep dives on coding agents - delivered weekly.

One email per weekReal code, not theoryFree forever