import type { McpServer, RegisteredTool } from "@modelcontextprotocol/sdk/server/mcp.js"; import type { ToolContext } from "../tool-context.js"; import type { ToolResult } from "../tool-result.js"; import { type ClangdClient, type CompileDb, type ProjectId } from "../utils/clangd.js"; export declare const SYMBOL_ACTIONS: readonly ["definition", "references", "hover", "implementations", "call_hierarchy", "document_symbols"]; export type SymbolAction = (typeof SYMBOL_ACTIONS)[number]; interface LspPosition { line: number; character: number; } interface LspRange { start: LspPosition; end: LspPosition; } interface LspLocation { uri: string; range: LspRange; } interface LspSymbolInformation { name: string; kind?: number; containerName?: string; location: LspLocation; } interface LspDocumentSymbol { name: string; detail?: string; kind?: number; range: LspRange; selectionRange: LspRange; children?: LspDocumentSymbol[]; } export declare function kindName(kind: number | undefined): string | undefined; export interface SymbolLocation { file: string; line: number; character: number; end_line?: number; name?: string; kind?: string; container?: string; preview?: string; } /** Per-call source cache: the same file supplies the preview for every hit. */ type LineCache = Map; /** LSP location (0-based) → the 1-based shape every other CrossPad tool uses. */ export declare function toLocation(loc: LspLocation, cache: LineCache, extra?: Partial): SymbolLocation; export interface Target { file: string; /** 0-based, i.e. already in LSP coordinates. */ position: LspPosition; name?: string; kind?: string; container?: string; } /** * Rank workspace/symbol hits for a name. clangd returns fuzzy matches, so * "PadManager" also brings back "PadManagerTest" and "makePadManager"; an * exact name (or an exact trailing `::name`) has to win, or the tool answers * a question nobody asked. */ export declare function rankCandidates(symbols: LspSymbolInformation[], query: string): LspSymbolInformation[]; /** Explicit file+line wins; a bare name goes through workspace/symbol first. */ export declare function resolveTarget(client: ClangdClient, args: { symbol?: string; file?: string; line?: number; character?: number; }, signal?: AbortSignal): Promise<{ target: Target; candidates: SymbolLocation[]; }>; export interface HoverInfo { /** The signature/type line clangd puts in the hover's code block. */ signature?: string; /** The whole hover card, markdown as clangd wrote it (doc comment included). */ text: string; } /** clangd's hover is markdown: a ```cpp block with the declaration, then the * doc comment. The block is the answer to "what type is this actually". */ export declare function parseHover(contents: unknown): HoverInfo | null; export interface IncomingCall { caller: string; kind?: string; detail?: string; file: string; line: number; /** Lines inside the caller where the call itself appears. */ call_lines: number[]; } /** DocumentSymbol is a tree; a flat list with a depth reads better in a JSON * result and keeps the schema closed. */ export declare function flattenDocumentSymbols(symbols: LspDocumentSymbol[], file: string, cache: LineCache, depth?: number, out?: SymbolLocation[]): SymbolLocation[]; export interface ActionPayload { locations?: SymbolLocation[]; hover?: HoverInfo; calls?: IncomingCall[]; symbols?: SymbolLocation[]; } export declare function runAction(client: ClangdClient, action: SymbolAction, target: Target, limit: number, signal?: AbortSignal): Promise; /** ClangdError (and anything else) → the `{success:false, error:{…}}` envelope. */ export declare function symbolError(e: unknown): ToolResult; export interface SymbolArgs { action?: SymbolAction; symbol?: string; file?: string; line?: number; character?: number; project?: ProjectId; limit?: number; } /** The whole call, with the clangd lookup injectable so tests need no clangd. * * `signal` is the client's cancellation, and it has to reach clangd: a cold * platform-idf tree is a two-minute handshake plus a poll loop of further * two-minute requests, and a cancel that only unwinds this function would * leave every one of them running. */ export declare function crosspadSymbol(args: SymbolArgs, connect?: (db: CompileDb, signal?: AbortSignal) => Promise, locate?: (p?: ProjectId) => CompileDb | null, signal?: AbortSignal): Promise; export declare function registerSymbolTool(server: McpServer, _ctx: ToolContext): RegisteredTool; export {};