hive-intelligence 1.1.3 → 1.1.4

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 (112) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +175 -54
  3. package/agent-skills/.claude-plugin/plugin.json +6 -0
  4. package/agent-skills/.mcp.json +11 -0
  5. package/agent-skills/AGENTS.md +37 -0
  6. package/agent-skills/README.md +13 -14
  7. package/agent-skills/SKILL.md +16 -4
  8. package/agent-skills/evals/trigger-queries.json +270 -0
  9. package/agent-skills/package.json +3 -3
  10. package/agent-skills/packs/hive-build/SKILL.md +11 -10
  11. package/agent-skills/packs/hive-build/evals/evals.json +2 -2
  12. package/agent-skills/packs/hive-mcp/SKILL.md +44 -121
  13. package/agent-skills/packs/hive-mcp/evals/evals.json +1 -1
  14. package/agent-skills/packs/hive-mcp/references/client-install-matrix.md +1 -1
  15. package/agent-skills/packs/hive-mcp/references/clients.md +141 -0
  16. package/agent-skills/packs/hive-query/SKILL.md +3 -2
  17. package/agent-skills/packs/hive-query/references/root-mcp-workflow.md +1 -1
  18. package/agent-skills/packs/hive-stateful-monitoring/SKILL.md +75 -0
  19. package/agent-skills/packs/hive-stateful-monitoring/evals/evals.json +49 -0
  20. package/agent-skills/packs/hive-tool-discovery/SKILL.md +1 -1
  21. package/agent-skills/references/agents-routing.md +2 -0
  22. package/agent-skills/scripts/validate-agent-skills-package.mjs +49 -11
  23. package/agent-skills/skills.sh.json +3 -2
  24. package/build/{alias-CZ3DEYHF.js → alias-3OPMQF4X.js} +2 -3
  25. package/build/{api-client-I23XLSHU.js → api-client-EPF6FD7A.js} +4 -4
  26. package/build/{auth-KKINNBXT.js → auth-Q5Q24IRI.js} +3 -4
  27. package/build/{browser-auth-EEFGRHWY.js → browser-auth-VPF5LZMZ.js} +2 -3
  28. package/build/{cache-EGNMENNA.js → cache-T6KC5YEY.js} +2 -3
  29. package/build/{chunk-KBVPIZS4.js → chunk-3WYWXTNN.js} +0 -1
  30. package/build/{chunk-2MYMHMBF.js → chunk-4F5CI6LX.js} +6 -6
  31. package/build/{chunk-RKICZ6DZ.js → chunk-5XXI25JE.js} +7 -8
  32. package/build/{chunk-IZTN7WFH.js → chunk-7JWXBKEJ.js} +5 -3
  33. package/build/chunk-CEWCB5YS.js +71 -0
  34. package/build/{chunk-MPIUUE3T.js → chunk-FH3YGSY5.js} +0 -1
  35. package/build/{chunk-QNCI4DEB.js → chunk-FRXMGRZQ.js} +35 -21
  36. package/build/{chunk-PGBVNMNZ.js → chunk-GZPDEXO4.js} +0 -1
  37. package/build/{chunk-UKHZIVDT.js → chunk-IZPAMRHP.js} +5 -6
  38. package/build/{chunk-2X3U4DFK.js → chunk-JTUKQWIO.js} +3267 -916
  39. package/build/{chunk-XYBEFFZ3.js → chunk-NP6NSOG2.js} +1 -2
  40. package/build/{chunk-V77LO4RO.js → chunk-POT2MBEK.js} +0 -1
  41. package/build/{chunk-B6G222LS.js → chunk-VBOKVQ74.js} +18 -3
  42. package/build/{chunk-DYJBTKNR.js → chunk-YZ2PXBJK.js} +5 -3
  43. package/build/chunk-ZCU7XQKF.js +14 -0
  44. package/build/{chunk-KGYBTXIN.js → chunk-ZTJVOWDQ.js} +0 -1
  45. package/build/{chunk-IDZD2NVG.js → chunk-ZXB53E7H.js} +5 -6
  46. package/build/cli.js +56 -54
  47. package/build/{completion-BELZL7ND.js → completion-46K674EL.js} +2 -3
  48. package/build/{config-TDX4VUGW.js → config-XE6Q5P4I.js} +3 -4
  49. package/build/{config-dir-V43W2WIA.js → config-dir-MAWX5AUF.js} +2 -3
  50. package/build/{doctor-5K5UWHNX.js → doctor-HGMQE6IN.js} +33 -9
  51. package/build/{errors-E6MVUBNA.js → errors-J2PH3NLJ.js} +2 -3
  52. package/build/{format-TSFSI2K7.js → format-5X2HIVDT.js} +1 -2
  53. package/build/{init-YQ5NBICF.js → init-JMDNM7ZZ.js} +1 -2
  54. package/build/{init-all-6OWEQALB.js → init-all-5SKNV75X.js} +10 -11
  55. package/build/{mcpServer-AEX3RQ4U.js → mcpServer-5TKKSKJM.js} +7 -6
  56. package/build/monitor-worker.js +1140 -0
  57. package/build/{namespace-PVHBFDW2.js → namespace-FSX2G3NM.js} +2 -3
  58. package/build/{open-YUIJP37F.js → open-5A6ZQMGC.js} +2 -3
  59. package/build/{output-IYJBFCYK.js → output-V3D4YZ6U.js} +2 -3
  60. package/build/{serve-KWNJK6EY.js → serve-AGCOXXFM.js} +9 -4
  61. package/build/server.js +437 -145
  62. package/build/{setup-YTUKMPNP.js → setup-RMETGJWK.js} +4 -5
  63. package/build/stdio.js +9 -8
  64. package/build/{telemetry-5IPRKZBL.js → telemetry-WCME5XEU.js} +4 -4
  65. package/build/{tools-PJHWFCAG.js → tools-KAB6QBZC.js} +15 -15
  66. package/build/{uninstall-HWXEIP6K.js → uninstall-FLJMBBSC.js} +7 -8
  67. package/build/update-check-LNZQK3XA.js +18 -0
  68. package/build/upgrade-DTUIHVPS.js +171 -0
  69. package/build/version-I6HDAF4L.js +14 -0
  70. package/build/{watch-KZ5EDZK3.js → watch-YNN255QX.js} +7 -7
  71. package/package.json +14 -9
  72. package/build/alias-CZ3DEYHF.js.map +0 -1
  73. package/build/api-client-I23XLSHU.js.map +0 -1
  74. package/build/auth-KKINNBXT.js.map +0 -1
  75. package/build/browser-auth-EEFGRHWY.js.map +0 -1
  76. package/build/cache-EGNMENNA.js.map +0 -1
  77. package/build/chunk-2MYMHMBF.js.map +0 -1
  78. package/build/chunk-2X3U4DFK.js.map +0 -1
  79. package/build/chunk-B6G222LS.js.map +0 -1
  80. package/build/chunk-DYJBTKNR.js.map +0 -1
  81. package/build/chunk-IDZD2NVG.js.map +0 -1
  82. package/build/chunk-IZTN7WFH.js.map +0 -1
  83. package/build/chunk-KBVPIZS4.js.map +0 -1
  84. package/build/chunk-KGYBTXIN.js.map +0 -1
  85. package/build/chunk-MPIUUE3T.js.map +0 -1
  86. package/build/chunk-PGBVNMNZ.js.map +0 -1
  87. package/build/chunk-QNCI4DEB.js.map +0 -1
  88. package/build/chunk-RKICZ6DZ.js.map +0 -1
  89. package/build/chunk-UKHZIVDT.js.map +0 -1
  90. package/build/chunk-V77LO4RO.js.map +0 -1
  91. package/build/chunk-XYBEFFZ3.js.map +0 -1
  92. package/build/cli.js.map +0 -1
  93. package/build/completion-BELZL7ND.js.map +0 -1
  94. package/build/config-TDX4VUGW.js.map +0 -1
  95. package/build/config-dir-V43W2WIA.js.map +0 -1
  96. package/build/doctor-5K5UWHNX.js.map +0 -1
  97. package/build/errors-E6MVUBNA.js.map +0 -1
  98. package/build/format-TSFSI2K7.js.map +0 -1
  99. package/build/init-YQ5NBICF.js.map +0 -1
  100. package/build/init-all-6OWEQALB.js.map +0 -1
  101. package/build/mcpServer-AEX3RQ4U.js.map +0 -1
  102. package/build/namespace-PVHBFDW2.js.map +0 -1
  103. package/build/open-YUIJP37F.js.map +0 -1
  104. package/build/output-IYJBFCYK.js.map +0 -1
  105. package/build/serve-KWNJK6EY.js.map +0 -1
  106. package/build/server.js.map +0 -1
  107. package/build/setup-YTUKMPNP.js.map +0 -1
  108. package/build/stdio.js.map +0 -1
  109. package/build/telemetry-5IPRKZBL.js.map +0 -1
  110. package/build/tools-PJHWFCAG.js.map +0 -1
  111. package/build/uninstall-HWXEIP6K.js.map +0 -1
  112. package/build/watch-KZ5EDZK3.js.map +0 -1
package/build/server.js CHANGED
@@ -1,13 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
3
+ import {
4
+ executeToolByName
5
+ } from "./chunk-CEWCB5YS.js";
3
6
  import {
4
7
  AUTH_COMPATIBILITY,
5
8
  CategoryEndpoints,
9
+ HIVE_AUTH_SUBJECT_ARG,
10
+ HIVE_AUTH_USER_ARG,
6
11
  HIVE_PROMPTS,
7
12
  HIVE_RESOURCES,
8
13
  RUNTIME_STATUSES,
9
- SERVER_NAME,
10
- SERVER_VERSION,
11
14
  TASK_TOOLSETS,
12
15
  TASK_TOOLSET_RUNTIME_STATUSES,
13
16
  ToolRegistry,
@@ -15,9 +18,8 @@ import {
15
18
  buildToolCatalogEntry,
16
19
  classifyRuntimeStatusFromError,
17
20
  createHiveMcpServer,
18
- createToolNotFoundResult,
19
21
  dynamicTools,
20
- executeEndpoint,
22
+ generateSubjectSigningSecret,
21
23
  getAllWrappedEndpoints,
22
24
  getCorsAllowedOrigins,
23
25
  getCsvEnv,
@@ -27,27 +29,35 @@ import {
27
29
  getProviderList,
28
30
  getRateLimitMax,
29
31
  getRedisClient,
30
- getRequiredEnvVar,
31
32
  getRootVisibleToolCount,
32
- getSharedClients,
33
+ getSupabaseAdmin,
34
+ getSupabaseAuthClient,
33
35
  getTaskCanaryCatalog,
34
36
  getTaskCanaryHistory,
35
- hasEnvVars,
37
+ hasSubjectSigningSecret,
38
+ isB2BSubjectsEnabled,
36
39
  isProduction,
37
40
  isRedisAvailable,
38
- resolveEndpoint,
41
+ isSupabaseConfigured,
42
+ recordSubjectAuditEvent,
43
+ resolveSubjectContext,
39
44
  runSelfTestFull,
40
45
  runSelfTestProvider,
41
46
  runSelfTestQuick,
42
47
  runTaskCanariesQuick,
43
48
  runTaskCanary,
49
+ sanitizeKeyMeta,
44
50
  secureLogger,
45
51
  trackServerEvent
46
- } from "./chunk-2X3U4DFK.js";
52
+ } from "./chunk-JTUKQWIO.js";
47
53
  import {
48
54
  HIVE_AGENT_SKILLS
49
- } from "./chunk-B6G222LS.js";
50
- import "./chunk-KBVPIZS4.js";
55
+ } from "./chunk-VBOKVQ74.js";
56
+ import {
57
+ SERVER_NAME,
58
+ SERVER_VERSION
59
+ } from "./chunk-ZCU7XQKF.js";
60
+ import "./chunk-3WYWXTNN.js";
51
61
 
52
62
  // src/server.ts
53
63
  import dotenv from "dotenv";
@@ -1048,46 +1058,6 @@ import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
1048
1058
 
1049
1059
  // src/services/unkey-service.ts
1050
1060
  import { Unkey } from "@unkey/api";
1051
-
1052
- // src/db/supabase.ts
1053
- import { createClient } from "@supabase/supabase-js";
1054
- var _supabaseAdmin = null;
1055
- var _supabaseAuth = null;
1056
- function isSupabaseConfigured() {
1057
- return hasEnvVars("SUPABASE_URL", "SUPABASE_SERVICE_ROLE_KEY");
1058
- }
1059
- function getSupabaseAdmin() {
1060
- if (!_supabaseAdmin) {
1061
- if (!isSupabaseConfigured()) {
1062
- throw new Error(
1063
- "Supabase not configured. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY."
1064
- );
1065
- }
1066
- _supabaseAdmin = createClient(
1067
- getRequiredEnvVar("SUPABASE_URL"),
1068
- getRequiredEnvVar("SUPABASE_SERVICE_ROLE_KEY"),
1069
- { auth: { persistSession: false, autoRefreshToken: false } }
1070
- );
1071
- }
1072
- return _supabaseAdmin;
1073
- }
1074
- function getSupabaseAuthClient() {
1075
- if (!_supabaseAuth) {
1076
- if (!hasEnvVars("SUPABASE_URL", "SUPABASE_ANON_KEY")) {
1077
- throw new Error(
1078
- "Supabase auth client not configured. Set SUPABASE_URL and SUPABASE_ANON_KEY."
1079
- );
1080
- }
1081
- _supabaseAuth = createClient(
1082
- getRequiredEnvVar("SUPABASE_URL"),
1083
- getRequiredEnvVar("SUPABASE_ANON_KEY"),
1084
- { auth: { persistSession: false, autoRefreshToken: false } }
1085
- );
1086
- }
1087
- return _supabaseAuth;
1088
- }
1089
-
1090
- // src/services/unkey-service.ts
1091
1061
  var _unkey = null;
1092
1062
  function getAuthBackendMode() {
1093
1063
  const mode = (process.env.HIVE_AUTH_BACKEND ?? "auto").trim().toLowerCase();
@@ -1155,13 +1125,22 @@ async function createApiKey(opts) {
1155
1125
  `Key limit reached. Your ${plan.name} plan allows ${plan.max_api_keys} keys.`
1156
1126
  );
1157
1127
  }
1128
+ const subjectSigningSecret = opts.b2bSubjectsEnabled ? generateSubjectSigningSecret() : void 0;
1129
+ const meta = {
1130
+ plan: opts.planId,
1131
+ name: opts.name,
1132
+ ...opts.b2bSubjectsEnabled ? {
1133
+ b2b_subjects_enabled: true,
1134
+ subject_signing_secret: subjectSigningSecret
1135
+ } : {}
1136
+ };
1158
1137
  const result = await getUnkey().keys.createKey({
1159
1138
  apiId: getApiId(),
1160
1139
  prefix: "hive_live",
1161
1140
  name: opts.name,
1162
1141
  byteLength: 24,
1163
1142
  externalId: opts.userId,
1164
- meta: { plan: opts.planId, name: opts.name },
1143
+ meta,
1165
1144
  ratelimits: [
1166
1145
  {
1167
1146
  name: "requests",
@@ -1177,7 +1156,11 @@ async function createApiKey(opts) {
1177
1156
  });
1178
1157
  throw new Error("Failed to create API key");
1179
1158
  }
1180
- return { keyId: result.data.keyId, key: result.data.key };
1159
+ return {
1160
+ keyId: result.data.keyId,
1161
+ key: result.data.key,
1162
+ subjectSigningSecret
1163
+ };
1181
1164
  }
1182
1165
  async function verifyApiKey(rawKey, analyticsTags = []) {
1183
1166
  const tags = normalizeAnalyticsTags(analyticsTags);
@@ -1207,6 +1190,7 @@ async function verifyApiKey(rawKey, analyticsTags = []) {
1207
1190
  planId: d.meta?.plan,
1208
1191
  name: d.name,
1209
1192
  credits: d.credits ?? void 0,
1193
+ meta: d.meta ?? void 0,
1210
1194
  ratelimit: rl ? { remaining: rl.remaining, limit: rl.limit, reset: rl.reset } : void 0
1211
1195
  };
1212
1196
  }
@@ -1225,7 +1209,7 @@ async function listKeys(userId) {
1225
1209
  enabled: k.enabled ?? true,
1226
1210
  credits: k.credits?.remaining ?? void 0,
1227
1211
  externalId: k.identity?.externalId ?? void 0,
1228
- meta: k.meta ?? void 0
1212
+ meta: sanitizeKeyMeta(k.meta ?? void 0)
1229
1213
  }));
1230
1214
  }
1231
1215
  async function revokeKey(keyId) {
@@ -3564,7 +3548,8 @@ async function handleRedisLookup(key, res, next) {
3564
3548
  // src/routes/keys.ts
3565
3549
  var router3 = Router3();
3566
3550
  var CreateKeySchema = z2.object({
3567
- name: z2.string().min(1).max(100).optional()
3551
+ name: z2.string().min(1).max(100).optional(),
3552
+ b2b_subjects_enabled: z2.boolean().optional()
3568
3553
  });
3569
3554
  router3.post(
3570
3555
  "/",
@@ -3582,7 +3567,7 @@ router3.post(
3582
3567
  )
3583
3568
  );
3584
3569
  }
3585
- const { name } = parseResult.data;
3570
+ const { name, b2b_subjects_enabled } = parseResult.data;
3586
3571
  const { data: profile } = await getSupabaseAdmin().from("user_profiles").select("plan_id").eq("id", user.id).single();
3587
3572
  const planId = profile?.plan_id ?? "demo";
3588
3573
  await ensureWallet(user.id, planId);
@@ -3590,7 +3575,8 @@ router3.post(
3590
3575
  const result = await createApiKey({
3591
3576
  userId: user.id,
3592
3577
  name: name ?? "Default",
3593
- planId
3578
+ planId,
3579
+ b2bSubjectsEnabled: b2b_subjects_enabled ?? false
3594
3580
  });
3595
3581
  return res.status(201).json({
3596
3582
  ok: true,
@@ -3599,6 +3585,8 @@ router3.post(
3599
3585
  key: result.key,
3600
3586
  name: name ?? "Default",
3601
3587
  plan: planId,
3588
+ b2b_subjects_enabled: b2b_subjects_enabled ?? false,
3589
+ ...result.subjectSigningSecret ? { subject_signing_secret: result.subjectSigningSecret } : {},
3602
3590
  warning: "Save this key \u2014 it will not be shown again."
3603
3591
  }
3604
3592
  });
@@ -3743,6 +3731,176 @@ router4.get(
3743
3731
  );
3744
3732
  var usage_default = router4;
3745
3733
 
3734
+ // src/routes/b2b.ts
3735
+ import { Router as Router5 } from "express";
3736
+ var router5 = Router5();
3737
+ var SIGNED_SUBJECT_HEADERS = [
3738
+ "X-Hive-Tenant-Id",
3739
+ "X-Hive-End-User-Id",
3740
+ "X-Hive-Subject-Timestamp",
3741
+ "X-Hive-Subject-Signature"
3742
+ ];
3743
+ var SIGNATURE_PAYLOAD = 'METHOD + "\\n" + PATH + "\\n" + TENANT_ID + "\\n" + END_USER_ID + "\\n" + TIMESTAMP';
3744
+ function buildB2BReadinessPayload(args) {
3745
+ const meta = args.verifyResult?.meta;
3746
+ const b2bEnabled = args.authBackend === "unkey" ? isB2BSubjectsEnabled(meta) : false;
3747
+ const secretConfigured = args.authBackend === "unkey" && b2bEnabled ? hasSubjectSigningSecret(meta) : false;
3748
+ const warnings = [];
3749
+ let mode;
3750
+ if (args.authBackend === "static") {
3751
+ mode = "static_key";
3752
+ warnings.push(
3753
+ "Static HIVE_API_KEYS authentication does not provide a Hive owner user_id or per-key B2B subject metadata. Use Unkey-backed Hive keys for partner/end-user state isolation."
3754
+ );
3755
+ } else if (b2bEnabled) {
3756
+ mode = "b2b_enabled";
3757
+ if (!secretConfigured) {
3758
+ warnings.push(
3759
+ "This API key has B2B subjects enabled but no subject signing secret is configured. Stateful writes with signed subject headers will fail."
3760
+ );
3761
+ }
3762
+ } else {
3763
+ mode = "direct_user";
3764
+ warnings.push(
3765
+ "This key is valid for direct-user state, but B2B subjects are not enabled. A partner using this key without signed subject headers will share one default subject across downstream customers."
3766
+ );
3767
+ }
3768
+ return {
3769
+ b2b_adapter_ready: args.authBackend === "unkey" && b2bEnabled && secretConfigured,
3770
+ mode,
3771
+ auth_backend: args.authBackend,
3772
+ api_key: {
3773
+ valid: true,
3774
+ ...args.verifyResult?.keyId ? { key_id: args.verifyResult.keyId } : {},
3775
+ ...args.verifyResult?.userId ? { owner_user_id: args.verifyResult.userId } : {},
3776
+ ...args.verifyResult?.planId ? { plan_id: args.verifyResult.planId } : {},
3777
+ ...args.verifyResult?.name ? { name: args.verifyResult.name } : {},
3778
+ b2b_subjects_enabled: b2bEnabled,
3779
+ subject_signing_secret_configured: secretConfigured,
3780
+ ...args.verifyResult?.ratelimit ? { ratelimit_remaining: args.verifyResult.ratelimit.remaining } : {}
3781
+ },
3782
+ state: {
3783
+ stateful_tools_supported: args.authBackend === "unkey",
3784
+ direct_user_subject: "default_self",
3785
+ signed_subjects_required_for_stateful_writes: b2bEnabled,
3786
+ isolation_boundary: "owner_user_id + subject_id"
3787
+ },
3788
+ signed_subject_headers: SIGNED_SUBJECT_HEADERS,
3789
+ signature_payload: SIGNATURE_PAYLOAD,
3790
+ signature_algorithm: "HMAC-SHA256",
3791
+ timestamp_skew_seconds: 300,
3792
+ endpoints: {
3793
+ mcp: "/mcp",
3794
+ rest_execute: "/api/v1/execute",
3795
+ readiness: "/api/v1/b2b/readiness"
3796
+ },
3797
+ smoke: {
3798
+ command: "npm run smoke:b2b-partner",
3799
+ required_env: ["HIVE_API_KEY", "HIVE_SUBJECT_SIGNING_SECRET"]
3800
+ },
3801
+ warnings
3802
+ };
3803
+ }
3804
+ function getRequestApiKey(req) {
3805
+ const xApiKey = req.headers["x-api-key"];
3806
+ if (typeof xApiKey === "string" && xApiKey.trim()) return xApiKey.trim();
3807
+ const auth = req.headers.authorization;
3808
+ if (auth?.startsWith("Bearer ")) {
3809
+ const token = auth.slice("Bearer ".length).trim();
3810
+ return token || void 0;
3811
+ }
3812
+ return void 0;
3813
+ }
3814
+ router5.get(
3815
+ "/readiness",
3816
+ asyncHandler(async (req, res) => {
3817
+ const key = getRequestApiKey(req);
3818
+ if (!key) {
3819
+ return res.status(401).json(
3820
+ apiError(
3821
+ "authentication_error",
3822
+ "AUTH_REQUIRED",
3823
+ "API key required. Set x-api-key header or Authorization: Bearer <key>.",
3824
+ { requestId: req.requestId }
3825
+ )
3826
+ );
3827
+ }
3828
+ if (isUnkeyRequired() && !isUnkeyConfigured()) {
3829
+ return res.status(503).json(
3830
+ apiError(
3831
+ "internal_error",
3832
+ "AUTH_NOT_CONFIGURED",
3833
+ "Unkey authentication is selected but not configured. Set UNKEY_ROOT_KEY and UNKEY_API_ID, or set HIVE_AUTH_BACKEND=static with HIVE_API_KEYS.",
3834
+ { requestId: req.requestId }
3835
+ )
3836
+ );
3837
+ }
3838
+ if (isUnkeyConfigured()) {
3839
+ const result = await verifyApiKey(key, [
3840
+ "service=hive",
3841
+ "transport=rest",
3842
+ "route=/api/v1/b2b/readiness"
3843
+ ]);
3844
+ if (!result.valid) {
3845
+ const statusCode = result.code === "RATE_LIMITED" ? 429 : 403;
3846
+ const errorCode = result.code === "RATE_LIMITED" ? "RATE_LIMITED" : "INVALID_API_KEY";
3847
+ if (result.code === "RATE_LIMITED") res.setHeader("Retry-After", "60");
3848
+ return res.status(statusCode).json(
3849
+ apiError(
3850
+ "authentication_error",
3851
+ errorCode,
3852
+ result.code === "RATE_LIMITED" ? "Rate limit exceeded." : "Invalid API key.",
3853
+ { requestId: req.requestId }
3854
+ )
3855
+ );
3856
+ }
3857
+ if (!result.userId) {
3858
+ return res.status(403).json(
3859
+ apiError(
3860
+ "authentication_error",
3861
+ "INVALID_API_KEY",
3862
+ "Invalid API key.",
3863
+ { requestId: req.requestId }
3864
+ )
3865
+ );
3866
+ }
3867
+ return res.json({
3868
+ ok: true,
3869
+ data: buildB2BReadinessPayload({
3870
+ authBackend: "unkey",
3871
+ verifyResult: result
3872
+ })
3873
+ });
3874
+ }
3875
+ const staticKeys = getCsvEnv("HIVE_API_KEYS");
3876
+ if (staticKeys.length === 0) {
3877
+ return res.status(503).json(
3878
+ apiError(
3879
+ "internal_error",
3880
+ "AUTH_NOT_CONFIGURED",
3881
+ "API key authentication is not configured. Set HIVE_API_KEYS or configure Unkey.",
3882
+ { requestId: req.requestId }
3883
+ )
3884
+ );
3885
+ }
3886
+ if (!staticKeys.includes(key)) {
3887
+ return res.status(403).json(
3888
+ apiError(
3889
+ "authentication_error",
3890
+ "INVALID_API_KEY",
3891
+ "Invalid API key.",
3892
+ { requestId: req.requestId }
3893
+ )
3894
+ );
3895
+ }
3896
+ return res.json({
3897
+ ok: true,
3898
+ data: buildB2BReadinessPayload({ authBackend: "static" })
3899
+ });
3900
+ })
3901
+ );
3902
+ var b2b_default = router5;
3903
+
3746
3904
  // src/middleware/request-id.ts
3747
3905
  import { randomUUID as randomUUID2 } from "crypto";
3748
3906
  function requestIdMiddleware(req, res, next) {
@@ -4075,64 +4233,6 @@ function generateOpenApiSpec() {
4075
4233
  return _cachedSpec;
4076
4234
  }
4077
4235
 
4078
- // src/services/tool-execution.ts
4079
- async function executeToolByName(toolName, args) {
4080
- const allEndpoints = getAllWrappedEndpoints();
4081
- const lookup = resolveEndpoint(allEndpoints, toolName);
4082
- if (!lookup.ok) {
4083
- const result2 = createToolNotFoundResult(toolName);
4084
- secureLogger.toolCall(toolName, false, result2.durationMs, {
4085
- transport: "rest",
4086
- runtimeStatus: "failing",
4087
- errorClass: "not_found"
4088
- });
4089
- return {
4090
- ok: false,
4091
- error: result2.error,
4092
- durationMs: result2.durationMs,
4093
- meta: result2.hive
4094
- };
4095
- }
4096
- const result = await executeEndpoint(lookup.endpoint, args, {
4097
- transport: "rest",
4098
- clients: getSharedClients()
4099
- });
4100
- if (result.validationErrors) {
4101
- return {
4102
- ok: false,
4103
- error: result.error,
4104
- validationErrors: result.validationErrors,
4105
- durationMs: result.durationMs,
4106
- meta: result.hive
4107
- };
4108
- }
4109
- if (result.ok) {
4110
- return {
4111
- ok: true,
4112
- data: result.data,
4113
- durationMs: result.durationMs,
4114
- meta: result.hive
4115
- };
4116
- }
4117
- if (result.error?.code === "PROVIDER_UNAVAILABLE") {
4118
- return {
4119
- ok: false,
4120
- error: result.error,
4121
- durationMs: result.durationMs,
4122
- meta: result.hive
4123
- };
4124
- }
4125
- if (result.error?.code === "INTERNAL_ERROR") {
4126
- secureLogger.error(`[tool-execution] ${toolName} threw`, result.error, {});
4127
- }
4128
- return {
4129
- ok: false,
4130
- error: result.error,
4131
- durationMs: result.durationMs,
4132
- meta: result.hive
4133
- };
4134
- }
4135
-
4136
4236
  // src/utils/mcpHttp.ts
4137
4237
  function isMcpPath(path) {
4138
4238
  return path === "/mcp" || path === "/mcp/" || /\/mcp\/?$/.test(path);
@@ -4145,6 +4245,7 @@ function hasRequiredStreamableHttpAcceptHeader(acceptHeader) {
4145
4245
  }
4146
4246
 
4147
4247
  // src/serverCard.ts
4248
+ import { LATEST_PROTOCOL_VERSION } from "@modelcontextprotocol/sdk/types.js";
4148
4249
  function buildServerCard() {
4149
4250
  const underlyingToolCount = getAllWrappedEndpoints().length;
4150
4251
  const visibleToolCount = getRootVisibleToolCount();
@@ -4153,8 +4254,8 @@ function buildServerCard() {
4153
4254
  name: "Hive Intelligence",
4154
4255
  id: "io.github.sharpe-labs/hive-mcp",
4155
4256
  version: SERVER_VERSION,
4156
- protocolVersion: "2025-06-18",
4157
- description: "Institutional-grade crypto market infrastructure for AI \u2014 live prices, DeFi, wallets, and token risk through a managed MCP, REST API, or CLI.",
4257
+ protocolVersion: LATEST_PROTOCOL_VERSION,
4258
+ description: "Managed crypto market infrastructure for AI agents \u2014 live prices, DeFi, wallets, and token risk through MCP, REST API, or CLI.",
4158
4259
  author: {
4159
4260
  name: "Hive Intelligence",
4160
4261
  url: "https://www.hiveintelligence.xyz",
@@ -4164,7 +4265,7 @@ function buildServerCard() {
4164
4265
  documentation: "https://www.hiveintelligence.xyz/crypto-mcp",
4165
4266
  repository: {
4166
4267
  type: "git",
4167
- url: "https://github.com/sharpe-labs/hive-mcp2"
4268
+ url: "https://github.com/hive-intel/hive-sdk"
4168
4269
  },
4169
4270
  license: "MIT",
4170
4271
  categories: ["finance", "crypto", "defi", "web3", "ai-agents"],
@@ -4211,6 +4312,18 @@ function buildServerCard() {
4211
4312
  Authorization: "Bearer <YOUR_HIVE_API_KEY>",
4212
4313
  "x-api-key": "<YOUR_HIVE_API_KEY>"
4213
4314
  },
4315
+ b2bSubjectHeaders: {
4316
+ note: "B2B-enabled API keys may isolate downstream customer state by sending signed subject headers from a trusted backend adapter. Stateful writes require these headers when b2b_subjects_enabled=true.",
4317
+ readinessUrl: "https://mcp.hiveintelligence.xyz/api/v1/b2b/readiness",
4318
+ headers: [
4319
+ "X-Hive-Tenant-Id",
4320
+ "X-Hive-End-User-Id",
4321
+ "X-Hive-Subject-Timestamp",
4322
+ "X-Hive-Subject-Signature"
4323
+ ],
4324
+ signaturePayload: 'METHOD + "\\n" + PATH + "\\n" + TENANT_ID + "\\n" + END_USER_ID + "\\n" + TIMESTAMP',
4325
+ algorithm: "HMAC-SHA256"
4326
+ },
4214
4327
  signupUrl: "https://www.hiveintelligence.xyz/login?next=/dashboard/keys",
4215
4328
  freeTier: {
4216
4329
  monthlyCredits: 1e4,
@@ -4266,9 +4379,13 @@ function buildServerCard() {
4266
4379
  setupUrl: "https://hiveintelligence.xyz/install/claude-code"
4267
4380
  },
4268
4381
  {
4269
- name: "ChatGPT Desktop",
4382
+ name: "OpenAI Responses API",
4270
4383
  setupUrl: "https://hiveintelligence.xyz/install/chatgpt"
4271
4384
  },
4385
+ {
4386
+ name: "Codex CLI",
4387
+ setupUrl: "https://hiveintelligence.xyz/install/codex"
4388
+ },
4272
4389
  {
4273
4390
  name: "Cursor",
4274
4391
  setupUrl: "https://hiveintelligence.xyz/install/cursor"
@@ -4363,13 +4480,16 @@ app.use(
4363
4480
  (req, res, next) => {
4364
4481
  if (req.method === "POST" && (req.path === "/mcp" || req.path.endsWith("/mcp"))) {
4365
4482
  const origin = req.headers.origin;
4366
- if (origin && !LOCALHOST_RE.test(origin) && ALLOWED_MCP_ORIGINS.length > 0 && !ALLOWED_MCP_ORIGINS.includes(origin)) {
4367
- res.status(403).json({
4368
- jsonrpc: "2.0",
4369
- error: { code: -32600, message: "Origin not allowed" },
4370
- id: null
4371
- });
4372
- return;
4483
+ if (origin && !LOCALHOST_RE.test(origin)) {
4484
+ const enforce = isProduction() || ALLOWED_MCP_ORIGINS.length > 0;
4485
+ if (enforce && !ALLOWED_MCP_ORIGINS.includes(origin)) {
4486
+ res.status(403).json({
4487
+ jsonrpc: "2.0",
4488
+ error: { code: -32600, message: "Origin not allowed" },
4489
+ id: null
4490
+ });
4491
+ return;
4492
+ }
4373
4493
  }
4374
4494
  }
4375
4495
  next();
@@ -4435,7 +4555,7 @@ function buildMcpDiscoveryDescriptor() {
4435
4555
  name: "Hive Intelligence",
4436
4556
  id: SERVER_NAME,
4437
4557
  version: SERVER_VERSION,
4438
- description: "Institutional-grade crypto market infrastructure for AI \u2014 unified API for crypto market data, DeFi, wallets, security, DEX flows, NFTs, and prediction markets",
4558
+ description: "Managed crypto market infrastructure for AI agents \u2014 unified API for crypto market data, DeFi, wallets, security, DEX flows, NFTs, and prediction markets",
4439
4559
  endpoints: {
4440
4560
  mcp: "/mcp",
4441
4561
  rest: "/api/v1",
@@ -4464,7 +4584,11 @@ app.get(["/.well-known/mcp.json", "/mcp.json"], (_req, res) => {
4464
4584
  res.json(buildMcpDiscoveryDescriptor());
4465
4585
  });
4466
4586
  app.get(
4467
- ["/.well-known/mcp/server-card.json", "/server-card.json", "/mcp/server-card.json"],
4587
+ [
4588
+ "/.well-known/mcp/server-card.json",
4589
+ "/server-card.json",
4590
+ "/mcp/server-card.json"
4591
+ ],
4468
4592
  (_req, res) => {
4469
4593
  setDiscoveryHeaders(res);
4470
4594
  res.json(buildServerCard());
@@ -4489,6 +4613,7 @@ app.use(health_default);
4489
4613
  app.use("/auth", auth_default);
4490
4614
  app.use("/api/v1/keys", keys_default);
4491
4615
  app.use("/api/v1/usage", usage_default);
4616
+ app.use("/api/v1/b2b", b2b_default);
4492
4617
  var mcpIpRateLimiter = createIpRateLimiter();
4493
4618
  var restIpRateLimiter = createIpRateLimiter();
4494
4619
  var mcpMiddlewares = [mcpIpRateLimiter];
@@ -4526,42 +4651,127 @@ function extractApiKey(req) {
4526
4651
  async function validateMcpApiKey(req) {
4527
4652
  const key = extractApiKey(req);
4528
4653
  if (isUnkeyRequired() && !isUnkeyConfigured()) {
4529
- return "Unkey authentication is selected but not configured. Set UNKEY_ROOT_KEY and UNKEY_API_ID, or set HIVE_AUTH_BACKEND=static with HIVE_API_KEYS.";
4654
+ return {
4655
+ ok: false,
4656
+ error: "Unkey authentication is selected but not configured. Set UNKEY_ROOT_KEY and UNKEY_API_ID, or set HIVE_AUTH_BACKEND=static with HIVE_API_KEYS."
4657
+ };
4530
4658
  }
4531
4659
  if (isUnkeyConfigured()) {
4532
4660
  if (!key)
4533
- return `API key required. Get a free key at https://hiveintelligence.xyz/dashboard/keys then pass it as 'Authorization: Bearer <key>' or 'x-api-key: <key>'. Claude Code: claude mcp add --transport http hive https://mcp.hiveintelligence.xyz/mcp --header "Authorization: Bearer <key>".`;
4661
+ return {
4662
+ ok: false,
4663
+ error: `API key required. Get a free key at https://hiveintelligence.xyz/dashboard/keys then pass it as 'Authorization: Bearer <key>' or 'x-api-key: <key>'. Claude Code: claude mcp add --transport http hive https://mcp.hiveintelligence.xyz/mcp --header "Authorization: Bearer <key>".`
4664
+ };
4534
4665
  let result;
4535
4666
  try {
4536
- result = await withTimeout(verifyApiKey(key, getMcpAnalyticsTags(req)), 500);
4667
+ result = await withTimeout(
4668
+ verifyApiKey(key, getMcpAnalyticsTags(req)),
4669
+ 500
4670
+ );
4537
4671
  } catch (err) {
4538
4672
  secureLogger.warn("MCP Unkey verifyApiKey timeout/failure", {
4539
4673
  error: err instanceof Error ? err.message : String(err)
4540
4674
  });
4541
- return "Authentication service temporarily unavailable. Please retry in a moment.";
4675
+ return {
4676
+ ok: false,
4677
+ error: "Authentication service temporarily unavailable. Please retry in a moment."
4678
+ };
4542
4679
  }
4543
4680
  if (!result.valid) {
4544
- if (result.code === "RATE_LIMITED") return "Rate limit exceeded.";
4545
- return "Invalid API key.";
4681
+ if (result.code === "RATE_LIMITED") {
4682
+ return { ok: false, error: "Rate limit exceeded." };
4683
+ }
4684
+ return { ok: false, error: "Invalid API key." };
4546
4685
  }
4547
4686
  if (!result.userId) {
4548
- return "Invalid API key.";
4687
+ return { ok: false, error: "Invalid API key." };
4549
4688
  }
4550
4689
  void debitCreditsAsync({
4551
4690
  userId: result.userId,
4552
4691
  keyId: result.keyId,
4553
4692
  requestId: req.requestId
4554
4693
  });
4555
- return null;
4694
+ return {
4695
+ ok: true,
4696
+ userId: result.userId,
4697
+ keyId: result.keyId,
4698
+ keyMeta: result.meta
4699
+ };
4556
4700
  }
4557
4701
  const validKeys = (process.env.HIVE_API_KEYS || "").split(",").filter(Boolean);
4558
4702
  if (validKeys.length === 0) {
4559
- return "API key authentication is not configured on this server.";
4703
+ return {
4704
+ ok: false,
4705
+ error: "API key authentication is not configured on this server."
4706
+ };
4560
4707
  }
4561
4708
  if (!key)
4562
- return "API key required. Set x-api-key header or Authorization: Bearer <key>.";
4563
- if (!validKeys.includes(key)) return "Invalid API key.";
4564
- return null;
4709
+ return {
4710
+ ok: false,
4711
+ error: "API key required. Set x-api-key header or Authorization: Bearer <key>."
4712
+ };
4713
+ if (!validKeys.includes(key)) return { ok: false, error: "Invalid API key." };
4714
+ return { ok: true };
4715
+ }
4716
+ var STATEFUL_WRITE_TOOLS = /* @__PURE__ */ new Set([
4717
+ "hive_create_monitor",
4718
+ "hive_update_monitor",
4719
+ "hive_archive_monitor",
4720
+ "hive_update_alert_status",
4721
+ "hive_remember_fact",
4722
+ "hive_forget_memory_fact"
4723
+ ]);
4724
+ function getMcpHiveToolName(body) {
4725
+ if (body?.method !== "tools/call") return void 0;
4726
+ const toolName = body.params?.name;
4727
+ const toolArgs = body.params?.arguments;
4728
+ if (!toolName || typeof toolName !== "string") return void 0;
4729
+ if (toolName === "invoke_api_endpoint") {
4730
+ const endpointName = typeof toolArgs?.endpoint_name === "string" ? toolArgs.endpoint_name : typeof toolArgs?.args?.endpoint_name === "string" ? toolArgs.args.endpoint_name : void 0;
4731
+ return endpointName?.startsWith("hive_") ? endpointName : void 0;
4732
+ }
4733
+ return toolName.startsWith("hive_") ? toolName : void 0;
4734
+ }
4735
+ function removeHiddenHiveAuthArgs(args) {
4736
+ if (!args || typeof args !== "object" || Array.isArray(args)) return;
4737
+ delete args[HIVE_AUTH_USER_ARG];
4738
+ delete args[HIVE_AUTH_SUBJECT_ARG];
4739
+ }
4740
+ function getRestHiveToolName(toolName, args) {
4741
+ if (toolName.startsWith("hive_")) return toolName;
4742
+ if (toolName !== "invoke_api_endpoint") return void 0;
4743
+ const endpointName = typeof args.endpoint_name === "string" ? args.endpoint_name : typeof args.args?.endpoint_name === "string" ? args.args.endpoint_name : void 0;
4744
+ return endpointName?.startsWith("hive_") ? endpointName : void 0;
4745
+ }
4746
+ function injectMcpAuthContext(body, context) {
4747
+ if (body?.method !== "tools/call") return;
4748
+ const toolName = body.params?.name;
4749
+ if (!toolName || typeof toolName !== "string") return;
4750
+ if (toolName !== "invoke_api_endpoint" && !toolName.startsWith("hive_")) {
4751
+ return;
4752
+ }
4753
+ if (!body.params.arguments || typeof body.params.arguments !== "object") {
4754
+ body.params.arguments = {};
4755
+ }
4756
+ const toolArgs = body.params.arguments;
4757
+ if (toolName === "invoke_api_endpoint") {
4758
+ removeHiddenHiveAuthArgs(toolArgs);
4759
+ removeHiddenHiveAuthArgs(toolArgs.args);
4760
+ const endpointName = typeof toolArgs.endpoint_name === "string" ? toolArgs.endpoint_name : typeof toolArgs.args?.endpoint_name === "string" ? toolArgs.args.endpoint_name : void 0;
4761
+ if (!endpointName?.startsWith("hive_") || !context) return;
4762
+ if (!toolArgs.args || typeof toolArgs.args !== "object") {
4763
+ toolArgs.args = {};
4764
+ }
4765
+ toolArgs.args[HIVE_AUTH_USER_ARG] = context.userId;
4766
+ toolArgs.args[HIVE_AUTH_SUBJECT_ARG] = context.subjectId;
4767
+ return;
4768
+ }
4769
+ removeHiddenHiveAuthArgs(toolArgs);
4770
+ if (typeof toolName === "string" && toolName.startsWith("hive_")) {
4771
+ if (!context) return;
4772
+ toolArgs[HIVE_AUTH_USER_ARG] = context.userId;
4773
+ toolArgs[HIVE_AUTH_SUBJECT_ARG] = context.subjectId;
4774
+ }
4565
4775
  }
4566
4776
  function getMcpAnalyticsTags(req) {
4567
4777
  const body = req.body;
@@ -4582,11 +4792,11 @@ function getMcpAnalyticsTags(req) {
4582
4792
  function createStatelessMcpHandler(scope) {
4583
4793
  return async (req, res) => {
4584
4794
  const sessionCorrelationId = req.requestId;
4585
- const authError = await validateMcpApiKey(req);
4586
- if (authError) {
4795
+ const auth = await validateMcpApiKey(req);
4796
+ if (!auth.ok) {
4587
4797
  res.status(200).json({
4588
4798
  jsonrpc: "2.0",
4589
- error: { code: -32001, message: authError },
4799
+ error: { code: -32001, message: auth.error },
4590
4800
  id: req.body?.id ?? null
4591
4801
  });
4592
4802
  return;
@@ -4606,6 +4816,43 @@ function createStatelessMcpHandler(scope) {
4606
4816
  }
4607
4817
  }
4608
4818
  }
4819
+ const hiveToolName = getMcpHiveToolName(body);
4820
+ let subjectContext;
4821
+ if (hiveToolName && auth.userId) {
4822
+ const subject = await resolveSubjectContext({
4823
+ userId: auth.userId,
4824
+ keyId: auth.keyId,
4825
+ keyMeta: auth.keyMeta,
4826
+ method: req.method,
4827
+ path: req.path,
4828
+ headers: req.headers,
4829
+ requiresSubjectHeaders: STATEFUL_WRITE_TOOLS.has(hiveToolName)
4830
+ });
4831
+ if (!subject.ok) {
4832
+ res.status(200).json({
4833
+ jsonrpc: "2.0",
4834
+ error: {
4835
+ code: -32002,
4836
+ message: subject.message,
4837
+ data: { code: subject.code }
4838
+ },
4839
+ id: body?.id ?? null
4840
+ });
4841
+ return;
4842
+ }
4843
+ subjectContext = subject.data;
4844
+ if (STATEFUL_WRITE_TOOLS.has(hiveToolName)) {
4845
+ recordSubjectAuditEvent({
4846
+ userId: subject.data.userId,
4847
+ subjectId: subject.data.subjectId,
4848
+ keyId: auth.keyId,
4849
+ transport: "mcp",
4850
+ toolName: hiveToolName,
4851
+ requestId: req.requestId
4852
+ });
4853
+ }
4854
+ }
4855
+ injectMcpAuthContext(body, subjectContext);
4609
4856
  const server = createHiveMcpServer(scope).getServer();
4610
4857
  const transport = new StreamableHTTPServerTransport({
4611
4858
  sessionIdGenerator: void 0,
@@ -4787,7 +5034,53 @@ app.post(
4787
5034
  meta: { tool: toolName ?? null, duration_ms: 0 }
4788
5035
  });
4789
5036
  }
4790
- const result = await executeToolByName(toolName, args ?? {});
5037
+ const endpointArgs = { ...args ?? {} };
5038
+ removeHiddenHiveAuthArgs(endpointArgs);
5039
+ removeHiddenHiveAuthArgs(endpointArgs.args);
5040
+ const authReq = req;
5041
+ const hiveToolName = getRestHiveToolName(toolName, endpointArgs);
5042
+ if (hiveToolName && authReq.userId) {
5043
+ const subject = await resolveSubjectContext({
5044
+ userId: authReq.userId,
5045
+ keyId: authReq.unkeyKeyId,
5046
+ keyMeta: authReq.unkeyResult?.meta,
5047
+ method: req.method,
5048
+ path: req.path,
5049
+ headers: req.headers,
5050
+ requiresSubjectHeaders: STATEFUL_WRITE_TOOLS.has(hiveToolName)
5051
+ });
5052
+ if (!subject.ok) {
5053
+ return res.status(subject.status).json(
5054
+ apiError(
5055
+ subject.status === 400 ? "invalid_request_error" : "authentication_error",
5056
+ subject.code,
5057
+ subject.message,
5058
+ { requestId: req.requestId }
5059
+ )
5060
+ );
5061
+ }
5062
+ if (toolName === "invoke_api_endpoint") {
5063
+ if (!endpointArgs.args || typeof endpointArgs.args !== "object") {
5064
+ endpointArgs.args = {};
5065
+ }
5066
+ endpointArgs.args[HIVE_AUTH_USER_ARG] = subject.data.userId;
5067
+ endpointArgs.args[HIVE_AUTH_SUBJECT_ARG] = subject.data.subjectId;
5068
+ } else {
5069
+ endpointArgs[HIVE_AUTH_USER_ARG] = subject.data.userId;
5070
+ endpointArgs[HIVE_AUTH_SUBJECT_ARG] = subject.data.subjectId;
5071
+ }
5072
+ if (STATEFUL_WRITE_TOOLS.has(hiveToolName)) {
5073
+ recordSubjectAuditEvent({
5074
+ userId: subject.data.userId,
5075
+ subjectId: subject.data.subjectId,
5076
+ keyId: authReq.unkeyKeyId,
5077
+ transport: "rest",
5078
+ toolName: hiveToolName,
5079
+ requestId: req.requestId
5080
+ });
5081
+ }
5082
+ }
5083
+ const result = await executeToolByName(toolName, endpointArgs);
4791
5084
  const meta = {
4792
5085
  tool: toolName,
4793
5086
  duration_ms: result.durationMs,
@@ -5017,4 +5310,3 @@ export {
5017
5310
  server_default as default,
5018
5311
  startHttpServer
5019
5312
  };
5020
- //# sourceMappingURL=server.js.map