mcp-squared 0.3.4 → 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.
@@ -123,6 +123,274 @@ function ensureConfigDir(configPath) {
123
123
  var SOCKET_FILENAME = "mcp-squared.sock", INSTANCE_DIR_NAME = "instances", SOCKET_DIR_NAME = "sockets", DAEMON_DIR_NAME = "daemon", DAEMON_REGISTRY_FILENAME = "daemon.json", DAEMON_SOCKET_FILENAME = "daemon.sock", CONFIG_FILENAME = "mcp-squared.toml", CONFIG_DIR_NAME = ".mcp-squared", APP_NAME = "mcp-squared";
124
124
  var init_paths = () => {};
125
125
 
126
+ // src/capabilities/inference.ts
127
+ function createEmptyScores() {
128
+ return CAPABILITY_IDS.reduce((acc, capability) => {
129
+ acc[capability] = 0;
130
+ return acc;
131
+ }, {});
132
+ }
133
+ function extractSchemaSignal(schema) {
134
+ if (!schema || schema.type !== "object") {
135
+ return "";
136
+ }
137
+ const keys = Object.keys(schema.properties ?? {});
138
+ const required = schema.required ?? [];
139
+ return `${keys.join(" ")} ${required.join(" ")}`;
140
+ }
141
+ function scoreTextSignals(scores, text) {
142
+ for (const capability of CAPABILITY_IDS) {
143
+ for (const pattern of CAPABILITY_PATTERNS[capability]) {
144
+ if (pattern.test(text)) {
145
+ scores[capability] += 4;
146
+ }
147
+ }
148
+ }
149
+ }
150
+ function getHighestScoringCapability(scores) {
151
+ const bestScore = Math.max(...Object.values(scores));
152
+ if (bestScore <= 0) {
153
+ return "general";
154
+ }
155
+ for (const capability of CAPABILITY_PRIORITY) {
156
+ if (scores[capability] === bestScore) {
157
+ return capability;
158
+ }
159
+ }
160
+ return "general";
161
+ }
162
+ function inferNamespaceCapability(namespace, tools, capabilityOverrides = {}) {
163
+ const override = capabilityOverrides[namespace];
164
+ if (override) {
165
+ return override;
166
+ }
167
+ const scores = createEmptyScores();
168
+ const namespaceText = namespace.toLowerCase();
169
+ for (const hint of NAMESPACE_HINTS) {
170
+ if (hint.pattern.test(namespaceText)) {
171
+ scores[hint.capability] += hint.score;
172
+ }
173
+ }
174
+ for (const tool of tools) {
175
+ const signal = [
176
+ tool.name,
177
+ tool.description ?? "",
178
+ extractSchemaSignal(tool.inputSchema)
179
+ ].join(" ").toLowerCase();
180
+ scoreTextSignals(scores, signal);
181
+ }
182
+ return getHighestScoringCapability(scores);
183
+ }
184
+ function groupNamespacesByCapability(inventories, capabilityOverrides = {}) {
185
+ const grouped = CAPABILITY_IDS.reduce((acc, capability) => {
186
+ acc[capability] = [];
187
+ return acc;
188
+ }, {});
189
+ const byNamespace = {};
190
+ const sorted = [...inventories].sort((a, b) => a.namespace.localeCompare(b.namespace));
191
+ for (const inventory of sorted) {
192
+ const capability = inferNamespaceCapability(inventory.namespace, inventory.tools, capabilityOverrides);
193
+ byNamespace[inventory.namespace] = capability;
194
+ grouped[capability].push(inventory.namespace);
195
+ }
196
+ return { byNamespace, grouped };
197
+ }
198
+ var CAPABILITY_IDS, CAPABILITY_PRIORITY, NAMESPACE_HINTS, CAPABILITY_PATTERNS;
199
+ var init_inference = __esm(() => {
200
+ CAPABILITY_IDS = [
201
+ "code_search",
202
+ "docs",
203
+ "browser_automation",
204
+ "issue_tracking",
205
+ "cms_content",
206
+ "design",
207
+ "ai_media_generation",
208
+ "hosting_deploy",
209
+ "time_util",
210
+ "research",
211
+ "general"
212
+ ];
213
+ CAPABILITY_PRIORITY = [
214
+ "code_search",
215
+ "docs",
216
+ "browser_automation",
217
+ "issue_tracking",
218
+ "cms_content",
219
+ "design",
220
+ "ai_media_generation",
221
+ "hosting_deploy",
222
+ "time_util",
223
+ "research",
224
+ "general"
225
+ ];
226
+ NAMESPACE_HINTS = [
227
+ {
228
+ capability: "code_search",
229
+ pattern: /(auggie|augment|ctxdb|code|source|repo|symbol|search)/i,
230
+ score: 24
231
+ },
232
+ {
233
+ capability: "docs",
234
+ pattern: /(context7|ref|docs?|documentation|shadcn)/i,
235
+ score: 18
236
+ },
237
+ {
238
+ capability: "browser_automation",
239
+ pattern: /(chrome|devtools|browser|playwright|puppeteer|webdriver)/i,
240
+ score: 24
241
+ },
242
+ {
243
+ capability: "issue_tracking",
244
+ pattern: /(linear|jira|issue|ticket|project|milestone)/i,
245
+ score: 20
246
+ },
247
+ {
248
+ capability: "cms_content",
249
+ pattern: /(sanity|content|cms|dataset|schema|studio)/i,
250
+ score: 20
251
+ },
252
+ {
253
+ capability: "design",
254
+ pattern: /(pencil|figma|ui|design|artifact|visual)/i,
255
+ score: 20
256
+ },
257
+ {
258
+ capability: "hosting_deploy",
259
+ pattern: /(vercel|host|hosting|domain|dns|vps|deploy|infra)/i,
260
+ score: 22
261
+ },
262
+ {
263
+ capability: "time_util",
264
+ pattern: /(time|timezone|clock|date|utc)/i,
265
+ score: 22
266
+ },
267
+ {
268
+ capability: "ai_media_generation",
269
+ pattern: /(wavespeed|stability|replicate|midjourney|dall.?e|runway|imagen|flux|fal\.ai|dreamstudio)/i,
270
+ score: 24
271
+ },
272
+ {
273
+ capability: "research",
274
+ pattern: /(exa|perplexity|firecrawl|crawl|scrape|research|search)/i,
275
+ score: 16
276
+ }
277
+ ];
278
+ CAPABILITY_PATTERNS = {
279
+ code_search: [
280
+ /\bcodebase\b/i,
281
+ /\bsource\b/i,
282
+ /\brepo(?:sitory)?\b/i,
283
+ /\bsymbol(?:s)?\b/i,
284
+ /\bdefinition(?:s)?\b/i,
285
+ /\breference(?:s)?\b/i,
286
+ /\busage(?:s)?\b/i,
287
+ /\bsearch_context\b/i,
288
+ /\bcodebase-retrieval\b/i,
289
+ /\bdirectory_path\b/i
290
+ ],
291
+ docs: [
292
+ /\bdoc(?:s|umentation)?\b/i,
293
+ /\bread_docs\b/i,
294
+ /\bquery-docs\b/i,
295
+ /\breference\b/i,
296
+ /\bmanual\b/i,
297
+ /\bknowledge\b/i,
298
+ /\bregist(?:ry|ries)\b/i,
299
+ /\bcomponent(?:s)?\b/i,
300
+ /\bexample(?:s)?\b/i
301
+ ],
302
+ browser_automation: [
303
+ /\bbrowser\b/i,
304
+ /\bdevtools\b/i,
305
+ /\bnavigate\b/i,
306
+ /\bclick\b/i,
307
+ /\bhover\b/i,
308
+ /\bnetwork\b/i,
309
+ /\bconsole\b/i,
310
+ /\bscreenshot\b/i,
311
+ /\bpage\b/i
312
+ ],
313
+ issue_tracking: [
314
+ /\bissue(?:s)?\b/i,
315
+ /\bticket(?:s)?\b/i,
316
+ /\bmilestone(?:s)?\b/i,
317
+ /\bcycle(?:s)?\b/i,
318
+ /\bproject(?:s)?\b/i,
319
+ /\bcomment(?:s)?\b/i,
320
+ /\blinear\b/i
321
+ ],
322
+ cms_content: [
323
+ /\bcms\b/i,
324
+ /\bcontent\b/i,
325
+ /\bdocument(?:s)?\b/i,
326
+ /\bdataset(?:s)?\b/i,
327
+ /\bschema\b/i,
328
+ /\bpublish\b/i,
329
+ /\bdraft(?:s)?\b/i,
330
+ /\bsanity\b/i,
331
+ /\bmigration\b/i
332
+ ],
333
+ design: [
334
+ /\bdesign\b/i,
335
+ /\bui\b/i,
336
+ /\bartifact\b/i,
337
+ /\bstyle_guide\b/i,
338
+ /\bscreenshot\b/i,
339
+ /\bdiagram\b/i,
340
+ /\bimage\b/i,
341
+ /\blayout\b/i,
342
+ /\bframe\b/i
343
+ ],
344
+ ai_media_generation: [
345
+ /\btext.to.image\b/i,
346
+ /\bimage.to.image\b/i,
347
+ /\btext.to.video\b/i,
348
+ /\binpaint(?:ing)?\b/i,
349
+ /\bupscal(?:e|ing)\b/i,
350
+ /\bgenerat(?:e|ion)\b.*\bimage/i,
351
+ /\bimage\b.*\bgenerat(?:e|ion)\b/i,
352
+ /\bai\b.*\b(?:image|photo|video)\b/i,
353
+ /\bstable.diffusion\b/i,
354
+ /\bdiffusion\b/i,
355
+ /\bprompt\b.*\b(?:image|visual)\b/i
356
+ ],
357
+ hosting_deploy: [
358
+ /\bdeploy(?:ment)?\b/i,
359
+ /\bhosting\b/i,
360
+ /\bdomain(?:s)?\b/i,
361
+ /\bdns\b/i,
362
+ /\bvps\b/i,
363
+ /\bvirtual_machine(?:s)?\b/i,
364
+ /\bfirewall\b/i,
365
+ /\bwebsite\b/i,
366
+ /\bbilling\b/i,
367
+ /\bnameserver(?:s)?\b/i
368
+ ],
369
+ time_util: [
370
+ /\btime\b/i,
371
+ /\btimezone\b/i,
372
+ /\butc\b/i,
373
+ /\bclock\b/i,
374
+ /\bdate\b/i,
375
+ /\bconvert_time\b/i,
376
+ /\bget_current_time\b/i
377
+ ],
378
+ research: [
379
+ /\bresearch\b/i,
380
+ /\bcrawl\b/i,
381
+ /\bscrape\b/i,
382
+ /\bextract\b/i,
383
+ /\bsemantic_search\b/i,
384
+ /\bweb_search\b/i,
385
+ /\bask\b/i,
386
+ /\bperplexity\b/i,
387
+ /\bfirecrawl\b/i,
388
+ /\bexa\b/i
389
+ ],
390
+ general: []
391
+ };
392
+ });
393
+
126
394
  // src/tui/config.ts
127
395
  import {
128
396
  ASCIIFontRenderable,
@@ -378,6 +646,7 @@ import { parse as parseToml } from "smol-toml";
378
646
  import { ZodError } from "zod";
379
647
 
380
648
  // src/config/schema.ts
649
+ init_inference();
381
650
  import { z } from "zod";
382
651
  var LATEST_SCHEMA_VERSION = 1;
383
652
  var LogLevelSchema = z.enum([
@@ -434,11 +703,29 @@ var SecuritySchema = z.object({
434
703
  });
435
704
  var SearchModeSchema = z.enum(["fast", "semantic", "hybrid"]);
436
705
  var DetailLevelSchema = z.enum(["L0", "L1", "L2"]);
706
+ var CapabilityIdSchema = z.enum(CAPABILITY_IDS);
707
+ var DynamicToolSurfaceInferenceSchema = z.enum([
708
+ "heuristic_with_overrides",
709
+ "hybrid"
710
+ ]);
711
+ var DynamicToolSurfaceRefreshSchema = z.enum(["on_connect"]);
712
+ var DynamicToolSurfaceSchema = z.object({
713
+ inference: DynamicToolSurfaceInferenceSchema.default("heuristic_with_overrides"),
714
+ refresh: DynamicToolSurfaceRefreshSchema.default("on_connect"),
715
+ capabilityOverrides: z.record(z.string().min(1), CapabilityIdSchema).default({}),
716
+ semanticConfidenceThreshold: z.number().min(0).max(1).default(0.45)
717
+ });
718
+ var PreferredNamespacesByIntentSchema = z.object({
719
+ codeSearch: z.array(z.string().min(1)).default([])
720
+ });
437
721
  var FindToolsSchema = z.object({
438
722
  defaultLimit: z.number().int().min(1).default(5),
439
723
  maxLimit: z.number().int().min(1).max(200).default(50),
440
724
  defaultMode: SearchModeSchema.default("fast"),
441
- defaultDetailLevel: DetailLevelSchema.default("L1")
725
+ defaultDetailLevel: DetailLevelSchema.default("L1"),
726
+ preferredNamespacesByIntent: PreferredNamespacesByIntentSchema.default({
727
+ codeSearch: []
728
+ })
442
729
  });
443
730
  var IndexSchema = z.object({
444
731
  refreshIntervalMs: z.number().int().min(1000).default(30000)
@@ -459,7 +746,8 @@ var OperationsSchema = z.object({
459
746
  defaultLimit: 5,
460
747
  maxLimit: 50,
461
748
  defaultMode: "fast",
462
- defaultDetailLevel: "L1"
749
+ defaultDetailLevel: "L1",
750
+ preferredNamespacesByIntent: { codeSearch: [] }
463
751
  }),
464
752
  index: IndexSchema.default({ refreshIntervalMs: 30000 }),
465
753
  logging: LoggingSchema.default({ level: "info" }),
@@ -468,13 +756,20 @@ var OperationsSchema = z.object({
468
756
  enabled: true,
469
757
  minCooccurrenceThreshold: 2,
470
758
  maxBundleSuggestions: 3
759
+ }),
760
+ dynamicToolSurface: DynamicToolSurfaceSchema.default({
761
+ inference: "heuristic_with_overrides",
762
+ refresh: "on_connect",
763
+ capabilityOverrides: {},
764
+ semanticConfidenceThreshold: 0.45
471
765
  })
472
766
  }).default({
473
767
  findTools: {
474
768
  defaultLimit: 5,
475
769
  maxLimit: 50,
476
770
  defaultMode: "fast",
477
- defaultDetailLevel: "L1"
771
+ defaultDetailLevel: "L1",
772
+ preferredNamespacesByIntent: { codeSearch: [] }
478
773
  },
479
774
  index: { refreshIntervalMs: 30000 },
480
775
  logging: { level: "info" },
@@ -483,6 +778,12 @@ var OperationsSchema = z.object({
483
778
  enabled: true,
484
779
  minCooccurrenceThreshold: 2,
485
780
  maxBundleSuggestions: 3
781
+ },
782
+ dynamicToolSurface: {
783
+ inference: "heuristic_with_overrides",
784
+ refresh: "on_connect",
785
+ capabilityOverrides: {},
786
+ semanticConfidenceThreshold: 0.45
486
787
  }
487
788
  });
488
789
  var ConfigSchema = z.object({
@@ -536,6 +837,34 @@ function migrateV0ToV1(config) {
536
837
 
537
838
  // src/config/load.ts
538
839
  init_paths();
840
+ function isRecord(value) {
841
+ return typeof value === "object" && value !== null;
842
+ }
843
+ function getDeprecatedDynamicToolSurfaceKeys(raw) {
844
+ const operations = raw["operations"];
845
+ if (!isRecord(operations)) {
846
+ return [];
847
+ }
848
+ const dynamicToolSurface = operations["dynamicToolSurface"];
849
+ if (!isRecord(dynamicToolSurface)) {
850
+ return [];
851
+ }
852
+ const deprecated = [];
853
+ if ("mode" in dynamicToolSurface) {
854
+ deprecated.push("operations.dynamicToolSurface.mode");
855
+ }
856
+ if ("naming" in dynamicToolSurface) {
857
+ deprecated.push("operations.dynamicToolSurface.naming");
858
+ }
859
+ return deprecated;
860
+ }
861
+ function warnDeprecatedDynamicToolSurfaceKeys(filePath, keys) {
862
+ if (keys.length === 0) {
863
+ return;
864
+ }
865
+ console.warn(`[mcp\xB2] Deprecated config keys in ${filePath}: ${keys.join(", ")}. Run 'mcp-squared migrate' to clean up legacy settings.`);
866
+ }
867
+
539
868
  class ConfigError extends Error {
540
869
  cause;
541
870
  constructor(message, cause) {
@@ -603,6 +932,7 @@ async function loadConfigFromPath(filePath, source) {
603
932
  } catch (err) {
604
933
  throw new ConfigParseError(filePath, err);
605
934
  }
935
+ warnDeprecatedDynamicToolSurfaceKeys(filePath, getDeprecatedDynamicToolSurfaceKeys(rawConfig));
606
936
  const migrated = migrateConfig(rawConfig);
607
937
  let config;
608
938
  try {
@@ -1465,60 +1795,68 @@ function cleanupExpiredTokens() {
1465
1795
  }
1466
1796
  }
1467
1797
  }
1468
- function validateConfirmationToken(token, serverKey, toolName) {
1798
+ function validateConfirmationToken(token, capability, action) {
1469
1799
  cleanupExpiredTokens();
1470
1800
  const confirmation = pendingConfirmations.get(token);
1471
1801
  if (!confirmation) {
1472
1802
  return false;
1473
1803
  }
1474
- if (confirmation.serverKey !== serverKey || confirmation.toolName !== toolName) {
1804
+ if (confirmation.capability !== capability || confirmation.action !== action) {
1475
1805
  return false;
1476
1806
  }
1477
1807
  pendingConfirmations.delete(token);
1478
1808
  return true;
1479
1809
  }
1480
- function createConfirmationToken(serverKey, toolName) {
1810
+ function createConfirmationToken(capability, action) {
1481
1811
  cleanupExpiredTokens();
1482
1812
  const token = generateToken();
1483
1813
  pendingConfirmations.set(token, {
1484
- serverKey,
1485
- toolName,
1814
+ capability,
1815
+ action,
1486
1816
  createdAt: Date.now()
1487
1817
  });
1488
1818
  return token;
1489
1819
  }
1490
1820
  function evaluatePolicy(context, config) {
1491
- const { serverKey, toolName, confirmationToken } = context;
1821
+ const capability = context.capability ?? context.serverKey;
1822
+ const action = context.action ?? context.toolName;
1823
+ const confirmationToken = context.confirmationToken;
1492
1824
  const { block, confirm, allow } = config.security.tools;
1493
- if (matchesAnyPattern(block, serverKey, toolName)) {
1825
+ if (!capability || !action) {
1494
1826
  return {
1495
1827
  decision: "block",
1496
- reason: `Tool "${toolName}" on server "${serverKey}" is blocked by security policy`
1828
+ reason: "Missing capability/action in security policy context"
1497
1829
  };
1498
1830
  }
1499
- if (matchesAnyPattern(allow, serverKey, toolName)) {
1831
+ if (matchesAnyPattern(block, capability, action)) {
1832
+ return {
1833
+ decision: "block",
1834
+ reason: `Action "${action}" in capability "${capability}" is blocked by security policy`
1835
+ };
1836
+ }
1837
+ if (matchesAnyPattern(allow, capability, action)) {
1500
1838
  return {
1501
1839
  decision: "allow",
1502
- reason: `Tool "${toolName}" is allowed by security policy`
1840
+ reason: `Action "${action}" is allowed by security policy`
1503
1841
  };
1504
1842
  }
1505
- if (matchesAnyPattern(confirm, serverKey, toolName)) {
1506
- if (confirmationToken && validateConfirmationToken(confirmationToken, serverKey, toolName)) {
1843
+ if (matchesAnyPattern(confirm, capability, action)) {
1844
+ if (confirmationToken && validateConfirmationToken(confirmationToken, capability, action)) {
1507
1845
  return {
1508
1846
  decision: "allow",
1509
- reason: `Tool "${toolName}" confirmed with valid token`
1847
+ reason: `Action "${action}" confirmed with valid token`
1510
1848
  };
1511
1849
  }
1512
- const token = createConfirmationToken(serverKey, toolName);
1850
+ const token = createConfirmationToken(capability, action);
1513
1851
  return {
1514
1852
  decision: "confirm",
1515
- reason: `Tool "${toolName}" on server "${serverKey}" requires confirmation`,
1853
+ reason: `Action "${action}" in capability "${capability}" requires confirmation`,
1516
1854
  confirmationToken: token
1517
1855
  };
1518
1856
  }
1519
1857
  return {
1520
1858
  decision: "block",
1521
- reason: `Tool "${toolName}" on server "${serverKey}" is not in the allow or confirm list`
1859
+ reason: `Action "${action}" in capability "${capability}" is not in the allow or confirm list`
1522
1860
  };
1523
1861
  }
1524
1862
  function compilePolicy(config) {
@@ -1677,6 +2015,26 @@ async function waitForProcessExit(proc, timeoutMs) {
1677
2015
  }
1678
2016
 
1679
2017
  // src/upstream/cataloger.ts
2018
+ var AUTH_ERROR_PATTERNS = [
2019
+ "invalid_token",
2020
+ "invalid token",
2021
+ "unauthorized",
2022
+ "no token provided",
2023
+ "no authorization",
2024
+ "api key",
2025
+ "api_key",
2026
+ "authentication required",
2027
+ "authentication failed",
2028
+ "invalid credentials",
2029
+ "invalid api",
2030
+ "forbidden",
2031
+ "access denied",
2032
+ "not authenticated"
2033
+ ];
2034
+ function isAuthError(message) {
2035
+ const lower = message.toLowerCase();
2036
+ return AUTH_ERROR_PATTERNS.some((pattern) => lower.includes(pattern));
2037
+ }
1680
2038
  function resolveEnvVars(env) {
1681
2039
  const resolved = {};
1682
2040
  for (const [key, value] of Object.entries(env)) {
@@ -1757,7 +2115,7 @@ class Cataloger {
1757
2115
  if (err instanceof UnauthorizedError2 && connection.authProvider) {
1758
2116
  if (connection.authProvider.isNonInteractive()) {
1759
2117
  connection.authPending = true;
1760
- connection.status = "error";
2118
+ connection.status = "needs_auth";
1761
2119
  connection.error = `OAuth authorization required. Run: mcp-squared auth ${key}`;
1762
2120
  return;
1763
2121
  }
@@ -1781,8 +2139,9 @@ class Cataloger {
1781
2139
  }));
1782
2140
  connection.status = "connected";
1783
2141
  } catch (err) {
1784
- connection.status = "error";
1785
- connection.error = err instanceof Error ? err.message : String(err);
2142
+ const errorMsg = err instanceof Error ? err.message : String(err);
2143
+ connection.status = isAuthError(errorMsg) ? "needs_auth" : "error";
2144
+ connection.error = errorMsg;
1786
2145
  try {
1787
2146
  await this.cleanupConnection(connection);
1788
2147
  } catch (_cleanupErr) {}
@@ -1944,13 +2303,14 @@ class Cataloger {
1944
2303
  if (err instanceof UnauthorizedError2 && connection.authProvider) {
1945
2304
  if (connection.authProvider.isNonInteractive()) {
1946
2305
  connection.authPending = true;
1947
- connection.status = "error";
2306
+ connection.status = "needs_auth";
1948
2307
  connection.error = `OAuth authorization required. Run: mcp-squared auth ${key}`;
1949
2308
  return;
1950
2309
  }
1951
2310
  }
1952
- connection.status = "error";
1953
- connection.error = err instanceof Error ? err.message : String(err);
2311
+ const errorMsg = err instanceof Error ? err.message : String(err);
2312
+ connection.status = isAuthError(errorMsg) ? "needs_auth" : "error";
2313
+ connection.error = errorMsg;
1954
2314
  }
1955
2315
  }
1956
2316
  async refreshAllTools() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-squared",
3
- "version": "0.3.4",
3
+ "version": "0.6.0",
4
4
  "description": "MCP² (Mercury Control Plane) - A local-first meta-server and proxy for the Model Context Protocol",
5
5
  "author": "aditzel",
6
6
  "license": "Apache-2.0",
@@ -28,6 +28,7 @@
28
28
  "test": "bun test",
29
29
  "test:fast": "SKIP_SLOW_TESTS=true bun test",
30
30
  "test:watch": "bun test --watch",
31
+ "coverage:check": "bun run scripts/check-line-coverage.ts coverage/coverage-summary.txt 80",
31
32
  "typecheck": "tsc --noEmit",
32
33
  "lint": "biome check src tests scripts AGENTS.md CLAUDE.md WARP.md README.md CHANGELOG.md package.json biome.json tsconfig.json",
33
34
  "release:check": "bun run audit && bun test && bun run build && bun run build:verify && bun run lint && bun run typecheck && bun pm pack --dry-run",
@@ -35,7 +36,8 @@
35
36
  "lint:fix": "biome check --write .",
36
37
  "format": "biome format --write .",
37
38
  "clean": "rm -rf dist",
38
- "safety:sim": "bun run agent_safety_kit/cost_model/simulate.ts --tasks agent_safety_kit/cost_model/tasks.csv --pricing agent_safety_kit/cost_model/pricing.csv --out agent_safety_kit/cost_model/report.md"
39
+ "safety:sim": "bun run agent_safety_kit/cost_model/simulate.ts --tasks agent_safety_kit/cost_model/tasks.csv --pricing agent_safety_kit/cost_model/pricing.csv --out agent_safety_kit/cost_model/report.md",
40
+ "eval:routing": "bun run scripts/eval-tool-routing.ts"
39
41
  },
40
42
  "devDependencies": {
41
43
  "@biomejs/biome": "^2.4.4",
@@ -58,10 +60,13 @@
58
60
  "url": "https://github.com/aditzel/mcp-squared"
59
61
  },
60
62
  "dependencies": {
63
+ "@hono/node-server": "^1.19.11",
61
64
  "@huggingface/transformers": "^3.8.1",
62
65
  "@modelcontextprotocol/sdk": "^1.27.1",
63
66
  "@opentui/core": "^0.1.82",
67
+ "hono": "^4.12.5",
64
68
  "smol-toml": "^1.6.0",
69
+ "tar": "^7.5.10",
65
70
  "yaml": "^2.8.2",
66
71
  "zod": "^4.3.6"
67
72
  },
@@ -70,10 +75,11 @@
70
75
  "@opentelemetry/sdk-trace-base": "^1.30.1"
71
76
  },
72
77
  "overrides": {
78
+ "@hono/node-server": "^1.19.11",
73
79
  "ajv": "^8.18.0",
74
80
  "diff": "8.0.3",
75
- "hono": "^4.11.10",
81
+ "hono": "^4.12.5",
76
82
  "qs": "6.15.0",
77
- "tar": "7.5.9"
83
+ "tar": "^7.5.10"
78
84
  }
79
85
  }