@gwdn/nexus-mcp 0.8.6 → 0.8.8

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 (52) hide show
  1. package/README.md +3 -4
  2. package/dist/nexus-api.d.ts.map +1 -1
  3. package/dist/nexus-api.js +10 -1
  4. package/dist/nexus-api.js.map +1 -1
  5. package/dist/server.js +1 -1
  6. package/package.json +9 -2
  7. package/.github/workflows/ci.yml +0 -38
  8. package/.github/workflows/release.yml +0 -57
  9. package/src/__tests__/auth.test.ts +0 -162
  10. package/src/__tests__/decision-comments.test.ts +0 -173
  11. package/src/__tests__/e2e-integration.test.ts +0 -443
  12. package/src/__tests__/helpers.ts +0 -58
  13. package/src/__tests__/layer1-knowledge.test.ts +0 -302
  14. package/src/__tests__/layer2-coordination.test.ts +0 -918
  15. package/src/__tests__/layer3-governance.test.ts +0 -205
  16. package/src/__tests__/machine-id.test.ts +0 -136
  17. package/src/__tests__/nexus-api.test.ts +0 -127
  18. package/src/__tests__/project-list-and-skill-assign.test.ts +0 -282
  19. package/src/__tests__/reviews.test.ts +0 -420
  20. package/src/__tests__/server.test.ts +0 -251
  21. package/src/__tests__/setup.ts +0 -15
  22. package/src/__tests__/task-list-and-doc-list.test.ts +0 -226
  23. package/src/auth.ts +0 -81
  24. package/src/machine-id.ts +0 -60
  25. package/src/nexus-api.ts +0 -141
  26. package/src/server.ts +0 -629
  27. package/src/tools/add-task-note.ts +0 -50
  28. package/src/tools/append-session-entry.ts +0 -113
  29. package/src/tools/classify-document.ts +0 -55
  30. package/src/tools/create-task.ts +0 -66
  31. package/src/tools/decision-comments.ts +0 -103
  32. package/src/tools/delete-document.ts +0 -43
  33. package/src/tools/directives.ts +0 -303
  34. package/src/tools/get-document.ts +0 -80
  35. package/src/tools/get-project-memory.ts +0 -65
  36. package/src/tools/get-related-entities.ts +0 -73
  37. package/src/tools/governance.ts +0 -165
  38. package/src/tools/ingest-document.ts +0 -65
  39. package/src/tools/letter-inbox.ts +0 -157
  40. package/src/tools/letters.ts +0 -144
  41. package/src/tools/list-documents.ts +0 -58
  42. package/src/tools/list-tasks.ts +0 -57
  43. package/src/tools/project-list.ts +0 -52
  44. package/src/tools/reviews.ts +0 -281
  45. package/src/tools/search-knowledge.ts +0 -68
  46. package/src/tools/sessions.ts +0 -157
  47. package/src/tools/skill-assign.ts +0 -142
  48. package/src/tools/skills.ts +0 -255
  49. package/src/tools/update-document.ts +0 -66
  50. package/src/tools/update-task-status.ts +0 -64
  51. package/tsconfig.json +0 -20
  52. package/vitest.config.ts +0 -8
@@ -1,302 +0,0 @@
1
- /**
2
- * Tests for Layer 1 Knowledge Access tools:
3
- * - kb_search
4
- * - kb_memory
5
- * - kb_get
6
- * - kb_related
7
- *
8
- * All tools now delegate to the Nexus API via nexusPost().
9
- * Tests mock the nexus-api module.
10
- */
11
-
12
- import { beforeEach, describe, expect, it, vi } from 'vitest'
13
- import { mockApiError, mockApiSuccess, parseToolResponse, TEST_IDS } from './helpers'
14
-
15
- vi.mock('../nexus-api.js', () => ({
16
- nexusPost: vi.fn(),
17
- }))
18
-
19
- import { nexusPost } from '../nexus-api.js'
20
-
21
- // ---------------------------------------------------------------------------
22
- // kb_search
23
- // ---------------------------------------------------------------------------
24
-
25
- describe('Layer 1: kb_search', () => {
26
- beforeEach(() => {
27
- vi.restoreAllMocks()
28
- })
29
-
30
- it('should return matching results for keyword search', async () => {
31
- vi.mocked(nexusPost).mockResolvedValue(
32
- mockApiSuccess({
33
- total_results: 1,
34
- results: [
35
- {
36
- entity_type: 'task',
37
- entity_id: TEST_IDS.taskId,
38
- title: 'Fix authentication bug',
39
- relevance: 'exact',
40
- },
41
- ],
42
- }),
43
- )
44
-
45
- const { searchKnowledge } = await import('../tools/search-knowledge.js')
46
- const result = await searchKnowledge({
47
- query: 'authentication bug',
48
- project_id: TEST_IDS.projectId,
49
- entity_types: ['task'],
50
- })
51
-
52
- expect(result.isError).toBeUndefined()
53
- const parsed = parseToolResponse(result)
54
- expect(parsed.total_results).toBe(1)
55
- expect(parsed.results[0].entity_type).toBe('task')
56
- expect(parsed.results[0].entity_id).toBe(TEST_IDS.taskId)
57
- })
58
-
59
- it('should return empty results when no matches', async () => {
60
- vi.mocked(nexusPost).mockResolvedValue(
61
- mockApiSuccess({ total_results: 0, results: [] }),
62
- )
63
-
64
- const { searchKnowledge } = await import('../tools/search-knowledge.js')
65
- const result = await searchKnowledge({
66
- query: 'nonexistent term xyz123',
67
- project_id: TEST_IDS.projectId,
68
- })
69
-
70
- const parsed = parseToolResponse(result)
71
- expect(parsed.total_results).toBe(0)
72
- expect(parsed.results).toEqual([])
73
- })
74
-
75
- it('should pass correct parameters to the API', async () => {
76
- vi.mocked(nexusPost).mockResolvedValue(
77
- mockApiSuccess({ total_results: 0, results: [] }),
78
- )
79
-
80
- const { searchKnowledge } = await import('../tools/search-knowledge.js')
81
- await searchKnowledge({
82
- query: 'test',
83
- project_id: TEST_IDS.projectId,
84
- entity_types: ['task', 'decision'],
85
- search_mode: 'hybrid',
86
- limit: 5,
87
- })
88
-
89
- expect(nexusPost).toHaveBeenCalledWith('/api/mcp/search', {
90
- project_id: TEST_IDS.projectId,
91
- query: 'test',
92
- entity_types: ['task', 'decision'],
93
- search_mode: 'hybrid',
94
- limit: 5,
95
- })
96
- })
97
-
98
- it('should handle API errors gracefully', async () => {
99
- vi.mocked(nexusPost).mockResolvedValue(mockApiError('connection lost'))
100
-
101
- const { searchKnowledge } = await import('../tools/search-knowledge.js')
102
- const result = await searchKnowledge({
103
- query: 'test',
104
- project_id: TEST_IDS.projectId,
105
- })
106
-
107
- expect(result.isError).toBe(true)
108
- const parsed = parseToolResponse(result)
109
- expect(parsed.error).toBe('connection lost')
110
- })
111
- })
112
-
113
- // ---------------------------------------------------------------------------
114
- // kb_memory
115
- // ---------------------------------------------------------------------------
116
-
117
- describe('Layer 1: kb_memory', () => {
118
- beforeEach(() => {
119
- vi.restoreAllMocks()
120
- })
121
-
122
- it('should return curated project context', async () => {
123
- vi.mocked(nexusPost).mockResolvedValue(
124
- mockApiSuccess({
125
- project_id: TEST_IDS.projectId,
126
- depth: 'standard',
127
- categories_included: ['adrs', 'active_tasks'],
128
- memory: {
129
- project: { id: TEST_IDS.projectId, name: 'Test Project' },
130
- adrs: [{ id: TEST_IDS.adrId, title: 'ADR-001', status: 'accepted' }],
131
- active_tasks: [{ id: TEST_IDS.taskId, title: 'Open task', status: 'open' }],
132
- },
133
- }),
134
- )
135
-
136
- const { getProjectMemory } = await import('../tools/get-project-memory.js')
137
- const result = await getProjectMemory({
138
- project_id: TEST_IDS.projectId,
139
- include: ['adrs', 'active_tasks'],
140
- })
141
-
142
- expect(result.isError).toBeUndefined()
143
- const parsed = parseToolResponse(result)
144
- expect(parsed.project_id).toBe(TEST_IDS.projectId)
145
- expect(parsed.memory.adrs).toHaveLength(1)
146
- expect(parsed.memory.active_tasks).toHaveLength(1)
147
- })
148
-
149
- it('should pass depth parameter to the API', async () => {
150
- vi.mocked(nexusPost).mockResolvedValue(
151
- mockApiSuccess({ project_id: TEST_IDS.projectId, depth: 'light', memory: {} }),
152
- )
153
-
154
- const { getProjectMemory } = await import('../tools/get-project-memory.js')
155
- await getProjectMemory({
156
- project_id: TEST_IDS.projectId,
157
- include: ['adrs'],
158
- depth: 'light',
159
- })
160
-
161
- expect(nexusPost).toHaveBeenCalledWith('/api/mcp/memory', {
162
- project_id: TEST_IDS.projectId,
163
- include: ['adrs'],
164
- depth: 'light',
165
- })
166
- })
167
-
168
- it('should handle API errors', async () => {
169
- vi.mocked(nexusPost).mockResolvedValue(mockApiError('Project not found'))
170
-
171
- const { getProjectMemory } = await import('../tools/get-project-memory.js')
172
- const result = await getProjectMemory({
173
- project_id: TEST_IDS.projectId,
174
- include: ['adrs'],
175
- })
176
-
177
- expect(result.isError).toBe(true)
178
- })
179
- })
180
-
181
- // ---------------------------------------------------------------------------
182
- // kb_get
183
- // ---------------------------------------------------------------------------
184
-
185
- describe('Layer 1: kb_get', () => {
186
- beforeEach(() => {
187
- vi.restoreAllMocks()
188
- })
189
-
190
- it('should fetch a document in structured mode', async () => {
191
- vi.mocked(nexusPost).mockResolvedValue(
192
- mockApiSuccess({
193
- entity_type: 'session',
194
- entity_id: TEST_IDS.sessionId,
195
- document: { id: TEST_IDS.sessionId, title: 'Test Session', status: 'open' },
196
- entries: [{ id: TEST_IDS.entryId, entry_type: 'note', summary: 'A note' }],
197
- }),
198
- )
199
-
200
- const { getDocument } = await import('../tools/get-document.js')
201
- const result = await getDocument({
202
- entity_type: 'session',
203
- entity_id: TEST_IDS.sessionId,
204
- })
205
-
206
- expect(result.isError).toBeUndefined()
207
- const parsed = parseToolResponse(result)
208
- expect(parsed.entity_type).toBe('session')
209
- expect(parsed.entity_id).toBe(TEST_IDS.sessionId)
210
- })
211
-
212
- it('should fetch a document in markdown mode', async () => {
213
- vi.mocked(nexusPost).mockResolvedValue(
214
- mockApiSuccess({
215
- entity_type: 'decision',
216
- entity_id: TEST_IDS.adrId,
217
- format: 'markdown',
218
- content: '# ADR-001\n\nSome content',
219
- }),
220
- )
221
-
222
- const { getDocument } = await import('../tools/get-document.js')
223
- const result = await getDocument({
224
- entity_type: 'decision',
225
- entity_id: TEST_IDS.adrId,
226
- render_mode: 'markdown',
227
- })
228
-
229
- expect(result.isError).toBeUndefined()
230
- expect(result.content[0].text).toContain('# ADR-001')
231
- })
232
-
233
- it('should return error for not found entity', async () => {
234
- vi.mocked(nexusPost).mockResolvedValue(mockApiError('Document not found', 404))
235
-
236
- const { getDocument } = await import('../tools/get-document.js')
237
- const result = await getDocument({
238
- entity_type: 'session',
239
- entity_id: TEST_IDS.sessionId,
240
- })
241
-
242
- expect(result.isError).toBe(true)
243
- })
244
- })
245
-
246
- // ---------------------------------------------------------------------------
247
- // kb_related
248
- // ---------------------------------------------------------------------------
249
-
250
- describe('Layer 1: kb_related', () => {
251
- beforeEach(() => {
252
- vi.restoreAllMocks()
253
- })
254
-
255
- it('should return related entities for a session', async () => {
256
- vi.mocked(nexusPost).mockResolvedValue(
257
- mockApiSuccess({
258
- source: {
259
- entity_type: 'session',
260
- entity_id: TEST_IDS.sessionId,
261
- project_id: TEST_IDS.projectId,
262
- },
263
- total_related: 1,
264
- related: [
265
- {
266
- relation: 'task_in_project',
267
- entity_type: 'task',
268
- entity_id: TEST_IDS.taskId,
269
- title: 'Related task',
270
- status: 'open',
271
- created_at: '2026-04-12',
272
- },
273
- ],
274
- }),
275
- )
276
-
277
- const { getRelatedEntities } = await import('../tools/get-related-entities.js')
278
- const result = await getRelatedEntities({
279
- entity_type: 'session',
280
- entity_id: TEST_IDS.sessionId,
281
- })
282
-
283
- expect(result.isError).toBeUndefined()
284
- const parsed = parseToolResponse(result)
285
- expect(parsed.source.entity_type).toBe('session')
286
- expect(parsed.source.entity_id).toBe(TEST_IDS.sessionId)
287
- expect(parsed.total_related).toBe(1)
288
- expect(parsed.related[0].entity_type).toBe('task')
289
- })
290
-
291
- it('should handle API errors', async () => {
292
- vi.mocked(nexusPost).mockResolvedValue(mockApiError('Entity not found', 404))
293
-
294
- const { getRelatedEntities } = await import('../tools/get-related-entities.js')
295
- const result = await getRelatedEntities({
296
- entity_type: 'session',
297
- entity_id: TEST_IDS.sessionId,
298
- })
299
-
300
- expect(result.isError).toBe(true)
301
- })
302
- })