MCP Server Use Cases
November 20, 2024 • AI • Technical • Development
Loading...
What is the Model Context Protocol (MCP)?
The Model Context Protocol (MCP) standardizes how AI applications discover and call tools over a secure, streaming channel. An MCP server exposes capabilities—APIs, databases, filesystems, or internal services—as typed tools that any compliant client (your app, an agent, or an IDE plugin) can list, describe, and invoke. This decouples tool integration from model prompts and lets teams evolve capabilities without hard‑wiring them into prompts.
Why engineers adopt MCP servers
- Separation of concerns: tools live behind a stable server; prompts just call named functions.
- Security: a single chokepoint for auth, rate limits, audit logs, and data redaction.
- Observability: structured tool events with inputs/outputs for replay and tuning.
- Reuse: one server powers CLI agents, web apps, and IDE copilots.
MCP server architecture (practical)
A minimal production layout has four pieces: the client, the transport, the tool registry, and the handlers. The example below sketches a server with two tools: searchTickets and createTicket.
// pseudo-typescript: mcp server skeleton
import { createServer, tool } from '@acme/mcp';
const server = createServer({
transport: { kind: 'websocket', url: process.env.MCP_WS_URL },
auth: { strategy: 'bearer', verify: async (t) => t.startsWith('mcp_') }
});
server.register(tool({
name: 'searchTickets',
input: { query: 'string' },
output: { results: 'array' },
handler: async ({ query }, ctx) => ctx.db.search(query)
}));
server.register(tool({
name: 'createTicket',
input: { title: 'string', body: 'string', priority: 'enum(low|med|high)' },
output: { id: 'string', url: 'string' },
handler: async (i, ctx) => ctx.tracker.create(i)
}));
server.start();Common use cases
- RAG and search: expose a
retrievetool that abstracts vector DBs and re‑ranking. - DevOps: safe wrappers for deployments, feature flags, and incident runbooks.
- Data/BI: parameterized SQL with guards; return row samples plus chart JSON.
- Customer support: ticket search, macro generation, and action tools with approvals.
- Sales ops: CRM read/write tools with automatic PII redaction.
Case study: reducing ticket time-to-first-touch by 42%
A B2B SaaS team served 2k+ weekly support tickets across three regions. Agents used an LLM assistant inside the help desk, but answers were inconsistent and actions (creating follow‑ups, linking issues) required tab‑hopping. The team deployed an MCP server with three tools: searchTickets, summarizeIssue, and createTicket. The server handled auth to Zendesk, masked emails/phone numbers, and emitted structured telemetry.
- TTFT dropped from 21m → 12m (‑42%) after assistants could search and act in one flow.
- Agent‑written macros improved consistency; reusable prompts called the same MCP tools.
- Safety: writes required a short approval step; all tool calls were logged for audit.
Deployment tips
- Start read‑only: ship
list/get/searchtools first, then add writes with approvals. - Schema everything: define inputs/outputs narrowly; reject unknown fields to prevent prompt injection.
- Budget tokens: return compact objects; let the client render rich UI if needed.
- Observe: log inputs/outputs, latencies, and error classes; sample transcripts for prompt tuning.
Security and governance
Treat the MCP server as a policy gateway. Enforce per‑tool scopes, redact sensitive fields, and add guardrails (regex allowlists, numeric bounds). For regulated data, run the server inside your VPC and proxy any third‑party traffic.
Checklist before production
- Tool inventory reviewed with owners; fallbacks defined for every dependency.
- Latency SLOs per tool; retries and circuit‑breakers configured.
- Audit trail with user/agent identity and purpose strings.
- Load test with realistic burst patterns; chaos test dependency failures.
SEO FAQs
Is MCP just for agents? No—web apps and IDEs benefit equally from a uniform tool layer.
How is it different from plain REST? MCP standardizes discovery, typing, and streaming I/O for tools the model can call directly.
When to avoid MCP? For a single, static integration, direct SDK calls may be simpler. Choose MCP when you expect multiple tools/clients or evolving capabilities.
Further reading
- RAG Explained Simply: retrieval, reranking, grounding, and production patterns
- LLM Prompting: Getting Effective Output
- Vibe Coding: Ship Faster with Focused Flow
Real‑world use case: Add an MCP tool to an agent
Expose a calendar or docs API via MCP to your agent.
- Pick one tool
- Implement schema + server
- Connect client and test
Expected outcome: Reliable tool calling with typed I/O.
Implementation guide
- Time: 2–3 hours
- Tools: MCP server library, Agent client
- Prerequisites: API key and test account
- Define the tool schema and guardrails.
- Implement the MCP server; test locally.
- Register the tool with the client; run end‑to‑end test.
Architecture
LLM Agent (tool calling)
| tool: calendar.createEvent(args)
v
Tool Bridge (HTTP JSON‑RPC)
| POST /rpc { method, params }
v
MCP Server (Calendar)
| stores events; validates schema
v
External Calendar Provider (optional)
Input (example)
{
"method": "calendar.createEvent",
"params": {
"title": "Product sync",
"start": "2025-11-10T15:00:00Z",
"end": "2025-11-10T15:30:00Z",
"attendees": ["dev@acme.co", "pm@acme.co"],
"notes": "Agenda: triage + roadmap"
},
"id": 1,
"jsonrpc": "2.0"
}
Code (POC)
calendar-mcp-server.ts (minimal JSON‑RPC server with validation)
import http from 'http';
type CreateEventParams = {
title: string;
start: string; // ISO8601
end: string; // ISO8601
attendees?: string[];
notes?: string;
};
type JsonRpcRequest = { jsonrpc: '2.0'; method: string; params?: unknown; id?: number|string };
type JsonRpcResponse = { jsonrpc: '2.0'; result?: unknown; error?: { code: number; message: string }; id?: number|string };
const events: Array<CreateEventParams & { id: string }> = [];
function isCreateEventParams(x: any): x is CreateEventParams {
return x && typeof x.title === 'string' && typeof x.start === 'string' && typeof x.end === 'string';
}
function handleRpc(req: JsonRpcRequest): JsonRpcResponse {
if (req.method === 'calendar.createEvent') {
if (!isCreateEventParams(req.params)) {
return { jsonrpc: '2.0', error: { code: -32602, message: 'Invalid params' }, id: req.id };
}
const ev = { id: 'evt_' + Math.random().toString(36).slice(2), ...req.params };
events.push(ev);
return { jsonrpc: '2.0', result: { id: ev.id, status: 'created' }, id: req.id };
}
if (req.method === 'calendar.listEvents') {
return { jsonrpc: '2.0', result: events, id: req.id };
}
return { jsonrpc: '2.0', error: { code: -32601, message: 'Method not found' }, id: req.id };
}
const server = http.createServer((req, res) => {
if (req.method !== 'POST' || req.url !== '/rpc') { res.statusCode = 404; return res.end('Not found'); }
let body = '';
req.on('data', (c) => (body += c));
req.on('end', () => {
try {
const rpc = JSON.parse(body) as JsonRpcRequest;
const out = handleRpc(rpc);
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(out));
} catch (e: any) {
res.statusCode = 400;
res.end(JSON.stringify({ jsonrpc: '2.0', error: { code: -32700, message: 'Parse error' } }));
}
});
});
server.listen(8787, () => console.log('MCP calendar server on http://localhost:8787/rpc'));
agent-bridge.ts (tool definition + bridge to JSON‑RPC)
type ToolCall = { name: 'calendar.createEvent' | 'calendar.listEvents'; arguments: any };
async function callRpc(method: string, params?: any) {
const res = await fetch('http://localhost:8787/rpc', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: Date.now(), method, params })
});
const json = await res.json();
if (json.error) throw new Error(json.error.message);
return json.result;
}
export const tools = [
{
name: 'calendar.createEvent',
description: 'Create a calendar event (ISO8601 timestamps).',
parameters: {
type: 'object',
properties: {
title: { type: 'string' },
start: { type: 'string', description: 'ISO8601 start' },
end: { type: 'string', description: 'ISO8601 end' },
attendees: { type: 'array', items: { type: 'string' } },
notes: { type: 'string' }
},
required: ['title', 'start', 'end']
}
},
{
name: 'calendar.listEvents',
description: 'List in-memory events',
parameters: { type: 'object', properties: {} }
}
];
export async function handleToolCall(call: ToolCall) {
switch (call.name) {
case 'calendar.createEvent':
return await callRpc(call.name, call.arguments);
case 'calendar.listEvents':
return await callRpc(call.name);
default:
throw new Error('Unknown tool');
}
}
// Example usage (pseudo‑agent loop)
async function demo() {
const result = await handleToolCall({
name: 'calendar.createEvent',
arguments: {
title: 'Product sync',
start: '2025-11-10T15:00:00Z',
end: '2025-11-10T15:30:00Z',
attendees: ['dev@acme.co', 'pm@acme.co']
}
});
console.log(result);
}
demo();
Output (example)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "evt_01HZX...",
"status": "created"
}
}
SEO notes
- Target: model context protocol server
- Add diagram alt text
Loading...
Related Articles
RAG Explained Simply: Real-time Data & Why It Matters
Understanding Retrieval-Augmented Generation and why real-time data integration is crucial for AI applications.
LLM Prompting: Getting Effective Output
Best practices for prompting large language models to get the results you need consistently.
Vibe Coding: Ship Faster with Focused Flow
Build software in a state of focused flow—guided by rapid feedback and clear intent—without abandoning engineering discipline.