← Back to all entries
2025-12-12 💡 Tips 'n' Tricks

Building with MCP: A Practical Developer Guide

Building with MCP: A Practical Developer Guide — visual for 2025-12-12

💡 The Model Context Protocol — What It Is and When to Reach for It

With MCP now donated to the Linux Foundation and 10,000+ public servers in existence, it is increasingly the default choice for connecting Claude to external data sources and tools. But many developers still reach for bare API tool definitions when MCP would serve them better — or vice versa. The key distinction is scope: if you are building a one-off integration for a single application, raw tool definitions in your API call are simpler. If you are building a data connector that should be reusable across multiple models, applications, or teams, MCP is the right level of abstraction. MCP servers are independently deployable services that expose a standard interface; any MCP-compatible client can consume them without modification.

When MCP is the right choice

MCP vs. tool use — a quick rule of thumb

Use bare tool definitions for throw-away scripts, one-off prototypes, and applications where the toolset is tightly coupled to the specific application. Use MCP when the integration should outlive a single project or needs to be shared.

MCP tool use developer guide integration patterns retrospective

💡 Writing Your First MCP Server — Structure, Tools, and Resources

The MCP TypeScript and Python SDKs make standing up a basic server straightforward. An MCP server exposes three kinds of primitives: tools (functions the model can call), resources (data the model can read), and prompts (template prompt fragments the host can surface to users). Most integrations start with tools alone and add resources only when there is genuinely useful contextual data to expose. A minimal server needs a name, a version, and at least one tool or resource definition.

Anatomy of a minimal MCP tool

// TypeScript example
server.tool(
  "get_customer",
  "Fetch a customer record by ID",
  { customer_id: z.string().describe("The customer's UUID") },
  async ({ customer_id }) => {
    const record = await db.customers.findById(customer_id);
    return { content: [{ type: "text", text: JSON.stringify(record) }] };
  }
);
MCP server TypeScript tools retrospective