@agentistics/mcp 2.135.1 → 2.136.1

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.
@@ -1028,7 +1028,7 @@ var AGENT_TOOL_POLICY = {
1028
1028
  reason: "reads or switches away mode (what newly started sessions are told about the owner being out) and lets a leader raise a notice in the owner's bell; reversible by switching it off; the server accepts writes only from a verified LEADER session"
1029
1029
  },
1030
1030
  agentistics_summary: { ...DATA, capability: "localTranscripts", host: true, risk: "R", routes: ["GET /api/data", "GET /api/runtime/metrics"], reason: "reads computed metrics" },
1031
- agentistics_harnesses: { ...DATA, capability: "localTranscripts", host: true, risk: "R", routes: ["GET /api/data", "GET /api/runtime/metrics"], reason: "reads computed metrics per harness" },
1031
+ agentistics_harnesses: { ...DATA, capability: "localTranscripts", host: true, risk: "R", routes: ["GET /api/data", "GET /api/runtime/metrics", "GET /api/plan-limits"], reason: "reads computed metrics per harness and whether each can be spawned" },
1032
1032
  agentistics_plan_limits: { ...DATA, capability: "localTranscripts", host: true, risk: "R", routes: ["GET /api/plan-limits"], reason: "reads subscription windows and routing guidance; does not start work" },
1033
1033
  agentistics_projects: { ...DATA, capability: "localTranscripts", host: true, risk: "R", routes: ["GET /api/data", "GET /api/runtime/metrics"], reason: "reads computed metrics per project" },
1034
1034
  agentistics_sessions: { ...DATA, capability: "localShell", host: true, risk: "R", routes: ["GET /api/data", "GET /api/fleet"], reason: "reads session metadata (first_prompt is untrusted text, §4.8)" },
@@ -1071,7 +1071,7 @@ var ROUTE_PREFERENCES = {
1071
1071
  };
1072
1072
  function routeRecommendation(budgets, kind, authorHarness) {
1073
1073
  const allowTight = kind === "lead";
1074
- const eligible = budgets.filter((b) => b.plan !== "unregistered" && b.status !== "hold" && (allowTight || b.status !== "tight") && b.harness !== (kind === "qa" ? authorHarness : undefined));
1074
+ const eligible = budgets.filter((b) => b.spawnable !== false && b.plan !== "unregistered" && b.status !== "hold" && (allowTight || b.status !== "tight") && b.harness !== (kind === "qa" ? authorHarness : undefined));
1075
1075
  const ordered = [...eligible].sort((a, b) => {
1076
1076
  const ap = a.paceStatus === "under" ? 0 : 1;
1077
1077
  const bp = b.paceStatus === "under" ? 0 : 1;
@@ -1085,6 +1085,9 @@ function routeRecommendation(budgets, kind, authorHarness) {
1085
1085
  const chosen = ordered.find((b) => preference.some(([h]) => h === b.harness));
1086
1086
  const pick = chosen ?? ordered[0];
1087
1087
  if (!pick) {
1088
+ if (budgets.length && budgets.every((b) => b.spawnable === false)) {
1089
+ return { harness: null, reason: "No harness can start a new session.", alternatives: [], cadence: { parallel: 0, note: "Install or repair a harness before opening workers." } };
1090
+ }
1088
1091
  const earliest = budgets.filter((b) => b.status === "hold").sort((a, b) => a.weekResetsAt - b.weekResetsAt)[0];
1089
1092
  const reset = earliest ? new Date(earliest.weekResetsAt).toISOString() : "the next reset";
1090
1093
  return { harness: null, reason: `all plans on hold until ${reset}`, alternatives: [], cadence: { parallel: 0, note: "Wait for a plan to renew." } };
@@ -1493,6 +1496,7 @@ function planLimitsTool(args, body) {
1493
1496
  const recommendation = args?.kind ? routeRecommendation(budgets, args.kind, args.authorHarness) : undefined;
1494
1497
  return {
1495
1498
  budgets,
1499
+ harnesses: body.harnesses ?? {},
1496
1500
  freeSlots: body.freeSlots ?? (budgets.length ? Math.max(...budgets.map((b) => b.freeSlots ?? 0)) : 0),
1497
1501
  freeSlotsByHarness: body.freeSlotsByHarness ?? Object.fromEntries(budgets.map((b) => [b.harness, b.freeSlots ?? 0])),
1498
1502
  liveSessions: body.liveSessions ?? budgets.flatMap((b) => b.liveSessions ?? []).filter((s, i, all) => all.findIndex((x) => x.id === s.id) === i),
@@ -1502,6 +1506,13 @@ function planLimitsTool(args, body) {
1502
1506
  };
1503
1507
  }
1504
1508
 
1509
+ // harnesses-tool.ts
1510
+ function harnessesTool(rows, body) {
1511
+ if (!Array.isArray(rows))
1512
+ return rows;
1513
+ return rows.map((row) => ({ ...row, ...body.harnesses?.[row.harness] }));
1514
+ }
1515
+
1505
1516
  // legacy-analytics.ts
1506
1517
  function legacySummary(data, harness) {
1507
1518
  const unified = !harness || harness === "all";
@@ -2856,10 +2867,11 @@ async function callTool(req) {
2856
2867
  }));
2857
2868
  }
2858
2869
  case "agentistics_harnesses": {
2859
- return text(await analytics("agentistics_harnesses", undefined, {
2870
+ const [rows, availability] = await Promise.all([analytics("agentistics_harnesses", undefined, {
2860
2871
  legacy: () => apiGet("/api/data"),
2861
2872
  metrics: (q) => fetch(`${API}/api/runtime/metrics?${q}`)
2862
- }));
2873
+ }), apiGet("/api/plan-limits")]);
2874
+ return text(harnessesTool(rows, availability));
2863
2875
  }
2864
2876
  case "agentistics_plan_limits": {
2865
2877
  return text(planLimitsTool(args ?? {}, await apiGet("/api/plan-limits")));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentistics/mcp",
3
- "version": "2.135.1",
3
+ "version": "2.136.1",
4
4
  "description": "Agentistics MCP server — Claude Code analytics for Claude Desktop and Claude Code",
5
5
  "type": "module",
6
6
  "main": "./dist/agentistics-mcp.js",