@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.
Files changed (133) hide show
  1. package/.github/workflows/ci.yml +38 -0
  2. package/.github/workflows/release.yml +57 -0
  3. package/README.md +89 -0
  4. package/dist/auth.d.ts +39 -0
  5. package/dist/auth.d.ts.map +1 -0
  6. package/dist/auth.js +47 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/nexus-api.d.ts +35 -0
  9. package/dist/nexus-api.d.ts.map +1 -0
  10. package/dist/nexus-api.js +90 -0
  11. package/dist/nexus-api.js.map +1 -0
  12. package/dist/server.d.ts +67 -0
  13. package/dist/server.d.ts.map +1 -0
  14. package/dist/server.js +189 -0
  15. package/dist/server.js.map +1 -0
  16. package/dist/tools/add-task-note.d.ts +34 -0
  17. package/dist/tools/add-task-note.d.ts.map +1 -0
  18. package/dist/tools/add-task-note.js +39 -0
  19. package/dist/tools/add-task-note.js.map +1 -0
  20. package/dist/tools/append-session-entry.d.ts +53 -0
  21. package/dist/tools/append-session-entry.d.ts.map +1 -0
  22. package/dist/tools/append-session-entry.js +68 -0
  23. package/dist/tools/append-session-entry.js.map +1 -0
  24. package/dist/tools/create-task.d.ts +52 -0
  25. package/dist/tools/create-task.d.ts.map +1 -0
  26. package/dist/tools/create-task.js +51 -0
  27. package/dist/tools/create-task.js.map +1 -0
  28. package/dist/tools/decision-comments.d.ts +54 -0
  29. package/dist/tools/decision-comments.d.ts.map +1 -0
  30. package/dist/tools/decision-comments.js +81 -0
  31. package/dist/tools/decision-comments.js.map +1 -0
  32. package/dist/tools/get-document.d.ts +47 -0
  33. package/dist/tools/get-document.d.ts.map +1 -0
  34. package/dist/tools/get-document.js +68 -0
  35. package/dist/tools/get-document.js.map +1 -0
  36. package/dist/tools/get-project-memory.d.ts +47 -0
  37. package/dist/tools/get-project-memory.d.ts.map +1 -0
  38. package/dist/tools/get-project-memory.js +53 -0
  39. package/dist/tools/get-project-memory.js.map +1 -0
  40. package/dist/tools/get-related-entities.d.ts +44 -0
  41. package/dist/tools/get-related-entities.d.ts.map +1 -0
  42. package/dist/tools/get-related-entities.js +60 -0
  43. package/dist/tools/get-related-entities.js.map +1 -0
  44. package/dist/tools/governance.d.ts +90 -0
  45. package/dist/tools/governance.d.ts.map +1 -0
  46. package/dist/tools/governance.js +127 -0
  47. package/dist/tools/governance.js.map +1 -0
  48. package/dist/tools/ingest-document.d.ts +40 -0
  49. package/dist/tools/ingest-document.d.ts.map +1 -0
  50. package/dist/tools/ingest-document.js +49 -0
  51. package/dist/tools/ingest-document.js.map +1 -0
  52. package/dist/tools/letter-inbox.d.ts +80 -0
  53. package/dist/tools/letter-inbox.d.ts.map +1 -0
  54. package/dist/tools/letter-inbox.js +118 -0
  55. package/dist/tools/letter-inbox.js.map +1 -0
  56. package/dist/tools/letters.d.ts +91 -0
  57. package/dist/tools/letters.d.ts.map +1 -0
  58. package/dist/tools/letters.js +112 -0
  59. package/dist/tools/letters.js.map +1 -0
  60. package/dist/tools/list-documents.d.ts +33 -0
  61. package/dist/tools/list-documents.d.ts.map +1 -0
  62. package/dist/tools/list-documents.js +47 -0
  63. package/dist/tools/list-documents.js.map +1 -0
  64. package/dist/tools/list-tasks.d.ts +39 -0
  65. package/dist/tools/list-tasks.d.ts.map +1 -0
  66. package/dist/tools/list-tasks.js +46 -0
  67. package/dist/tools/list-tasks.js.map +1 -0
  68. package/dist/tools/project-list.d.ts +28 -0
  69. package/dist/tools/project-list.d.ts.map +1 -0
  70. package/dist/tools/project-list.js +43 -0
  71. package/dist/tools/project-list.js.map +1 -0
  72. package/dist/tools/reviews.d.ts +145 -0
  73. package/dist/tools/reviews.d.ts.map +1 -0
  74. package/dist/tools/reviews.js +220 -0
  75. package/dist/tools/reviews.js.map +1 -0
  76. package/dist/tools/search-knowledge.d.ts +48 -0
  77. package/dist/tools/search-knowledge.d.ts.map +1 -0
  78. package/dist/tools/search-knowledge.js +54 -0
  79. package/dist/tools/search-knowledge.js.map +1 -0
  80. package/dist/tools/sessions.d.ts +81 -0
  81. package/dist/tools/sessions.d.ts.map +1 -0
  82. package/dist/tools/sessions.js +123 -0
  83. package/dist/tools/sessions.js.map +1 -0
  84. package/dist/tools/skill-assign.d.ts +77 -0
  85. package/dist/tools/skill-assign.d.ts.map +1 -0
  86. package/dist/tools/skill-assign.js +108 -0
  87. package/dist/tools/skill-assign.js.map +1 -0
  88. package/dist/tools/skills.d.ts +138 -0
  89. package/dist/tools/skills.d.ts.map +1 -0
  90. package/dist/tools/skills.js +195 -0
  91. package/dist/tools/skills.js.map +1 -0
  92. package/dist/tools/update-task-status.d.ts +48 -0
  93. package/dist/tools/update-task-status.d.ts.map +1 -0
  94. package/dist/tools/update-task-status.js +51 -0
  95. package/dist/tools/update-task-status.js.map +1 -0
  96. package/package.json +30 -0
  97. package/src/__tests__/auth.test.ts +162 -0
  98. package/src/__tests__/decision-comments.test.ts +173 -0
  99. package/src/__tests__/e2e-integration.test.ts +443 -0
  100. package/src/__tests__/helpers.ts +58 -0
  101. package/src/__tests__/layer1-knowledge.test.ts +302 -0
  102. package/src/__tests__/layer2-coordination.test.ts +842 -0
  103. package/src/__tests__/layer3-governance.test.ts +205 -0
  104. package/src/__tests__/project-list-and-skill-assign.test.ts +282 -0
  105. package/src/__tests__/reviews.test.ts +420 -0
  106. package/src/__tests__/server.test.ts +250 -0
  107. package/src/__tests__/setup.ts +15 -0
  108. package/src/__tests__/task-list-and-doc-list.test.ts +226 -0
  109. package/src/auth.ts +81 -0
  110. package/src/nexus-api.ts +127 -0
  111. package/src/server.ts +520 -0
  112. package/src/tools/add-task-note.ts +50 -0
  113. package/src/tools/append-session-entry.ts +84 -0
  114. package/src/tools/create-task.ts +66 -0
  115. package/src/tools/decision-comments.ts +103 -0
  116. package/src/tools/get-document.ts +80 -0
  117. package/src/tools/get-project-memory.ts +65 -0
  118. package/src/tools/get-related-entities.ts +73 -0
  119. package/src/tools/governance.ts +165 -0
  120. package/src/tools/ingest-document.ts +65 -0
  121. package/src/tools/letter-inbox.ts +157 -0
  122. package/src/tools/letters.ts +144 -0
  123. package/src/tools/list-documents.ts +58 -0
  124. package/src/tools/list-tasks.ts +57 -0
  125. package/src/tools/project-list.ts +52 -0
  126. package/src/tools/reviews.ts +281 -0
  127. package/src/tools/search-knowledge.ts +68 -0
  128. package/src/tools/sessions.ts +157 -0
  129. package/src/tools/skill-assign.ts +142 -0
  130. package/src/tools/skills.ts +255 -0
  131. package/src/tools/update-task-status.ts +64 -0
  132. package/tsconfig.json +20 -0
  133. package/vitest.config.ts +8 -0
@@ -0,0 +1,157 @@
1
+ /**
2
+ * vl_inbox + vl_outbox + vl_ack -- Layer 2 Coordination
3
+ *
4
+ * Inbox/outbox polling and acknowledgment for vault letters.
5
+ * Delegates to POST /api/mcp/letters (actions: vl_inbox, vl_outbox, vl_ack).
6
+ */
7
+
8
+ import { z } from 'zod'
9
+ import { nexusPost } from '../nexus-api.js'
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // list_inbox
13
+ // ---------------------------------------------------------------------------
14
+
15
+ export const listInboxSchema = {
16
+ project_id: z.string().uuid().describe('Project UUID'),
17
+ status_filter: z
18
+ .array(z.string().max(50))
19
+ .optional()
20
+ .describe(
21
+ 'Filter by letter status (default: new, acknowledged, in_progress, blocked, needs_review)',
22
+ ),
23
+ limit: z
24
+ .number()
25
+ .min(1)
26
+ .max(50)
27
+ .default(20)
28
+ .describe('Max number of letters to return'),
29
+ }
30
+
31
+ type ListInboxArgs = {
32
+ project_id: string
33
+ status_filter?: string[]
34
+ limit?: number
35
+ user_id: string
36
+ agent_id?: string
37
+ }
38
+
39
+ export async function listInbox(args: ListInboxArgs) {
40
+ const result = await nexusPost('/api/mcp/letters', {
41
+ action: 'vl_inbox',
42
+ project_id: args.project_id,
43
+ status_filter: args.status_filter,
44
+ limit: args.limit ?? 20,
45
+ })
46
+
47
+ if (!result.ok) {
48
+ return {
49
+ content: [
50
+ {
51
+ type: 'text' as const,
52
+ text: JSON.stringify({ error: result.error }, null, 2),
53
+ },
54
+ ],
55
+ isError: true,
56
+ }
57
+ }
58
+
59
+ return {
60
+ content: [
61
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
62
+ ],
63
+ }
64
+ }
65
+
66
+ // ---------------------------------------------------------------------------
67
+ // list_outbox
68
+ // ---------------------------------------------------------------------------
69
+
70
+ export const listOutboxSchema = {
71
+ project_id: z.string().uuid().describe('Project UUID'),
72
+ status_filter: z
73
+ .array(z.string().max(50))
74
+ .optional()
75
+ .describe('Filter by letter status (default: all non-closed)'),
76
+ limit: z
77
+ .number()
78
+ .min(1)
79
+ .max(50)
80
+ .default(20)
81
+ .describe('Max number of letters to return'),
82
+ }
83
+
84
+ type ListOutboxArgs = {
85
+ project_id: string
86
+ status_filter?: string[]
87
+ limit?: number
88
+ user_id: string
89
+ agent_id?: string
90
+ }
91
+
92
+ export async function listOutbox(args: ListOutboxArgs) {
93
+ const result = await nexusPost('/api/mcp/letters', {
94
+ action: 'vl_outbox',
95
+ project_id: args.project_id,
96
+ status_filter: args.status_filter,
97
+ limit: args.limit ?? 20,
98
+ })
99
+
100
+ if (!result.ok) {
101
+ return {
102
+ content: [
103
+ {
104
+ type: 'text' as const,
105
+ text: JSON.stringify({ error: result.error }, null, 2),
106
+ },
107
+ ],
108
+ isError: true,
109
+ }
110
+ }
111
+
112
+ return {
113
+ content: [
114
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
115
+ ],
116
+ }
117
+ }
118
+
119
+ // ---------------------------------------------------------------------------
120
+ // acknowledge_letter
121
+ // ---------------------------------------------------------------------------
122
+
123
+ export const acknowledgeLetterSchema = {
124
+ letter_id: z.string().uuid().describe('Letter UUID to acknowledge'),
125
+ }
126
+
127
+ type AcknowledgeLetterArgs = {
128
+ letter_id: string
129
+ user_id: string
130
+ agent_id?: string
131
+ }
132
+
133
+ export async function acknowledgeLetter(args: AcknowledgeLetterArgs) {
134
+ const result = await nexusPost('/api/mcp/letters', {
135
+ action: 'vl_ack',
136
+ letter_id: args.letter_id,
137
+ agent_id: args.agent_id,
138
+ })
139
+
140
+ if (!result.ok) {
141
+ return {
142
+ content: [
143
+ {
144
+ type: 'text' as const,
145
+ text: JSON.stringify({ error: result.error }, null, 2),
146
+ },
147
+ ],
148
+ isError: true,
149
+ }
150
+ }
151
+
152
+ return {
153
+ content: [
154
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
155
+ ],
156
+ }
157
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * vl_create + vl_reply -- Layer 2 Coordination
3
+ *
4
+ * Vault letter management for agent coordination.
5
+ * Delegates to POST /api/mcp/letters (actions: vl_create, vl_reply).
6
+ */
7
+
8
+ import { z } from 'zod'
9
+ import { nexusPost } from '../nexus-api.js'
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // create_letter
13
+ // ---------------------------------------------------------------------------
14
+
15
+ export const createLetterSchema = {
16
+ project_id: z.string().uuid().describe('Project UUID'),
17
+ from_actor: z.string().max(200).describe('Sender identifier (agent name or user)'),
18
+ to_actor: z.string().max(200).describe('Recipient identifier (agent name or user)'),
19
+ subject: z.string().max(500).describe('Letter subject'),
20
+ body: z.string().max(100_000).describe('Initial message body'),
21
+ priority: z
22
+ .enum(['low', 'normal', 'high', 'urgent'])
23
+ .default('normal')
24
+ .describe('Letter priority'),
25
+ blocking: z
26
+ .boolean()
27
+ .default(false)
28
+ .describe('Whether this letter blocks the sender'),
29
+ thread_id: z
30
+ .string()
31
+ .uuid()
32
+ .optional()
33
+ .describe('Optional thread UUID to group related letters'),
34
+ agent_id: z.string().max(200).optional().describe('Agent identifier if applicable'),
35
+ }
36
+
37
+ type CreateLetterArgs = {
38
+ project_id: string
39
+ from_actor: string
40
+ to_actor: string
41
+ subject: string
42
+ body: string
43
+ priority?: string
44
+ blocking?: boolean
45
+ thread_id?: string
46
+ user_id: string
47
+ agent_id?: string
48
+ }
49
+
50
+ export async function createLetter(args: CreateLetterArgs) {
51
+ const result = await nexusPost('/api/mcp/letters', {
52
+ action: 'vl_create',
53
+ project_id: args.project_id,
54
+ from_actor: args.from_actor,
55
+ to_actor: args.to_actor,
56
+ subject: args.subject,
57
+ body: args.body,
58
+ priority: args.priority ?? 'normal',
59
+ blocking: args.blocking ?? false,
60
+ thread_id: args.thread_id,
61
+ agent_id: args.agent_id,
62
+ })
63
+
64
+ if (!result.ok) {
65
+ return {
66
+ content: [
67
+ {
68
+ type: 'text' as const,
69
+ text: JSON.stringify({ error: result.error }, null, 2),
70
+ },
71
+ ],
72
+ isError: true,
73
+ }
74
+ }
75
+
76
+ return {
77
+ content: [
78
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
79
+ ],
80
+ }
81
+ }
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // reply_letter
85
+ // ---------------------------------------------------------------------------
86
+
87
+ export const replyLetterSchema = {
88
+ letter_id: z.string().uuid().describe('Letter UUID to reply to'),
89
+ body: z.string().max(100_000).describe('Reply message body'),
90
+ message_type: z
91
+ .enum(['response', 'clarification', 'review_note', 'follow_up', 'context'])
92
+ .default('response')
93
+ .describe('Type of reply message'),
94
+ agent_id: z.string().max(200).optional().describe('Agent identifier if applicable'),
95
+ new_status: z
96
+ .enum([
97
+ 'acknowledged',
98
+ 'in_progress',
99
+ 'answered',
100
+ 'blocked',
101
+ 'needs_review',
102
+ 'closed',
103
+ ])
104
+ .optional()
105
+ .describe('Optionally update the letter status'),
106
+ }
107
+
108
+ type ReplyLetterArgs = {
109
+ letter_id: string
110
+ body: string
111
+ message_type?: string
112
+ user_id: string
113
+ agent_id?: string
114
+ new_status?: string
115
+ }
116
+
117
+ export async function replyLetter(args: ReplyLetterArgs) {
118
+ const result = await nexusPost('/api/mcp/letters', {
119
+ action: 'vl_reply',
120
+ letter_id: args.letter_id,
121
+ body: args.body,
122
+ message_type: args.message_type ?? 'response',
123
+ agent_id: args.agent_id,
124
+ new_status: args.new_status,
125
+ })
126
+
127
+ if (!result.ok) {
128
+ return {
129
+ content: [
130
+ {
131
+ type: 'text' as const,
132
+ text: JSON.stringify({ error: result.error }, null, 2),
133
+ },
134
+ ],
135
+ isError: true,
136
+ }
137
+ }
138
+
139
+ return {
140
+ content: [
141
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
142
+ ],
143
+ }
144
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * doc_list -- Layer 2 Coordination
3
+ *
4
+ * List ingested documents for a project with optional source filtering.
5
+ * Delegates to POST /api/mcp/documents (action: doc_list).
6
+ */
7
+
8
+ import { z } from 'zod'
9
+ import { nexusPost } from '../nexus-api.js'
10
+
11
+ export const listDocumentsSchema = {
12
+ project_id: z.string().uuid().describe('Project UUID'),
13
+ source: z
14
+ .string()
15
+ .max(200)
16
+ .optional()
17
+ .describe('Filter by source (e.g., "mcp-agent", "research", "session-extract")'),
18
+ limit: z
19
+ .number()
20
+ .min(1)
21
+ .max(100)
22
+ .default(50)
23
+ .describe('Maximum number of documents to return (default 50)'),
24
+ }
25
+
26
+ type ListDocumentsArgs = {
27
+ project_id: string
28
+ source?: string
29
+ limit?: number
30
+ user_id: string
31
+ }
32
+
33
+ export async function listDocuments(args: ListDocumentsArgs) {
34
+ const result = await nexusPost('/api/mcp/documents', {
35
+ action: 'doc_list',
36
+ project_id: args.project_id,
37
+ source: args.source,
38
+ limit: args.limit ?? 50,
39
+ })
40
+
41
+ if (!result.ok) {
42
+ return {
43
+ content: [
44
+ {
45
+ type: 'text' as const,
46
+ text: JSON.stringify({ error: result.error }, null, 2),
47
+ },
48
+ ],
49
+ isError: true,
50
+ }
51
+ }
52
+
53
+ return {
54
+ content: [
55
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
56
+ ],
57
+ }
58
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * task_list -- Layer 2 Coordination
3
+ *
4
+ * List tasks for a project with optional status filtering.
5
+ * Delegates to POST /api/mcp/tasks (action: task_list).
6
+ */
7
+
8
+ import { z } from 'zod'
9
+ import { nexusPost } from '../nexus-api.js'
10
+
11
+ export const listTasksSchema = {
12
+ project_id: z.string().uuid().describe('Project UUID'),
13
+ status_filter: z
14
+ .array(z.enum(['open', 'in_progress', 'blocked', 'done', 'cancelled']))
15
+ .optional()
16
+ .describe('Filter by task status (default: all statuses)'),
17
+ limit: z
18
+ .number()
19
+ .min(1)
20
+ .max(100)
21
+ .default(50)
22
+ .describe('Maximum number of tasks to return (default 50)'),
23
+ }
24
+
25
+ type ListTasksArgs = {
26
+ project_id: string
27
+ status_filter?: string[]
28
+ limit?: number
29
+ user_id: string
30
+ }
31
+
32
+ export async function listTasks(args: ListTasksArgs) {
33
+ const result = await nexusPost('/api/mcp/tasks', {
34
+ action: 'task_list',
35
+ project_id: args.project_id,
36
+ status_filter: args.status_filter,
37
+ limit: args.limit ?? 50,
38
+ })
39
+
40
+ if (!result.ok) {
41
+ return {
42
+ content: [
43
+ {
44
+ type: 'text' as const,
45
+ text: JSON.stringify({ error: result.error }, null, 2),
46
+ },
47
+ ],
48
+ isError: true,
49
+ }
50
+ }
51
+
52
+ return {
53
+ content: [
54
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
55
+ ],
56
+ }
57
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * project_list -- Layer 1 Knowledge Access
3
+ *
4
+ * List accessible projects for the authenticated user/agent.
5
+ * Delegates to GET /api/mcp/projects.
6
+ */
7
+
8
+ import { z } from 'zod'
9
+ import { nexusGet } from '../nexus-api.js'
10
+
11
+ export const projectListSchema = {
12
+ limit: z
13
+ .number()
14
+ .int()
15
+ .min(1)
16
+ .max(100)
17
+ .optional()
18
+ .describe('Maximum number of projects to return'),
19
+ }
20
+
21
+ type ProjectListArgs = {
22
+ limit?: number
23
+ }
24
+
25
+ export async function projectList(args: ProjectListArgs) {
26
+ const params = new URLSearchParams()
27
+ if (args.limit !== undefined) {
28
+ params.set('limit', String(args.limit))
29
+ }
30
+ const qs = params.toString()
31
+ const path = `/api/mcp/projects${qs ? `?${qs}` : ''}`
32
+
33
+ const result = await nexusGet(path)
34
+
35
+ if (!result.ok) {
36
+ return {
37
+ content: [
38
+ {
39
+ type: 'text' as const,
40
+ text: JSON.stringify({ error: result.error }, null, 2),
41
+ },
42
+ ],
43
+ isError: true,
44
+ }
45
+ }
46
+
47
+ return {
48
+ content: [
49
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
50
+ ],
51
+ }
52
+ }