agentic-mermaid 0.3.1 → 0.4.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 (57) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/dist/agent-core.d.ts +2 -2
  3. package/dist/agent-core.js +2 -2
  4. package/dist/agent.d.ts +2 -2
  5. package/dist/agent.js +4 -4
  6. package/dist/agentic-mermaid-mcp.js +5 -5
  7. package/dist/am.js +6 -6
  8. package/dist/browser-lazy/chunks/{architecture-3CGEU363.js → architecture-NUJTDJJ7.js} +1 -1
  9. package/dist/browser-lazy/chunks/{chunk-VDTSULBU.js → chunk-2W3BS3M3.js} +1 -1
  10. package/dist/browser-lazy/chunks/{chunk-HZ4ADQMK.js → chunk-4RLZTVJP.js} +1 -1
  11. package/dist/browser-lazy/chunks/{chunk-CTVVJPMX.js → chunk-4ZURJQXD.js} +1 -1
  12. package/dist/browser-lazy/chunks/{chunk-RVO6J7S3.js → chunk-55F5M5XA.js} +1 -1
  13. package/dist/browser-lazy/chunks/{chunk-MMWVZP6M.js → chunk-5QI4P3EJ.js} +1 -1
  14. package/dist/browser-lazy/chunks/{chunk-DPSSG7LR.js → chunk-6LBHOBXT.js} +1 -1
  15. package/dist/browser-lazy/chunks/{chunk-JX5ZZY3T.js → chunk-ASPYKC6M.js} +1 -1
  16. package/dist/browser-lazy/chunks/{chunk-FXBBGAMJ.js → chunk-DQHK4JCG.js} +2 -2
  17. package/dist/browser-lazy/chunks/{chunk-6UT2VTFI.js → chunk-EKHEVTE2.js} +1 -1
  18. package/dist/browser-lazy/chunks/{chunk-4IUBLBJJ.js → chunk-HO5GDIPN.js} +1 -1
  19. package/dist/browser-lazy/chunks/{chunk-4U2TVB2S.js → chunk-N2K2BPQT.js} +1 -1
  20. package/dist/browser-lazy/chunks/{chunk-2U4EUPSI.js → chunk-OLQF6DTZ.js} +1 -1
  21. package/dist/browser-lazy/chunks/{chunk-7D24ZLOV.js → chunk-TCPK32QH.js} +1 -1
  22. package/dist/browser-lazy/chunks/{chunk-KTTWXSIX.js → chunk-UO3RFEMI.js} +1 -1
  23. package/dist/browser-lazy/chunks/{chunk-PXRUFH7U.js → chunk-ZMPTJUXS.js} +1 -1
  24. package/dist/browser-lazy/chunks/{class-B3AVLSIF.js → class-ABIOBAFL.js} +1 -1
  25. package/dist/browser-lazy/chunks/{er-AF4BKKKC.js → er-CX3NGEC2.js} +1 -1
  26. package/dist/browser-lazy/chunks/{flowchart-BE6BQZLZ.js → flowchart-ML54IJ7F.js} +1 -1
  27. package/dist/browser-lazy/chunks/{gantt-U4BMMSEL.js → gantt-ZMOMOTF6.js} +1 -1
  28. package/dist/browser-lazy/chunks/{gitgraph-UPSWNFRP.js → gitgraph-OBTCRWCA.js} +1 -1
  29. package/dist/browser-lazy/chunks/{journey-PDZ7FDJR.js → journey-RJBHWLRG.js} +1 -1
  30. package/dist/browser-lazy/chunks/{mindmap-BFEUURLS.js → mindmap-YXHLCHOO.js} +1 -1
  31. package/dist/browser-lazy/chunks/{pie-ZFYW5JZO.js → pie-TN2QOLSL.js} +1 -1
  32. package/dist/browser-lazy/chunks/{quadrant-XJVEYYXK.js → quadrant-QE5JZ4H2.js} +1 -1
  33. package/dist/browser-lazy/chunks/{radar-OVXFNRNC.js → radar-ZPV6O27I.js} +1 -1
  34. package/dist/browser-lazy/chunks/{render-core-R4ZGGEFS.js → render-core-VPMAH3HT.js} +2 -2
  35. package/dist/browser-lazy/chunks/{sequence-AWY6JCSB.js → sequence-4AERT525.js} +1 -1
  36. package/dist/browser-lazy/chunks/{state-TCE4DXKR.js → state-67TZ7USF.js} +1 -1
  37. package/dist/browser-lazy/chunks/{timeline-W4ZVT3FF.js → timeline-AHOAT7ZL.js} +1 -1
  38. package/dist/browser-lazy/chunks/{xychart-K3QQACKS.js → xychart-YUY3CPT2.js} +1 -1
  39. package/dist/browser-lazy/index.js +1 -1
  40. package/dist/browser.global.js +6 -6
  41. package/dist/{chunk-BSVM3VMO.js → chunk-M3VTTD3Q.js} +2 -2
  42. package/dist/{chunk-XVY324NY.js → chunk-PG4PTPJL.js} +10 -8
  43. package/dist/{chunk-KQMJ37OY.js → chunk-QWCD67AZ.js} +4 -4
  44. package/dist/{chunk-JJ7JRYZV.js → chunk-SDJYD4OP.js} +2 -2
  45. package/dist/{chunk-MBIR6S3B.js → chunk-UKLKEZBJ.js} +2 -2
  46. package/dist/{chunk-FGO3J7RA.js → chunk-WMFFVZ4Q.js} +677 -48
  47. package/dist/{index-Do8z5rPq.d.ts → index-BoqfBufn.d.ts} +1 -1
  48. package/dist/index.d.ts +1 -1
  49. package/dist/index.js +1 -1
  50. package/dist/mcp-cli-YOAFIAVD.js +17 -0
  51. package/docs/mcp-http-transport.md +2 -0
  52. package/docs/style-authoring.md +1 -1
  53. package/package.json +16 -4
  54. package/server.json +2 -2
  55. package/skills/agentic-mermaid-diagram-workflow/SKILL.md +64 -1
  56. package/skills/agentic-mermaid-diagram-workflow/references/hosted-mcp.md +110 -0
  57. package/dist/mcp-cli-7FLGTEG3.js +0 -17
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  projectKnownRenderErrorDiagnostic,
3
3
  projectRenderErrorDiagnostic
4
- } from "./chunk-JJ7JRYZV.js";
4
+ } from "./chunk-SDJYD4OP.js";
5
5
  import {
6
6
  renderMermaidPNG,
7
7
  renderMermaidPNGWithReceipt
8
- } from "./chunk-MBIR6S3B.js";
8
+ } from "./chunk-UKLKEZBJ.js";
9
9
  import {
10
10
  analyzeMermaid,
11
11
  analyzeMermaidSource,
@@ -31,7 +31,7 @@ import {
31
31
  renderMermaidSVGWithReceipt,
32
32
  verifyMermaid,
33
33
  verifySummary
34
- } from "./chunk-BSVM3VMO.js";
34
+ } from "./chunk-M3VTTD3Q.js";
35
35
  import {
36
36
  BUILTIN_FAMILY_METADATA,
37
37
  PACKAGE_VERSION,
@@ -71,13 +71,11 @@ import {
71
71
  styleSpecTypeScriptDeclaration,
72
72
  validateJsonConfigAdmission,
73
73
  validateSerializableRenderOptions
74
- } from "./chunk-XVY324NY.js";
74
+ } from "./chunk-PG4PTPJL.js";
75
75
 
76
76
  // src/mcp/server.ts
77
77
  import { randomUUID as randomUUID2 } from "crypto";
78
78
  import { createServer } from "http";
79
- import { tmpdir as tmpdir2 } from "os";
80
- import { join as join2 } from "path";
81
79
  import { URL } from "url";
82
80
 
83
81
  // src/mcp/sandbox.ts
@@ -1214,7 +1212,7 @@ function preserveExactJsonRpcIds(body) {
1214
1212
  cursor++;
1215
1213
  while (/\s/.test(body[cursor] ?? "")) cursor++;
1216
1214
  const number = body.slice(cursor).match(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/)?.[0];
1217
- if (number && !isSafelyRoundTrippableInteger(number)) {
1215
+ if (number && isIntegerNumberToken(number) && !isSafelyRoundTrippableInteger(number)) {
1218
1216
  let sentinel = `__agentic_mermaid_exact_id_${replacements.length}__`;
1219
1217
  while (body.includes(sentinel)) sentinel += "_";
1220
1218
  replacements.push({ sentinel, raw: number, start: cursor, end: cursor + number.length });
@@ -1233,6 +1231,10 @@ function preserveExactJsonRpcIds(body) {
1233
1231
  }
1234
1232
  return { body: protectedBody, ids: replacements.map(({ sentinel, raw }) => ({ sentinel, raw })) };
1235
1233
  }
1234
+ function isIntegerNumberToken(token) {
1235
+ const value = Number(token);
1236
+ return Number.isFinite(value) && Number.isInteger(value);
1237
+ }
1236
1238
  function isSafelyRoundTrippableInteger(token) {
1237
1239
  if (!/^-?(?:0|[1-9]\d*)$/.test(token)) return false;
1238
1240
  if (token === "-0") return false;
@@ -1259,8 +1261,335 @@ function stringifyJsonRpc(payload, exactIds = []) {
1259
1261
  function reply(id, result) {
1260
1262
  return { jsonrpc: "2.0", id, result };
1261
1263
  }
1262
- function rpcError(id, code, message) {
1263
- return { jsonrpc: "2.0", id, error: { code, message } };
1264
+ function rpcError(id, code, message, data) {
1265
+ return { jsonrpc: "2.0", id, error: data === void 0 ? { code, message } : { code, message, data } };
1266
+ }
1267
+ function toolResult(id, payload, isError) {
1268
+ return reply(id, { content: [{ type: "text", text: JSON.stringify(payload) }], isError });
1269
+ }
1270
+
1271
+ // src/mcp/protocol-versions.ts
1272
+ var LEGACY_PROTOCOL_VERSIONS = ["2024-11-05", "2025-03-26", "2025-06-18", "2025-11-25"];
1273
+ var MODERN_PROTOCOL_VERSIONS = ["2026-07-28"];
1274
+ var META_PROTOCOL_VERSION = "io.modelcontextprotocol/protocolVersion";
1275
+ var META_CLIENT_INFO = "io.modelcontextprotocol/clientInfo";
1276
+ var META_CLIENT_CAPABILITIES = "io.modelcontextprotocol/clientCapabilities";
1277
+ var META_LOG_LEVEL = "io.modelcontextprotocol/logLevel";
1278
+ var META_SERVER_INFO = "io.modelcontextprotocol/serverInfo";
1279
+ var HEADER_MISMATCH = -32020;
1280
+ var UNSUPPORTED_PROTOCOL_VERSION = -32022;
1281
+ var TOOL_ERROR_VALIDATION_SINCE = "2025-11-25";
1282
+ function isModernProtocolVersion(version) {
1283
+ return typeof version === "string" && MODERN_PROTOCOL_VERSIONS.includes(version);
1284
+ }
1285
+ function isLegacyProtocolVersion(version) {
1286
+ return typeof version === "string" && LEGACY_PROTOCOL_VERSIONS.includes(version);
1287
+ }
1288
+ function usesToolErrorForInvalidArguments(version) {
1289
+ return typeof version === "string" && version >= TOOL_ERROR_VALIDATION_SINCE;
1290
+ }
1291
+ function paramsMeta(req) {
1292
+ const params = req.params;
1293
+ if (!params || typeof params !== "object" || Array.isArray(params)) return void 0;
1294
+ const meta = params._meta;
1295
+ if (!meta || typeof meta !== "object" || Array.isArray(meta)) return void 0;
1296
+ return meta;
1297
+ }
1298
+ function requestMetaProtocolVersion(req) {
1299
+ const claim = requestMetaProtocolVersionClaim(req);
1300
+ const value = claim.present ? claim.value : void 0;
1301
+ return typeof value === "string" ? value : void 0;
1302
+ }
1303
+ function requestMetaProtocolVersionClaim(req) {
1304
+ const meta = paramsMeta(req);
1305
+ if (!meta || !Object.prototype.hasOwnProperty.call(meta, META_PROTOCOL_VERSION)) return { present: false };
1306
+ return { present: true, value: meta[META_PROTOCOL_VERSION] };
1307
+ }
1308
+ function mcpImplementationProblems(value, path) {
1309
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1310
+ return [`${path} is required and must be an object with name and version`];
1311
+ }
1312
+ const problems = [];
1313
+ const info = value;
1314
+ if (typeof info.name !== "string") problems.push(`${path}.name is required and must be a string`);
1315
+ if (typeof info.version !== "string") problems.push(`${path}.version is required and must be a string`);
1316
+ for (const key of ["title", "description", "websiteUrl"]) {
1317
+ if (info[key] !== void 0 && typeof info[key] !== "string") {
1318
+ problems.push(`${path}.${key} must be a string when present`);
1319
+ }
1320
+ }
1321
+ if (info.icons !== void 0) {
1322
+ if (!Array.isArray(info.icons)) {
1323
+ problems.push(`${path}.icons must be an array when present`);
1324
+ } else {
1325
+ for (const [index, icon] of info.icons.entries()) {
1326
+ if (!icon || typeof icon !== "object" || Array.isArray(icon)) {
1327
+ problems.push(`${path}.icons[${index}] must be an object`);
1328
+ continue;
1329
+ }
1330
+ const record = icon;
1331
+ if (typeof record.src !== "string") problems.push(`${path}.icons[${index}].src is required and must be a string`);
1332
+ if (record.mimeType !== void 0 && typeof record.mimeType !== "string") problems.push(`${path}.icons[${index}].mimeType must be a string when present`);
1333
+ if (record.sizes !== void 0 && (!Array.isArray(record.sizes) || record.sizes.some((size) => typeof size !== "string"))) {
1334
+ problems.push(`${path}.icons[${index}].sizes must be an array of strings when present`);
1335
+ }
1336
+ if (record.theme !== void 0 && record.theme !== "light" && record.theme !== "dark") {
1337
+ problems.push(`${path}.icons[${index}].theme must be light or dark when present`);
1338
+ }
1339
+ }
1340
+ }
1341
+ }
1342
+ return problems;
1343
+ }
1344
+ function mcpClientCapabilitiesProblems(value, path) {
1345
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1346
+ return [`${path} is required and must be an object (an empty object declares no optional capabilities)`];
1347
+ }
1348
+ const problems = [];
1349
+ const record = value;
1350
+ const objectMember = (key) => {
1351
+ const member = record[key];
1352
+ if (member === void 0) return void 0;
1353
+ if (typeof member !== "object" || member === null || Array.isArray(member)) {
1354
+ problems.push(`${path}.${key} must be an object when present`);
1355
+ return void 0;
1356
+ }
1357
+ return member;
1358
+ };
1359
+ const roots = objectMember("roots");
1360
+ if (roots?.listChanged !== void 0 && typeof roots.listChanged !== "boolean") {
1361
+ problems.push(`${path}.roots.listChanged must be a boolean when present`);
1362
+ }
1363
+ const sampling = objectMember("sampling");
1364
+ for (const key of ["context", "tools"]) {
1365
+ const member = sampling?.[key];
1366
+ if (member !== void 0 && (typeof member !== "object" || member === null || Array.isArray(member))) {
1367
+ problems.push(`${path}.sampling.${key} must be an object when present`);
1368
+ }
1369
+ }
1370
+ const elicitation = objectMember("elicitation");
1371
+ for (const key of ["form", "url"]) {
1372
+ const member = elicitation?.[key];
1373
+ if (member !== void 0 && (typeof member !== "object" || member === null || Array.isArray(member))) {
1374
+ problems.push(`${path}.elicitation.${key} must be an object when present`);
1375
+ }
1376
+ }
1377
+ for (const key of ["experimental", "extensions"]) {
1378
+ const entries = objectMember(key);
1379
+ if (!entries) continue;
1380
+ for (const [name, member] of Object.entries(entries)) {
1381
+ if (key === "extensions" && !/^[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?\/.+/.test(name)) {
1382
+ problems.push(`${path}.extensions.${name} must use a namespaced key with a prefix`);
1383
+ }
1384
+ if (typeof member !== "object" || member === null || Array.isArray(member)) {
1385
+ problems.push(`${path}.${key}.${name} must be an object`);
1386
+ }
1387
+ }
1388
+ }
1389
+ return problems;
1390
+ }
1391
+ function modernRequestMetaProblems(req) {
1392
+ const meta = paramsMeta(req);
1393
+ if (!meta) return [`params._meta is required and must carry ${META_PROTOCOL_VERSION} and ${META_CLIENT_CAPABILITIES}`];
1394
+ const problems = [];
1395
+ const clientInfo = meta[META_CLIENT_INFO];
1396
+ if (clientInfo !== void 0) {
1397
+ problems.push(...mcpImplementationProblems(clientInfo, `params._meta.${META_CLIENT_INFO}`));
1398
+ }
1399
+ const logLevel = meta[META_LOG_LEVEL];
1400
+ if (logLevel !== void 0 && (typeof logLevel !== "string" || !["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"].includes(logLevel))) {
1401
+ problems.push(`params._meta.${META_LOG_LEVEL} must be a valid logging level when present`);
1402
+ }
1403
+ const capabilities = meta[META_CLIENT_CAPABILITIES];
1404
+ problems.push(...mcpClientCapabilitiesProblems(capabilities, `params._meta.${META_CLIENT_CAPABILITIES}`));
1405
+ return problems;
1406
+ }
1407
+
1408
+ // src/mcp/admission.ts
1409
+ var admittedMcpMessage = /* @__PURE__ */ Symbol("AdmittedMcpMessage");
1410
+ function responseId(raw, validId) {
1411
+ const value = raw.id;
1412
+ return validId && value !== void 0 ? value : null;
1413
+ }
1414
+ function rejection(kind, notification, response, protocol, requestedEra) {
1415
+ return {
1416
+ ok: false,
1417
+ kind,
1418
+ response: notification ? null : response,
1419
+ ...protocol ? { protocol } : {},
1420
+ ...requestedEra ? { requestedEra } : {}
1421
+ };
1422
+ }
1423
+ function acceptance(request, id, notification, protocol) {
1424
+ const base = { request, id, protocol, [admittedMcpMessage]: true };
1425
+ return notification ? { ok: true, message: { ...base, notification: true } } : { ok: true, message: { ...base, notification: false } };
1426
+ }
1427
+ function admitMcpMessage(rawMessage, options) {
1428
+ const raw = rawMessage;
1429
+ const hasId = Boolean(raw && Object.prototype.hasOwnProperty.call(raw, "id"));
1430
+ const rawId = raw?.id;
1431
+ const validId = rawId === void 0 || typeof rawId === "string" || typeof rawId === "number" && Number.isSafeInteger(rawId);
1432
+ const validEnvelope = Boolean(raw && !Array.isArray(raw) && raw.jsonrpc === "2.0" && typeof raw.method === "string" && validId);
1433
+ if (!validEnvelope) {
1434
+ return { ok: false, kind: "invalid-request", response: rpcError(null, -32600, "invalid JSON-RPC request") };
1435
+ }
1436
+ const request = rawMessage;
1437
+ const id = responseId(raw, validId);
1438
+ const notification = !hasId;
1439
+ const versionClaim = requestMetaProtocolVersionClaim(request);
1440
+ const declaredVersion = requestMetaProtocolVersion(request);
1441
+ const requestedEra = versionClaim.present ? "modern" : "legacy";
1442
+ const supportedVersions = options.protocolEra === "legacy" ? options.supportedVersions.filter(isLegacyProtocolVersion) : options.protocolEra === "modern" ? options.supportedVersions.filter(isModernProtocolVersion) : [...options.supportedVersions];
1443
+ const effectiveTransportVersion = options.negotiatedVersion ?? options.headerVersion ?? void 0;
1444
+ const provisionalProtocol = isModernProtocolVersion(declaredVersion) ? { era: "modern", version: declaredVersion, supportedVersions } : { era: "legacy", version: declaredVersion ?? effectiveTransportVersion, supportedVersions };
1445
+ if (versionClaim.present && typeof versionClaim.value !== "string") {
1446
+ return rejection(
1447
+ "invalid-modern-metadata",
1448
+ notification,
1449
+ rpcError(id, -32602, `Invalid params: params._meta.${META_PROTOCOL_VERSION} is required and must be a string`),
1450
+ void 0,
1451
+ "modern"
1452
+ );
1453
+ }
1454
+ if (options.headerVersion != null && !supportedVersions.includes(options.headerVersion)) {
1455
+ return rejection(
1456
+ "unsupported-version",
1457
+ notification,
1458
+ rpcError(
1459
+ id,
1460
+ UNSUPPORTED_PROTOCOL_VERSION,
1461
+ `Unsupported protocol version: ${options.headerVersion}`,
1462
+ { supported: [...supportedVersions], requested: options.headerVersion }
1463
+ ),
1464
+ provisionalProtocol,
1465
+ requestedEra
1466
+ );
1467
+ }
1468
+ if (options.negotiatedVersion != null && !supportedVersions.includes(options.negotiatedVersion)) {
1469
+ return rejection(
1470
+ "unsupported-version",
1471
+ notification,
1472
+ rpcError(
1473
+ id,
1474
+ UNSUPPORTED_PROTOCOL_VERSION,
1475
+ `Unsupported protocol version: ${options.negotiatedVersion}`,
1476
+ { supported: [...supportedVersions], requested: options.negotiatedVersion }
1477
+ ),
1478
+ provisionalProtocol,
1479
+ requestedEra
1480
+ );
1481
+ }
1482
+ if (declaredVersion !== void 0 && options.headerVersion != null && declaredVersion !== options.headerVersion) {
1483
+ return rejection(
1484
+ "header-mismatch",
1485
+ notification,
1486
+ rpcError(
1487
+ id,
1488
+ HEADER_MISMATCH,
1489
+ `Header mismatch: MCP-Protocol-Version header value '${options.headerVersion}' does not match body value '${declaredVersion}'`
1490
+ ),
1491
+ provisionalProtocol,
1492
+ requestedEra
1493
+ );
1494
+ }
1495
+ if (options.protocolEra !== void 0 && requestedEra !== options.protocolEra) {
1496
+ const requested = declaredVersion ?? effectiveTransportVersion ?? "unversioned";
1497
+ return rejection(
1498
+ "unsupported-version",
1499
+ notification,
1500
+ rpcError(
1501
+ id,
1502
+ UNSUPPORTED_PROTOCOL_VERSION,
1503
+ `Unsupported protocol version: ${requested}`,
1504
+ { supported: [...supportedVersions], requested }
1505
+ ),
1506
+ provisionalProtocol,
1507
+ requestedEra
1508
+ );
1509
+ }
1510
+ if (requestedEra === "modern" && isLegacyProtocolVersion(declaredVersion) && (!options.requireModernVersionHeader || options.headerVersion != null)) {
1511
+ const modernSupportedVersions = supportedVersions.filter(isModernProtocolVersion);
1512
+ return rejection(
1513
+ "unsupported-version",
1514
+ notification,
1515
+ rpcError(
1516
+ id,
1517
+ UNSUPPORTED_PROTOCOL_VERSION,
1518
+ `Unsupported protocol version: ${declaredVersion}`,
1519
+ { supported: modernSupportedVersions, requested: declaredVersion }
1520
+ ),
1521
+ provisionalProtocol,
1522
+ requestedEra
1523
+ );
1524
+ }
1525
+ if (declaredVersion !== void 0 && !supportedVersions.includes(declaredVersion)) {
1526
+ return rejection(
1527
+ "unsupported-version",
1528
+ notification,
1529
+ rpcError(
1530
+ id,
1531
+ UNSUPPORTED_PROTOCOL_VERSION,
1532
+ `Unsupported protocol version: ${declaredVersion}`,
1533
+ { supported: [...supportedVersions], requested: declaredVersion }
1534
+ ),
1535
+ provisionalProtocol,
1536
+ requestedEra
1537
+ );
1538
+ }
1539
+ const era = options.protocolEra ?? (isModernProtocolVersion(options.headerVersion) || isModernProtocolVersion(options.negotiatedVersion) ? "modern" : requestedEra);
1540
+ if (era === "modern") {
1541
+ if (!isModernProtocolVersion(declaredVersion)) {
1542
+ const problem = `params._meta.${META_PROTOCOL_VERSION} is required and must match the MCP-Protocol-Version header (${options.headerVersion})`;
1543
+ return rejection(
1544
+ "invalid-modern-metadata",
1545
+ notification,
1546
+ rpcError(id, -32602, `Invalid params: ${problem}`),
1547
+ provisionalProtocol,
1548
+ requestedEra
1549
+ );
1550
+ }
1551
+ const protocol2 = { era: "modern", version: declaredVersion, supportedVersions };
1552
+ const metaProblems = modernRequestMetaProblems(request);
1553
+ if (metaProblems.length > 0) {
1554
+ return rejection(
1555
+ "invalid-modern-metadata",
1556
+ notification,
1557
+ rpcError(id, -32602, `Invalid params: ${metaProblems.join("; ")}`),
1558
+ protocol2,
1559
+ requestedEra
1560
+ );
1561
+ }
1562
+ if (options.requireModernVersionHeader && options.headerVersion == null) {
1563
+ return rejection(
1564
+ "header-mismatch",
1565
+ notification,
1566
+ rpcError(
1567
+ id,
1568
+ HEADER_MISMATCH,
1569
+ `Header mismatch: MCP-Protocol-Version header is required for protocol version ${declaredVersion}`
1570
+ ),
1571
+ protocol2,
1572
+ requestedEra
1573
+ );
1574
+ }
1575
+ const transportProblem = options.modernTransportProblem?.(request) ?? null;
1576
+ if (transportProblem !== null) {
1577
+ return rejection(
1578
+ "header-mismatch",
1579
+ notification,
1580
+ rpcError(id, HEADER_MISMATCH, `Header mismatch: ${transportProblem}`),
1581
+ protocol2,
1582
+ requestedEra
1583
+ );
1584
+ }
1585
+ return acceptance(request, id, notification, protocol2);
1586
+ }
1587
+ const protocol = {
1588
+ era: "legacy",
1589
+ version: declaredVersion ?? effectiveTransportVersion,
1590
+ supportedVersions
1591
+ };
1592
+ return acceptance(request, id, notification, protocol);
1264
1593
  }
1265
1594
 
1266
1595
  // src/mcp/tool-surface.ts
@@ -1269,6 +1598,7 @@ function withClosedMcpInputSchema(tool) {
1269
1598
  }
1270
1599
  var MCP_SERVER_NAME = "agentic-mermaid-mcp";
1271
1600
  var MCP_SERVER_VERSION = PACKAGE_VERSION;
1601
+ var SERVER_CAPABILITIES = { tools: {} };
1272
1602
  var PURE_COMPUTE_ANNOTATIONS = {
1273
1603
  readOnlyHint: true,
1274
1604
  destructiveHint: false,
@@ -1476,32 +1806,66 @@ function validateMcpToolArguments(tool, value) {
1476
1806
  const problems = validateSchemaValue(value, tool.inputSchema, tool.inputSchema, [], /* @__PURE__ */ new Set()).map((problem) => `${formatSchemaPath(problem.path)} ${problem.message}`);
1477
1807
  return limitJsonConfigDiagnostics(problems, "arguments");
1478
1808
  }
1479
- async function dispatchMcpRequest(req, context, surface) {
1480
- const raw = req;
1481
- const hasId = Boolean(raw && Object.prototype.hasOwnProperty.call(raw, "id"));
1482
- const rawId = raw?.id;
1483
- const validId = rawId === void 0 || rawId === null || typeof rawId === "string" || typeof rawId === "number" && Number.isFinite(rawId);
1484
- const valid = Boolean(raw && raw.jsonrpc === "2.0" && typeof raw.method === "string" && validId);
1485
- const id = validId && rawId !== void 0 ? rawId : null;
1486
- if (!valid) return rpcError(null, -32600, "invalid JSON-RPC request");
1487
- const notification = !hasId;
1809
+ function surfaceSupportedVersions(surface, options = {}) {
1810
+ const surfaceVersions = surface.supportedVersions ?? (typeof surface.protocolVersion === "string" ? [surface.protocolVersion] : []);
1811
+ if (!options.supportedVersions) return surfaceVersions;
1812
+ return surfaceVersions.filter((version) => options.supportedVersions.includes(version));
1813
+ }
1814
+ function discoverResult(surface, supportedVersions) {
1815
+ return {
1816
+ supportedVersions: [...supportedVersions],
1817
+ capabilities: SERVER_CAPABILITIES,
1818
+ instructions: surface.instructions
1819
+ };
1820
+ }
1821
+ function initializeParamsProblems(params) {
1822
+ if (!plainJsonObject(params)) return ["params is required and must be an object"];
1823
+ const problems = [];
1824
+ if (typeof params.protocolVersion !== "string") {
1825
+ problems.push("params.protocolVersion is required and must be a string");
1826
+ }
1827
+ problems.push(...mcpClientCapabilitiesProblems(params.capabilities, "params.capabilities"));
1828
+ problems.push(...mcpImplementationProblems(params.clientInfo, "params.clientInfo"));
1829
+ return problems;
1830
+ }
1831
+ async function dispatchAdmittedMcpRequest(message, context, surface) {
1832
+ const { request: req, id, notification, protocol } = message;
1833
+ const { era, version, supportedVersions: servedVersions } = protocol;
1488
1834
  let response;
1489
1835
  switch (req.method) {
1836
+ // initialize / notifications/initialized / ping are REMOVED in the modern
1837
+ // era. Under a modern request they are simply unknown methods; a legacy
1838
+ // request keeps the handshake it depends on.
1490
1839
  case "initialize": {
1491
- const protocolVersion = typeof surface.protocolVersion === "function" ? surface.protocolVersion(req.params) : surface.protocolVersion;
1840
+ if (era === "modern") {
1841
+ response = unknownMethod(id, req.method);
1842
+ break;
1843
+ }
1844
+ const problems = initializeParamsProblems(req.params);
1845
+ if (problems.length > 0) {
1846
+ response = rpcError(id, -32602, `Invalid params: ${problems.join("; ")}`);
1847
+ break;
1848
+ }
1849
+ const offered = req.params?.protocolVersion;
1850
+ const legacyServedVersions = servedVersions.filter(isLegacyProtocolVersion);
1851
+ const fallbackLegacyVersion = legacyServedVersions.at(-1) ?? (typeof surface.protocolVersion === "function" ? surface.protocolVersion(req.params) : surface.protocolVersion);
1852
+ const protocolVersion = isLegacyProtocolVersion(offered) && legacyServedVersions.includes(offered) ? offered : fallbackLegacyVersion;
1492
1853
  response = reply(id, {
1493
1854
  protocolVersion,
1494
1855
  serverInfo: { name: surface.serverName ?? MCP_SERVER_NAME, version: MCP_SERVER_VERSION },
1495
- capabilities: { tools: {} },
1856
+ capabilities: SERVER_CAPABILITIES,
1496
1857
  instructions: surface.instructions
1497
1858
  });
1498
1859
  break;
1499
1860
  }
1500
1861
  case "notifications/initialized":
1501
- response = null;
1862
+ response = era === "modern" ? unknownMethod(id, req.method) : null;
1502
1863
  break;
1503
1864
  case "ping":
1504
- response = reply(id, {});
1865
+ response = era === "modern" ? unknownMethod(id, req.method) : reply(id, {});
1866
+ break;
1867
+ case "server/discover":
1868
+ response = era === "modern" ? reply(id, discoverResult(surface, servedVersions)) : unknownMethod(id, req.method);
1505
1869
  break;
1506
1870
  case "tools/list":
1507
1871
  response = reply(id, { tools: surface.tools });
@@ -1524,22 +1888,39 @@ async function dispatchMcpRequest(req, context, surface) {
1524
1888
  const args = req.params.arguments ?? {};
1525
1889
  const problems = validateMcpToolArguments(tool, args);
1526
1890
  if (problems.length > 0) {
1527
- response = rpcError(id, -32602, `Invalid arguments for ${name}: ${problems.join("; ")}`);
1891
+ const message2 = `Invalid arguments for ${name}: ${problems.join("; ")}`;
1892
+ response = usesToolErrorForInvalidArguments(version) ? toolResult(id, { ok: false, error: { code: "INVALID_ARGUMENTS", message: message2 } }, true) : rpcError(id, -32602, message2);
1528
1893
  break;
1529
1894
  }
1530
1895
  response = await surface.handleToolCall(id, { ...req.params, arguments: args }, context);
1531
1896
  break;
1532
1897
  }
1533
- case "prompts/list":
1534
- response = reply(id, { prompts: [] });
1535
- break;
1536
- case "resources/list":
1537
- response = reply(id, { resources: [] });
1538
- break;
1539
1898
  default:
1540
- response = rpcError(id, -32601, `Method not found: ${req.method}`);
1899
+ response = unknownMethod(id, req.method);
1900
+ }
1901
+ return notification ? null : decorateMcpResult(response, req.method, era, surface.serverName ?? MCP_SERVER_NAME);
1902
+ }
1903
+ var LIST_RESULT_TTL_MS = 3e5;
1904
+ var CACHEABLE_METHODS = /* @__PURE__ */ new Set(["server/discover", "tools/list"]);
1905
+ function decorateMcpResult(response, method, era, serverName) {
1906
+ if (era !== "modern" || !response || !plainJsonObject(response.result)) return response;
1907
+ const existingMeta = plainJsonObject(response.result._meta) ? response.result._meta : {};
1908
+ const result = {
1909
+ resultType: "complete",
1910
+ ...response.result,
1911
+ _meta: {
1912
+ ...existingMeta,
1913
+ [META_SERVER_INFO]: { name: serverName, version: MCP_SERVER_VERSION }
1914
+ }
1915
+ };
1916
+ if (CACHEABLE_METHODS.has(method)) {
1917
+ result.ttlMs = LIST_RESULT_TTL_MS;
1918
+ result.cacheScope = "public";
1541
1919
  }
1542
- return notification ? null : response;
1920
+ return { ...response, result };
1921
+ }
1922
+ function unknownMethod(id, method) {
1923
+ return rpcError(id, -32601, `Method not found: ${method}`);
1543
1924
  }
1544
1925
  function createExecuteTool(options) {
1545
1926
  const hostedNote = options.hosted ? `Hosted note: execute runs in an on-demand isolate and costs more than the direct
@@ -2656,6 +3037,7 @@ import {
2656
3037
  readFileSync,
2657
3038
  readdirSync,
2658
3039
  renameSync,
3040
+ rmdirSync,
2659
3041
  unlinkSync,
2660
3042
  writeFileSync,
2661
3043
  writeSync
@@ -2669,7 +3051,12 @@ var DEFAULT_TTL_MS = 60 * 60 * 1e3;
2669
3051
  var MANIFEST_NAME = ".agentic-mermaid-artifacts-v1.json";
2670
3052
  var LOCK_NAME = ".agentic-mermaid-artifacts-v1.lock";
2671
3053
  var MAX_MANIFEST_BYTES = 1024 * 1024;
3054
+ var MAX_LOCK_BYTES = 4096;
2672
3055
  var MANAGED_NAME = /^[0-9a-z]+-[0-9a-f-]{36}\.[a-z0-9_-]+$/;
3056
+ var IMPLICIT_NAMESPACE = /^store-[1-9][0-9]*-[0-9a-f-]{36}$/;
3057
+ var LEGACY_IMPLICIT_NAMESPACE = /^agentic-mermaid-mcp-artifacts-[1-9][0-9]*-[0-9a-f-]{36}$/;
3058
+ var IMPLICIT_REAP_GRACE_MS = 3e4;
3059
+ var DEFAULT_ARTIFACT_ROOT = join(tmpdir(), "agentic-mermaid-mcp-artifacts");
2673
3060
  function positiveSafeInteger(value, field) {
2674
3061
  if (!Number.isSafeInteger(value) || value <= 0) throw new Error(`artifact ${field} must be a positive safe integer`);
2675
3062
  return value;
@@ -2689,7 +3076,9 @@ var ArtifactStore = class {
2689
3076
  lockFd = -1;
2690
3077
  closed = false;
2691
3078
  constructor(opts = {}) {
2692
- this.dir = resolve(opts.dir ?? join(tmpdir(), "agentic-mermaid-mcp-artifacts"));
3079
+ if (opts.dir !== void 0 && opts.namespaceRoot !== void 0) {
3080
+ throw new Error("artifact dir and namespaceRoot are mutually exclusive");
3081
+ }
2693
3082
  this.baseUrl = normalizeBaseUrl(opts.baseUrl);
2694
3083
  this.maxBytes = positiveSafeInteger(opts.maxBytes ?? DEFAULT_MAX_BYTES, "maxBytes");
2695
3084
  this.maxTotalBytes = positiveSafeInteger(opts.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES, "maxTotalBytes");
@@ -2697,7 +3086,23 @@ var ArtifactStore = class {
2697
3086
  this.ttlMs = positiveSafeInteger(opts.ttlMs ?? DEFAULT_TTL_MS, "ttlMs");
2698
3087
  if (this.maxBytes > this.maxTotalBytes) throw new Error("artifact maxBytes must not exceed maxTotalBytes");
2699
3088
  this.now = opts.now ?? (() => Date.now());
2700
- mkdirSync(this.dir, { recursive: true, mode: 448 });
3089
+ if (opts.dir !== void 0) {
3090
+ this.dir = resolve(opts.dir);
3091
+ mkdirSync(this.dir, { recursive: true, mode: 448 });
3092
+ } else {
3093
+ const root = resolve(opts.namespaceRoot ?? DEFAULT_ARTIFACT_ROOT);
3094
+ mkdirSync(root, { recursive: true, mode: 448 });
3095
+ const rootStat = lstatSync(root);
3096
+ if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) {
3097
+ throw new Error("artifact namespace root must be a real directory");
3098
+ }
3099
+ if (opts.namespaceRoot === void 0) {
3100
+ reapImplicitArtifactNamespaces(resolve(tmpdir()), this.now(), LEGACY_IMPLICIT_NAMESPACE);
3101
+ }
3102
+ reapImplicitArtifactNamespaces(root, this.now());
3103
+ this.dir = join(root, `store-${process.pid}-${randomUUID()}`);
3104
+ mkdirSync(this.dir, { mode: 448 });
3105
+ }
2701
3106
  this.manifestPath = join(this.dir, MANIFEST_NAME);
2702
3107
  this.lockPath = join(this.dir, LOCK_NAME);
2703
3108
  this.acquireOwnership();
@@ -2900,7 +3305,7 @@ var ArtifactStore = class {
2900
3305
  }
2901
3306
  let totalBytes = 0;
2902
3307
  for (const candidate of manifest.records) {
2903
- if (!candidate || typeof candidate !== "object" || typeof candidate.name !== "string" || !MANAGED_NAME.test(candidate.name) || typeof candidate.mimeType !== "string" || candidate.mimeType.length === 0 || !Number.isSafeInteger(candidate.bytes) || candidate.bytes < 0 || typeof candidate.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(candidate.sha256) || !Number.isSafeInteger(candidate.createdAt) || !Number.isSafeInteger(candidate.expiresAt) || candidate.expiresAt <= candidate.createdAt) {
3308
+ if (!isManifestRecord(candidate)) {
2904
3309
  throw new Error("artifact manifest contains an invalid record");
2905
3310
  }
2906
3311
  const path = safePath(this.dir, candidate.name);
@@ -2941,6 +3346,113 @@ var ArtifactStore = class {
2941
3346
  if (persist) this.persistManifest();
2942
3347
  }
2943
3348
  };
3349
+ function reapImplicitArtifactNamespaces(root, now, namespacePattern = IMPLICIT_NAMESPACE) {
3350
+ let entries;
3351
+ try {
3352
+ entries = readdirSync(root);
3353
+ } catch {
3354
+ return;
3355
+ }
3356
+ for (const name of entries) {
3357
+ if (!namespacePattern.test(name)) continue;
3358
+ const dir = safePath(root, name);
3359
+ try {
3360
+ const namespace = lstatSync(dir);
3361
+ if (!namespace.isDirectory() || namespace.isSymbolicLink()) continue;
3362
+ if (now - namespace.mtimeMs < IMPLICIT_REAP_GRACE_MS) continue;
3363
+ const lockPath = join(dir, LOCK_NAME);
3364
+ if (existsSync(lockPath)) {
3365
+ const lock = lstatSync(lockPath);
3366
+ if (!lock.isFile() || lock.isSymbolicLink() || lock.size > MAX_LOCK_BYTES) continue;
3367
+ const marker = JSON.parse(readFileSync(lockPath, "utf8"));
3368
+ if (marker.host !== hostname() || !Number.isSafeInteger(marker.pid) || marker.pid <= 0) continue;
3369
+ if (processIsAlive(marker.pid)) continue;
3370
+ const current = lstatSync(lockPath);
3371
+ if (current.dev !== lock.dev || current.ino !== lock.ino) continue;
3372
+ unlinkSync(lockPath);
3373
+ }
3374
+ reapClosedNamespace(dir, now);
3375
+ } catch {
3376
+ }
3377
+ }
3378
+ }
3379
+ function processIsAlive(pid) {
3380
+ try {
3381
+ process.kill(pid, 0);
3382
+ return true;
3383
+ } catch (error) {
3384
+ return error.code !== "ESRCH";
3385
+ }
3386
+ }
3387
+ function reapClosedNamespace(dir, now) {
3388
+ const manifestPath = join(dir, MANIFEST_NAME);
3389
+ let records = [];
3390
+ if (existsSync(manifestPath)) {
3391
+ const stat = lstatSync(manifestPath);
3392
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_MANIFEST_BYTES) return;
3393
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
3394
+ if (manifest?.schemaVersion !== 1 || !Array.isArray(manifest.records) || manifest.records.some((record) => !isManifestRecord(record))) return;
3395
+ records = manifest.records;
3396
+ }
3397
+ const live = [];
3398
+ for (const record of records) {
3399
+ const path = safePath(dir, record.name);
3400
+ if (record.expiresAt <= now) {
3401
+ try {
3402
+ unlinkSync(path);
3403
+ } catch {
3404
+ }
3405
+ continue;
3406
+ }
3407
+ try {
3408
+ const file = lstatSync(path);
3409
+ if (file.isFile() && !file.isSymbolicLink() && file.size === record.bytes) live.push(record);
3410
+ else if (file.isFile() || file.isSymbolicLink()) unlinkSync(path);
3411
+ } catch {
3412
+ }
3413
+ }
3414
+ const liveNames = new Set(live.map((record) => record.name));
3415
+ for (const name of readdirSync(dir)) {
3416
+ if (!MANAGED_NAME.test(name) || liveNames.has(name)) continue;
3417
+ const path = safePath(dir, name);
3418
+ try {
3419
+ const file = lstatSync(path);
3420
+ if (file.isFile() || file.isSymbolicLink()) unlinkSync(path);
3421
+ } catch {
3422
+ }
3423
+ }
3424
+ if (live.length > 0) {
3425
+ if (live.length !== records.length) persistManifestRecords(dir, live);
3426
+ return;
3427
+ }
3428
+ try {
3429
+ const manifest = lstatSync(manifestPath);
3430
+ if (manifest.isFile() && !manifest.isSymbolicLink()) unlinkSync(manifestPath);
3431
+ } catch {
3432
+ }
3433
+ try {
3434
+ rmdirSync(dir);
3435
+ } catch {
3436
+ }
3437
+ }
3438
+ function persistManifestRecords(dir, records) {
3439
+ const path = join(dir, MANIFEST_NAME);
3440
+ const temp = join(dir, `.${MANIFEST_NAME}.${process.pid}.${randomUUID()}.tmp`);
3441
+ try {
3442
+ writeFileSync(temp, JSON.stringify({ schemaVersion: 1, records }), { mode: 384 });
3443
+ renameSync(temp, path);
3444
+ } finally {
3445
+ try {
3446
+ unlinkSync(temp);
3447
+ } catch {
3448
+ }
3449
+ }
3450
+ }
3451
+ function isManifestRecord(candidate) {
3452
+ if (!candidate || typeof candidate !== "object") return false;
3453
+ const record = candidate;
3454
+ return typeof record.name === "string" && MANAGED_NAME.test(record.name) && typeof record.mimeType === "string" && record.mimeType.length > 0 && Number.isSafeInteger(record.bytes) && record.bytes >= 0 && typeof record.sha256 === "string" && /^[a-f0-9]{64}$/.test(record.sha256) && Number.isSafeInteger(record.createdAt) && Number.isSafeInteger(record.expiresAt) && record.expiresAt > record.createdAt;
3455
+ }
2944
3456
  function createArtifactStore(opts = {}) {
2945
3457
  return new ArtifactStore(opts);
2946
3458
  }
@@ -2967,6 +3479,9 @@ function safePath(root, name) {
2967
3479
 
2968
3480
  // src/mcp/server.ts
2969
3481
  var PROTOCOL_VERSION = "2024-11-05";
3482
+ var STDIO_PROTOCOL_VERSIONS = ["2024-11-05", "2025-06-18", "2025-11-25", "2026-07-28"];
3483
+ var HTTP_SSE_PROTOCOL_VERSIONS = ["2024-11-05"];
3484
+ var HTTP_SSE_DISPATCH = { supportedVersions: HTTP_SSE_PROTOCOL_VERSIONS };
2970
3485
  var MAX_RPC_BODY_BYTES = 1024 * 1024;
2971
3486
  var MAX_SANDBOX_TIMEOUT_MS = 3e4;
2972
3487
  var MAX_SSE_SESSIONS = 32;
@@ -2989,12 +3504,21 @@ var MCP_NARROWERS = BUILTIN_FAMILY_METADATA.map((f) => f.narrower).join("/");
2989
3504
  var LOCAL_INSTRUCTIONS = `agentic-mermaid Code Mode server. Primary tool execute runs synchronous JavaScript against the typed mermaid.* SDK in a sandbox; async/await and Promise jobs are not supported. describe_sdk progressively discloses one family's version-matched mutation schema; call it before authoring unfamiliar ops. render_png and describe are narrow helpers. render_png can return base64, managed file paths, or managed URLs when the transport config provides an artifact store. There is no mutate tool on this server: structured edits go through the SDK's mermaid.mutate(...) inside execute; narrow via ${MCP_NARROWERS}. Every built-in renderable family ships a typed path when the body narrows; only opaque fallback bodies are source-level only. Layout is deterministic; there is no layout seed (the optional style seed only re-rolls ink of styled looks, never geometry).`;
2990
3505
  var LOCAL_SURFACE = {
2991
3506
  protocolVersion: PROTOCOL_VERSION,
3507
+ supportedVersions: STDIO_PROTOCOL_VERSIONS,
2992
3508
  tools: LOCAL_TOOLS,
2993
3509
  instructions: LOCAL_INSTRUCTIONS,
2994
3510
  handleToolCall
2995
3511
  };
2996
- async function handleRequest(req, context = {}) {
2997
- return dispatchMcpRequest(req, context, LOCAL_SURFACE);
3512
+ function admitLocalRequest(req, options = {}) {
3513
+ return admitMcpMessage(req, {
3514
+ supportedVersions: surfaceSupportedVersions(LOCAL_SURFACE, options),
3515
+ negotiatedVersion: options.protocolVersion,
3516
+ protocolEra: options.protocolEra
3517
+ });
3518
+ }
3519
+ async function handleRequest(req, context = {}, options = {}) {
3520
+ const admission = admitLocalRequest(req, options);
3521
+ return admission.ok ? dispatchAdmittedMcpRequest(admission.message, context, LOCAL_SURFACE) : admission.response;
2998
3522
  }
2999
3523
  async function handleToolCall(id, params, context) {
3000
3524
  const p = params;
@@ -3075,7 +3599,7 @@ function artifactPayload(artifact, output) {
3075
3599
  return { ...base, path: artifact.path };
3076
3600
  }
3077
3601
  function getDefaultArtifactStore() {
3078
- defaultArtifactStore ??= createArtifactStore({ dir: join2(tmpdir2(), "agentic-mermaid-mcp-artifacts") });
3602
+ defaultArtifactStore ??= createArtifactStore();
3079
3603
  if (!defaultArtifactStoreExitHook) {
3080
3604
  defaultArtifactStoreExitHook = true;
3081
3605
  process.once("exit", () => defaultArtifactStore?.close());
@@ -3088,6 +3612,112 @@ function warmUpPngRenderer() {
3088
3612
  } catch {
3089
3613
  }
3090
3614
  }
3615
+ function stdioCancellationTarget(value) {
3616
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
3617
+ const request = value;
3618
+ if (request.jsonrpc !== "2.0" || request.method !== "notifications/cancelled" || Object.prototype.hasOwnProperty.call(request, "id")) return void 0;
3619
+ const params = request.params;
3620
+ if (!params || typeof params !== "object" || Array.isArray(params)) return void 0;
3621
+ const requestId = params.requestId;
3622
+ return typeof requestId === "string" || typeof requestId === "number" && Number.isSafeInteger(requestId) ? requestId : void 0;
3623
+ }
3624
+ function stdioRequestId(value) {
3625
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
3626
+ const request = value;
3627
+ if (request.jsonrpc !== "2.0" || typeof request.method !== "string" || !Object.prototype.hasOwnProperty.call(request, "id")) return void 0;
3628
+ const requestId = request.id;
3629
+ return typeof requestId === "string" || typeof requestId === "number" && Number.isSafeInteger(requestId) ? requestId : void 0;
3630
+ }
3631
+ function stdioRequestKey(id) {
3632
+ return `${typeof id}:${String(id)}`;
3633
+ }
3634
+ function createStdioMessageProcessor(context, write, dispatch = dispatchAdmittedMcpRequest) {
3635
+ let negotiatedProtocolVersion = null;
3636
+ let negotiatedEra = null;
3637
+ let admissionGate = Promise.resolve();
3638
+ const tasks = /* @__PURE__ */ new Set();
3639
+ const inFlight = /* @__PURE__ */ new Map();
3640
+ const register = (id, controller) => {
3641
+ if (id === void 0) return;
3642
+ const key = stdioRequestKey(id);
3643
+ const controllers = inFlight.get(key) ?? /* @__PURE__ */ new Set();
3644
+ controllers.add(controller);
3645
+ inFlight.set(key, controllers);
3646
+ };
3647
+ const unregister = (id, controller) => {
3648
+ if (id === void 0) return;
3649
+ const key = stdioRequestKey(id);
3650
+ const controllers = inFlight.get(key);
3651
+ controllers?.delete(controller);
3652
+ if (controllers?.size === 0) inFlight.delete(key);
3653
+ };
3654
+ const emit = (response, exactIds, signal) => {
3655
+ if (response && !signal?.aborted) write(stringifyJsonRpc(response, exactIds) + "\n");
3656
+ };
3657
+ const accept = (line) => {
3658
+ let exact;
3659
+ let request;
3660
+ try {
3661
+ exact = preserveExactJsonRpcIds(line);
3662
+ request = JSON.parse(exact.body);
3663
+ } catch (cause) {
3664
+ write(JSON.stringify(rpcError(null, -32700, `parse error: ${cause instanceof Error ? cause.message : String(cause)}`)) + "\n");
3665
+ return;
3666
+ }
3667
+ const cancellationTarget = stdioCancellationTarget(request);
3668
+ if (cancellationTarget !== void 0) {
3669
+ for (const controller2 of inFlight.get(stdioRequestKey(cancellationTarget)) ?? []) controller2.abort();
3670
+ return;
3671
+ }
3672
+ const requestId = stdioRequestId(request);
3673
+ const controller = new AbortController();
3674
+ register(requestId, controller);
3675
+ const preparation = admissionGate.then(async () => {
3676
+ const dispatchOptions = negotiatedEra === "legacy" ? { protocolEra: "legacy", protocolVersion: negotiatedProtocolVersion, supportedVersions: negotiatedProtocolVersion ? [negotiatedProtocolVersion] : void 0 } : negotiatedEra === "modern" ? { protocolEra: "modern", supportedVersions: STDIO_PROTOCOL_VERSIONS } : {};
3677
+ const admission = admitLocalRequest(request, dispatchOptions);
3678
+ if (admission.ok && negotiatedEra === null && request.method === "initialize") {
3679
+ const response = controller.signal.aborted ? null : await dispatch(admission.message, { ...context, signal: controller.signal }, LOCAL_SURFACE);
3680
+ if (!controller.signal.aborted && response?.result && typeof response.result === "object") {
3681
+ const selected = response.result.protocolVersion;
3682
+ if (typeof selected === "string" && STDIO_PROTOCOL_VERSIONS.includes(selected)) {
3683
+ negotiatedProtocolVersion = selected;
3684
+ negotiatedEra = "legacy";
3685
+ }
3686
+ }
3687
+ emit(response, exact.ids, controller.signal);
3688
+ return { handled: true, admission };
3689
+ }
3690
+ if (admission.ok && negotiatedEra === null && admission.message.protocol.era === "modern") {
3691
+ negotiatedEra = "modern";
3692
+ }
3693
+ return { handled: false, admission };
3694
+ });
3695
+ admissionGate = preparation.then(() => void 0, () => void 0);
3696
+ let task;
3697
+ task = preparation.then(async (prepared) => {
3698
+ if (prepared.handled) return;
3699
+ const response = prepared.admission.ok ? controller.signal.aborted ? null : await dispatch(prepared.admission.message, { ...context, signal: controller.signal }, LOCAL_SURFACE) : prepared.admission.response;
3700
+ emit(response, exact.ids, controller.signal);
3701
+ }).catch((cause) => {
3702
+ emit(
3703
+ rpcError(requestId ?? null, -32603, `internal error: ${cause instanceof Error ? cause.message : String(cause)}`),
3704
+ exact.ids,
3705
+ controller.signal
3706
+ );
3707
+ }).finally(() => {
3708
+ unregister(requestId, controller);
3709
+ tasks.delete(task);
3710
+ });
3711
+ tasks.add(task);
3712
+ };
3713
+ return {
3714
+ accept,
3715
+ async drain() {
3716
+ await admissionGate;
3717
+ while (tasks.size > 0) await Promise.allSettled([...tasks]);
3718
+ }
3719
+ };
3720
+ }
3091
3721
  async function runStdio(options = {}) {
3092
3722
  warmUpPngRenderer();
3093
3723
  const artifactStore = createArtifactStore({
@@ -3097,22 +3727,20 @@ async function runStdio(options = {}) {
3097
3727
  maxArtifacts: options.maxArtifacts,
3098
3728
  ttlMs: options.artifactTtlMs
3099
3729
  });
3730
+ const processor = createStdioMessageProcessor(
3731
+ { artifactStore, maxSandboxTimeoutMs: options.maxSandboxTimeoutMs },
3732
+ (line) => process.stdout.write(line)
3733
+ );
3100
3734
  process.stdin.setEncoding("utf8");
3101
3735
  let buf = "";
3102
- process.stdin.on("data", async (chunk) => {
3736
+ process.stdin.on("data", (chunk) => {
3103
3737
  buf += chunk;
3104
3738
  let nl;
3105
3739
  while ((nl = buf.indexOf("\n")) >= 0) {
3106
3740
  const line = buf.slice(0, nl).trim();
3107
3741
  buf = buf.slice(nl + 1);
3108
3742
  if (!line) continue;
3109
- try {
3110
- const exact = preserveExactJsonRpcIds(line);
3111
- const res = await handleRequest(JSON.parse(exact.body), { artifactStore, maxSandboxTimeoutMs: options.maxSandboxTimeoutMs });
3112
- if (res) process.stdout.write(stringifyJsonRpc(res, exact.ids) + "\n");
3113
- } catch (e) {
3114
- process.stdout.write(JSON.stringify(rpcError(null, -32700, `parse error: ${e.message}`)) + "\n");
3115
- }
3743
+ processor.accept(line);
3116
3744
  }
3117
3745
  });
3118
3746
  try {
@@ -3120,6 +3748,7 @@ async function runStdio(options = {}) {
3120
3748
  process.stdin.on("end", () => resolve2());
3121
3749
  process.stdin.on("close", () => resolve2());
3122
3750
  });
3751
+ await processor.drain();
3123
3752
  } finally {
3124
3753
  artifactStore.close();
3125
3754
  }
@@ -3288,7 +3917,7 @@ async function postSseMessage(req, res, sessions, context, maxBytes) {
3288
3917
  } catch {
3289
3918
  throw new HttpStatusError(400, "invalid JSON-RPC body");
3290
3919
  }
3291
- const response = await handleRequest(parsed, context);
3920
+ const response = await handleRequest(parsed, context, HTTP_SSE_DISPATCH);
3292
3921
  if (response) {
3293
3922
  sse.write(`event: message
3294
3923
  data: ${stringifyJsonRpc(response, exact.ids)}
@@ -3308,7 +3937,7 @@ async function postRpc(req, res, context, maxBytes) {
3308
3937
  } catch {
3309
3938
  throw new HttpStatusError(400, "invalid JSON-RPC body");
3310
3939
  }
3311
- const response = await handleRequest(parsed, context);
3940
+ const response = await handleRequest(parsed, context, HTTP_SSE_DISPATCH);
3312
3941
  if (response === null) {
3313
3942
  res.writeHead(202);
3314
3943
  res.end();
@@ -3482,4 +4111,4 @@ export {
3482
4111
  parseMcpCliOptions,
3483
4112
  runMcpCli
3484
4113
  };
3485
- //# sourceMappingURL=chunk-FGO3J7RA.js.map
4114
+ //# sourceMappingURL=chunk-WMFFVZ4Q.js.map