mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-20 14:06:27 +00:00
1a9855cf70
Every write tool used to open with its own demo check, 196 copies across 30 tool files, most of them injecting AuthService for nothing else. The registry now takes a toolGate (built from the container) that runs before each registered tool handler, and TREK's gate refuses a demo account on every tool not annotated read-only with the same canned result. The per-tool checks, the AuthService injections, AuthService.isDemoUser and the AuthModule imports that only fed them are gone; ESLint refuses a demo check in a tool file, and a registry-wide test calls every write tool as the demo account.
26 lines
1.2 KiB
TypeScript
26 lines
1.2 KiB
TypeScript
/**
|
|
* Calls one decorated MCP tool method the way a session reaches it: behind the
|
|
* demo gate the registry puts in front of every registered tool. For suites
|
|
* that build a controller with stubs and call its methods directly, so they
|
|
* keep their stubs instead of attaching a whole registry (which would also run
|
|
* the `when` gates those stubs cannot answer).
|
|
*/
|
|
import { getEntry, type ClassRef } from '../../src/nest-mcp/metadata';
|
|
import { trekDemoToolGate } from '../../src/mcp/nest-mcp-policy';
|
|
import type { McpContext } from '../../src/nest-mcp';
|
|
|
|
export async function callGatedTool(
|
|
instance: object,
|
|
methodName: string,
|
|
args: unknown,
|
|
ctx: McpContext,
|
|
isDemoUser: (userId: number) => Promise<boolean>,
|
|
): Promise<unknown> {
|
|
const entry = getEntry((instance as { constructor: ClassRef }).constructor, methodName);
|
|
if (entry?.kind !== 'tool') throw new Error(`${methodName} is not a decorated tool`);
|
|
const refusal = await trekDemoToolGate(isDemoUser)(entry.options, ctx);
|
|
if (refusal !== undefined) return refusal;
|
|
const method = (instance as Record<string, (a: unknown, c: McpContext) => unknown>)[methodName];
|
|
return method.call(instance, args, ctx);
|
|
}
|