@gwdn/nexus-mcp 0.7.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/.github/workflows/ci.yml +38 -0
- package/.github/workflows/release.yml +57 -0
- package/README.md +89 -0
- package/dist/auth.d.ts +39 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +47 -0
- package/dist/auth.js.map +1 -0
- package/dist/nexus-api.d.ts +35 -0
- package/dist/nexus-api.d.ts.map +1 -0
- package/dist/nexus-api.js +90 -0
- package/dist/nexus-api.js.map +1 -0
- package/dist/server.d.ts +67 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +189 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/add-task-note.d.ts +34 -0
- package/dist/tools/add-task-note.d.ts.map +1 -0
- package/dist/tools/add-task-note.js +39 -0
- package/dist/tools/add-task-note.js.map +1 -0
- package/dist/tools/append-session-entry.d.ts +53 -0
- package/dist/tools/append-session-entry.d.ts.map +1 -0
- package/dist/tools/append-session-entry.js +68 -0
- package/dist/tools/append-session-entry.js.map +1 -0
- package/dist/tools/create-task.d.ts +52 -0
- package/dist/tools/create-task.d.ts.map +1 -0
- package/dist/tools/create-task.js +51 -0
- package/dist/tools/create-task.js.map +1 -0
- package/dist/tools/decision-comments.d.ts +54 -0
- package/dist/tools/decision-comments.d.ts.map +1 -0
- package/dist/tools/decision-comments.js +81 -0
- package/dist/tools/decision-comments.js.map +1 -0
- package/dist/tools/get-document.d.ts +47 -0
- package/dist/tools/get-document.d.ts.map +1 -0
- package/dist/tools/get-document.js +68 -0
- package/dist/tools/get-document.js.map +1 -0
- package/dist/tools/get-project-memory.d.ts +47 -0
- package/dist/tools/get-project-memory.d.ts.map +1 -0
- package/dist/tools/get-project-memory.js +53 -0
- package/dist/tools/get-project-memory.js.map +1 -0
- package/dist/tools/get-related-entities.d.ts +44 -0
- package/dist/tools/get-related-entities.d.ts.map +1 -0
- package/dist/tools/get-related-entities.js +60 -0
- package/dist/tools/get-related-entities.js.map +1 -0
- package/dist/tools/governance.d.ts +90 -0
- package/dist/tools/governance.d.ts.map +1 -0
- package/dist/tools/governance.js +127 -0
- package/dist/tools/governance.js.map +1 -0
- package/dist/tools/ingest-document.d.ts +40 -0
- package/dist/tools/ingest-document.d.ts.map +1 -0
- package/dist/tools/ingest-document.js +49 -0
- package/dist/tools/ingest-document.js.map +1 -0
- package/dist/tools/letter-inbox.d.ts +80 -0
- package/dist/tools/letter-inbox.d.ts.map +1 -0
- package/dist/tools/letter-inbox.js +118 -0
- package/dist/tools/letter-inbox.js.map +1 -0
- package/dist/tools/letters.d.ts +91 -0
- package/dist/tools/letters.d.ts.map +1 -0
- package/dist/tools/letters.js +112 -0
- package/dist/tools/letters.js.map +1 -0
- package/dist/tools/list-documents.d.ts +33 -0
- package/dist/tools/list-documents.d.ts.map +1 -0
- package/dist/tools/list-documents.js +47 -0
- package/dist/tools/list-documents.js.map +1 -0
- package/dist/tools/list-tasks.d.ts +39 -0
- package/dist/tools/list-tasks.d.ts.map +1 -0
- package/dist/tools/list-tasks.js +46 -0
- package/dist/tools/list-tasks.js.map +1 -0
- package/dist/tools/project-list.d.ts +28 -0
- package/dist/tools/project-list.d.ts.map +1 -0
- package/dist/tools/project-list.js +43 -0
- package/dist/tools/project-list.js.map +1 -0
- package/dist/tools/reviews.d.ts +145 -0
- package/dist/tools/reviews.d.ts.map +1 -0
- package/dist/tools/reviews.js +220 -0
- package/dist/tools/reviews.js.map +1 -0
- package/dist/tools/search-knowledge.d.ts +48 -0
- package/dist/tools/search-knowledge.d.ts.map +1 -0
- package/dist/tools/search-knowledge.js +54 -0
- package/dist/tools/search-knowledge.js.map +1 -0
- package/dist/tools/sessions.d.ts +81 -0
- package/dist/tools/sessions.d.ts.map +1 -0
- package/dist/tools/sessions.js +123 -0
- package/dist/tools/sessions.js.map +1 -0
- package/dist/tools/skill-assign.d.ts +77 -0
- package/dist/tools/skill-assign.d.ts.map +1 -0
- package/dist/tools/skill-assign.js +108 -0
- package/dist/tools/skill-assign.js.map +1 -0
- package/dist/tools/skills.d.ts +138 -0
- package/dist/tools/skills.d.ts.map +1 -0
- package/dist/tools/skills.js +195 -0
- package/dist/tools/skills.js.map +1 -0
- package/dist/tools/update-task-status.d.ts +48 -0
- package/dist/tools/update-task-status.d.ts.map +1 -0
- package/dist/tools/update-task-status.js +51 -0
- package/dist/tools/update-task-status.js.map +1 -0
- package/package.json +30 -0
- package/src/__tests__/auth.test.ts +162 -0
- package/src/__tests__/decision-comments.test.ts +173 -0
- package/src/__tests__/e2e-integration.test.ts +443 -0
- package/src/__tests__/helpers.ts +58 -0
- package/src/__tests__/layer1-knowledge.test.ts +302 -0
- package/src/__tests__/layer2-coordination.test.ts +842 -0
- package/src/__tests__/layer3-governance.test.ts +205 -0
- package/src/__tests__/project-list-and-skill-assign.test.ts +282 -0
- package/src/__tests__/reviews.test.ts +420 -0
- package/src/__tests__/server.test.ts +250 -0
- package/src/__tests__/setup.ts +15 -0
- package/src/__tests__/task-list-and-doc-list.test.ts +226 -0
- package/src/auth.ts +81 -0
- package/src/nexus-api.ts +127 -0
- package/src/server.ts +520 -0
- package/src/tools/add-task-note.ts +50 -0
- package/src/tools/append-session-entry.ts +84 -0
- package/src/tools/create-task.ts +66 -0
- package/src/tools/decision-comments.ts +103 -0
- package/src/tools/get-document.ts +80 -0
- package/src/tools/get-project-memory.ts +65 -0
- package/src/tools/get-related-entities.ts +73 -0
- package/src/tools/governance.ts +165 -0
- package/src/tools/ingest-document.ts +65 -0
- package/src/tools/letter-inbox.ts +157 -0
- package/src/tools/letters.ts +144 -0
- package/src/tools/list-documents.ts +58 -0
- package/src/tools/list-tasks.ts +57 -0
- package/src/tools/project-list.ts +52 -0
- package/src/tools/reviews.ts +281 -0
- package/src/tools/search-knowledge.ts +68 -0
- package/src/tools/sessions.ts +157 -0
- package/src/tools/skill-assign.ts +142 -0
- package/src/tools/skills.ts +255 -0
- package/src/tools/update-task-status.ts +64 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test (Node ${{ matrix.node-version }})
|
|
12
|
+
runs-on: blacksmith-2vcpu-ubuntu-2204
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
node-version: [20, 22]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Setup Node.js ${{ matrix.node-version }}
|
|
23
|
+
uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: ${{ matrix.node-version }}
|
|
26
|
+
cache: npm
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: npm ci
|
|
30
|
+
|
|
31
|
+
- name: Typecheck
|
|
32
|
+
run: npm run typecheck
|
|
33
|
+
|
|
34
|
+
- name: Test
|
|
35
|
+
run: npm test
|
|
36
|
+
|
|
37
|
+
- name: Build
|
|
38
|
+
run: npm run build
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release:
|
|
13
|
+
name: Publish to npm
|
|
14
|
+
runs-on: blacksmith-2vcpu-ubuntu-2204
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Setup Node.js
|
|
21
|
+
uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: 22
|
|
24
|
+
cache: npm
|
|
25
|
+
registry-url: https://registry.npmjs.org
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: npm ci
|
|
29
|
+
|
|
30
|
+
- name: Typecheck
|
|
31
|
+
run: npm run typecheck
|
|
32
|
+
|
|
33
|
+
- name: Test
|
|
34
|
+
run: npm test
|
|
35
|
+
|
|
36
|
+
- name: Build
|
|
37
|
+
run: npm run build
|
|
38
|
+
|
|
39
|
+
- name: Verify version matches tag
|
|
40
|
+
run: |
|
|
41
|
+
PKG_VERSION="v$(node -p "require('./package.json').version")"
|
|
42
|
+
TAG_VERSION="${GITHUB_REF#refs/tags/}"
|
|
43
|
+
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
|
|
44
|
+
echo "ERROR: package.json version ($PKG_VERSION) does not match tag ($TAG_VERSION)"
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
echo "Version verified: $TAG_VERSION"
|
|
48
|
+
|
|
49
|
+
- name: Publish to npm
|
|
50
|
+
run: npm publish --access public
|
|
51
|
+
env:
|
|
52
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
53
|
+
|
|
54
|
+
- name: Create GitHub Release
|
|
55
|
+
uses: softprops/action-gh-release@v2
|
|
56
|
+
with:
|
|
57
|
+
generate_release_notes: true
|
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# nexus-mcp
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@gwdn/nexus-mcp)
|
|
4
|
+
|
|
5
|
+
MCP server for the Nexus platform. Provides the mediation layer between
|
|
6
|
+
local agent runtimes (terminals) and the Nexus HTTP API.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npx @gwdn/nexus-mcp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or add to your agent's MCP configuration:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"mcpServers": {
|
|
19
|
+
"nexus": {
|
|
20
|
+
"command": "npx",
|
|
21
|
+
"args": ["-y", "@gwdn/nexus-mcp"],
|
|
22
|
+
"env": {
|
|
23
|
+
"NEXUS_API_URL": "https://nexus.gatewarden.eu",
|
|
24
|
+
"NEXUS_PRIVATE_TOKEN": "nxs_pat_..."
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
The server exposes 38 tools across 4 layers via the Model Context Protocol
|
|
34
|
+
(stdio transport). All data access goes through the Nexus API — the MCP server
|
|
35
|
+
has no direct database access.
|
|
36
|
+
|
|
37
|
+
- **Layer 1 — Knowledge Access:** kb_search, kb_memory, kb_get, kb_related, project_list
|
|
38
|
+
- **Layer 2 — Coordination:** vault letters (vl_create/vl_reply/vl_inbox/vl_outbox/vl_ack),
|
|
39
|
+
tasks (task_create/task_update/task_note/task_list), sessions (session_create/session_list/session_close/session_append),
|
|
40
|
+
decision comments (dc_add/dc_list), documents (doc_ingest/doc_list),
|
|
41
|
+
skills (sk_list/sk_get/sk_create/sk_update/sk_activate/sk_assign/sk_unassign/sk_export)
|
|
42
|
+
- **Layer 3 — Governance:** ADR lifecycle (adr_create/adr_submit/adr_decide)
|
|
43
|
+
- **Layer 4 — Reviews:** entity reviews (rv_list/rv_get/rv_create/rv_decide/rv_comment)
|
|
44
|
+
|
|
45
|
+
## Authentication
|
|
46
|
+
|
|
47
|
+
Identity is resolved once at startup via `GET /api/mcp/identity` using the
|
|
48
|
+
`NEXUS_PRIVATE_TOKEN` as a Bearer token. All subsequent API calls use the same
|
|
49
|
+
token for authentication. The Nexus backend resolves the token to a user
|
|
50
|
+
identity and enforces project-scoped RBAC.
|
|
51
|
+
|
|
52
|
+
## Environment Variables
|
|
53
|
+
|
|
54
|
+
| Variable | Required | Description |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `NEXUS_API_URL` | yes | Nexus API base URL (e.g. `https://nexus.gatewarden.eu`) |
|
|
57
|
+
| `NEXUS_PRIVATE_TOKEN` | yes | nxs_pat_* API token for identity resolution |
|
|
58
|
+
|
|
59
|
+
## Development
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install
|
|
63
|
+
npm run typecheck # TypeScript check
|
|
64
|
+
npm test # Run tests
|
|
65
|
+
npm run build # Compile to dist/
|
|
66
|
+
npm run dev # Run via tsx (development)
|
|
67
|
+
npm start # Run compiled JS (production)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Project Structure
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
src/
|
|
74
|
+
server.ts # MCP server entry point (stdio transport)
|
|
75
|
+
auth.ts # Token-based identity resolution via Nexus API
|
|
76
|
+
nexus-api.ts # HTTP client for Nexus API (nexusGet, nexusPost)
|
|
77
|
+
tools/ # Tool modules (38 tools total)
|
|
78
|
+
__tests__/ # Unit tests (112) and E2E integration tests (34)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Related
|
|
82
|
+
|
|
83
|
+
- [nexus](https://github.com/gwnexus/nexus-hub) — Backend + Frontend (Next.js/Supabase/Netlify)
|
|
84
|
+
- [nexus-cli](https://github.com/gwnexus/nexus-cli) — Rust CLI client
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
Nexus is a product of the Nexus Product Group, owned by
|
|
89
|
+
RelicFrog Holding UG (haftungsbeschränkt).
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Authentication Layer
|
|
3
|
+
*
|
|
4
|
+
* Resolves the NEXUS_PRIVATE_TOKEN environment variable at server startup
|
|
5
|
+
* to a verified user identity by calling the Nexus API identity endpoint.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. Read NEXUS_PRIVATE_TOKEN from process.env
|
|
9
|
+
* 2. Call GET /api/mcp/identity with Bearer token
|
|
10
|
+
* 3. Cache resolved identity for the lifetime of the MCP process
|
|
11
|
+
*/
|
|
12
|
+
export interface McpIdentity {
|
|
13
|
+
userId: string;
|
|
14
|
+
email: string | null;
|
|
15
|
+
displayName: string | null;
|
|
16
|
+
isPlatformAdmin: boolean;
|
|
17
|
+
isPlatformOwner: boolean;
|
|
18
|
+
tenantId: string | null;
|
|
19
|
+
memberships: Array<{
|
|
20
|
+
project_id: string;
|
|
21
|
+
role: string;
|
|
22
|
+
}>;
|
|
23
|
+
agentAssignments: Array<{
|
|
24
|
+
project_id: string;
|
|
25
|
+
agent_id: string;
|
|
26
|
+
agent_owner: string;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the MCP server identity from NEXUS_PRIVATE_TOKEN.
|
|
31
|
+
* Called once at server startup. Caches the result.
|
|
32
|
+
* Throws if no valid token is available.
|
|
33
|
+
*/
|
|
34
|
+
export declare function initIdentity(): Promise<McpIdentity>;
|
|
35
|
+
/**
|
|
36
|
+
* Get the cached MCP identity. Must call initIdentity() first.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getIdentity(): McpIdentity;
|
|
39
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,eAAe,EAAE,OAAO,CAAA;IACxB,eAAe,EAAE,OAAO,CAAA;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxD,gBAAgB,EAAE,KAAK,CAAC;QACtB,UAAU,EAAE,MAAM,CAAA;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAC,CAAA;CACH;AASD;;;;GAIG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC,CAyBzD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,WAAW,CAKzC"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Authentication Layer
|
|
3
|
+
*
|
|
4
|
+
* Resolves the NEXUS_PRIVATE_TOKEN environment variable at server startup
|
|
5
|
+
* to a verified user identity by calling the Nexus API identity endpoint.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. Read NEXUS_PRIVATE_TOKEN from process.env
|
|
9
|
+
* 2. Call GET /api/mcp/identity with Bearer token
|
|
10
|
+
* 3. Cache resolved identity for the lifetime of the MCP process
|
|
11
|
+
*/
|
|
12
|
+
import { nexusGet } from './nexus-api.js';
|
|
13
|
+
// Module-level cache: resolved once at startup
|
|
14
|
+
let _identity = null;
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Public API
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Resolve the MCP server identity from NEXUS_PRIVATE_TOKEN.
|
|
20
|
+
* Called once at server startup. Caches the result.
|
|
21
|
+
* Throws if no valid token is available.
|
|
22
|
+
*/
|
|
23
|
+
export async function initIdentity() {
|
|
24
|
+
if (_identity)
|
|
25
|
+
return _identity;
|
|
26
|
+
const rawToken = process.env.NEXUS_PRIVATE_TOKEN;
|
|
27
|
+
if (!rawToken) {
|
|
28
|
+
throw new Error('MCP: NEXUS_PRIVATE_TOKEN is not set. The MCP server requires a valid nxs_pat_* token.');
|
|
29
|
+
}
|
|
30
|
+
const result = await nexusGet('/api/mcp/identity');
|
|
31
|
+
if (!result.ok || !result.data) {
|
|
32
|
+
throw new Error(`MCP: Identity resolution failed: ${result.error ?? 'Unknown error'}. Check that the token is valid, not expired, and not revoked.`);
|
|
33
|
+
}
|
|
34
|
+
_identity = result.data;
|
|
35
|
+
console.error(`[nexus-mcp] Identity resolved: ${_identity.displayName ?? _identity.email ?? _identity.userId} (admin=${_identity.isPlatformAdmin}, owner=${_identity.isPlatformOwner})`);
|
|
36
|
+
return _identity;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the cached MCP identity. Must call initIdentity() first.
|
|
40
|
+
*/
|
|
41
|
+
export function getIdentity() {
|
|
42
|
+
if (!_identity) {
|
|
43
|
+
throw new Error('MCP: Identity not initialized. Call initIdentity() first.');
|
|
44
|
+
}
|
|
45
|
+
return _identity;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAqBzC,+CAA+C;AAC/C,IAAI,SAAS,GAAuB,IAAI,CAAA;AAExC,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,SAAS;QAAE,OAAO,SAAS,CAAA;IAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAA;IAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAc,mBAAmB,CAAC,CAAA;IAE/D,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,oCAAoC,MAAM,CAAC,KAAK,IAAI,eAAe,gEAAgE,CACpI,CAAA;IACH,CAAC;IAED,SAAS,GAAG,MAAM,CAAC,IAAI,CAAA;IAEvB,OAAO,CAAC,KAAK,CACX,kCAAkC,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,WAAW,SAAS,CAAC,eAAe,WAAW,SAAS,CAAC,eAAe,GAAG,CAC1K,CAAA;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAA;IAC9E,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus API client for MCP server context.
|
|
3
|
+
*
|
|
4
|
+
* Replaces direct Supabase access with HTTP calls to the Nexus API.
|
|
5
|
+
* All operations go through /api/mcp/* endpoints, authenticated
|
|
6
|
+
* via the NEXUS_PRIVATE_TOKEN (nxs_pat_*) Bearer token.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Reset the cached API configuration. Used by E2E tests to switch
|
|
10
|
+
* from mocked env vars to real credentials.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resetApiConfig(): void;
|
|
13
|
+
export interface NexusApiResponse<T = unknown> {
|
|
14
|
+
ok: boolean;
|
|
15
|
+
status: number;
|
|
16
|
+
data: T | null;
|
|
17
|
+
error: string | null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Make an authenticated request to the Nexus API.
|
|
21
|
+
*/
|
|
22
|
+
export declare function nexusApi<T = unknown>(path: string, options?: {
|
|
23
|
+
method?: 'GET' | 'POST' | 'PATCH' | 'DELETE';
|
|
24
|
+
body?: unknown;
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
}): Promise<NexusApiResponse<T>>;
|
|
27
|
+
/**
|
|
28
|
+
* Convenience: POST to a Nexus MCP endpoint.
|
|
29
|
+
*/
|
|
30
|
+
export declare function nexusPost<T = unknown>(path: string, body: unknown): Promise<NexusApiResponse<T>>;
|
|
31
|
+
/**
|
|
32
|
+
* Convenience: GET from a Nexus MCP endpoint.
|
|
33
|
+
*/
|
|
34
|
+
export declare function nexusGet<T = unknown>(path: string): Promise<NexusApiResponse<T>>;
|
|
35
|
+
//# sourceMappingURL=nexus-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nexus-api.d.ts","sourceRoot":"","sources":["../src/nexus-api.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;;GAGG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AA0BD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC3C,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAKD;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;IAC5C,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACd,GACL,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CA2C9B;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,GAAG,OAAO,EACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAE9B;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAE9B"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus API client for MCP server context.
|
|
3
|
+
*
|
|
4
|
+
* Replaces direct Supabase access with HTTP calls to the Nexus API.
|
|
5
|
+
* All operations go through /api/mcp/* endpoints, authenticated
|
|
6
|
+
* via the NEXUS_PRIVATE_TOKEN (nxs_pat_*) Bearer token.
|
|
7
|
+
*/
|
|
8
|
+
let _baseUrl = null;
|
|
9
|
+
let _token = null;
|
|
10
|
+
/**
|
|
11
|
+
* Reset the cached API configuration. Used by E2E tests to switch
|
|
12
|
+
* from mocked env vars to real credentials.
|
|
13
|
+
*/
|
|
14
|
+
export function resetApiConfig() {
|
|
15
|
+
_baseUrl = null;
|
|
16
|
+
_token = null;
|
|
17
|
+
}
|
|
18
|
+
function getConfig() {
|
|
19
|
+
if (_baseUrl && _token)
|
|
20
|
+
return { baseUrl: _baseUrl, token: _token };
|
|
21
|
+
const url = process.env.NEXUS_API_URL ?? process.env.NEXUS_URL;
|
|
22
|
+
const token = process.env.NEXUS_PRIVATE_TOKEN;
|
|
23
|
+
if (!url) {
|
|
24
|
+
throw new Error('MCP: Missing NEXUS_API_URL. Set the base URL of the Nexus app (e.g. https://nexus.gatewarden.eu).');
|
|
25
|
+
}
|
|
26
|
+
if (!token) {
|
|
27
|
+
throw new Error('MCP: Missing NEXUS_PRIVATE_TOKEN. The MCP server requires a valid nxs_pat_* token.');
|
|
28
|
+
}
|
|
29
|
+
// Normalize: strip trailing slash
|
|
30
|
+
_baseUrl = url.replace(/\/$/, '');
|
|
31
|
+
_token = token.trim();
|
|
32
|
+
return { baseUrl: _baseUrl, token: _token };
|
|
33
|
+
}
|
|
34
|
+
/** Default HTTP timeout in milliseconds (30 seconds). */
|
|
35
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
36
|
+
/**
|
|
37
|
+
* Make an authenticated request to the Nexus API.
|
|
38
|
+
*/
|
|
39
|
+
export async function nexusApi(path, options = {}) {
|
|
40
|
+
const { baseUrl, token } = getConfig();
|
|
41
|
+
const method = options.method ?? 'GET';
|
|
42
|
+
const url = `${baseUrl}${path}`;
|
|
43
|
+
const headers = {
|
|
44
|
+
Authorization: `Bearer ${token}`,
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
};
|
|
47
|
+
try {
|
|
48
|
+
const fetchOpts = {
|
|
49
|
+
method,
|
|
50
|
+
headers,
|
|
51
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS),
|
|
52
|
+
};
|
|
53
|
+
if (options.body !== undefined) {
|
|
54
|
+
fetchOpts.body = JSON.stringify(options.body);
|
|
55
|
+
}
|
|
56
|
+
const response = await fetch(url, fetchOpts);
|
|
57
|
+
const data = (await response.json());
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
status: response.status,
|
|
62
|
+
data: null,
|
|
63
|
+
error: data?.error ??
|
|
64
|
+
`HTTP ${response.status}`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return { ok: true, status: response.status, data, error: null };
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
return {
|
|
71
|
+
ok: false,
|
|
72
|
+
status: 0,
|
|
73
|
+
data: null,
|
|
74
|
+
error: err instanceof Error ? err.message : 'Unknown fetch error',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Convenience: POST to a Nexus MCP endpoint.
|
|
80
|
+
*/
|
|
81
|
+
export async function nexusPost(path, body) {
|
|
82
|
+
return nexusApi(path, { method: 'POST', body });
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Convenience: GET from a Nexus MCP endpoint.
|
|
86
|
+
*/
|
|
87
|
+
export async function nexusGet(path) {
|
|
88
|
+
return nexusApi(path, { method: 'GET' });
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=nexus-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nexus-api.js","sourceRoot":"","sources":["../src/nexus-api.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* nexus-mcp -- MCP Server for Nexus
|
|
4
|
+
*
|
|
5
|
+
* Provides Knowledge Access (Layer 1), Coordination (Layer 2),
|
|
6
|
+
* Governance (Layer 3), and Reviews (Layer 4) tools.
|
|
7
|
+
* Runs as a standalone stdio MCP server.
|
|
8
|
+
*
|
|
9
|
+
* Authentication:
|
|
10
|
+
* Identity is resolved once at startup from NEXUS_PRIVATE_TOKEN (nxs_pat_*).
|
|
11
|
+
* All write tools receive user_id automatically from the resolved identity.
|
|
12
|
+
* Callers no longer pass user_id as a parameter.
|
|
13
|
+
*
|
|
14
|
+
* Layer 1 - Knowledge Access:
|
|
15
|
+
* - kb_search: Search project knowledge (keyword/semantic/hybrid)
|
|
16
|
+
* - kb_memory: Curated project context for agent bootstrapping
|
|
17
|
+
* - kb_get: Fetch a single knowledge object
|
|
18
|
+
* - kb_related: Navigate entity relationships
|
|
19
|
+
* - project_list: List accessible projects
|
|
20
|
+
*
|
|
21
|
+
* Layer 2 - Coordination:
|
|
22
|
+
* - vl_create: Create a new vault letter
|
|
23
|
+
* - vl_reply: Reply to an existing vault letter
|
|
24
|
+
* - vl_inbox: List letters addressed to the calling agent/user
|
|
25
|
+
* - vl_outbox: List letters sent by the calling agent/user
|
|
26
|
+
* - vl_ack: Acknowledge receipt of a new vault letter
|
|
27
|
+
* - task_create: Create a task in a project
|
|
28
|
+
* - task_update: Update task status, priority, or assignee
|
|
29
|
+
* - task_note: Append a note to a task (append-only)
|
|
30
|
+
* - task_list: List tasks for a project with filters
|
|
31
|
+
* - dc_add: Add a comment to an ADR (append-only)
|
|
32
|
+
* - dc_list: List comments for an ADR
|
|
33
|
+
* - sk_list: List skills for the current tenant
|
|
34
|
+
* - sk_get: Get full skill content by identifier
|
|
35
|
+
* - sk_create: Create a new skill in draft status
|
|
36
|
+
* - sk_update: Update skill content or metadata
|
|
37
|
+
* - sk_activate: Change skill status (draft/active/archived)
|
|
38
|
+
* - sk_assign: Assign a skill to a project
|
|
39
|
+
* - sk_unassign: Remove a skill assignment from a project
|
|
40
|
+
* - sk_export: Export all skill assignments for a project
|
|
41
|
+
* - doc_ingest: Push text/markdown content into project knowledge base
|
|
42
|
+
* - doc_list: List ingested documents for a project
|
|
43
|
+
* - session_append: Append to a session (write-isolated)
|
|
44
|
+
* - session_create: Start a new work session
|
|
45
|
+
* - session_close: End a session with summary and next entry point
|
|
46
|
+
* - session_list: List open sessions for a project
|
|
47
|
+
*
|
|
48
|
+
* Layer 3 - Governance:
|
|
49
|
+
* - adr_create: Create a new ADR draft
|
|
50
|
+
* - adr_submit: Submit an ADR for review
|
|
51
|
+
* - adr_decide: Accept or reject an ADR
|
|
52
|
+
*
|
|
53
|
+
* Layer 4 - Reviews:
|
|
54
|
+
* - rv_list: List reviews with optional filters
|
|
55
|
+
* - rv_get: Get a review by ID or entity reference
|
|
56
|
+
* - rv_create: Create a new review for an entity
|
|
57
|
+
* - rv_decide: Transition a review state
|
|
58
|
+
* - rv_comment: Add a comment to a review
|
|
59
|
+
*
|
|
60
|
+
* Usage:
|
|
61
|
+
* npx tsx src/mcp/server.ts
|
|
62
|
+
*
|
|
63
|
+
* Or via .mcp.json configuration:
|
|
64
|
+
* { "command": "npx", "args": ["tsx", "src/mcp/server.ts"] }
|
|
65
|
+
*/
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG"}
|