Part I — Foundations (Day‑1, AM Theory)¶
3.1 What is MCP and Why a Gateway¶
Model Context Protocol (MCP) standardizes how agents communicate with tool servers that expose tools, resources, and prompts.
The MCP Gateway sits in front of many MCP servers and REST sources to:
- Federate tools into a unified, discoverable catalog
- Enforce policy with plugins (pre/post hooks), RBAC, and authentication
- Observe every call (structured logs + OTEL traces)
- Abstract transport: SSE, streamable HTTP, stdio, WebSockets
Mental model
Agent ↔ Gateway ↔ MCP Servers / REST APIs
Example — A tool contract (JSON Schema)
{
"name": "calc.add",
"description": "Return a + b",
"schema": {
"type": "object",
"properties": { "a": { "type": "number" }, "b": { "type": "number" } },
"required": ["a", "b"]
}
}
3.2 Architecture and Core Concepts¶
- Gateway: reverse proxy + registry + policy engine
- MCP Server: serves tools/resources/prompts
- Virtual Servers: group tools logically
- Plugins: middleware hooks for rate limit, secrets/PII, schema guard, retries
- Auth & RBAC: JWT/OAuth; role-based access per tool
- Observability: JSON logs + OTEL → Phoenix/APM
High‑level diagram
flowchart LR
A[CrewAI Agent] -->|MCP| B(MCP Gateway)
B -->|RBAC / Guardrails| B
B --> C[Server/Adapter 1]
B --> D[Server/Adapter 2]
C --> E[(External API)]
D --> F[(Langflow / RAG)]
B --> G[(Logs & Traces)]
3.3 Agents & Clients Overview¶
- Agents: CrewAI, LangChain, LangGraph, LlamaIndex, Semantic Kernel, OpenAI SDK
- Clients: MCP CLI, Inspector, IDE clients (Continue, Cline, Claude Desktop), OpenWebUI
- Pattern: point all agents at one gateway; discover/invoke tools from there
Minimal CrewAI example:
from crewai import Agent, Task, Crew
analyst = Agent(role="Analyst", goal="Summarize inputs concisely", backstory="Operates under gateway policies")
task = Task(description="Summarize: {text}", expected_output="2-3 sentences", agent=analyst)
print(Crew(agents=[analyst], tasks=[task]).kickoff(inputs={"text":"MCP Gateway centralizes governance for tools."}))
3.4 Serving Patterns: gRPC, REST, Reverse Proxy, Wrappers¶
Expose capabilities by direct MCP servers, reverse proxies, or HTTP wrappers.
Adapter sketch (FastAPI wrapping httpbin):
from fastapi import FastAPI, HTTPException
import requests
app = FastAPI(); UPSTREAM="https://httpbin.org/get"
@app.get("/tools")
def tools(): return {"tools":[{"name":"httpbin.get","schema":{"type":"object","properties":{"q":{"type":"string"}}}}]}
@app.post("/call/httpbin.get")
def call(payload: dict):
try:
r = requests.get(UPSTREAM, params={"q":payload.get("q","")}, timeout=10); r.raise_for_status()
return {"status": r.status_code, "json": r.json()}
except Exception as e:
raise HTTPException(status_code=502, detail=str(e))
3.5 Security & Governance Essentials¶
JWT + RBAC and guardrails (rate limiter, secrets/PII, schema guards) at the gateway.
RBAC example
rbac:
roles:
- name: admin
allow_all: true
- name: analyst
allow_tools: ["calc.add", "lf.summarize"]
- name: viewer
allow_tools: []
Rate limiter
plugins:
- name: rate_limiter
kind: plugins.rate_limiter.rate_limiter.RateLimiterPlugin
hooks: ["prompt_pre_fetch","tool_pre_invoke"]
mode: enforce
priority: 50
config: { by_user: "60/m", by_tenant: "600/m", by_tool: "30/m", burst: 5 }
3.6 Observability & Telemetry¶
Enable OTEL and export to Phoenix:
docker run -p 6006:6006 -p 4317:4317 arizephoenix/phoenix:latest
export OTEL_ENABLE_OBSERVABILITY=true
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
mcpgateway --host 0.0.0.0 --port 4444