@mcp-rating/gateway 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/dist/ads/ad-tracker.d.ts +63 -0
- package/dist/ads/ad-tracker.js +144 -0
- package/dist/ads/ad-tracker.js.map +1 -0
- package/dist/analytics/usage-tracker.d.ts +67 -0
- package/dist/analytics/usage-tracker.js +148 -0
- package/dist/analytics/usage-tracker.js.map +1 -0
- package/dist/audit/audit-log.d.ts +71 -0
- package/dist/audit/audit-log.js +72 -0
- package/dist/audit/audit-log.js.map +1 -0
- package/dist/config/gateway-config.d.ts +6 -0
- package/dist/config/gateway-config.js +135 -0
- package/dist/config/gateway-config.js.map +1 -0
- package/dist/config/groups.d.ts +29 -0
- package/dist/config/groups.js +102 -0
- package/dist/config/groups.js.map +1 -0
- package/dist/config/profiles.d.ts +42 -0
- package/dist/config/profiles.js +167 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/types.d.ts +76 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/connection/auto-installer.d.ts +13 -0
- package/dist/connection/auto-installer.js +61 -0
- package/dist/connection/auto-installer.js.map +1 -0
- package/dist/connection/connection-manager.d.ts +106 -0
- package/dist/connection/connection-manager.js +845 -0
- package/dist/connection/connection-manager.js.map +1 -0
- package/dist/connection/downstream-client.d.ts +50 -0
- package/dist/connection/downstream-client.js +170 -0
- package/dist/connection/downstream-client.js.map +1 -0
- package/dist/connection/http-client.d.ts +12 -0
- package/dist/connection/http-client.js +26 -0
- package/dist/connection/http-client.js.map +1 -0
- package/dist/connection/sse-client.d.ts +12 -0
- package/dist/connection/sse-client.js +26 -0
- package/dist/connection/sse-client.js.map +1 -0
- package/dist/connection/transport-factory.d.ts +31 -0
- package/dist/connection/transport-factory.js +67 -0
- package/dist/connection/transport-factory.js.map +1 -0
- package/dist/connection/types.d.ts +134 -0
- package/dist/connection/types.js +5 -0
- package/dist/connection/types.js.map +1 -0
- package/dist/connection/ws-client.d.ts +12 -0
- package/dist/connection/ws-client.js +26 -0
- package/dist/connection/ws-client.js.map +1 -0
- package/dist/discovery/auto-recommender.d.ts +51 -0
- package/dist/discovery/auto-recommender.js +176 -0
- package/dist/discovery/auto-recommender.js.map +1 -0
- package/dist/gateway-server.d.ts +42 -0
- package/dist/gateway-server.js +135 -0
- package/dist/gateway-server.js.map +1 -0
- package/dist/http-daemon.d.ts +26 -0
- package/dist/http-daemon.js +302 -0
- package/dist/http-daemon.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +83 -0
- package/dist/index.js.map +1 -0
- package/dist/meta-tools/ad-status.d.ts +8 -0
- package/dist/meta-tools/ad-status.js +41 -0
- package/dist/meta-tools/ad-status.js.map +1 -0
- package/dist/meta-tools/audit.d.ts +12 -0
- package/dist/meta-tools/audit.js +98 -0
- package/dist/meta-tools/audit.js.map +1 -0
- package/dist/meta-tools/call-tool.d.ts +11 -0
- package/dist/meta-tools/call-tool.js +65 -0
- package/dist/meta-tools/call-tool.js.map +1 -0
- package/dist/meta-tools/connect.d.ts +3 -0
- package/dist/meta-tools/connect.js +105 -0
- package/dist/meta-tools/connect.js.map +1 -0
- package/dist/meta-tools/disconnect.d.ts +3 -0
- package/dist/meta-tools/disconnect.js +30 -0
- package/dist/meta-tools/disconnect.js.map +1 -0
- package/dist/meta-tools/discover.d.ts +3 -0
- package/dist/meta-tools/discover.js +97 -0
- package/dist/meta-tools/discover.js.map +1 -0
- package/dist/meta-tools/groups.d.ts +7 -0
- package/dist/meta-tools/groups.js +237 -0
- package/dist/meta-tools/groups.js.map +1 -0
- package/dist/meta-tools/health.d.ts +4 -0
- package/dist/meta-tools/health.js +76 -0
- package/dist/meta-tools/health.js.map +1 -0
- package/dist/meta-tools/index.d.ts +28 -0
- package/dist/meta-tools/index.js +56 -0
- package/dist/meta-tools/index.js.map +1 -0
- package/dist/meta-tools/list-active.d.ts +3 -0
- package/dist/meta-tools/list-active.js +50 -0
- package/dist/meta-tools/list-active.js.map +1 -0
- package/dist/meta-tools/profiles.d.ts +6 -0
- package/dist/meta-tools/profiles.js +197 -0
- package/dist/meta-tools/profiles.js.map +1 -0
- package/dist/meta-tools/recommend.d.ts +14 -0
- package/dist/meta-tools/recommend.js +74 -0
- package/dist/meta-tools/recommend.js.map +1 -0
- package/dist/meta-tools/sandbox.d.ts +12 -0
- package/dist/meta-tools/sandbox.js +125 -0
- package/dist/meta-tools/sandbox.js.map +1 -0
- package/dist/meta-tools/server-info.d.ts +4 -0
- package/dist/meta-tools/server-info.js +156 -0
- package/dist/meta-tools/server-info.js.map +1 -0
- package/dist/meta-tools/usage.d.ts +6 -0
- package/dist/meta-tools/usage.js +149 -0
- package/dist/meta-tools/usage.js.map +1 -0
- package/dist/permissions/permission-manager.d.ts +26 -0
- package/dist/permissions/permission-manager.js +73 -0
- package/dist/permissions/permission-manager.js.map +1 -0
- package/dist/permissions/trust-tiers.d.ts +18 -0
- package/dist/permissions/trust-tiers.js +42 -0
- package/dist/permissions/trust-tiers.js.map +1 -0
- package/dist/plugins/builtin/logging-plugin.d.ts +6 -0
- package/dist/plugins/builtin/logging-plugin.js +41 -0
- package/dist/plugins/builtin/logging-plugin.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +65 -0
- package/dist/plugins/plugin-manager.js +137 -0
- package/dist/plugins/plugin-manager.js.map +1 -0
- package/dist/proxy/prime-handlers.d.ts +27 -0
- package/dist/proxy/prime-handlers.js +47 -0
- package/dist/proxy/prime-handlers.js.map +1 -0
- package/dist/proxy/progress-forwarder.d.ts +44 -0
- package/dist/proxy/progress-forwarder.js +40 -0
- package/dist/proxy/progress-forwarder.js.map +1 -0
- package/dist/proxy/prompt-router.d.ts +25 -0
- package/dist/proxy/prompt-router.js +110 -0
- package/dist/proxy/prompt-router.js.map +1 -0
- package/dist/proxy/resource-router.d.ts +25 -0
- package/dist/proxy/resource-router.js +91 -0
- package/dist/proxy/resource-router.js.map +1 -0
- package/dist/proxy/schema-adapter.d.ts +11 -0
- package/dist/proxy/schema-adapter.js +36 -0
- package/dist/proxy/schema-adapter.js.map +1 -0
- package/dist/proxy/task-proxy.d.ts +28 -0
- package/dist/proxy/task-proxy.js +186 -0
- package/dist/proxy/task-proxy.js.map +1 -0
- package/dist/proxy/tool-router.d.ts +38 -0
- package/dist/proxy/tool-router.js +229 -0
- package/dist/proxy/tool-router.js.map +1 -0
- package/dist/proxy/ui-detect.d.ts +22 -0
- package/dist/proxy/ui-detect.js +30 -0
- package/dist/proxy/ui-detect.js.map +1 -0
- package/dist/registry/registry-client.d.ts +55 -0
- package/dist/registry/registry-client.js +211 -0
- package/dist/registry/registry-client.js.map +1 -0
- package/dist/registry/types.d.ts +69 -0
- package/dist/registry/types.js +2 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/sandbox/container-runtime.d.ts +91 -0
- package/dist/sandbox/container-runtime.js +178 -0
- package/dist/sandbox/container-runtime.js.map +1 -0
- package/dist/sandbox/egress-proxy.d.ts +51 -0
- package/dist/sandbox/egress-proxy.js +146 -0
- package/dist/sandbox/egress-proxy.js.map +1 -0
- package/dist/sandbox/env-scoper.d.ts +29 -0
- package/dist/sandbox/env-scoper.js +60 -0
- package/dist/sandbox/env-scoper.js.map +1 -0
- package/dist/sandbox/manifest-resolver.d.ts +40 -0
- package/dist/sandbox/manifest-resolver.js +185 -0
- package/dist/sandbox/manifest-resolver.js.map +1 -0
- package/dist/sandbox/types.d.ts +88 -0
- package/dist/sandbox/types.js +21 -0
- package/dist/sandbox/types.js.map +1 -0
- package/dist/utils/errors.d.ts +39 -0
- package/dist/utils/errors.js +67 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.js +51 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DownstreamTool, DownstreamResource } from "../connection/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Authoritative UI-capability detection from a LIVE connection.
|
|
4
|
+
*
|
|
5
|
+
* Unlike the registry's heuristic ("UI-capable (detected)" from package deps /
|
|
6
|
+
* keywords), this inspects the actual data the server returned after
|
|
7
|
+
* connecting — so it's ground truth:
|
|
8
|
+
*
|
|
9
|
+
* - Any tool carrying `_meta.ui.resourceUri` (MCP Apps marker), or
|
|
10
|
+
* - Any resource whose URI uses the `ui://` scheme (MCP-UI / MCP Apps).
|
|
11
|
+
*
|
|
12
|
+
* Returns which tools/resources triggered it so the gateway can show the user
|
|
13
|
+
* exactly what's UI-capable.
|
|
14
|
+
*/
|
|
15
|
+
export interface LiveUiResult {
|
|
16
|
+
supportsUi: boolean;
|
|
17
|
+
/** Tool names that declare a UI resource via _meta.ui.resourceUri. */
|
|
18
|
+
uiTools: string[];
|
|
19
|
+
/** Resource URIs using the ui:// scheme. */
|
|
20
|
+
uiResources: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function detectLiveUi(tools: Iterable<DownstreamTool>, resources: Iterable<DownstreamResource>): LiveUiResult;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function detectLiveUi(tools, resources) {
|
|
2
|
+
const uiTools = [];
|
|
3
|
+
const uiResources = [];
|
|
4
|
+
for (const tool of tools) {
|
|
5
|
+
const meta = tool._meta;
|
|
6
|
+
if (hasUiResourceUri(meta))
|
|
7
|
+
uiTools.push(tool.name);
|
|
8
|
+
}
|
|
9
|
+
for (const res of resources) {
|
|
10
|
+
if (typeof res.uri === "string" && res.uri.startsWith("ui://")) {
|
|
11
|
+
uiResources.push(res.uri);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
supportsUi: uiTools.length > 0 || uiResources.length > 0,
|
|
16
|
+
uiTools,
|
|
17
|
+
uiResources,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** True if a tool's _meta carries a `ui.resourceUri` (MCP Apps). */
|
|
21
|
+
function hasUiResourceUri(meta) {
|
|
22
|
+
if (!meta || typeof meta !== "object")
|
|
23
|
+
return false;
|
|
24
|
+
const ui = meta.ui;
|
|
25
|
+
if (!ui || typeof ui !== "object")
|
|
26
|
+
return false;
|
|
27
|
+
const uri = ui.resourceUri;
|
|
28
|
+
return typeof uri === "string" && uri.length > 0;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=ui-detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-detect.js","sourceRoot":"","sources":["../../src/proxy/ui-detect.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,YAAY,CAC1B,KAA+B,EAC/B,SAAuC;IAEvC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAI,IAA4B,CAAC,KAAK,CAAC;QACjD,IAAI,gBAAgB,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/D,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QACxD,OAAO;QACP,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,SAAS,gBAAgB,CAAC,IAAa;IACrC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACpD,MAAM,EAAE,GAAI,IAAyB,CAAC,EAAE,CAAC;IACzC,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,GAAG,GAAI,EAAgC,CAAC,WAAW,CAAC;IAC1D,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { RegistryServer, RegistryListResponse, InstallCommand, TrustTier } from "./types.js";
|
|
2
|
+
export interface RegistryStatus {
|
|
3
|
+
lastSuccessfulCall: Date | null;
|
|
4
|
+
lastError: string | null;
|
|
5
|
+
cacheSize: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* HTTP client for querying the MCP-Rating API.
|
|
9
|
+
*
|
|
10
|
+
* Uses native fetch (Node 18+). Falls back gracefully when the
|
|
11
|
+
* registry is unreachable — users can still connect servers manually
|
|
12
|
+
* via explicit command+args.
|
|
13
|
+
*
|
|
14
|
+
* Features:
|
|
15
|
+
* - In-memory cache with configurable TTL
|
|
16
|
+
* - Automatic retry with backoff for transient failures (5xx / network)
|
|
17
|
+
* - Reachability tracking for health diagnostics
|
|
18
|
+
*/
|
|
19
|
+
export declare class RegistryClient {
|
|
20
|
+
private readonly baseUrl;
|
|
21
|
+
private readonly cacheTtlMs;
|
|
22
|
+
private readonly partnerKey?;
|
|
23
|
+
private cache;
|
|
24
|
+
private _lastSuccessfulCall;
|
|
25
|
+
private _lastError;
|
|
26
|
+
constructor(baseUrl: string, cacheTtlMs?: number, partnerKey?: string | undefined);
|
|
27
|
+
search(query: string, options?: {
|
|
28
|
+
category?: string;
|
|
29
|
+
limit?: number;
|
|
30
|
+
offset?: number;
|
|
31
|
+
}): Promise<RegistryListResponse>;
|
|
32
|
+
getServer(slug: string): Promise<RegistryServer | null>;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve install command for a server.
|
|
35
|
+
* Prefers the stored `installCommand`, falling back to `npx -y {npmPackage}`.
|
|
36
|
+
*/
|
|
37
|
+
resolveInstallCommand(server: RegistryServer): InstallCommand | null;
|
|
38
|
+
/**
|
|
39
|
+
* Determine trust tier from registry data.
|
|
40
|
+
*
|
|
41
|
+
* NOTE: This logic is mirrored in the main app at src/scoring/trust-tier.ts
|
|
42
|
+
* (so the REST API exposes the same `trustTier`). Keep the two in sync — the
|
|
43
|
+
* gateway is a separately-published package and can't import from the root.
|
|
44
|
+
*/
|
|
45
|
+
static determineTrustTier(server: RegistryServer): TrustTier;
|
|
46
|
+
/** Get reachability status for diagnostics. */
|
|
47
|
+
getStatus(): RegistryStatus;
|
|
48
|
+
/** Clear all cached entries. */
|
|
49
|
+
clearCache(): void;
|
|
50
|
+
private getFromCache;
|
|
51
|
+
private setCache;
|
|
52
|
+
private fetchWithRetry;
|
|
53
|
+
private recordSuccess;
|
|
54
|
+
private recordError;
|
|
55
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { log } from "../utils/logger.js";
|
|
2
|
+
import { RegistryError } from "../utils/errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* HTTP client for querying the MCP-Rating API.
|
|
5
|
+
*
|
|
6
|
+
* Uses native fetch (Node 18+). Falls back gracefully when the
|
|
7
|
+
* registry is unreachable — users can still connect servers manually
|
|
8
|
+
* via explicit command+args.
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - In-memory cache with configurable TTL
|
|
12
|
+
* - Automatic retry with backoff for transient failures (5xx / network)
|
|
13
|
+
* - Reachability tracking for health diagnostics
|
|
14
|
+
*/
|
|
15
|
+
export class RegistryClient {
|
|
16
|
+
baseUrl;
|
|
17
|
+
cacheTtlMs;
|
|
18
|
+
partnerKey;
|
|
19
|
+
cache = new Map();
|
|
20
|
+
_lastSuccessfulCall = null;
|
|
21
|
+
_lastError = null;
|
|
22
|
+
constructor(baseUrl, cacheTtlMs = 300_000, partnerKey) {
|
|
23
|
+
this.baseUrl = baseUrl;
|
|
24
|
+
this.cacheTtlMs = cacheTtlMs;
|
|
25
|
+
this.partnerKey = partnerKey;
|
|
26
|
+
}
|
|
27
|
+
async search(query, options) {
|
|
28
|
+
const params = new URLSearchParams({
|
|
29
|
+
search: query,
|
|
30
|
+
limit: String(options?.limit ?? 10),
|
|
31
|
+
offset: String(options?.offset ?? 0),
|
|
32
|
+
});
|
|
33
|
+
if (options?.category) {
|
|
34
|
+
params.set("category", options.category);
|
|
35
|
+
}
|
|
36
|
+
const url = `${this.baseUrl}/servers?${params}`;
|
|
37
|
+
const cacheKey = `search:${url}`;
|
|
38
|
+
const cached = this.getFromCache(cacheKey);
|
|
39
|
+
if (cached) {
|
|
40
|
+
log.debug("Registry cache hit", { cacheKey });
|
|
41
|
+
return cached;
|
|
42
|
+
}
|
|
43
|
+
log.debug("Registry search", { url });
|
|
44
|
+
try {
|
|
45
|
+
const res = await this.fetchWithRetry(url);
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
throw new RegistryError(`Registry API returned ${res.status}: ${res.statusText}`);
|
|
48
|
+
}
|
|
49
|
+
const data = (await res.json());
|
|
50
|
+
this.setCache(cacheKey, data);
|
|
51
|
+
this.recordSuccess();
|
|
52
|
+
return data;
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
this.recordError(err);
|
|
56
|
+
if (err instanceof RegistryError)
|
|
57
|
+
throw err;
|
|
58
|
+
throw new RegistryError(`Failed to reach MCP-Rating registry at ${this.baseUrl}: ${String(err)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async getServer(slug) {
|
|
62
|
+
const url = `${this.baseUrl}/servers/${encodeURIComponent(slug)}`;
|
|
63
|
+
const cacheKey = `server:${slug}`;
|
|
64
|
+
const cached = this.getFromCache(cacheKey);
|
|
65
|
+
if (cached !== undefined) {
|
|
66
|
+
log.debug("Registry cache hit", { cacheKey });
|
|
67
|
+
return cached;
|
|
68
|
+
}
|
|
69
|
+
log.debug("Registry getServer", { url });
|
|
70
|
+
try {
|
|
71
|
+
const res = await this.fetchWithRetry(url);
|
|
72
|
+
if (res.status === 404) {
|
|
73
|
+
this.setCache(cacheKey, null);
|
|
74
|
+
this.recordSuccess();
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
if (!res.ok) {
|
|
78
|
+
throw new RegistryError(`Registry API returned ${res.status}: ${res.statusText}`);
|
|
79
|
+
}
|
|
80
|
+
const data = (await res.json());
|
|
81
|
+
this.setCache(cacheKey, data);
|
|
82
|
+
this.recordSuccess();
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
this.recordError(err);
|
|
87
|
+
if (err instanceof RegistryError)
|
|
88
|
+
throw err;
|
|
89
|
+
throw new RegistryError(`Failed to reach MCP-Rating registry: ${String(err)}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Resolve install command for a server.
|
|
94
|
+
* Prefers the stored `installCommand`, falling back to `npx -y {npmPackage}`.
|
|
95
|
+
*/
|
|
96
|
+
resolveInstallCommand(server) {
|
|
97
|
+
if (server.installCommand) {
|
|
98
|
+
const parts = server.installCommand.split(/\s+/);
|
|
99
|
+
if (parts.length > 0) {
|
|
100
|
+
return { command: parts[0], args: parts.slice(1) };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (server.npmPackage) {
|
|
104
|
+
return { command: "npx", args: ["-y", server.npmPackage] };
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Determine trust tier from registry data.
|
|
110
|
+
*
|
|
111
|
+
* NOTE: This logic is mirrored in the main app at src/scoring/trust-tier.ts
|
|
112
|
+
* (so the REST API exposes the same `trustTier`). Keep the two in sync — the
|
|
113
|
+
* gateway is a separately-published package and can't import from the root.
|
|
114
|
+
*/
|
|
115
|
+
static determineTrustTier(server) {
|
|
116
|
+
if (server.isVerified ||
|
|
117
|
+
(server.isOfficial && (server.qualityScore ?? 0) >= 80)) {
|
|
118
|
+
return "verified";
|
|
119
|
+
}
|
|
120
|
+
if ((server.qualityScore ?? 0) >= 60 &&
|
|
121
|
+
server.repositoryUrl &&
|
|
122
|
+
server.installCommand) {
|
|
123
|
+
return "trusted";
|
|
124
|
+
}
|
|
125
|
+
if ((server.qualityScore ?? 0) >= 30) {
|
|
126
|
+
return "community";
|
|
127
|
+
}
|
|
128
|
+
return "unknown";
|
|
129
|
+
}
|
|
130
|
+
/** Get reachability status for diagnostics. */
|
|
131
|
+
getStatus() {
|
|
132
|
+
return {
|
|
133
|
+
lastSuccessfulCall: this._lastSuccessfulCall,
|
|
134
|
+
lastError: this._lastError,
|
|
135
|
+
cacheSize: this.cache.size,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** Clear all cached entries. */
|
|
139
|
+
clearCache() {
|
|
140
|
+
this.cache.clear();
|
|
141
|
+
log.debug("Registry cache cleared");
|
|
142
|
+
}
|
|
143
|
+
// ── Cache helpers ──────────────────────────────────────────────
|
|
144
|
+
getFromCache(key) {
|
|
145
|
+
const entry = this.cache.get(key);
|
|
146
|
+
if (!entry)
|
|
147
|
+
return undefined;
|
|
148
|
+
if (Date.now() > entry.expiresAt) {
|
|
149
|
+
this.cache.delete(key);
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
return entry.data;
|
|
153
|
+
}
|
|
154
|
+
setCache(key, data) {
|
|
155
|
+
this.cache.set(key, {
|
|
156
|
+
data,
|
|
157
|
+
expiresAt: Date.now() + this.cacheTtlMs,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
// ── Retry helper ───────────────────────────────────────────────
|
|
161
|
+
async fetchWithRetry(url, maxRetries = 2) {
|
|
162
|
+
const headers = {};
|
|
163
|
+
if (this.partnerKey) {
|
|
164
|
+
headers["x-partner-key"] = this.partnerKey;
|
|
165
|
+
}
|
|
166
|
+
let lastError;
|
|
167
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
168
|
+
try {
|
|
169
|
+
const res = await fetch(url, {
|
|
170
|
+
headers,
|
|
171
|
+
signal: AbortSignal.timeout(10_000),
|
|
172
|
+
});
|
|
173
|
+
// Don't retry on client errors (4xx) or success
|
|
174
|
+
if (res.ok || res.status < 500)
|
|
175
|
+
return res;
|
|
176
|
+
// 5xx — retry if attempts remain
|
|
177
|
+
lastError = new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
178
|
+
log.warn("Registry returned 5xx, retrying", {
|
|
179
|
+
url,
|
|
180
|
+
status: res.status,
|
|
181
|
+
attempt: attempt + 1,
|
|
182
|
+
maxRetries,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
lastError = err;
|
|
187
|
+
if (attempt < maxRetries) {
|
|
188
|
+
log.warn("Registry fetch failed, retrying", {
|
|
189
|
+
url,
|
|
190
|
+
error: String(err),
|
|
191
|
+
attempt: attempt + 1,
|
|
192
|
+
maxRetries,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (attempt < maxRetries) {
|
|
197
|
+
await new Promise((r) => setTimeout(r, 500 * (attempt + 1)));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
throw lastError;
|
|
201
|
+
}
|
|
202
|
+
// ── Reachability tracking ──────────────────────────────────────
|
|
203
|
+
recordSuccess() {
|
|
204
|
+
this._lastSuccessfulCall = new Date();
|
|
205
|
+
this._lastError = null;
|
|
206
|
+
}
|
|
207
|
+
recordError(err) {
|
|
208
|
+
this._lastError = err instanceof Error ? err.message : String(err);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=registry-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-client.js","sourceRoot":"","sources":["../../src/registry/registry-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Server data returned by the MCP-Rating API */
|
|
2
|
+
export interface RegistryServer {
|
|
3
|
+
id: string;
|
|
4
|
+
slug: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string | null;
|
|
7
|
+
author: string | null;
|
|
8
|
+
repositoryUrl: string | null;
|
|
9
|
+
npmPackage: string | null;
|
|
10
|
+
homepage: string | null;
|
|
11
|
+
installCommand: string | null;
|
|
12
|
+
stars: number | null;
|
|
13
|
+
weeklyDownloads: number | null;
|
|
14
|
+
qualityScore: number | null;
|
|
15
|
+
isOfficial: boolean;
|
|
16
|
+
isVerified: boolean;
|
|
17
|
+
supportsDiscovery: boolean;
|
|
18
|
+
discoveryUrl: string | null;
|
|
19
|
+
/** Heuristic UI capability from the registry ("UI-capable (detected)"). */
|
|
20
|
+
supportsUi?: boolean;
|
|
21
|
+
uiType?: string | null;
|
|
22
|
+
/** How the server is run: npm | pypi | docker | remote | github-manual. */
|
|
23
|
+
accessMethod?: string | null;
|
|
24
|
+
/** Supply-chain safety screen, 0-100 (>=80 safe, 50-79 caution, <50 risk). */
|
|
25
|
+
safetyScore?: number | null;
|
|
26
|
+
safetyFlags?: string[] | null;
|
|
27
|
+
category: {
|
|
28
|
+
slug: string;
|
|
29
|
+
name: string;
|
|
30
|
+
} | null;
|
|
31
|
+
tools: {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string | null;
|
|
34
|
+
}[];
|
|
35
|
+
resources: {
|
|
36
|
+
uri: string;
|
|
37
|
+
name: string;
|
|
38
|
+
description: string | null;
|
|
39
|
+
}[];
|
|
40
|
+
metadata: Record<string, unknown> | null;
|
|
41
|
+
/** Whether this server requires API keys or authentication (computed from metadata) */
|
|
42
|
+
requiresAuth?: boolean;
|
|
43
|
+
/** Detailed auth info (computed from metadata) */
|
|
44
|
+
authDetails?: {
|
|
45
|
+
envVars: Array<{
|
|
46
|
+
name: string;
|
|
47
|
+
description?: string;
|
|
48
|
+
}>;
|
|
49
|
+
allEnvVars: Array<{
|
|
50
|
+
name: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
}>;
|
|
53
|
+
schemes: string[];
|
|
54
|
+
} | null;
|
|
55
|
+
}
|
|
56
|
+
/** Paginated list response from the API */
|
|
57
|
+
export interface RegistryListResponse {
|
|
58
|
+
data: RegistryServer[];
|
|
59
|
+
total: number;
|
|
60
|
+
limit: number;
|
|
61
|
+
offset: number;
|
|
62
|
+
}
|
|
63
|
+
/** Trust tiers derived from registry data */
|
|
64
|
+
export type TrustTier = "verified" | "trusted" | "community" | "unknown";
|
|
65
|
+
/** Resolved install command for spawning a server */
|
|
66
|
+
export interface InstallCommand {
|
|
67
|
+
command: string;
|
|
68
|
+
args: string[];
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { CapabilityManifest } from "./types.js";
|
|
2
|
+
/** A container runtime available on the host. */
|
|
3
|
+
export type ContainerEngine = "docker" | "podman";
|
|
4
|
+
/** Result of wrapping a spawn command for container execution. */
|
|
5
|
+
export interface WrappedSpawn {
|
|
6
|
+
command: string;
|
|
7
|
+
args: string[];
|
|
8
|
+
/**
|
|
9
|
+
* Env var NAMES that must be forwarded into the container. The values are
|
|
10
|
+
* supplied via the spawn process env (the scoped env), and `-e NAME` tells
|
|
11
|
+
* the engine to forward them. Kept separate so callers can audit.
|
|
12
|
+
*/
|
|
13
|
+
forwardedEnvNames: string[];
|
|
14
|
+
}
|
|
15
|
+
/** Default base images by command family. Overridable via config. */
|
|
16
|
+
export interface ContainerImages {
|
|
17
|
+
/** Image for node/npm/npx-based servers. */
|
|
18
|
+
node: string;
|
|
19
|
+
/** Image for python/pip/uvx-based servers. */
|
|
20
|
+
python: string;
|
|
21
|
+
/** Fallback image for anything else. */
|
|
22
|
+
default: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const DEFAULT_IMAGES: ContainerImages;
|
|
25
|
+
/**
|
|
26
|
+
* Detect an available container engine (docker preferred, then podman).
|
|
27
|
+
* Result is cached for the process lifetime. Returns null if none is usable.
|
|
28
|
+
*/
|
|
29
|
+
export declare function detectContainerEngine(): Promise<ContainerEngine | null>;
|
|
30
|
+
/** Reset the cached engine (for tests). */
|
|
31
|
+
export declare function _resetEngineCache(): void;
|
|
32
|
+
/** Deterministic image name for a pre-baked server image. */
|
|
33
|
+
export declare function bakedImageName(slug: string): string;
|
|
34
|
+
export interface BakedImage {
|
|
35
|
+
image: string;
|
|
36
|
+
/**
|
|
37
|
+
* The executable name baked into the image (from the mcp.sandbox.bin label).
|
|
38
|
+
* Run directly at runtime — npx can't resolve a globally-installed scoped
|
|
39
|
+
* package offline, so we invoke the bin instead.
|
|
40
|
+
*/
|
|
41
|
+
bin: string | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check whether a pre-baked image exists locally for this slug. A baked image
|
|
45
|
+
* has the server package installed at build time, so it runs offline under
|
|
46
|
+
* `network: none` without an npx/uvx fetch.
|
|
47
|
+
*
|
|
48
|
+
* Returns { image, bin } if present, else null.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveBakedImage(engine: ContainerEngine, slug: string): Promise<BakedImage | null>;
|
|
51
|
+
/**
|
|
52
|
+
* Choose a base image for the given command.
|
|
53
|
+
* - npx / npm / node / yarn / pnpm → node image
|
|
54
|
+
* - uvx / uv / python / python3 / pip → python image
|
|
55
|
+
* - anything else → default image
|
|
56
|
+
*/
|
|
57
|
+
export declare function selectImage(command: string, images?: ContainerImages): string;
|
|
58
|
+
/**
|
|
59
|
+
* Build the `docker run` / `podman run` invocation that executes the
|
|
60
|
+
* downstream server inside a constrained container.
|
|
61
|
+
*
|
|
62
|
+
* Pure function (no I/O) so the flag construction is unit-testable without a
|
|
63
|
+
* running engine. The caller supplies the scoped environment separately (via
|
|
64
|
+
* the spawn process env); here we only emit `-e NAME` forwarding flags.
|
|
65
|
+
*
|
|
66
|
+
* Enforcement applied:
|
|
67
|
+
* - Capabilities dropped (--cap-drop ALL), no privilege escalation
|
|
68
|
+
* - Read-only root filesystem + tmpfs scratch
|
|
69
|
+
* - Non-root user
|
|
70
|
+
* - Memory / CPU limits from manifest.limits
|
|
71
|
+
* - Network mode from manifest.network
|
|
72
|
+
* - Read/write mounts from manifest.filesystem
|
|
73
|
+
* - Env forwarding limited to manifest.env.allow
|
|
74
|
+
*/
|
|
75
|
+
export interface ContainerBuildOptions {
|
|
76
|
+
images?: ContainerImages;
|
|
77
|
+
/**
|
|
78
|
+
* Egress proxy URL for `network: allowlist` mode. When set, the container is
|
|
79
|
+
* given HTTP(S)_PROXY env vars pointing here and a host.docker.internal
|
|
80
|
+
* mapping so proxy-aware clients route through the gateway's allowlist filter.
|
|
81
|
+
*/
|
|
82
|
+
egressProxyUrl?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Pre-baked image (from resolveBakedImage). When set, this image is used
|
|
85
|
+
* instead of a generic base, and the baked bin is run directly (offline) —
|
|
86
|
+
* enabling true `network: none`. npx cannot resolve a globally-installed
|
|
87
|
+
* scoped package offline, so we invoke the bin instead.
|
|
88
|
+
*/
|
|
89
|
+
bakedImage?: BakedImage;
|
|
90
|
+
}
|
|
91
|
+
export declare function buildContainerCommand(engine: ContainerEngine, manifest: CapabilityManifest, command: string, args: string[], opts?: ContainerBuildOptions): WrappedSpawn;
|