mandala-computer-mcp 0.5.0 → 0.6.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 (66) hide show
  1. package/README.md +119 -11
  2. package/dist/api.d.ts +47 -1
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +248 -22
  5. package/dist/api.js.map +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +17 -0
  8. package/dist/cli.js.map +1 -1
  9. package/dist/errors.d.ts +93 -2
  10. package/dist/errors.d.ts.map +1 -1
  11. package/dist/errors.js +166 -7
  12. package/dist/errors.js.map +1 -1
  13. package/dist/format.d.ts +25 -0
  14. package/dist/format.d.ts.map +1 -1
  15. package/dist/format.js +31 -2
  16. package/dist/format.js.map +1 -1
  17. package/dist/http.d.ts +42 -0
  18. package/dist/http.d.ts.map +1 -1
  19. package/dist/http.js +379 -3
  20. package/dist/http.js.map +1 -1
  21. package/dist/index.d.ts +4 -3
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +3 -3
  24. package/dist/index.js.map +1 -1
  25. package/dist/paths.d.ts +10 -2
  26. package/dist/paths.d.ts.map +1 -1
  27. package/dist/paths.js +15 -5
  28. package/dist/paths.js.map +1 -1
  29. package/dist/secret-errors.d.ts +59 -0
  30. package/dist/secret-errors.d.ts.map +1 -0
  31. package/dist/secret-errors.js +199 -0
  32. package/dist/secret-errors.js.map +1 -0
  33. package/dist/secret-store.d.ts +115 -0
  34. package/dist/secret-store.d.ts.map +1 -0
  35. package/dist/secret-store.js +105 -0
  36. package/dist/secret-store.js.map +1 -0
  37. package/dist/server.d.ts +1 -1
  38. package/dist/server.js +1 -1
  39. package/dist/session.d.ts +6 -1
  40. package/dist/session.d.ts.map +1 -1
  41. package/dist/session.js +1 -1
  42. package/dist/session.js.map +1 -1
  43. package/dist/tool-filters.d.ts +1 -1
  44. package/dist/tool-filters.d.ts.map +1 -1
  45. package/dist/tool-filters.js +9 -1
  46. package/dist/tool-filters.js.map +1 -1
  47. package/dist/tools/computers.d.ts.map +1 -1
  48. package/dist/tools/computers.js +11 -10
  49. package/dist/tools/computers.js.map +1 -1
  50. package/dist/tools/guest.d.ts.map +1 -1
  51. package/dist/tools/guest.js +134 -20
  52. package/dist/tools/guest.js.map +1 -1
  53. package/dist/tools/input.d.ts +2 -0
  54. package/dist/tools/input.d.ts.map +1 -1
  55. package/dist/tools/input.js +31 -5
  56. package/dist/tools/input.js.map +1 -1
  57. package/dist/tools/secrets.d.ts +33 -13
  58. package/dist/tools/secrets.d.ts.map +1 -1
  59. package/dist/tools/secrets.js +259 -15
  60. package/dist/tools/secrets.js.map +1 -1
  61. package/dist/tools/snapshots.d.ts.map +1 -1
  62. package/dist/tools/snapshots.js +9 -3
  63. package/dist/tools/snapshots.js.map +1 -1
  64. package/dist/tools/webhooks.js +1 -1
  65. package/dist/tools/webhooks.js.map +1 -1
  66. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
package/dist/http.d.ts CHANGED
@@ -12,7 +12,49 @@ export type HttpConfig = Omit<ServerConfig, 'apiKey' | 'activity'> & {
12
12
  maxSessions?: number;
13
13
  /** How many requests may retain a parsed body above 256 KiB at once. */
14
14
  maxLargeBodyParses?: number;
15
+ /**
16
+ * The OAuth protected-resource metadata URL (RFC 9728) of this server, for
17
+ * the hosted install (OPL-4982). Setting it turns on the OAuth answers: a
18
+ * request with no bearer, or whose bearer the platform refused, is a 401
19
+ * carrying {@link bearerChallenge}, which is how an MCP client discovers
20
+ * where to authorize and knows to refresh. Unset, nothing changes.
21
+ */
22
+ resourceMetadataUrl?: string;
23
+ /**
24
+ * The platform's shared secret for this service, sent as
25
+ * `X-Mandala-MCP-Service` on every platform request a session makes. Needed
26
+ * for the platform to take an OAuth access token at all. Never logged.
27
+ */
28
+ serviceSecret?: string;
29
+ /**
30
+ * Hosted mode: how long a bearer the platform accepted is taken on trust
31
+ * before it is checked again, in ms. Default 60 s.
32
+ */
33
+ bearerCheckTtlMs?: number;
34
+ /**
35
+ * Hosted mode: refused initializes one source may make per minute before it
36
+ * is answered 429 without asking the platform. Default 20.
37
+ */
38
+ maxFailedInitializes?: number;
39
+ /**
40
+ * Hosted mode: once a source has spent that budget, how often it may still
41
+ * have one new bearer checked, in ms. Default 5 s.
42
+ */
43
+ exhaustedProbeIntervalMs?: number;
44
+ /** The SDK's SSE keep-alive interval, in ms. For tests; default 15 s. */
45
+ sseKeepAliveMs?: number;
15
46
  };
47
+ /** The OAuth scope the hosted resource asks for. */
48
+ export declare const MCP_SCOPE = "mcp:tools";
49
+ /**
50
+ * The `WWW-Authenticate` value of every OAuth refusal this server makes.
51
+ *
52
+ * The same header whether no bearer was sent or the platform refused one: RFC
53
+ * 9728 §5.1 has a client find the authorization server through
54
+ * `resource_metadata`, and the MCP authorization spec has it refresh or
55
+ * re-authorize on any 401 that carries it.
56
+ */
57
+ export declare function bearerChallenge(resourceMetadataUrl: string): string;
16
58
  export declare function isLoopbackHost(host: string): boolean;
17
59
  /**
18
60
  * One operator-supplied allowlist entry, as the Host headers it should match.
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAOxC,OAAO,EAA6C,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3F,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAgEF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUpD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAWlE;AA+BD;;;;;;;;;;GAUG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CA+uB9D"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AASxC,OAAO,EAA6C,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3F,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAyBF,oDAAoD;AACpD,eAAO,MAAM,SAAS,cAAc,CAAC;AAErC;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,mBAAmB,EAAE,MAAM,GAAG,MAAM,CAEnE;AA+FD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUpD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAWlE;AA+BD;;;;;;;;;;GAUG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAs+B9D"}
package/dist/http.js CHANGED
@@ -5,9 +5,57 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/
5
5
  import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
6
6
  import express, {} from 'express';
7
7
  import { Api, MODEL_KEY_HEADER } from './api.js';
8
+ import { APIError } from './errors.js';
8
9
  import { MeteredBody } from './http-body.js';
10
+ import { SSH_KEYS } from './paths.js';
9
11
  import { createServer, SERVER_NAME, SERVER_VERSION } from './server.js';
10
12
  import { toolFilter } from './tool-filters.js';
13
+ /** The OAuth scope the hosted resource asks for. */
14
+ export const MCP_SCOPE = 'mcp:tools';
15
+ /**
16
+ * The `WWW-Authenticate` value of every OAuth refusal this server makes.
17
+ *
18
+ * The same header whether no bearer was sent or the platform refused one: RFC
19
+ * 9728 §5.1 has a client find the authorization server through
20
+ * `resource_metadata`, and the MCP authorization spec has it refresh or
21
+ * re-authorize on any 401 that carries it.
22
+ */
23
+ export function bearerChallenge(resourceMetadataUrl) {
24
+ return `Bearer resource_metadata="${resourceMetadataUrl}", scope="${MCP_SCOPE}"`;
25
+ }
26
+ /**
27
+ * The metadata URL, or a refusal naming the setting.
28
+ *
29
+ * It goes inside a quoted-string in a response header, so a quote, a backslash
30
+ * or a control character would change what the header says — refused rather
31
+ * than escaped, since no real URL needs one.
32
+ */
33
+ function checkedMetadataUrl(raw) {
34
+ let parsed;
35
+ try {
36
+ parsed = new URL(raw);
37
+ }
38
+ catch {
39
+ throw new Error('MANDALA_MCP_RESOURCE_METADATA_URL is not a URL. Set it to the absolute https URL of ' +
40
+ 'this resource’s OAuth metadata, e.g. https://app.mandala.computer/.well-known/oauth-protected-resource/mcp');
41
+ }
42
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
43
+ throw new Error('MANDALA_MCP_RESOURCE_METADATA_URL must be an http(s) URL.');
44
+ }
45
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: refusing them is the point.
46
+ if (/["\\\u0000-\u001f\u007f\s]/.test(raw)) {
47
+ throw new Error('MANDALA_MCP_RESOURCE_METADATA_URL contains a quote, backslash, space or control character.');
48
+ }
49
+ return raw;
50
+ }
51
+ /** Visible ASCII only: anything else cannot be a header value, and says so here. */
52
+ function checkedServiceSecret(raw) {
53
+ if (!/^[\x21-\x7e]+$/.test(raw)) {
54
+ // The value is deliberately not echoed.
55
+ throw new Error('MANDALA_MCP_SERVICE_SECRET must be printable ASCII with no spaces; it is sent as a header.');
56
+ }
57
+ return raw;
58
+ }
11
59
  const DEFAULT_TTL_MS = 30 * 60 * 1000;
12
60
  /**
13
61
  * A ceiling on live sessions.
@@ -142,7 +190,138 @@ export async function runHttp(cfg) {
142
190
  // with a generic 500. Validate it before opening the listening socket, using
143
191
  // the same constructor and therefore the same rules as every real session.
144
192
  new Api('startup-validation-only', cfg.baseUrl);
193
+ // The hosted install's two settings, checked before the bind for the same
194
+ // reason. `challenge` being set IS hosted mode: every OAuth-specific answer
195
+ // below is gated on it, so a server started without the metadata URL behaves
196
+ // exactly as it did before OPL-4982.
197
+ const metadataUrl = cfg.resourceMetadataUrl !== undefined ? checkedMetadataUrl(cfg.resourceMetadataUrl) : undefined;
198
+ const serviceSecret = cfg.serviceSecret !== undefined ? checkedServiceSecret(cfg.serviceSecret) : undefined;
199
+ const challenge = metadataUrl ? bearerChallenge(metadataUrl) : undefined;
200
+ /** The POST being answered, so a refused bearer can turn it into a 401. */
201
+ const heldAnswer = new AsyncLocalStorage();
202
+ // ---- Checking a bearer with the platform (hosted mode) -----------------
203
+ //
204
+ // Initialize makes no platform request, so without this an invented bearer
205
+ // bought a whole session: 256 of them filled the cap and every real client
206
+ // was 503'd until the sweep. And a POST's event stream is committed by the
207
+ // SDK's keep-alive after 15 s, after which a refused token can only end that
208
+ // call as a tool error. So in hosted mode a bearer is checked before a
209
+ // session is created for it, and before a POST carrying a request is
210
+ // dispatched — the latter cached briefly, keyed by the token's digest and
211
+ // never by the token.
212
+ const checkTtl = cfg.bearerCheckTtlMs ?? DEFAULT_BEARER_CHECK_TTL_MS;
213
+ const accepted = new Map();
214
+ let checksInFlight = 0;
215
+ /** Whether the platform accepted this bearer within the cache window. */
216
+ const isAccepted = (key) => {
217
+ const until = accepted.get(digest(key).toString('hex'));
218
+ return until !== undefined && until > Date.now();
219
+ };
220
+ /**
221
+ * `ok`: the probe answered 2xx, and only that — the one answer that says the
222
+ * platform authenticated this credential AND let it act. `refused`: a 401.
223
+ * `unknown`: anything else — a 403 (a suspended account or a lost
224
+ * membership), a 404 (the route moved), a 429, a 5xx, a timeout, or this
225
+ * server already asking about as many bearers as it will at once. Only `ok`
226
+ * is cached.
227
+ */
228
+ // `onStart` runs only when a probe really starts — never for a cached answer
229
+ // or a full cap — and synchronously, before the first await, so a caller's
230
+ // bookkeeping and its check against it cannot interleave with another's.
231
+ const checkBearer = async (key, onStart) => {
232
+ const id = digest(key).toString('hex');
233
+ if (isAccepted(key))
234
+ return 'ok';
235
+ if (checksInFlight >= MAX_BEARER_CHECKS_IN_FLIGHT)
236
+ return 'unknown';
237
+ checksInFlight++;
238
+ onStart?.();
239
+ try {
240
+ const api = new Api(key, cfg.baseUrl, AbortSignal.timeout(BEARER_CHECK_TIMEOUT_MS), {
241
+ serviceSecret,
242
+ });
243
+ // `GET ssh-keys`, chosen because it is the cheapest read that every
244
+ // valid credential is answered 2xx on. The platform's route table
245
+ // gives it the lowest role there is (viewer), a workspace-scoped key is
246
+ // refused only the key WRITES, and the handler lists the caller's own
247
+ // keys from the control plane without asking any host — so no role a
248
+ // grant can carry, and no host being down, turns it into a refusal.
249
+ // `account` is the alternative and costs two fleet inventories. The one
250
+ // valid credential it does not admit is a suspended account's (403),
251
+ // which is answered as unconfirmed. It takes no parameters, so none are
252
+ // sent.
253
+ await api.json('GET', SSH_KEYS);
254
+ }
255
+ catch (err) {
256
+ return err instanceof APIError && err.status === 401 ? 'refused' : 'unknown';
257
+ }
258
+ finally {
259
+ checksInFlight--;
260
+ }
261
+ const now = Date.now();
262
+ if (accepted.size >= MAX_ACCEPTED_BEARERS) {
263
+ for (const [k, t] of accepted)
264
+ if (t <= now)
265
+ accepted.delete(k);
266
+ // Still full: drop the oldest, which Map iteration yields first.
267
+ if (accepted.size >= MAX_ACCEPTED_BEARERS) {
268
+ accepted.delete(accepted.keys().next().value);
269
+ }
270
+ }
271
+ accepted.set(id, now + checkTtl);
272
+ return 'ok';
273
+ };
274
+ // Refused initializes per source, in fixed one-minute windows. Kept apart
275
+ // from the session cap so a flood of invented tokens is turned away before
276
+ // it asks the platform anything, rather than by starving the pool.
277
+ const maxFailed = cfg.maxFailedInitializes ?? DEFAULT_MAX_FAILED_INITIALIZES;
278
+ // `lastProbeAt` lives on the window's entry, so the window's reset restores
279
+ // the normal budget and forgets the spent-address clock in one step.
280
+ const failures = new Map();
281
+ const exhaustedInterval = cfg.exhaustedProbeIntervalMs ?? DEFAULT_EXHAUSTED_PROBE_INTERVAL_MS;
282
+ const sourceOf = (req) => req.ip ?? req.socket.remoteAddress ?? 'unknown';
283
+ const overFailureBudget = (req) => {
284
+ const entry = failures.get(sourceOf(req));
285
+ if (!entry)
286
+ return undefined;
287
+ const now = Date.now();
288
+ if (entry.resetAt <= now) {
289
+ failures.delete(sourceOf(req));
290
+ return undefined;
291
+ }
292
+ return entry.count >= maxFailed ? Math.ceil((entry.resetAt - now) / 1000) : undefined;
293
+ };
294
+ const noteFailure = (req) => {
295
+ const source = sourceOf(req);
296
+ const now = Date.now();
297
+ const entry = failures.get(source);
298
+ if (entry && entry.resetAt > now) {
299
+ entry.count++;
300
+ return;
301
+ }
302
+ if (failures.size >= MAX_FAILURE_SOURCES) {
303
+ for (const [k, e] of failures)
304
+ if (e.resetAt <= now)
305
+ failures.delete(k);
306
+ if (failures.size >= MAX_FAILURE_SOURCES) {
307
+ failures.delete(failures.keys().next().value);
308
+ }
309
+ }
310
+ failures.set(source, { count: 1, resetAt: now + FAILURE_WINDOW_MS });
311
+ };
312
+ /** A 401 an OAuth client acts on: authorize, or refresh and try again. */
313
+ const challenged = (res, message, id = null) => {
314
+ if (challenge)
315
+ res.set('WWW-Authenticate', challenge);
316
+ unauthorized(res, message, id);
317
+ };
145
318
  const app = express();
319
+ // Hosted mode sits behind a proxy on this machine, and the refused-
320
+ // initialize budget is per source: without this every caller would be the
321
+ // proxy's one loopback address, sharing one budget. Only a loopback peer's
322
+ // X-Forwarded-For is believed, so a direct caller cannot choose its source.
323
+ if (challenge)
324
+ app.set('trust proxy', 'loopback');
146
325
  // parseBody consumes every POST /mcp body. Every other route deliberately
147
326
  // ignores request bodies, so put those requests in flowing mode immediately:
148
327
  // leaving bytes unread can strand a keep-alive connection behind one wrong
@@ -548,6 +727,14 @@ export async function runHttp(cfg) {
548
727
  app.post('/mcp', parseBody, async (req, res) => {
549
728
  const sessionId = req.header('mcp-session-id');
550
729
  const key = bearer(req);
730
+ // Hosted: EVERY request needs a bearer, initialize and tools/list included.
731
+ // Orgo answers those two anonymously; refusing them is simpler, costs a
732
+ // client nothing (it authorizes on the first 401 whichever request that
733
+ // is), and means no McpServer is ever built for a caller with no credential.
734
+ if (challenge && !key) {
735
+ releaseLargeBody(res);
736
+ return challenged(res, NO_TOKEN, rpcId(req));
737
+ }
551
738
  if (sessionId) {
552
739
  try {
553
740
  const live = sessions.get(sessionId);
@@ -557,10 +744,36 @@ export async function runHttp(cfg) {
557
744
  // session id travels in a plain header and is the sort of thing that ends
558
745
  // up in a proxy log; on its own it must not be a credential.
559
746
  if (!key || !sameKey(live.keyDigest, key)) {
747
+ // Hosted: a different bearer is most often the SAME client after a
748
+ // token refresh, and nothing this server can see proves that — an
749
+ // access token is opaque, and the refresh token never comes here. So
750
+ // the session is not rebound, which would hand its bound computer,
751
+ // buffered events and retained results to whoever holds any valid
752
+ // credential and the session id. It is answered as unknown instead,
753
+ // which is the MCP spec's signal to initialize a new session; the new
754
+ // bearer gets a new session, and this one is left to the idle sweep
755
+ // (closing it here would let anyone with the id end it).
756
+ if (challenge) {
757
+ return notFound(res, 'Unknown session. Initialize a new one.', rpcId(req));
758
+ }
560
759
  return unauthorized(res, 'This session belongs to a different API key.', rpcId(req));
561
760
  }
761
+ if (challenge && live.refused)
762
+ return challenged(res, TOKEN_REFUSED, rpcId(req));
763
+ // Checked before a request is dispatched, while the answer can still
764
+ // be a 401 whatever the call goes on to do. A platform that cannot say
765
+ // is not a refusal: the call goes ahead, and a real refusal during it
766
+ // still reaches the client through the held answer or the mark.
767
+ if (challenge && carriesRequest(req.body) && (await checkBearer(key)) === 'refused') {
768
+ live.refused = true;
769
+ return challenged(res, TOKEN_REFUSED, rpcId(req));
770
+ }
562
771
  const lease = res.locals.largeBodyLease;
563
- return await requestBodyLease.run(lease, () => serving(live, () => live.transport.handleRequest(req, res, req.body)));
772
+ const id = rpcId(req);
773
+ const held = challenge
774
+ ? holdAnswer(res, () => challenged(res, TOKEN_REFUSED, id))
775
+ : undefined;
776
+ return await heldAnswer.run(held, () => requestBodyLease.run(lease, () => serving(live, () => live.transport.handleRequest(req, res, req.body))));
564
777
  }
565
778
  finally {
566
779
  // A verified session is the only request allowed through the large
@@ -587,6 +800,43 @@ export async function runHttp(cfg) {
587
800
  const refused = dnsRebindingRefusal(req, hosts, allowedOrigins);
588
801
  if (refused)
589
802
  return rpcError(res, 403, -32000, refused, rpcId(req));
803
+ // Hosted: no session for a bearer the platform does not accept. Before the
804
+ // cap and the reservation, so a refused bearer never holds a slot.
805
+ if (challenge) {
806
+ // A spent budget does not close the address. Many clients can share one
807
+ // (a NAT, an office), and one bad neighbour must not lock out the rest:
808
+ // a bearer the platform already accepted passes outright, and a new one
809
+ // still gets a probe — but at most one per interval per spent address,
810
+ // taken when the probe starts, so the address costs the platform one probe per
811
+ // interval however hard it pushes, and a valid client there waits at
812
+ // most one interval. The process-wide cap on probes bounds the total.
813
+ const spent = !isAccepted(key) && overFailureBudget(req) !== undefined;
814
+ if (spent) {
815
+ const entry = failures.get(sourceOf(req));
816
+ const wait = entry?.lastProbeAt !== undefined ? entry.lastProbeAt + exhaustedInterval - Date.now() : 0;
817
+ if (wait > 0) {
818
+ res.set('Retry-After', String(Math.max(1, Math.ceil(wait / 1000))));
819
+ return rpcError(res, 429, -32002, 'Too many refused initializes from this address. Retry later with a valid token.', rpcId(req));
820
+ }
821
+ }
822
+ // The interval is spent only by a probe that starts: a request turned
823
+ // away because the process-wide cap is full reached nobody, and must not
824
+ // make the next client at this address wait out an interval for it.
825
+ const verdict = await checkBearer(key, spent
826
+ ? () => {
827
+ const entry = failures.get(sourceOf(req));
828
+ if (entry)
829
+ entry.lastProbeAt = Date.now();
830
+ }
831
+ : undefined);
832
+ if (verdict === 'refused') {
833
+ noteFailure(req);
834
+ return challenged(res, TOKEN_REFUSED, rpcId(req));
835
+ }
836
+ if (verdict === 'unknown') {
837
+ return unavailable(res, 'The platform could not confirm this token just now. Retry shortly.', rpcId(req));
838
+ }
839
+ }
590
840
  // Swept sessions free their slot on the timer; this is the backstop for the
591
841
  // case the timer cannot help with, which is arrivals faster than the TTL.
592
842
  if (sessions.size + pending >= maxSessions) {
@@ -618,6 +868,7 @@ export async function runHttp(cfg) {
618
868
  try {
619
869
  const t = new StreamableHTTPServerTransport({
620
870
  sessionIdGenerator: () => randomUUID(),
871
+ ...(cfg.sseKeepAliveMs !== undefined ? { keepAliveMs: cfg.sseKeepAliveMs } : {}),
621
872
  // On whenever there is a list to check against, which for a loopback
622
873
  // bind is always — see `allowedHosts`. A browser cannot be stopped from
623
874
  // resolving a name it controls to 127.0.0.1, so the Host header is the
@@ -635,6 +886,7 @@ export async function runHttp(cfg) {
635
886
  // Initialize is already in flight when the session first becomes
636
887
  // visible to the sweeper. Count it until handleRequest settles.
637
888
  active: 1,
889
+ refused: false,
638
890
  };
639
891
  sessions.set(id, live);
640
892
  let held = true;
@@ -680,6 +932,21 @@ export async function runHttp(cfg) {
680
932
  // every call until they run use_computer 404s, and the id of a machine
681
933
  // that is not theirs is named back to them by way of explanation.
682
934
  computerId: undefined,
935
+ platform: {
936
+ serviceSecret,
937
+ // Hosted only. Marks the session, so the NEXT request on this bearer
938
+ // is refused before dispatch, and turns the request in flight into a
939
+ // 401 if nothing of its answer has been sent yet.
940
+ onBearerRefused: challenge
941
+ ? () => {
942
+ const id = t.sessionId;
943
+ const live = id ? sessions.get(id) : undefined;
944
+ if (live)
945
+ live.refused = true;
946
+ heldAnswer.getStore()?.refuse();
947
+ }
948
+ : undefined,
949
+ },
683
950
  });
684
951
  mcp = server;
685
952
  await server.connect(t);
@@ -717,13 +984,22 @@ export async function runHttp(cfg) {
717
984
  // the POST does.
718
985
  const bySession = async (req, res) => {
719
986
  const sessionId = req.header('mcp-session-id');
987
+ const key = bearer(req);
988
+ if (challenge && !key)
989
+ return challenged(res, NO_TOKEN);
720
990
  const live = sessionId ? sessions.get(sessionId) : undefined;
721
991
  if (!live)
722
992
  return notFound(res, 'Unknown session.');
723
- const key = bearer(req);
724
993
  if (!key || !sameKey(live.keyDigest, key)) {
994
+ // As on POST: hosted answers a different bearer as an unknown session.
995
+ if (challenge)
996
+ return notFound(res, 'Unknown session.');
725
997
  return unauthorized(res, 'This session belongs to a different API key.');
726
998
  }
999
+ // The stream is refused on a token the platform has already refused; a
1000
+ // DELETE is still honoured, since the digest shows it is the holder.
1001
+ if (challenge && live.refused && req.method === 'GET')
1002
+ return challenged(res, TOKEN_REFUSED);
727
1003
  // The DELETE is a request and is held for; the GET is the notification
728
1004
  // stream and is only noted. See `serving`.
729
1005
  if (req.method === 'GET') {
@@ -794,7 +1070,13 @@ export async function runHttp(cfg) {
794
1070
  const addr = http.address();
795
1071
  const bound = typeof addr === 'object' && addr ? addr.port : cfg.port;
796
1072
  boundPort = bound;
797
- console.error(`mandala-computer-mcp on http://${cfg.host}:${bound}/mcp — callers authenticate with their own Mandala API key`);
1073
+ console.error(metadataUrl
1074
+ ? `mandala-computer-mcp on http://${cfg.host}:${bound}/mcp — OAuth: callers without a bearer are sent to ${metadataUrl}`
1075
+ : `mandala-computer-mcp on http://${cfg.host}:${bound}/mcp — callers authenticate with their own Mandala API key`);
1076
+ // Said, never shown: whether the secret is set is the useful fact.
1077
+ if (metadataUrl && !serviceSecret) {
1078
+ console.error(' MANDALA_MCP_SERVICE_SECRET is not set — the platform accepts OAuth access tokens only with it, so every tool call will be refused');
1079
+ }
798
1080
  // Said once, at the only moment anybody is reading. A bind that is not
799
1081
  // loopback cannot have its legitimate Host values guessed, so the check
800
1082
  // is off and the operator is the only one who can turn it on — and an
@@ -860,6 +1142,100 @@ export async function runHttp(cfg) {
860
1142
  http.on('close', teardown);
861
1143
  });
862
1144
  }
1145
+ const DEFAULT_BEARER_CHECK_TTL_MS = 60_000;
1146
+ const DEFAULT_MAX_FAILED_INITIALIZES = 20;
1147
+ const DEFAULT_EXHAUSTED_PROBE_INTERVAL_MS = 5_000;
1148
+ const FAILURE_WINDOW_MS = 60_000;
1149
+ const BEARER_CHECK_TIMEOUT_MS = 10_000;
1150
+ /** How many bearers this server will be asking the platform about at once. */
1151
+ const MAX_BEARER_CHECKS_IN_FLIGHT = 32;
1152
+ const MAX_ACCEPTED_BEARERS = 4096;
1153
+ const MAX_FAILURE_SOURCES = 10_000;
1154
+ /** Whether a POST body holds a JSON-RPC request, which is what opens a stream. */
1155
+ function carriesRequest(body) {
1156
+ const isRequest = (m) => typeof m === 'object' && m !== null && 'method' in m && 'id' in m;
1157
+ return Array.isArray(body) ? body.some(isRequest) : isRequest(body);
1158
+ }
1159
+ const NO_TOKEN = 'Authorization required. Authorize this client with Mandala (OAuth), or send a Mandala API key: Authorization: Bearer …';
1160
+ const TOKEN_REFUSED = 'The platform no longer accepts this access token. Refresh it, or authorize again.';
1161
+ /**
1162
+ * Hold a response's status line until its first byte of body (hosted mode).
1163
+ *
1164
+ * A Streamable HTTP POST answers 200 and opens its event stream the moment the
1165
+ * request is dispatched, long before a tool reaches the platform — so a token
1166
+ * the platform refuses could only ever come back as a tool error inside a 200,
1167
+ * which no MCP client treats as "refresh your token". Deferring `writeHead`
1168
+ * and `flushHeaders` until the first write lets that refusal become the 401
1169
+ * the client acts on instead: the platform's 401 is reported before the tool
1170
+ * has produced anything, so the first write finds the answer already refused.
1171
+ *
1172
+ * The first byte of anything — a result, a progress notification, the SDK's
1173
+ * keep-alive comment — commits the stream, and a refusal after that stays a
1174
+ * tool error. The session is marked either way, so the next request carrying
1175
+ * the refused bearer gets the 401 before it is dispatched.
1176
+ */
1177
+ function holdAnswer(res, answer401) {
1178
+ const target = res;
1179
+ const names = ['writeHead', 'flushHeaders', 'write', 'end'];
1180
+ const own = Object.fromEntries(names.map((n) => [n, target[n]]));
1181
+ const deferred = [];
1182
+ let state = 'holding';
1183
+ const restore = () => {
1184
+ for (const n of names)
1185
+ target[n] = own[n];
1186
+ };
1187
+ const release = () => {
1188
+ if (state !== 'holding')
1189
+ return;
1190
+ state = 'released';
1191
+ restore();
1192
+ for (const replay of deferred.splice(0))
1193
+ replay();
1194
+ };
1195
+ const refuse = () => {
1196
+ if (state !== 'holding')
1197
+ return;
1198
+ state = 'refused';
1199
+ restore();
1200
+ if (!res.headersSent && !res.writableEnded && !res.destroyed)
1201
+ answer401();
1202
+ // Whatever the transport still writes belongs to the answer that was
1203
+ // replaced, and writing after end would raise an unhandled 'error'.
1204
+ target.writeHead = () => res;
1205
+ target.flushHeaders = () => undefined;
1206
+ target.write = (...args) => {
1207
+ const cb = args.find((a) => typeof a === 'function');
1208
+ cb?.();
1209
+ return true;
1210
+ };
1211
+ target.end = (...args) => {
1212
+ const cb = args.find((a) => typeof a === 'function');
1213
+ cb?.();
1214
+ return res;
1215
+ };
1216
+ };
1217
+ target.writeHead = (...args) => {
1218
+ if (state !== 'holding')
1219
+ return target.writeHead.apply(res, args);
1220
+ deferred.push(() => own.writeHead.apply(res, args));
1221
+ return res;
1222
+ };
1223
+ target.flushHeaders = (...args) => {
1224
+ if (state !== 'holding')
1225
+ return target.flushHeaders.apply(res, args);
1226
+ deferred.push(() => own.flushHeaders.apply(res, args));
1227
+ return undefined;
1228
+ };
1229
+ target.write = (...args) => {
1230
+ release();
1231
+ return target.write.apply(res, args);
1232
+ };
1233
+ target.end = (...args) => {
1234
+ release();
1235
+ return target.end.apply(res, args);
1236
+ };
1237
+ return { refuse };
1238
+ }
863
1239
  /**
864
1240
  * Whether this request is allowed through the 96mb parser.
865
1241
  *