/** * Read-only client for the ue-mcp plugin registry (plugins.ue-mcp.com). * * The registry is the list of published plugins, each with the repo that owns * its issue tracker. feedback(submit) consults it so a report about a plugin's * surface can be filed against that plugin instead of against ue-mcp core. * * Three rules hold everywhere in this module: * * 1. Never throw. The registry is a convenience layer. A DNS failure, a * 500, or an offline laptop must degrade to "no candidates", never to a * failed feedback submission. * 2. Never block for long. A short timeout keeps the elicitation prompt * responsive; the whole point is a sub-second detour. * 3. Cache on disk. An offline session still routes correctly using the * last catalog this machine saw. */ export interface RegistryPlugin { slug: string; name: string; packageName?: string; repoUrl?: string; repoPrivate?: boolean; homepageUrl?: string; tagline?: string; description?: string; category?: string; tags?: string[]; provides?: string[]; status?: string; } export interface GitHubRepo { owner: string; repo: string; } /** ue-mcp core. Everything that is not plugin-owned lands here. */ export declare const CORE_REPO: GitHubRepo; export declare function registryBase(): string; /** * Origin of the anonymous feedback signing service. * * Separate from the registry on purpose. Feedback about ue-mcp core has nothing * to do with the plugin catalog, and addressing it through the catalog's * hostname tied two unrelated surfaces together. Both names happen to be served * by the same deployment today, which is an operational detail, not a contract. * * `UE_MCP_FEEDBACK` overrides the origin; `UE_MCP_FEEDBACK_ENDPOINT` (read in * src/github-app.ts) overrides the full URL when the path differs too. */ export declare function feedbackBase(): string; /** `https://github.com/db-lyon/pie-studio(.git)` -> `{owner, repo}`. */ export declare function parseGitHubRepo(url: string | null | undefined): GitHubRepo | null; /** `owner/name` for display and comparison. */ export declare function repoSlug(r: GitHubRepo): string; export declare function sameRepo(a: GitHubRepo | null, b: GitHubRepo | null): boolean; /** Parse an `owner/name` string. Returns null for anything else. */ export declare function parseRepoSlug(s: string | null | undefined): GitHubRepo | null; /** * Prefilled "new issue" URL. The escape hatch when the API post is refused * (issues disabled, private repo, bot not installed there) - the user can * still land the report in one click with the body already written. */ export declare function newIssueUrl(repo: GitHubRepo, title: string, body: string): string; /** Test seam: drop the in-process cache so a test can control the catalog. */ export declare function clearRegistryCatalogCache(): void; /** * Fetch the published catalog. Returns [] when the registry is unreachable * and no cached copy exists on this machine. * * A stale disk cache is preferred over an empty list: routing a report to the * plugin that owned the surface last week beats not routing it at all. */ export declare function fetchRegistryCatalog(opts?: { timeoutMs?: number; force?: boolean; }): Promise;