@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,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rv_list + rv_get + rv_create + rv_decide + rv_comment -- Layer 4 Reviews
|
|
3
|
+
*
|
|
4
|
+
* Review lifecycle management tools for the Nexus platform.
|
|
5
|
+
* Reviews cover skills, agents, and other governed entities.
|
|
6
|
+
* Delegates to POST /api/mcp/reviews.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { z } from 'zod'
|
|
10
|
+
import { nexusPost } from '../nexus-api.js'
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// rv_list
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
export const rvListSchema = {
|
|
17
|
+
entity_type: z
|
|
18
|
+
.enum(['skill', 'agent'])
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Filter by entity type (skill or agent)'),
|
|
21
|
+
status: z
|
|
22
|
+
.string()
|
|
23
|
+
.max(50)
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('Filter by review status'),
|
|
26
|
+
limit: z
|
|
27
|
+
.number()
|
|
28
|
+
.int()
|
|
29
|
+
.min(1)
|
|
30
|
+
.max(100)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('Maximum number of reviews to return'),
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type RvListArgs = {
|
|
36
|
+
entity_type?: string
|
|
37
|
+
status?: string
|
|
38
|
+
limit?: number
|
|
39
|
+
user_id: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function rvList(args: RvListArgs) {
|
|
43
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
44
|
+
action: 'rv_list',
|
|
45
|
+
entity_type: args.entity_type,
|
|
46
|
+
status: args.status,
|
|
47
|
+
limit: args.limit,
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
if (!result.ok) {
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: 'text' as const,
|
|
55
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
isError: true,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
content: [
|
|
64
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
65
|
+
],
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// rv_get
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
export const rvGetSchema = {
|
|
74
|
+
review_id: z
|
|
75
|
+
.string()
|
|
76
|
+
.uuid()
|
|
77
|
+
.optional()
|
|
78
|
+
.describe('Review UUID (look up by review ID)'),
|
|
79
|
+
entity_type: z
|
|
80
|
+
.string()
|
|
81
|
+
.max(50)
|
|
82
|
+
.optional()
|
|
83
|
+
.describe('Entity type (used with entity_id for lookup by entity)'),
|
|
84
|
+
entity_id: z
|
|
85
|
+
.string()
|
|
86
|
+
.uuid()
|
|
87
|
+
.optional()
|
|
88
|
+
.describe('Entity UUID (used with entity_type for lookup by entity)'),
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
type RvGetArgs = {
|
|
92
|
+
review_id?: string
|
|
93
|
+
entity_type?: string
|
|
94
|
+
entity_id?: string
|
|
95
|
+
user_id: string
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function rvGet(args: RvGetArgs) {
|
|
99
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
100
|
+
action: 'rv_get',
|
|
101
|
+
review_id: args.review_id,
|
|
102
|
+
entity_type: args.entity_type,
|
|
103
|
+
entity_id: args.entity_id,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
if (!result.ok) {
|
|
107
|
+
return {
|
|
108
|
+
content: [
|
|
109
|
+
{
|
|
110
|
+
type: 'text' as const,
|
|
111
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
isError: true,
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
121
|
+
],
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// rv_create
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
export const rvCreateSchema = {
|
|
130
|
+
entity_type: z
|
|
131
|
+
.enum(['skill', 'agent'])
|
|
132
|
+
.describe('Type of entity to create a review for'),
|
|
133
|
+
entity_id: z
|
|
134
|
+
.string()
|
|
135
|
+
.uuid()
|
|
136
|
+
.describe('UUID of the entity to review'),
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
type RvCreateArgs = {
|
|
140
|
+
entity_type: string
|
|
141
|
+
entity_id: string
|
|
142
|
+
user_id: string
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export async function rvCreate(args: RvCreateArgs) {
|
|
146
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
147
|
+
action: 'rv_create',
|
|
148
|
+
entity_type: args.entity_type,
|
|
149
|
+
entity_id: args.entity_id,
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
if (!result.ok) {
|
|
153
|
+
return {
|
|
154
|
+
content: [
|
|
155
|
+
{
|
|
156
|
+
type: 'text' as const,
|
|
157
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
isError: true,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
content: [
|
|
166
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
167
|
+
],
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// rv_decide
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
|
|
175
|
+
export const rvDecideSchema = {
|
|
176
|
+
review_id: z.string().uuid().describe('Review UUID'),
|
|
177
|
+
transition: z
|
|
178
|
+
.enum(['submit', 'accept', 'reject', 'request_revision', 'resubmit', 'archive'])
|
|
179
|
+
.describe('State transition to apply'),
|
|
180
|
+
rationale: z
|
|
181
|
+
.string()
|
|
182
|
+
.max(10_000)
|
|
183
|
+
.optional()
|
|
184
|
+
.describe('Optional rationale for the decision'),
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
type RvDecideArgs = {
|
|
188
|
+
review_id: string
|
|
189
|
+
transition: string
|
|
190
|
+
rationale?: string
|
|
191
|
+
user_id: string
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export async function rvDecide(args: RvDecideArgs) {
|
|
195
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
196
|
+
action: 'rv_decide',
|
|
197
|
+
review_id: args.review_id,
|
|
198
|
+
transition: args.transition,
|
|
199
|
+
rationale: args.rationale,
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
if (!result.ok) {
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: 'text' as const,
|
|
207
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
isError: true,
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
content: [
|
|
216
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
217
|
+
],
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
// rv_comment
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
|
|
225
|
+
export const rvCommentSchema = {
|
|
226
|
+
review_id: z.string().uuid().describe('Review UUID'),
|
|
227
|
+
body: z.string().max(100_000).describe('Comment body (markdown supported)'),
|
|
228
|
+
agent_id: z
|
|
229
|
+
.string()
|
|
230
|
+
.max(200)
|
|
231
|
+
.optional()
|
|
232
|
+
.describe('Agent identifier if comment is posted by an agent'),
|
|
233
|
+
line_start: z
|
|
234
|
+
.number()
|
|
235
|
+
.int()
|
|
236
|
+
.optional()
|
|
237
|
+
.describe('Start line number for inline comments'),
|
|
238
|
+
line_end: z
|
|
239
|
+
.number()
|
|
240
|
+
.int()
|
|
241
|
+
.optional()
|
|
242
|
+
.describe('End line number for inline comments'),
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
type RvCommentArgs = {
|
|
246
|
+
review_id: string
|
|
247
|
+
body: string
|
|
248
|
+
agent_id?: string
|
|
249
|
+
line_start?: number
|
|
250
|
+
line_end?: number
|
|
251
|
+
user_id: string
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export async function rvComment(args: RvCommentArgs) {
|
|
255
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
256
|
+
action: 'rv_comment',
|
|
257
|
+
review_id: args.review_id,
|
|
258
|
+
body: args.body,
|
|
259
|
+
agent_id: args.agent_id,
|
|
260
|
+
line_start: args.line_start,
|
|
261
|
+
line_end: args.line_end,
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
if (!result.ok) {
|
|
265
|
+
return {
|
|
266
|
+
content: [
|
|
267
|
+
{
|
|
268
|
+
type: 'text' as const,
|
|
269
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
isError: true,
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
content: [
|
|
278
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
279
|
+
],
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kb_search -- Layer 1 Knowledge Access
|
|
3
|
+
*
|
|
4
|
+
* Searches project knowledge using keyword, semantic, or hybrid mode.
|
|
5
|
+
* Delegates to POST /api/mcp/search.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod'
|
|
9
|
+
import { nexusPost } from '../nexus-api.js'
|
|
10
|
+
|
|
11
|
+
export const searchKnowledgeSchema = {
|
|
12
|
+
query: z.string().max(1000).describe('Free-text search query'),
|
|
13
|
+
project_id: z.string().uuid().describe('Project UUID to scope the search'),
|
|
14
|
+
entity_types: z
|
|
15
|
+
.array(
|
|
16
|
+
z.enum([
|
|
17
|
+
'session',
|
|
18
|
+
'decision',
|
|
19
|
+
'letter',
|
|
20
|
+
'task',
|
|
21
|
+
'research_note',
|
|
22
|
+
'planning_item',
|
|
23
|
+
'ingest_item',
|
|
24
|
+
]),
|
|
25
|
+
)
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('Filter to specific entity types'),
|
|
28
|
+
search_mode: z
|
|
29
|
+
.enum(['keyword', 'semantic', 'hybrid'])
|
|
30
|
+
.default('keyword')
|
|
31
|
+
.describe('Search mode: keyword, semantic, or hybrid'),
|
|
32
|
+
limit: z
|
|
33
|
+
.number()
|
|
34
|
+
.int()
|
|
35
|
+
.min(1)
|
|
36
|
+
.max(50)
|
|
37
|
+
.default(10)
|
|
38
|
+
.describe('Maximum results to return'),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type SearchArgs = {
|
|
42
|
+
query: string
|
|
43
|
+
project_id: string
|
|
44
|
+
entity_types?: string[]
|
|
45
|
+
search_mode?: string
|
|
46
|
+
limit?: number
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function searchKnowledge(args: SearchArgs) {
|
|
50
|
+
const result = await nexusPost('/api/mcp/search', {
|
|
51
|
+
project_id: args.project_id,
|
|
52
|
+
query: args.query,
|
|
53
|
+
entity_types: args.entity_types,
|
|
54
|
+
search_mode: args.search_mode ?? 'keyword',
|
|
55
|
+
limit: args.limit ?? 10,
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
if (!result.ok) {
|
|
59
|
+
return {
|
|
60
|
+
content: [{ type: 'text' as const, text: JSON.stringify({ error: result.error }, null, 2) }],
|
|
61
|
+
isError: true,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) }],
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session lifecycle tools -- Layer 2 Coordination
|
|
3
|
+
*
|
|
4
|
+
* session_create: Start a new work session for a project
|
|
5
|
+
* session_close: End a session with summary and next entry point
|
|
6
|
+
* session_list: List open sessions for a project
|
|
7
|
+
*
|
|
8
|
+
* Delegates to POST /api/mcp/sessions.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from 'zod'
|
|
12
|
+
import { nexusPost } from '../nexus-api.js'
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// create_session -> session_create
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
export const createSessionSchema = {
|
|
19
|
+
project_id: z.string().uuid().describe('Project UUID'),
|
|
20
|
+
title: z.string().max(500).describe('Session title (e.g., "Architecture review")'),
|
|
21
|
+
agent_id: z
|
|
22
|
+
.string()
|
|
23
|
+
.max(200)
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('Agent identifier starting this session'),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type CreateSessionArgs = {
|
|
29
|
+
project_id: string
|
|
30
|
+
title: string
|
|
31
|
+
agent_id?: string
|
|
32
|
+
user_id: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function createSession(args: CreateSessionArgs) {
|
|
36
|
+
const result = await nexusPost('/api/mcp/sessions', {
|
|
37
|
+
action: 'session_create',
|
|
38
|
+
project_id: args.project_id,
|
|
39
|
+
title: args.title,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
if (!result.ok) {
|
|
43
|
+
return {
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: 'text' as const,
|
|
47
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
isError: true,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
57
|
+
],
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// close_session -> session_close
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
export const closeSessionSchema = {
|
|
66
|
+
session_id: z.string().uuid().describe('Session UUID to close'),
|
|
67
|
+
summary: z
|
|
68
|
+
.string()
|
|
69
|
+
.max(100_000)
|
|
70
|
+
.optional()
|
|
71
|
+
.describe('Summary of what was accomplished in the session'),
|
|
72
|
+
next_entry_point: z
|
|
73
|
+
.string()
|
|
74
|
+
.max(10_000)
|
|
75
|
+
.optional()
|
|
76
|
+
.describe('Suggested starting point for the next session'),
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
type CloseSessionArgs = {
|
|
80
|
+
session_id: string
|
|
81
|
+
summary?: string
|
|
82
|
+
next_entry_point?: string
|
|
83
|
+
user_id: string
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function closeSession(args: CloseSessionArgs) {
|
|
87
|
+
const result = await nexusPost('/api/mcp/sessions', {
|
|
88
|
+
action: 'session_close',
|
|
89
|
+
session_id: args.session_id,
|
|
90
|
+
summary: args.summary,
|
|
91
|
+
next_entry_point: args.next_entry_point,
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
if (!result.ok) {
|
|
95
|
+
return {
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: 'text' as const,
|
|
99
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
isError: true,
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
content: [
|
|
108
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
109
|
+
],
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// list_open_sessions -> session_list
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
export const listOpenSessionsSchema = {
|
|
118
|
+
project_id: z.string().uuid().describe('Project UUID'),
|
|
119
|
+
limit: z
|
|
120
|
+
.number()
|
|
121
|
+
.int()
|
|
122
|
+
.min(1)
|
|
123
|
+
.max(100)
|
|
124
|
+
.default(25)
|
|
125
|
+
.describe('Maximum number of sessions to return (default 25)'),
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
type ListOpenSessionsArgs = {
|
|
129
|
+
project_id: string
|
|
130
|
+
limit?: number
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function listOpenSessions(args: ListOpenSessionsArgs) {
|
|
134
|
+
const result = await nexusPost('/api/mcp/sessions', {
|
|
135
|
+
action: 'session_list',
|
|
136
|
+
project_id: args.project_id,
|
|
137
|
+
limit: args.limit ?? 25,
|
|
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,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sk_assign + sk_unassign + sk_export -- Layer 2 Coordination
|
|
3
|
+
*
|
|
4
|
+
* Skill-project assignment management tools for the Nexus platform.
|
|
5
|
+
* Delegates to POST /api/mcp/skills.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod'
|
|
9
|
+
import { nexusPost } from '../nexus-api.js'
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// sk_assign
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export const skAssignSchema = {
|
|
16
|
+
project_id: z.string().uuid().describe('Project UUID'),
|
|
17
|
+
skill_id: z.string().max(200).describe('Skill identifier or UUID'),
|
|
18
|
+
pinned_version: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('Pin to a specific skill version'),
|
|
23
|
+
enabled: z
|
|
24
|
+
.boolean()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Whether the assignment is enabled (default: true)'),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type SkAssignArgs = {
|
|
30
|
+
project_id: string
|
|
31
|
+
skill_id: string
|
|
32
|
+
pinned_version?: number
|
|
33
|
+
enabled?: boolean
|
|
34
|
+
user_id: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function skAssign(args: SkAssignArgs) {
|
|
38
|
+
const result = await nexusPost('/api/mcp/skills', {
|
|
39
|
+
action: 'sk_assign',
|
|
40
|
+
project_id: args.project_id,
|
|
41
|
+
skill_id: args.skill_id,
|
|
42
|
+
pinned_version: args.pinned_version,
|
|
43
|
+
enabled: args.enabled,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (!result.ok) {
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: 'text' as const,
|
|
51
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
isError: true,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
61
|
+
],
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// sk_unassign
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
export const skUnassignSchema = {
|
|
70
|
+
project_id: z.string().uuid().describe('Project UUID'),
|
|
71
|
+
skill_id: z.string().max(200).describe('Skill identifier or UUID'),
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
type SkUnassignArgs = {
|
|
75
|
+
project_id: string
|
|
76
|
+
skill_id: string
|
|
77
|
+
user_id: string
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function skUnassign(args: SkUnassignArgs) {
|
|
81
|
+
const result = await nexusPost('/api/mcp/skills', {
|
|
82
|
+
action: 'sk_unassign',
|
|
83
|
+
project_id: args.project_id,
|
|
84
|
+
skill_id: args.skill_id,
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
if (!result.ok) {
|
|
88
|
+
return {
|
|
89
|
+
content: [
|
|
90
|
+
{
|
|
91
|
+
type: 'text' as const,
|
|
92
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
isError: true,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
102
|
+
],
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// sk_export
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
export const skExportSchema = {
|
|
111
|
+
project_id: z.string().uuid().describe('Project UUID'),
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
type SkExportArgs = {
|
|
115
|
+
project_id: string
|
|
116
|
+
user_id: string
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export async function skExport(args: SkExportArgs) {
|
|
120
|
+
const result = await nexusPost('/api/mcp/skills', {
|
|
121
|
+
action: 'sk_export',
|
|
122
|
+
project_id: args.project_id,
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
if (!result.ok) {
|
|
126
|
+
return {
|
|
127
|
+
content: [
|
|
128
|
+
{
|
|
129
|
+
type: 'text' as const,
|
|
130
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
isError: true,
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
content: [
|
|
139
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
140
|
+
],
|
|
141
|
+
}
|
|
142
|
+
}
|