evrex-mcp 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -64,6 +64,30 @@ re-rendered from the transcript and marked authoritative over the summary).
64
64
  | `EVREX_API_BASE_URL` | no | Point at a self-hosted evrex backend. Defaults to the hosted one. |
65
65
  | `ANTHROPIC_MODEL` | no | Defaults to `claude-opus-5`. |
66
66
 
67
+ ## Hosted mode
68
+
69
+ The same tools over HTTPS, for agents that run in someone else's cloud and can only attach a remote MCP server.
70
+ That includes Claude Tag in Slack, Cursor cloud agents, the Copilot coding agent, Devin and CI.
71
+ Evrex runs it at `https://api.evrex.ai/mcp`. Mint a read-only token at https://app.evrex.ai/agents and give the agent:
72
+
73
+ - `Authorization: Bearer evx_…` (required)
74
+ - `X-Evrex-Repo: owner/name` (optional), or the full git remote URL for a repo not on github.com. This is the repo to
75
+ search when a tool call names none. Without it, a call searches every repo your team has indexed. A value that names
76
+ no repo is refused with a 400.
77
+
78
+ Where a config reads the token from the environment, keep it in `EVREX_MCP_TOKEN`, never `EVREX_TOKEN`: on a machine
79
+ that captures sessions, `EVREX_TOKEN` takes precedence over the enrolled capture credential, so a read-only agent
80
+ token there makes every capture upload fail.
81
+
82
+ To run your own copy:
83
+
84
+ ```sh
85
+ PORT=3100 EVREX_API_BASE_URL=https://api.evrex.ai npx -y evrex-mcp serve
86
+ ```
87
+
88
+ It is stateless (POST `/mcp` only) and keeps no data. Each request's token makes that request's calls to the backend.
89
+ `EVREX_MCP_ALLOWED_ORIGINS` (comma-separated) replaces the default list of browser origins it admits.
90
+
67
91
  ## No API credits needed to query
68
92
 
69
93
  The tools return the recorded context — constraints, rejected approaches, prior
package/dist/account.js CHANGED
@@ -3,21 +3,42 @@
3
3
  // src/account.ts
4
4
  import { statSync, openSync, readSync, closeSync } from "node:fs";
5
5
 
6
+ // src/request-context.ts
7
+ import { AsyncLocalStorage } from "node:async_hooks";
8
+ var storage = new AsyncLocalStorage();
9
+ function currentRequest() {
10
+ return storage.getStore();
11
+ }
12
+
6
13
  // src/client.ts
7
14
  var DEFAULT_API_BASE_URL = "https://api.evrex.ai";
8
15
  var API_BASE_URL = (process.env.EVREX_API_BASE_URL ?? process.env.EVREX_API_URL ?? DEFAULT_API_BASE_URL).replace(/\/+$/, "");
9
16
  var EVREX_TOKEN = process.env.EVREX_TOKEN ?? process.env.EVREX_API_TOKEN ?? null;
17
+ function token() {
18
+ return currentRequest()?.token ?? EVREX_TOKEN;
19
+ }
10
20
  function headers() {
11
21
  const base = { "Content-Type": "application/json" };
12
- if (EVREX_TOKEN) base.Authorization = `Bearer ${EVREX_TOKEN}`;
22
+ const credential = token();
23
+ if (credential) base.Authorization = `Bearer ${credential}`;
13
24
  return base;
14
25
  }
15
26
  function describeFailure(method, path, status, statusText) {
16
27
  if (status === 401 || status === 403) {
28
+ if (currentRequest()) {
29
+ return `${method} ${path} -> ${status}: the Evrex token this connection carries was rejected, or lacks the scope this needs. Mint a read token at https://app.evrex.ai/agents.`;
30
+ }
17
31
  return EVREX_TOKEN ? `${method} ${path} -> ${status}: the EVREX_TOKEN this server was started with was rejected. It may be revoked or expired.` : `${method} ${path} -> ${status}: this evrex backend requires a credential, but no EVREX_TOKEN is set for this MCP server.`;
18
32
  }
19
33
  return `${method} ${path} -> ${status} ${statusText}`;
20
34
  }
35
+ var EvrexApiError = class extends Error {
36
+ constructor(message, status) {
37
+ super(message);
38
+ this.status = status;
39
+ this.name = "EvrexApiError";
40
+ }
41
+ };
21
42
  async function request(method, path, { body, absentIsAnswer } = {}) {
22
43
  const res = await fetch(`${API_BASE_URL}${path}`, {
23
44
  method,
@@ -25,7 +46,7 @@ async function request(method, path, { body, absentIsAnswer } = {}) {
25
46
  ...body === void 0 ? {} : { body: JSON.stringify(body) }
26
47
  });
27
48
  if (res.status === 404 && absentIsAnswer) return null;
28
- if (!res.ok) throw new Error(describeFailure(method, path, res.status, res.statusText));
49
+ if (!res.ok) throw new EvrexApiError(describeFailure(method, path, res.status, res.statusText), res.status);
29
50
  return await res.json();
30
51
  }
31
52
  var get = (path) => request("GET", path);
@@ -34,6 +55,7 @@ var post = (path, body) => request("POST", path, { body });
34
55
  var evrexApi = {
35
56
  baseUrl: API_BASE_URL,
36
57
  repos: () => get("/repos"),
58
+ me: () => get("/auth/me"),
37
59
  commits: (repoPath) => get(`/commits?repoPath=${encodeURIComponent(repoPath)}`),
38
60
  // Abbreviated shas resolve server-side, so a value pasted from `git log`
39
61
  // works here (apps/backend/src/reads/reads.service.ts#resolveSha).
package/dist/capture.js CHANGED
@@ -3368,18 +3368,39 @@ var init_src = __esm({
3368
3368
  }
3369
3369
  });
3370
3370
 
3371
+ // src/request-context.ts
3372
+ import { AsyncLocalStorage } from "node:async_hooks";
3373
+ function currentRequest() {
3374
+ return storage.getStore();
3375
+ }
3376
+ var storage;
3377
+ var init_request_context = __esm({
3378
+ "src/request-context.ts"() {
3379
+ "use strict";
3380
+ storage = new AsyncLocalStorage();
3381
+ }
3382
+ });
3383
+
3371
3384
  // src/client.ts
3372
3385
  var client_exports = {};
3373
3386
  __export(client_exports, {
3387
+ EvrexApiError: () => EvrexApiError,
3374
3388
  evrexApi: () => evrexApi
3375
3389
  });
3390
+ function token() {
3391
+ return currentRequest()?.token ?? EVREX_TOKEN;
3392
+ }
3376
3393
  function headers() {
3377
3394
  const base = { "Content-Type": "application/json" };
3378
- if (EVREX_TOKEN) base.Authorization = `Bearer ${EVREX_TOKEN}`;
3395
+ const credential = token();
3396
+ if (credential) base.Authorization = `Bearer ${credential}`;
3379
3397
  return base;
3380
3398
  }
3381
3399
  function describeFailure(method, path, status, statusText) {
3382
3400
  if (status === 401 || status === 403) {
3401
+ if (currentRequest()) {
3402
+ return `${method} ${path} -> ${status}: the Evrex token this connection carries was rejected, or lacks the scope this needs. Mint a read token at https://app.evrex.ai/agents.`;
3403
+ }
3383
3404
  return EVREX_TOKEN ? `${method} ${path} -> ${status}: the EVREX_TOKEN this server was started with was rejected. It may be revoked or expired.` : `${method} ${path} -> ${status}: this evrex backend requires a credential, but no EVREX_TOKEN is set for this MCP server.`;
3384
3405
  }
3385
3406
  return `${method} ${path} -> ${status} ${statusText}`;
@@ -3391,22 +3412,31 @@ async function request(method, path, { body, absentIsAnswer } = {}) {
3391
3412
  ...body === void 0 ? {} : { body: JSON.stringify(body) }
3392
3413
  });
3393
3414
  if (res.status === 404 && absentIsAnswer) return null;
3394
- if (!res.ok) throw new Error(describeFailure(method, path, res.status, res.statusText));
3415
+ if (!res.ok) throw new EvrexApiError(describeFailure(method, path, res.status, res.statusText), res.status);
3395
3416
  return await res.json();
3396
3417
  }
3397
- var DEFAULT_API_BASE_URL, API_BASE_URL, EVREX_TOKEN, get, getOrNull, post, evrexApi;
3418
+ var DEFAULT_API_BASE_URL, API_BASE_URL, EVREX_TOKEN, EvrexApiError, get, getOrNull, post, evrexApi;
3398
3419
  var init_client = __esm({
3399
3420
  "src/client.ts"() {
3400
3421
  "use strict";
3422
+ init_request_context();
3401
3423
  DEFAULT_API_BASE_URL = "https://api.evrex.ai";
3402
3424
  API_BASE_URL = (process.env.EVREX_API_BASE_URL ?? process.env.EVREX_API_URL ?? DEFAULT_API_BASE_URL).replace(/\/+$/, "");
3403
3425
  EVREX_TOKEN = process.env.EVREX_TOKEN ?? process.env.EVREX_API_TOKEN ?? null;
3426
+ EvrexApiError = class extends Error {
3427
+ constructor(message, status) {
3428
+ super(message);
3429
+ this.status = status;
3430
+ this.name = "EvrexApiError";
3431
+ }
3432
+ };
3404
3433
  get = (path) => request("GET", path);
3405
3434
  getOrNull = (path) => request("GET", path, { absentIsAnswer: true });
3406
3435
  post = (path, body) => request("POST", path, { body });
3407
3436
  evrexApi = {
3408
3437
  baseUrl: API_BASE_URL,
3409
3438
  repos: () => get("/repos"),
3439
+ me: () => get("/auth/me"),
3410
3440
  commits: (repoPath) => get(`/commits?repoPath=${encodeURIComponent(repoPath)}`),
3411
3441
  // Abbreviated shas resolve server-side, so a value pasted from `git log`
3412
3442
  // works here (apps/backend/src/reads/reads.service.ts#resolveSha).
@@ -3500,11 +3530,13 @@ evrex will not fall back to writing the credential in a plain file.`
3500
3530
  if (!await this.available()) throw new NoKeychainError(this.runner.platform);
3501
3531
  switch (this.runner.platform) {
3502
3532
  case "darwin": {
3533
+ if (/["\\\r\n]/.test(secret)) {
3534
+ throw new Error("Keychain write refused: the credential has a character `security -i` cannot carry.");
3535
+ }
3503
3536
  const result = await this.runner.run(
3504
3537
  "security",
3505
- ["add-generic-password", "-a", ACCOUNT, "-s", SERVICE, "-U", "-w"],
3506
- `${secret}
3507
- ${secret}
3538
+ ["-i"],
3539
+ `add-generic-password -a "${ACCOUNT}" -s "${SERVICE}" -U -w "${secret}"
3508
3540
  `
3509
3541
  );
3510
3542
  if (result.code !== 0) throw new Error(`Keychain write failed: ${result.stderr.trim()}`);
@@ -3860,8 +3892,8 @@ async function main() {
3860
3892
  return;
3861
3893
  }
3862
3894
  const { evrexApi: evrexApi2 } = await Promise.resolve().then(() => (init_client(), client_exports));
3863
- let token;
3864
- const credential = () => token ??= captureToken(process.env, async () => {
3895
+ let token2;
3896
+ const credential = () => token2 ??= captureToken(process.env, async () => {
3865
3897
  const { CredentialStore: CredentialStore2 } = await Promise.resolve().then(() => (init_credential_store(), credential_store_exports));
3866
3898
  return new CredentialStore2().retrieve();
3867
3899
  });
@@ -5,21 +5,42 @@ import { execFileSync as execFileSync2 } from "node:child_process";
5
5
  import { closeSync, openSync, readSync, statSync } from "node:fs";
6
6
  import { pathToFileURL } from "node:url";
7
7
 
8
+ // src/request-context.ts
9
+ import { AsyncLocalStorage } from "node:async_hooks";
10
+ var storage = new AsyncLocalStorage();
11
+ function currentRequest() {
12
+ return storage.getStore();
13
+ }
14
+
8
15
  // src/client.ts
9
16
  var DEFAULT_API_BASE_URL = "https://api.evrex.ai";
10
17
  var API_BASE_URL = (process.env.EVREX_API_BASE_URL ?? process.env.EVREX_API_URL ?? DEFAULT_API_BASE_URL).replace(/\/+$/, "");
11
18
  var EVREX_TOKEN = process.env.EVREX_TOKEN ?? process.env.EVREX_API_TOKEN ?? null;
19
+ function token() {
20
+ return currentRequest()?.token ?? EVREX_TOKEN;
21
+ }
12
22
  function headers() {
13
23
  const base = { "Content-Type": "application/json" };
14
- if (EVREX_TOKEN) base.Authorization = `Bearer ${EVREX_TOKEN}`;
24
+ const credential = token();
25
+ if (credential) base.Authorization = `Bearer ${credential}`;
15
26
  return base;
16
27
  }
17
28
  function describeFailure(method, path, status, statusText) {
18
29
  if (status === 401 || status === 403) {
30
+ if (currentRequest()) {
31
+ return `${method} ${path} -> ${status}: the Evrex token this connection carries was rejected, or lacks the scope this needs. Mint a read token at https://app.evrex.ai/agents.`;
32
+ }
19
33
  return EVREX_TOKEN ? `${method} ${path} -> ${status}: the EVREX_TOKEN this server was started with was rejected. It may be revoked or expired.` : `${method} ${path} -> ${status}: this evrex backend requires a credential, but no EVREX_TOKEN is set for this MCP server.`;
20
34
  }
21
35
  return `${method} ${path} -> ${status} ${statusText}`;
22
36
  }
37
+ var EvrexApiError = class extends Error {
38
+ constructor(message, status) {
39
+ super(message);
40
+ this.status = status;
41
+ this.name = "EvrexApiError";
42
+ }
43
+ };
23
44
  async function request(method, path, { body, absentIsAnswer } = {}) {
24
45
  const res = await fetch(`${API_BASE_URL}${path}`, {
25
46
  method,
@@ -27,7 +48,7 @@ async function request(method, path, { body, absentIsAnswer } = {}) {
27
48
  ...body === void 0 ? {} : { body: JSON.stringify(body) }
28
49
  });
29
50
  if (res.status === 404 && absentIsAnswer) return null;
30
- if (!res.ok) throw new Error(describeFailure(method, path, res.status, res.statusText));
51
+ if (!res.ok) throw new EvrexApiError(describeFailure(method, path, res.status, res.statusText), res.status);
31
52
  return await res.json();
32
53
  }
33
54
  var get = (path) => request("GET", path);
@@ -36,6 +57,7 @@ var post = (path, body) => request("POST", path, { body });
36
57
  var evrexApi = {
37
58
  baseUrl: API_BASE_URL,
38
59
  repos: () => get("/repos"),
60
+ me: () => get("/auth/me"),
39
61
  commits: (repoPath) => get(`/commits?repoPath=${encodeURIComponent(repoPath)}`),
40
62
  // Abbreviated shas resolve server-side, so a value pasted from `git log`
41
63
  // works here (apps/backend/src/reads/reads.service.ts#resolveSha).
package/dist/hook.js CHANGED
@@ -3,21 +3,42 @@
3
3
  // src/hook.ts
4
4
  import { pathToFileURL } from "node:url";
5
5
 
6
+ // src/request-context.ts
7
+ import { AsyncLocalStorage } from "node:async_hooks";
8
+ var storage = new AsyncLocalStorage();
9
+ function currentRequest() {
10
+ return storage.getStore();
11
+ }
12
+
6
13
  // src/client.ts
7
14
  var DEFAULT_API_BASE_URL = "https://api.evrex.ai";
8
15
  var API_BASE_URL = (process.env.EVREX_API_BASE_URL ?? process.env.EVREX_API_URL ?? DEFAULT_API_BASE_URL).replace(/\/+$/, "");
9
16
  var EVREX_TOKEN = process.env.EVREX_TOKEN ?? process.env.EVREX_API_TOKEN ?? null;
17
+ function token() {
18
+ return currentRequest()?.token ?? EVREX_TOKEN;
19
+ }
10
20
  function headers() {
11
21
  const base = { "Content-Type": "application/json" };
12
- if (EVREX_TOKEN) base.Authorization = `Bearer ${EVREX_TOKEN}`;
22
+ const credential = token();
23
+ if (credential) base.Authorization = `Bearer ${credential}`;
13
24
  return base;
14
25
  }
15
26
  function describeFailure(method, path, status, statusText) {
16
27
  if (status === 401 || status === 403) {
28
+ if (currentRequest()) {
29
+ return `${method} ${path} -> ${status}: the Evrex token this connection carries was rejected, or lacks the scope this needs. Mint a read token at https://app.evrex.ai/agents.`;
30
+ }
17
31
  return EVREX_TOKEN ? `${method} ${path} -> ${status}: the EVREX_TOKEN this server was started with was rejected. It may be revoked or expired.` : `${method} ${path} -> ${status}: this evrex backend requires a credential, but no EVREX_TOKEN is set for this MCP server.`;
18
32
  }
19
33
  return `${method} ${path} -> ${status} ${statusText}`;
20
34
  }
35
+ var EvrexApiError = class extends Error {
36
+ constructor(message, status) {
37
+ super(message);
38
+ this.status = status;
39
+ this.name = "EvrexApiError";
40
+ }
41
+ };
21
42
  async function request(method, path, { body, absentIsAnswer } = {}) {
22
43
  const res = await fetch(`${API_BASE_URL}${path}`, {
23
44
  method,
@@ -25,7 +46,7 @@ async function request(method, path, { body, absentIsAnswer } = {}) {
25
46
  ...body === void 0 ? {} : { body: JSON.stringify(body) }
26
47
  });
27
48
  if (res.status === 404 && absentIsAnswer) return null;
28
- if (!res.ok) throw new Error(describeFailure(method, path, res.status, res.statusText));
49
+ if (!res.ok) throw new EvrexApiError(describeFailure(method, path, res.status, res.statusText), res.status);
29
50
  return await res.json();
30
51
  }
31
52
  var get = (path) => request("GET", path);
@@ -34,6 +55,7 @@ var post = (path, body) => request("POST", path, { body });
34
55
  var evrexApi = {
35
56
  baseUrl: API_BASE_URL,
36
57
  repos: () => get("/repos"),
58
+ me: () => get("/auth/me"),
37
59
  commits: (repoPath) => get(`/commits?repoPath=${encodeURIComponent(repoPath)}`),
38
60
  // Abbreviated shas resolve server-side, so a value pasted from `git log`
39
61
  // works here (apps/backend/src/reads/reads.service.ts#resolveSha).
package/dist/import.js CHANGED
@@ -3368,18 +3368,39 @@ var init_src = __esm({
3368
3368
  }
3369
3369
  });
3370
3370
 
3371
+ // src/request-context.ts
3372
+ import { AsyncLocalStorage } from "node:async_hooks";
3373
+ function currentRequest() {
3374
+ return storage.getStore();
3375
+ }
3376
+ var storage;
3377
+ var init_request_context = __esm({
3378
+ "src/request-context.ts"() {
3379
+ "use strict";
3380
+ storage = new AsyncLocalStorage();
3381
+ }
3382
+ });
3383
+
3371
3384
  // src/client.ts
3372
3385
  var client_exports = {};
3373
3386
  __export(client_exports, {
3387
+ EvrexApiError: () => EvrexApiError,
3374
3388
  evrexApi: () => evrexApi
3375
3389
  });
3390
+ function token() {
3391
+ return currentRequest()?.token ?? EVREX_TOKEN;
3392
+ }
3376
3393
  function headers() {
3377
3394
  const base = { "Content-Type": "application/json" };
3378
- if (EVREX_TOKEN) base.Authorization = `Bearer ${EVREX_TOKEN}`;
3395
+ const credential = token();
3396
+ if (credential) base.Authorization = `Bearer ${credential}`;
3379
3397
  return base;
3380
3398
  }
3381
3399
  function describeFailure(method, path, status, statusText) {
3382
3400
  if (status === 401 || status === 403) {
3401
+ if (currentRequest()) {
3402
+ return `${method} ${path} -> ${status}: the Evrex token this connection carries was rejected, or lacks the scope this needs. Mint a read token at https://app.evrex.ai/agents.`;
3403
+ }
3383
3404
  return EVREX_TOKEN ? `${method} ${path} -> ${status}: the EVREX_TOKEN this server was started with was rejected. It may be revoked or expired.` : `${method} ${path} -> ${status}: this evrex backend requires a credential, but no EVREX_TOKEN is set for this MCP server.`;
3384
3405
  }
3385
3406
  return `${method} ${path} -> ${status} ${statusText}`;
@@ -3391,22 +3412,31 @@ async function request(method, path, { body, absentIsAnswer } = {}) {
3391
3412
  ...body === void 0 ? {} : { body: JSON.stringify(body) }
3392
3413
  });
3393
3414
  if (res.status === 404 && absentIsAnswer) return null;
3394
- if (!res.ok) throw new Error(describeFailure(method, path, res.status, res.statusText));
3415
+ if (!res.ok) throw new EvrexApiError(describeFailure(method, path, res.status, res.statusText), res.status);
3395
3416
  return await res.json();
3396
3417
  }
3397
- var DEFAULT_API_BASE_URL, API_BASE_URL, EVREX_TOKEN, get, getOrNull, post, evrexApi;
3418
+ var DEFAULT_API_BASE_URL, API_BASE_URL, EVREX_TOKEN, EvrexApiError, get, getOrNull, post, evrexApi;
3398
3419
  var init_client = __esm({
3399
3420
  "src/client.ts"() {
3400
3421
  "use strict";
3422
+ init_request_context();
3401
3423
  DEFAULT_API_BASE_URL = "https://api.evrex.ai";
3402
3424
  API_BASE_URL = (process.env.EVREX_API_BASE_URL ?? process.env.EVREX_API_URL ?? DEFAULT_API_BASE_URL).replace(/\/+$/, "");
3403
3425
  EVREX_TOKEN = process.env.EVREX_TOKEN ?? process.env.EVREX_API_TOKEN ?? null;
3426
+ EvrexApiError = class extends Error {
3427
+ constructor(message, status) {
3428
+ super(message);
3429
+ this.status = status;
3430
+ this.name = "EvrexApiError";
3431
+ }
3432
+ };
3404
3433
  get = (path) => request("GET", path);
3405
3434
  getOrNull = (path) => request("GET", path, { absentIsAnswer: true });
3406
3435
  post = (path, body) => request("POST", path, { body });
3407
3436
  evrexApi = {
3408
3437
  baseUrl: API_BASE_URL,
3409
3438
  repos: () => get("/repos"),
3439
+ me: () => get("/auth/me"),
3410
3440
  commits: (repoPath) => get(`/commits?repoPath=${encodeURIComponent(repoPath)}`),
3411
3441
  // Abbreviated shas resolve server-side, so a value pasted from `git log`
3412
3442
  // works here (apps/backend/src/reads/reads.service.ts#resolveSha).
@@ -3500,11 +3530,13 @@ evrex will not fall back to writing the credential in a plain file.`
3500
3530
  if (!await this.available()) throw new NoKeychainError(this.runner.platform);
3501
3531
  switch (this.runner.platform) {
3502
3532
  case "darwin": {
3533
+ if (/["\\\r\n]/.test(secret)) {
3534
+ throw new Error("Keychain write refused: the credential has a character `security -i` cannot carry.");
3535
+ }
3503
3536
  const result = await this.runner.run(
3504
3537
  "security",
3505
- ["add-generic-password", "-a", ACCOUNT, "-s", SERVICE, "-U", "-w"],
3506
- `${secret}
3507
- ${secret}
3538
+ ["-i"],
3539
+ `add-generic-password -a "${ACCOUNT}" -s "${SERVICE}" -U -w "${secret}"
3508
3540
  `
3509
3541
  );
3510
3542
  if (result.code !== 0) throw new Error(`Keychain write failed: ${result.stderr.trim()}`);
@@ -3778,8 +3810,8 @@ async function durability(target, argv) {
3778
3810
  };
3779
3811
  const minAgeDays = flag("--min-age-days", 30);
3780
3812
  const limit = flag("--limit", 300);
3781
- const token = process.env.EVREX_TOKEN ?? await new (await Promise.resolve().then(() => (init_credential_store(), credential_store_exports))).CredentialStore().retrieve().catch(() => null);
3782
- if (!token) {
3813
+ const token2 = process.env.EVREX_TOKEN ?? await new (await Promise.resolve().then(() => (init_credential_store(), credential_store_exports))).CredentialStore().retrieve().catch(() => null);
3814
+ if (!token2) {
3783
3815
  console.error("evrex: this machine is not enrolled.\n Run `npx -y evrex-mcp enrol` first, or set EVREX_TOKEN.");
3784
3816
  process.exit(1);
3785
3817
  }
@@ -3796,7 +3828,7 @@ async function durability(target, argv) {
3796
3828
  }
3797
3829
  const res = await fetch(`${evrexApi2.baseUrl}/ingest/commits/durability`, {
3798
3830
  method: "POST",
3799
- headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
3831
+ headers: { "content-type": "application/json", authorization: `Bearer ${token2}` },
3800
3832
  body: JSON.stringify({ repoId, measurements })
3801
3833
  });
3802
3834
  if (!res.ok) {
@@ -3812,8 +3844,8 @@ async function parents(target) {
3812
3844
  const { deriveRepoId: deriveRepoId2 } = await Promise.resolve().then(() => (init_src(), src_exports));
3813
3845
  const { execFileSync: execFileSync5 } = await import("node:child_process");
3814
3846
  const { evrexApi: evrexApi2 } = await Promise.resolve().then(() => (init_client(), client_exports));
3815
- const token = process.env.EVREX_TOKEN ?? await new (await Promise.resolve().then(() => (init_credential_store(), credential_store_exports))).CredentialStore().retrieve().catch(() => null);
3816
- if (!token) {
3847
+ const token2 = process.env.EVREX_TOKEN ?? await new (await Promise.resolve().then(() => (init_credential_store(), credential_store_exports))).CredentialStore().retrieve().catch(() => null);
3848
+ if (!token2) {
3817
3849
  console.error("evrex: this machine is not enrolled.\n Run `npx -y evrex-mcp enrol` first, or set EVREX_TOKEN.");
3818
3850
  process.exit(1);
3819
3851
  }
@@ -3828,7 +3860,7 @@ async function parents(target) {
3828
3860
  for (let i = 0; i < rows.length; i += 500) {
3829
3861
  const res = await fetch(`${evrexApi2.baseUrl}/ingest/commits/parents`, {
3830
3862
  method: "POST",
3831
- headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
3863
+ headers: { "content-type": "application/json", authorization: `Bearer ${token2}` },
3832
3864
  body: JSON.stringify({ repoId, commits: rows.slice(i, i + 500) })
3833
3865
  });
3834
3866
  if (!res.ok) {
@@ -3853,8 +3885,8 @@ async function main() {
3853
3885
  const target = resolve(process.argv[3] ?? process.cwd());
3854
3886
  const { evrexApi: evrexApi2 } = await Promise.resolve().then(() => (init_client(), client_exports));
3855
3887
  const { CredentialStore: CredentialStore2 } = await Promise.resolve().then(() => (init_credential_store(), credential_store_exports));
3856
- const token = process.env.EVREX_TOKEN ?? await new CredentialStore2().retrieve().catch(() => null);
3857
- if (!token) {
3888
+ const token2 = process.env.EVREX_TOKEN ?? await new CredentialStore2().retrieve().catch(() => null);
3889
+ if (!token2) {
3858
3890
  console.error(
3859
3891
  "evrex: this machine is not enrolled.\n Run `npx -y evrex-mcp enrol` first, or set EVREX_TOKEN."
3860
3892
  );
@@ -3873,7 +3905,7 @@ async function main() {
3873
3905
  method: "POST",
3874
3906
  headers: {
3875
3907
  "content-type": "application/json",
3876
- authorization: `Bearer ${token}`
3908
+ authorization: `Bearer ${token2}`
3877
3909
  },
3878
3910
  body: JSON.stringify(body)
3879
3911
  });