hive-intelligence 1.15.0 → 1.16.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.
Files changed (28) hide show
  1. package/build/{api-client-POBN6Y5S.js → api-client-MK3CVNCH.js} +2 -2
  2. package/build/{auth-6XVL5CE3.js → auth-TZQC54EJ.js} +1 -1
  3. package/build/{call-args-BUB6YNHW.js → call-args-4YRVKOLV.js} +2 -2
  4. package/build/{chunk-ZSPPJW4G.js → chunk-4U4IL5KA.js} +15 -1
  5. package/build/{chunk-762ZUJ4Q.js → chunk-6M6O3DZM.js} +1 -1
  6. package/build/{chunk-GNZGLVFE.js → chunk-757ZNB6W.js} +468 -444
  7. package/build/{chunk-KQVPKTEO.js → chunk-AVTIJGWS.js} +2 -2
  8. package/build/chunk-MYSS5SBE.js +71 -0
  9. package/build/{chunk-YLHNUAFT.js → chunk-O5YKCM67.js} +22 -6
  10. package/build/{chunk-APBLB62S.js → chunk-PODCJTBV.js} +1 -1
  11. package/build/{chunk-RNVZIPNY.js → chunk-VO6NWVJD.js} +1 -1
  12. package/build/{chunk-AZFOTKS2.js → chunk-WZ2NMSV3.js} +1 -1
  13. package/build/cli.js +31 -29
  14. package/build/{doctor-25WPHR4J.js → doctor-SP73PMX2.js} +4 -4
  15. package/build/{errors-YQAVCXXO.js → errors-BPXK3KCR.js} +1 -1
  16. package/build/{feedback-G2DFCCI6.js → feedback-6XX2R75U.js} +2 -2
  17. package/build/{init-all-UDWHV2ER.js → init-all-XDQRGJ3D.js} +1 -1
  18. package/build/{mcpServer-O4KXRE62.js → mcpServer-4JE5FTVP.js} +2 -1
  19. package/build/monitor-worker.js +3 -2
  20. package/build/release.json +4 -4
  21. package/build/{routing-4VKAVRYR.js → routing-S7DPEROC.js} +2 -2
  22. package/build/{serve-V2KPPJCD.js → serve-YV4RZIK5.js} +6 -4
  23. package/build/server.js +116 -105
  24. package/build/stdio.js +2 -1
  25. package/build/{tools-K2P77L4T.js → tools-NSHQSUIK.js} +5 -5
  26. package/build/{uninstall-I6ERJ2ED.js → uninstall-CECLA5YZ.js} +2 -2
  27. package/build/{watch-BUSEPVDM.js → watch-4VHBLAL6.js} +3 -3
  28. package/package.json +22 -31
@@ -5,63 +5,20 @@ import {
5
5
  import {
6
6
  OAUTH_FIRST_MATERIAL_RECEIPT_EVENT
7
7
  } from "./chunk-EPF36Q3Z.js";
8
+ import {
9
+ getCsvEnv,
10
+ getEnvVar,
11
+ getLogLevel,
12
+ getNodeEnv,
13
+ getRequiredEnvVar,
14
+ hasEnvVars,
15
+ loadEnvFile
16
+ } from "./chunk-MYSS5SBE.js";
8
17
  import {
9
18
  SERVER_NAME,
10
19
  SERVER_VERSION
11
20
  } from "./chunk-ZXKFJQDE.js";
12
21
 
13
- // src/mcpServer.ts
14
- import dotenv from "dotenv";
15
-
16
- // src/config/env.ts
17
- import { z } from "zod";
18
- var nodeEnvSchema = z.enum(["development", "production", "test"]).catch("development");
19
- var logLevelSchema = z.enum(["debug", "info", "warn", "error"]).catch("info");
20
- var portSchema = z.coerce.number().int().min(1).max(65535);
21
- var rateLimitMaxSchema = z.coerce.number().int().min(1).max(1e4);
22
- function getEnvVar(name) {
23
- const value = process.env[name]?.trim();
24
- return value ? value : void 0;
25
- }
26
- function getRequiredEnvVar(name, message) {
27
- const value = getEnvVar(name);
28
- if (!value) {
29
- throw new Error(message ?? `Missing required environment variable: ${name}`);
30
- }
31
- return value;
32
- }
33
- function hasEnvVars(...names) {
34
- return names.every((name) => Boolean(getEnvVar(name)));
35
- }
36
- function getCsvEnv(name) {
37
- const value = getEnvVar(name);
38
- if (!value) return [];
39
- return value.split(",").map((part) => part.trim()).filter(Boolean);
40
- }
41
- function getNodeEnv() {
42
- return nodeEnvSchema.parse(process.env.NODE_ENV);
43
- }
44
- function isProduction() {
45
- return getNodeEnv() === "production";
46
- }
47
- function getLogLevel() {
48
- return logLevelSchema.parse(process.env.LOG_LEVEL);
49
- }
50
- function getPort() {
51
- return portSchema.parse(process.env.PORT ?? 8080);
52
- }
53
- function getRateLimitMax() {
54
- return rateLimitMaxSchema.parse(process.env.RATE_LIMIT_MAX ?? 30);
55
- }
56
- function getCredentialedRateLimitMax() {
57
- return rateLimitMaxSchema.parse(
58
- process.env.CREDENTIALED_RATE_LIMIT_MAX ?? 1500
59
- );
60
- }
61
- function getCorsAllowedOrigins() {
62
- return getCsvEnv("CORS_ALLOWED_ORIGINS");
63
- }
64
-
65
22
  // src/tools/types.ts
66
23
  function asTextContentResult(result2, isError = false) {
67
24
  const jsonString = JSON.stringify(result2);
@@ -18634,65 +18591,161 @@ var wrapper = {
18634
18591
  ]
18635
18592
  };
18636
18593
 
18637
- // src/tools/defillamaTools/api/defillama.ts
18638
- import axios from "axios";
18639
-
18640
- // src/tools/defillamaTools/utils/logger.ts
18641
- import winston from "winston";
18642
- var loggerInstance = null;
18643
- function setupLogger() {
18644
- if (loggerInstance) {
18645
- return loggerInstance;
18646
- }
18647
- const logFormat = winston.format.combine(
18648
- winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
18649
- winston.format.errors({ stack: true }),
18650
- winston.format.splat(),
18651
- winston.format.json()
18652
- );
18653
- const consoleFormat = winston.format.combine(
18654
- winston.format.colorize(),
18655
- winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
18656
- winston.format.printf(({ timestamp, level, message, ...metadata103 }) => {
18657
- let msg = `${timestamp} [${level}]: ${message}`;
18658
- if (Object.keys(metadata103).length > 0) {
18659
- msg += ` ${JSON.stringify(metadata103)}`;
18660
- }
18661
- return msg;
18662
- })
18663
- );
18664
- const logger = winston.createLogger({
18665
- level: process.env.LOG_LEVEL || "info",
18666
- format: logFormat,
18667
- transports: [
18668
- // Console transport for development
18669
- new winston.transports.Console({
18670
- format: consoleFormat,
18671
- handleExceptions: true
18672
- })
18673
- ]
18674
- });
18675
- if (process.env.NODE_ENV === "production" && !process.env.VERCEL) {
18676
- logger.add(
18677
- new winston.transports.File({
18678
- filename: "logs/error.log",
18679
- level: "error",
18680
- maxsize: 5242880,
18681
- // 5MB
18682
- maxFiles: 5
18683
- })
18684
- );
18685
- logger.add(
18686
- new winston.transports.File({
18687
- filename: "logs/combined.log",
18688
- maxsize: 5242880,
18689
- // 5MB
18690
- maxFiles: 5
18691
- })
18692
- );
18594
+ // src/utils/fetchClient.ts
18595
+ var HttpError = class extends Error {
18596
+ config;
18597
+ constructor(message, config2, code, response) {
18598
+ super(message);
18599
+ this.name = "HttpError";
18600
+ this.config = config2;
18601
+ if (code) this.code = code;
18602
+ if (response) this.response = response;
18603
+ }
18604
+ };
18605
+ function encode(value) {
18606
+ return encodeURIComponent(value).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+");
18607
+ }
18608
+ function appendParam(pairs, key, value) {
18609
+ if (value === null || value === void 0) return;
18610
+ if (Array.isArray(value)) {
18611
+ for (const item of value) appendParam(pairs, `${key}[]`, item);
18612
+ } else if (value instanceof Date) {
18613
+ pairs.push(`${encode(key)}=${encode(value.toISOString())}`);
18614
+ } else if (typeof value === "object") {
18615
+ for (const [sub, item] of Object.entries(value)) {
18616
+ appendParam(pairs, `${key}[${sub}]`, item);
18617
+ }
18618
+ } else {
18619
+ pairs.push(`${encode(key)}=${encode(String(value))}`);
18620
+ }
18621
+ }
18622
+ function buildUrl(baseURL, url, params) {
18623
+ const full = !baseURL || /^[a-z][a-z\d+.-]*:\/\//i.test(url) ? url : url ? `${baseURL.replace(/\/+$/, "")}/${url.replace(/^\/+/, "")}` : baseURL;
18624
+ const pairs = [];
18625
+ for (const [key, value] of Object.entries(params ?? {})) {
18626
+ appendParam(pairs, key, value);
18627
+ }
18628
+ if (pairs.length === 0) return full;
18629
+ return `${full}${full.includes("?") ? "&" : "?"}${pairs.join("&")}`;
18630
+ }
18631
+ var UNDICI_CODES = {
18632
+ UND_ERR_CONNECT_TIMEOUT: "ETIMEDOUT",
18633
+ UND_ERR_HEADERS_TIMEOUT: "ETIMEDOUT",
18634
+ UND_ERR_BODY_TIMEOUT: "ETIMEDOUT",
18635
+ UND_ERR_SOCKET: "ECONNRESET"
18636
+ };
18637
+ function networkError(error, timedOut, timeout, config2) {
18638
+ if (timedOut) {
18639
+ return new HttpError(`timeout of ${timeout}ms exceeded`, config2, "ECONNABORTED");
18640
+ }
18641
+ const cause = error?.cause;
18642
+ const rawCode = cause?.code;
18643
+ const code = (rawCode && UNDICI_CODES[rawCode]) ?? rawCode ?? "ERR_NETWORK";
18644
+ return new HttpError(cause?.message || rawCode || "Network Error", config2, code);
18645
+ }
18646
+ async function readBody(response, maxContentLength, config2, onChunk) {
18647
+ if (!response.body) return "";
18648
+ const reader = response.body.getReader();
18649
+ const chunks = [];
18650
+ let size = 0;
18651
+ for (; ; ) {
18652
+ const { done, value } = await reader.read();
18653
+ if (done) break;
18654
+ onChunk();
18655
+ size += value.byteLength;
18656
+ if (maxContentLength && size > maxContentLength) {
18657
+ await reader.cancel();
18658
+ throw new HttpError(
18659
+ `maxContentLength size of ${maxContentLength} exceeded`,
18660
+ config2,
18661
+ "ERR_BAD_RESPONSE"
18662
+ );
18663
+ }
18664
+ chunks.push(value);
18693
18665
  }
18694
- loggerInstance = logger;
18695
- return loggerInstance;
18666
+ return new TextDecoder().decode(Buffer.concat(chunks));
18667
+ }
18668
+ function parseBody(text) {
18669
+ if (!text) return text;
18670
+ try {
18671
+ return JSON.parse(text);
18672
+ } catch {
18673
+ return text;
18674
+ }
18675
+ }
18676
+ function createFetchClient(options = {}) {
18677
+ async function request(method, url, data, config2 = {}) {
18678
+ const info = { method, url };
18679
+ const timeout = config2.timeout ?? options.timeout ?? 0;
18680
+ const controller = new AbortController();
18681
+ let timedOut = false;
18682
+ let timer;
18683
+ const armTimeout = () => {
18684
+ clearTimeout(timer);
18685
+ if (timeout <= 0) return;
18686
+ timer = setTimeout(() => {
18687
+ timedOut = true;
18688
+ controller.abort();
18689
+ }, timeout);
18690
+ };
18691
+ armTimeout();
18692
+ try {
18693
+ options.onRequest?.({ method, url, data });
18694
+ const headers = {
18695
+ Accept: "application/json, text/plain, */*",
18696
+ ...options.headers,
18697
+ ...config2.headers
18698
+ };
18699
+ let body;
18700
+ if (data !== void 0) {
18701
+ body = typeof data === "string" ? data : JSON.stringify(data);
18702
+ const hasContentType = Object.keys(headers).some(
18703
+ (name) => name.toLowerCase() === "content-type"
18704
+ );
18705
+ if (!hasContentType) headers["Content-Type"] = "application/json";
18706
+ }
18707
+ let text;
18708
+ let res;
18709
+ try {
18710
+ res = await fetch(buildUrl(options.baseURL, url, config2.params), {
18711
+ method: method.toUpperCase(),
18712
+ headers,
18713
+ body,
18714
+ signal: controller.signal
18715
+ });
18716
+ armTimeout();
18717
+ text = await readBody(res, options.maxContentLength, info, armTimeout);
18718
+ } catch (error) {
18719
+ if (error instanceof HttpError) throw error;
18720
+ throw networkError(error, timedOut, timeout, info);
18721
+ }
18722
+ const response = {
18723
+ data: parseBody(text),
18724
+ status: res.status,
18725
+ headers: Object.fromEntries(res.headers)
18726
+ };
18727
+ if (res.status < 200 || res.status >= 300) {
18728
+ throw new HttpError(
18729
+ `Request failed with status code ${res.status}`,
18730
+ info,
18731
+ res.status < 500 ? "ERR_BAD_REQUEST" : "ERR_BAD_RESPONSE",
18732
+ response
18733
+ );
18734
+ }
18735
+ return response;
18736
+ } catch (error) {
18737
+ options.onError?.(error);
18738
+ throw error;
18739
+ } finally {
18740
+ clearTimeout(timer);
18741
+ }
18742
+ }
18743
+ return {
18744
+ get: (url, config2) => request("get", url, void 0, config2),
18745
+ post: (url, data, config2) => request("post", url, data, config2),
18746
+ put: (url, data, config2) => request("put", url, data, config2),
18747
+ delete: (url, config2) => request("delete", url, void 0, config2)
18748
+ };
18696
18749
  }
18697
18750
 
18698
18751
  // src/tools/defillamaTools/api/defillama.ts
@@ -18701,69 +18754,60 @@ var DeFiLlamaAPI = class {
18701
18754
  stablecoinsClient;
18702
18755
  yieldsClient;
18703
18756
  coinsClient;
18704
- logger = setupLogger();
18757
+ logger = secureLogger;
18705
18758
  baseURL = "https://api.llama.fi";
18706
18759
  stablecoinsURL = "https://stablecoins.llama.fi";
18707
18760
  yieldsURL = "https://yields.llama.fi";
18708
18761
  coinsURL = "https://coins.llama.fi";
18709
18762
  constructor() {
18710
- this.client = axios.create({
18763
+ const errorHandler = (error) => {
18764
+ const status = error.response?.status;
18765
+ const message = error.response?.data?.message || error.message;
18766
+ if (status === 402) {
18767
+ throw new Error(
18768
+ `DeFiLlama API Error: this endpoint requires a DeFiLlama Pro plan subscription (HTTP 402); retrying on the free API will not succeed. ${message}`
18769
+ );
18770
+ }
18771
+ throw new Error(`DeFiLlama API Error: ${message}`);
18772
+ };
18773
+ this.client = createFetchClient({
18711
18774
  baseURL: this.baseURL,
18712
18775
  timeout: 6e4,
18713
18776
  // Increased from 30s to 60s for large responses
18714
18777
  headers: {
18715
18778
  "Content-Type": "application/json",
18716
18779
  "User-Agent": "defillama-mcp-server/1.0.0"
18717
- }
18780
+ },
18781
+ onError: errorHandler
18718
18782
  });
18719
- this.stablecoinsClient = axios.create({
18783
+ this.stablecoinsClient = createFetchClient({
18720
18784
  baseURL: this.stablecoinsURL,
18721
18785
  timeout: 3e4,
18722
18786
  // Reduced to 30s for MCP production
18723
18787
  headers: {
18724
18788
  "Content-Type": "application/json",
18725
18789
  "User-Agent": "defillama-mcp-server/1.0.0"
18726
- }
18790
+ },
18791
+ onError: errorHandler
18727
18792
  });
18728
- this.yieldsClient = axios.create({
18793
+ this.yieldsClient = createFetchClient({
18729
18794
  baseURL: this.yieldsURL,
18730
18795
  timeout: 6e4,
18731
18796
  headers: {
18732
18797
  "Content-Type": "application/json",
18733
18798
  "User-Agent": "defillama-mcp-server/1.0.0"
18734
- }
18799
+ },
18800
+ onError: errorHandler
18735
18801
  });
18736
- this.coinsClient = axios.create({
18802
+ this.coinsClient = createFetchClient({
18737
18803
  baseURL: this.coinsURL,
18738
18804
  timeout: 3e4,
18739
18805
  headers: {
18740
18806
  "Content-Type": "application/json",
18741
18807
  "User-Agent": "defillama-mcp-server/1.0.0"
18742
- }
18808
+ },
18809
+ onError: errorHandler
18743
18810
  });
18744
- const errorHandler = (error) => {
18745
- const status = error.response?.status;
18746
- const message = error.response?.data?.message || error.message;
18747
- if (status === 402) {
18748
- throw new Error(
18749
- `DeFiLlama API Error: this endpoint requires a DeFiLlama Pro plan subscription (HTTP 402); retrying on the free API will not succeed. ${message}`
18750
- );
18751
- }
18752
- throw new Error(`DeFiLlama API Error: ${message}`);
18753
- };
18754
- this.client.interceptors.response.use((response) => response, errorHandler);
18755
- this.stablecoinsClient.interceptors.response.use(
18756
- (response) => response,
18757
- errorHandler
18758
- );
18759
- this.yieldsClient.interceptors.response.use(
18760
- (response) => response,
18761
- errorHandler
18762
- );
18763
- this.coinsClient.interceptors.response.use(
18764
- (response) => response,
18765
- errorHandler
18766
- );
18767
18811
  }
18768
18812
  /**
18769
18813
  * Helper method to log API calls with timing and response details
@@ -19424,7 +19468,7 @@ var DeFiLlamaAPI = class {
19424
19468
  });
19425
19469
  return response.data;
19426
19470
  } catch (error) {
19427
- if (axios.isAxiosError(error)) {
19471
+ if (error instanceof HttpError) {
19428
19472
  if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") {
19429
19473
  throw new Error(
19430
19474
  `Timeout while fetching DEX volume data for ${dexName}. The response may be too large.`
@@ -31492,9 +31536,6 @@ function getAllCCXTEndpoints() {
31492
31536
  }
31493
31537
 
31494
31538
  // src/utils/httpClient.ts
31495
- import axios2, {
31496
- AxiosError
31497
- } from "axios";
31498
31539
  var circuitBreakers = /* @__PURE__ */ new Map();
31499
31540
  function getCircuitBreaker(serviceName) {
31500
31541
  if (!circuitBreakers.has(serviceName)) {
@@ -31526,7 +31567,7 @@ function upstreamDetail(error) {
31526
31567
  return compact ? compact.slice(0, 240) : null;
31527
31568
  }
31528
31569
  function withUpstreamDetail(error) {
31529
- if (!(error instanceof AxiosError)) return error;
31570
+ if (!(error instanceof HttpError)) return error;
31530
31571
  const detail = upstreamDetail(error);
31531
31572
  if (detail && !error.message.includes(detail)) {
31532
31573
  error.message = `${error.message}: ${detail}`;
@@ -31535,7 +31576,7 @@ function withUpstreamDetail(error) {
31535
31576
  }
31536
31577
  function failureMessage(error) {
31537
31578
  let message = "";
31538
- if (error instanceof AxiosError) {
31579
+ if (error instanceof HttpError) {
31539
31580
  message = upstreamDetail(error) ?? error.message;
31540
31581
  } else if (error instanceof Error) {
31541
31582
  message = error.message;
@@ -31568,7 +31609,7 @@ function sleep(ms) {
31568
31609
  return new Promise((resolve) => setTimeout(resolve, ms));
31569
31610
  }
31570
31611
  var ResilientHttpClient = class {
31571
- axiosInstance;
31612
+ http;
31572
31613
  config;
31573
31614
  circuitBreaker;
31574
31615
  constructor(config2) {
@@ -31584,10 +31625,10 @@ var ResilientHttpClient = class {
31584
31625
  circuitBreakerThreshold: config2.circuitBreakerThreshold ?? 5,
31585
31626
  circuitBreakerResetTimeout: config2.circuitBreakerResetTimeout ?? 3e4
31586
31627
  };
31587
- this.axiosInstance = axios2.create({
31628
+ this.http = createFetchClient({
31588
31629
  baseURL: this.config.baseURL,
31589
31630
  timeout: this.config.timeout,
31590
- ...config2.maxContentLength ? { maxContentLength: config2.maxContentLength } : {},
31631
+ maxContentLength: config2.maxContentLength,
31591
31632
  headers: {
31592
31633
  "Content-Type": "application/json",
31593
31634
  Accept: "application/json",
@@ -31595,35 +31636,28 @@ var ResilientHttpClient = class {
31595
31636
  }
31596
31637
  });
31597
31638
  this.circuitBreaker = getCircuitBreaker(this.config.serviceName);
31598
- this.axiosInstance.interceptors.request.use(
31599
- (requestConfig) => {
31600
- secureLogger.debug(`[${this.config.serviceName}] Request`, {
31601
- method: requestConfig.method?.toUpperCase(),
31602
- url: requestConfig.url,
31603
- params: requestConfig.params
31604
- });
31605
- return requestConfig;
31606
- },
31607
- (error) => {
31608
- secureLogger.error(
31609
- `[${this.config.serviceName}] Request setup failed`,
31610
- error
31611
- );
31612
- return Promise.reject(error);
31613
- }
31614
- );
31615
- this.axiosInstance.interceptors.response.use(
31616
- (response) => {
31617
- secureLogger.debug(`[${this.config.serviceName}] Response`, {
31618
- status: response.status,
31619
- url: response.config.url
31620
- });
31621
- return response;
31622
- },
31623
- (error) => {
31624
- return Promise.reject(error);
31625
- }
31626
- );
31639
+ }
31640
+ /**
31641
+ * Send one request, with debug logging on either side. Failures are logged
31642
+ * by the retry logic.
31643
+ */
31644
+ async send(method, endpoint, options) {
31645
+ secureLogger.debug(`[${this.config.serviceName}] Request`, {
31646
+ method: method.toUpperCase(),
31647
+ url: endpoint,
31648
+ params: options.params
31649
+ });
31650
+ const config2 = {
31651
+ params: options.params,
31652
+ timeout: options.timeout ?? this.config.timeout,
31653
+ headers: options.headers
31654
+ };
31655
+ const response = method === "get" || method === "delete" ? await this.http[method](endpoint, config2) : await this.http[method](endpoint, options.body, config2);
31656
+ secureLogger.debug(`[${this.config.serviceName}] Response`, {
31657
+ status: response.status,
31658
+ url: endpoint
31659
+ });
31660
+ return response;
31627
31661
  }
31628
31662
  /**
31629
31663
  * Check if the circuit breaker allows the request
@@ -31706,7 +31740,7 @@ var ResilientHttpClient = class {
31706
31740
  return response.data;
31707
31741
  } catch (error) {
31708
31742
  lastError = error;
31709
- if (error instanceof AxiosError && isRetryableError(error)) {
31743
+ if (error instanceof HttpError && isRetryableError(error)) {
31710
31744
  this.recordFailure(error);
31711
31745
  if (attempt < maxRetries) {
31712
31746
  const delay2 = calculateBackoffDelay(
@@ -31727,7 +31761,7 @@ var ResilientHttpClient = class {
31727
31761
  continue;
31728
31762
  }
31729
31763
  } else {
31730
- if (error instanceof AxiosError) {
31764
+ if (error instanceof HttpError) {
31731
31765
  const status = error.response?.status ?? 0;
31732
31766
  const oversized = error.message.includes("maxContentLength");
31733
31767
  if (!status && !oversized || status >= 500 || status === 429) {
@@ -31735,7 +31769,7 @@ var ResilientHttpClient = class {
31735
31769
  }
31736
31770
  }
31737
31771
  }
31738
- const errorDetails = error instanceof AxiosError ? {
31772
+ const errorDetails = error instanceof HttpError ? {
31739
31773
  status: error.response?.status,
31740
31774
  code: error.code,
31741
31775
  message: error.message,
@@ -31757,13 +31791,8 @@ var ResilientHttpClient = class {
31757
31791
  * Perform a GET request
31758
31792
  */
31759
31793
  async get(endpoint, options = {}) {
31760
- const config2 = {
31761
- params: options.params,
31762
- timeout: options.timeout ?? this.config.timeout,
31763
- headers: options.headers
31764
- };
31765
31794
  return this.executeWithRetry(
31766
- () => this.axiosInstance.get(endpoint, config2),
31795
+ () => this.send("get", endpoint, options),
31767
31796
  options
31768
31797
  );
31769
31798
  }
@@ -31771,13 +31800,8 @@ var ResilientHttpClient = class {
31771
31800
  * Perform a POST request
31772
31801
  */
31773
31802
  async post(endpoint, options = {}) {
31774
- const config2 = {
31775
- params: options.params,
31776
- timeout: options.timeout ?? this.config.timeout,
31777
- headers: options.headers
31778
- };
31779
31803
  return this.executeWithRetry(
31780
- () => this.axiosInstance.post(endpoint, options.body, config2),
31804
+ () => this.send("post", endpoint, options),
31781
31805
  options
31782
31806
  );
31783
31807
  }
@@ -31785,13 +31809,8 @@ var ResilientHttpClient = class {
31785
31809
  * Perform a PUT request
31786
31810
  */
31787
31811
  async put(endpoint, options = {}) {
31788
- const config2 = {
31789
- params: options.params,
31790
- timeout: options.timeout ?? this.config.timeout,
31791
- headers: options.headers
31792
- };
31793
31812
  return this.executeWithRetry(
31794
- () => this.axiosInstance.put(endpoint, options.body, config2),
31813
+ () => this.send("put", endpoint, options),
31795
31814
  options
31796
31815
  );
31797
31816
  }
@@ -31799,13 +31818,8 @@ var ResilientHttpClient = class {
31799
31818
  * Perform a DELETE request
31800
31819
  */
31801
31820
  async delete(endpoint, options = {}) {
31802
- const config2 = {
31803
- params: options.params,
31804
- timeout: options.timeout ?? this.config.timeout,
31805
- headers: options.headers
31806
- };
31807
31821
  return this.executeWithRetry(
31808
- () => this.axiosInstance.delete(endpoint, config2),
31822
+ () => this.send("delete", endpoint, options),
31809
31823
  options
31810
31824
  );
31811
31825
  }
@@ -38764,7 +38778,6 @@ function removedVenueMessage(venue) {
38764
38778
  }
38765
38779
 
38766
38780
  // src/tools/hyperliquid/api/hyperliquid.ts
38767
- import axios3 from "axios";
38768
38781
  var HYPERLIQUID_API_URL = "https://api.hyperliquid.xyz";
38769
38782
  var DEFAULT_LEADERBOARD_LIMIT = 20;
38770
38783
  var MAX_LEADERBOARD_LIMIT = 500;
@@ -38785,30 +38798,27 @@ var HyperliquidAPI = class {
38785
38798
  now;
38786
38799
  constructor(now = Date.now) {
38787
38800
  this.now = now;
38788
- this.client = axios3.create({
38801
+ this.client = createFetchClient({
38789
38802
  baseURL: HYPERLIQUID_API_URL,
38790
38803
  timeout: 3e4,
38791
38804
  headers: {
38792
38805
  "Content-Type": "application/json",
38793
38806
  "User-Agent": "hive-mcp-server/1.0.0"
38794
- }
38795
- });
38796
- this.client.interceptors.request.use((config2) => {
38797
- const dex = config2.data?.dex;
38798
- if (typeof dex === "string" && REMOVED_HYPERLIQUID_DEXES.has(dex)) {
38799
- throw new Error(removedVenueMessage(`hyperliquid:${dex}`));
38800
- }
38801
- return config2;
38802
- });
38803
- this.client.interceptors.response.use(
38804
- (response) => response,
38805
- (error) => {
38807
+ },
38808
+ // One gate for every /info read that scopes to a builder dex.
38809
+ onRequest: ({ data }) => {
38810
+ const dex = data?.dex;
38811
+ if (typeof dex === "string" && REMOVED_HYPERLIQUID_DEXES.has(dex)) {
38812
+ throw new Error(removedVenueMessage(`hyperliquid:${dex}`));
38813
+ }
38814
+ },
38815
+ onError: (error) => {
38806
38816
  const err = error;
38807
38817
  const message = err?.response?.data?.message || err?.message || "request failed";
38808
38818
  secureLogger.warn("Hyperliquid API error", { message });
38809
38819
  throw new Error(`Hyperliquid API Error: ${message}`);
38810
38820
  }
38811
- );
38821
+ });
38812
38822
  }
38813
38823
  /**
38814
38824
  * Per-pair 24h notional volume leaderboard for a Hyperliquid perp DEX.
@@ -41736,7 +41746,7 @@ async function probeExtremes(query, dataset, baseCoin) {
41736
41746
  const where = baseCoin ? " WHERE base_coin = {base_coin:String}" : "";
41737
41747
  try {
41738
41748
  const [row] = await query(
41739
- `SELECT minOrNull(${spec.tsColumn}) AS earliest_at, maxOrNull(${spec.tsColumn}) AS latest_at FROM ${spec.table} FINAL${where}`,
41749
+ `SELECT minOrNull(${spec.tsColumn}) AS earliest_at, maxOrNull(${spec.tsColumn}) AS latest_at FROM ${spec.table}${where}`,
41740
41750
  baseCoin ? { base_coin: baseCoin } : {}
41741
41751
  );
41742
41752
  return {
@@ -41753,7 +41763,7 @@ async function probeExtremes(query, dataset, baseCoin) {
41753
41763
  async function listFundingVenues(query) {
41754
41764
  try {
41755
41765
  const rows = await query(
41756
- `SELECT DISTINCT venue FROM ${HISTORY_TABLES.funding.table} FINAL ORDER BY venue LIMIT ${VENUE_LIST_MAX + 1}`
41766
+ `SELECT DISTINCT venue FROM ${HISTORY_TABLES.funding.table} ORDER BY venue LIMIT ${VENUE_LIST_MAX + 1}`
41757
41767
  );
41758
41768
  const venues = rows.map((row) => row.venue).filter((venue) => typeof venue === "string");
41759
41769
  return {
@@ -42164,7 +42174,7 @@ var PolymarketNotFoundError = class extends Error {
42164
42174
  }
42165
42175
  url;
42166
42176
  };
42167
- function buildUrl(base, path, params = {}) {
42177
+ function buildUrl2(base, path, params = {}) {
42168
42178
  const url = new URL(path, base);
42169
42179
  for (const [key, value] of Object.entries(params)) {
42170
42180
  if (value === void 0) continue;
@@ -42803,7 +42813,7 @@ function toActivityRow(raw) {
42803
42813
  }
42804
42814
  async function fetchGammaKeyset(resource, params) {
42805
42815
  const label = `Gamma /${resource}/keyset`;
42806
- const url = buildUrl(GAMMA_BASE_URL, `/${resource}/keyset`, params);
42816
+ const url = buildUrl2(GAMMA_BASE_URL, `/${resource}/keyset`, params);
42807
42817
  const page = asRecord(await fetchPolymarketJson(url, label));
42808
42818
  return {
42809
42819
  url,
@@ -42831,7 +42841,7 @@ function parseDataPage(value, label) {
42831
42841
  };
42832
42842
  }
42833
42843
  async function searchGammaMarkets(query, closed) {
42834
- const url = buildUrl(GAMMA_BASE_URL, "/public-search", {
42844
+ const url = buildUrl2(GAMMA_BASE_URL, "/public-search", {
42835
42845
  q: query,
42836
42846
  limit_per_type: SEARCH_EVENT_LIMIT,
42837
42847
  events_status: closed ? "closed" : "active"
@@ -42869,7 +42879,7 @@ async function resolveMarket(selector) {
42869
42879
  if (gamma.rows.length > 0) {
42870
42880
  return { url: gamma.url, market: normalizeGammaMarket(gamma.rows[0]) };
42871
42881
  }
42872
- const clobUrl = buildUrl(
42882
+ const clobUrl = buildUrl2(
42873
42883
  CLOB_BASE_URL,
42874
42884
  `/clob-markets/${selector.conditionId}`
42875
42885
  );
@@ -42895,7 +42905,7 @@ async function resolveMarket(selector) {
42895
42905
  }
42896
42906
  }
42897
42907
  async function fetchOrderbook(tokenId) {
42898
- const url = buildUrl(CLOB_BASE_URL, "/book", { token_id: tokenId });
42908
+ const url = buildUrl2(CLOB_BASE_URL, "/book", { token_id: tokenId });
42899
42909
  try {
42900
42910
  const data = await fetchPolymarketJson(url, "CLOB /book");
42901
42911
  const raw = asRecord(data);
@@ -42921,11 +42931,11 @@ async function fetchPriceHistory(tokenId, interval, fidelity) {
42921
42931
  interval,
42922
42932
  bucket_seconds: fidelity * 60
42923
42933
  };
42924
- const url = buildUrl(DATA_API_BASE_URL, "/v2/prices-history", params);
42934
+ const url = buildUrl2(DATA_API_BASE_URL, "/v2/prices-history", params);
42925
42935
  const rows = [];
42926
42936
  let cursor = null;
42927
42937
  for (let page = 0; page < MAX_HISTORY_PAGES; page++) {
42928
- const pageUrl = cursor ? buildUrl(DATA_API_BASE_URL, "/v2/prices-history", {
42938
+ const pageUrl = cursor ? buildUrl2(DATA_API_BASE_URL, "/v2/prices-history", {
42929
42939
  ...params,
42930
42940
  cursor
42931
42941
  }) : url;
@@ -42943,7 +42953,7 @@ async function fetchPriceHistory(tokenId, interval, fidelity) {
42943
42953
  }
42944
42954
  async function fetchPositions(user, limit, cursor) {
42945
42955
  const label = "Data API /v2/positions";
42946
- const url = buildUrl(DATA_API_BASE_URL, "/v2/positions", {
42956
+ const url = buildUrl2(DATA_API_BASE_URL, "/v2/positions", {
42947
42957
  user,
42948
42958
  limit,
42949
42959
  cursor: cursor ?? void 0
@@ -42957,7 +42967,7 @@ async function fetchPositions(user, limit, cursor) {
42957
42967
  }
42958
42968
  async function fetchActivity(user, limit, cursor) {
42959
42969
  const label = "Data API /v2/activity";
42960
- const url = buildUrl(DATA_API_BASE_URL, "/v2/activity", {
42970
+ const url = buildUrl2(DATA_API_BASE_URL, "/v2/activity", {
42961
42971
  user,
42962
42972
  limit,
42963
42973
  cursor: cursor ?? void 0
@@ -43633,7 +43643,7 @@ var KalshiNotFoundError = class extends Error {
43633
43643
  }
43634
43644
  url;
43635
43645
  };
43636
- function buildUrl2(path, params = {}, base = KALSHI_BASE_URL) {
43646
+ function buildUrl3(path, params = {}, base = KALSHI_BASE_URL) {
43637
43647
  const url = new URL(`${base}${path}`);
43638
43648
  for (const [key, value] of Object.entries(params)) {
43639
43649
  if (value === void 0) continue;
@@ -44208,7 +44218,7 @@ function readCursor(record) {
44208
44218
  return cursor;
44209
44219
  }
44210
44220
  async function fetchMarketsPage(params) {
44211
- const url = buildUrl2("/markets", params);
44221
+ const url = buildUrl3("/markets", params);
44212
44222
  const data = await fetchKalshiJson(url, "GET /markets");
44213
44223
  const record = asRecord2(data);
44214
44224
  return {
@@ -44268,7 +44278,7 @@ async function searchMarkets(filters) {
44268
44278
  };
44269
44279
  }
44270
44280
  async function fetchMarket(ticker) {
44271
- const url = buildUrl2(`/markets/${encodeURIComponent(ticker)}`);
44281
+ const url = buildUrl3(`/markets/${encodeURIComponent(ticker)}`);
44272
44282
  try {
44273
44283
  const data = await fetchKalshiJson(url, "GET /markets/{ticker}");
44274
44284
  const record = asRecord2(asRecord2(data)?.market);
@@ -44288,7 +44298,7 @@ async function fetchMarket(ticker) {
44288
44298
  }
44289
44299
  }
44290
44300
  async function fetchEventsPage(params) {
44291
- const url = buildUrl2("/events", {
44301
+ const url = buildUrl3("/events", {
44292
44302
  status: params.status ?? void 0,
44293
44303
  series_ticker: params.seriesTicker ?? void 0,
44294
44304
  limit: params.limit,
@@ -44303,7 +44313,7 @@ async function fetchEventsPage(params) {
44303
44313
  return { url, rows, nextCursor: readCursor(record) };
44304
44314
  }
44305
44315
  async function fetchEvent(eventTicker, withNested) {
44306
- const url = buildUrl2(`/events/${encodeURIComponent(eventTicker)}`, {
44316
+ const url = buildUrl3(`/events/${encodeURIComponent(eventTicker)}`, {
44307
44317
  with_nested_markets: withNested ? true : void 0
44308
44318
  });
44309
44319
  try {
@@ -44326,7 +44336,7 @@ async function fetchEvent(eventTicker, withNested) {
44326
44336
  }
44327
44337
  }
44328
44338
  async function fetchOrderbook2(ticker, depth) {
44329
- const url = buildUrl2(`/markets/${encodeURIComponent(ticker)}/orderbook`);
44339
+ const url = buildUrl3(`/markets/${encodeURIComponent(ticker)}/orderbook`);
44330
44340
  try {
44331
44341
  const data = await fetchKalshiJson(
44332
44342
  url,
@@ -44349,7 +44359,7 @@ async function fetchOrderbook2(ticker, depth) {
44349
44359
  }
44350
44360
  }
44351
44361
  async function fetchTrades(ticker, limit, cursor) {
44352
- const url = buildUrl2("/markets/trades", {
44362
+ const url = buildUrl3("/markets/trades", {
44353
44363
  ticker,
44354
44364
  limit,
44355
44365
  cursor: cursor ?? void 0
@@ -44366,7 +44376,7 @@ async function assertMarketExists(ticker) {
44366
44376
  await fetchMarket(ticker);
44367
44377
  }
44368
44378
  async function fetchCandlesticks(seriesTicker, ticker, window) {
44369
- const url = buildUrl2(
44379
+ const url = buildUrl3(
44370
44380
  `/series/${encodeURIComponent(seriesTicker)}/markets/${encodeURIComponent(ticker)}/candlesticks`,
44371
44381
  {
44372
44382
  start_ts: window.start_ts,
@@ -47811,7 +47821,7 @@ async function assertHostResolvesPublic(host) {
47811
47821
  }
47812
47822
  }
47813
47823
  }
47814
- function buildUrl3(entry2, path, query) {
47824
+ function buildUrl4(entry2, path, query) {
47815
47825
  if (/^[a-z]+:\/\//i.test(path) || path.includes("@")) {
47816
47826
  throw new FetchInputError(
47817
47827
  `Invalid argument: path "${path}" must be a path on the host, not a full URL.`
@@ -47844,7 +47854,7 @@ async function fetchPublicApi(params) {
47844
47854
  `Method "${method}" is not supported for host "${entry2.host}" (allowed: ${entry2.methods.join(", ")}).`
47845
47855
  );
47846
47856
  }
47847
- const url = buildUrl3(entry2, params.path, params.query);
47857
+ const url = buildUrl4(entry2, params.path, params.query);
47848
47858
  await assertHostResolvesPublic(entry2.host);
47849
47859
  const headers = { Accept: "application/json" };
47850
47860
  let payload;
@@ -51409,11 +51419,11 @@ import { fileURLToPath } from "url";
51409
51419
  import Coingecko5 from "@coingecko/coingecko-typescript";
51410
51420
 
51411
51421
  // src/tools/dynamic-tools.ts
51412
- import { z as z4 } from "zod";
51422
+ import { z as z3 } from "zod";
51413
51423
  import { isDeepStrictEqual } from "util";
51414
51424
 
51415
51425
  // src/tools/heroTools.ts
51416
- import { z as z2 } from "zod";
51426
+ import { z } from "zod";
51417
51427
 
51418
51428
  // src/services/tool-execution-pipeline.ts
51419
51429
  import { randomUUID as randomUUID2 } from "crypto";
@@ -53940,7 +53950,7 @@ var HERO_TOOL_NAMES = /* @__PURE__ */ new Set([
53940
53950
  "check_token_safety",
53941
53951
  "get_wallet_portfolio"
53942
53952
  ]);
53943
- var RESPONSE_FORMAT = z2.enum(["concise", "detailed", "json", "markdown"]).optional().describe(
53953
+ var RESPONSE_FORMAT = z.enum(["concise", "detailed", "json", "markdown"]).optional().describe(
53944
53954
  "concise (default) returns the trimmed essentials; detailed returns the full provider payload. json and markdown, the platform-wide values every other tool advertises, are accepted and treated as concise."
53945
53955
  );
53946
53956
  function heroFormat(value) {
@@ -54203,15 +54213,15 @@ function heroTools(endpoints, options = {}) {
54203
54213
  source_receipt: sourceReceipt(result2)
54204
54214
  });
54205
54215
  };
54206
- const tokenPriceSchema = z2.object({
54207
- token: z2.string().trim().min(1).max(100).optional().describe(
54216
+ const tokenPriceSchema = z.object({
54217
+ token: z.string().trim().min(1).max(100).optional().describe(
54208
54218
  'CoinGecko coin id or ticker symbol, for example "bitcoin" or "BTC". Omit when passing chain + address.'
54209
54219
  ),
54210
- chain: z2.string().trim().max(40).optional().describe(
54220
+ chain: z.string().trim().max(40).optional().describe(
54211
54221
  'Chain name for the contract-address variant, for example "eth", "base", "bsc", or "solana".'
54212
54222
  ),
54213
- address: z2.string().trim().max(100).optional().describe("Token contract address; requires chain."),
54214
- vs_currency: z2.string().trim().max(20).optional().describe('Quote currency. Default "usd".'),
54223
+ address: z.string().trim().max(100).optional().describe("Token contract address; requires chain."),
54224
+ vs_currency: z.string().trim().max(20).optional().describe('Quote currency. Default "usd".'),
54215
54225
  response_format: RESPONSE_FORMAT
54216
54226
  });
54217
54227
  const trimSimplePrice = (query, vsCurrency) => (payload) => {
@@ -54318,11 +54328,11 @@ function heroTools(endpoints, options = {}) {
54318
54328
  );
54319
54329
  }
54320
54330
  };
54321
- const tokenSafetySchema = z2.object({
54322
- address: z2.string().trim().min(1).max(100).describe(
54331
+ const tokenSafetySchema = z.object({
54332
+ address: z.string().trim().min(1).max(100).describe(
54323
54333
  "Required. Token contract address (0x\u2026 for EVM, base58 for Solana)."
54324
54334
  ),
54325
- chain: z2.string().trim().max(40).optional().describe(
54335
+ chain: z.string().trim().max(40).optional().describe(
54326
54336
  'Chain name or EVM chain id, for example "eth", "bsc", "8453", or "solana". Defaults to eth for 0x addresses; Solana is auto-detected.'
54327
54337
  ),
54328
54338
  response_format: RESPONSE_FORMAT
@@ -54410,12 +54420,12 @@ function heroTools(endpoints, options = {}) {
54410
54420
  return respond(result2, format, trimTokenSafety(address, normalized));
54411
54421
  }
54412
54422
  };
54413
- const walletPortfolioSchema = z2.object({
54414
- address: z2.string().trim().min(1).max(100).describe("Required. Wallet address (0x\u2026 for EVM, base58 for Solana)."),
54415
- chain: z2.string().trim().max(40).optional().describe(
54423
+ const walletPortfolioSchema = z.object({
54424
+ address: z.string().trim().min(1).max(100).describe("Required. Wallet address (0x\u2026 for EVM, base58 for Solana)."),
54425
+ chain: z.string().trim().max(40).optional().describe(
54416
54426
  'Chain name, for example "eth", "base", "arbitrum", or "solana". Defaults to eth for 0x addresses; Solana is auto-detected.'
54417
54427
  ),
54418
- include_spam: z2.boolean().optional().describe(
54428
+ include_spam: z.boolean().optional().describe(
54419
54429
  "Show likely spam airdrops (tokens with a URL or claim lure in the name, and on EVM chains tokens with no market price). Default false; the response says how many were hidden."
54420
54430
  ),
54421
54431
  response_format: RESPONSE_FORMAT
@@ -57754,7 +57764,7 @@ function canonicalResource(value) {
57754
57764
 
57755
57765
  // src/auth/oauth/clients.ts
57756
57766
  import { randomUUID as randomUUID3 } from "crypto";
57757
- import { z as z3 } from "zod";
57767
+ import { z as z2 } from "zod";
57758
57768
  import { InvalidClientMetadataError } from "@modelcontextprotocol/sdk/server/auth/errors.js";
57759
57769
  var OAUTH_DEPLOYMENT_CANARY_SOFTWARE_ID = "xyz.hiveintelligence/deployment-canary";
57760
57770
  var OAUTH_DEPLOYMENT_CANARY_CLIENT_NAME = "Hive deployment OAuth canary";
@@ -57834,21 +57844,21 @@ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]
57834
57844
  var EXACT_NATIVE_REDIRECT_URIS = /* @__PURE__ */ new Set([
57835
57845
  CURSOR_DESKTOP_OAUTH_REDIRECT_URI
57836
57846
  ]);
57837
- var cimdDocumentSchema = z3.object({
57838
- client_id: z3.string().url(),
57839
- client_name: z3.string().trim().min(1).max(200),
57840
- redirect_uris: z3.array(z3.string().url()).min(1).max(20),
57841
- token_endpoint_auth_method: z3.literal("none").optional(),
57842
- grant_types: z3.array(z3.string()).max(4).optional(),
57843
- response_types: z3.array(z3.string()).max(4).optional(),
57844
- client_uri: z3.string().url().optional(),
57845
- logo_uri: z3.string().url().optional(),
57846
- scope: z3.string().max(1e3).optional(),
57847
- contacts: z3.array(z3.string().max(320)).max(10).optional(),
57848
- tos_uri: z3.string().url().optional(),
57849
- policy_uri: z3.string().url().optional(),
57850
- software_id: z3.string().max(200).optional(),
57851
- software_version: z3.string().max(100).optional()
57847
+ var cimdDocumentSchema = z2.object({
57848
+ client_id: z2.string().url(),
57849
+ client_name: z2.string().trim().min(1).max(200),
57850
+ redirect_uris: z2.array(z2.string().url()).min(1).max(20),
57851
+ token_endpoint_auth_method: z2.literal("none").optional(),
57852
+ grant_types: z2.array(z2.string()).max(4).optional(),
57853
+ response_types: z2.array(z2.string()).max(4).optional(),
57854
+ client_uri: z2.string().url().optional(),
57855
+ logo_uri: z2.string().url().optional(),
57856
+ scope: z2.string().max(1e3).optional(),
57857
+ contacts: z2.array(z2.string().max(320)).max(10).optional(),
57858
+ tos_uri: z2.string().url().optional(),
57859
+ policy_uri: z2.string().url().optional(),
57860
+ software_id: z2.string().max(200).optional(),
57861
+ software_version: z2.string().max(100).optional()
57852
57862
  }).strip();
57853
57863
  function registeredClientTtlSeconds(client2, configuredTtlSeconds) {
57854
57864
  return client2.software_id === OAUTH_DEPLOYMENT_CANARY_SOFTWARE_ID ? Math.min(
@@ -58270,41 +58280,41 @@ var HIVE_PROMPTS = [
58270
58280
  }
58271
58281
  ];
58272
58282
 
58273
- // src/services/unkey-service.ts
58274
- import { randomUUID as randomUUID4 } from "crypto";
58275
- var _unkey = null;
58283
+ // src/services/api-key-service.ts
58284
+ import { createHash as createHash6, randomInt, randomUUID as randomUUID4 } from "crypto";
58276
58285
  function getAuthBackendMode() {
58277
58286
  const mode = (getEnvVar("HIVE_AUTH_BACKEND") ?? "auto").toLowerCase();
58278
- if (mode === "unkey" || mode === "static" || mode === "auto") {
58279
- return mode;
58280
- }
58287
+ if (mode === "hosted" || mode === "unkey") return "hosted";
58288
+ if (mode === "static") return "static";
58281
58289
  return "auto";
58282
58290
  }
58283
- function isUnkeyRequired() {
58284
- return getAuthBackendMode() === "unkey";
58291
+ function isHostedKeysRequired() {
58292
+ return getAuthBackendMode() === "hosted";
58285
58293
  }
58286
- function hasUnkeyCredentials() {
58287
- return hasEnvVars("UNKEY_ROOT_KEY", "UNKEY_API_ID");
58294
+ function isHostedKeysConfigured() {
58295
+ return getAuthBackendMode() !== "static" && isSupabaseConfigured();
58288
58296
  }
58289
- function isUnkeyConfigured() {
58290
- return getAuthBackendMode() !== "static" && hasUnkeyCredentials();
58297
+ function isLegacyUnkeyConfigured() {
58298
+ return hasEnvVars("UNKEY_ROOT_KEY");
58291
58299
  }
58292
- async function getUnkey() {
58293
- if (!_unkey) {
58294
- if (!isUnkeyConfigured()) {
58295
- throw new Error(
58296
- "Unkey not configured. Set UNKEY_ROOT_KEY and UNKEY_API_ID."
58297
- );
58298
- }
58299
- const { Unkey: UnkeyClient } = await import("@unkey/api");
58300
- _unkey ??= new UnkeyClient({
58301
- rootKey: getRequiredEnvVar("UNKEY_ROOT_KEY")
58302
- });
58303
- }
58300
+ var _unkey = null;
58301
+ function legacyUnkey() {
58302
+ _unkey ??= createFetchClient({
58303
+ baseURL: "https://api.unkey.com/v2",
58304
+ timeout: 5e3,
58305
+ headers: { Authorization: `Bearer ${getEnvVar("UNKEY_ROOT_KEY")}` }
58306
+ });
58304
58307
  return _unkey;
58305
58308
  }
58306
- function getApiId() {
58307
- return getRequiredEnvVar("UNKEY_API_ID");
58309
+ var KEY_PREFIX = "hive_live_";
58310
+ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
58311
+ var START_LENGTH = KEY_PREFIX.length + 4;
58312
+ var BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
58313
+ function randomBase58(length) {
58314
+ return Array.from({ length }, () => BASE58[randomInt(BASE58.length)]).join("");
58315
+ }
58316
+ function hashKey(key) {
58317
+ return createHash6("sha256").update(key).digest("hex");
58308
58318
  }
58309
58319
  function normalizeAnalyticsTags(tags) {
58310
58320
  const normalized = /* @__PURE__ */ new Set();
@@ -58317,6 +58327,24 @@ function normalizeAnalyticsTags(tags) {
58317
58327
  }
58318
58328
  return [...normalized];
58319
58329
  }
58330
+ function withoutStalePlan(meta2) {
58331
+ if (!meta2) return void 0;
58332
+ const { plan: _stalePlan, ...rest } = meta2;
58333
+ return rest;
58334
+ }
58335
+ var VERIFY_CACHE_TTL_MS = 3e4;
58336
+ var VERIFY_CACHE_MAX = 1e4;
58337
+ var verifyCache = /* @__PURE__ */ new Map();
58338
+ function cacheVerified(keyHash, result2) {
58339
+ if (verifyCache.size >= VERIFY_CACHE_MAX) {
58340
+ const oldest = verifyCache.keys().next().value;
58341
+ if (oldest !== void 0) verifyCache.delete(oldest);
58342
+ }
58343
+ verifyCache.set(keyHash, {
58344
+ result: result2,
58345
+ expiresAt: Date.now() + VERIFY_CACHE_TTL_MS
58346
+ });
58347
+ }
58320
58348
  async function getPlan(planId) {
58321
58349
  const supabase = getSupabaseAdmin();
58322
58350
  const { data, error } = await supabase.from("plans").select("*").eq("id", planId).single();
@@ -58325,32 +58353,10 @@ async function getPlan(planId) {
58325
58353
  }
58326
58354
  return data;
58327
58355
  }
58328
- var KEYS_PAGE_LIMIT = 100;
58329
- var KEYS_MAX_PAGES = 100;
58330
- async function listAllUserKeysRaw(userId) {
58331
- const apiId = getApiId();
58332
- const all = [];
58333
- let cursor;
58334
- for (let page = 0; page < KEYS_MAX_PAGES; page += 1) {
58335
- const unkey = await getUnkey();
58336
- const result2 = await unkey.apis.listKeys({
58337
- apiId,
58338
- externalId: userId,
58339
- limit: KEYS_PAGE_LIMIT,
58340
- revalidateKeysCache: true,
58341
- ...cursor ? { cursor } : {}
58342
- });
58343
- const keys = Array.isArray(result2.result.data) ? result2.result.data : [];
58344
- all.push(...keys);
58345
- const pagination = result2.result.pagination;
58346
- if (!pagination?.hasMore || !pagination.cursor) break;
58347
- cursor = pagination.cursor;
58348
- }
58349
- return all;
58350
- }
58351
58356
  async function countActiveUserKeys(userId) {
58352
- const keys = await listAllUserKeysRaw(userId);
58353
- return keys.filter((k) => k.enabled !== false).length;
58357
+ const { count, error } = await getSupabaseAdmin().from("api_keys").select("id", { count: "exact", head: true }).eq("user_id", userId).eq("enabled", true);
58358
+ if (error) throw new Error(`Counting API keys failed: ${error.message}`);
58359
+ return count ?? 0;
58354
58360
  }
58355
58361
  var KEY_CREATION_LEASE_TTL_SECONDS = 120;
58356
58362
  var KEY_CREATION_LEASE_WAIT_MS = 1e4;
@@ -58406,82 +58412,114 @@ async function createApiKey(opts) {
58406
58412
  subject_signing_secret: subjectSigningSecret
58407
58413
  } : {}
58408
58414
  };
58409
- const unkey = await getUnkey();
58410
- const result2 = await unkey.keys.createKey({
58411
- apiId: getApiId(),
58412
- prefix: "hive_live",
58415
+ const key = KEY_PREFIX + randomBase58(33);
58416
+ const keyId = `key_${randomBase58(16)}`;
58417
+ const { error } = await getSupabaseAdmin().from("api_keys").insert({
58418
+ id: keyId,
58419
+ user_id: opts.userId,
58413
58420
  name: opts.name,
58414
- byteLength: 24,
58415
- externalId: opts.userId,
58416
- meta: meta2,
58417
- enabled: true
58421
+ start: key.slice(0, START_LENGTH),
58422
+ key_hash: hashKey(key),
58423
+ meta: meta2
58418
58424
  });
58419
- if (!result2.data) {
58420
- secureLogger.error("Unkey createKey failed", null, {
58421
- error: "No data in response"
58425
+ if (error) {
58426
+ secureLogger.error("API key insert failed", error, {
58427
+ userId: opts.userId
58422
58428
  });
58423
58429
  throw new Error("Failed to create API key");
58424
58430
  }
58425
- return {
58426
- keyId: result2.data.keyId,
58427
- key: result2.data.key,
58428
- subjectSigningSecret
58429
- };
58431
+ return { keyId, key, subjectSigningSecret };
58430
58432
  } finally {
58431
58433
  await releaseKeyCreationLease(opts.userId, leaseToken);
58432
58434
  }
58433
58435
  }
58434
- async function verifyApiKey(rawKey, analyticsTags = []) {
58436
+ async function verifyLegacyUnkeyKey(rawKey, keyHash, analyticsTags) {
58435
58437
  const tags = normalizeAnalyticsTags(analyticsTags);
58436
- const unkey = await getUnkey();
58437
- const result2 = await unkey.keys.verifyKey({
58438
+ const { data: body } = await legacyUnkey().post("/keys.verifyKey", {
58438
58439
  key: rawKey,
58439
58440
  ...tags.length > 0 ? { tags } : {}
58440
58441
  });
58441
- if (!result2.data) {
58442
- secureLogger.warn("Unkey verifyKey call failed", {
58443
- error: "No data in response"
58444
- });
58445
- return { valid: false, code: "VERIFICATION_FAILED" };
58442
+ const d = body?.data;
58443
+ if (!d) throw new Error("Unkey verifyKey answered without a result");
58444
+ if (!d.valid) return { valid: false, code: d.code ?? "UNKNOWN" };
58445
+ const userId = d.identity?.externalId;
58446
+ if (!d.keyId || !userId || !UUID_PATTERN.test(userId)) {
58447
+ return { valid: false, code: "NOT_FOUND" };
58448
+ }
58449
+ const { data: enabled, error } = await getSupabaseAdmin().rpc(
58450
+ "migrate_unkey_api_key",
58451
+ {
58452
+ p_id: d.keyId,
58453
+ p_user_id: userId,
58454
+ p_key_hash: keyHash,
58455
+ p_name: d.name ?? "Unnamed",
58456
+ p_start: rawKey.slice(0, START_LENGTH),
58457
+ p_meta: withoutStalePlan(d.meta) ?? {}
58458
+ }
58459
+ );
58460
+ if (error) {
58461
+ throw new Error(`Recording a legacy API key failed: ${error.message}`);
58462
+ }
58463
+ if (enabled !== true) {
58464
+ return { valid: false, code: "DISABLED", keyId: d.keyId };
58446
58465
  }
58447
- const d = result2.data;
58448
58466
  return {
58449
- valid: d.valid,
58450
- code: d.code ?? (d.valid ? "VALID" : "UNKNOWN"),
58467
+ valid: true,
58468
+ code: "VALID",
58451
58469
  keyId: d.keyId,
58452
- userId: d.identity?.externalId,
58470
+ userId,
58453
58471
  name: d.name,
58454
- credits: d.credits ?? void 0,
58455
- meta: d.meta ?? void 0
58472
+ meta: withoutStalePlan(d.meta)
58456
58473
  };
58457
58474
  }
58475
+ async function verifyApiKey(rawKey, analyticsTags = []) {
58476
+ const keyHash = hashKey(rawKey);
58477
+ const cached = verifyCache.get(keyHash);
58478
+ if (cached && cached.expiresAt > Date.now()) return cached.result;
58479
+ const { data: row, error } = await getSupabaseAdmin().from("api_keys").select("id, user_id, name, meta, enabled").eq("key_hash", keyHash).maybeSingle();
58480
+ if (error) throw new Error(`API key lookup failed: ${error.message}`);
58481
+ let result2;
58482
+ if (row) {
58483
+ result2 = row.enabled ? {
58484
+ valid: true,
58485
+ code: "VALID",
58486
+ keyId: row.id,
58487
+ userId: row.user_id,
58488
+ name: row.name,
58489
+ meta: row.meta ?? void 0
58490
+ } : { valid: false, code: "DISABLED", keyId: row.id };
58491
+ } else if (isLegacyUnkeyConfigured()) {
58492
+ result2 = await verifyLegacyUnkeyKey(rawKey, keyHash, analyticsTags);
58493
+ } else {
58494
+ result2 = { valid: false, code: "NOT_FOUND" };
58495
+ }
58496
+ if (result2.valid) cacheVerified(keyHash, result2);
58497
+ return result2;
58498
+ }
58458
58499
  async function listKeys(userId) {
58459
- const keys = await listAllUserKeysRaw(userId);
58460
- if (keys.length === 0) return [];
58461
- return keys.map((k) => ({
58462
- keyId: k.keyId ?? "",
58500
+ const { data, error } = await getSupabaseAdmin().from("api_keys").select("id, name, start, enabled, meta, created_at").eq("user_id", userId).order("created_at", { ascending: true });
58501
+ if (error) throw new Error(`Listing API keys failed: ${error.message}`);
58502
+ return (data ?? []).map((k) => ({
58503
+ keyId: k.id,
58463
58504
  name: k.name ?? "Unnamed",
58464
58505
  prefix: k.start ?? "",
58465
- createdAt: k.createdAt ? new Date(k.createdAt).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
58506
+ createdAt: new Date(k.created_at).toISOString(),
58466
58507
  enabled: k.enabled ?? true,
58467
- credits: k.credits?.remaining ?? void 0,
58468
- externalId: k.identity?.externalId ?? void 0,
58469
- meta: withoutStalePlan(
58470
- sanitizeKeyMeta(k.meta ?? void 0)
58471
- )
58508
+ externalId: userId,
58509
+ meta: withoutStalePlan(sanitizeKeyMeta(k.meta ?? void 0))
58472
58510
  }));
58473
58511
  }
58474
- function withoutStalePlan(meta2) {
58475
- if (!meta2) return void 0;
58476
- const { plan: _stalePlan, ...rest } = meta2;
58477
- return rest;
58478
- }
58479
58512
  async function revokeKey(keyId) {
58480
- const unkey = await getUnkey();
58481
- await unkey.keys.updateKey({
58482
- keyId,
58483
- enabled: false
58484
- });
58513
+ const { data, error } = await getSupabaseAdmin().from("api_keys").update({ enabled: false }).eq("id", keyId).select("key_hash, source").maybeSingle();
58514
+ if (error) throw new Error(`Revoking API key failed: ${error.message}`);
58515
+ if (data?.key_hash) verifyCache.delete(data.key_hash);
58516
+ if (data?.source === "unkey" && isLegacyUnkeyConfigured()) {
58517
+ await legacyUnkey().post("/keys.updateKey", { keyId, enabled: false }).catch(
58518
+ (err) => secureLogger.error("Unkey disable failed; the key stays revoked in Hive", err, {
58519
+ keyId
58520
+ })
58521
+ );
58522
+ }
58485
58523
  }
58486
58524
 
58487
58525
  // src/health/mcpProtocol.ts
@@ -58491,28 +58529,28 @@ function getStaticApiKeys() {
58491
58529
  function getHttpMcpAuthReadiness() {
58492
58530
  const backend = getAuthBackendMode();
58493
58531
  const staticKeyCount = getStaticApiKeys().length;
58494
- if (isUnkeyRequired()) {
58495
- if (!isUnkeyConfigured()) {
58532
+ if (isHostedKeysRequired()) {
58533
+ if (!isHostedKeysConfigured()) {
58496
58534
  return {
58497
58535
  status: "missing_key",
58498
58536
  backend,
58499
58537
  configured: false,
58500
- detail: "Unkey authentication is selected but UNKEY_ROOT_KEY or UNKEY_API_ID is missing."
58538
+ detail: "Hosted API key authentication is selected but SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY is missing."
58501
58539
  };
58502
58540
  }
58503
58541
  return {
58504
58542
  status: "ok",
58505
58543
  backend,
58506
58544
  configured: true,
58507
- detail: "Unkey authentication is configured for HTTP MCP."
58545
+ detail: "Hosted API key authentication is configured for HTTP MCP."
58508
58546
  };
58509
58547
  }
58510
- if (isUnkeyConfigured()) {
58548
+ if (isHostedKeysConfigured()) {
58511
58549
  return {
58512
58550
  status: "ok",
58513
58551
  backend,
58514
58552
  configured: true,
58515
- detail: "Unkey authentication is configured for HTTP MCP."
58553
+ detail: "Hosted API key authentication is configured for HTTP MCP."
58516
58554
  };
58517
58555
  }
58518
58556
  if (staticKeyCount > 0) {
@@ -58527,7 +58565,7 @@ function getHttpMcpAuthReadiness() {
58527
58565
  status: "missing_key",
58528
58566
  backend,
58529
58567
  configured: false,
58530
- detail: "HTTP MCP authentication is not configured. Set Unkey credentials or HIVE_AUTH_BACKEND=static with HIVE_API_KEYS."
58568
+ detail: "HTTP MCP authentication is not configured. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY for hosted keys, or HIVE_AUTH_BACKEND=static with HIVE_API_KEYS."
58531
58569
  };
58532
58570
  }
58533
58571
  async function timedCheck(name, fn) {
@@ -58912,7 +58950,7 @@ async function runMcpProtocolHealth(options = {}) {
58912
58950
  }
58913
58951
 
58914
58952
  // src/health/oauthLifecycle.ts
58915
- import { createHash as createHash7, randomBytes as randomBytes3 } from "crypto";
58953
+ import { createHash as createHash8, randomBytes as randomBytes3 } from "crypto";
58916
58954
 
58917
58955
  // src/auth/oauth/provider.ts
58918
58956
  import { randomBytes as randomBytes2 } from "crypto";
@@ -59288,10 +59326,10 @@ function isHiveOAuthAccessToken(token) {
59288
59326
  }
59289
59327
 
59290
59328
  // src/auth/oauth/store.ts
59291
- import { createHash as createHash6 } from "crypto";
59329
+ import { createHash as createHash7 } from "crypto";
59292
59330
  var REVOKED_FAMILY_TTL_SECONDS = 7776e3;
59293
59331
  function digest(value) {
59294
- return createHash6("sha256").update(value).digest("hex");
59332
+ return createHash7("sha256").update(value).digest("hex");
59295
59333
  }
59296
59334
  function parseJson(raw) {
59297
59335
  if (!raw) return void 0;
@@ -59700,7 +59738,7 @@ var OAUTH_LIFECYCLE_CHECK_NAMES = [
59700
59738
  "token_revocation",
59701
59739
  "connected_app_cleanup"
59702
59740
  ];
59703
- var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
59741
+ var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
59704
59742
  function elapsed(started) {
59705
59743
  return Math.max(0, Date.now() - started);
59706
59744
  }
@@ -59743,7 +59781,7 @@ async function operationRejects(operation) {
59743
59781
  }
59744
59782
  async function issueCanaryFamily(args) {
59745
59783
  const verifier = randomBytes3(48).toString("base64url");
59746
- const challenge = createHash7("sha256").update(verifier).digest("base64url");
59784
+ const challenge = createHash8("sha256").update(verifier).digest("base64url");
59747
59785
  let consentLocation;
59748
59786
  const response = {
59749
59787
  redirect(status, location) {
@@ -59863,7 +59901,7 @@ async function runOAuthLifecycleHealth(overrides = {}) {
59863
59901
  }
59864
59902
  const userStarted = Date.now();
59865
59903
  const canaryUserId = dependencies.canaryUserId;
59866
- if (!canaryUserId || !UUID_PATTERN.test(canaryUserId)) {
59904
+ if (!canaryUserId || !UUID_PATTERN2.test(canaryUserId)) {
59867
59905
  checks.push(
59868
59906
  check(
59869
59907
  "canary_identity",
@@ -60055,7 +60093,7 @@ async function runOAuthLifecycleHealth(overrides = {}) {
60055
60093
  import Coingecko4 from "@coingecko/coingecko-typescript";
60056
60094
 
60057
60095
  // src/tools/goplus/goplusClient.ts
60058
- import { createHash as createHash8 } from "crypto";
60096
+ import { createHash as createHash9 } from "crypto";
60059
60097
  function parsePositiveInteger(value, fallback) {
60060
60098
  const parsed = Number.parseInt(value || "", 10);
60061
60099
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
@@ -60149,7 +60187,7 @@ var GoPlusClient = class {
60149
60187
  const time = Math.floor(Date.now() / 1e3);
60150
60188
  const timeStr = time.toString();
60151
60189
  const signInput = this.appKey + timeStr + this.appSecret;
60152
- const sign = createHash8("sha1").update(signInput).digest("hex");
60190
+ const sign = createHash9("sha1").update(signInput).digest("hex");
60153
60191
  secureLogger.info("GoPlus: requesting access token", {
60154
60192
  appKeyLength: this.appKey.length,
60155
60193
  appSecretLength: this.appSecret.length,
@@ -66033,32 +66071,32 @@ function dynamicTools(endpoints, options = {}) {
66033
66071
  const taskToolsetCatalogEntries = TASK_TOOLSETS.map(
66034
66072
  (toolset) => toolsetCatalogEntry(toolset, providerByToolName)
66035
66073
  );
66036
- const searchToolsSchema = z4.object({
66037
- query: z4.string().max(512).optional().describe(
66074
+ const searchToolsSchema = z3.object({
66075
+ query: z3.string().max(512).optional().describe(
66038
66076
  "Search text matched against tool name, title, category, provider, and summary."
66039
66077
  ),
66040
- provider: z4.string().max(128).optional().describe(
66078
+ provider: z3.string().max(128).optional().describe(
66041
66079
  "Optional provider filter such as CoinGecko, Tenderly, Helius, GoPlus, CCXT, Alchemy, DeFiLlama, Hyperliquid, or Open Data Fetch."
66042
66080
  ),
66043
- category: z4.string().max(128).optional().describe("Optional category filter, for example Portfolio & Wallet."),
66044
- limit: z4.number().int().min(1).max(MAX_SEARCH_LIMIT).optional().describe(`Maximum tools to return. Default ${DEFAULT_SEARCH_LIMIT}.`),
66045
- cursor: z4.string().optional().describe("Pagination cursor from the previous response."),
66046
- toolset_id: z4.string().max(100).optional().describe(
66081
+ category: z3.string().max(128).optional().describe("Optional category filter, for example Portfolio & Wallet."),
66082
+ limit: z3.number().int().min(1).max(MAX_SEARCH_LIMIT).optional().describe(`Maximum tools to return. Default ${DEFAULT_SEARCH_LIMIT}.`),
66083
+ cursor: z3.string().optional().describe("Pagination cursor from the previous response."),
66084
+ toolset_id: z3.string().max(100).optional().describe(
66047
66085
  "Optional exact canonical task toolset id. Use this after an initial compact result to inspect one workflow."
66048
66086
  ),
66049
- route_id: z4.string().max(100).optional().describe(
66087
+ route_id: z3.string().max(100).optional().describe(
66050
66088
  "Optional exact task-shaped route id. Use the matched route's ordered calls and conditional fallbacks instead of choosing from the coverage catalog."
66051
66089
  ),
66052
- evidence_phase: z4.string().max(100).optional().describe(
66090
+ evidence_phase: z3.string().max(100).optional().describe(
66053
66091
  `Optional exact workflow evidence phase. Supported values: ${CANONICAL_EVIDENCE_PHASES.join(", ")}.`
66054
66092
  ),
66055
- detail: z4.enum(["compact", "standard", "full"]).optional().describe(
66093
+ detail: z3.enum(["compact", "standard", "full"]).optional().describe(
66056
66094
  "Toolset detail level. Defaults to compact. Use full only when the task output schema is needed."
66057
66095
  ),
66058
- toolset_limit: z4.number().int().min(1).max(MAX_TOOLSET_LIMIT).optional().describe(
66096
+ toolset_limit: z3.number().int().min(1).max(MAX_TOOLSET_LIMIT).optional().describe(
66059
66097
  `Maximum matching task toolsets to return. Default ${DEFAULT_TOOLSET_LIMIT}, max ${MAX_TOOLSET_LIMIT}.`
66060
66098
  ),
66061
- toolset_cursor: z4.string().optional().describe("Pagination cursor for task toolset matches.")
66099
+ toolset_cursor: z3.string().optional().describe("Pagination cursor for task toolset matches.")
66062
66100
  });
66063
66101
  const searchToolsTool = {
66064
66102
  metadata: {
@@ -66192,9 +66230,9 @@ function dynamicTools(endpoints, options = {}) {
66192
66230
  });
66193
66231
  }
66194
66232
  };
66195
- const getEndpointSchema = z4.object({
66196
- endpoint: z4.string().optional().describe("The name of the endpoint to get the schema for."),
66197
- endpoint_name: z4.string().optional().describe(
66233
+ const getEndpointSchema = z3.object({
66234
+ endpoint: z3.string().optional().describe("The name of the endpoint to get the schema for."),
66235
+ endpoint_name: z3.string().optional().describe(
66198
66236
  "Alias for 'endpoint', accepted for symmetry with invoke_api_endpoint. Provide one of the two."
66199
66237
  )
66200
66238
  });
@@ -66272,12 +66310,12 @@ function dynamicTools(endpoints, options = {}) {
66272
66310
  });
66273
66311
  }
66274
66312
  };
66275
- const invokeEndpointSchema = z4.object({
66276
- endpoint_name: z4.string().optional().describe("The name of the endpoint to invoke."),
66277
- endpoint: z4.string().optional().describe(
66313
+ const invokeEndpointSchema = z3.object({
66314
+ endpoint_name: z3.string().optional().describe("The name of the endpoint to invoke."),
66315
+ endpoint: z3.string().optional().describe(
66278
66316
  "Alias for 'endpoint_name', accepted by both root invokers. Provide one of the two."
66279
66317
  ),
66280
- args: z4.record(z4.string(), z4.any()).optional().describe(
66318
+ args: z3.record(z3.string(), z3.any()).optional().describe(
66281
66319
  "The arguments to pass to the endpoint. This must match the schema returned by the `get_api_endpoint_schema` tool. You may also pass arguments as flat top-level keys alongside endpoint_name."
66282
66320
  )
66283
66321
  }).passthrough();
@@ -66348,9 +66386,9 @@ function dynamicTools(endpoints, options = {}) {
66348
66386
  },
66349
66387
  handler: async (client2, args) => invokeWithPolicy(STATEFUL_WRITE_ENDPOINT_INVOKER, client2, args)
66350
66388
  };
66351
- const validateTaskResultSchema = z4.object({
66352
- task_toolset_id: z4.string().describe("Canonical task toolset id returned by search_tools."),
66353
- result: z4.record(z4.string(), z4.any()).describe(
66389
+ const validateTaskResultSchema = z3.object({
66390
+ task_toolset_id: z3.string().describe("Canonical task toolset id returned by search_tools."),
66391
+ result: z3.record(z3.string(), z3.any()).describe(
66354
66392
  "The proposed task result envelope. Each receipt.calls entry must be copied exactly from a material call's _hive object."
66355
66393
  )
66356
66394
  });
@@ -66642,10 +66680,10 @@ function dynamicTools(endpoints, options = {}) {
66642
66680
  }
66643
66681
  };
66644
66682
  const categoryTools = ToolRegistry.map((category, categoryIndex) => {
66645
- const categorySchema = z4.object({
66646
- search: z4.string().optional().describe("Ignored; retained for 1.2.0 compatibility."),
66647
- limit: z4.number().int().optional().describe("Ignored; retained for 1.2.0 compatibility."),
66648
- cursor: z4.string().optional().describe("Ignored; retained for 1.2.0 compatibility.")
66683
+ const categorySchema = z3.object({
66684
+ search: z3.string().optional().describe("Ignored; retained for 1.2.0 compatibility."),
66685
+ limit: z3.number().int().optional().describe("Ignored; retained for 1.2.0 compatibility."),
66686
+ cursor: z3.string().optional().describe("Ignored; retained for 1.2.0 compatibility.")
66649
66687
  });
66650
66688
  const categoryEndpointName = category.name;
66651
66689
  const categoryPath = CategoryEndpoints[categoryIndex] ?? "";
@@ -66724,7 +66762,7 @@ function dynamicTools(endpoints, options = {}) {
66724
66762
  }
66725
66763
 
66726
66764
  // src/utils/jsonSchemaToZod.ts
66727
- import { z as z5 } from "zod";
66765
+ import { z as z4 } from "zod";
66728
66766
  var TOP_LEVEL_COMBINATORS = /* @__PURE__ */ new Set([
66729
66767
  "allOf",
66730
66768
  "anyOf",
@@ -66806,10 +66844,10 @@ function zodPath(field) {
66806
66844
  });
66807
66845
  }
66808
66846
  function jsonSchemaToZodInputSchema(schema) {
66809
- const base = z5.fromJSONSchema(
66847
+ const base = z4.fromJSONSchema(
66810
66848
  zodBaseSchema(schema)
66811
66849
  );
66812
- if (!(base instanceof z5.ZodObject)) {
66850
+ if (!(base instanceof z4.ZodObject)) {
66813
66851
  throw new Error("Tool input schema must compile to a Zod object");
66814
66852
  }
66815
66853
  const properties = schema.properties ?? {};
@@ -66856,34 +66894,34 @@ function jsonSchemaToZodShape(schema) {
66856
66894
  return shape;
66857
66895
  }
66858
66896
  function jsonSchemaToZodObject(schema, options = {}) {
66859
- const objectSchema = z5.object(jsonSchemaToZodShape(schema));
66897
+ const objectSchema = z4.object(jsonSchemaToZodShape(schema));
66860
66898
  return options.passthrough ? objectSchema.passthrough() : objectSchema;
66861
66899
  }
66862
66900
  function buildZodType(prop) {
66863
66901
  const type = prop.type;
66864
66902
  const enumValues = prop.enum;
66865
66903
  if (enumValues && enumValues.length > 0) {
66866
- return z5.enum(enumValues);
66904
+ return z4.enum(enumValues);
66867
66905
  }
66868
66906
  switch (type) {
66869
66907
  case "string":
66870
- return z5.string();
66908
+ return z4.string();
66871
66909
  case "number":
66872
66910
  case "integer":
66873
- return z5.number();
66911
+ return z4.number();
66874
66912
  case "boolean":
66875
- return z5.boolean();
66913
+ return z4.boolean();
66876
66914
  case "array":
66877
- return z5.array(z5.unknown());
66915
+ return z4.array(z4.unknown());
66878
66916
  case "object":
66879
- return z5.record(z5.string(), z5.unknown());
66917
+ return z4.record(z4.string(), z4.unknown());
66880
66918
  default:
66881
- return z5.unknown();
66919
+ return z4.unknown();
66882
66920
  }
66883
66921
  }
66884
66922
 
66885
66923
  // src/mcpServer.ts
66886
- dotenv.config({ quiet: true });
66924
+ loadEnvFile();
66887
66925
  var ROOT_META_TOOL_COUNT = getRootVisibleToolCount();
66888
66926
  var ROOT_VISIBLE_TOOL_ORDER = [
66889
66927
  "get_token_price",
@@ -67629,12 +67667,6 @@ var HiveMCPServer = class {
67629
67667
  "/api/health/toolsets/quick",
67630
67668
  "/api/health/toolsets/history"
67631
67669
  ],
67632
- unkeyAnalyticsTags: [
67633
- "service=hive",
67634
- "transport=rest",
67635
- "route=<route>",
67636
- "endpoint=<tool_name>"
67637
- ],
67638
67670
  mcpToolCallLogFields: [
67639
67671
  "tool",
67640
67672
  "success",
@@ -67811,14 +67843,6 @@ function createHiveMcpServer(scope, options) {
67811
67843
  }
67812
67844
 
67813
67845
  export {
67814
- getEnvVar,
67815
- getCsvEnv,
67816
- getNodeEnv,
67817
- isProduction,
67818
- getPort,
67819
- getRateLimitMax,
67820
- getCredentialedRateLimitMax,
67821
- getCorsAllowedOrigins,
67822
67846
  isSupabaseConfigured,
67823
67847
  getSupabaseAdmin,
67824
67848
  getUserPlanId,
@@ -67881,8 +67905,8 @@ export {
67881
67905
  OAUTH_CLIENT_REDIRECT_PROFILES,
67882
67906
  MAX_DCR_CLIENT_METADATA_BYTES,
67883
67907
  buildAuthCompatibility,
67884
- isUnkeyRequired,
67885
- isUnkeyConfigured,
67908
+ isHostedKeysRequired,
67909
+ isHostedKeysConfigured,
67886
67910
  createApiKey,
67887
67911
  verifyApiKey,
67888
67912
  listKeys,