Core ConceptsMCP Protocol

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:

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}/mcp

Supported Methods

MethodDescription
initializeNegotiate capabilities
tools/listList available tools
tools/callExecute a tool
resources/listList available resources
resources/readRead resource content
prompts/listList available prompts
prompts/getGet 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:

CodeMeaningWhen Used
-32700Parse errorInvalid JSON
-32600Invalid requestMalformed request
-32601Method not foundUnknown method
-32602Invalid paramsBad parameters
-32603Internal errorServer error
-32001UnauthorizedAuth 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

  1. Create new POST request
  2. Set URL to MCP endpoint
  3. Set headers: Content-Type: application/json
  4. 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

Learn more about testing →

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


Learn More: Visit modelcontextprotocol.io for the official specification.