UNPKG

@extenshi/mcp

Version:

Extenshi MCP server — bring the extension catalog (search, security, market research) and pre-publish scanning into your AI tools

90 lines • 4.17 kB
/** * Documentation access for the Extenshi MCP server (`search_docs` tool). * * Teaches the assistant to consult the LIVE extenshi.io documentation — * including the full `@extenshi/cli` command reference — so it can answer * "how do I…" questions and quote exact CLI commands instead of guessing. * * Source of truth is the docs site's machine-readable export (the llms.txt * convention), regenerated on every docs deploy: * - <docsUrl>/llms.txt a one-line index of every page * - <docsUrl>/llms-full.txt the full text of every page (one H1 per page) * * Both are PUBLIC static files — no API key, no metering — so this tool works * even before a developer has configured a key (handy for guiding setup). We * fetch lazily, cache in-process with a short TTL, and rank sections locally. * * stdout is the MCP protocol channel — this module must NEVER write to it. */ /** A failure the tool layer turns into an actionable `UserError`. */ export declare class DocsError extends Error { constructor(message: string); } /** One page-sized chunk of `llms-full.txt`, split on top-level headings. */ export interface DocSection { title: string; body: string; } /** Clear the cache — test seam, also usable to force a refresh. */ export declare function clearDocsCache(): void; /** * Split `llms-full.txt` into per-page sections on top-level (`# `) headings. * Fence-aware: a `# comment` inside a ``` code block is NOT a boundary, so CLI * examples never get chopped in half. */ export declare function splitSections(full: string): DocSection[]; /** * Rank sections against a query. A term in the title is worth more than one in * the body. Pure (no I/O) so it is unit-testable with a fixture. */ export declare function rankSections(full: string, query: string, limit: number): DocSection[]; /** * One searchable passage: a `##` subsection of a docs page (or the page intro * before its first `##`). Returning passages instead of whole pages keeps a * search result proportional to the question — a page can run to 8k+ chars, * while the answer usually lives in one subsection. */ export interface DocPassage { page: string; heading?: string; url?: string; body: string; } /** Split `llms-full.txt` into `##`-level passages, fence-aware, carrying the page source URL. */ export declare function splitPassages(full: string): DocPassage[]; /** * Rank passages against a query with BM25 over passage bodies, so a long * passage that merely repeats common words does not outrank a short one that * answers the question. Heading and page-title matches add a bonus; hyphenated * or long tokens (command and flag names) get a phrase boost. Pure (no I/O) so * it is unit-testable with a fixture. */ export declare function rankPassages(full: string, query: string, limit: number): DocPassage[]; /** Default and bounds for the per-result excerpt length (characters). */ export declare const DEFAULT_EXCERPT_CHARS = 1500; export declare const MIN_EXCERPT_CHARS = 200; export declare const MAX_EXCERPT_CHARS = 8000; /** * Cut a passage to `maxChars` on a line boundary. An unterminated code fence is * closed so the rest of the response still renders as prose. */ export declare function excerpt(body: string, maxChars: number): { text: string; truncated: boolean; }; /** Fetch the docs index (`llms.txt`) — the page list returned when no query is given. */ export declare function getDocsIndex(docsUrl: string): Promise<string>; export interface SearchDocsOptions { /** Max passages returned. */ limit: number; /** Max characters per passage excerpt. */ maxChars?: number; } /** Render ranked passages: page › heading, source URL, bounded excerpt. Pure. */ export declare function renderPassages(query: string, matches: DocPassage[], maxChars: number): string; /** * Search the docs and return the top matching passages, each with its source * link and a bounded excerpt. Falls back to a "nothing matched" note. */ export declare function searchDocs(docsUrl: string, query: string, options: SearchDocsOptions): Promise<string>; //# sourceMappingURL=docs.d.ts.map