Coding Agents in Practice (3/5) — Building MCP Servers: Spec, Examples, Debugging

AI ์ฝ”๋”ฉ ์—์ด์ „ํŠธ ์‹ค์ „ (3/5) — MCP ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ: ์ŠคํŽ™·์˜ˆ์ œ·๋””๋ฒ„๊น…

Cursor, Claude Code, and VS Code Agent all adopted the Model Context Protocol. Build a server yourself to understand it.


ํ•ต์‹ฌ ์š”์•ฝ

  • MCP is a standard protocol for LLM agents to access external tools, resources, and prompts
  • Primary sources: modelcontextprotocol.io spec, Anthropic Claude Code MCP docs
  • Three core capabilities: Tools (functions the agent calls) / Resources (read-only data) / Prompts (reusable templates)
  • Debugging is mcp inspector + stderr logging — that's the de facto standard
  • Pitfall: a single stray print() to stdout can break the entire JSON-RPC channel

1. The problem MCP solves

Each agent had its own tool-integration mechanism: Claude Code had one tool spec, Cursor had its own extensions, VS Code had a separate API. The same integration had to be built three times.

MCP standardizes this: write one MCP server, and it works in every MCP-supporting agent (Claude Code, Cursor, VS Code Agent, Continue, etc.). As of 2026 it is effectively the default.

Protocol essentials: JSON-RPC 2.0 + three capabilities (Tools / Resources / Prompts) + three transports (stdio / SSE / Streamable HTTP).


2. The three capabilities

2.1 Tools — Functions the agent calls

The most-used capability. The agent takes action. - Examples: search_database(query), create_jira_ticket(title, body), run_shell(cmd). - Definition: name + JSON Schema for arguments + short description. - Returns text or structured data.

2.2 Resources — Read-only data

Resources the agent reads but does not change. - Examples: file contents, DB rows, configuration values, API responses. - Identified by URI: file:///path, db://table/row/123, config://app/setting. - Unlike tools, no side effects are guaranteed (safe for agents to pre-load).

2.3 Prompts — Reusable templates

Frequent task patterns exposed as prompt templates. - Examples: "review this code," "explain this SQL," "draft a PR message for this diff." - Can be triggered as slash commands.


3. Minimum example — A Python MCP server in 30 lines

Using the mcp Python SDK. This is a real, working MCP server:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hello-mcp")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two integers and return the sum."""
    return a + b

@mcp.tool()
def greet(name: str) -> str:
    """Greet a person by name."""
    return f"Hello, {name}!"

@mcp.resource("config://app/version")
def app_version() -> str:
    """Read-only application version."""
    return "1.0.0"

if __name__ == "__main__":
    mcp.run(transport="stdio")

Register with Claude Code:

claude mcp add hello-mcp --command "python /abs/path/server.py"

That single command makes add, greet, and config://app/version auto-discovered inside the session.


4. Debugging — Looking inside an invisible channel

MCP's biggest pitfall is that stdout is the protocol channel. Under stdio transport, JSON-RPC messages flow through stdout — adding print("debug") immediately corrupts the channel.

Four debugging rules: 1. Never write to stdout. Logs go to sys.stderr or a file. 2. Use the MCP Inspectornpx @modelcontextprotocol/inspector python server.py opens a GUI to invoke tools/resources/prompts and see responses. 3. Raise errors. Don't swallow with try/except — raising propagates the error to the client. 4. Validate JSON Schema. The SDK auto-generates argument schemas, but inspect complex types yourself.

Common errors: - "server disconnected": process died at startup. Check stderr. - "tool not found": registered but typo or stale cache after signature change. - "invalid arguments": client sent JSON that violates the schema. Use Inspector to inspect the exact argument shape.


5. Choosing a transport

Transport Use case Notes
stdio Local server, single user Simplest. Client spawns server as a child process
SSE / Streamable HTTP Remote server, multi-user HTTP-based with auth. For data centers / internal services

Start with stdio. Move to HTTP only when remote use becomes a real requirement.


6. Security checklist — Before trusting an MCP server

Third-party MCP servers carry arbitrary code-execution authority. A tool call is a function execution, and the function can do anything. Before connecting an external server:

  • Read the source. Open the GitHub repository and check what system calls the server makes.
  • Permission scope. File system access, network, external API keys — what does it require?
  • Isolation. Use containers, VMs, or separate OS users when possible.
  • Audit logging. Record every tool invocation.

Use catalogs like awesome-mcp-servers as a starting point, but run all four checks before any production connection.


7. At a glance

Step Core Watch out for
Design Separate Tools / Resources / Prompts Side-effecting → Tool, side-effect-free → Resource
Implementation mcp SDK + @mcp.tool() decorator Never print to stdout
Registration claude mcp add <name> --command ... Use absolute paths
Debugging MCP Inspector + stderr logs "server disconnected" → check stderr
Operation Permission scope + isolation + audit External MCP = arbitrary code execution

Next up

Part 4/5: Multi-Agent Patterns — Orchestrator and Specialist Separation. If MCP integrates external tools, multi-agent patterns are how you split internal work.


References

  • Model Context Protocol, Specification — modelcontextprotocol.io (verified 2026-05-05).
  • Anthropic, Using MCP with Claude Code — code.claude.com/docs/mcp (verified 2026-05-05).
  • awesome-mcp-servers — github.com/punkpeye/awesome-mcp-servers.

This is part 3/5 of the Coding Agents in Practice series.

๋Œ“๊ธ€

์ด ๋ธ”๋กœ๊ทธ์˜ ์ธ๊ธฐ ๊ฒŒ์‹œ๋ฌผ

Agent Memory Engine (2/10) — Building an AI Agent Memory System with SQLite Alone

"ML Foundations (9/9) — PyTorch vs TensorFlow, and the Road to Local LLMs"

"RAG Core Study (14/26) — Evaluation Sets with RAGAS & DeepEval"

"ML Foundations (8/9) — Deep Learning Architectures: CNN, RNN, Attention"

"ML Foundations (7/9) — Deep Learning Training: Optimizers, Regularization, Initialization"

OpenClaw to Hermes Migration (2/13) — What to Preserve, Partially Port, or Discard

AI Agents I Built (5/7) — Building an Automated Blogger API Publishing System