@extenshi/mcp
Version:
Extenshi MCP server — bring the extension catalog (search, security, market research) and pre-publish scanning into your AI tools
47 lines • 2.46 kB
TypeScript
/**
* Cross-store filter validation for `search_extensions`.
*
* Some catalog filters are backed by STORE-SPECIFIC metrics, so combining them
* with a `stores` filter that excludes every store reporting that metric yields
* a silently-empty (or misleading) result set. We reject those combinations up
* front with an actionable message instead of letting the caller "search half
* the catalog and wonder why nothing matched".
*
* Field population (source of truth: catalog/scraper/src):
* - weeklyDownloads → Firefox ONLY (`addon.weekly_downloads`). Chrome reports
* install counts via `usersNumeric`; Edge via `activeInstallCount`; neither
* sets weeklyDownloads. There is no server-side min-usersNumeric filter, so
* for Chrome/Edge popularity the only lever is `sortBy: 'popular'`.
*
* Kept free of any `fastmcp` import so it stays unit-testable in isolation; the
* caller (index.ts) turns a returned message into a `UserError`.
*/
export type StoreType = 'CHROME' | 'FIREFOX' | 'EDGE';
interface StoreSpecificFilter {
/** The arg key whose presence triggers the check. */
field: string;
/** Stores whose snapshots actually populate the metric this filter needs. */
supportedStores: readonly StoreType[];
/** Actionable guidance appended to the conflict message. */
hint: string;
}
export declare const STORE_SPECIFIC_FILTERS: readonly StoreSpecificFilter[];
/**
* One-line, model-facing summary of every store-specific constraint, derived
* from the SAME table that enforces them. Injected into the `search_extensions`
* tool description so the constraint is known BEFORE a call is made — this lets
* the model avoid composing a request that would only be rejected (and, once
* read-enforcement is on, would still burn a read credit at the backend). The
* description (advertised limit) and validateSearchFilters (runtime rejection)
* can never drift because both read STORE_SPECIFIC_FILTERS.
*/
export declare function describeStoreConstraints(): string;
/**
* Returns a human-readable conflict message when the args combine a
* store-specific filter with a `stores` set that supports none of it; otherwise
* null. A missing/empty `stores` filter never conflicts (the metric simply
* narrows results to the stores that report it).
*/
export declare function validateSearchFilters(args: Record<string, unknown>): string | null;
export {};
//# sourceMappingURL=search-filters.d.ts.map