ᛗMUNINN
GuidesPricing
Sign inTry Muninn
Back to home

Guide

How to create a Claude MCP server

Starter code, plus what actually makes an MCP tool good

An MCP server is any process that speaks the Model Context Protocol. Claude — and every other MCP-compatible assistant — can call its tools. Anthropic maintains SDKs for TypeScript, Python, and other languages; the examples here use TypeScript.

Pick a transport

stdio is easiest for local, developer-focused servers. Claude Desktop launches your process, talks over stdin/stdout, kills it when Claude quits.

Streamable HTTP is what you want for a hosted server users can add remotely (OAuth, no local install). Use this if you're shipping the server to other people.

Minimal stdio server

Install the SDK:

npm install @modelcontextprotocol/sdk zod

server.ts:

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: "hello-mcp", version: "0.1.0" });

server.tool(
  "greet",
  "Greet a person by name.",
  { name: z.string().describe("The person's name") },
  async ({ name }) => ({
    content: [{ type: "text", text: `Hello, ${name}!` }],
  }),
);

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

Wire it into Claude Desktop's claude_desktop_config.json with "command": "node", "args": ["/path/to/server.js"] and restart Claude.

Design tools an LLM will actually use well

  • Name tools like functions. search_notes beats notesSearcher. The model reads names, so make them read like verbs.
  • Write descriptions for the model, not the human. Say when to use the tool and what shape the result has. The description is the prompt.
  • Small, sharp inputs. One argument that maps cleanly to the task beats a dozen options. If you need a lot of knobs, split into two tools.
  • Return text the model can quote. Structured JSON is fine, but include a short human-readable summary — the model will paste it into the answer.
  • Fail loudly. Return an explicit error message in the content, not a silent empty result.

Going remote

To host the server publicly, swap StdioServerTransport for the SDK's HTTP transport, put it behind OAuth, and expose the endpoint at a URL. Users then add it in Claude via Connectors.

Doing this well — token issuance, scopes, revocation, rate limits, per-user data isolation — is real work. If you're building a product around private-data tools, it's often faster to buy a hosted MCP layer than build one from scratch. Muninn is exactly that for notes: a hosted MCP server with OAuth, row-level security, and a full tool suite you can wire straight into Claude.

Related reading

  • What is an MCP server?
  • What is the Model Context Protocol?
  • How to add an MCP server to Claude

Try Muninn

One memory for every assistant

Keep notes once. Let Claude, ChatGPT, and any MCP client retrieve and update them when you ask.

Get started