import { approvalPolicy, type CapabilityMetadata, } from "./capability-policy.ts"; import { z } from "zod"; import type { McpConnection } from "./mcp.ts"; import { MAX_MCP_CAPABILITIES, type McpCapability } from "./mcp-catalog.ts"; export const mcpToolSelection = z .strictObject({ settingsRevision: z .number() .int() .nonnegative() .max(Number.MAX_SAFE_INTEGER), enabled: z.boolean().optional(), approval: approvalPolicy.nullable().optional(), tools: z .array( z.strictObject({ id: z.string().regex(/^[0-9a-f]{64}$/), fingerprint: z.string().regex(/^[0-9a-f]{64}$/), }), ) .min(1) .max(MAX_MCP_CAPABILITIES) .refine( (tools) => new Set(tools.map((tool) => tool.id)).size === tools.length, ), }) .refine( (value) => value.enabled !== undefined || value.approval !== undefined, ); export type McpToolSelection = z.infer; export type SelectableMcpTool = McpCapability & { kind: "tool"; id: string; fingerprint: string; serverId: string; inputSchema: NonNullable; }; export function selectableMcpTool( tool: McpCapability, ): tool is SelectableMcpTool { return ( tool.kind === "tool" && !tool.issue && !!tool.id && !!tool.fingerprint && !!tool.serverId && !!tool.inputSchema ); } // This is the canonical definition boundary consumed by the Think bridge. Remote // hints never confer enablement, and stale/offline catalogs are not executable. export function enabledMcpTools(connections: McpConnection[]) { return connections.flatMap((connection) => connection.enabled && connection.state === "ready" ? connection.capabilities .filter(selectableMcpTool) .filter( (tool) => tool.settings?.enabled === true && tool.settings.approval !== "never", ) : [], ); } export function mcpCapabilityMetadata( connection: McpConnection, tool: SelectableMcpTool, ): CapabilityMetadata { return { id: tool.id, fingerprint: tool.fingerprint, source: { kind: "mcp", id: connection.id }, name: tool.name, sourceName: connection.name, actionSummary: `Run ${tool.name} from ${connection.name}`, enabled: connection.enabled && connection.state === "ready" && tool.settings?.enabled === true, approval: tool.settings?.approval, }; }