MCP Protocol Architecture

How Bootspring implements the Model Context Protocol.

Overview#

The Model Context Protocol (MCP) is a standard for AI assistants to interact with external tools and resources. Bootspring implements an MCP server that exposes its functionality to AI clients like Claude.

Protocol Basics#

Communication Flow#

┌─────────────────┐ ┌─────────────────┐ │ AI Client │◄────────────▶│ MCP Server │ │ (Claude, etc.) │ Messages │ (Bootspring) │ └─────────────────┘ └─────────────────┘

Message Types#

TypeDirectionPurpose
initializeClient → ServerEstablish connection
tools/listClient → ServerList available tools
tools/callClient → ServerInvoke a tool
resources/listClient → ServerList available resources
resources/readClient → ServerRead a resource

Bootspring MCP Server#

Server Implementation#

1// mcp-server/src/server.ts 2 3import { Server } from '@modelcontextprotocol/sdk/server'; 4import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio'; 5 6export class BootspringMcpServer { 7 private server: Server; 8 private toolRegistry: ToolRegistry; 9 private resourceRegistry: ResourceRegistry; 10 11 constructor() { 12 this.server = new Server({ 13 name: 'bootspring', 14 version: '1.0.0', 15 }, { 16 capabilities: { 17 tools: {}, 18 resources: {}, 19 }, 20 }); 21 22 this.setupHandlers(); 23 } 24 25 private setupHandlers(): void { 26 // List tools 27 this.server.setRequestHandler('tools/list', async () => ({ 28 tools: this.toolRegistry.list(), 29 })); 30 31 // Call tool 32 this.server.setRequestHandler('tools/call', async (request) => { 33 const { name, arguments: args } = request.params; 34 return this.toolRegistry.call(name, args); 35 }); 36 37 // List resources 38 this.server.setRequestHandler('resources/list', async () => ({ 39 resources: this.resourceRegistry.list(), 40 })); 41 42 // Read resource 43 this.server.setRequestHandler('resources/read', async (request) => { 44 const { uri } = request.params; 45 return this.resourceRegistry.read(uri); 46 }); 47 } 48 49 async start(): Promise<void> { 50 const transport = new StdioServerTransport(); 51 await this.server.connect(transport); 52 } 53}

Tool System#

Tool Definition#

1interface McpTool { 2 name: string; 3 description: string; 4 inputSchema: JsonSchema; 5} 6 7interface ToolHandler { 8 (args: Record<string, unknown>): Promise<ToolResult>; 9}

Registered Tools#

ToolDescription
bootspring_assistNatural language assistant
bootspring_contextGet project context
bootspring_agentInvoke expert agents
bootspring_skillDiscover and apply skills
bootspring_todoManage todos
bootspring_generateRegenerate context
bootspring_workflowWorkflow operations
bootspring_qualityQuality gates
bootspring_prdPRD management
bootspring_loopDevelopment loops
bootspring_seedSeed operations
bootspring_mvpMVP generation
bootspring_memoryAccess memory
bootspring_dashboardDashboard control
bootspring_configConfiguration
bootspring_analyzeCode analysis
bootspring_feedbackSend feedback
bootspring_statusCheck status
bootspring_orchestratorOrchestrate workflows

Tool Implementation Example#

1// mcp-server/src/tools/agent.ts 2 3export const agentTool: McpTool = { 4 name: 'bootspring_agent', 5 description: 'Invoke an expert agent for specialized assistance', 6 inputSchema: { 7 type: 'object', 8 properties: { 9 agent: { 10 type: 'string', 11 description: 'Agent name (e.g., frontend-expert)', 12 }, 13 prompt: { 14 type: 'string', 15 description: 'Task or question for the agent', 16 }, 17 context: { 18 type: 'object', 19 description: 'Additional context', 20 properties: { 21 files: { type: 'array', items: { type: 'string' } }, 22 }, 23 }, 24 }, 25 required: ['agent', 'prompt'], 26 }, 27}; 28 29export async function handleAgentTool( 30 args: { agent: string; prompt: string; context?: object } 31): Promise<ToolResult> { 32 const invoker = new AgentInvoker(); 33 34 const result = await invoker.invoke(args.agent, args.prompt, { 35 files: args.context?.files, 36 }); 37 38 return { 39 content: [{ 40 type: 'text', 41 text: result.response, 42 }], 43 }; 44}

Resource System#

Resource Definition#

1interface McpResource { 2 uri: string; 3 name: string; 4 description: string; 5 mimeType: string; 6}

Registered Resources#

URIDescription
project://contextProject context (CLAUDE.md)
project://configBootspring configuration
project://prdProduct Requirements
project://todosTodo list

Resource Implementation#

1// mcp-server/src/resources/context.ts 2 3export const contextResource: McpResource = { 4 uri: 'project://context', 5 name: 'Project Context', 6 description: 'Generated project context (CLAUDE.md)', 7 mimeType: 'text/markdown', 8}; 9 10export async function readContextResource(): Promise<ResourceContent> { 11 const contextPath = await findContextFile(); 12 13 if (!contextPath) { 14 return { 15 contents: [{ 16 uri: 'project://context', 17 mimeType: 'text/plain', 18 text: 'No context file found. Run `bootspring generate` to create one.', 19 }], 20 }; 21 } 22 23 const content = await fs.readFile(contextPath, 'utf-8'); 24 25 return { 26 contents: [{ 27 uri: 'project://context', 28 mimeType: 'text/markdown', 29 text: content, 30 }], 31 }; 32}

Transport Layer#

Stdio Transport#

For Claude Desktop integration:

// Start with stdio transport bootspring mcp start --stdio

Communication via stdin/stdout with JSON-RPC messages.

HTTP Transport#

For web integrations:

// Start with HTTP transport bootspring mcp start --port=3100

RESTful API with WebSocket support for streaming.

Message Format#

JSON-RPC 2.0#

All MCP messages use JSON-RPC 2.0:

1// Request 2{ 3 "jsonrpc": "2.0", 4 "id": 1, 5 "method": "tools/call", 6 "params": { 7 "name": "bootspring_agent", 8 "arguments": { 9 "agent": "frontend-expert", 10 "prompt": "Create a button component" 11 } 12 } 13} 14 15// Response 16{ 17 "jsonrpc": "2.0", 18 "id": 1, 19 "result": { 20 "content": [{ 21 "type": "text", 22 "text": "Here's a button component..." 23 }] 24 } 25}

Streaming Responses#

For long operations:

1// Progress notification 2{ 3 "jsonrpc": "2.0", 4 "method": "notifications/progress", 5 "params": { 6 "progressToken": "abc123", 7 "progress": 50, 8 "total": 100 9 } 10}

Authentication#

Session Authentication#

1// Initialize with auth 2{ 3 "method": "initialize", 4 "params": { 5 "clientInfo": { 6 "name": "claude-desktop", 7 "version": "1.0.0" 8 }, 9 "capabilities": {} 10 } 11}

API Key Validation#

Tools validate API keys for cloud operations:

1async function validateApiKey(args: ToolArgs): Promise<void> { 2 if (requiresAuth(args)) { 3 const apiKey = await getStoredApiKey(); 4 if (!apiKey) { 5 throw new AuthenticationRequiredError(); 6 } 7 await validateWithApi(apiKey); 8 } 9}

Error Handling#

MCP Error Codes#

CodeMeaning
-32700Parse error
-32600Invalid request
-32601Method not found
-32602Invalid params
-32603Internal error

Bootspring Errors#

CodeMeaning
1001Agent not found
1002Skill not found
1003Authentication required
1004Rate limit exceeded
1005Entitlement required

Client Configuration#

Claude Desktop#

1{ 2 "mcpServers": { 3 "bootspring": { 4 "command": "bootspring", 5 "args": ["mcp", "start", "--stdio"], 6 "cwd": "/path/to/project" 7 } 8 } 9}

VS Code#

{ "bootspring.mcp.enabled": true, "bootspring.mcp.port": 3100 }

Debugging#

Enable Debug Logging#

DEBUG=mcp:* bootspring mcp start --stdio

Log Output#

mcp:server Received: tools/list mcp:server Responding with 19 tools mcp:server Received: tools/call bootspring_agent mcp:tools Invoking agent: frontend-expert mcp:tools Agent completed in 2340ms mcp:server Responding with result

Performance#

Connection Pooling#

MCP server maintains connection pools:

const pool = { maxConnections: 10, idleTimeout: 30000, acquireTimeout: 5000, };

Response Caching#

Cacheable responses are stored:

const cacheConfig = { 'project://context': { ttl: 60000 }, 'project://config': { ttl: 300000 }, };

Security#

Input Validation#

All tool inputs validated against schemas:

1function validateToolInput(tool: McpTool, args: unknown): void { 2 const ajv = new Ajv(); 3 const validate = ajv.compile(tool.inputSchema); 4 5 if (!validate(args)) { 6 throw new InvalidParamsError(validate.errors); 7 } 8}

Sandboxing#

Tool execution is sandboxed:

  • File access limited to project directory
  • Network access controlled
  • Resource limits enforced