@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 @@
|
|
|
1
|
+
{"version":3,"file":"trust-tiers.js","sourceRoot":"","sources":["../../src/permissions/trust-tiers.ts"],"names":[],"mappings":"AAEA,yDAAyD;AACzD,MAAM,CAAC,MAAM,YAAY,GAA8B;IACrD,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,OAAO,EAAE,YAAY;CACtB,CAAC;AAEF,uDAAuD;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAA8B;IAC/D,QAAQ,EAAE,EAAE;IACZ,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,OAAO,EAAE,CAAC;CACX,CAAC;AAYF,sCAAsC;AACtC,MAAM,CAAC,MAAM,sBAAsB,GAAmC;IACpE,QAAQ,EAAE;QACR,oBAAoB,EAAE,KAAK;QAC3B,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,sDAAsD;KACpE;IACD,OAAO,EAAE;QACP,oBAAoB,EAAE,KAAK;QAC3B,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,oEAAoE;KAClF;IACD,SAAS,EAAE;QACT,oBAAoB,EAAE,IAAI;QAC1B,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,0FAA0F;KACxG;IACD,OAAO,EAAE;QACP,oBAAoB,EAAE,IAAI;QAC1B,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,iEAAiE;KAC/E;CACF,CAAC;AAEF,4CAA4C;AAC5C,MAAM,UAAU,cAAc,CAAC,IAAe;IAC5C,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { GatewayPlugin } from "../plugin-manager.js";
|
|
2
|
+
/**
|
|
3
|
+
* Built-in logging plugin that logs all tool calls, connections, and disconnections.
|
|
4
|
+
* Serves as both a default plugin and an example for custom plugin development.
|
|
5
|
+
*/
|
|
6
|
+
export declare const loggingPlugin: GatewayPlugin;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { log } from "../../utils/logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Built-in logging plugin that logs all tool calls, connections, and disconnections.
|
|
4
|
+
* Serves as both a default plugin and an example for custom plugin development.
|
|
5
|
+
*/
|
|
6
|
+
export const loggingPlugin = {
|
|
7
|
+
name: "builtin-logging",
|
|
8
|
+
version: "1.0.0",
|
|
9
|
+
async beforeToolCall(ctx) {
|
|
10
|
+
log.debug("[plugin:logging] Tool call starting", {
|
|
11
|
+
slug: ctx.slug,
|
|
12
|
+
tool: ctx.toolName,
|
|
13
|
+
trustTier: ctx.trustTier,
|
|
14
|
+
argKeys: Object.keys(ctx.args),
|
|
15
|
+
});
|
|
16
|
+
return ctx;
|
|
17
|
+
},
|
|
18
|
+
async afterToolCall(ctx, result) {
|
|
19
|
+
log.debug("[plugin:logging] Tool call completed", {
|
|
20
|
+
slug: ctx.slug,
|
|
21
|
+
tool: ctx.toolName,
|
|
22
|
+
isError: result.isError ?? false,
|
|
23
|
+
contentCount: result.content?.length ?? 0,
|
|
24
|
+
});
|
|
25
|
+
return result;
|
|
26
|
+
},
|
|
27
|
+
async onConnect(connection) {
|
|
28
|
+
log.debug("[plugin:logging] Server connected", {
|
|
29
|
+
slug: connection.slug,
|
|
30
|
+
displayName: connection.displayName,
|
|
31
|
+
transportType: connection.transportType,
|
|
32
|
+
toolCount: connection.toolCount,
|
|
33
|
+
resourceCount: connection.resourceCount,
|
|
34
|
+
promptCount: connection.promptCount,
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
async onDisconnect(slug) {
|
|
38
|
+
log.debug("[plugin:logging] Server disconnected", { slug });
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=logging-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-plugin.js","sourceRoot":"","sources":["../../../src/plugins/builtin/logging-plugin.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAE5C;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,OAAO;IAEhB,KAAK,CAAC,cAAc,CAAC,GAAoB;QACvC,GAAG,CAAC,KAAK,CAAC,qCAAqC,EAAE;YAC/C,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,QAAQ;YAClB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;SAC/B,CAAC,CAAC;QACH,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,GAAoB,EACpB,MAAsB;QAEtB,GAAG,CAAC,KAAK,CAAC,sCAAsC,EAAE;YAChD,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,QAAQ;YAClB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;YAChC,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;SAC1C,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,UAA6B;QAC3C,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE;YAC7C,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,WAAW,EAAE,UAAU,CAAC,WAAW;YACnC,aAAa,EAAE,UAAU,CAAC,aAAa;YACvC,SAAS,EAAE,UAAU,CAAC,SAAS;YAC/B,aAAa,EAAE,UAAU,CAAC,aAAa;YACvC,WAAW,EAAE,UAAU,CAAC,WAAW;SACpC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY;QAC7B,GAAG,CAAC,KAAK,CAAC,sCAAsC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type { ConnectionSummary } from "../connection/types.js";
|
|
3
|
+
import type { TrustTier } from "../registry/types.js";
|
|
4
|
+
export interface ToolCallContext {
|
|
5
|
+
slug: string;
|
|
6
|
+
toolName: string;
|
|
7
|
+
args: Record<string, unknown>;
|
|
8
|
+
trustTier: TrustTier;
|
|
9
|
+
}
|
|
10
|
+
export interface GatewayPlugin {
|
|
11
|
+
name: string;
|
|
12
|
+
version?: string;
|
|
13
|
+
/** Called before a proxied tool call is forwarded downstream */
|
|
14
|
+
beforeToolCall?(context: ToolCallContext): Promise<ToolCallContext | null>;
|
|
15
|
+
/** Called after a proxied tool call returns */
|
|
16
|
+
afterToolCall?(context: ToolCallContext, result: CallToolResult): Promise<CallToolResult>;
|
|
17
|
+
/** Called when a server connects */
|
|
18
|
+
onConnect?(connection: ConnectionSummary): Promise<void>;
|
|
19
|
+
/** Called when a server disconnects */
|
|
20
|
+
onDisconnect?(slug: string): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Manages gateway plugins and runs lifecycle hooks.
|
|
24
|
+
*
|
|
25
|
+
* Plugins are run in registration order.
|
|
26
|
+
* `beforeToolCall` returning null blocks the call.
|
|
27
|
+
* Errors in plugins are logged but don't block the call (fault-tolerant).
|
|
28
|
+
*/
|
|
29
|
+
export declare class PluginManager {
|
|
30
|
+
private plugins;
|
|
31
|
+
/**
|
|
32
|
+
* Register a plugin.
|
|
33
|
+
*/
|
|
34
|
+
register(plugin: GatewayPlugin): void;
|
|
35
|
+
/**
|
|
36
|
+
* Unregister a plugin by name.
|
|
37
|
+
*/
|
|
38
|
+
unregister(name: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* List all registered plugins.
|
|
41
|
+
*/
|
|
42
|
+
listPlugins(): Array<{
|
|
43
|
+
name: string;
|
|
44
|
+
version?: string;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Run beforeToolCall hooks in order.
|
|
48
|
+
* Returns null if any plugin blocks the call.
|
|
49
|
+
* Returns the (potentially modified) context otherwise.
|
|
50
|
+
*/
|
|
51
|
+
runBeforeToolCall(ctx: ToolCallContext): Promise<ToolCallContext | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Run afterToolCall hooks in order.
|
|
54
|
+
* Returns the (potentially modified) result.
|
|
55
|
+
*/
|
|
56
|
+
runAfterToolCall(ctx: ToolCallContext, result: CallToolResult): Promise<CallToolResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Run onConnect hooks for all plugins.
|
|
59
|
+
*/
|
|
60
|
+
runOnConnect(connection: ConnectionSummary): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Run onDisconnect hooks for all plugins.
|
|
63
|
+
*/
|
|
64
|
+
runOnDisconnect(slug: string): Promise<void>;
|
|
65
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { log } from "../utils/logger.js";
|
|
2
|
+
// ── Plugin Manager ───────────────────────────────────────────────────────────
|
|
3
|
+
/**
|
|
4
|
+
* Manages gateway plugins and runs lifecycle hooks.
|
|
5
|
+
*
|
|
6
|
+
* Plugins are run in registration order.
|
|
7
|
+
* `beforeToolCall` returning null blocks the call.
|
|
8
|
+
* Errors in plugins are logged but don't block the call (fault-tolerant).
|
|
9
|
+
*/
|
|
10
|
+
export class PluginManager {
|
|
11
|
+
plugins = [];
|
|
12
|
+
/**
|
|
13
|
+
* Register a plugin.
|
|
14
|
+
*/
|
|
15
|
+
register(plugin) {
|
|
16
|
+
// Don't double-register
|
|
17
|
+
if (this.plugins.some((p) => p.name === plugin.name)) {
|
|
18
|
+
log.warn("Plugin already registered, replacing", { name: plugin.name });
|
|
19
|
+
this.plugins = this.plugins.filter((p) => p.name !== plugin.name);
|
|
20
|
+
}
|
|
21
|
+
this.plugins.push(plugin);
|
|
22
|
+
log.info("Plugin registered", {
|
|
23
|
+
name: plugin.name,
|
|
24
|
+
version: plugin.version,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Unregister a plugin by name.
|
|
29
|
+
*/
|
|
30
|
+
unregister(name) {
|
|
31
|
+
const before = this.plugins.length;
|
|
32
|
+
this.plugins = this.plugins.filter((p) => p.name !== name);
|
|
33
|
+
if (this.plugins.length < before) {
|
|
34
|
+
log.info("Plugin unregistered", { name });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* List all registered plugins.
|
|
39
|
+
*/
|
|
40
|
+
listPlugins() {
|
|
41
|
+
return this.plugins.map((p) => ({
|
|
42
|
+
name: p.name,
|
|
43
|
+
version: p.version,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Run beforeToolCall hooks in order.
|
|
48
|
+
* Returns null if any plugin blocks the call.
|
|
49
|
+
* Returns the (potentially modified) context otherwise.
|
|
50
|
+
*/
|
|
51
|
+
async runBeforeToolCall(ctx) {
|
|
52
|
+
let currentCtx = ctx;
|
|
53
|
+
for (const plugin of this.plugins) {
|
|
54
|
+
if (!plugin.beforeToolCall)
|
|
55
|
+
continue;
|
|
56
|
+
try {
|
|
57
|
+
const result = await plugin.beforeToolCall(currentCtx);
|
|
58
|
+
if (result === null) {
|
|
59
|
+
log.info("Tool call blocked by plugin", {
|
|
60
|
+
plugin: plugin.name,
|
|
61
|
+
tool: ctx.toolName,
|
|
62
|
+
server: ctx.slug,
|
|
63
|
+
});
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
currentCtx = result;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
log.warn("Plugin beforeToolCall error (continuing)", {
|
|
70
|
+
plugin: plugin.name,
|
|
71
|
+
error: String(err),
|
|
72
|
+
});
|
|
73
|
+
// Continue with unmodified context on error
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return currentCtx;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Run afterToolCall hooks in order.
|
|
80
|
+
* Returns the (potentially modified) result.
|
|
81
|
+
*/
|
|
82
|
+
async runAfterToolCall(ctx, result) {
|
|
83
|
+
let currentResult = result;
|
|
84
|
+
for (const plugin of this.plugins) {
|
|
85
|
+
if (!plugin.afterToolCall)
|
|
86
|
+
continue;
|
|
87
|
+
try {
|
|
88
|
+
currentResult = await plugin.afterToolCall(ctx, currentResult);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
log.warn("Plugin afterToolCall error (continuing)", {
|
|
92
|
+
plugin: plugin.name,
|
|
93
|
+
error: String(err),
|
|
94
|
+
});
|
|
95
|
+
// Continue with unmodified result on error
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return currentResult;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Run onConnect hooks for all plugins.
|
|
102
|
+
*/
|
|
103
|
+
async runOnConnect(connection) {
|
|
104
|
+
for (const plugin of this.plugins) {
|
|
105
|
+
if (!plugin.onConnect)
|
|
106
|
+
continue;
|
|
107
|
+
try {
|
|
108
|
+
await plugin.onConnect(connection);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
log.warn("Plugin onConnect error", {
|
|
112
|
+
plugin: plugin.name,
|
|
113
|
+
error: String(err),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Run onDisconnect hooks for all plugins.
|
|
120
|
+
*/
|
|
121
|
+
async runOnDisconnect(slug) {
|
|
122
|
+
for (const plugin of this.plugins) {
|
|
123
|
+
if (!plugin.onDisconnect)
|
|
124
|
+
continue;
|
|
125
|
+
try {
|
|
126
|
+
await plugin.onDisconnect(slug);
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
log.warn("Plugin onDisconnect error", {
|
|
130
|
+
plugin: plugin.name,
|
|
131
|
+
error: String(err),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=plugin-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-manager.js","sourceRoot":"","sources":["../../src/plugins/plugin-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/**
|
|
3
|
+
* Prime the SDK's resource and prompt request handlers BEFORE the transport
|
|
4
|
+
* is connected.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists:
|
|
7
|
+
* The MCP SDK initializes resource/prompt request handlers lazily — the
|
|
8
|
+
* first time you call `mcpServer.resource()` / `mcpServer.prompt()`. That
|
|
9
|
+
* lazy init calls `server.registerCapabilities(...)`, which throws
|
|
10
|
+
* "Cannot register capabilities after connecting to transport" once a
|
|
11
|
+
* transport is attached.
|
|
12
|
+
*
|
|
13
|
+
* The gateway only registers resources/prompts dynamically — AFTER a
|
|
14
|
+
* downstream server connects (well after the gateway's own transport is up).
|
|
15
|
+
* So the first dynamic registration would throw, and downstream resources
|
|
16
|
+
* and prompts would never be proxied to the upstream client.
|
|
17
|
+
*
|
|
18
|
+
* The fix: register a throwaway resource and prompt at construction time
|
|
19
|
+
* (before connect) and immediately remove them. This flips the SDK's
|
|
20
|
+
* one-way `_resourceHandlersInitialized` / `_promptHandlersInitialized`
|
|
21
|
+
* flags and registers the capabilities while still allowed. Subsequent
|
|
22
|
+
* dynamic registrations short-circuit the lazy init and never re-register
|
|
23
|
+
* capabilities — so they no longer throw.
|
|
24
|
+
*
|
|
25
|
+
* Must be called before `mcpServer.connect(transport)`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function primeProxyHandlers(mcpServer: McpServer): void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { log } from "../utils/logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Prime the SDK's resource and prompt request handlers BEFORE the transport
|
|
4
|
+
* is connected.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists:
|
|
7
|
+
* The MCP SDK initializes resource/prompt request handlers lazily — the
|
|
8
|
+
* first time you call `mcpServer.resource()` / `mcpServer.prompt()`. That
|
|
9
|
+
* lazy init calls `server.registerCapabilities(...)`, which throws
|
|
10
|
+
* "Cannot register capabilities after connecting to transport" once a
|
|
11
|
+
* transport is attached.
|
|
12
|
+
*
|
|
13
|
+
* The gateway only registers resources/prompts dynamically — AFTER a
|
|
14
|
+
* downstream server connects (well after the gateway's own transport is up).
|
|
15
|
+
* So the first dynamic registration would throw, and downstream resources
|
|
16
|
+
* and prompts would never be proxied to the upstream client.
|
|
17
|
+
*
|
|
18
|
+
* The fix: register a throwaway resource and prompt at construction time
|
|
19
|
+
* (before connect) and immediately remove them. This flips the SDK's
|
|
20
|
+
* one-way `_resourceHandlersInitialized` / `_promptHandlersInitialized`
|
|
21
|
+
* flags and registers the capabilities while still allowed. Subsequent
|
|
22
|
+
* dynamic registrations short-circuit the lazy init and never re-register
|
|
23
|
+
* capabilities — so they no longer throw.
|
|
24
|
+
*
|
|
25
|
+
* Must be called before `mcpServer.connect(transport)`.
|
|
26
|
+
*/
|
|
27
|
+
export function primeProxyHandlers(mcpServer) {
|
|
28
|
+
// Resources
|
|
29
|
+
try {
|
|
30
|
+
const placeholder = mcpServer.resource("__gateway_capability_init__", "gateway-init://capability-priming", { description: "Internal capability-priming placeholder (removed immediately)" }, async () => ({ contents: [] }));
|
|
31
|
+
placeholder.remove();
|
|
32
|
+
log.debug("Primed resource handlers");
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
log.warn("Failed to prime resource handlers", { error: String(err) });
|
|
36
|
+
}
|
|
37
|
+
// Prompts
|
|
38
|
+
try {
|
|
39
|
+
const placeholder = mcpServer.prompt("__gateway_capability_init__", "Internal capability-priming placeholder (removed immediately)", {}, async () => ({ messages: [] }));
|
|
40
|
+
placeholder.remove();
|
|
41
|
+
log.debug("Primed prompt handlers");
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
log.warn("Failed to prime prompt handlers", { error: String(err) });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=prime-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prime-handlers.js","sourceRoot":"","sources":["../../src/proxy/prime-handlers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAoB;IACrD,YAAY;IACZ,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,SAAS,CAAC,QAAQ,CACpC,6BAA6B,EAC7B,mCAAmC,EACnC,EAAE,WAAW,EAAE,+DAA+D,EAAE,EAChF,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC/B,CAAC;QACF,WAAW,CAAC,MAAM,EAAE,CAAC;QACrB,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,UAAU;IACV,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAClC,6BAA6B,EAC7B,+DAA+D,EAC/D,EAAE,EACF,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAC/B,CAAC;QACF,WAAW,CAAC,MAAM,EAAE,CAAC;QACrB,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress notification from the downstream server's onprogress callback.
|
|
3
|
+
* Matches the MCP `notifications/progress` params shape (without progressToken,
|
|
4
|
+
* which the forwarder adds).
|
|
5
|
+
*/
|
|
6
|
+
export interface DownstreamProgress {
|
|
7
|
+
progress: number;
|
|
8
|
+
total?: number;
|
|
9
|
+
message?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Minimal slice of the upstream `RequestHandlerExtra` we need to forward
|
|
13
|
+
* progress notifications back to the original client. Typed loosely so we
|
|
14
|
+
* stay compatible with future MCP SDK changes to `RequestHandlerExtra`.
|
|
15
|
+
*/
|
|
16
|
+
export interface UpstreamProgressContext {
|
|
17
|
+
_meta?: {
|
|
18
|
+
progressToken?: string | number;
|
|
19
|
+
} | undefined;
|
|
20
|
+
sendNotification: (notification: {
|
|
21
|
+
method: "notifications/progress";
|
|
22
|
+
params: {
|
|
23
|
+
progressToken: string | number;
|
|
24
|
+
progress: number;
|
|
25
|
+
total?: number;
|
|
26
|
+
message?: string;
|
|
27
|
+
};
|
|
28
|
+
}) => Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build an `onprogress` callback that relays downstream progress events back
|
|
32
|
+
* to the upstream client using the upstream-supplied `progressToken`.
|
|
33
|
+
*
|
|
34
|
+
* Returns `undefined` when the upstream client didn't supply a progress
|
|
35
|
+
* token — in which case we skip the wiring entirely so the SDK doesn't
|
|
36
|
+
* allocate handlers we'll never invoke.
|
|
37
|
+
*
|
|
38
|
+
* Failures inside the forwarder are logged but never thrown — progress
|
|
39
|
+
* notifications are best-effort by design.
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildProgressForwarder(extra: UpstreamProgressContext | undefined, context: {
|
|
42
|
+
slug: string;
|
|
43
|
+
toolName: string;
|
|
44
|
+
}): ((progress: DownstreamProgress) => void) | undefined;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { log } from "../utils/logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build an `onprogress` callback that relays downstream progress events back
|
|
4
|
+
* to the upstream client using the upstream-supplied `progressToken`.
|
|
5
|
+
*
|
|
6
|
+
* Returns `undefined` when the upstream client didn't supply a progress
|
|
7
|
+
* token — in which case we skip the wiring entirely so the SDK doesn't
|
|
8
|
+
* allocate handlers we'll never invoke.
|
|
9
|
+
*
|
|
10
|
+
* Failures inside the forwarder are logged but never thrown — progress
|
|
11
|
+
* notifications are best-effort by design.
|
|
12
|
+
*/
|
|
13
|
+
export function buildProgressForwarder(extra, context) {
|
|
14
|
+
const upstreamToken = extra?._meta?.progressToken;
|
|
15
|
+
if (upstreamToken === undefined || !extra?.sendNotification) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return (progress) => {
|
|
19
|
+
extra
|
|
20
|
+
.sendNotification({
|
|
21
|
+
method: "notifications/progress",
|
|
22
|
+
params: {
|
|
23
|
+
progressToken: upstreamToken,
|
|
24
|
+
progress: progress.progress,
|
|
25
|
+
total: progress.total,
|
|
26
|
+
message: progress.message,
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
.catch((err) => {
|
|
30
|
+
// Best-effort: don't fail the tool call if a progress notification
|
|
31
|
+
// can't be delivered (e.g. transport already closed).
|
|
32
|
+
log.warn("Failed to forward progress notification", {
|
|
33
|
+
slug: context.slug,
|
|
34
|
+
toolName: context.toolName,
|
|
35
|
+
error: err instanceof Error ? err.message : String(err),
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=progress-forwarder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress-forwarder.js","sourceRoot":"","sources":["../../src/proxy/progress-forwarder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AA+BzC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAA0C,EAC1C,OAA2C;IAE3C,MAAM,aAAa,GAAG,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC;IAClD,IAAI,aAAa,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC5D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,CAAC,QAA4B,EAAQ,EAAE;QAC5C,KAAK;aACF,gBAAgB,CAAC;YAChB,MAAM,EAAE,wBAAwB;YAChC,MAAM,EAAE;gBACN,aAAa,EAAE,aAAa;gBAC5B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,OAAO,EAAE,QAAQ,CAAC,OAAO;aAC1B;SACF,CAAC;aACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,mEAAmE;YACnE,sDAAsD;YACtD,GAAG,CAAC,IAAI,CAAC,yCAAyC,EAAE;gBAClD,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { DownstreamConnection, DownstreamPrompt } from "../connection/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Namespace a prompt name: `{slug}__{promptname}`
|
|
5
|
+
*/
|
|
6
|
+
export declare function namespacePrompt(slug: string, promptName: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Register proxied prompts on the gateway McpServer for a downstream connection.
|
|
9
|
+
*
|
|
10
|
+
* Each downstream prompt is registered with:
|
|
11
|
+
* - Namespaced name: `slug__promptname`
|
|
12
|
+
* - Description prefixed with trust tier and server name
|
|
13
|
+
* - Get handler that forwards to `client.getPrompt()`
|
|
14
|
+
*
|
|
15
|
+
* Returns a map of namespaced name → { remove } handle for cleanup.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerProxiedPrompts(mcpServer: McpServer, connection: DownstreamConnection, downstreamPrompts: DownstreamPrompt[]): Map<string, {
|
|
18
|
+
remove: () => void;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Remove all proxied prompts for a connection.
|
|
22
|
+
*/
|
|
23
|
+
export declare function removeProxiedPrompts(proxies: Map<string, {
|
|
24
|
+
remove: () => void;
|
|
25
|
+
}>): void;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { TRUST_LABELS } from "../permissions/trust-tiers.js";
|
|
3
|
+
import { log } from "../utils/logger.js";
|
|
4
|
+
const SEPARATOR = "__";
|
|
5
|
+
/**
|
|
6
|
+
* Namespace a prompt name: `{slug}__{promptname}`
|
|
7
|
+
*/
|
|
8
|
+
export function namespacePrompt(slug, promptName) {
|
|
9
|
+
return `${slug}${SEPARATOR}${promptName}`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Register proxied prompts on the gateway McpServer for a downstream connection.
|
|
13
|
+
*
|
|
14
|
+
* Each downstream prompt is registered with:
|
|
15
|
+
* - Namespaced name: `slug__promptname`
|
|
16
|
+
* - Description prefixed with trust tier and server name
|
|
17
|
+
* - Get handler that forwards to `client.getPrompt()`
|
|
18
|
+
*
|
|
19
|
+
* Returns a map of namespaced name → { remove } handle for cleanup.
|
|
20
|
+
*/
|
|
21
|
+
export function registerProxiedPrompts(mcpServer, connection, downstreamPrompts) {
|
|
22
|
+
const registered = new Map();
|
|
23
|
+
const trustLabel = TRUST_LABELS[connection.trustTier];
|
|
24
|
+
for (const prompt of downstreamPrompts) {
|
|
25
|
+
const nsName = namespacePrompt(connection.slug, prompt.name);
|
|
26
|
+
const description = `[${trustLabel}] [${connection.displayName}] ${prompt.description || prompt.name}`;
|
|
27
|
+
log.debug("Registering proxied prompt", {
|
|
28
|
+
nsName,
|
|
29
|
+
downstream: prompt.name,
|
|
30
|
+
server: connection.slug,
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
// Build args schema from prompt arguments
|
|
34
|
+
const argsSchema = {};
|
|
35
|
+
if (prompt.arguments) {
|
|
36
|
+
for (const arg of prompt.arguments) {
|
|
37
|
+
if (arg.required) {
|
|
38
|
+
argsSchema[arg.name] = z
|
|
39
|
+
.string()
|
|
40
|
+
.describe(arg.description || arg.name);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
argsSchema[arg.name] = z
|
|
44
|
+
.string()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe(arg.description || arg.name);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const handle = mcpServer.prompt(nsName, description, argsSchema, async (args) => {
|
|
51
|
+
log.debug("Proxying prompt get", {
|
|
52
|
+
nsName,
|
|
53
|
+
downstream: prompt.name,
|
|
54
|
+
server: connection.slug,
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
// Convert args to string values for the downstream prompt
|
|
58
|
+
const stringArgs = {};
|
|
59
|
+
for (const [key, value] of Object.entries(args)) {
|
|
60
|
+
if (value !== undefined && value !== null) {
|
|
61
|
+
stringArgs[key] = String(value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const result = await connection.client.getPrompt({
|
|
65
|
+
name: prompt.name,
|
|
66
|
+
arguments: stringArgs,
|
|
67
|
+
});
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
72
|
+
log.error("Proxied prompt get failed", {
|
|
73
|
+
nsName,
|
|
74
|
+
error: msg,
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
messages: [
|
|
78
|
+
{
|
|
79
|
+
role: "user",
|
|
80
|
+
content: {
|
|
81
|
+
type: "text",
|
|
82
|
+
text: `Error getting prompt from ${connection.displayName}: ${msg}`,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
registered.set(nsName, handle);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
log.warn("Failed to register proxied prompt", {
|
|
93
|
+
nsName,
|
|
94
|
+
error: String(err),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return registered;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Remove all proxied prompts for a connection.
|
|
102
|
+
*/
|
|
103
|
+
export function removeProxiedPrompts(proxies) {
|
|
104
|
+
for (const [name, handle] of proxies) {
|
|
105
|
+
log.debug("Removing proxied prompt", { name });
|
|
106
|
+
handle.remove();
|
|
107
|
+
}
|
|
108
|
+
proxies.clear();
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=prompt-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-router.js","sourceRoot":"","sources":["../../src/proxy/prompt-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { DownstreamConnection, DownstreamResource } from "../connection/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register proxied resources on the gateway McpServer for a downstream connection.
|
|
5
|
+
*
|
|
6
|
+
* Each downstream resource is registered with:
|
|
7
|
+
* - Namespaced URI: `slug://original-uri`
|
|
8
|
+
* - Description prefixed with trust tier and server name
|
|
9
|
+
* - Read handler that forwards to downstream `client.readResource()`
|
|
10
|
+
*
|
|
11
|
+
* Returns a map of namespaced URI → { remove } handle for cleanup.
|
|
12
|
+
*/
|
|
13
|
+
export declare function registerProxiedResources(mcpServer: McpServer, connection: DownstreamConnection, downstreamResources: DownstreamResource[]): Map<string, {
|
|
14
|
+
remove: () => void;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* Remove all proxied resources for a connection.
|
|
18
|
+
*/
|
|
19
|
+
export declare function removeProxiedResources(proxies: Map<string, {
|
|
20
|
+
remove: () => void;
|
|
21
|
+
}>): void;
|
|
22
|
+
/**
|
|
23
|
+
* Namespace a resource URI: `slug://original-uri-path`
|
|
24
|
+
*/
|
|
25
|
+
export declare function namespaceResourceUri(slug: string, originalUri: string): string;
|