๐Ÿ”Œ

MCP (Model Context Protocol)

Model Context Protocol reference: architecture, primitives, server config, building servers, tools/resources/prompts, transports, auth, and debugging.

Protocol Overview & Architecture

What MCP is, how clients and servers relate, and the two transport types.

textยทArchitecture overview
MCP โ€” Model Context Protocol
  Open standard for connecting AI applications to external tools and data.
  Think of it as "USB-C for AI" โ€” one interface, many peripherals.

ROLES
  MCP Host    AI application that embeds an MCP client
              (Claude Desktop, Claude Code, VS Code, Cursor โ€ฆ)
  MCP Client  Component inside the host managing one server connection
  MCP Server  Process exposing tools / resources / prompts via MCP

  Host โ†โ”€โ”€โ”€โ”€ MCP Client โ”€โ”€โ”€โ”€โ†’ MCP Server (filesystem)
         โ†โ”€โ”€โ”€โ”€ MCP Client โ”€โ”€โ”€โ”€โ†’ MCP Server (GitHub)
         โ†โ”€โ”€โ”€โ”€ MCP Client โ”€โ”€โ”€โ”€โ†’ MCP Server (Postgres)

  One host can connect to many servers simultaneously.
  Each connection is a dedicated client instance.

WIRE PROTOCOL
  JSON-RPC 2.0 over the chosen transport.
  Messages: Request โ†’ Response  |  Notification (fire-and-forget)

TRANSPORT OPTIONS
  stdio           stdin / stdout โ€” local only, zero network overhead
  Streamable HTTP POST for clientโ†’server, optional SSE for streaming
                  supports standard HTTP auth, multi-client, remote

MCP Primitives

The five building blocks servers and clients expose: Tools, Resources, Prompts, Sampling, and Roots.

textยทServer-side primitives
PRIMITIVE   WHO DECIDES TO USE IT   WHAT IT IS
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Tools       The model (AI)          Executable functions the LLM can call
                                    e.g. searchFlights(), queryDatabase()
                                    Protocol: tools/list  tools/call

Resources   The application         Read-only data sources for context
                                    e.g. file contents, DB schemas, API docs
                                    Direct (fixed URI) or Template (parameterised)
                                    Protocol: resources/list  resources/read
                                              resources/templates/list
                                              resources/subscribe

Prompts     The user                Reusable instruction templates with parameters
                                    e.g. "Plan a vacation" with destination/days args
                                    Protocol: prompts/list  prompts/get

CLIENT-SIDE PRIMITIVES (what servers can request from the host)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Sampling    Server asks client to run an LLM completion
            sampling/complete โ€” lets servers leverage the host model

Roots       Client tells server which filesystem roots it may access
            Servers should respect roots for path-based operations

Server Configuration

JSON config format for Claude Desktop, Claude Code, and other MCP clients.

textยทConfig file locations
CLIENT              CONFIG FILE LOCATION
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Claude Desktop      ~/Library/Application Support/Claude/claude_desktop_config.json  (macOS)
                    %APPDATA%\Claude\claude_desktop_config.json                      (Windows)
Claude Code         ~/.claude/settings.json  (mcpServers key)
                    or  .claude/settings.json  (project-level)
                    or  --mcp-config <path>    (CLI flag per session)
VS Code / Cursor    .vscode/mcp.json  or workspace settings
jsonยทFull config example
{
  "mcpServers": {

    // Local stdio server โ€” runs a child process
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/docs"],
      "env": {}
    },

    // Python server via uv (recommended for Python projects)
    "weather": {
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/weather-server", "run", "weather.py"],
      "env": {
        "WEATHER_API_KEY": "sk_live_abc123"
      }
    },

    // Remote HTTP/SSE server
    "my-api": {
      "type": "sse",
      "url": "https://mcp.example.com/sse",
      "headers": {
        "Authorization": "Bearer ${MY_TOKEN}"
      }
    },

    // Streamable HTTP (newer standard)
    "remote-tools": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "headers": {
        "X-API-Key": "${REMOTE_API_KEY}"
      }
    }
  }
}

// IMPORTANT: Always use absolute paths โ€” relative paths often fail
// because the client's working directory is undefined at launch.

Building an MCP Server โ€” TypeScript

Creating an MCP server with the official TypeScript SDK.

bashยทSetup
# Initialise project
mkdir my-mcp-server && cd my-mcp-server
npm init -y

# Install SDK
npm install @modelcontextprotocol/sdk zod

# TypeScript tooling
npm install -D typescript @types/node tsx

# package.json โ€” add type & bin
# "type": "module"
# "bin": { "my-server": "dist/index.js" }
typescriptยทMinimal server (stdio)
// src/index.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: "my-server",
  version: "1.0.0",
});

// Register a tool
server.tool(
  "add",
  "Add two numbers",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }],
  })
);

// Register a resource
server.resource(
  "config",
  "config://app",
  async (uri) => ({
    contents: [{ uri: uri.href, text: "port=3000
debug=false" }],
  })
);

// Register a prompt
server.prompt(
  "review-code",
  { code: z.string() },
  ({ code }) => ({
    messages: [{
      role: "user",
      content: { type: "text", text: `Review this code:\n${code}` },
    }],
  })
);

// Start
const transport = new StdioServerTransport();
await server.connect(transport);
// NEVER log to stdout in stdio servers โ€” it corrupts JSON-RPC
// Use console.error() or process.stderr.write() instead
typescriptยทHTTP server (multi-client)
// src/http-server.ts
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";

const app = express();
app.use(express.json());

const server = new McpServer({ name: "remote-server", version: "1.0.0" });
// ... register tools/resources/prompts ...

const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);

app.post("/mcp", (req, res) => transport.handleRequest(req, res));
app.get("/mcp", (req, res) => transport.handleRequest(req, res));  // SSE
app.delete("/mcp", (req, res) => transport.handleRequest(req, res));

app.listen(3000);

Building an MCP Server โ€” Python

Creating an MCP server with the official Python SDK using FastMCP.

bashยทSetup
# Using uv (recommended)
uv init my-mcp-server
cd my-mcp-server
uv add "mcp[cli]"

# Or pip
pip install "mcp[cli]"

# Scaffold a new server interactively
mcp new my-server

# Run during development
mcp dev server.py

# Install into Claude Desktop
mcp install server.py
pythonยทFastMCP server (decorator style)
# server.py
from mcp.server.fastmcp import FastMCP
from mcp.types import Resource, TextContent

mcp = FastMCP("weather")

# โ”€โ”€ TOOL โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@mcp.tool()
async def get_forecast(city: str, days: int = 3) -> str:
    """Get a weather forecast for a city."""
    # implementation โ€ฆ
    return f"Forecast for {city}: sunny for {days} days"

# โ”€โ”€ RESOURCE โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@mcp.resource("config://settings")
def get_settings() -> str:
    """Application settings."""
    return "theme=dark\nlocale=en"

# Dynamic resource with URI template
@mcp.resource("weather://{city}/current")
def current_weather(city: str) -> str:
    """Current conditions for a city."""
    return f"Current weather in {city}: 22ยฐC, partly cloudy"

# โ”€โ”€ PROMPT โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@mcp.prompt()
def weather_report(city: str) -> str:
    """Generate a weather briefing prompt."""
    return f"Write a friendly weather report for {city}."

# โ”€โ”€ RUN โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
if __name__ == "__main__":
    mcp.run()          # defaults to stdio
    # mcp.run(transport="streamable-http")  # for remote

Tool Definition Deep-Dive

How to define tools with JSON Schema input validation and proper return types.

typescriptยทTool with full JSON Schema
// Using low-level server API for full schema control
import { Server } from "@modelcontextprotocol/sdk/server/index.js";

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [{
    name: "search_flights",
    title: "Flight Search",          // human-readable display name
    description: "Search available flights between two cities.",
    inputSchema: {
      type: "object",
      properties: {
        origin:      { type: "string",  description: "IATA departure code, e.g. JFK" },
        destination: { type: "string",  description: "IATA arrival code, e.g. LHR" },
        date:        { type: "string",  format: "date", description: "ISO 8601 date" },
        class:       { type: "string",  enum: ["economy","business","first"],
                       default: "economy" },
        max_price:   { type: "number",  description: "Max price in USD" },
      },
      required: ["origin", "destination", "date"],
    },
  }],
}));

server.setRequestHandler(CallToolRequestSchema, async (req) => {
  if (req.params.name === "search_flights") {
    const { origin, destination, date, class: cls = "economy" } = req.params.arguments;
    const results = await flightApi.search(origin, destination, date, cls);
    return {
      content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
      isError: false,
    };
  }
});

// RETURN TYPES
// content is an array of:
//   { type: "text",  text: string }
//   { type: "image", data: base64, mimeType: "image/png" }
//   { type: "resource", resource: { uri, text | blob } }

Resources & Prompts

Defining static and dynamic resources, and reusable prompt templates.

typescriptยทResources โ€” static & template
// Static resource (fixed URI)
server.resource(
  "app-config",
  "config://app",
  { mimeType: "application/json", description: "App configuration" },
  async () => ({
    contents: [{
      uri: "config://app",
      mimeType: "application/json",
      text: JSON.stringify({ port: 3000, debug: false }),
    }],
  })
);

// Dynamic resource (URI template)
server.resource(
  "user-profile",
  new ResourceTemplate("users://{userId}/profile", { list: undefined }),
  { mimeType: "application/json", description: "User profile by ID" },
  async (uri, { userId }) => ({
    contents: [{
      uri: uri.href,
      mimeType: "application/json",
      text: JSON.stringify(await db.getUser(userId)),
    }],
  })
);

// PROTOCOL METHODS
// resources/list                โ†’ list direct resources
// resources/templates/list      โ†’ list URI templates
// resources/read  { uri }       โ†’ fetch contents
// resources/subscribe { uri }   โ†’ stream updates
// notifications/resources/updated  โ†’ server-push on change
typescriptยทPrompts โ€” parameterised templates
server.prompt(
  "code-review",
  "Review code for issues and improvements",
  {
    code:     z.string().describe("Source code to review"),
    language: z.string().optional().describe("Programming language"),
    focus:    z.enum(["security","performance","readability"]).optional(),
  },
  ({ code, language = "unknown", focus = "all" }) => ({
    messages: [
      {
        role: "user",
        content: {
          type: "text",
          text: `Review the following ${language} code focusing on ${focus}:\n\n${code}`,
        },
      },
    ],
  })
);

// PROTOCOL METHODS
// prompts/list              โ†’ discover available prompts
// prompts/get { name, args} โ†’ get rendered prompt messages

Transport Types

stdio vs Streamable HTTP โ€” when to use each and how they work.

textยทTransport comparison
FEATURE             STDIO                     STREAMABLE HTTP
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Where               Local machine only        Local or remote
Clients             Single (1:1)              Multiple (1:N)
Network overhead    None                      Minimal (HTTP/2)
Auth                Env vars / process perms  Bearer token, API key, headers
Setup complexity    Low                       Medium
Streaming           N/A (synchronous)         Server-Sent Events (SSE)
Session state       Process lifetime          Mcp-Session-Id header
Use for             Local tools (fs, git, db) Cloud services, shared servers
Logging             stderr ONLY               stdout or SSE notifications

STDIO GOLDEN RULE
  Never write to stdout inside a stdio server.
  stdout is the JSON-RPC channel โ€” any stray bytes corrupt the protocol.
  Use: console.error(), process.stderr.write(), logging to a file.

HTTP SESSION LIFECYCLE
  1. Client POST /mcp  with Initialize request
  2. Server returns Mcp-Session-Id header
  3. Client includes Mcp-Session-Id on all subsequent requests
  4. Client DELETE /mcp to terminate session
typescriptยทChoosing & starting a transport
// โ”€โ”€ STDIO โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

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


// โ”€โ”€ STREAMABLE HTTP โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { randomUUID } from "crypto";

const transport = new StreamableHTTPServerTransport({
  sessionIdGenerator: () => randomUUID(),    // stateful sessions
  // sessionIdGenerator: undefined,          // stateless (simpler)
  onsessioninitialized: (sessionId) => {
    sessions.set(sessionId, transport);
  },
});
await server.connect(transport);

app.post("/mcp",   (req, res) => transport.handleRequest(req, res, req.body));
app.get("/mcp",    (req, res) => transport.handleRequest(req, res));   // SSE
app.delete("/mcp", (req, res) => transport.handleRequest(req, res));


// โ”€โ”€ PYTHON FastMCP โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
mcp.run()                               # stdio (default)
mcp.run(transport="streamable-http")    # HTTP

Authentication & Security

How auth works with MCP servers and key security considerations.

textยทAuth patterns
STDIO SERVERS
  Auth is implicit โ€” the server inherits the process owner's permissions.
  API keys go in env vars in the config file:
    "env": { "GITHUB_TOKEN": "ghp_abc123" }
  Access them in the server: process.env.GITHUB_TOKEN

HTTP SERVERS โ€” OPTIONS
  API Key (simplest)
    Client sends header:  Authorization: Bearer <token>
    Server validates against a known key or secret.

  OAuth 2.0 (third-party APIs)
    MCP spec uses OAuth 2.0 with dynamic client registration.
    Flow: client registers โ†’ user consents โ†’ server gets token.
    Server validates the token was issued TO IT, not just forwarded.

  mTLS (high-security internal services)
    Client and server both present certificates.

SECURITY RULES
  โœ— Never hardcode secrets in source code
  โœ— Never blindly forward client tokens to third-party APIs
       ("token passthrough" โ€” confused deputy attack)
  โœ“ Validate tokens were issued for your server's audience
  โœ“ Use HTTPS for all remote HTTP transport in production
  โœ“ Implement per-client OAuth consent, not shared static IDs
  โœ“ Apply minimal scope โ€” request only what each operation needs
typescriptยทHTTP auth middleware example
// Express middleware to validate Bearer token
app.use("/mcp", (req, res, next) => {
  const auth = req.headers.authorization;
  if (!auth?.startsWith("Bearer ")) {
    return res.status(401).json({ error: "Missing token" });
  }
  const token = auth.slice(7);
  if (!isValidToken(token)) {           // your validation logic
    return res.status(403).json({ error: "Invalid token" });
  }
  next();
});

// Block SSRF โ€” private IP ranges in fetch-based servers
const BLOCKED = [
  /^127\./, /^10\./, /^192\.168\./, /^172\.(1[6-9]|2\d|3[01])\./,
  /^169\.254\./,  // link-local / AWS metadata
];
function isSafeUrl(url: string): boolean {
  const { hostname } = new URL(url);
  return !BLOCKED.some(re => re.test(hostname));
}

Notable MCP Servers

Official and community MCP servers worth knowing about.

textยทOfficial reference servers
SERVER              PACKAGE                                      WHAT IT DOES
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
filesystem          @modelcontextprotocol/server-filesystem     Read/write/search local files
git                 @modelcontextprotocol/server-git             Git log, diff, status, clone
github              @modelcontextprotocol/server-github          Issues, PRs, repos, code search
gitlab              @modelcontextprotocol/server-gitlab          GitLab API equivalents
postgres            @modelcontextprotocol/server-postgres        SQL queries, schema inspection
sqlite              @modelcontextprotocol/server-sqlite          SQLite queries
memory              @modelcontextprotocol/server-memory          Persistent knowledge graph
fetch               @modelcontextprotocol/server-fetch           Web content retrieval + HTMLโ†’MD
brave-search        @modelcontextprotocol/server-brave-search    Web search via Brave API
puppeteer           @modelcontextprotocol/server-puppeteer       Browser automation, screenshots
time                @modelcontextprotocol/server-time            Time, timezone conversions
slack               @modelcontextprotocol/server-slack           Slack channels, messages

INSTALL ANY VIA npx (no install needed)
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"]
textยทPopular third-party servers
SERVER              SOURCE                       WHAT IT DOES
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
AWS KB Retrieval    awslabs/mcp                  Query AWS Bedrock Knowledge Bases
Cloudflare          cloudflare/mcp-server-cf     Workers, KV, R2, D1 management
Stripe              stripe/agent-toolkit         Payments, customers, subscriptions
Sentry              getsentry/sentry-mcp         Issues, events, performance data
Linear              linear-mcp                   Issues, projects, teams
Jira                atlassian/mcp-atlassian      Jira issues, Confluence pages
Grafana             grafana-mcp                  Dashboards, alerts, datasources
Docker              mcp-docker                   Container management
Kubernetes          mcp-kubernetes               Cluster resources, logs, pods
Redis               redis/mcp-server-redis       Get/set/query Redis
Qdrant              qdrant-mcp                   Vector search and storage
Playwright          mcp-playwright               Browser automation (alt to Puppeteer)

DISCOVERY
  https://github.com/modelcontextprotocol/servers  โ€” official list
  https://mcp.so                                   โ€” community directory

Debugging & Testing

MCP Inspector, log locations, and common errors.

bashยทMCP Inspector
# Launch Inspector against a local stdio server
npx @modelcontextprotocol/inspector npx @modelcontextprotocol/server-filesystem /tmp

# Custom port
npx @modelcontextprotocol/inspector --port 5174 node dist/index.js

# Against an HTTP server
npx @modelcontextprotocol/inspector --transport http --url http://localhost:3000/mcp

# Python server via uv
npx @modelcontextprotocol/inspector uv run server.py

# Inspector features (runs at http://localhost:5173 by default)
#   โ€ข List and call tools interactively
#   โ€ข Browse resources and templates
#   โ€ข Invoke prompts with arguments
#   โ€ข View raw JSON-RPC messages
#   โ€ข Inspect server capabilities and version
bashยทLog locations & common errors
# Claude Desktop log files
tail -f ~/Library/Logs/Claude/mcp*.log                   # macOS
# %APPDATA%\Claude\logs\mcp*.log                       # Windows

# Claude Code (stdio server stderr goes here)
journalctl -f   # or check terminal output

# Python FastMCP dev mode โ€” shows all messages
mcp dev server.py

COMMON ERRORS & FIXES
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
"spawn ENOENT"              command not found โ€” use absolute path
                            or ensure executable is on PATH

"JSON parse error"          server wrote to stdout (stdio transport)
                            Move all logging to stderr

"Protocol version mismatch" SDK version mismatch between client/server
                            Update both to same MCP spec version

"ECONNREFUSED"              HTTP server not running on expected port
                            Check port and that server started

"Timeout"                   Tool handler too slow
                            Add timeouts; return partial results early

Config not loading          Restart the MCP host after editing config
                            Check JSON syntax (no trailing commas)