Connection Proxy Endpoint
Connect MCP clients directly to upstream MCP servers through deco CMS
Overview
The Connection Proxy endpoint ( /mcp/:connectionId ) enables MCP clients (like Cursor, Claude Desktop, or custom applications) to connect directly to a specific upstream MCP server through deco CMS. This endpoint acts as a secure, observable proxy that handles authentication, authorization, credential management, and monitoring.
Endpoint
POST https://your-mesh-instance.com/mcp/:connectionId
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
connectionId | string (UUID) | Required | The unique identifier of the connection to proxy requests to |
Authentication
The Connection Proxy requires authentication using one of:
- OAuth Bearer Token:
Authorization: Bearer <token> - API Key:
Authorization: Bearer <api_key>
When unauthenticated, the endpoint returns a 401 response with an WWW-Authenticate header containing OAuth discovery metadata:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="mcp",resource_metadata="https://your-mesh-instance.com/mcp/:connectionId/.well-known/oauth-protected-resource"
Clients supporting OAuth 2.1 can use the resource metadata URL to discover authorization endpoints and complete the OAuth flow automatically.
How It Works
When a client sends an MCP request through the Connection Proxy:
- Authentication: deco CMS verifies the client’s credentials (OAuth token or API key)
- Connection Lookup: deco CMS retrieves the connection configuration and verifies it’s active
- Authorization: deco CMS checks if the client has permission to invoke the requested tool
- Credential Injection: deco CMS decrypts stored credentials and injects them into the upstream request
- Request Proxying: deco CMS forwards the MCP request to the upstream server
- Monitoring: deco CMS logs metrics (duration, status, errors) for observability
- Response Return: deco CMS returns the upstream server’s response to the client
Request Format
The Connection Proxy accepts standard MCP protocol requests. The request body should be a JSON-RPC 2.0 message following the MCP specification.
Example: List Tools
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
Example: Call Tool
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "github_create_issue",
"arguments": {
"repo": "myorg/myrepo",
"title": "Bug report",
"body": "Description of the bug"
}
}
}
Response Format
Responses follow standard MCP protocol format:
Success Response
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Issue created successfully: #123"
}
]
}
}
Error Response
{
"jsonrpc": "2.0",
"id": 2,
"error": {
"code": -32603,
"message": "Tool execution failed"
}
}
Authorization
The Connection Proxy enforces fine-grained authorization using deco CMS’s permission system:
- Per-Tool Permissions: Users must have explicit permission for each tool they invoke
- Connection-Scoped: Permissions are scoped to the specific connection
- Role-Based: Permissions are inherited from user roles and organization settings
Permission Format
Permissions are stored in the format:
{
"<connectionId>": ["tool_name_1", "tool_name_2"]
}
Public Tools
Tools can be marked as public using metadata:
{
"_meta": {
"mcp.mesh": {
"public_tool": true
}
}
}
Public tools allow unauthenticated access and bypass authorization checks.
Error Responses
| Status Code | Description | Example Scenario |
|---|---|---|
401 | Unauthorized | No valid OAuth token or API key provided |
403 | Forbidden | User lacks permission to invoke the requested tool |
404 | Not Found | Connection ID doesn’t exist or user doesn’t have access |
500 | Internal Server Error | Unexpected error during request processing |
503 | Service Unavailable | Connection is inactive or upstream server is unreachable |
Streaming Support
The Connection Proxy supports streaming tool responses for HTTP-based connections:
Streamable Tool Endpoint
POST https://your-mesh-instance.com/mcp/:connectionId/call-tool/:toolName
This endpoint allows tools to stream responses back to the client, useful for long-running operations or large data transfers.
Streaming is only supported for HTTP connections. STDIO and VIRTUAL connections fall back to regular tool calls.
Monitoring & Observability
Every request through the Connection Proxy generates:
Metrics
- Duration Histograms:
connection.proxy.durationandconnection.proxy.streamable.duration - Request Counters:
connection.proxy.requestsandconnection.proxy.streamable.requests - Error Counters:
connection.proxy.errorsandconnection.proxy.streamable.errors
All metrics include labels:
connection.id: The connection UUIDtool.name: The tool being invokedstatus: success or error
Traces
OpenTelemetry spans are created for:
mcp.proxy.callTool: Regular tool invocationsmcp.proxy.callStreamableTool: Streaming tool invocations
Traces include attributes:
connection.id: Connection identifiertool.name: Tool namerequest.id: Unique request identifier
Configuration Options
Connections can be configured with:
Timeout Settings
The default timeout for tool calls is 5 minutes (300,000ms). This can be adjusted per connection based on tool execution characteristics.
Custom Headers
Connections can include custom HTTP headers for authentication or routing:
{
"connection_headers": {
"headers": {
"X-Custom-Header": "value"
}
}
}
Use Cases
Direct MCP Access
Connect Cursor or Claude Desktop directly to a specific upstream MCP:
Cursor Configuration:
{
"mcpServers": {
"github-production": {
"url": "https://mesh.example.com/mcp/conn_abc123",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Tool-Specific Clients
Build custom clients that need access to a specific MCP server’s tools without Virtual MCP composition:
const response = await fetch('https://mesh.example.com/mcp/conn_abc123', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'tools/call',
params: {
name: 'database_query',
arguments: { query: 'SELECT * FROM users LIMIT 10' }
}
})
});
Multi-Tenant Isolation
Each connection is organization-scoped, providing natural tenant isolation:
Organization A → conn_123 (GitHub Org A) → GitHub Tools (Org A only)
Organization B → conn_456 (GitHub Org B) → GitHub Tools (Org B only)
Connection States
Connections have a status field that affects proxy behavior:
active: Connection is ready to proxy requestsinactive: Connection is disabled; proxy returns503errorerror: Connection has configuration issues; proxy may fail
Security Considerations
Credential Handling
- Encrypted at Rest: Credentials are stored encrypted using AES-256-GCM
- Decrypted Just-in-Time: Credentials are only decrypted when proxying requests
- Never Exposed to Clients: Clients never receive upstream credentials
Request Validation
- Schema Validation: Tool arguments are validated against input schemas
- Rate Limiting: (Planned) Per-connection and per-user rate limits
- Audit Logging: All tool invocations are logged with user identity
Network Security
- TLS Required: All connections to upstream servers use HTTPS
- Certificate Validation: SSL certificates are validated by default
- Proxy Headers: Upstream servers receive authenticated requests with credentials
Comparison with Other Endpoints
| Endpoint | Use Case | Tools Available |
|---|---|---|
/mcp/:connectionId | Direct access to one upstream MCP | All tools from that connection only |
/mcp/gateway/:agentId | Curated tool surface (agent/virtual MCP) | Tools from multiple connections, composed |
/mcp/self | Management operations | deco CMS management tools only |
For most production use cases, use Agents ( /mcp/gateway/:agentId ) instead of direct connection proxies. Agents provide better control over tool exposure, support context and resources, and allow multi-connection composition.
Related
- Connections - Understanding the Connection abstraction
- Virtual MCPs - Compose multiple connections into agents
- API Keys - Authentication setup
- Monitoring - Observability and metrics
Found an error or want to improve this page?
Edit this page