@apideck/docs-mcp
Version:
MCP server that lets agents search and retrieve your documentation at query time instead of relying on stale training data.
87 lines • 3.58 kB
TypeScript
import type { DocPage, SearchHit } from './types.js';
/** Per-page overrides supplied by the host, e.g. from a build manifest. */
export interface PageMetadata {
title?: string;
description?: string;
url?: string;
}
export interface DocStoreOptions {
/** Directory holding the markdown docs. */
root: string;
/** Resolve extra metadata for a page path (root-relative, no extension). Wins over frontmatter and `baseUrl`. */
metadata?: (docPath: string) => PageMetadata | undefined;
/** Public site root used to build `url` fields, e.g. `https://docs.example.com`. */
baseUrl?: string;
extensions?: string[];
/** Directory names to skip while walking. */
ignore?: string[];
}
export interface SearchOptions {
limit?: number;
pathPrefix?: string;
/** Max hits from the same page (default 3), so one long page does not crowd out the rest. */
perPage?: number;
}
export interface StoreStats {
root: string;
pages: number;
sections: number;
words: number;
indexedAt: Date | null;
}
/**
* Tokenizer that keeps identifiers such as `search_docs`, `rate-limit` or
* `foo.bar` as one token and also emits their parts, so an exact identifier
* query outranks pages that merely contain the words.
*/
export declare const tokenize: (text: string) => string[];
/** Turn any user-supplied reference into the canonical page path. */
export declare const normalizePath: (ref: string) => string;
/** URL for a section: page URL plus anchor, unless the page URL already carries a fragment (e.g. a Redoc deep link). */
export declare const sectionUrl: (page: Pick<DocPage, "url">, anchor: string) => string | undefined;
export declare class DocStore {
readonly root: string;
readonly baseUrl: string | undefined;
private readonly metadata;
private readonly extensions;
private readonly ignore;
private pagesByPath;
private pagesByUrl;
private index;
private indexedAt;
private loading;
constructor(opts: DocStoreOptions);
/** Read every page under `root` and rebuild the search index. Safe to call repeatedly. */
load(): Promise<void>;
private rebuild;
private walk;
private readPage;
private urlFor;
private ensureLoaded;
stats(): StoreStats;
listPages(pathPrefix?: string): DocPage[];
/** Resolve a page by path, tolerating extensions, leading `./`, `docs://`, anchors and folder-index shorthand. */
get(ref: string): DocPage | undefined;
/**
* Resolve a page by its public URL (as configured via `baseUrl` or the
* `metadata` hook), tolerating a trailing slash and a `#fragment`. Returns
* the page plus the fragment as a candidate section anchor, when the URL's
* own fragment isn't already baked into the page's stored URL (e.g. a
* Redoc deep link) — matching that case would strip a fragment the page
* actually needs.
*/
getByUrl(url: string): {
page: DocPage;
anchor?: string;
} | undefined;
/** Resolve a relative link from `fromPath` to a page in the store. */
resolveLink(fromPath: string, href: string): DocPage | undefined;
search(query: string, opts?: SearchOptions): SearchHit[];
/**
* Rebuild the index whenever a file under `root` changes. Returns a function
* that stops watching. Recursive watching needs Node 20+ on Linux; on older
* setups this logs a warning and returns a no-op.
*/
watch(onReload?: (err: Error | null) => void, debounceMs?: number): () => void;
}
//# sourceMappingURL=store.d.ts.map