@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.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +130 -0
  3. package/dist/ads/ad-tracker.d.ts +63 -0
  4. package/dist/ads/ad-tracker.js +144 -0
  5. package/dist/ads/ad-tracker.js.map +1 -0
  6. package/dist/analytics/usage-tracker.d.ts +67 -0
  7. package/dist/analytics/usage-tracker.js +148 -0
  8. package/dist/analytics/usage-tracker.js.map +1 -0
  9. package/dist/audit/audit-log.d.ts +71 -0
  10. package/dist/audit/audit-log.js +72 -0
  11. package/dist/audit/audit-log.js.map +1 -0
  12. package/dist/config/gateway-config.d.ts +6 -0
  13. package/dist/config/gateway-config.js +135 -0
  14. package/dist/config/gateway-config.js.map +1 -0
  15. package/dist/config/groups.d.ts +29 -0
  16. package/dist/config/groups.js +102 -0
  17. package/dist/config/groups.js.map +1 -0
  18. package/dist/config/profiles.d.ts +42 -0
  19. package/dist/config/profiles.js +167 -0
  20. package/dist/config/profiles.js.map +1 -0
  21. package/dist/config/types.d.ts +76 -0
  22. package/dist/config/types.js +2 -0
  23. package/dist/config/types.js.map +1 -0
  24. package/dist/connection/auto-installer.d.ts +13 -0
  25. package/dist/connection/auto-installer.js +61 -0
  26. package/dist/connection/auto-installer.js.map +1 -0
  27. package/dist/connection/connection-manager.d.ts +106 -0
  28. package/dist/connection/connection-manager.js +845 -0
  29. package/dist/connection/connection-manager.js.map +1 -0
  30. package/dist/connection/downstream-client.d.ts +50 -0
  31. package/dist/connection/downstream-client.js +170 -0
  32. package/dist/connection/downstream-client.js.map +1 -0
  33. package/dist/connection/http-client.d.ts +12 -0
  34. package/dist/connection/http-client.js +26 -0
  35. package/dist/connection/http-client.js.map +1 -0
  36. package/dist/connection/sse-client.d.ts +12 -0
  37. package/dist/connection/sse-client.js +26 -0
  38. package/dist/connection/sse-client.js.map +1 -0
  39. package/dist/connection/transport-factory.d.ts +31 -0
  40. package/dist/connection/transport-factory.js +67 -0
  41. package/dist/connection/transport-factory.js.map +1 -0
  42. package/dist/connection/types.d.ts +134 -0
  43. package/dist/connection/types.js +5 -0
  44. package/dist/connection/types.js.map +1 -0
  45. package/dist/connection/ws-client.d.ts +12 -0
  46. package/dist/connection/ws-client.js +26 -0
  47. package/dist/connection/ws-client.js.map +1 -0
  48. package/dist/discovery/auto-recommender.d.ts +51 -0
  49. package/dist/discovery/auto-recommender.js +176 -0
  50. package/dist/discovery/auto-recommender.js.map +1 -0
  51. package/dist/gateway-server.d.ts +42 -0
  52. package/dist/gateway-server.js +135 -0
  53. package/dist/gateway-server.js.map +1 -0
  54. package/dist/http-daemon.d.ts +26 -0
  55. package/dist/http-daemon.js +302 -0
  56. package/dist/http-daemon.js.map +1 -0
  57. package/dist/index.d.ts +2 -0
  58. package/dist/index.js +83 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/meta-tools/ad-status.d.ts +8 -0
  61. package/dist/meta-tools/ad-status.js +41 -0
  62. package/dist/meta-tools/ad-status.js.map +1 -0
  63. package/dist/meta-tools/audit.d.ts +12 -0
  64. package/dist/meta-tools/audit.js +98 -0
  65. package/dist/meta-tools/audit.js.map +1 -0
  66. package/dist/meta-tools/call-tool.d.ts +11 -0
  67. package/dist/meta-tools/call-tool.js +65 -0
  68. package/dist/meta-tools/call-tool.js.map +1 -0
  69. package/dist/meta-tools/connect.d.ts +3 -0
  70. package/dist/meta-tools/connect.js +105 -0
  71. package/dist/meta-tools/connect.js.map +1 -0
  72. package/dist/meta-tools/disconnect.d.ts +3 -0
  73. package/dist/meta-tools/disconnect.js +30 -0
  74. package/dist/meta-tools/disconnect.js.map +1 -0
  75. package/dist/meta-tools/discover.d.ts +3 -0
  76. package/dist/meta-tools/discover.js +97 -0
  77. package/dist/meta-tools/discover.js.map +1 -0
  78. package/dist/meta-tools/groups.d.ts +7 -0
  79. package/dist/meta-tools/groups.js +237 -0
  80. package/dist/meta-tools/groups.js.map +1 -0
  81. package/dist/meta-tools/health.d.ts +4 -0
  82. package/dist/meta-tools/health.js +76 -0
  83. package/dist/meta-tools/health.js.map +1 -0
  84. package/dist/meta-tools/index.d.ts +28 -0
  85. package/dist/meta-tools/index.js +56 -0
  86. package/dist/meta-tools/index.js.map +1 -0
  87. package/dist/meta-tools/list-active.d.ts +3 -0
  88. package/dist/meta-tools/list-active.js +50 -0
  89. package/dist/meta-tools/list-active.js.map +1 -0
  90. package/dist/meta-tools/profiles.d.ts +6 -0
  91. package/dist/meta-tools/profiles.js +197 -0
  92. package/dist/meta-tools/profiles.js.map +1 -0
  93. package/dist/meta-tools/recommend.d.ts +14 -0
  94. package/dist/meta-tools/recommend.js +74 -0
  95. package/dist/meta-tools/recommend.js.map +1 -0
  96. package/dist/meta-tools/sandbox.d.ts +12 -0
  97. package/dist/meta-tools/sandbox.js +125 -0
  98. package/dist/meta-tools/sandbox.js.map +1 -0
  99. package/dist/meta-tools/server-info.d.ts +4 -0
  100. package/dist/meta-tools/server-info.js +156 -0
  101. package/dist/meta-tools/server-info.js.map +1 -0
  102. package/dist/meta-tools/usage.d.ts +6 -0
  103. package/dist/meta-tools/usage.js +149 -0
  104. package/dist/meta-tools/usage.js.map +1 -0
  105. package/dist/permissions/permission-manager.d.ts +26 -0
  106. package/dist/permissions/permission-manager.js +73 -0
  107. package/dist/permissions/permission-manager.js.map +1 -0
  108. package/dist/permissions/trust-tiers.d.ts +18 -0
  109. package/dist/permissions/trust-tiers.js +42 -0
  110. package/dist/permissions/trust-tiers.js.map +1 -0
  111. package/dist/plugins/builtin/logging-plugin.d.ts +6 -0
  112. package/dist/plugins/builtin/logging-plugin.js +41 -0
  113. package/dist/plugins/builtin/logging-plugin.js.map +1 -0
  114. package/dist/plugins/plugin-manager.d.ts +65 -0
  115. package/dist/plugins/plugin-manager.js +137 -0
  116. package/dist/plugins/plugin-manager.js.map +1 -0
  117. package/dist/proxy/prime-handlers.d.ts +27 -0
  118. package/dist/proxy/prime-handlers.js +47 -0
  119. package/dist/proxy/prime-handlers.js.map +1 -0
  120. package/dist/proxy/progress-forwarder.d.ts +44 -0
  121. package/dist/proxy/progress-forwarder.js +40 -0
  122. package/dist/proxy/progress-forwarder.js.map +1 -0
  123. package/dist/proxy/prompt-router.d.ts +25 -0
  124. package/dist/proxy/prompt-router.js +110 -0
  125. package/dist/proxy/prompt-router.js.map +1 -0
  126. package/dist/proxy/resource-router.d.ts +25 -0
  127. package/dist/proxy/resource-router.js +91 -0
  128. package/dist/proxy/resource-router.js.map +1 -0
  129. package/dist/proxy/schema-adapter.d.ts +11 -0
  130. package/dist/proxy/schema-adapter.js +36 -0
  131. package/dist/proxy/schema-adapter.js.map +1 -0
  132. package/dist/proxy/task-proxy.d.ts +28 -0
  133. package/dist/proxy/task-proxy.js +186 -0
  134. package/dist/proxy/task-proxy.js.map +1 -0
  135. package/dist/proxy/tool-router.d.ts +38 -0
  136. package/dist/proxy/tool-router.js +229 -0
  137. package/dist/proxy/tool-router.js.map +1 -0
  138. package/dist/proxy/ui-detect.d.ts +22 -0
  139. package/dist/proxy/ui-detect.js +30 -0
  140. package/dist/proxy/ui-detect.js.map +1 -0
  141. package/dist/registry/registry-client.d.ts +55 -0
  142. package/dist/registry/registry-client.js +211 -0
  143. package/dist/registry/registry-client.js.map +1 -0
  144. package/dist/registry/types.d.ts +69 -0
  145. package/dist/registry/types.js +2 -0
  146. package/dist/registry/types.js.map +1 -0
  147. package/dist/sandbox/container-runtime.d.ts +91 -0
  148. package/dist/sandbox/container-runtime.js +178 -0
  149. package/dist/sandbox/container-runtime.js.map +1 -0
  150. package/dist/sandbox/egress-proxy.d.ts +51 -0
  151. package/dist/sandbox/egress-proxy.js +146 -0
  152. package/dist/sandbox/egress-proxy.js.map +1 -0
  153. package/dist/sandbox/env-scoper.d.ts +29 -0
  154. package/dist/sandbox/env-scoper.js +60 -0
  155. package/dist/sandbox/env-scoper.js.map +1 -0
  156. package/dist/sandbox/manifest-resolver.d.ts +40 -0
  157. package/dist/sandbox/manifest-resolver.js +185 -0
  158. package/dist/sandbox/manifest-resolver.js.map +1 -0
  159. package/dist/sandbox/types.d.ts +88 -0
  160. package/dist/sandbox/types.js +21 -0
  161. package/dist/sandbox/types.js.map +1 -0
  162. package/dist/utils/errors.d.ts +39 -0
  163. package/dist/utils/errors.js +67 -0
  164. package/dist/utils/errors.js.map +1 -0
  165. package/dist/utils/logger.d.ts +16 -0
  166. package/dist/utils/logger.js +51 -0
  167. package/dist/utils/logger.js.map +1 -0
  168. package/package.json +72 -0
@@ -0,0 +1,302 @@
1
+ import { createServer } from "node:http";
2
+ import { randomUUID } from "node:crypto";
3
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
4
+ import { createGatewayServer } from "./gateway-server.js";
5
+ import { RegistryClient } from "./registry/registry-client.js";
6
+ import { ManifestResolver } from "./sandbox/manifest-resolver.js";
7
+ import { log } from "./utils/logger.js";
8
+ import { dirname, join } from "node:path";
9
+ /**
10
+ * Run the gateway as a long-running HTTP daemon.
11
+ *
12
+ * Multiple MCP clients connect over Streamable HTTP. Each gets its own
13
+ * isolated session (McpServer + ConnectionManager + downstream connections),
14
+ * but all sessions share a warm RegistryClient cache and a single Manifest
15
+ * resolver (one source of truth for sandbox manifests on disk).
16
+ *
17
+ * Security: every /mcp request must carry `Authorization: Bearer <token>`.
18
+ * The token is required in daemon mode regardless of bind address.
19
+ *
20
+ * Multi-tenant: supply `tokens` (tenantId → token) to run a shared daemon
21
+ * where each tenant authenticates with its own token. Sessions are bound to
22
+ * the authenticating tenant (cross-tenant session reuse is rejected), and each
23
+ * tenant gets an isolated sandbox-manifest store. The single `token` maps to
24
+ * tenant "default" for backward compatibility.
25
+ */
26
+ export async function runHttpDaemon(config, opts) {
27
+ const { port, host } = opts;
28
+ // Build the tenant → token map. The single token (if any) becomes "default".
29
+ const tenantTokens = { ...(opts.tokens ?? {}) };
30
+ if (opts.token)
31
+ tenantTokens.default ??= opts.token;
32
+ const tenantCount = Object.keys(tenantTokens).length;
33
+ if (tenantCount === 0) {
34
+ throw new Error("HTTP daemon requires at least one auth token. Set MCP_GATEWAY_HTTP_TOKEN or MCP_GATEWAY_HTTP_TOKENS.");
35
+ }
36
+ // Precompute the expected `Bearer <token>` header per tenant for matching.
37
+ const expectedHeaders = Object.entries(tenantTokens).map(([tenant, t]) => ({ tenant, header: `Bearer ${t}` }));
38
+ // DNS-rebinding protection. If the operator didn't specify an allowlist,
39
+ // default to localhost variants on the bind port — safe for local daemons.
40
+ // When binding publicly (0.0.0.0 behind a domain), the operator should set
41
+ // MCP_GATEWAY_HTTP_ALLOWED_HOSTS to the real hostname(s).
42
+ const allowedHosts = new Set((opts.allowedHosts ?? [
43
+ `127.0.0.1:${port}`,
44
+ `localhost:${port}`,
45
+ `[::1]:${port}`,
46
+ ]).map((h) => h.toLowerCase()));
47
+ const allowedOrigins = new Set((opts.allowedOrigins ?? []).map((o) => o.toLowerCase()));
48
+ // Process-wide shared singleton: the registry cache holds public, read-only
49
+ // data, so all tenants safely share one warm cache.
50
+ const registryClient = new RegistryClient(config.registryApiUrl, config.registryCacheTtlMs, config.partnerKey);
51
+ // Sandbox manifests are tenant-private — one tenant must not see or alter
52
+ // another's sandbox config. Each tenant gets its own resolver + file,
53
+ // created lazily on first use.
54
+ const manifestResolvers = new Map();
55
+ function manifestResolverFor(tenant) {
56
+ let r = manifestResolvers.get(tenant);
57
+ if (!r) {
58
+ const safe = tenant.replace(/[^a-z0-9_.-]/gi, "-").toLowerCase();
59
+ const file = tenantCount === 1 && tenant === "default"
60
+ ? join(dirname(config.permissionsPath), "mcp-gateway-manifests.json")
61
+ : join(dirname(config.permissionsPath), `mcp-gateway-manifests-${safe}.json`);
62
+ r = new ManifestResolver(file, config.enableContainerIsolation === true);
63
+ manifestResolvers.set(tenant, r);
64
+ }
65
+ return r;
66
+ }
67
+ const sessions = new Map();
68
+ /**
69
+ * DNS-rebinding defense. Validates the Host header against the allowlist and
70
+ * (if present) the Origin header against the origin allowlist. Browsers send
71
+ * Origin; non-browser clients (agents, curl) don't — those pass the origin
72
+ * check by design, but still must pass the Host check.
73
+ *
74
+ * Returns null if OK, or a short rejection reason string.
75
+ */
76
+ function checkHostOrigin(req) {
77
+ const hostHeader = req.headers["host"];
78
+ const reqHost = Array.isArray(hostHeader) ? hostHeader[0] : hostHeader;
79
+ if (!reqHost || !allowedHosts.has(reqHost.toLowerCase())) {
80
+ return `Host "${reqHost ?? "(none)"}" not allowed`;
81
+ }
82
+ const originHeader = req.headers["origin"];
83
+ const origin = Array.isArray(originHeader) ? originHeader[0] : originHeader;
84
+ if (origin && !allowedOrigins.has(origin.toLowerCase())) {
85
+ // An Origin header means a browser made this request. Reject unless
86
+ // explicitly allowlisted — an agent daemon shouldn't take browser traffic.
87
+ return `Origin "${origin}" not allowed`;
88
+ }
89
+ return null;
90
+ }
91
+ /** Constant-time-ish compare of two strings. */
92
+ function safeEqual(a, b) {
93
+ if (a.length !== b.length)
94
+ return false;
95
+ let diff = 0;
96
+ for (let i = 0; i < a.length; i++)
97
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
98
+ return diff === 0;
99
+ }
100
+ /**
101
+ * Resolve the authenticating tenant from the bearer token. Compares against
102
+ * every tenant token (constant-time per token) so the work doesn't reveal
103
+ * which/how many tenants matched. Returns the tenant id, or null if no match.
104
+ */
105
+ function resolveTenant(req) {
106
+ const header = req.headers["authorization"];
107
+ if (!header || Array.isArray(header))
108
+ return null;
109
+ let matched = null;
110
+ for (const { tenant, header: expected } of expectedHeaders) {
111
+ if (safeEqual(header, expected))
112
+ matched = tenant;
113
+ }
114
+ return matched;
115
+ }
116
+ function sendJson(res, status, body) {
117
+ const json = JSON.stringify(body);
118
+ res.writeHead(status, { "Content-Type": "application/json" });
119
+ res.end(json);
120
+ }
121
+ async function readBody(req) {
122
+ const chunks = [];
123
+ for await (const chunk of req)
124
+ chunks.push(chunk);
125
+ if (chunks.length === 0)
126
+ return undefined;
127
+ try {
128
+ return JSON.parse(Buffer.concat(chunks).toString("utf-8"));
129
+ }
130
+ catch {
131
+ return undefined;
132
+ }
133
+ }
134
+ function isInitialize(body) {
135
+ return (typeof body === "object" &&
136
+ body !== null &&
137
+ body.method === "initialize");
138
+ }
139
+ async function createSession(tenant) {
140
+ // Build the session object first so the SDK callbacks can close over THIS
141
+ // specific session — avoids any shared/pending-state race when multiple
142
+ // clients initialize concurrently.
143
+ const session = { id: "", tenant, createdAt: new Date() };
144
+ const transport = new StreamableHTTPServerTransport({
145
+ sessionIdGenerator: () => randomUUID(),
146
+ onsessioninitialized: (sid) => {
147
+ session.id = sid;
148
+ sessions.set(sid, session);
149
+ log.info("HTTP session initialized", {
150
+ sessionId: sid,
151
+ tenant,
152
+ total: sessions.size,
153
+ });
154
+ },
155
+ onsessionclosed: (sid) => {
156
+ const s = sessions.get(sid);
157
+ if (s) {
158
+ s.context.connectionManager.disconnectAll().catch(() => { });
159
+ sessions.delete(sid);
160
+ log.info("HTTP session closed", {
161
+ sessionId: sid,
162
+ tenant: s.tenant,
163
+ total: sessions.size,
164
+ });
165
+ }
166
+ },
167
+ });
168
+ session.transport = transport;
169
+ // Each session gets its own gateway context. The registry cache is shared;
170
+ // the manifest store is the tenant's own (sandbox config stays private).
171
+ const context = createGatewayServer(config, {
172
+ registryClient,
173
+ manifestResolver: manifestResolverFor(tenant),
174
+ });
175
+ session.context = context;
176
+ await context.mcpServer.connect(transport);
177
+ context.connectionManager.startHealthChecks();
178
+ return session;
179
+ }
180
+ const server = createServer(async (req, res) => {
181
+ const url = req.url || "/";
182
+ // Health endpoint — unauthenticated, for liveness probes.
183
+ if (url === "/health" || url === "/health/live") {
184
+ return sendJson(res, 200, {
185
+ status: "ok",
186
+ sessions: sessions.size,
187
+ uptime: process.uptime(),
188
+ });
189
+ }
190
+ if (!url.startsWith("/mcp")) {
191
+ return sendJson(res, 404, { error: "Not found" });
192
+ }
193
+ // DNS-rebinding protection: validate Host/Origin before anything else.
194
+ const hostOriginError = checkHostOrigin(req);
195
+ if (hostOriginError) {
196
+ log.warn("Rejected request (host/origin)", { reason: hostOriginError });
197
+ return sendJson(res, 403, {
198
+ jsonrpc: "2.0",
199
+ error: { code: -32002, message: `Forbidden: ${hostOriginError}` },
200
+ id: null,
201
+ });
202
+ }
203
+ // Auth: always required for /mcp. Resolves which tenant the token belongs to.
204
+ const tenant = resolveTenant(req);
205
+ if (!tenant) {
206
+ res.setHeader("WWW-Authenticate", "Bearer");
207
+ return sendJson(res, 401, {
208
+ jsonrpc: "2.0",
209
+ error: { code: -32001, message: "Unauthorized: missing or invalid bearer token" },
210
+ id: null,
211
+ });
212
+ }
213
+ const sessionId = req.headers["mcp-session-id"];
214
+ const sid = Array.isArray(sessionId) ? sessionId[0] : sessionId;
215
+ try {
216
+ // Existing session → route to its transport, but only if the token's
217
+ // tenant owns it (prevents cross-tenant session hijacking).
218
+ if (sid && sessions.has(sid)) {
219
+ const session = sessions.get(sid);
220
+ if (session.tenant !== tenant) {
221
+ log.warn("Rejected cross-tenant session access", {
222
+ sessionId: sid,
223
+ sessionTenant: session.tenant,
224
+ requestTenant: tenant,
225
+ });
226
+ return sendJson(res, 403, {
227
+ jsonrpc: "2.0",
228
+ error: { code: -32003, message: "Forbidden: session belongs to another tenant" },
229
+ id: null,
230
+ });
231
+ }
232
+ const body = req.method === "POST" ? await readBody(req) : undefined;
233
+ await session.transport.handleRequest(req, res, body);
234
+ return;
235
+ }
236
+ // New session: only valid for an initialize POST without a session id.
237
+ if (req.method === "POST") {
238
+ const body = await readBody(req);
239
+ if (!sid && isInitialize(body)) {
240
+ const session = await createSession(tenant);
241
+ await session.transport.handleRequest(req, res, body);
242
+ return;
243
+ }
244
+ return sendJson(res, 400, {
245
+ jsonrpc: "2.0",
246
+ error: {
247
+ code: -32000,
248
+ message: sid
249
+ ? "Unknown session id. Re-initialize."
250
+ : "Missing session id (only initialize may omit it).",
251
+ },
252
+ id: null,
253
+ });
254
+ }
255
+ // GET/DELETE without a known session.
256
+ return sendJson(res, 400, {
257
+ jsonrpc: "2.0",
258
+ error: { code: -32000, message: "No active session for this request." },
259
+ id: null,
260
+ });
261
+ }
262
+ catch (err) {
263
+ log.error("HTTP request handling failed", { error: String(err) });
264
+ if (!res.headersSent) {
265
+ sendJson(res, 500, {
266
+ jsonrpc: "2.0",
267
+ error: { code: -32603, message: "Internal error" },
268
+ id: null,
269
+ });
270
+ }
271
+ }
272
+ });
273
+ // Graceful shutdown.
274
+ const shutdown = async () => {
275
+ log.info("HTTP daemon shutting down", { sessions: sessions.size });
276
+ for (const session of sessions.values()) {
277
+ try {
278
+ await session.context.connectionManager.disconnectAll();
279
+ await session.context.mcpServer.close();
280
+ }
281
+ catch {
282
+ /* best effort */
283
+ }
284
+ }
285
+ sessions.clear();
286
+ server.close(() => process.exit(0));
287
+ };
288
+ process.on("SIGINT", shutdown);
289
+ process.on("SIGTERM", shutdown);
290
+ await new Promise((resolve) => {
291
+ server.listen(port, host, () => {
292
+ log.info("MCP Gateway HTTP daemon listening", {
293
+ url: `http://${host}:${port}/mcp`,
294
+ health: `http://${host}:${port}/health`,
295
+ authRequired: true,
296
+ tenants: tenantCount,
297
+ });
298
+ resolve();
299
+ });
300
+ });
301
+ }
302
+ //# sourceMappingURL=http-daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-daemon.js","sourceRoot":"","sources":["../src/http-daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createGatewayServer } from "./gateway-server.js";
4
+ import { runHttpDaemon } from "./http-daemon.js";
5
+ import { loadConfig } from "./config/gateway-config.js";
6
+ import { setLogLevel, log } from "./utils/logger.js";
7
+ async function main() {
8
+ const config = loadConfig();
9
+ setLogLevel(config.logLevel);
10
+ // HTTP daemon mode: when a port is configured, run as a long-running HTTP
11
+ // server that many MCP clients can connect to. Otherwise, classic stdio.
12
+ if (config.httpPort) {
13
+ log.info("Starting MCP Gateway (HTTP daemon mode)", {
14
+ registryApiUrl: config.registryApiUrl,
15
+ port: config.httpPort,
16
+ host: config.httpHost,
17
+ });
18
+ const hasToken = Boolean(config.httpToken) ||
19
+ (config.httpTokens && Object.keys(config.httpTokens).length > 0);
20
+ if (!hasToken) {
21
+ process.stderr.write("MCP Gateway HTTP daemon requires MCP_GATEWAY_HTTP_TOKEN or MCP_GATEWAY_HTTP_TOKENS to be set.\n");
22
+ process.exit(1);
23
+ }
24
+ await runHttpDaemon(config, {
25
+ port: config.httpPort,
26
+ host: config.httpHost || "127.0.0.1",
27
+ token: config.httpToken,
28
+ tokens: config.httpTokens,
29
+ allowedHosts: config.httpAllowedHosts,
30
+ allowedOrigins: config.httpAllowedOrigins,
31
+ });
32
+ return;
33
+ }
34
+ log.info("Starting MCP Gateway", {
35
+ registryApiUrl: config.registryApiUrl,
36
+ maxConnections: config.maxConnections,
37
+ });
38
+ const { mcpServer, connectionManager } = createGatewayServer(config);
39
+ const transport = new StdioServerTransport();
40
+ // Graceful shutdown — only run once
41
+ let shuttingDown = false;
42
+ const cleanup = async () => {
43
+ if (shuttingDown)
44
+ return;
45
+ shuttingDown = true;
46
+ log.info("Gateway shutting down...");
47
+ try {
48
+ await connectionManager.disconnectAll();
49
+ }
50
+ catch (err) {
51
+ log.warn("Error during disconnectAll", { error: String(err) });
52
+ }
53
+ try {
54
+ await mcpServer.close();
55
+ }
56
+ catch (err) {
57
+ log.warn("Error closing MCP server", { error: String(err) });
58
+ }
59
+ process.exit(0);
60
+ };
61
+ process.on("SIGINT", cleanup);
62
+ process.on("SIGTERM", cleanup);
63
+ // Safety nets for unhandled errors — log but don't crash the gateway
64
+ process.on("uncaughtException", (err) => {
65
+ log.error("Uncaught exception", { error: String(err), stack: err.stack });
66
+ });
67
+ process.on("unhandledRejection", (reason) => {
68
+ log.error("Unhandled rejection", { reason: String(reason) });
69
+ });
70
+ await mcpServer.connect(transport);
71
+ log.info("MCP Gateway connected and ready");
72
+ // Start health monitoring
73
+ connectionManager.startHealthChecks();
74
+ // Auto-connect from saved profiles (fire-and-forget)
75
+ connectionManager.autoConnectFromProfiles().catch((err) => {
76
+ log.warn("Error during auto-connect from profiles", { error: String(err) });
77
+ });
78
+ }
79
+ main().catch((err) => {
80
+ process.stderr.write(`MCP Gateway fatal error: ${String(err)}\n`);
81
+ process.exit(1);
82
+ });
83
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ConnectionManager } from "../connection/connection-manager.js";
3
+ import type { AdTracker } from "../ads/ad-tracker.js";
4
+ /**
5
+ * Register the mcp_ad_status meta-tool.
6
+ * Shows partner earnings, tracked events, and which connected servers are promoted.
7
+ */
8
+ export declare function registerAdStatus(server: McpServer, connectionManager: ConnectionManager, adTracker: AdTracker): void;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Register the mcp_ad_status meta-tool.
3
+ * Shows partner earnings, tracked events, and which connected servers are promoted.
4
+ */
5
+ export function registerAdStatus(server, connectionManager, adTracker) {
6
+ server.tool("mcp_ad_status", "View partner ad earnings, tracked events (connects, tool usage), and ad network status for this gateway session.", {}, async () => {
7
+ const status = adTracker.getStatus();
8
+ const earnings = await adTracker.getPartnerEarnings();
9
+ const connections = connectionManager.listConnections();
10
+ const lines = [
11
+ "## Ad Network Status",
12
+ "",
13
+ `**Session ID:** ${status.sessionId}`,
14
+ `**Partner Key:** Configured`,
15
+ "",
16
+ "### Event Tracking",
17
+ `- **Connect events:** ${status.eventCounts.connect}`,
18
+ `- **Tool usage events:** ${status.eventCounts.tool_usage}`,
19
+ `- **Total tracked:** ${status.totalEvents}`,
20
+ "",
21
+ ];
22
+ if (earnings) {
23
+ lines.push("### Partner Earnings", `- **Total gross:** $${(earnings.totalGrossCents / 100).toFixed(2)}`, `- **Your share:** $${(earnings.totalPartnerShareCents / 100).toFixed(2)}`, `- **Revenue events:** ${earnings.eventCount}`, "");
24
+ }
25
+ else {
26
+ lines.push("### Partner Earnings", "*Unable to fetch earnings from registry.*", "");
27
+ }
28
+ // Show connected servers
29
+ if (connections.length > 0) {
30
+ lines.push("### Connected Servers", ...connections.map((c) => `- **${c.displayName}** (\`${c.slug}\`) — ${c.state}`), "");
31
+ }
32
+ // Show recent events
33
+ if (status.recentEvents.length > 0) {
34
+ lines.push("### Recent Events (last 10)", ...status.recentEvents.map((e) => `- \`${e.eventType}\` on **${e.serverSlug}**${e.toolName ? ` (tool: ${e.toolName})` : ""} at ${e.timestamp}`));
35
+ }
36
+ return {
37
+ content: [{ type: "text", text: lines.join("\n") }],
38
+ };
39
+ });
40
+ }
41
+ //# sourceMappingURL=ad-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ad-status.js","sourceRoot":"","sources":["../../src/meta-tools/ad-status.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAiB,EACjB,iBAAoC,EACpC,SAAoB;IAEpB,MAAM,CAAC,IAAI,CACT,eAAe,EACf,kHAAkH,EAClH,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,kBAAkB,EAAE,CAAC;QACtD,MAAM,WAAW,GAAG,iBAAiB,CAAC,eAAe,EAAE,CAAC;QAExD,MAAM,KAAK,GAAa;YACtB,sBAAsB;YACtB,EAAE;YACF,mBAAmB,MAAM,CAAC,SAAS,EAAE;YACrC,6BAA6B;YAC7B,EAAE;YACF,oBAAoB;YACpB,yBAAyB,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE;YACrD,4BAA4B,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE;YAC3D,wBAAwB,MAAM,CAAC,WAAW,EAAE;YAC5C,EAAE;SACH,CAAC;QAEF,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,CAAC,IAAI,CACR,sBAAsB,EACtB,uBAAuB,CAAC,QAAQ,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EACpE,sBAAsB,CAAC,QAAQ,CAAC,sBAAsB,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAC1E,yBAAyB,QAAQ,CAAC,UAAU,EAAE,EAC9C,EAAE,CACH,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CACR,sBAAsB,EACtB,2CAA2C,EAC3C,EAAE,CACH,CAAC;QACJ,CAAC;QAED,yBAAyB;QACzB,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CACR,uBAAuB,EACvB,GAAG,WAAW,CAAC,GAAG,CAChB,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,WAAW,SAAS,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,KAAK,EAAE,CAC7D,EACD,EAAE,CACH,CAAC;QACJ,CAAC;QAED,qBAAqB;QACrB,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CACR,6BAA6B,EAC7B,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CACxB,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,CAC/G,CACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;SACpD,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { AuditLog } from "../audit/audit-log.js";
3
+ /**
4
+ * Register the `mcp_audit` meta-tool — the safety forensics view.
5
+ *
6
+ * Surfaces the audit trail of what sandboxed servers actually did and what the
7
+ * sandbox blocked: tool calls (under their enforcement level), blocked tools,
8
+ * blocked/allowed network egress, connects (with granted capability envelope),
9
+ * and disconnects. This is the "did this untrusted server try anything?"
10
+ * artifact a security reviewer reads — distinct from usage analytics.
11
+ */
12
+ export declare function registerAudit(server: McpServer, auditLog: AuditLog): void;
@@ -0,0 +1,98 @@
1
+ import { z } from "zod";
2
+ import { toolError } from "../utils/errors.js";
3
+ /**
4
+ * Register the `mcp_audit` meta-tool — the safety forensics view.
5
+ *
6
+ * Surfaces the audit trail of what sandboxed servers actually did and what the
7
+ * sandbox blocked: tool calls (under their enforcement level), blocked tools,
8
+ * blocked/allowed network egress, connects (with granted capability envelope),
9
+ * and disconnects. This is the "did this untrusted server try anything?"
10
+ * artifact a security reviewer reads — distinct from usage analytics.
11
+ */
12
+ export function registerAudit(server, auditLog) {
13
+ server.tool("mcp_audit", "View the safety audit trail — a forensics log of what sandboxed MCP servers did and what the sandbox blocked (tool calls, blocked tools, blocked/allowed network egress, connects with granted capabilities). Use `securityOnly: true` to see only blocks and errors.", {
14
+ slug: z
15
+ .string()
16
+ .optional()
17
+ .describe("Filter to a single server slug"),
18
+ event: z
19
+ .enum([
20
+ "connect",
21
+ "tool_call",
22
+ "tool_blocked",
23
+ "egress_blocked",
24
+ "egress_allowed",
25
+ "disconnect",
26
+ ])
27
+ .optional()
28
+ .describe("Filter to a single event type"),
29
+ securityOnly: z
30
+ .boolean()
31
+ .optional()
32
+ .describe("Show only security-relevant events (blocks + errored calls)"),
33
+ limit: z
34
+ .number()
35
+ .min(1)
36
+ .max(500)
37
+ .optional()
38
+ .describe("Max events to return (default 50, newest first)"),
39
+ }, async ({ slug, event, securityOnly, limit = 50 }) => {
40
+ try {
41
+ const events = auditLog.query({
42
+ slug,
43
+ type: event,
44
+ securityRelevantOnly: securityOnly,
45
+ limit,
46
+ });
47
+ const summary = auditLog.summary();
48
+ const lines = [
49
+ "## 🛡️ Safety Audit Trail",
50
+ "",
51
+ `**Totals:** ${summary.total} events · ${summary.securityEvents} security-relevant (blocks)`,
52
+ `**By type:** ` +
53
+ Object.entries(summary.counts)
54
+ .filter(([, n]) => n > 0)
55
+ .map(([t, n]) => `${t}=${n}`)
56
+ .join(", "),
57
+ "",
58
+ ];
59
+ if (events.length === 0) {
60
+ lines.push("_No matching events recorded yet._");
61
+ }
62
+ else {
63
+ lines.push(`### Recent events (${events.length})`, "");
64
+ for (const e of events) {
65
+ const icon = e.type === "tool_blocked" || e.type === "egress_blocked"
66
+ ? "🚫"
67
+ : e.type === "tool_call" && e.ok === false
68
+ ? "⚠️"
69
+ : e.type === "egress_allowed"
70
+ ? "🌐"
71
+ : e.type === "connect"
72
+ ? "🔗"
73
+ : e.type === "disconnect"
74
+ ? "🔌"
75
+ : "•";
76
+ const parts = [
77
+ `${icon} \`${e.ts}\``,
78
+ `**${e.type}**`,
79
+ e.slug,
80
+ e.tool ? `tool=${e.tool}` : "",
81
+ e.target ? `target=${e.target}` : "",
82
+ e.enforcement ? `[${e.enforcement}]` : "",
83
+ e.reason ? `— ${e.reason}` : "",
84
+ ].filter(Boolean);
85
+ lines.push("- " + parts.join(" · "));
86
+ }
87
+ }
88
+ return {
89
+ content: [{ type: "text", text: lines.join("\n") }],
90
+ structuredContent: { summary, events },
91
+ };
92
+ }
93
+ catch (err) {
94
+ return toolError(err instanceof Error ? err.message : String(err));
95
+ }
96
+ });
97
+ }
98
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/meta-tools/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ConnectionManager } from "../connection/connection-manager.js";
3
+ /**
4
+ * Register the `mcp_call_tool` meta-tool.
5
+ *
6
+ * This is a fallback for MCP clients that don't refresh their tool list
7
+ * when `notifications/tools/list_changed` fires. The AI can call any
8
+ * tool on any connected downstream server by passing the namespaced
9
+ * tool name (e.g. "server-slug__echo") and a JSON arguments object.
10
+ */
11
+ export declare function registerCallTool(server: McpServer, connectionManager: ConnectionManager): void;