/** * @fileoverview Extracts MCP tool references from SKILL.md content * @module @skillsmith/core/analysis/McpReferenceExtractor * @see SMI-3145: Build McpReferenceExtractor * @see SMI-5676: Wave 1 Step 3b — harden extraction (26-file validation found a * 71% false-negative rate against real SKILL.md files) * * Scans skill content for three kinds of MCP dependency signal: * 1. Inline `mcp____` references in prose/code (original * SMI-3145 behavior), tracking fenced-code-block state for confidence. * 2. Frontmatter `allowed-tools`/`tools` YAML fields, including the * bare-server (`mcp__linear`) and wildcard (`mcp__linear__*`) forms. * 3. Embedded `mcpServers` JSON registration blocks (e.g. a fenced code * block showing how to add the skill's server to `.mcp.json`). * * All three feed the same `references`/`servers`/`highConfidenceServers` * output — hardening changes what gets *extracted*, not how extracted * results get scored (see `DependencyMerger.ts`, unchanged). * * A fourth signal, `registeredServers`, lets a caller cross-check every * candidate server name against the consuming project's own `.mcp.json`. * This is advisory tagging only (`serverResolutions`) — a name is NEVER * excluded from `references`/`servers` just because it doesn't resolve, * since a real (but not-yet-installed) dependency looks identical to a * stale/renamed one from here. See `serverResolutions` doc below. */ /** A single MCP tool reference found in content */ export interface McpReference { /** MCP server name, e.g. "linear" */ server: string; /** * MCP tool name, e.g. "save_issue". `'*'` marks a server-level reference * with no specific tool named — the bare-server frontmatter form * (`mcp__linear`), the wildcard frontmatter form (`mcp__linear__*`), or an * `mcpServers` JSON registration entry (which names a server, not a tool). */ tool: string; /** 1-indexed line number where the reference appears */ line: number; /** true if the reference is inside a fenced code block */ inCodeBlock: boolean; } /** * Resolution of a candidate server name against the consuming project's * `.mcp.json` (SMI-5676's `registeredServers` cross-check). * - `registered`: found in the `registeredServers` list passed in * - `unregistered`: `registeredServers` was provided but didn't contain this * name (e.g. the `claude-flow` -> `ruflo` rename: bundled skill docs still * say `mcp__claude-flow__*`, but this project's `.mcp.json` only registers * `ruflo`) * - `unknown`: no `registeredServers` list was available to cross-check * (caller passed nothing — e.g. `.mcp.json` missing/unparseable; fail open) */ export type McpServerResolution = 'registered' | 'unregistered' | 'unknown'; /** Aggregated extraction result */ export interface McpExtractionResult { /** All individual references found */ references: McpReference[]; /** Unique server names across all references */ servers: string[]; /** Servers referenced at least once outside a code block */ highConfidenceServers: string[]; /** true if input exceeded the 100KB cap and was truncated */ truncated?: boolean; /** * Resolution state for every name in `servers`, keyed by server name. See * {@link McpServerResolution}. Optional only for backward compatibility * with hand-constructed `McpExtractionResult` fixtures predating SMI-5676 * (e.g. `DependencyMerger.test.ts`'s helpers) — {@link extractMcpReferences} * itself always populates this (with `'unknown'` entries when * `registeredServers` wasn't passed), so a real caller can always rely on * it being present. */ serverResolutions?: Record; } /** * Extract all MCP tool references from skill content. * * Scans each line for `mcp__server__tool` patterns, tracking fenced * code block state to distinguish high-confidence (prose) references * from low-confidence (code example) references. Also parses frontmatter * `allowed-tools`/`tools` fields and embedded `mcpServers` JSON blocks * (SMI-5676). * * @param content - Raw SKILL.md content (markdown) * @param registeredServers - Optional list of MCP server names actually * registered in the consuming project's `.mcp.json`. When provided * (even as `[]`), every candidate server name is tagged `registered` or * `unregistered` in the result's `serverResolutions` map — never filtered * out. Omit (or pass `undefined`) when the caller couldn't determine this * (e.g. `.mcp.json` missing/unparseable); every name is then tagged * `unknown` rather than assumed unregistered. * @returns Extraction result with references, servers, and confidence info */ export declare function extractMcpReferences(content: string, registeredServers?: string[]): McpExtractionResult; //# sourceMappingURL=McpReferenceExtractor.d.ts.map