fix(security): enforce Tess MCP server identity (#717)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful

This commit was merged in pull request #717.
This commit is contained in:
2026-07-12 22:49:00 +00:00
parent a959b1d6b4
commit 227b73fcdf
3 changed files with 882 additions and 83 deletions

View File

@@ -3,7 +3,11 @@ import { Logger } from '@nestjs/common';
import { fromNodeHeaders } from 'better-auth/node';
import type { Auth } from '@mosaicstack/auth';
import type { NestFastifyApplication } from '@nestjs/platform-fastify';
import type { McpService } from './mcp.service.js';
import {
createMcpActorContext,
deriveMcpToolScopesForUser,
type McpService,
} from './mcp.service.js';
import { AUTH } from '../auth/auth.tokens.js';
/**
@@ -67,14 +71,25 @@ async function handleMcpRequest(
return;
}
const userId = result.user.id;
const authUser = result.user as {
id: string;
role?: string | null;
tenantId?: string | null;
organizationId?: string | null;
};
const actor = createMcpActorContext({
userId: authUser.id,
role: authUser.role,
tenantId: authUser.tenantId ?? authUser.organizationId ?? undefined,
scopes: deriveMcpToolScopesForUser({ role: authUser.role }),
});
// ─── Session routing ─────────────────────────────────────────────────────
const sessionId = req.raw.headers['mcp-session-id'];
if (typeof sessionId === 'string' && sessionId.length > 0) {
// Existing session request
const transport = mcpService.getSession(sessionId);
const transport = mcpService.getSession(sessionId, actor);
if (!transport) {
logger.warn(`MCP session not found: ${sessionId}`);
reply.raw.writeHead(404, { 'Content-Type': 'application/json' });
@@ -112,8 +127,10 @@ async function handleMcpRequest(
}
// Create new session and handle this initializing request
const { transport } = mcpService.createSession(userId);
logger.log(`New MCP session created for user ${userId}`);
const { transport } = mcpService.createSession(actor);
logger.log(
`New MCP session created for actor=${actor.userId} tenant=${actor.tenantId} correlation=${actor.correlationId}`,
);
await transport.handleRequest(req.raw, reply.raw, body);
}