Skip to content
Agentic AI
Agentic AI6 min read0 views

Build a Claude MCP Server and Skill: Full Walkthrough

Step-by-step: scaffold an MCP server, pair it with an Agent Skill, and wire both into Claude Code — with real TypeScript code and testing tips.

Architecture diagrams are useful right up until you have to actually ship something. This post is the opposite of a diagram: it is the sequence of commands and files an engineer follows to take Claude from "can talk about my system" to "can act on my system." We will build a small but real capability — a server that exposes an internal product inventory — pair it with a Skill that teaches Claude how to use it, and wire the whole thing into Claude Code. Every step is something you can type today.

The example is deliberately humble so the mechanics stay visible. Once you have done it once, the same skeleton scales to payments, CRMs, internal APIs, or anything else behind a function.

Step 1: Scaffold the MCP server

Start a fresh project and install the MCP SDK. We will use TypeScript over stdio, which is the simplest transport for a tool Claude Code launches locally.

npm init -y
npm install @modelcontextprotocol/sdk zod

Create server.ts. The skeleton registers the server, declares one tool with a typed input schema, and starts listening on stdio. The schema is not decoration — it is the contract Claude reads to know what arguments the tool accepts.

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: "inventory", version: "1.0.0" });

server.tool(
  "get_stock",
  "Return current stock count for a product SKU.",
  { sku: z.string().describe("Product SKU, e.g. WIDGET-001") },
  async ({ sku }) => {
    const count = await lookupStock(sku); // your DB call
    return { content: [{ type: "text", text: JSON.stringify({ sku, count }) }] };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

That is a complete, working server. The describe calls matter more than they look: they become the natural-language hints Claude uses to fill arguments correctly.

Hear it before you finish reading

Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.

Try Live Demo →

Step 2: Register the server with Claude Code

Claude Code reads MCP server definitions from its config. Add an entry telling it how to launch your process.

claude mcp add inventory -- node /abs/path/to/server.js

On the next session, Claude Code starts the process, performs the capability handshake, and the get_stock tool becomes available. You can confirm by asking Claude to list its tools, or simply asking "what's the stock for WIDGET-001" and watching it call the tool.

flowchart TD
  A["Scaffold MCP server"] --> B["Define typed tool + schema"]
  B --> C["Register server in Claude Code"]
  C --> D["Write Skill folder & SKILL.md"]
  D --> E["Skill names the tool & the procedure"]
  E --> F["Ask Claude a real task"]
  F --> G{"Tool called correctly?"}
  G -->|No| D
  G -->|Yes| H["Ship & iterate on guidance"]

Step 3: Write the Skill that teaches usage

The server gives Claude a verb. The Skill gives it judgment. Create a folder with a SKILL.md whose front matter carries a sharp name and description — that pair is the trigger signal Claude matches against incoming tasks.

---
name: inventory-ops
description: Check and reason about product stock levels using the inventory tools. Use for restock decisions and availability questions.
---

When asked about availability, call get_stock with the exact SKU.
If stock is below 10, flag it as low and suggest a reorder quantity
of 50 unless the user specifies otherwise. Never guess a count —
always call the tool. If get_stock returns an error, report the SKU
and ask the user to confirm it.

Notice what the Skill does that the server cannot: it encodes the reorder threshold, the default quantity, and the hard rule never to fabricate a number. That business logic does not belong in the server, which should stay a thin, reusable capability. Drop this folder where Claude Code discovers Skills, and on the next session the lightweight description is in context, ready to trigger.

Step 4: Test the round trip

Now run a real task: "We're planning a promo on WIDGET-001 and WIDGET-002 — are we covered?" Watch the transcript. You should see the Skill trigger, two get_stock calls with the correct SKUs, and a recommendation that respects your threshold. If Claude answers without calling the tool, your Skill description probably didn't match — tighten it. If it calls the tool but passes a malformed SKU, your describe hint needs a clearer example.

This tight feedback loop is the actual work of building agents. The code is small; the iteration is on the words. Test with adversarial inputs too: a SKU that doesn't exist, an empty string, a wildly out-of-range request. Each failure tells you whether the fix belongs in the server (validation) or the Skill (guidance).

Still reading? Stop comparing — try CallSphere live.

CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.

Step 5: Harden before you trust it

Before letting an agent touch anything that matters, add three things. First, input validation in the server itself — never trust that the model passed a clean SKU; reject malformed input with a clear error. Second, a read-only default: if a tool has a destructive variant, gate it behind explicit user confirmation in the Skill. Third, structured errors: return { error: "SKU_NOT_FOUND", sku } rather than throwing a raw exception, so the Skill's error-handling instructions can act on a stable code.

With those in place you have a real, safe capability. The same five steps — scaffold, register, write the Skill, test the round trip, harden — repeat for every system you connect. The first one takes an afternoon; the tenth takes twenty minutes.

Frequently asked questions

Can I build the server in Python instead of TypeScript?

Yes. The MCP SDK is available for Python with the same concepts: a server object, typed tools, and a transport. The choice is purely about which ecosystem your backend already lives in; Claude doesn't care which language the server is written in.

Do I have to write a Skill, or will the tool description suffice?

For a single trivial tool, a good description may be enough. The moment you have business rules — thresholds, defaults, ordering of calls, safety gates — put them in a Skill. That keeps the server reusable and the judgment versioned separately from the capability.

How do I debug a server that won't connect?

Run the server process directly from your shell first; stdio servers will print startup errors there. Confirm the absolute path in your Claude Code config is correct, and check that the process stays alive rather than exiting immediately. Most connection failures are a bad path or a crash on startup, not a protocol issue.

Bringing agentic AI to your phone lines

CallSphere applies this exact build pattern — typed capabilities plus skill-style guidance — to voice and chat, so AI agents pick up every call, fetch data through tools mid-conversation, and book work 24/7. See it running at callsphere.ai.


Source & attribution: This is an independent, original explainer inspired by Anthropic's coverage on the Claude blog. Claude, Claude Code, Claude Cowork, Claude Opus, and the Model Context Protocol are products and trademarks of Anthropic. CallSphere is not affiliated with or endorsed by Anthropic.

Share

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.