@mpowr/nexus-mcp 0.5.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 +59 -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 +29 -0
- package/dist/nexus-api.d.ts.map +1 -0
- package/dist/nexus-api.js +76 -0
- package/dist/nexus-api.js.map +1 -0
- package/dist/server.d.ts +65 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +183 -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 +67 -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 +80 -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 +124 -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 +48 -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/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 +216 -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 +120 -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 +192 -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__/helpers.ts +58 -0
- package/src/__tests__/layer1-knowledge.test.ts +302 -0
- package/src/__tests__/layer2-coordination.test.ts +775 -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 +238 -0
- package/src/__tests__/setup.ts +15 -0
- package/src/auth.ts +81 -0
- package/src/nexus-api.ts +110 -0
- package/src/server.ts +499 -0
- package/src/tools/add-task-note.ts +50 -0
- package/src/tools/append-session-entry.ts +83 -0
- package/src/tools/create-task.ts +66 -0
- package/src/tools/decision-comments.ts +102 -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 +162 -0
- package/src/tools/ingest-document.ts +64 -0
- package/src/tools/letter-inbox.ts +157 -0
- package/src/tools/letters.ts +144 -0
- package/src/tools/project-list.ts +52 -0
- package/src/tools/reviews.ts +277 -0
- package/src/tools/search-knowledge.ts +68 -0
- package/src/tools/sessions.ts +154 -0
- package/src/tools/skill-assign.ts +142 -0
- package/src/tools/skills.ts +252 -0
- package/src/tools/update-task-status.ts +64 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* doc_ingest -- Layer 2 Coordination
|
|
3
|
+
*
|
|
4
|
+
* Allows agents to push text/markdown content into a project's
|
|
5
|
+
* knowledge base via the ingest_items table.
|
|
6
|
+
* Delegates to POST /api/mcp/documents (action: doc_ingest).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { z } from 'zod'
|
|
10
|
+
import { nexusPost } from '../nexus-api.js'
|
|
11
|
+
|
|
12
|
+
export const ingestDocumentSchema = {
|
|
13
|
+
project_id: z.string().uuid().describe('Project UUID'),
|
|
14
|
+
title: z.string().describe('Document title'),
|
|
15
|
+
body: z.string().describe('Document content (text or markdown)'),
|
|
16
|
+
source: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe(
|
|
20
|
+
'Source identifier (e.g. "mcp-agent", "research", "session-extract")',
|
|
21
|
+
),
|
|
22
|
+
source_url: z.string().url().optional().describe('Source URL if applicable'),
|
|
23
|
+
agent_id: z.string().optional().describe('Agent identifier if applicable'),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type IngestDocumentArgs = {
|
|
27
|
+
project_id: string
|
|
28
|
+
title: string
|
|
29
|
+
body: string
|
|
30
|
+
source?: string
|
|
31
|
+
source_url?: string
|
|
32
|
+
user_id: string
|
|
33
|
+
agent_id?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function ingestDocument(args: IngestDocumentArgs) {
|
|
37
|
+
const result = await nexusPost('/api/mcp/documents', {
|
|
38
|
+
action: 'doc_ingest',
|
|
39
|
+
project_id: args.project_id,
|
|
40
|
+
title: args.title,
|
|
41
|
+
body: args.body,
|
|
42
|
+
source: args.source,
|
|
43
|
+
source_url: args.source_url,
|
|
44
|
+
agent_id: args.agent_id,
|
|
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
|
+
}
|
|
@@ -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())
|
|
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())
|
|
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().describe('Sender identifier (agent name or user)'),
|
|
18
|
+
to_actor: z.string().describe('Recipient identifier (agent name or user)'),
|
|
19
|
+
subject: z.string().describe('Letter subject'),
|
|
20
|
+
body: z.string().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().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().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().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,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
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
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
|
+
.optional()
|
|
24
|
+
.describe('Filter by review status'),
|
|
25
|
+
limit: z
|
|
26
|
+
.number()
|
|
27
|
+
.int()
|
|
28
|
+
.min(1)
|
|
29
|
+
.max(100)
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('Maximum number of reviews to return'),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type RvListArgs = {
|
|
35
|
+
entity_type?: string
|
|
36
|
+
status?: string
|
|
37
|
+
limit?: number
|
|
38
|
+
user_id: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function rvList(args: RvListArgs) {
|
|
42
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
43
|
+
action: 'rv_list',
|
|
44
|
+
entity_type: args.entity_type,
|
|
45
|
+
status: args.status,
|
|
46
|
+
limit: args.limit,
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
if (!result.ok) {
|
|
50
|
+
return {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: 'text' as const,
|
|
54
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
isError: true,
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// rv_get
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
export const rvGetSchema = {
|
|
73
|
+
review_id: z
|
|
74
|
+
.string()
|
|
75
|
+
.uuid()
|
|
76
|
+
.optional()
|
|
77
|
+
.describe('Review UUID (look up by review ID)'),
|
|
78
|
+
entity_type: z
|
|
79
|
+
.string()
|
|
80
|
+
.optional()
|
|
81
|
+
.describe('Entity type (used with entity_id for lookup by entity)'),
|
|
82
|
+
entity_id: z
|
|
83
|
+
.string()
|
|
84
|
+
.uuid()
|
|
85
|
+
.optional()
|
|
86
|
+
.describe('Entity UUID (used with entity_type for lookup by entity)'),
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
type RvGetArgs = {
|
|
90
|
+
review_id?: string
|
|
91
|
+
entity_type?: string
|
|
92
|
+
entity_id?: string
|
|
93
|
+
user_id: string
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function rvGet(args: RvGetArgs) {
|
|
97
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
98
|
+
action: 'rv_get',
|
|
99
|
+
review_id: args.review_id,
|
|
100
|
+
entity_type: args.entity_type,
|
|
101
|
+
entity_id: args.entity_id,
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
if (!result.ok) {
|
|
105
|
+
return {
|
|
106
|
+
content: [
|
|
107
|
+
{
|
|
108
|
+
type: 'text' as const,
|
|
109
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
isError: true,
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
content: [
|
|
118
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
119
|
+
],
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// rv_create
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
export const rvCreateSchema = {
|
|
128
|
+
entity_type: z
|
|
129
|
+
.enum(['skill', 'agent'])
|
|
130
|
+
.describe('Type of entity to create a review for'),
|
|
131
|
+
entity_id: z
|
|
132
|
+
.string()
|
|
133
|
+
.uuid()
|
|
134
|
+
.describe('UUID of the entity to review'),
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
type RvCreateArgs = {
|
|
138
|
+
entity_type: string
|
|
139
|
+
entity_id: string
|
|
140
|
+
user_id: string
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export async function rvCreate(args: RvCreateArgs) {
|
|
144
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
145
|
+
action: 'rv_create',
|
|
146
|
+
entity_type: args.entity_type,
|
|
147
|
+
entity_id: args.entity_id,
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
if (!result.ok) {
|
|
151
|
+
return {
|
|
152
|
+
content: [
|
|
153
|
+
{
|
|
154
|
+
type: 'text' as const,
|
|
155
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
isError: true,
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
content: [
|
|
164
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
165
|
+
],
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
// rv_decide
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
|
|
173
|
+
export const rvDecideSchema = {
|
|
174
|
+
review_id: z.string().uuid().describe('Review UUID'),
|
|
175
|
+
transition: z
|
|
176
|
+
.enum(['submit', 'accept', 'reject', 'request_revision', 'resubmit', 'archive'])
|
|
177
|
+
.describe('State transition to apply'),
|
|
178
|
+
rationale: z
|
|
179
|
+
.string()
|
|
180
|
+
.optional()
|
|
181
|
+
.describe('Optional rationale for the decision'),
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
type RvDecideArgs = {
|
|
185
|
+
review_id: string
|
|
186
|
+
transition: string
|
|
187
|
+
rationale?: string
|
|
188
|
+
user_id: string
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export async function rvDecide(args: RvDecideArgs) {
|
|
192
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
193
|
+
action: 'rv_decide',
|
|
194
|
+
review_id: args.review_id,
|
|
195
|
+
transition: args.transition,
|
|
196
|
+
rationale: args.rationale,
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
if (!result.ok) {
|
|
200
|
+
return {
|
|
201
|
+
content: [
|
|
202
|
+
{
|
|
203
|
+
type: 'text' as const,
|
|
204
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
isError: true,
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
content: [
|
|
213
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
214
|
+
],
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
// rv_comment
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
|
|
222
|
+
export const rvCommentSchema = {
|
|
223
|
+
review_id: z.string().uuid().describe('Review UUID'),
|
|
224
|
+
body: z.string().describe('Comment body (markdown supported)'),
|
|
225
|
+
agent_id: z
|
|
226
|
+
.string()
|
|
227
|
+
.optional()
|
|
228
|
+
.describe('Agent identifier if comment is posted by an agent'),
|
|
229
|
+
line_start: z
|
|
230
|
+
.number()
|
|
231
|
+
.int()
|
|
232
|
+
.optional()
|
|
233
|
+
.describe('Start line number for inline comments'),
|
|
234
|
+
line_end: z
|
|
235
|
+
.number()
|
|
236
|
+
.int()
|
|
237
|
+
.optional()
|
|
238
|
+
.describe('End line number for inline comments'),
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
type RvCommentArgs = {
|
|
242
|
+
review_id: string
|
|
243
|
+
body: string
|
|
244
|
+
agent_id?: string
|
|
245
|
+
line_start?: number
|
|
246
|
+
line_end?: number
|
|
247
|
+
user_id: string
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export async function rvComment(args: RvCommentArgs) {
|
|
251
|
+
const result = await nexusPost('/api/mcp/reviews', {
|
|
252
|
+
action: 'rv_comment',
|
|
253
|
+
review_id: args.review_id,
|
|
254
|
+
body: args.body,
|
|
255
|
+
agent_id: args.agent_id,
|
|
256
|
+
line_start: args.line_start,
|
|
257
|
+
line_end: args.line_end,
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
if (!result.ok) {
|
|
261
|
+
return {
|
|
262
|
+
content: [
|
|
263
|
+
{
|
|
264
|
+
type: 'text' as const,
|
|
265
|
+
text: JSON.stringify({ error: result.error }, null, 2),
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
isError: true,
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
content: [
|
|
274
|
+
{ type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
|
|
275
|
+
],
|
|
276
|
+
}
|
|
277
|
+
}
|