Skip to main content

Model Context Protocol (MCP)

This document is an independent paraphrased tutorial describing public concepts of the Model Context Protocol (MCP). For definitive specifications and evolving details, always consult the official MCP repositories and documentation.

1. Executive Summary

The Model Context Protocol (MCP) defines a standardized, transport‑agnostic contract that lets AI clients (editors, IDEs, orchestrators, agent frameworks) discover and invoke servers that expose structured context (resources), callable tools, and streaming events. MCP aims to eradicate bespoke plugin APIs, enabling portable tool ecosystems and reproducible model contexts across environments (local dev, cloud, CI, notebooks).

2. Why MCP? (Motivation)

ProblemLimitation Without MCPMCP Remedy
Fragmented Tool IntegrationsEach app invents a plugin API.Unified capability negotiation + tool schema.
Opaque Context InjectionAd‑hoc prompt stuffing without provenance.Explicit resource listing/versioning + structured retrieval.
Model / Runtime DivergenceTooling tied to a single vendor.Open, transport‑agnostic protocol surface.
Lack of Streaming SemanticsPolling / brittle websockets.Built‑in event & token streaming channels.
Poor ReproducibilityHidden side effects.Declarative capabilities & deterministic resource handles.

3. High-Level Architecture

+-----------+        Transport (JSON-RPC / stdio / WebSocket)        +-------------+
| Client | <-----------------------------------------------> | MCP Server|
| (IDE/LLM) | Init -> Capability Exchange -> Resource/Tool Calls | (Adapter) |
+-----------+ +-------------+
| |
| Tool Invoke / Resource Fetch | Backend Systems
v v
Model / Agent Stack <-- internal orchestration --> Databases / APIs / Repos / Vector Stores

Roles:

  • Client: Initiates session, queries capabilities, presents UI or feeds model.
  • Server: Declares resources, tools, events; executes actions deterministically.
  • Transport: Usually JSON-RPC 2.0 framing (often over stdio or WebSocket); not mandated by semantics.

4. Core Protocol Primitives

PrimitivePurposeNotes
InitializationNegotiate protocol + feature versions.Prevents silent divergence.
CapabilitiesServer declares optional features (tools, resources, streaming).Enables graceful fallback.
ResourcesEnumerated contextual objects (files, embeddings, configs).Addressed by stable uri or handle.
ToolsStructured callable functions with JSON schemas for params & result.Model / agent can plan reliably.
Events / StreamingAsynchronous push: status, progress, token streams.Avoids blocking synchronous calls.
ErrorsStandardized error codes & messages.Encourages predictable recovery.

5. Capabilities & Negotiation

Handshake typically includes:

{
"jsonrpc": "2.0",
"method": "initialize",
"params": {
"protocolVersion": "1.0",
"client": { "name": "example-ide", "version": "0.4.2" },
"wanted": { "tools": true, "resources": true, "streaming": true }
},
"id": 1
}

Server responds with accepted + advertised capabilities (example structure). The client must gracefully handle omitted/false features.

6. Resource Model

Characteristics:

  • Each resource described with metadata: uri, kind, title, mimeType, optional version, hash / etag.
  • Retrieval via request—may return content inline or a reference (e.g., pre-signed URL).
  • Pagination or chunking for large resources.
  • Determinism: Clients can verify integrity (hash) to include stable context in prompts.

Example resource listing response (illustrative):

{
"jsonrpc": "2.0", "id": 2,
"result": {
"resources": [
{"uri": "repo://main/src/models/model.py", "kind": "code", "mimeType": "text/x-python", "version": "acbd18", "hash": "sha256:..."},
{"uri": "vector://products/index", "kind": "embedding-index", "mimeType": "application/vnd.vector+json"}
]
}
}

7. Tools (Callable Functions)

A tool definition surfaces:

  • Name (stable identifier)
  • Description (model-readable & human)
  • JSON Schema for input parameters
  • JSON Schema or shape for result
  • Side-effect classification (pure vs mutating) & safety notes
  • Optional cost hints / latency class

Example tool declaration fragment:

{
"name": "searchProducts",
"description": "Semantic product search returning top matches.",
"inputSchema": {
"type": "object",
"required": ["query"],
"properties": { "query": {"type": "string", "minLength": 2}, "limit": {"type": "integer", "default": 5, "minimum": 1, "maximum": 20} }
},
"outputSchema": {
"type": "object",
"properties": { "results": { "type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "score": {"type": "number"}}}} }
},
"sideEffects": "read-only"
}

Invocation request (illustrative):

{
"jsonrpc": "2.0",
"method": "tool/execute",
"params": { "name": "searchProducts", "arguments": { "query": "wireless earbuds", "limit": 3 }},
"id": 42
}

8. Streaming & Events

Use cases:

  • Long‑running tool progress
  • Incremental retrieval (token / chunk streaming)
  • Observability (log channels)

Pattern (pseudo): initial request acknowledges, subsequent notification messages deliver event objects with sequence numbers. Client reassembles or displays progressively. Ensure idempotency or ordering guarantees via monotonic seq.

9. Error Handling

Error ClassExample CodeClient Strategy
ValidationINVALID_PARAMSReconstruct request with corrected shape.
Capability MissingUNSUPPORTED_FEATUREFallback or disable UI affordance.
Transient BackendRETRYABLEExponential backoff with jitter.
Rate / BudgetRATE_LIMITSurface to user; delay further calls.
InternalINTERNAL_ERRORCapture diagnostic metadata; show minimal message.

Include stable code, human message, and optional structured data for machine recovery.

10. Versioning & Compatibility

Strategies:

  • Protocol semantic version (e.g., 1.0, 1.1) in initialize.
  • Capability flags for additive features (avoid breaking shape changes mid‑major).
  • Deprecation metadata: server may include deprecatedSince + removalTarget in tool descriptors.
  • Use contract tests in CI: golden JSON requests/responses to prevent accidental drift.

11. Security & Isolation

DomainControl
TransportUse local stdio for colocated processes; TLS for remote sockets.
AuthNOut‑of‑band (e.g., bearer token env var) or mutual trust if local user session.
AuthZServer internally scopes which tools/resources a client identity can see.
Input ValidationStrict JSON Schema validation before execution.
SandboxingRun high‑risk tools in subprocess / container with resource limits.
AuditingLog tool invocations, arguments hash (avoid secrets in plaintext logs).

Never assume the client is benign—treat all inputs as untrusted.

12. Implementing a Minimal Node.js MCP Server

Illustrative simplified server (conceptual only):

#!/usr/bin/env node
import { stdin as input, stdout as output } from 'node:process';

interface JsonRpc { jsonrpc: '2.0'; id?: number | string; method?: string; params?: any; result?: any; error?: any; }

function send(msg: any) {
output.write(JSON.stringify(msg) + '\n');
}

send({ jsonrpc: '2.0', method: 'log', params: { level: 'info', message: 'MCP server starting' }});

process.stdin.setEncoding('utf8');
input.on('data', (chunk) => {
for (const line of chunk.trim().split(/\n+/)) {
if (!line) continue;
let req: JsonRpc;
try { req = JSON.parse(line); } catch (e) { continue; }
if (req.method === 'initialize') {
send({ jsonrpc: '2.0', id: req.id, result: { protocolVersion: '1.0', capabilities: { tools: true, resources: true }}});
} else if (req.method === 'resource/list') {
send({ jsonrpc: '2.0', id: req.id, result: { resources: [{ uri: 'memo://welcome', kind: 'text', mimeType: 'text/plain', version: '1', hash: 'sha256:demo' }] }});
} else if (req.method === 'tool/list') {
send({ jsonrpc: '2.0', id: req.id, result: { tools: [{ name: 'echo', description: 'Echo text', inputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] }, outputSchema: { type: 'object', properties: { text: { type: 'string' }}} }] }});
} else if (req.method === 'tool/execute') {
const text = req.params?.arguments?.text ?? '';
send({ jsonrpc: '2.0', id: req.id, result: { text } });
} else {
send({ jsonrpc: '2.0', id: req.id, error: { code: 'METHOD_NOT_FOUND', message: 'Unknown method' }});
}
}
});

Run:

chmod +x ./mcp-echo-server.ts
# (transpile or run with ts-node) then connect your client via stdio

13. Python Sketch (Server Skeleton)

#!/usr/bin/env python3
import sys, json

def send(msg):
sys.stdout.write(json.dumps(msg) + '\n')
sys.stdout.flush()

send({"jsonrpc":"2.0","method":"log","params":{"level":"info","message":"MCP py server starting"}})

for line in sys.stdin:
line=line.strip()
if not line:
continue
try:
req=json.loads(line)
except Exception:
continue
mid=req.get('id')
method=req.get('method')
if method=='initialize':
send({"jsonrpc":"2.0","id":mid,"result":{"protocolVersion":"1.0","capabilities":{"tools":True,"resources":True}}})
elif method=='resource/list':
send({"jsonrpc":"2.0","id":mid,"result":{"resources":[{"uri":"memo://py","kind":"text","mimeType":"text/plain","version":"1"}]}})
elif method=='tool/list':
send({"jsonrpc":"2.0","id":mid,"result":{"tools":[{"name":"echo","description":"Echo text","inputSchema":{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]},"outputSchema":{"type":"object","properties":{"text":{"type":"string"}}}}]}})
elif method=='tool/execute':
args=req.get('params',{}).get('arguments',{})
send({"jsonrpc":"2.0","id":mid,"result":{"text":args.get('text','')}})
else:
send({"jsonrpc":"2.0","id":mid,"error":{"code":"METHOD_NOT_FOUND","message":"Unknown method"}})

14. Client Considerations

ConcernGuidance
BackpressureBuffer bounded; request concurrency gating.
Tool DiscoveryCache descriptors; refresh on tool/updated events if supported.
Prompt AssemblyInsert resource excerpts with provenance (URI + version/hash).
Retry LogicIdempotent GET‑like calls safe; avoid re‑invoking mutating tools blindly.
Secret HandlingClient should redact or avoid transmitting secrets unless required.

15. Observability & Telemetry

  • Structured invocation logs: timestamp, tool, latency ms, outcome.
  • Metrics: success rate, p95 tool latency, resource fetch size distribution.
  • Optional tracing: correlate request IDs across server backends.
  • Anomaly detection: spikes in attempts for METHOD_NOT_FOUND may indicate version skew.

16. Advanced Extensions

FeatureIdea
Partial Tool PlansServer suggests intermediate sub‑calls for complex workflows.
Cost MetadataTools expose estimated token or compute cost → model planning.
Adaptive StreamingClient negotiates chunk size or token cadence.
Multi-Modal ResourcesmimeType variants (image embeddings, audio transcripts).
Sandboxed WASM ToolsDistribute portable tool payloads executed client‑side.

17. Best Practices

  • Separate pure vs mutating tools to inform safe auto‑invocation.
  • Keep tool surface minimal; avoid overlapping semantics.
  • Provide JSON Schema enums & constraints to reduce model ambiguity.
  • Version bump only when contract changes; additive fields gated by capability flags.
  • Log hashes rather than raw sensitive content for debug traceability.

18. Common Pitfalls & Troubleshooting

SymptomLikely CauseResolution
Client ignores toolCapability not advertisedEnsure initialize response sets tools: true.
Repeated METHOD_NOT_FOUNDMethod name mismatchAlign to canonical tool/execute etc.
Resource hash mismatchServer content mutated mid-sessionAdd version pin & stable snapshot semantics.
Latency spikesOverloaded backend or synchronous heavy toolIntroduce async worker / queue.
Broken streaming orderMissing sequence monotonicityAdd seq field & reorder or reject out‑of‑order.

19. FAQ

QuestionAnswer
Is MCP tied to a specific model vendor?No; it's model/runtime agnostic.
Do I need WebSockets?Not necessarily; stdio or pipes suffice locally.
How do I secure remote servers?TLS + client auth (mTLS or token) + strict tool allowlists.
Can tools call other tools?Yes, but avoid recursive loops; maintain trace context.
How big can resources be?Chunk or page large datasets; advertise size hints.

20. Reference Implementation Checklist

AreaMinimalProduction
Transportstdio JSON-RPCTLS WebSocket + auth + backpressure
ValidationBasic try/exceptJSON Schema + contract tests
LoggingConsole linesStructured logs + metrics + tracing
Tool RegistryHardcoded listDynamic plugin discovery & hot reload
SecurityLocal trustAuthZ per tool + sandboxing + rate limits
ObservabilityManual timingp95 metrics, alerts, anomaly detection

21. Integration Opportunities

  • IDE & Editor Extensions (context panel + tool palette)
  • CI Agents (deterministic environment diff resource tool)
  • Retrieval Augmented Generation pipelines (resource enumerator + embedding index tool)
  • Governance: audit export tool enumerating all context passed to models
  • Multi‑tenant platform: per‑tenant server processes with isolated tool registries

22. Migration & Evolution Strategy

  1. Start with read‑only resource exposure.
  2. Introduce low‑risk tools (search/list) with schemas.
  3. Add streaming for long operations (embedding build, index refresh).
  4. Implement mutating tools guarded by policies & review.
  5. Automate contract tests in CI.
  6. Monitor metrics -> refine capacity planning.

23. Attribution

Model Context Protocol™ concepts are attributed to their respective open initiative & contributors. This document is an educational paraphrased guide.


End of guide.