---
title: "Build Your Own MCP Server"
description: "Your knowledge becomes an API in thirty lines."
order: 27
duration: "15 min"
chapter: "07-the-always-on-system"
type: lesson
---

## Knowledge becomes an API

This is the next step in the distillation pipeline. Your knowledge started as a conversation (Chapters 01-02), became Project and CLAUDE.md context (Chapter 04), was formalized into a SKILL.md (Chapter 04), and now becomes a programmatic tool — an MCP server that any Claude surface can call.

The difference matters. A SKILL.md is a document Claude reads at session start. An MCP server is a live tool Claude calls on demand. The skill says "here are the rules." The MCP server says "ask me about any vendor and I will tell you the rules." One is passive context. The other is an active capability.

Building one is simpler than you might expect.

Here is a minimal working example — a server that exposes a single tool:

```typescript
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: "cornwall-rules", version: "1.0.0" });

server.registerTool(
  "get_vendor_rules",
  {
    description: "Get categorization rules for a specific vendor",
    inputSchema: { vendor: z.string().describe("Vendor name") },
  },
  async ({ vendor }) => {
    // In production, this would query a database or read a config file
    const rules: Record<string, string> = {
      "Chen's Produce": "Account 5100. Invoices Tue/Thu. Rounding OK.",
      "Chen's Bakery Supplies": "Account 5120. Invoices Monday AM.",
      "Pacific Foods": "Split by dept: produce→5100, dairy→5110, dry→5130, cleaning→6100. Flag items >$500.",
    };
    const rule = rules[vendor] ?? "No specific rules found. Use general categorization.";
    return { content: [{ type: "text", text: rule }] };
  }
);

await server.connect(new StdioServerTransport());
```

One `registerTool` call: a name, a description Claude uses to decide when to call it, a typed input schema, and the function that does the work. Connect a transport and you have a working MCP server.

<div class="exercise">
  <div class="callout-label">Try This</div>
  <p>Build a minimal MCP server. It can be as simple as the example above — a single tool that returns information specific to your work. Save it, register it with <code>claude mcp add cornwall-rules -- npx tsx server.ts</code>, restart Claude Code, and verify Claude can call it. (Better yet: ask Claude Code to write the server for you from your SKILL.md — this is exactly the kind of task it is good at.)</p>
  <p>The value of building your own is that your categorization rules (or whatever domain logic you encoded) become available as an MCP tool — accessible from the terminal, from your phone via Remote Control, through Dispatch, through scheduled tasks. One server, every surface.</p>
</div>

**Next:** [Channels](/mastering-claude/07-the-always-on-system/28-channels/)
