MCP Server Architecture
System design documentation for the @muzie/mcp-server package.
Overview
The MCP Server provides AI-powered meeting intelligence through the Model Context Protocol (MCP). It exposes 10 MCP tools that internally use 28 primitive functions for querying meetings, recordings, transcriptions, and collaboration networks.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Client Layer │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ Claude Desktop│ │ HTTP Client │ │ Custom MCP │ │
│ │ (Streamable │ │ (cURL, etc.) │ │ Client │ │
│ │ HTTP) │ │ │ │ │ │
│ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ │
│ │ │ │ │
└──────────┼──────────────────┼──────────────────┼────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Transport Layer │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Streamable HTTP (Recommended) │ │
│ │ GET/POST/DELETE /mcp │ Mcp-Session-Id header │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Legacy SSE (Deprecated) │ │
│ │ GET /mcp/sse │ POST /mcp/messages │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Authentication Layer │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ OAuth 2.1 │ │ MCP Token │ │ Email + API Key│ │
│ │ (PKCE) │ │ (64-char hex) │ │ (Internal) │ │
│ │ │ │ │ │ │ │
│ │ Claude Desktop │ │ External APIs │ │ Internal svc │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ @muzie/mcp-server │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌────────────────────────┐ │
│ │ SmartRouter │ │ MCPClient │ │ MCPAgentOrchestrator │ │
│ │ (Routing) │ │ (Bridge) │ │ (Complex Queries) │ │
│ └──────────────────┘ └──────────────────┘ └────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ MCP Tools (10) │ │
│ │ natural_query │ query_data │ agent_query │ summarize_meeting │ │
│ │ search_content │ query_meeting_context │ start_meeting │ │
│ │ create_room │ create_schedule │ cancel_schedule │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Primitive Functions (28) │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Data │ │ Search │ │ Graph │ │ AI │ │ Actions │ │ │
│ │ │ Queries │ │ Content │ │ Analysis│ │ Helpers │ │ (CRUD) │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Security & Authorization │ │
│ │ buildSecurityContext() │ applyAuthorizationFilters() │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘
Transport Architecture
Streamable HTTP (Recommended)
The primary transport for Claude Desktop and modern clients:
┌─────────────────────────────────────────────────────────────────┐
│ Streamable HTTP Transport │
│ │
│ Client Server │
│ │ │ │
│ │ POST /mcp (initialize) │ │
│ │──────────────────────────────>│ │
│ │ │ │
│ │ 200 + Mcp-Session-Id header │ │
│ │<──────────────────────────────│ │
│ │ │ │
│ │ POST /mcp (tools/call) │ │
│ │ + Mcp-Session-Id header │ │
│ │──────────────────────────────>│ │
│ │ │ │
│ │ 200 + JSON-RPC response │ │
│ │<──────────────────────────────│ │
│ │ │ │
│ │ DELETE /mcp │ │
│ │ + Mcp-Session-Id header │ │
│ │──────────────────────────────>│ Close session │
│ │ │ │
└─────────────────────────────────────────────────────────────────┘
Legacy SSE (Deprecated)
Separate endpoints for backward compatibility:
┌─────────────────────────────────────────────────────────────────┐
│ Legacy SSE Transport │
│ │
│ Client Server │
│ │ │ │
│ │ GET /mcp/sse │ │
│ │──────────────────────────────>│ │
│ │ │ │
│ │ SSE stream + sessionId │ │
│ │<━━━━━━━━━━━━━━━━━━━━━━━━━━━━━│ (Keep-alive) │
│ │ │ │
│ │ POST /mcp/messages │ │
│ │ ?sessionId=xxx │ │
│ │──────────────────────────────>│ │
│ │ │ │
│ │ SSE event with response │ │
│ │<━━━━━━━━━━━━━━━━━━━━━━━━━━━━━│ │
│ │ │ │
└─────────────────────────────────────────────────────────────────┘
Authentication Architecture
OAuth 2.1 Flow (Claude Desktop)
┌─────────────────────────────────────────────────────────────────────────────┐
│ OAuth 2.1 with PKCE │
│ │
│ Claude Desktop MCP Server Browser │
│ │ │ │ │
│ │ POST /mcp (no auth) │ │ │
│ │──────────────────────────────>│ │ │
│ │ │ │ │
│ │ 401 + WWW-Authenticate │ │ │
│ │<──────────────────────────────│ │ │
│ │ │ │ │
│ │ GET /.well-known/oauth-* │ │ │
│ │──────────────────────────────>│ │ │
│ │ │ │ │
│ │ Discovery metadata │ │ │
│ │<──────────────────────────────│ │ │
│ │ │ │ │
│ │ │ Opens browser │ │
│ │───────────────────────────────────────────────────────────>│ │
│ │ │ │ │
│ │ │ User logs in │ │
│ │ │<────────────────────────────│ │
│ │ │ │ │
│ │ Authorization code │ │ │
│ │<──────────────────────────────│ │ │
│ │ │ │ │
│ │ POST /oauth/token │ │ │
│ │ + code + code_verifier │ │ │
│ │──────────────────────────────>│ │ │
│ │ │ │ │
│ │ Access token + refresh token │ │ │
│ │<──────────────────────────────│ │ │
│ │ │ │ │
│ │ POST /mcp (+ Bearer token) │ │ │
│ │──────────────────────────────>│ Authenticated requests │ │
│ │ │ │ │
└─────────────────────────────────────────────────────────────────────────────┘
Authentication Priority
┌───────────────────────────────────────────────────────────────┐
│ Authentication Flow │
│ │
│ Request arrives │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Has Bearer │ Yes ┌─────────────────┐ │
│ │ token? │─────>│ Try OAuth JWT │ │
│ └────────┬────────┘ │ validation │ │
│ │ No └────────┬────────┘ │
│ ▼ │ │
│ ┌─────────────────┐ │ Failed │
│ │ Has 64-char │ ▼ │
│ │ hex token? │ Yes ┌─────────────────┐ │
│ └────────┬────────┘─────>│ Try MCP Token │ │
│ │ No │ validation │ │
│ ▼ └────────┬────────┘ │
│ ┌─────────────────┐ │ Failed │
│ │ Has x-user-email│ ▼ │
│ │ + X-API-Key? │ Yes ┌─────────────────┐ │
│ └────────┬────────┘─────>│ Validate email │ │
│ │ No │ + API key │ │
│ ▼ └────────┬────────┘ │
│ ┌─────────────────┐ │ │
│ │ Return 401 │ ▼ │
│ │ + OAuth hint │ ┌─────────────────┐ │
│ └─────────────────┘ │ Authenticated │ │
│ │ Security Context│ │
│ └─────────────────┘ │
└───────────────────────────────────────────────────────────────┘
Component Architecture
Dependency Injection Layer
The package uses a module-scoped dependency store initialized at startup:
// Internal dependency store
let _deps = null;
export function setDependencies(deps) {
_deps = deps;
}
export function getDependencies() {
if (!_deps) {
throw new Error('MCP Server not initialized. Call createMCPServer() first.');
}
return _deps;
}
Components access dependencies via getDependencies() at runtime:
// Inside a primitive tool
const { models, services } = getDependencies();
const { Room, Schedule } = models;
const { UnifiedAIService } = services;
Query Routing Flow (SmartRouter)
┌─────────────────────┐
│ User Query │
│ "Show my meetings │
│ from last week" │
└──────────┬──────────┘
│
▼
┌──────────────────────┐
│ SmartRouter │
│ .analyze() │
└──────────┬───────────┘
│
┌─────┼─────┬─────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐ ┌────────┐
│DIRECT│ │SIMPLE│ │AGENT │ │CLASSIFY│
└──┬───┘ └──┬───┘ └──┬───┘ └───┬────┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐ ┌────────┐
│Action│ │Single│ │Multi │ │Intent │
│Tool │ │Query │ │Step │ │Classify│
└──────┘ └──────┘ └──────┘ └────────┘
Route Types
| Route | When Used | Example |
|---|---|---|
| DIRECT | Single action, no data fetch | "Start a meeting" |
| SIMPLE | Single database query | "Show my rooms" |
| AGENT | Multi-step reasoning | "Find meetings with John and summarize" |
| CLASSIFY | Ambiguous intent | "Help me with my schedule" |
Agent Execution Flow (MCPAgentOrchestrator)
For complex queries requiring multi-step reasoning:
┌──────────────────────────────────────────────────────────────┐
│ MCPAgentOrchestrator │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Iteration Loop │ │
│ │ (max 7 iterations, 55s timeout) │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ THINKING │ -> │TOOL_CALL │ -> │TOOL_RESULT│ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ Analyze │ │ Execute │ │ Process │ │ │
│ │ │ context │ │ tool │ │ results │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │ │ │
│ │ └───────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────┐ │ │
│ │ │ RESPONSE │ │ │
│ │ │ │ │ │
│ │ │ Generate │ │ │
│ │ │ final │ │ │
│ │ │ answer │ │ │
│ │ └──────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
Step Types
| Step | Description |
|---|---|
THINKING |
AI reasoning about the current state |
TOOL_CALL |
Decision to execute a specific tool |
TOOL_RESULT |
Result from tool execution |
RESPONSE |
Final formatted response to user |
ERROR |
Error during execution |
Security Context Flow
┌─────────────────────────────────────────────────────────────────┐
│ Security Flow │
│ │
│ ┌─────────────┐ │
│ │ User Auth │ OAuth/Token/API Key validation │
│ │ (Transport) │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ buildSecurityContext│ │
│ │ │ │
│ │ - Resolve userId │ │
│ │ - Check org owner │ │
│ │ - Get accessible │ │
│ │ user IDs │ │
│ └──────────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ Security Context │ │
│ │ { │ │
│ │ userEmail, │ │
│ │ userId, │ │
│ │ apiKey, │ ◄── Passed to all tool calls │
│ │ isOrgOwner, │ │
│ │ orgUserIds │ │
│ │ } │ │
│ └──────────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ applyAuthorization │ │
│ │ Filters() │ │
│ │ │ │
│ │ - Filter by apiKey │ Multi-tenant isolation │
│ │ - Filter by userId │ User-level access │
│ │ - Check ownership │ Resource ownership │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Tool Execution Pipeline
┌───────────────────────────────────────────────────────────────┐
│ Tool Execution Pipeline │
│ │
│ ┌──────────────┐ │
│ │ Tool Request │ │
│ │ { │ │
│ │ tool, │ │
│ │ args, │ │
│ │ context │ │
│ │ } │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Validate │ --> │ Authorization│ │
│ │ Parameters │ │ Check │ │
│ └──────────────┘ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Tool Handler │ │
│ │ │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │
│ │ │ Build │->│ Execute │->│ Format │ │ │
│ │ │ Query │ │ Database │ │ Response │ │ │
│ │ │ │ │ Operation │ │ │ │ │
│ │ └───────────┘ └───────────┘ └───────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Tool Result │ │
│ │ { │ │
│ │ success, │ │
│ │ data, │ │
│ │ actionType │ │
│ │ } │ │
│ └──────────────┘ │
└───────────────────────────────────────────────────────────────┘
Data Models
Multi-Tenant Structure
┌─────────────────────────────────────────────────────────────┐
│ Multi-Tenant Data Model │
│ │
│ Organization (apiKey) │
│ ├── UserProfile │
│ │ ├── userId (cleaned email) │
│ │ ├── email │
│ │ └── roles │
│ │ │
│ ├── Rooms │
│ │ ├── apiKey (tenant) │
│ │ ├── owner (userId) │
│ │ └── participants │
│ │ │
│ ├── Schedules │
│ │ ├── apiKey (tenant) │
│ │ ├── organizer (userId) │
│ │ └── attendees │
│ │ │
│ ├── Recordings │
│ │ ├── apiKey (tenant) │
│ │ ├── roomSession │
│ │ └── transcription │
│ │ │
│ └── Files │
│ ├── apiKey (tenant) │
│ ├── uploadedBy (userId) │
│ └── roomSession │
└─────────────────────────────────────────────────────────────┘
Authorization Hierarchy
Organization Owner (org-owner role)
├── Can access ALL data in organization
├── Can manage other users
└── Full CRUD on all resources
Organization Member (org-member role)
├── Can access own data
├── Can access shared rooms/files
└── Limited to assigned permissions
Team Member (team-member role)
├── Can access team data
├── Subject to team permissions
└── orgOwner points to org owner's userId
Guest
├── Room-specific access only
├── No persistent data access
└── Token-based authentication
Deployment Architecture
Single-Instance Mode
The server runs in PM2 fork mode (single instance) for simplicity:
┌─────────────────────────────────────────────────────────────┐
│ Production Deployment │
│ │
│ EC2 Instance │
│ ├── PM2 (Fork Mode) │
│ │ └── server/index.js (Single Process) │
│ │ ├── Express HTTP Server │
│ │ ├── Streamable HTTP Transport │
│ │ ├── Legacy SSE Transport │
│ │ ├── OAuth 2.1 Endpoints │
│ │ └── In-Memory Session Store │
│ │ │
│ └── nginx (Reverse Proxy) │
│ └── SSL termination │
│ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ External Services │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ MongoDB │ │ OpenAI │ │ xAI │ │
│ │ (Atlas) │ │ API │ │ (Fallback) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Session Management
Sessions are stored in memory (no Redis required):
- Streamable HTTP: Sessions keyed by
Mcp-Session-IdUUID - Legacy SSE: Sessions keyed by connection-based session ID
- Session lifecycle: Created on first request, cleaned up on disconnect/DELETE
Performance Considerations
Query Optimization
- Pagination - All list queries support limit/offset
- Projection - Only fetch required fields
- Indexing - MongoDB indexes on apiKey, userId, timestamps
- Caching - AI client instances cached per provider
Agent Efficiency
- Max Iterations - Default 7 steps to prevent runaway
- Timeout - 55s timeout for complex queries
- Token Limits - 1500 max output tokens per step
- Early Exit - Stops when answer is found
Memory Management
- Lazy Initialization - Services initialized on first use
- Connection Pooling - MongoDB connection reuse
- Client Caching - AI clients cached and reused
- Session Cleanup - Automatic cleanup on disconnect
Related Documentation
- Hosted Server Guide - Connect to hosted servers
- Getting Started - Quick start guide
- Tools Reference - All 10 MCP tools and 28 primitives
- Authentication - OAuth 2.1, tokens, API keys
- HTTP Transport - Streamable HTTP and SSE