evrex-mcp 0.9.1 → 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 +24 -0
- package/dist/account.js +24 -2
- package/dist/capture.js +35 -5
- package/dist/continuity.js +24 -2
- package/dist/hook.js +24 -2
- package/dist/import.js +42 -12
- package/dist/index.js +1534 -1164
- package/dist/pretool.js +24 -2
- package/dist/tickets.js +36 -6
- package/package.json +16 -15
package/dist/pretool.js
CHANGED
|
@@ -3,21 +3,42 @@
|
|
|
3
3
|
// src/pretool.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
|
-
|
|
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
|
|
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/tickets.js
CHANGED
|
@@ -9,18 +9,39 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// src/request-context.ts
|
|
13
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
14
|
+
function currentRequest() {
|
|
15
|
+
return storage.getStore();
|
|
16
|
+
}
|
|
17
|
+
var storage;
|
|
18
|
+
var init_request_context = __esm({
|
|
19
|
+
"src/request-context.ts"() {
|
|
20
|
+
"use strict";
|
|
21
|
+
storage = new AsyncLocalStorage();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
12
25
|
// src/client.ts
|
|
13
26
|
var client_exports = {};
|
|
14
27
|
__export(client_exports, {
|
|
28
|
+
EvrexApiError: () => EvrexApiError,
|
|
15
29
|
evrexApi: () => evrexApi
|
|
16
30
|
});
|
|
31
|
+
function token() {
|
|
32
|
+
return currentRequest()?.token ?? EVREX_TOKEN;
|
|
33
|
+
}
|
|
17
34
|
function headers() {
|
|
18
35
|
const base = { "Content-Type": "application/json" };
|
|
19
|
-
|
|
36
|
+
const credential = token();
|
|
37
|
+
if (credential) base.Authorization = `Bearer ${credential}`;
|
|
20
38
|
return base;
|
|
21
39
|
}
|
|
22
40
|
function describeFailure(method, path, status, statusText) {
|
|
23
41
|
if (status === 401 || status === 403) {
|
|
42
|
+
if (currentRequest()) {
|
|
43
|
+
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.`;
|
|
44
|
+
}
|
|
24
45
|
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.`;
|
|
25
46
|
}
|
|
26
47
|
return `${method} ${path} -> ${status} ${statusText}`;
|
|
@@ -32,22 +53,31 @@ async function request(method, path, { body, absentIsAnswer } = {}) {
|
|
|
32
53
|
...body === void 0 ? {} : { body: JSON.stringify(body) }
|
|
33
54
|
});
|
|
34
55
|
if (res.status === 404 && absentIsAnswer) return null;
|
|
35
|
-
if (!res.ok) throw new
|
|
56
|
+
if (!res.ok) throw new EvrexApiError(describeFailure(method, path, res.status, res.statusText), res.status);
|
|
36
57
|
return await res.json();
|
|
37
58
|
}
|
|
38
|
-
var DEFAULT_API_BASE_URL, API_BASE_URL, EVREX_TOKEN, get, getOrNull, post, evrexApi;
|
|
59
|
+
var DEFAULT_API_BASE_URL, API_BASE_URL, EVREX_TOKEN, EvrexApiError, get, getOrNull, post, evrexApi;
|
|
39
60
|
var init_client = __esm({
|
|
40
61
|
"src/client.ts"() {
|
|
41
62
|
"use strict";
|
|
63
|
+
init_request_context();
|
|
42
64
|
DEFAULT_API_BASE_URL = "https://api.evrex.ai";
|
|
43
65
|
API_BASE_URL = (process.env.EVREX_API_BASE_URL ?? process.env.EVREX_API_URL ?? DEFAULT_API_BASE_URL).replace(/\/+$/, "");
|
|
44
66
|
EVREX_TOKEN = process.env.EVREX_TOKEN ?? process.env.EVREX_API_TOKEN ?? null;
|
|
67
|
+
EvrexApiError = class extends Error {
|
|
68
|
+
constructor(message, status) {
|
|
69
|
+
super(message);
|
|
70
|
+
this.status = status;
|
|
71
|
+
this.name = "EvrexApiError";
|
|
72
|
+
}
|
|
73
|
+
};
|
|
45
74
|
get = (path) => request("GET", path);
|
|
46
75
|
getOrNull = (path) => request("GET", path, { absentIsAnswer: true });
|
|
47
76
|
post = (path, body) => request("POST", path, { body });
|
|
48
77
|
evrexApi = {
|
|
49
78
|
baseUrl: API_BASE_URL,
|
|
50
79
|
repos: () => get("/repos"),
|
|
80
|
+
me: () => get("/auth/me"),
|
|
51
81
|
commits: (repoPath) => get(`/commits?repoPath=${encodeURIComponent(repoPath)}`),
|
|
52
82
|
// Abbreviated shas resolve server-side, so a value pasted from `git log`
|
|
53
83
|
// works here (apps/backend/src/reads/reads.service.ts#resolveSha).
|
|
@@ -611,8 +641,8 @@ async function syncTickets(deps) {
|
|
|
611
641
|
async function main() {
|
|
612
642
|
const { evrexApi: evrexApi2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
613
643
|
const { CredentialStore: CredentialStore2 } = await Promise.resolve().then(() => (init_credential_store(), credential_store_exports));
|
|
614
|
-
const
|
|
615
|
-
if (!
|
|
644
|
+
const token2 = process.env.EVREX_TOKEN ?? await new CredentialStore2().retrieve().catch(() => null);
|
|
645
|
+
if (!token2) {
|
|
616
646
|
console.error(
|
|
617
647
|
"evrex: this machine is not enrolled.\n Run `npx -y evrex-mcp enrol` first, or set EVREX_TOKEN."
|
|
618
648
|
);
|
|
@@ -627,7 +657,7 @@ async function main() {
|
|
|
627
657
|
method: "POST",
|
|
628
658
|
headers: {
|
|
629
659
|
"content-type": "application/json",
|
|
630
|
-
authorization: `Bearer ${
|
|
660
|
+
authorization: `Bearer ${token2}`
|
|
631
661
|
},
|
|
632
662
|
body: JSON.stringify(body)
|
|
633
663
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evrex-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "MCP server that gives coding agents the recorded reasoning behind a repo: prior decisions, hard constraints, and approaches already rejected.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -36,27 +36,28 @@
|
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=20"
|
|
38
38
|
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc -p tsconfig.json",
|
|
41
|
+
"bundle": "node scripts/bundle.mjs",
|
|
42
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
43
|
+
"lint": "eslint .",
|
|
44
|
+
"check-types": "tsc --noEmit",
|
|
45
|
+
"test": "tsc -p tsconfig.json && node --test dist/*.test.js",
|
|
46
|
+
"prepack": "pnpm run bundle"
|
|
47
|
+
},
|
|
39
48
|
"dependencies": {
|
|
40
49
|
"@anthropic-ai/sdk": "^0.72.0",
|
|
41
50
|
"@modelcontextprotocol/sdk": "^1.20.1",
|
|
42
51
|
"zod": "^3.24.1"
|
|
43
52
|
},
|
|
44
53
|
"devDependencies": {
|
|
54
|
+
"@repo/eslint-config": "workspace:*",
|
|
55
|
+
"@repo/ingest-core": "workspace:*",
|
|
56
|
+
"@repo/llm-core": "workspace:*",
|
|
57
|
+
"@repo/typescript-config": "workspace:*",
|
|
45
58
|
"@types/node": "^24.0.0",
|
|
46
59
|
"esbuild": "^0.25.12",
|
|
47
60
|
"eslint": "^9.39.1",
|
|
48
|
-
"typescript": "^5.9.2"
|
|
49
|
-
"@repo/eslint-config": "0.0.0",
|
|
50
|
-
"@repo/ingest-core": "0.0.0",
|
|
51
|
-
"@repo/llm-core": "0.0.0",
|
|
52
|
-
"@repo/typescript-config": "0.0.0"
|
|
53
|
-
},
|
|
54
|
-
"scripts": {
|
|
55
|
-
"build": "tsc -p tsconfig.json",
|
|
56
|
-
"bundle": "node scripts/bundle.mjs",
|
|
57
|
-
"dev": "tsc -p tsconfig.json --watch",
|
|
58
|
-
"lint": "eslint .",
|
|
59
|
-
"check-types": "tsc --noEmit",
|
|
60
|
-
"test": "tsc -p tsconfig.json && node --test dist/*.test.js"
|
|
61
|
+
"typescript": "^5.9.2"
|
|
61
62
|
}
|
|
62
|
-
}
|
|
63
|
+
}
|