336 lines
9.1 KiB
Markdown
336 lines
9.1 KiB
Markdown
# MCP Gateway Architecture
|
|
|
|
## Before vs After
|
|
|
|
### BEFORE (Claude Only)
|
|
```
|
|
┌─────────────────┐
|
|
│ Claude.ai │
|
|
└────────┬────────┘
|
|
│ MCP Protocol
|
|
▼
|
|
┌─────────────────────────────────────┐
|
|
│ MCP Gateway (Port 4444) │
|
|
│ - OAuth 2.1 provider │
|
|
│ - Tool aggregation │
|
|
│ - Session management │
|
|
└─────────────────────────────────────┘
|
|
│
|
|
┌────┴────┬────────┬──────────┐
|
|
▼ ▼ ▼ ▼
|
|
ERPNext Wave TrueNAS Home Assistant
|
|
ERP Finance Storage Automation
|
|
```
|
|
|
|
### AFTER (Claude + Open-UI)
|
|
```
|
|
┌─────────────────┐ ┌─────────────────┐
|
|
│ Claude.ai │ │ Open-UI │
|
|
└────────┬────────┘ └────────┬────────┘
|
|
│ MCP Protocol │ OpenAI API
|
|
│ │
|
|
└───────────────┬───────────┘
|
|
▼
|
|
┌─────────────────────────────────────────────┐
|
|
│ MCP Gateway (Port 4444) │
|
|
│ ┌─────────────────────────────────────┐ │
|
|
│ │ OAuth 2.1 (for Claude) │ │
|
|
│ │ /oauth/* endpoints │ │
|
|
│ │ /mcp protocol │ │
|
|
│ └─────────────────────────────────────┘ │
|
|
│ ┌─────────────────────────────────────┐ │
|
|
│ │ OpenAI API (for Open-UI) [NEW] │ │
|
|
│ │ /v1/models │ │
|
|
│ │ /v1/chat/completions │ │
|
|
│ │ Bearer token auth │ │
|
|
│ └─────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────┘
|
|
│
|
|
┌────┴────┬────────┬──────────┐
|
|
▼ ▼ ▼ ▼
|
|
ERPNext Wave TrueNAS Home Assistant
|
|
ERP Finance Storage Automation
|
|
```
|
|
|
|
## New Components Added
|
|
|
|
### 1. OpenAI Routes Module
|
|
**File**: `gateway-proxy/openai_routes.py`
|
|
|
|
```python
|
|
async def list_models() # GET /v1/models
|
|
async def chat_completions() # POST /v1/chat/completions
|
|
async def _get_mcp_tools() # Fetch available tools
|
|
async def _stream_response() # Stream responses to client
|
|
```
|
|
|
|
### 2. OpenAI Adapter (Optional)
|
|
**File**: `openai_adapter.py`
|
|
|
|
High-level abstraction for tool conversion and MCP calls:
|
|
```python
|
|
class OpenAIAdapter:
|
|
async def get_mcp_tools() # Get tools from MCP
|
|
async def call_mcp_tool() # Execute a tool
|
|
def _convert_mcp_tool_to_openai() # Convert schemas
|
|
async def chat_completions() # Handle chat requests
|
|
```
|
|
|
|
### 3. Gateway Proxy Enhancement
|
|
**File**: `gateway-proxy/gateway_proxy.py` (modified)
|
|
|
|
```python
|
|
# Imports
|
|
from openai_routes import chat_completions, list_models
|
|
|
|
# Routes
|
|
Route("/v1/models", openai_models, methods=["GET"]),
|
|
Route("/v1/chat/completions", openai_completions, methods=["POST"]),
|
|
```
|
|
|
|
## Request Flow
|
|
|
|
### Claude → MCP Gateway → Tools
|
|
|
|
```
|
|
1. Claude sends MCP request
|
|
↓
|
|
2. OAuth 2.1 validation
|
|
↓
|
|
3. Handle /mcp endpoint
|
|
↓
|
|
4. Parse MCP protocol
|
|
↓
|
|
5. Route to appropriate MCP backend
|
|
↓
|
|
6. Execute tool
|
|
↓
|
|
7. Return MCP response
|
|
↓
|
|
8. Claude processes result
|
|
```
|
|
|
|
### Open-UI → OpenAI API → Tools [NEW]
|
|
|
|
```
|
|
1. Open-UI sends OpenAI request (POST /v1/chat/completions)
|
|
├─ Headers: Authorization: Bearer TOKEN
|
|
├─ Body: { model, messages, stream }
|
|
↓
|
|
2. Bearer token validation
|
|
├─ Extract token from Authorization header
|
|
├─ Hash and check against ACCESS_TOKENS
|
|
↓
|
|
3. Parse OpenAI request
|
|
├─ Extract messages
|
|
├─ Determine if stream needed
|
|
↓
|
|
4. Fetch available MCP tools
|
|
├─ Call MCP gateway: tools/list
|
|
├─ Convert to OpenAI format
|
|
↓
|
|
5. Build OpenAI response
|
|
├─ List available tools
|
|
├─ Format as OpenAI compatible
|
|
↓
|
|
6. Return response (or stream)
|
|
├─ If stream=true: SSE format
|
|
├─ If stream=false: JSON response
|
|
↓
|
|
7. Open-UI receives and displays
|
|
```
|
|
|
|
## API Compatibility
|
|
|
|
### Endpoints
|
|
| Endpoint | Client | Protocol | Auth |
|
|
|----------|--------|----------|------|
|
|
| `/mcp` | Claude | MCP 2.0 | OAuth 2.1 |
|
|
| `/v1/models` | Open-UI | OpenAI | Bearer Token |
|
|
| `/v1/chat/completions` | Open-UI | OpenAI | Bearer Token |
|
|
| `/health` | Any | JSON | None |
|
|
| `/status` | Any | JSON | None |
|
|
|
|
### Authentication
|
|
|
|
**Claude (MCP):**
|
|
- Uses OAuth 2.1
|
|
- Token stored in `ACCESS_TOKENS` dictionary
|
|
- Hash-based validation
|
|
|
|
**Open-UI (OpenAI):**
|
|
- Uses Bearer tokens
|
|
- Token in `Authorization: Bearer` header
|
|
- Same hash-based validation
|
|
|
|
### Response Formats
|
|
|
|
**Claude (MCP):**
|
|
```json
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"result": { ... },
|
|
"id": 1
|
|
}
|
|
```
|
|
|
|
**Open-UI (OpenAI):**
|
|
```json
|
|
{
|
|
"id": "chatcmpl-...",
|
|
"object": "chat.completion",
|
|
"created": 1234567890,
|
|
"model": "mcp-gateway",
|
|
"choices": [{ "message": {...} }],
|
|
"usage": {...}
|
|
}
|
|
```
|
|
|
|
## Streaming Support
|
|
|
|
### Open-UI Streaming Format
|
|
Server-Sent Events (SSE):
|
|
```
|
|
data: {"id":"...", "object":"chat.completion.chunk", "choices":[...]}
|
|
|
|
data: [DONE]
|
|
```
|
|
|
|
Implemented in `_stream_response()` function.
|
|
|
|
## Tool Execution Flow (Future Enhancement)
|
|
|
|
Current: **Tools are listed only**
|
|
```
|
|
Open-UI asks: "What tools are available?"
|
|
Gateway responds: "Here are the tools..."
|
|
```
|
|
|
|
Future: **Tools will be executable**
|
|
```
|
|
Open-UI asks: "Create invoice for $100"
|
|
Gateway:
|
|
1. Intercepts request
|
|
2. Calls tool with parameters
|
|
3. Returns result
|
|
4. Open-UI shows outcome
|
|
```
|
|
|
|
To enable, modify `chat_completions()` to:
|
|
1. Parse `tool_use` in messages
|
|
2. Call `_call_mcp_tool()`
|
|
3. Return structured tool responses
|
|
|
|
## Security Architecture
|
|
|
|
### Token Management
|
|
```
|
|
┌─────────────────┐
|
|
│ Bearer Token │ (64-char urlsafe)
|
|
└────────┬────────┘
|
|
│ SHA256 hash
|
|
▼
|
|
┌─────────────────┐
|
|
│ Token Hash │ (stored in ACCESS_TOKENS)
|
|
└────────┬────────┘
|
|
│ Compared on each request
|
|
▼
|
|
┌─────────────────┐
|
|
│ Request Valid? │ ✅ / ❌
|
|
└─────────────────┘
|
|
```
|
|
|
|
### Multi-Tenant Ready
|
|
Each Open-UI instance can have its own token:
|
|
```python
|
|
ACCESS_TOKENS = {
|
|
"hash_of_token_1": {"client": "open-ui-1"},
|
|
"hash_of_token_2": {"client": "open-ui-2"},
|
|
"hash_of_claude": {"client": "claude.ai"}
|
|
}
|
|
```
|
|
|
|
## Deployment Architecture
|
|
|
|
### Single Container
|
|
```
|
|
Docker Container
|
|
├─ Python runtime
|
|
├─ Starlette web framework
|
|
├─ gateway_proxy.py
|
|
│ ├─ OAuth 2.1 endpoints
|
|
│ ├─ MCP routing
|
|
│ └─ OpenAI routes (NEW)
|
|
├─ openai_routes.py (NEW)
|
|
└─ openai_adapter.py (NEW)
|
|
```
|
|
|
|
### Multi-Backend
|
|
```
|
|
Gateway connects to:
|
|
├─ ERPNext (REST API)
|
|
├─ Wave Finance (GraphQL)
|
|
├─ TrueNAS (REST API)
|
|
└─ Home Assistant (REST API)
|
|
```
|
|
|
|
Each as separate MCP servers.
|
|
|
|
## Performance Considerations
|
|
|
|
### Current Limitations
|
|
- No response caching
|
|
- No rate limiting
|
|
- Sequential tool discovery
|
|
- Full tool list returned each request
|
|
|
|
### Future Optimizations
|
|
- Cache tool definitions (5 min TTL)
|
|
- Rate limit by token
|
|
- Parallel backend queries
|
|
- Filter tools by capability
|
|
- Batch tool calls
|
|
|
|
## Monitoring & Observability
|
|
|
|
### Log Lines Added
|
|
```
|
|
INFO - OpenAI-compatible endpoints registered at /v1/*
|
|
INFO - Bearer token validated
|
|
INFO - MCP tools fetched: N tools available
|
|
ERROR - Unauthorized access attempt
|
|
ERROR - Tool call failed: X
|
|
```
|
|
|
|
### Health Checks
|
|
```bash
|
|
# Gateway health
|
|
GET /health
|
|
|
|
# Full status
|
|
GET /status
|
|
```
|
|
|
|
## Future Enhancements
|
|
|
|
### Phase 2: Tool Execution
|
|
- [ ] Parse tool_use in messages
|
|
- [ ] Execute MCP tools
|
|
- [ ] Return structured results
|
|
|
|
### Phase 3: Advanced Features
|
|
- [ ] Function parameter validation
|
|
- [ ] Error recovery
|
|
- [ ] Async tool execution
|
|
- [ ] Caching layer
|
|
|
|
### Phase 4: Enterprise Ready
|
|
- [ ] Rate limiting
|
|
- [ ] Audit logging
|
|
- [ ] Metrics/Prometheus
|
|
- [ ] Multi-tenancy
|
|
- [ ] Custom LLM routing
|
|
|
|
---
|
|
|
|
**Summary**: Your MCP Gateway now runs a dual-protocol architecture supporting both Claude's MCP protocol and Open-UI's OpenAI API, all from a single gateway service.
|