/** * MCP-tool resolution — the cross-referencing moat ("valid is not true") applied * to an MCP tool reference's SERVER. A contract that lists `mcp__linear__search` * names a server `linear`; if the plugin declares its own MCP servers (a * `.mcp.json` / manifest `mcpServers` block) and `linear` isn't among them, the * tool can't resolve — a dead contract entry. This completes the tool moat: * `subagent-tool-contract` (tool-contract.ts) verifies BUILT-IN tools but passes * ANY `mcp__*` token unchecked; this verifies the MCP half. * * Calibrated HIGH-PRECISION — three guards, each learned from a real plugin in * the mid-2026 sweep (research/plugin-structural-findings.md): * * 1. GATE on a declared set. Only flag when the plugin SHIPS a `mcpServers` * declaration (a non-empty `declaredServers`). A plugin that declares no * servers reaches user-global / project-level ones (the normal pattern — * ananddtyagi's agents reference `mcp__ide__*` with no `.mcp.json`), so * flagging there would cry wolf. No declared set → return nothing. * 2. ALLOWLIST built-ins. A harness-provided server (`dialect.knownMcpServers`, * e.g. Claude Code's `ide`) is available without a declaration — never flag it. * 3. SKIP the plugin-namespaced form. Claude Code rewrites a plugin's own MCP * tool to `mcp__plugin____` (observed on han's * playwright-mcp: `mcp__plugin_playwright-mcp_playwright__…`). The plugin / * server segments are joined with single underscores and are ambiguous to * split, and the ref is by construction the plugin's OWN server — so we don't * interpret it (parsing it would be a false-positive factory). * * Pure + ONE detector reused by `scan` + the `mcp-tool-resolves` lint rule * (one-detector-no-drift). The dialect is injected (core ⊄ adapter). */ import type { HarnessDialect } from "./dialect.js"; export interface McpToolIssue { readonly tool: string; readonly server: string; readonly message: string; } /** * The server segment of a direct `mcp____` reference, or null when * the token isn't a direct MCP tool we resolve: a non-MCP tool, or the * plugin-namespaced `mcp__plugin_…__…` form (guard 3 — deliberately skipped). * A `Tool(restriction)` suffix is stripped first. */ export declare function mcpToolServer(raw: string, dialect: HarnessDialect): string | null; /** * Split a direct `mcp____` reference into its `{ server, tool }` * parts, or null when {@link mcpToolServer} declines it (non-MCP, plugin-namespaced, * malformed). The tool segment is everything after `mcp____` (MCP tool * names may themselves contain `__`). A `Tool(restriction)` suffix is stripped. * Used by the LIVE contract-tool resolution (`verifyMcpContractTools` in mcp.ts) to * check the tool actually exists on the server, not just that the server resolves. */ export declare function mcpToolParts(raw: string, dialect: HarnessDialect): { server: string; tool: string; } | null; /** * Verify the MCP tool references in a contract against the plugin's declared MCP * servers. Returns one {@link McpToolIssue} per direct `mcp____` * whose server is neither declared nor a known built-in. Returns `[]` when no * servers are declared (guard 1 — we can't know the resolvable set). */ export declare function verifyMcpToolServers(tools: readonly string[], declaredServers: readonly string[], dialect: HarnessDialect): McpToolIssue[]; //# sourceMappingURL=mcp-tool.d.ts.map