Walk through building a minimal MCP server step by step.

6 minbeginnermcpsdktutorialgetting-started

Quick Answer

1) Install the SDK (pip install mcp for Python, npm install @modelcontextprotocol/sdk for TypeScript). 2) Create a server instance and give it a name. 3) Register at least one tool (or resource/prompt) with a clear description and typed parameters — the SDK derives the JSON Schema automatically from type annotations. 4) Implement the handler function's actual logic. 5) Choose a transport (stdio for local use) and run the server. 6) Test it, ideally with the MCP Inspector before wiring it into a real host, to confirm tools/list and tools/call behave as expected. 7) Point a host (like Claude Desktop) at the server via its config file so it launches your server as a subprocess and connects automatically.

Detailed Answer

Here's the shortest realistic path from an empty directory to a working MCP server a host can actually talk to.

1. Install and scaffold

pip install mcp
# server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("notes-server")

2. Register a tool with real logic

import json
from pathlib import Path

NOTES_FILE = Path("notes.json")

@mcp.tool()
def add_note(title: str, body: str) -> str:
    """Add a new note with a title and body text."""
    notes = json.loads(NOTES_FILE.read_text()) if NOTES_FILE.exists() else []
    notes.append({"title": title, "body": body})
    NOTES_FILE.write_text(json.dumps(notes))
    return f"Saved note '{title}'"

@mcp.tool()
def list_notes() -> str:
    """List all saved note titles."""
    if not NOTES_FILE.exists():
        return "No notes yet."
    notes = json.loads(NOTES_FILE.read_text())
    return "\n".join(n["title"] for n in notes)

3. Run it over stdio

if __name__ == "__main__":
    mcp.run(transport="stdio")
python server.py   # runs and waits for JSON-RPC on stdin

4. Test before connecting a real host

npx @modelcontextprotocol/inspector python server.py

The Inspector launches your server, performs the handshake, and gives you a UI to call add_note/list_notes directly — confirming the schema and handler logic work before any host is involved.

5. Wire it into a host

Add an entry to the host's MCP config (for Claude Desktop, claude_desktop_config.json) pointing at the command to launch your server, restart the host, and the tools become available in conversation.

What to check once it's "working"

Confirm error cases too, not just the happy path. What happens if add_note is called with a missing title? Does the schema reject it before your handler even runs, or does your handler crash? A minimal server is only genuinely done once bad input is handled gracefully, not just the expected case.

Related Resources