The Three Primitives
MCP exposes three types of capabilities:
Tools — executable functions the AI can call. Examples:
query_database(sql: string) — run a SQL query
send_email(to: string, subject: string, body: string) — send an email
search_codebase(query: string, file_pattern: string) — semantic code search
Resources — read-only data the AI can access. Examples:
- The contents of a file
- A specific database record
- A Confluence page or JIRA ticket
Prompts — reusable prompt templates the server provides. Examples:
- A standard code review prompt template
- A security analysis framework
- A document summarisation structure
How the Protocol Works
MCP uses JSON-RPC 2.0 as its wire format. A typical tool call flow:
- Discovery: Client sends
tools/list — server responds with all available tools and their JSON schemas
- Invocation: AI decides to call a tool; client sends
tools/call with tool name and arguments
- Execution: Server runs the tool and returns the result
- Context injection: Client includes the tool result in the next LLM request
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "query_database",
"arguments": {
"sql": "SELECT * FROM orders WHERE status = 'pending' LIMIT 10"
}
}
}
{
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": "[{\"order_id\": 1001, \"customer\": \"Acme Corp\", ...}]"
}
]
}
}
The AI then receives this result as context and uses it to generate its response.
Building an MCP Server
Here's a minimal MCP server in Python using Anthropic's official SDK:
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
app = Server("enterprise-tools")
@app.list_tools()
async def list_tools():
return [
Tool(
name="get_customer",
description="Retrieve customer information by ID",
inputSchema={
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "The customer's unique identifier"
}
},
"required": ["customer_id"]
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "get_customer":
customer_id = arguments["customer_id"]
customer = db.get_customer(customer_id)
return [TextContent(type="text", text=str(customer))]
async def main():
async with stdio_server() as streams:
await app.run(*streams, app.create_initialization_options())
You now have a working MCP server. Any MCP-compatible AI (Claude Desktop, your custom agent) can connect to it and call get_customer.
Enterprise Use Cases
AI Copilots for Internal Tools. Connect Claude to your internal ticketing system, wiki, and code repositories. Engineers can ask "What's the status of incident INC-4521?" and the AI retrieves the actual JIRA ticket data — no hallucination, real data.
Multi-Agent Pipelines. An orchestrator agent breaks a complex task into subtasks and delegates to specialist agents, each connected to different MCP servers. The code review agent has access to your GitHub MCP server; the deployment agent has access to your Kubernetes MCP server.
Enterprise Search and Knowledge Retrieval. Connect MCP to your vector database, Confluence, and SharePoint. Employees ask natural language questions; the AI retrieves relevant documents using semantic search and synthesises an answer.
Workflow Automation. MCP servers that wrap your business APIs (Salesforce, SAP, internal microservices) let AI agents trigger real actions — create a quote, update a record, send a notification — with proper auth and audit trails.
Security Considerations
MCP shifts security responsibility to the server boundary. Key practices:
- Authentication: Each MCP server should validate the caller's identity. Use OAuth 2.0 or API keys that are scoped per AI application, not shared across all clients.
- Authorisation: Tool calls should enforce the same RBAC rules as your regular APIs. An AI acting as a support agent should only access data that a support agent is allowed to see.
- Input validation: Validate all tool arguments rigorously. A tool that executes SQL should use parameterised queries, not string concatenation.
- Audit logging: Log every tool call with timestamp, caller identity, arguments, and result summary. This is essential for compliance and debugging.
MCP vs Custom Function Calling
For new enterprise AI projects, MCP is the right foundation. For existing OpenAI function calling integrations, migration is worth planning as MCP tooling matures.
Getting Started
The fastest path to your first MCP integration:
- Install Claude Desktop (already MCP-capable)
- Write a simple MCP server in Python or TypeScript using Anthropic's SDK
- Connect it to one internal data source (a read-only database query is a great start)
- Configure Claude Desktop to use your server
- Ask Claude questions about your data
You'll have a working internal AI tool in an afternoon. That's the promise of a protocol-based approach — the integration work compounds across tools rather than being reinvented for each new one.
Key Takeaways
- MCP is a USB-C for AI tools — write a tool once, use it with any MCP-compatible model
- The three primitives are Tools (executable functions), Resources (read-only data), and Prompts (reusable templates)
- MCP uses JSON-RPC 2.0 as the wire format — lightweight and inspectable
- Security lives at the server boundary. Validate every input; apply the same RBAC as your regular APIs; audit log every tool call
- MCP grows in value with scale — each new tool you write is immediately available to every AI in your organisation
- Start local with stdio transport, graduate to HTTP transport for multi-user production deployments
limit: 0 or tool restrictions mean the key doesn't have MCP server access — check your API key permissions
Practice Exercises
Exercise 1 — Starter (1 hour): Build your first MCP server that exposes one tool: a database lookup (read-only). Connect it to Claude Desktop and ask Claude natural-language questions about your data. Confirm tool calls appear in the inspector.
Exercise 2 — Intermediate (2–3 hours): Extend your MCP server to expose 3 tools: query, create, and update. Add input validation using JSON Schema and test with the OWASP injection examples. Implement audit logging that records every tool call with timestamp, caller, and arguments.
Exercise 3 — Advanced (half day): Deploy your MCP server as an HTTP endpoint with OAuth 2.0 authentication. Write a multi-agent workflow where one agent uses your MCP server to retrieve data and a second agent uses the results to generate a report. Measure the latency at each MCP call boundary using OpenTelemetry.