MCP Protocol
Understanding the Model Context Protocol (MCP) and how MA²D implements it.
What is MCP?
The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to Large Language Models (LLMs). It enables AI agents to:
- Call Functions (Tools)
- Access Data (Resources)
- Use Templates (Prompts)
Think of MCP as a universal API specification for AI agents.
Official Specification
MCP is maintained by Anthropic and the open-source community:
- Website: modelcontextprotocol.io
- Specification: spec.modelcontextprotocol.io
- SDK: @modelcontextprotocol/sdk
MCP Components
1. Tools
Tools are functions that AI agents can execute:
interface Tool {
name: string
description: string
inputSchema: JSONSchema // What the tool accepts
}Example:
{
"name": "get_weather",
"description": "Get current weather for a city",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
}
},
"required": ["city"]
}
}2. Resources
Resources are data sources that agents can read:
interface Resource {
uri: string // Unique identifier
name: string
description?: string
mimeType?: string
}Example:
{
"uri": "weather://cities",
"name": "Available Cities",
"description": "List of cities with weather data",
"mimeType": "application/json"
}3. Prompts
Prompts are templates for agent interactions:
interface Prompt {
name: string
description?: string
arguments?: PromptArgument[]
}Example:
{
"name": "weather_query",
"description": "Template for weather queries",
"arguments": [
{
"name": "location",
"description": "Location to query",
"required": true
}
]
}MCP Protocol Flow
Initialization
Tool Discovery and Execution
JSON-RPC 2.0
MCP uses JSON-RPC 2.0 for all communication:
Request Format
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "San Francisco"
}
}
}Response Format
Success:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\"temperature\": 72, \"conditions\": \"Sunny\"}"
}
]
}
}Error:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Invalid params: city is required"
}
}HTTP-Streamable Transport
MA²D implements the HTTP-Streamable transport:
Endpoint Structure
https://your-domain.com/api/platform/{serverId}/mcpSupported Methods
| Method | Description |
|---|---|
initialize | Negotiate capabilities |
tools/list | List available tools |
tools/call | Execute a tool |
resources/list | List available resources |
resources/read | Read resource content |
prompts/list | List available prompts |
prompts/get | Get prompt template |
Server-Sent Events (SSE)
MCP uses SSE for streaming responses:
POST /api/platform/abc123/mcp HTTP/1.1
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"tools/list"}Response:
HTTP/1.1 200 OK
Content-Type: text/event-stream
data: {"jsonrpc":"2.0","id":1,"result":{"tools":[...]}}MA²D Implementation
Stateless Architecture
Each request creates a fresh MCP server instance:
// Simplified example
export async function POST(request: Request) {
const { serverId } = await params
// 1. Fetch server configuration from database
const server = await fetchServer(serverId)
const tools = await fetchTools(serverId)
const resources = await fetchResources(serverId)
// 2. Create MCP server instance
const mcpServer = new Server({
name: server.name,
version: server.version
}, {
capabilities: {
tools: {},
resources: {},
prompts: {}
}
})
// 3. Register components
tools.forEach(tool => {
mcpServer.setRequestHandler(ToolsCall, async (args) => {
return executeMockScenarios(tool, args)
})
})
// 4. Handle request
return handleStatelessMCPRequest(mcpServer, request)
}Mock Execution
MA²D executes mock scenarios instead of real implementations:
function executeMockScenarios(tool: Tool, args: any) {
// Find matching scenario
const scenario = tool.mock_scenarios.find(s =>
matchesCondition(s.condition, args)
)
if (scenario) {
return {
content: [{
type: "text",
text: JSON.stringify(scenario.response)
}]
}
}
// Default response if no match
return {
content: [{
type: "text",
text: JSON.stringify({ message: "No matching scenario" })
}]
}
}Capability Negotiation
The initialize method declares server capabilities:
{
"capabilities": {
"tools": {}, // Server provides tools
"resources": {}, // Server provides resources
"prompts": {} // Server provides prompts
},
"protocolVersion": "2024-11-05",
"serverInfo": {
"name": "my-mcp-server",
"version": "1.0.0"
}
}MA²D only declares capabilities for components that exist:
const capabilities: any = {}
if (tools.length > 0) capabilities.tools = {}
if (resources.length > 0) capabilities.resources = {}
if (prompts.length > 0) capabilities.prompts = {}Error Codes
MCP defines standard JSON-RPC error codes:
| Code | Meaning | When Used |
|---|---|---|
-32700 | Parse error | Invalid JSON |
-32600 | Invalid request | Malformed request |
-32601 | Method not found | Unknown method |
-32602 | Invalid params | Bad parameters |
-32603 | Internal error | Server error |
-32001 | Unauthorized | Auth failed |
Example error response:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Invalid params",
"data": {
"field": "city",
"reason": "required field missing"
}
}
}Testing MCP Endpoints
Using curl
curl -X POST http://localhost:3000/api/platform/abc123/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'Using Postman
- Create new POST request
- Set URL to MCP endpoint
- Set headers:
Content-Type: application/json - Body (raw JSON):
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "San Francisco"
}
}
}Using MCP Clients
- Claude Desktop: Configure in settings
- Witsy: Add server endpoint
- Custom Client: Use @modelcontextprotocol/sdk
Protocol Compliance
MA²D is fully compliant with MCP specification:
✅ JSON-RPC 2.0: All requests/responses follow spec ✅ HTTP-Streamable: Server-Sent Events support ✅ Capability Negotiation: Proper initialization ✅ Error Handling: Standard error codes ✅ Type Safety: JSON Schema validation ✅ Stateless: No server-side session state
Advanced Features
Resource Templates
MA²D supports resource URI templates:
{
"uri": "weather://cities/{cityId}",
"name": "City Weather",
"description": "Weather for specific city"
}Prompt Arguments
Prompts can have arguments with validation:
{
"name": "analyze_data",
"arguments": [
{
"name": "dataset",
"description": "Dataset to analyze",
"required": true
},
{
"name": "format",
"description": "Output format",
"required": false
}
]
}Tool Input Validation
MA²D validates tool inputs against JSON Schema:
const schema = tool.input_schema
const valid = validateSchema(args, schema)
if (!valid) {
return {
error: {
code: -32602,
message: "Invalid params",
data: validationErrors
}
}
}Best Practices
Tool Design
- Clear names: Use descriptive, action-oriented names
- Detailed descriptions: Explain what the tool does (200+ chars)
- Complete schemas: Document all parameters
- Example scenarios: Provide realistic mock data
Resource Design
- Logical URIs: Follow consistent naming patterns
- Appropriate MIME types: Specify content types
- Version resources: Include version in URI if needed
- Document structure: Explain resource format
Prompt Design
- Template variables: Use clear argument names
- Default values: Provide sensible defaults
- Examples: Show expected usage
- Validation: Define required vs optional arguments
Next Steps
- API Reference - Complete endpoint documentation
- Testing Guide - Test with various clients
- Architecture - How MA²D implements MCP
Learn More: Visit modelcontextprotocol.io for the official specification.