Skip to content

Commit 767ffff

Browse files
author
Lasim
committed
docs: Update token consumption metrics and enhance session management details in OAuth authentication documentation
1 parent 656ba6d commit 767ffff

2 files changed

Lines changed: 92 additions & 4 deletions

File tree

development/satellite/hierarchical-router.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,8 @@ Next time the client calls `discover_mcp_tools`, the new tools are automatically
527527
| Metric | Traditional | Hierarchical | Reduction |
528528
|--------|-------------|--------------|-----------|
529529
| Tools Exposed | 150 | 2 | 98.7% |
530-
| Tokens Consumed | 75,000 | 350 | 99.5% |
531-
| Context Available | 62.5% | 99.8% | +37.3% |
530+
| Tokens Consumed | 75,000 | 1372 | 98.2% |
531+
| Context Available | 62.5% | 99.3% | +36.8% |
532532

533533
### Search Performance
534534

@@ -541,8 +541,8 @@ Next time the client calls `discover_mcp_tools`, the new tools are automatically
541541

542542
**Claude Code Example:**
543543
- Before: 82,000 tokens (41%) consumed by MCP tools
544-
- After: 350 tokens (0.175%) consumed by meta-tools
545-
- Result: **81,650 tokens freed for actual work**
544+
- After: 1372 tokens (0.686%) consumed by meta-tools
545+
- Result: **80,628 tokens freed for actual work**
546546

547547
## Implementation Status
548548

development/satellite/oauth-authentication.mdx

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,94 @@ const response = await fetch(`${backendUrl}/api/oauth2/introspect`, {
268268
- `active: false` - Token invalid, return authentication error
269269
- Team context includes: team_id, team_name, team_role, team_permissions
270270

271+
## Session Management and Security Model
272+
273+
### MCP Sessions vs OAuth Authentication
274+
275+
The satellite implements a two-layer security model that separates authentication from session management:
276+
277+
**Authentication Layer (OAuth Bearer Token):**
278+
- Primary security mechanism for all requests
279+
- Validates user identity, team membership, and permissions
280+
- Enforced by authentication middleware before session handling
281+
- Team isolation enforced at this layer via token introspection
282+
283+
**Session Layer (MCP Session ID):**
284+
- Transport-level identifier for HTTP/SSE connection routing
285+
- NOT a security credential - purely for protocol state management
286+
- Can be safely reused because security comes from Bearer token
287+
- Managed by StreamableHTTPServerTransport from MCP SDK
288+
289+
### Session Resurrection After Satellite Restart
290+
291+
When a satellite restarts (deployments, updates, crashes), MCP sessions are lost because they live in memory. The satellite implements transparent session resurrection to avoid forcing users to manually reconnect:
292+
293+
**How Session Resurrection Works:**
294+
1. Client sends request with old session ID (from before restart)
295+
2. Satellite validates Bearer token FIRST (authentication layer)
296+
3. If session ID is stale, satellite creates new Server + Transport with same session ID
297+
4. Bootstrap transport with synthetic `initialize` request
298+
5. Process actual client request normally
299+
6. Client continues without reconnection
300+
301+
**Implementation Details:**
302+
```typescript
303+
// Authentication happens FIRST (line 558 in mcp-server-wrapper.ts)
304+
const authHeader = request.headers['authorization'];
305+
const token = authHeader?.replace(/^Bearer\s+/i, '');
306+
307+
if (!token) {
308+
return reply.status(401).send({
309+
jsonrpc: '2.0',
310+
error: { code: -32001, message: 'Authentication required' },
311+
id: null
312+
});
313+
}
314+
315+
// Validate token via introspection BEFORE session handling
316+
const introspectionResult = await this.tokenIntrospectionService.validateToken(token);
317+
318+
if (!introspectionResult.valid) {
319+
return reply.status(401).send({
320+
jsonrpc: '2.0',
321+
error: { code: -32002, message: 'Invalid token' },
322+
id: null
323+
});
324+
}
325+
326+
// NOW handle session resurrection (lines 616-722)
327+
const sessionId = request.headers['mcp-session-id'];
328+
const existingTransport = this.transports.get(sessionId);
329+
330+
if (!existingTransport && sessionId) {
331+
// Create new Server + Transport with same session ID
332+
server = new Server({ name: 'deploystack-satellite', version: '1.0.0' });
333+
334+
transport = new StreamableHTTPServerTransport({
335+
sessionIdGenerator: () => sessionId, // Reuse old session ID
336+
onsessioninitialized: (restoredSessionId) => {
337+
this.transports.set(restoredSessionId, { transport, server });
338+
}
339+
});
340+
341+
await server.connect(transport);
342+
343+
// Bootstrap transport with synthetic initialize request
344+
const syntheticInitRequest = {
345+
jsonrpc: '2.0',
346+
id: 0,
347+
method: 'initialize',
348+
params: {
349+
protocolVersion: '2024-11-05',
350+
capabilities: {},
351+
clientInfo: { name: 'resurrected-session', version: '1.0.0' }
352+
}
353+
};
354+
355+
await transport.handleRequest(request.raw, mockRes, syntheticInitRequest);
356+
}
357+
```
358+
271359
## Team-Aware Tool Discovery
272360

273361
### Tool Filtering Implementation

0 commit comments

Comments
 (0)