mirror of
https://github.com/Sea-Haven-Industries/sh-mcp.git
synced 2026-10-07 10:28:57 +00:00
Add the single authoritative tool-execution path (executeTool) plus the two universal interfaces over it (design.md §2.5, §7.3): - dispatch.ts: scope enforcement, ajv input validation, rate limiting, finance egress redaction (redactDeep), and structured audit emission on one path. - audit.ts / rate-limit.ts: injected AuditLogger + RateLimiter abstractions. - mcp.ts: low-level MCP Server with scope-filtered tools/list (tool-hiding) and tools/call routed through executeTool. - http.ts: Express host mounting /mcp, /openapi.json, POST /tools/:name, /healthz. - openapi.ts: buildOpenApiDocument wraps the existing path generator into a full OpenAPI 3.1 document. - local-auth.ts: LocalAuthProvider (dev bearer tokens) that refuses to construct outside SH_MCP_ENV=local and enforces audience binding (design.md §3, §6).
26 lines
924 B
TypeScript
26 lines
924 B
TypeScript
/**
|
|
* Scope-based tool visibility (tool-hiding).
|
|
*
|
|
* design.md §2.5: a caller sees only the tools whose `requiredScope` is in their
|
|
* `AuthContext`. Both transports use this so the MCP `tools/list` and the
|
|
* per-caller OpenAPI document stay consistent.
|
|
*
|
|
* IMPORTANT: hiding is a CONVENIENCE, never the access boundary. The dispatcher
|
|
* (`executeTool` → `requireScope`) is authoritative; a forced call to a hidden
|
|
* tool still returns 403 (design.md §2.5).
|
|
*/
|
|
|
|
import type { ToolRegistry } from './registry.js';
|
|
import type { AuthContext, ToolDef } from './types.js';
|
|
|
|
/** Tools the caller is permitted to see, in registry insertion order. */
|
|
export function visibleTools(
|
|
registry: ToolRegistry,
|
|
ctx: AuthContext,
|
|
): ToolDef<unknown, unknown>[] {
|
|
const scopes = new Set(ctx.scopes);
|
|
return registry.list().filter((tool) => scopes.has(tool.requiredScope)) as ToolDef<
|
|
unknown,
|
|
unknown
|
|
>[];
|
|
}
|