# MCP Builder

> Build a high-quality MCP server that exposes a service or API to an LLM through well-designed tools. Use when asked to create, scaffold, or add an MCP server, wrap an API as MCP tools, or expose a service to Claude/agents. Writes files, so it runs only when invoked explicitly.

- Skill: `thedecipherist/mcp-builder` (Agent Skill)
- Install (CLI): `npx skillmds@latest add thedecipherist/mcp-builder`
- Raw SKILL.md: https://api.skillmd.com/api/skills/thedecipherist/mcp-builder/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: TheDecipherist (https://skillmd.com/u/thedecipherist)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/thedecipherist/mcp-builder

---


# Build an MCP Server

An MCP server is judged by one thing: whether an LLM can use its tools to finish real tasks. Tool count, endpoint coverage, and cleverness are means, not the goal. Build for the agent that will call it.

## Default stack

- **TypeScript, on the MCP SDK.** Strong typing and good model familiarity. Drop to Python (FastMCP) only when the service it wraps is Python-native.
- **Transport: streamable HTTP with stateless JSON for remote servers; stdio for local.** Stateless scales and debugs far more easily than session streaming.
- **Resolve the SDK version at build time**, don't hardcode from memory. The current SDK README is the source of truth.

## The four phases

**1. Understand the target.** Read the service's API or schema first. Identify the handful of tasks a user actually wants done through it, not every endpoint. A wrapper that mirrors 60 REST routes one-to-one is worse than 8 tools shaped around real workflows.

**2. Design the tools.** This is where quality is won or lost.

- **Discoverable names**: `verb_noun`, scoped by service, for example `github_create_issue`, `orders_find_by_customer`. The name should tell the model when to reach for it.
- **Descriptions written for the model**, stating what the tool does and when to use it, not just what it returns.
- **Explicit input and output schemas.** Constrain inputs; return structured, parseable output, not prose the model has to scrape.
- **Annotations**: mark each tool `readOnlyHint`, `destructiveHint`, or `idempotentHint` so the client can reason about safety.
- **Actionable errors.** "Invalid date" is useless; "expected ISO 8601, got 03/04/2026, did you mean 2026-03-04" lets the model self-correct.
- **Balance coverage against workflow tools.** Comprehensive low-level tools give the agent room to compose; a few high-level workflow tools cut steps for the common path. Most good servers ship both.

**3. Implement.** Shared infrastructure first (client, auth, pagination, error handling), then the tools on top. If the server touches a database, it follows the same kit rules as everything else: one shared client, data access through the adapter, StrictDB if installed otherwise the native driver, never Mongoose.

**4. Test with evaluations.** Write 10 realistic, multi-step questions a user would ask, then verify an LLM can answer each using only the tools. Solve each yourself first so you know the right answer. Failing evals point at a missing tool, a vague description, or output the model can't parse, fix those, not the eval.

## Project shape

    src/
      server.ts        transport + registration, thin
      client.ts        the upstream API/service client (the one place it's touched)
      tools/           one file per tool or tight tool group
      schemas/         input/output schemas (zod)
    evals/
      evals.json       the 10 questions and verified answers

Keep `server.ts` thin, the same discipline as `api-conventions`: it wires transport and registers tools, nothing more. Tool logic lives in `tools/`, upstream calls in `client.ts`. No file over 300 lines.

## What to avoid

- Dumping every endpoint as a tool with no workflow shaping.
- Tool names only the author understands.
- Returning raw upstream JSON the model has to guess the shape of.
- Skipping evals, an MCP server you haven't watched an LLM drive is untested.

