MCP Server Development
Build Model Context Protocol servers that expose tools, resources, and prompts to LLM applications.
Satellite files (loaded on-demand):
- references/resources.md -- full manifest specification, bundle structures, advanced examples
- ../skill-crafting/references/artifact-naming.md -- naming conventions for all artifact types
For MCP connector API features (calling MCP servers from the Messages API), consult the claude-ecosystem skill.
Table of Contents
- Language Contexts
- Core Primitives
- Transports
- Logging
- Client Integration
- Error Handling
- Testing
- Bundles (.mcpb)
- Common Pitfalls
- Resources
Language Contexts
| Language | Context File | Related Skills |
|---|---|---|
| Python | contexts/python.md | python-development, python-prj-mgmt |
| TypeScript | contexts/typescript.md | typescript-development, node-prj-mgmt |
When working in a specific language, load the corresponding context for SDK setup, code examples, testing, and deployment patterns.
Core Primitives
Tools -- Executable Functions
Tools perform computation and side effects. The LLM invokes them. Define parameters with types, defaults, and descriptions so the LLM understands how to call the tool.
Tool "search_database":
Parameters:
query: string (required) -- search query
limit: integer (default: 10) -- max results
Returns: array of objects
Tool "long_task":
Parameters:
name: string (required) -- task identifier
steps: integer (default: 5) -- number of steps
Returns: string (completion message)
Behavior: reports progress after each step
Use tools for: computation, side effects, actions on external systems, anything that changes state.
Tool design quality — naming a tool well, writing its description so a model comprehends it on every call, deciding fat-vs-thin decomposition, applying progressive disclosure when the surface exceeds ~20 tools, and designing errors the model can self-recover from — is a design discipline distinct from the implementation mechanics on this page. For that craft, see the agentic-interface-design skill (the tool name and description ARE the interface; the description is the primary lever for correcting model behavior). This page covers how to build an MCP server; agentic-interface-design covers how good the tool design is.
Resources -- Data Exposure
Resources provide data to LLMs (like GET endpoints). No significant side effects. Identified by URI templates.
Resource "config://settings":
Returns: string (JSON)
Resource "file://docs/{path}":
Parameters:
path: string (URI template variable)
Returns: string (file content)
Use resources for: read-only data, configuration, file access, database lookups without mutations.
Prompts -- Reusable Templates
Prompts define structured interaction patterns for LLMs. They accept parameters and return formatted text.
Prompt "analyze_data":
Parameters:
dataset: string (required)
focus: string (default: "trends")
Returns: string (prompt text)
Use prompts for: standardized analysis requests, review templates, multi-step workflows.
For prompt-body authoring patterns (few-shot examples, chain-of-thought, structured-output instructions, injection hardening) used inside MCP prompt templates, see the llm-prompt-engineering skill.
Do not mix primitives. Tools execute logic (side effects OK). Resources expose data (no side effects). Prompts template interactions. If a function reads data and mutates state, make it a tool.
See language context for SDK-specific decorator syntax and code examples.
Transports
| Transport | Use Case |
|---|---|
| stdio | Local development, Claude Desktop |
| Streamable HTTP | Production, remote clients |
SSE is deprecated. Use streamable HTTP for all new HTTP-based servers.
See language context for transport configuration code.
Logging
Universal rule: never print to stdout in stdio servers -- it corrupts JSON-RPC messages. Direct all logging output to stderr.
For HTTP servers, standard output logging is acceptable.
See language context for logging setup code.
Client Integration
Claude Desktop
Configure servers in the Claude Desktop config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"my-server": {
"command": "RUNTIME_COMMAND",
"args": ["RUNTIME_ARGS"]
}
}
}
See your language context for the command and args values appropriate to your runtime.
Claude Code
# HTTP server (language-agnostic)
claude mcp add --transport http my-server http://localhost:8000/mcp
# Scope: user (all projects), local (default, this project), project (.mcp.json, shareable)
claude mcp add my-server --scope project -- RUNTIME_COMMAND RUNTIME_ARGS
See your language context for the stdio launch command.
Error Handling
- Validate inputs early -- check types, ranges, required fields before processing
- Catch specific exceptions with targeted responses, fall back to generic handlers
- Return
isError: trueinCallToolResultfor tool-level failures - Log full error details to stderr; sanitize responses to avoid leaking internals
- Provide context-aware messages that help the LLM recover ("column 'xyz' not found -- did you mean 'xy'?")
Testing
MCP Inspector
The MCP Inspector provides interactive testing for any MCP server, regardless of language:
npx -y @modelcontextprotocol/inspector # Standalone Inspector
Connect to a running server or launch one directly. The Inspector lets you invoke tools, read resources, and test prompts through a web UI at localhost:6274.
See language context for in-memory / programmatic testing patterns.
Bundles (.mcpb) -- Packaging for Distribution
MCP Bundles are ZIP archives (.mcpb extension) containing a server and a manifest.json. They enable one-click installation in Claude Desktop (double-click, drag-and-drop, or Developer menu). Formerly called DXT (Desktop Extensions).
Repository: modelcontextprotocol/mcpb
Manifest Overview
Every bundle requires a manifest.json with at minimum:
Manifest fields (required):
manifest_version: string -- currently "0.4"
name: string -- unique identifier (lowercase, hyphens)
version: string -- semver
description: string -- what the server does
server:
type: string -- one of: node, uv, python, binary
entry_point: string -- path to server entry file
Manifest fields (optional):
author: { name, url, email }
user_config: object -- declares user-configurable fields
mcp_config: object -- environment variables for the server
Server Types
| Type | When to Use |
|---|---|
node |
Recommended -- ships with Claude Desktop, zero install friction |
uv |
Python servers -- host manages Python/deps via uv (experimental) |
python |
Python with pre-bundled deps -- limited portability for compiled pkgs |
binary |
Pre-compiled executables |
User Configuration
Declare config fields and Claude Desktop auto-generates a settings UI:
{
"user_config": {
"api_key": {
"type": "string",
"title": "API Key",
"required": true,
"sensitive": true
}
}
}
Reference via ${user_config.api_key} in mcp_config.env.
CLI
npm install -g @anthropic-ai/mcpb
mcpb init # Generate manifest.json interactively
mcpb pack # Package into .mcpb file
mcpb pack examples/hello-world-uv # Pack a specific directory
See references/resources.md for the full manifest specification, bundle directory structures, and advanced examples. See language context for language-specific bundle patterns.
Common Pitfalls
- Printing to stdout in stdio servers -- corrupts JSON-RPC. Log to stderr
- Using SSE transport -- deprecated. Use streamable HTTP
- Missing type annotations -- LLMs cannot understand tool parameters without annotations
- Mixing primitives -- tools execute logic (side effects OK), resources expose data (no side effects)
- Overly broad permissions -- start read-only, whitelist operations, restrict filesystem paths
See language context for language-specific pitfalls.
Resources
- MCP Specification -- Official protocol spec
- MCP Inspector -- Interactive testing tool
- Security Best Practices -- Official security guidance
- See language context for SDK-specific resources
- See references/resources.md for advanced patterns, security deep-dives, and community guides
Source: francisco-perez-sorrosal/praxion — distributed by TomeVault.