mmt-mcp 1.46.0-pre → 1.46.2-pre

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.
@@ -1151,12 +1151,6 @@
1151
1151
  "category": "professional",
1152
1152
  "title": "Echo API"
1153
1153
  },
1154
- {
1155
- "path": "professional/01_report_generation/multimeter.mmt",
1156
- "type": "env",
1157
- "category": "professional",
1158
- "title": "Report Generation Example"
1159
- },
1160
1154
  {
1161
1155
  "path": "professional/01_report_generation/reports/results.mmt",
1162
1156
  "type": "report",
package/dist/server.cjs CHANGED
@@ -11927,26 +11927,46 @@ function valueMatchesRandomToken(spec, actual) {
11927
11927
 
11928
11928
  // ../core/src/CurrentGit.ts
11929
11929
  var gitSnapshot;
11930
- function setGitCurrentSnapshot(snapshot) {
11931
- gitSnapshot = snapshot;
11930
+ var gitSnapshotLoaded = false;
11931
+ var gitSnapshotProvider;
11932
+ function setGitCurrentSnapshotProvider(provider) {
11933
+ gitSnapshotProvider = provider;
11934
+ }
11935
+ function clearGitCurrentSnapshot() {
11936
+ gitSnapshot = void 0;
11937
+ gitSnapshotLoaded = false;
11938
+ }
11939
+ function ensureGitCurrentSnapshot() {
11940
+ if (gitSnapshotLoaded) {
11941
+ return gitSnapshot;
11942
+ }
11943
+ gitSnapshotLoaded = true;
11944
+ if (gitSnapshotProvider) {
11945
+ try {
11946
+ gitSnapshot = gitSnapshotProvider() ?? void 0;
11947
+ } catch {
11948
+ gitSnapshot = void 0;
11949
+ }
11950
+ }
11951
+ return gitSnapshot;
11932
11952
  }
11933
11953
  function currentGitBranch() {
11934
- return gitSnapshot?.branch ?? "";
11954
+ return ensureGitCurrentSnapshot()?.branch ?? "";
11935
11955
  }
11936
11956
  function currentGitCommit() {
11937
- return gitSnapshot?.commit ?? "";
11957
+ return ensureGitCurrentSnapshot()?.commit ?? "";
11938
11958
  }
11939
11959
  function currentGitCommitHash() {
11940
- return gitSnapshot?.commitHash ?? "";
11960
+ return ensureGitCurrentSnapshot()?.commitHash ?? "";
11941
11961
  }
11942
11962
  function currentGitTag() {
11943
- return gitSnapshot?.tag ?? "";
11963
+ return ensureGitCurrentSnapshot()?.tag ?? "";
11944
11964
  }
11945
11965
  function currentGitDescribe() {
11946
- return gitSnapshot?.describe ?? "";
11966
+ return ensureGitCurrentSnapshot()?.describe ?? "";
11947
11967
  }
11948
11968
  function currentGitDirty() {
11949
- return gitSnapshot?.dirty === true;
11969
+ return ensureGitCurrentSnapshot()?.dirty === true;
11950
11970
  }
11951
11971
  function sanitizeReportPathSegment(raw) {
11952
11972
  const s = String(raw ?? "").trim().replace(/\\/g, "/").replace(/[\x00-\x1f\x7f]/g, "");
@@ -11959,7 +11979,8 @@ function sanitizeReportPathSegment(raw) {
11959
11979
  return s;
11960
11980
  }
11961
11981
  function currentReportFolder() {
11962
- const tagRaw = String(gitSnapshot?.tag ?? "").trim();
11982
+ const snap = ensureGitCurrentSnapshot();
11983
+ const tagRaw = String(snap?.tag ?? "").trim();
11963
11984
  if (tagRaw) {
11964
11985
  const firstTag = tagRaw.split(",")[0]?.trim() || "";
11965
11986
  const tagSeg = sanitizeReportPathSegment(firstTag);
@@ -11967,8 +11988,8 @@ function currentReportFolder() {
11967
11988
  return `tags/${tagSeg}`;
11968
11989
  }
11969
11990
  }
11970
- const commit = sanitizeReportPathSegment(String(gitSnapshot?.commit ?? "").trim());
11971
- const branchRaw = String(gitSnapshot?.branch ?? "").trim();
11991
+ const commit = sanitizeReportPathSegment(String(snap?.commit ?? "").trim());
11992
+ const branchRaw = String(snap?.branch ?? "").trim();
11972
11993
  if (branchRaw && commit) {
11973
11994
  const branchSeg = sanitizeReportPathSegment(branchRaw);
11974
11995
  if (branchSeg) {
@@ -16263,10 +16284,8 @@ var apiToJSfunc = async (ctx) => {
16263
16284
  }
16264
16285
  req_.body = __multipartBuilt_.body;
16265
16286
  ` : "";
16266
- const detailsRequestExpr = isBinaryRequest ? `{ ...req_, body: '<binary ' + __binaryBody_.length + ' bytes path=' + __binaryPath_ + '>' }` : isMultipartRequest ? `{ ...req_, body: '<multipart ' + req_.body.length + ' bytes>' }` : "req_";
16267
- return `const ${ctx.name} = async ({ ${inputParams} } = {}) => {
16268
- const __resolvedUrl = ${toTemplateWithEnvs(String(replaced.url || ""))};
16269
- ${binaryLoadLines}${multipartPrepLines} const req_ = {
16287
+ const detailsRequestExpr = isBinaryRequest ? `{ ...req_, body: '<binary ' + (req_.body && req_.body.length || 0) + ' bytes>' }` : isMultipartRequest ? `{ ...req_, body: '<multipart ' + (req_.body && req_.body.length || 0) + ' bytes>' }` : "req_";
16288
+ const builtReqLiteral = `{
16270
16289
  url: __resolvedUrl,
16271
16290
  protocol: ${protocolExpr},
16272
16291
  method: '${effectiveMethod}',
@@ -16274,11 +16293,30 @@ ${binaryLoadLines}${multipartPrepLines} const req_ = {
16274
16293
  query: ${queryParams ? "{ " + queryParams + " }" : "{}"},
16275
16294
  headers: ${headers ? "{ " + headers + " }" : "{}"},
16276
16295
  body: ${bodyExpr}
16277
- };
16296
+ }`;
16297
+ return `const ${ctx.name} = async ({ ${inputParams} } = {}) => {
16298
+ let req_;
16299
+ if (typeof __mmt_requestOverride !== 'undefined' && __mmt_requestOverride) {
16300
+ req_ = __mmt_requestOverride;
16301
+ ${isBinaryRequest ? ` if (typeof req_.body === 'string' && req_.body) {
16302
+ req_ = { ...req_, body: await readBinaryFile_(String(req_.body).trim()) };
16303
+ }
16304
+ ` : ""}${isMultipartRequest ? ` if (req_.body != null && typeof req_.body === 'object') {
16305
+ const __multipartBuilt_ = await buildMultipartBodyFromParts_(req_.body);
16306
+ if (!req_.headers) { req_.headers = {}; }
16307
+ if (!req_.headers["Content-Type"] || String(req_.headers["Content-Type"]).toLowerCase().indexOf("boundary=") < 0) {
16308
+ req_.headers["Content-Type"] = __multipartBuilt_.contentType;
16309
+ }
16310
+ req_ = { ...req_, body: __multipartBuilt_.body };
16311
+ }
16312
+ ` : ""} } else {
16313
+ const __resolvedUrl = ${toTemplateWithEnvs(String(replaced.url || ""))};
16314
+ ${binaryLoadLines}${multipartPrepLines} req_ = ${builtReqLiteral};
16315
+ ${declaredReqFormat === "auto" ? `const __reqFormat_ = resolveRequestFormat_('auto', req_.headers, req_.body);
16316
+ applyOmitToRequest_(req_, __reqFormat_);` : `applyOmitToRequest_(req_, '${declaredReqFormat}');`}
16317
+ ${multipartBuildLines ? multipartBuildLines.split("\n").map((l) => l ? " " + l : l).join("\n") : ""} }
16278
16318
  ${authCode}
16279
- ${declaredReqFormat === "auto" ? `const __reqFormat_ = resolveRequestFormat_('auto', req_.headers, req_.body);
16280
- applyOmitToRequest_(req_, __reqFormat_);` : `applyOmitToRequest_(req_, '${declaredReqFormat}');`}
16281
- ${multipartBuildLines} const res_ = await send_(req_);
16319
+ const res_ = await send_(req_);
16282
16320
 
16283
16321
  const __extractSource_ = {
16284
16322
  type: 'auto',
@@ -16351,26 +16389,33 @@ function generateGrpcFunction(ctx, replaced, inputParams, userExtractRules, toTp
16351
16389
  messageExpr = `{ ${msgParts} }`;
16352
16390
  }
16353
16391
  return `const ${ctx.name} = async ({ ${inputParams} } = {}) => {
16354
- const __resolvedUrl = ${toTpl(String(replaced.url || ""))};
16355
- const req_ = {
16356
- url: __resolvedUrl,
16357
- protocol: 'grpc',
16358
- method: 'grpc',
16359
- query: {},
16360
- headers: ${headers ? "{ " + headers + " }" : "{}"},
16361
- body: ${messageExpr}
16362
- };
16392
+ let req_;
16393
+ let __grpcReq;
16394
+ if (typeof __mmt_requestOverride !== 'undefined' && __mmt_requestOverride) {
16395
+ req_ = __mmt_requestOverride;
16396
+ __grpcReq = __mmt_requestOverride;
16397
+ } else {
16398
+ const __resolvedUrl = ${toTpl(String(replaced.url || ""))};
16399
+ req_ = {
16400
+ url: __resolvedUrl,
16401
+ protocol: 'grpc',
16402
+ method: 'grpc',
16403
+ query: {},
16404
+ headers: ${headers ? "{ " + headers + " }" : "{}"},
16405
+ body: ${messageExpr}
16406
+ };
16363
16407
  ${authCode}
16364
- const __grpcReq = {
16365
- url: __resolvedUrl,
16366
- proto: ${protoExpr},
16367
- service: ${serviceExpr},
16368
- method: ${methodExpr},
16369
- metadata: req_.headers,
16370
- message: ${messageExpr},
16371
- stream: ${streamExpr}
16372
- };
16373
- applyOmitToRequest_(__grpcReq);
16408
+ __grpcReq = {
16409
+ url: __resolvedUrl,
16410
+ proto: ${protoExpr},
16411
+ service: ${serviceExpr},
16412
+ method: ${methodExpr},
16413
+ metadata: req_.headers,
16414
+ message: ${messageExpr},
16415
+ stream: ${streamExpr}
16416
+ };
16417
+ applyOmitToRequest_(__grpcReq);
16418
+ }
16374
16419
  const __grpcRes = await sendGrpc_(__grpcReq);
16375
16420
 
16376
16421
  // Parse gRPC response message
@@ -16460,7 +16505,7 @@ function generateOAuth2JS(auth, toTpl) {
16460
16505
  const scopePart = auth.scope ? `
16461
16506
  scope: ${toTpl(auth.scope)},` : "";
16462
16507
  return ` if (!req_.headers["Authorization"]) {
16463
- const _tokenResp = await send_({
16508
+ const _tokenResp = await __mmt_originalSend({
16464
16509
  url: ${toTpl(auth.token_url)},
16465
16510
  method: "post",
16466
16511
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
@@ -26805,7 +26850,8 @@ ${helperFactorySource}
26805
26850
  const __mmt_originalSendGrpc = typeof sendGrpc_ === 'function' ? sendGrpc_ : null;
26806
26851
  send_ = async function(req) {
26807
26852
  await checkAbort_();
26808
- const __req = req || {};
26853
+ const __req = (typeof __mmt_requestOverride !== 'undefined' &&
26854
+ __mmt_requestOverride) ? __mmt_requestOverride : (req || {});
26809
26855
  const __maskedHeaders = {};
26810
26856
  for (const [k, v] of Object.entries(__req.headers || {})) {
26811
26857
  const lk = k.toLowerCase();
@@ -26835,7 +26881,7 @@ ${helperFactorySource}
26835
26881
  console.debug(__mmt_formatSection('Request:', __reqLog));
26836
26882
  __mmt_reportNetwork('network-request', __req);
26837
26883
  try {
26838
- const __res = await __mmt_originalSend(req);
26884
+ const __res = await __mmt_originalSend(__req);
26839
26885
  // Stop before Response logging when the user cancelled mid-request.
26840
26886
  await checkAbort_();
26841
26887
  const __status = __res && typeof __res.status === 'number' ? __res.status : '';
@@ -26915,10 +26961,11 @@ ${helperFactorySource}
26915
26961
  if (__mmt_originalSendGrpc) {
26916
26962
  sendGrpc_ = async function(req) {
26917
26963
  await checkAbort_();
26918
- const __req = req || {};
26964
+ const __req = (typeof __mmt_requestOverride !== 'undefined' &&
26965
+ __mmt_requestOverride) ? __mmt_requestOverride : (req || {});
26919
26966
  __mmt_reportNetwork('network-request', __req);
26920
26967
  try {
26921
- const __res = await __mmt_originalSendGrpc(req);
26968
+ const __res = await __mmt_originalSendGrpc(__req);
26922
26969
  await checkAbort_();
26923
26970
  __mmt_reportNetwork('network-response', __req, __res);
26924
26971
  return __res;
@@ -28395,22 +28442,50 @@ function optionalTags(tags) {
28395
28442
  return out.length ? out : void 0;
28396
28443
  }
28397
28444
  async function buildSuiteHierarchyFromSuiteFile(params) {
28398
- const { suiteFilePath, suiteRawText, fileLoader, leafPrefix, projectRoot } = params;
28399
- const convertSuiteToHierarchy = async (targetFilePath, rawText, indexPath, ancestors) => {
28445
+ const { suiteFilePath, suiteRawText, fileLoader, leafPrefix, projectRoot, maxDepth } = params;
28446
+ const convertSuiteToHierarchy = async (targetFilePath, rawText, indexPath, ancestors, depth) => {
28400
28447
  const suiteDoc = yamlToSuite(rawText);
28448
+ const title = typeof suiteDoc.title === "string" && suiteDoc.title.trim() ? suiteDoc.title.trim() : void 0;
28449
+ const suiteTags = optionalTags(suiteDoc.tags);
28450
+ if (typeof maxDepth === "number" && depth >= maxDepth) {
28451
+ const stub = {
28452
+ kind: "suite",
28453
+ id: createSuiteNodeId(indexPath, { prefix: leafPrefix }),
28454
+ path: targetFilePath,
28455
+ title,
28456
+ children: []
28457
+ };
28458
+ if (Array.isArray(suiteDoc.servers) && suiteDoc.servers.length > 0) {
28459
+ stub.servers = suiteDoc.servers;
28460
+ }
28461
+ if (suiteDoc.environment) {
28462
+ stub.environment = suiteDoc.environment;
28463
+ }
28464
+ if (Array.isArray(suiteDoc.export) && suiteDoc.export.length > 0) {
28465
+ stub.export = suiteDoc.export;
28466
+ }
28467
+ if (suiteTags) {
28468
+ stub.tags = suiteTags;
28469
+ }
28470
+ if (suiteDoc.filter) {
28471
+ stub.filter = suiteDoc.filter;
28472
+ }
28473
+ return stub;
28474
+ }
28401
28475
  const nextAncestors = new Set(ancestors);
28402
28476
  nextAncestors.add(targetFilePath);
28403
28477
  const children = await buildNodesFromEntries(
28404
28478
  suiteDoc.items ?? [],
28405
28479
  targetFilePath,
28406
28480
  indexPath,
28407
- nextAncestors
28481
+ nextAncestors,
28482
+ depth
28408
28483
  );
28409
28484
  const node = {
28410
28485
  kind: "suite",
28411
28486
  id: createSuiteNodeId(indexPath, { prefix: leafPrefix }),
28412
28487
  path: targetFilePath,
28413
- title: typeof suiteDoc.title === "string" && suiteDoc.title.trim() ? suiteDoc.title.trim() : void 0,
28488
+ title,
28414
28489
  children
28415
28490
  };
28416
28491
  if (Array.isArray(suiteDoc.servers) && suiteDoc.servers.length > 0) {
@@ -28420,7 +28495,8 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28420
28495
  entry,
28421
28496
  targetFilePath,
28422
28497
  [...indexPath, -1, idx],
28423
- nextAncestors
28498
+ nextAncestors,
28499
+ depth
28424
28500
  )
28425
28501
  ))).filter((n) => !!n && (n.kind === "server" || n.kind === "missing"));
28426
28502
  if (serverItems.length > 0) {
@@ -28433,7 +28509,6 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28433
28509
  if (Array.isArray(suiteDoc.export) && suiteDoc.export.length > 0) {
28434
28510
  node.export = suiteDoc.export;
28435
28511
  }
28436
- const suiteTags = optionalTags(suiteDoc.tags);
28437
28512
  if (suiteTags) {
28438
28513
  node.tags = suiteTags;
28439
28514
  }
@@ -28442,7 +28517,7 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28442
28517
  }
28443
28518
  return node;
28444
28519
  };
28445
- const buildNodesFromEntries = async (entries, ownerFilePath, parentIndexPath, ancestors) => {
28520
+ const buildNodesFromEntries = async (entries, ownerFilePath, parentIndexPath, ancestors, parentDepth) => {
28446
28521
  const groups = splitSuiteGroups([...entries]);
28447
28522
  const groupNodes = await Promise.all(
28448
28523
  groups.map(async (g, gi) => {
@@ -28452,7 +28527,8 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28452
28527
  p,
28453
28528
  ownerFilePath,
28454
28529
  [...groupIndexPath, idx],
28455
- ancestors
28530
+ ancestors,
28531
+ parentDepth
28456
28532
  ))
28457
28533
  )).filter((n) => n !== null);
28458
28534
  if (!children.length) {
@@ -28468,7 +28544,30 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28468
28544
  );
28469
28545
  return groupNodes.filter((n) => n !== null);
28470
28546
  };
28471
- const buildNodeFromEntry = async (entry, ownerFilePath, indexPath, ancestors) => {
28547
+ const buildSuiteStub = (resolvedPath, raw, indexPath) => {
28548
+ let title;
28549
+ let tags;
28550
+ try {
28551
+ const suiteDoc = yamlToSuite(raw);
28552
+ if (typeof suiteDoc.title === "string" && suiteDoc.title.trim()) {
28553
+ title = suiteDoc.title.trim();
28554
+ }
28555
+ tags = optionalTags(suiteDoc.tags);
28556
+ } catch {
28557
+ }
28558
+ const stub = {
28559
+ kind: "suite",
28560
+ id: createSuiteNodeId(indexPath, { prefix: leafPrefix }),
28561
+ path: resolvedPath,
28562
+ title,
28563
+ children: []
28564
+ };
28565
+ if (tags) {
28566
+ stub.tags = tags;
28567
+ }
28568
+ return stub;
28569
+ };
28570
+ const buildNodeFromEntry = async (entry, ownerFilePath, indexPath, ancestors, parentDepth) => {
28472
28571
  const trimmed = String(entry ?? "").trim();
28473
28572
  if (!trimmed || trimmed === "then") {
28474
28573
  return null;
@@ -28555,9 +28654,18 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28555
28654
  if (ancestors.has(resolvedPath)) {
28556
28655
  return { kind: "cycle", id: createSuiteNodeId(indexPath, { prefix: leafPrefix }), path: resolvedPath };
28557
28656
  }
28558
- return convertSuiteToHierarchy(resolvedPath, raw, indexPath, ancestors);
28657
+ if (typeof maxDepth === "number" && parentDepth + 1 >= maxDepth) {
28658
+ return buildSuiteStub(resolvedPath, raw, indexPath);
28659
+ }
28660
+ return convertSuiteToHierarchy(
28661
+ resolvedPath,
28662
+ raw,
28663
+ indexPath,
28664
+ ancestors,
28665
+ parentDepth + 1
28666
+ );
28559
28667
  };
28560
- return convertSuiteToHierarchy(suiteFilePath, suiteRawText, [], /* @__PURE__ */ new Set());
28668
+ return convertSuiteToHierarchy(suiteFilePath, suiteRawText, [], /* @__PURE__ */ new Set(), 0);
28561
28669
  }
28562
28670
 
28563
28671
  // ../core/src/suiteBundle.ts
@@ -32242,6 +32350,7 @@ ${/(?:^|[^\w$.])(?:const|let|var)\s+envVariables\b/.test(code) ? "" : 'const env
32242
32350
  "__binaryFileLoader",
32243
32351
  "__checkLogMode",
32244
32352
  "__mmtEnvValues",
32353
+ "__mmt_requestOverride",
32245
32354
  functionBody
32246
32355
  );
32247
32356
  if (compiledFunctionCache.size >= MAX_COMPILED_FUNCTION_CACHE_SIZE) {
@@ -32328,7 +32437,8 @@ ${/(?:^|[^\w$.])(?:const|let|var)\s+envVariables\b/.test(code) ? "" : 'const env
32328
32437
  context.fileLoader,
32329
32438
  context.binaryFileLoader,
32330
32439
  context.checkLogMode || "default",
32331
- context.envValues
32440
+ context.envValues,
32441
+ context.requestOverride ?? null
32332
32442
  );
32333
32443
  restoreReporterGlobals();
32334
32444
  if (context.abortSignal?.aborted) {
@@ -32831,10 +32941,9 @@ function resolveGitCurrentSnapshot(cwd) {
32831
32941
  }
32832
32942
  return snapshot;
32833
32943
  }
32834
- function applyGitCurrentSnapshot(cwd) {
32835
- const snapshot = resolveGitCurrentSnapshot(cwd);
32836
- setGitCurrentSnapshot(snapshot);
32837
- return snapshot;
32944
+ function installGitCurrentSnapshotProvider(cwd) {
32945
+ clearGitCurrentSnapshot();
32946
+ setGitCurrentSnapshotProvider(() => resolveGitCurrentSnapshot(cwd));
32838
32947
  }
32839
32948
 
32840
32949
  // src/resources/documentation.ts
@@ -33252,7 +33361,9 @@ async function handleRun(args) {
33252
33361
  }
33253
33362
  };
33254
33363
  try {
33255
- applyGitCurrentSnapshot(args.workspaceRoot || import_path4.default.dirname(fullPath));
33364
+ installGitCurrentSnapshotProvider(
33365
+ args.workspaceRoot || import_path4.default.dirname(fullPath)
33366
+ );
33256
33367
  const result = await runner_exports.runFile({
33257
33368
  file: fullPath,
33258
33369
  filePath: fullPath,
package/dist/server.js CHANGED
@@ -11927,26 +11927,46 @@ function valueMatchesRandomToken(spec, actual) {
11927
11927
 
11928
11928
  // ../core/src/CurrentGit.ts
11929
11929
  var gitSnapshot;
11930
- function setGitCurrentSnapshot(snapshot) {
11931
- gitSnapshot = snapshot;
11930
+ var gitSnapshotLoaded = false;
11931
+ var gitSnapshotProvider;
11932
+ function setGitCurrentSnapshotProvider(provider) {
11933
+ gitSnapshotProvider = provider;
11934
+ }
11935
+ function clearGitCurrentSnapshot() {
11936
+ gitSnapshot = void 0;
11937
+ gitSnapshotLoaded = false;
11938
+ }
11939
+ function ensureGitCurrentSnapshot() {
11940
+ if (gitSnapshotLoaded) {
11941
+ return gitSnapshot;
11942
+ }
11943
+ gitSnapshotLoaded = true;
11944
+ if (gitSnapshotProvider) {
11945
+ try {
11946
+ gitSnapshot = gitSnapshotProvider() ?? void 0;
11947
+ } catch {
11948
+ gitSnapshot = void 0;
11949
+ }
11950
+ }
11951
+ return gitSnapshot;
11932
11952
  }
11933
11953
  function currentGitBranch() {
11934
- return gitSnapshot?.branch ?? "";
11954
+ return ensureGitCurrentSnapshot()?.branch ?? "";
11935
11955
  }
11936
11956
  function currentGitCommit() {
11937
- return gitSnapshot?.commit ?? "";
11957
+ return ensureGitCurrentSnapshot()?.commit ?? "";
11938
11958
  }
11939
11959
  function currentGitCommitHash() {
11940
- return gitSnapshot?.commitHash ?? "";
11960
+ return ensureGitCurrentSnapshot()?.commitHash ?? "";
11941
11961
  }
11942
11962
  function currentGitTag() {
11943
- return gitSnapshot?.tag ?? "";
11963
+ return ensureGitCurrentSnapshot()?.tag ?? "";
11944
11964
  }
11945
11965
  function currentGitDescribe() {
11946
- return gitSnapshot?.describe ?? "";
11966
+ return ensureGitCurrentSnapshot()?.describe ?? "";
11947
11967
  }
11948
11968
  function currentGitDirty() {
11949
- return gitSnapshot?.dirty === true;
11969
+ return ensureGitCurrentSnapshot()?.dirty === true;
11950
11970
  }
11951
11971
  function sanitizeReportPathSegment(raw) {
11952
11972
  const s = String(raw ?? "").trim().replace(/\\/g, "/").replace(/[\x00-\x1f\x7f]/g, "");
@@ -11959,7 +11979,8 @@ function sanitizeReportPathSegment(raw) {
11959
11979
  return s;
11960
11980
  }
11961
11981
  function currentReportFolder() {
11962
- const tagRaw = String(gitSnapshot?.tag ?? "").trim();
11982
+ const snap = ensureGitCurrentSnapshot();
11983
+ const tagRaw = String(snap?.tag ?? "").trim();
11963
11984
  if (tagRaw) {
11964
11985
  const firstTag = tagRaw.split(",")[0]?.trim() || "";
11965
11986
  const tagSeg = sanitizeReportPathSegment(firstTag);
@@ -11967,8 +11988,8 @@ function currentReportFolder() {
11967
11988
  return `tags/${tagSeg}`;
11968
11989
  }
11969
11990
  }
11970
- const commit = sanitizeReportPathSegment(String(gitSnapshot?.commit ?? "").trim());
11971
- const branchRaw = String(gitSnapshot?.branch ?? "").trim();
11991
+ const commit = sanitizeReportPathSegment(String(snap?.commit ?? "").trim());
11992
+ const branchRaw = String(snap?.branch ?? "").trim();
11972
11993
  if (branchRaw && commit) {
11973
11994
  const branchSeg = sanitizeReportPathSegment(branchRaw);
11974
11995
  if (branchSeg) {
@@ -16263,10 +16284,8 @@ var apiToJSfunc = async (ctx) => {
16263
16284
  }
16264
16285
  req_.body = __multipartBuilt_.body;
16265
16286
  ` : "";
16266
- const detailsRequestExpr = isBinaryRequest ? `{ ...req_, body: '<binary ' + __binaryBody_.length + ' bytes path=' + __binaryPath_ + '>' }` : isMultipartRequest ? `{ ...req_, body: '<multipart ' + req_.body.length + ' bytes>' }` : "req_";
16267
- return `const ${ctx.name} = async ({ ${inputParams} } = {}) => {
16268
- const __resolvedUrl = ${toTemplateWithEnvs(String(replaced.url || ""))};
16269
- ${binaryLoadLines}${multipartPrepLines} const req_ = {
16287
+ const detailsRequestExpr = isBinaryRequest ? `{ ...req_, body: '<binary ' + (req_.body && req_.body.length || 0) + ' bytes>' }` : isMultipartRequest ? `{ ...req_, body: '<multipart ' + (req_.body && req_.body.length || 0) + ' bytes>' }` : "req_";
16288
+ const builtReqLiteral = `{
16270
16289
  url: __resolvedUrl,
16271
16290
  protocol: ${protocolExpr},
16272
16291
  method: '${effectiveMethod}',
@@ -16274,11 +16293,30 @@ ${binaryLoadLines}${multipartPrepLines} const req_ = {
16274
16293
  query: ${queryParams ? "{ " + queryParams + " }" : "{}"},
16275
16294
  headers: ${headers ? "{ " + headers + " }" : "{}"},
16276
16295
  body: ${bodyExpr}
16277
- };
16296
+ }`;
16297
+ return `const ${ctx.name} = async ({ ${inputParams} } = {}) => {
16298
+ let req_;
16299
+ if (typeof __mmt_requestOverride !== 'undefined' && __mmt_requestOverride) {
16300
+ req_ = __mmt_requestOverride;
16301
+ ${isBinaryRequest ? ` if (typeof req_.body === 'string' && req_.body) {
16302
+ req_ = { ...req_, body: await readBinaryFile_(String(req_.body).trim()) };
16303
+ }
16304
+ ` : ""}${isMultipartRequest ? ` if (req_.body != null && typeof req_.body === 'object') {
16305
+ const __multipartBuilt_ = await buildMultipartBodyFromParts_(req_.body);
16306
+ if (!req_.headers) { req_.headers = {}; }
16307
+ if (!req_.headers["Content-Type"] || String(req_.headers["Content-Type"]).toLowerCase().indexOf("boundary=") < 0) {
16308
+ req_.headers["Content-Type"] = __multipartBuilt_.contentType;
16309
+ }
16310
+ req_ = { ...req_, body: __multipartBuilt_.body };
16311
+ }
16312
+ ` : ""} } else {
16313
+ const __resolvedUrl = ${toTemplateWithEnvs(String(replaced.url || ""))};
16314
+ ${binaryLoadLines}${multipartPrepLines} req_ = ${builtReqLiteral};
16315
+ ${declaredReqFormat === "auto" ? `const __reqFormat_ = resolveRequestFormat_('auto', req_.headers, req_.body);
16316
+ applyOmitToRequest_(req_, __reqFormat_);` : `applyOmitToRequest_(req_, '${declaredReqFormat}');`}
16317
+ ${multipartBuildLines ? multipartBuildLines.split("\n").map((l) => l ? " " + l : l).join("\n") : ""} }
16278
16318
  ${authCode}
16279
- ${declaredReqFormat === "auto" ? `const __reqFormat_ = resolveRequestFormat_('auto', req_.headers, req_.body);
16280
- applyOmitToRequest_(req_, __reqFormat_);` : `applyOmitToRequest_(req_, '${declaredReqFormat}');`}
16281
- ${multipartBuildLines} const res_ = await send_(req_);
16319
+ const res_ = await send_(req_);
16282
16320
 
16283
16321
  const __extractSource_ = {
16284
16322
  type: 'auto',
@@ -16351,26 +16389,33 @@ function generateGrpcFunction(ctx, replaced, inputParams, userExtractRules, toTp
16351
16389
  messageExpr = `{ ${msgParts} }`;
16352
16390
  }
16353
16391
  return `const ${ctx.name} = async ({ ${inputParams} } = {}) => {
16354
- const __resolvedUrl = ${toTpl(String(replaced.url || ""))};
16355
- const req_ = {
16356
- url: __resolvedUrl,
16357
- protocol: 'grpc',
16358
- method: 'grpc',
16359
- query: {},
16360
- headers: ${headers ? "{ " + headers + " }" : "{}"},
16361
- body: ${messageExpr}
16362
- };
16392
+ let req_;
16393
+ let __grpcReq;
16394
+ if (typeof __mmt_requestOverride !== 'undefined' && __mmt_requestOverride) {
16395
+ req_ = __mmt_requestOverride;
16396
+ __grpcReq = __mmt_requestOverride;
16397
+ } else {
16398
+ const __resolvedUrl = ${toTpl(String(replaced.url || ""))};
16399
+ req_ = {
16400
+ url: __resolvedUrl,
16401
+ protocol: 'grpc',
16402
+ method: 'grpc',
16403
+ query: {},
16404
+ headers: ${headers ? "{ " + headers + " }" : "{}"},
16405
+ body: ${messageExpr}
16406
+ };
16363
16407
  ${authCode}
16364
- const __grpcReq = {
16365
- url: __resolvedUrl,
16366
- proto: ${protoExpr},
16367
- service: ${serviceExpr},
16368
- method: ${methodExpr},
16369
- metadata: req_.headers,
16370
- message: ${messageExpr},
16371
- stream: ${streamExpr}
16372
- };
16373
- applyOmitToRequest_(__grpcReq);
16408
+ __grpcReq = {
16409
+ url: __resolvedUrl,
16410
+ proto: ${protoExpr},
16411
+ service: ${serviceExpr},
16412
+ method: ${methodExpr},
16413
+ metadata: req_.headers,
16414
+ message: ${messageExpr},
16415
+ stream: ${streamExpr}
16416
+ };
16417
+ applyOmitToRequest_(__grpcReq);
16418
+ }
16374
16419
  const __grpcRes = await sendGrpc_(__grpcReq);
16375
16420
 
16376
16421
  // Parse gRPC response message
@@ -16460,7 +16505,7 @@ function generateOAuth2JS(auth, toTpl) {
16460
16505
  const scopePart = auth.scope ? `
16461
16506
  scope: ${toTpl(auth.scope)},` : "";
16462
16507
  return ` if (!req_.headers["Authorization"]) {
16463
- const _tokenResp = await send_({
16508
+ const _tokenResp = await __mmt_originalSend({
16464
16509
  url: ${toTpl(auth.token_url)},
16465
16510
  method: "post",
16466
16511
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
@@ -26805,7 +26850,8 @@ ${helperFactorySource}
26805
26850
  const __mmt_originalSendGrpc = typeof sendGrpc_ === 'function' ? sendGrpc_ : null;
26806
26851
  send_ = async function(req) {
26807
26852
  await checkAbort_();
26808
- const __req = req || {};
26853
+ const __req = (typeof __mmt_requestOverride !== 'undefined' &&
26854
+ __mmt_requestOverride) ? __mmt_requestOverride : (req || {});
26809
26855
  const __maskedHeaders = {};
26810
26856
  for (const [k, v] of Object.entries(__req.headers || {})) {
26811
26857
  const lk = k.toLowerCase();
@@ -26835,7 +26881,7 @@ ${helperFactorySource}
26835
26881
  console.debug(__mmt_formatSection('Request:', __reqLog));
26836
26882
  __mmt_reportNetwork('network-request', __req);
26837
26883
  try {
26838
- const __res = await __mmt_originalSend(req);
26884
+ const __res = await __mmt_originalSend(__req);
26839
26885
  // Stop before Response logging when the user cancelled mid-request.
26840
26886
  await checkAbort_();
26841
26887
  const __status = __res && typeof __res.status === 'number' ? __res.status : '';
@@ -26915,10 +26961,11 @@ ${helperFactorySource}
26915
26961
  if (__mmt_originalSendGrpc) {
26916
26962
  sendGrpc_ = async function(req) {
26917
26963
  await checkAbort_();
26918
- const __req = req || {};
26964
+ const __req = (typeof __mmt_requestOverride !== 'undefined' &&
26965
+ __mmt_requestOverride) ? __mmt_requestOverride : (req || {});
26919
26966
  __mmt_reportNetwork('network-request', __req);
26920
26967
  try {
26921
- const __res = await __mmt_originalSendGrpc(req);
26968
+ const __res = await __mmt_originalSendGrpc(__req);
26922
26969
  await checkAbort_();
26923
26970
  __mmt_reportNetwork('network-response', __req, __res);
26924
26971
  return __res;
@@ -28395,22 +28442,50 @@ function optionalTags(tags) {
28395
28442
  return out.length ? out : void 0;
28396
28443
  }
28397
28444
  async function buildSuiteHierarchyFromSuiteFile(params) {
28398
- const { suiteFilePath, suiteRawText, fileLoader, leafPrefix, projectRoot } = params;
28399
- const convertSuiteToHierarchy = async (targetFilePath, rawText, indexPath, ancestors) => {
28445
+ const { suiteFilePath, suiteRawText, fileLoader, leafPrefix, projectRoot, maxDepth } = params;
28446
+ const convertSuiteToHierarchy = async (targetFilePath, rawText, indexPath, ancestors, depth) => {
28400
28447
  const suiteDoc = yamlToSuite(rawText);
28448
+ const title = typeof suiteDoc.title === "string" && suiteDoc.title.trim() ? suiteDoc.title.trim() : void 0;
28449
+ const suiteTags = optionalTags(suiteDoc.tags);
28450
+ if (typeof maxDepth === "number" && depth >= maxDepth) {
28451
+ const stub = {
28452
+ kind: "suite",
28453
+ id: createSuiteNodeId(indexPath, { prefix: leafPrefix }),
28454
+ path: targetFilePath,
28455
+ title,
28456
+ children: []
28457
+ };
28458
+ if (Array.isArray(suiteDoc.servers) && suiteDoc.servers.length > 0) {
28459
+ stub.servers = suiteDoc.servers;
28460
+ }
28461
+ if (suiteDoc.environment) {
28462
+ stub.environment = suiteDoc.environment;
28463
+ }
28464
+ if (Array.isArray(suiteDoc.export) && suiteDoc.export.length > 0) {
28465
+ stub.export = suiteDoc.export;
28466
+ }
28467
+ if (suiteTags) {
28468
+ stub.tags = suiteTags;
28469
+ }
28470
+ if (suiteDoc.filter) {
28471
+ stub.filter = suiteDoc.filter;
28472
+ }
28473
+ return stub;
28474
+ }
28401
28475
  const nextAncestors = new Set(ancestors);
28402
28476
  nextAncestors.add(targetFilePath);
28403
28477
  const children = await buildNodesFromEntries(
28404
28478
  suiteDoc.items ?? [],
28405
28479
  targetFilePath,
28406
28480
  indexPath,
28407
- nextAncestors
28481
+ nextAncestors,
28482
+ depth
28408
28483
  );
28409
28484
  const node = {
28410
28485
  kind: "suite",
28411
28486
  id: createSuiteNodeId(indexPath, { prefix: leafPrefix }),
28412
28487
  path: targetFilePath,
28413
- title: typeof suiteDoc.title === "string" && suiteDoc.title.trim() ? suiteDoc.title.trim() : void 0,
28488
+ title,
28414
28489
  children
28415
28490
  };
28416
28491
  if (Array.isArray(suiteDoc.servers) && suiteDoc.servers.length > 0) {
@@ -28420,7 +28495,8 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28420
28495
  entry,
28421
28496
  targetFilePath,
28422
28497
  [...indexPath, -1, idx],
28423
- nextAncestors
28498
+ nextAncestors,
28499
+ depth
28424
28500
  )
28425
28501
  ))).filter((n) => !!n && (n.kind === "server" || n.kind === "missing"));
28426
28502
  if (serverItems.length > 0) {
@@ -28433,7 +28509,6 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28433
28509
  if (Array.isArray(suiteDoc.export) && suiteDoc.export.length > 0) {
28434
28510
  node.export = suiteDoc.export;
28435
28511
  }
28436
- const suiteTags = optionalTags(suiteDoc.tags);
28437
28512
  if (suiteTags) {
28438
28513
  node.tags = suiteTags;
28439
28514
  }
@@ -28442,7 +28517,7 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28442
28517
  }
28443
28518
  return node;
28444
28519
  };
28445
- const buildNodesFromEntries = async (entries, ownerFilePath, parentIndexPath, ancestors) => {
28520
+ const buildNodesFromEntries = async (entries, ownerFilePath, parentIndexPath, ancestors, parentDepth) => {
28446
28521
  const groups = splitSuiteGroups([...entries]);
28447
28522
  const groupNodes = await Promise.all(
28448
28523
  groups.map(async (g, gi) => {
@@ -28452,7 +28527,8 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28452
28527
  p,
28453
28528
  ownerFilePath,
28454
28529
  [...groupIndexPath, idx],
28455
- ancestors
28530
+ ancestors,
28531
+ parentDepth
28456
28532
  ))
28457
28533
  )).filter((n) => n !== null);
28458
28534
  if (!children.length) {
@@ -28468,7 +28544,30 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28468
28544
  );
28469
28545
  return groupNodes.filter((n) => n !== null);
28470
28546
  };
28471
- const buildNodeFromEntry = async (entry, ownerFilePath, indexPath, ancestors) => {
28547
+ const buildSuiteStub = (resolvedPath, raw, indexPath) => {
28548
+ let title;
28549
+ let tags;
28550
+ try {
28551
+ const suiteDoc = yamlToSuite(raw);
28552
+ if (typeof suiteDoc.title === "string" && suiteDoc.title.trim()) {
28553
+ title = suiteDoc.title.trim();
28554
+ }
28555
+ tags = optionalTags(suiteDoc.tags);
28556
+ } catch {
28557
+ }
28558
+ const stub = {
28559
+ kind: "suite",
28560
+ id: createSuiteNodeId(indexPath, { prefix: leafPrefix }),
28561
+ path: resolvedPath,
28562
+ title,
28563
+ children: []
28564
+ };
28565
+ if (tags) {
28566
+ stub.tags = tags;
28567
+ }
28568
+ return stub;
28569
+ };
28570
+ const buildNodeFromEntry = async (entry, ownerFilePath, indexPath, ancestors, parentDepth) => {
28472
28571
  const trimmed = String(entry ?? "").trim();
28473
28572
  if (!trimmed || trimmed === "then") {
28474
28573
  return null;
@@ -28555,9 +28654,18 @@ async function buildSuiteHierarchyFromSuiteFile(params) {
28555
28654
  if (ancestors.has(resolvedPath)) {
28556
28655
  return { kind: "cycle", id: createSuiteNodeId(indexPath, { prefix: leafPrefix }), path: resolvedPath };
28557
28656
  }
28558
- return convertSuiteToHierarchy(resolvedPath, raw, indexPath, ancestors);
28657
+ if (typeof maxDepth === "number" && parentDepth + 1 >= maxDepth) {
28658
+ return buildSuiteStub(resolvedPath, raw, indexPath);
28659
+ }
28660
+ return convertSuiteToHierarchy(
28661
+ resolvedPath,
28662
+ raw,
28663
+ indexPath,
28664
+ ancestors,
28665
+ parentDepth + 1
28666
+ );
28559
28667
  };
28560
- return convertSuiteToHierarchy(suiteFilePath, suiteRawText, [], /* @__PURE__ */ new Set());
28668
+ return convertSuiteToHierarchy(suiteFilePath, suiteRawText, [], /* @__PURE__ */ new Set(), 0);
28561
28669
  }
28562
28670
 
28563
28671
  // ../core/src/suiteBundle.ts
@@ -32242,6 +32350,7 @@ ${/(?:^|[^\w$.])(?:const|let|var)\s+envVariables\b/.test(code) ? "" : 'const env
32242
32350
  "__binaryFileLoader",
32243
32351
  "__checkLogMode",
32244
32352
  "__mmtEnvValues",
32353
+ "__mmt_requestOverride",
32245
32354
  functionBody
32246
32355
  );
32247
32356
  if (compiledFunctionCache.size >= MAX_COMPILED_FUNCTION_CACHE_SIZE) {
@@ -32328,7 +32437,8 @@ ${/(?:^|[^\w$.])(?:const|let|var)\s+envVariables\b/.test(code) ? "" : 'const env
32328
32437
  context.fileLoader,
32329
32438
  context.binaryFileLoader,
32330
32439
  context.checkLogMode || "default",
32331
- context.envValues
32440
+ context.envValues,
32441
+ context.requestOverride ?? null
32332
32442
  );
32333
32443
  restoreReporterGlobals();
32334
32444
  if (context.abortSignal?.aborted) {
@@ -32831,10 +32941,9 @@ function resolveGitCurrentSnapshot(cwd) {
32831
32941
  }
32832
32942
  return snapshot;
32833
32943
  }
32834
- function applyGitCurrentSnapshot(cwd) {
32835
- const snapshot = resolveGitCurrentSnapshot(cwd);
32836
- setGitCurrentSnapshot(snapshot);
32837
- return snapshot;
32944
+ function installGitCurrentSnapshotProvider(cwd) {
32945
+ clearGitCurrentSnapshot();
32946
+ setGitCurrentSnapshotProvider(() => resolveGitCurrentSnapshot(cwd));
32838
32947
  }
32839
32948
 
32840
32949
  // src/resources/documentation.ts
@@ -33252,7 +33361,9 @@ async function handleRun(args) {
33252
33361
  }
33253
33362
  };
33254
33363
  try {
33255
- applyGitCurrentSnapshot(args.workspaceRoot || import_path4.default.dirname(fullPath));
33364
+ installGitCurrentSnapshotProvider(
33365
+ args.workspaceRoot || import_path4.default.dirname(fullPath)
33366
+ );
33256
33367
  const result = await runner_exports.runFile({
33257
33368
  file: fullPath,
33258
33369
  filePath: fullPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mmt-mcp",
3
- "version": "1.46.0-pre",
3
+ "version": "1.46.2-pre",
4
4
  "description": "Multimeter MCP server for Cursor, Copilot, and Claude. Scaffold, validate, format, and run YAML .mmt API tests. Do not invent .mmt syntax.",
5
5
  "mcpName": "io.github.mshobeyri/multimeter",
6
6
  "type": "module",
@@ -1,3 +0,0 @@
1
- type: env
2
- title: Report Generation Example
3
- description: Project root marker so report exports use +/ paths