🧩 High-Level Goal

You're not just exposing endpoints anymore β€” you're exposing "capabilities" that an LLM can invoke, inspect, and reason about within an ongoing session.

🧱 Side-by-Side Architecture Map

Layer REST API (Stateless) MCP Server (Stateful) Ξ” Transformation
Entry Point main.py runs HTTP server server.py runs message loop πŸ” Replace request/response with message dispatch
Router @app.route("/path") @mcp.tool() πŸ” Path routing β†’ tool routing
Transport HTTP verbs + routes JSON-RPC methods βž• Session persists; multi-step interactions
Schema OpenAPI / code docs Auto-extracted from type hints βž• Machine-readable for LLMs
Context Each request new (no memory) Shared context across invocations βž• Stateful (cache, auth, session)
Discovery Humans read /docs LLM queries list_tools βž• Self-discoverable
Client Browser, mobile app LLM / AI Agent ⚑️ Programmatic reasoning

πŸ“ File Structure Transformation

REST API β€” Classic Layout

api_server/
β”œβ”€β”€ main.py           # HTTP server
β”œβ”€β”€ routes/
β”‚   β”œβ”€β”€ users.py      # @app.route('/users')
β”‚   └── orders.py
β”œβ”€β”€ models/
β”‚   β”œβ”€β”€ user_model.py
β”‚   └── order_model.py
β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ db_service.py
β”‚   └── cache_service.py
└── utils/
    β”œβ”€β”€ auth.py
    └── error_handlers.py

MCP Server β€” Transformed Layout

mcp_server/
β”œβ”€β”€ server.py         # Message loop (stdio/ws)
β”œβ”€β”€ tools/
β”‚   β”œβ”€β”€ users.py      # @mcp.tool() get_user(id)
β”‚   └── orders.py     # @mcp.tool() create_order()
β”œβ”€β”€ resources/
β”‚   β”œβ”€β”€ user://{id}   # dynamic URI resource
β”‚   └── inventory://{sku}
β”œβ”€β”€ schema/
β”‚   └── generated.json # JSON-Schema
β”œβ”€β”€ context/
β”‚   β”œβ”€β”€ state.py      # Session context store
β”‚   └── memory.py     # Persistent across calls
└── transports/
    β”œβ”€β”€ stdio.py
    └── websocket.py

🧭 Key Transformations:

  • β†’ /routes becomes /tools
  • β†’ /models becomes /resources (conceptual entities)
  • β†’ /services remain same (but injected into context)
  • + /context added (state/session layer)

βš™οΈ Internal Code Transformation

Example 1: Basic Addition Handler

REST API (Flask)
@app.route("/add", methods=["POST"])
def add():
    data = request.json
    result = data["a"] + data["b"]
    return jsonify({"result": result})
MCP Server
@mcp.tool()
async def add(a: int, b: int) -> int:
    return a + b

Key difference: MCP uses tool name + schema routing instead of path + method. Input/output validation comes from type hints automatically.

Example 2: Stateful Context Handling

REST (Stateless)
@app.route("/cart", methods=["POST"])
def add_to_cart():
    user = request.headers["User"]
    cart = db.get_cart(user)
    cart.add(request.json["item"])
    db.save_cart(cart)
    return jsonify({"message": "ok"})
MCP (Stateful)
@mcp.tool()
def add_to_cart(ctx: Context, item: str):
    cart = ctx.session.get("cart", [])
    cart.append(item)
    ctx.session["cart"] = cart
    return {"cart_size": len(cart)}

Ξ” Transformation: Session is in-memory, persists across tool invocations β€” useful for reasoning and chaining.

🧠 REST β†’ MCP Concept Mapping

REST Concept MCP Equivalent Remarks
Route Tool Invokable function, schema-aware
GET /resource/:id read_resource("uri") Accesses a resource handler
POST /data invoke_tool("tool_name") Calls a capability
Request.headers Context.session Holds user/session info
Middleware Hook / Lifespan Pre/post invocation wrappers
OpenAPI MCP Schema Generated from annotations
404 Error.code=32001 JSON-RPC error variant

βš–οΈ Summary of Trade-offs

Aspect REST (+) MCP (+) Comment
Simplicity βœ… Very simple ⚠️ More complex REST easier for humans
AI Integrability ❌ Hard (needs wrapper) βœ… Native MCP made for LLMs
State ❌ Stateless βœ… Stateful Enables tool chaining
Discoverability 🧍 Manual docs πŸ€– Auto via list_tools Self-describe
Security Mature Evolving Requires trust boundary design
Performance High (HTTP optimized) Medium (RPC overhead) But fine for tool calls
Purpose Web & API apps AI orchestration Complementary layers

🧭 Big Picture

MCP doesn't replace REST; it wraps or extends it β€” turning traditional endpoints into introspectable, schema-aware, conversational tools.

"An RPC faΓ§ade for LLMs, sitting on top of APIs that were originally built for humans."