@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.
Files changed (119) hide show
  1. package/README.md +59 -0
  2. package/dist/auth.d.ts +39 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +47 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/nexus-api.d.ts +29 -0
  7. package/dist/nexus-api.d.ts.map +1 -0
  8. package/dist/nexus-api.js +76 -0
  9. package/dist/nexus-api.js.map +1 -0
  10. package/dist/server.d.ts +65 -0
  11. package/dist/server.d.ts.map +1 -0
  12. package/dist/server.js +183 -0
  13. package/dist/server.js.map +1 -0
  14. package/dist/tools/add-task-note.d.ts +34 -0
  15. package/dist/tools/add-task-note.d.ts.map +1 -0
  16. package/dist/tools/add-task-note.js +39 -0
  17. package/dist/tools/add-task-note.js.map +1 -0
  18. package/dist/tools/append-session-entry.d.ts +53 -0
  19. package/dist/tools/append-session-entry.d.ts.map +1 -0
  20. package/dist/tools/append-session-entry.js +67 -0
  21. package/dist/tools/append-session-entry.js.map +1 -0
  22. package/dist/tools/create-task.d.ts +52 -0
  23. package/dist/tools/create-task.d.ts.map +1 -0
  24. package/dist/tools/create-task.js +51 -0
  25. package/dist/tools/create-task.js.map +1 -0
  26. package/dist/tools/decision-comments.d.ts +54 -0
  27. package/dist/tools/decision-comments.d.ts.map +1 -0
  28. package/dist/tools/decision-comments.js +80 -0
  29. package/dist/tools/decision-comments.js.map +1 -0
  30. package/dist/tools/get-document.d.ts +47 -0
  31. package/dist/tools/get-document.d.ts.map +1 -0
  32. package/dist/tools/get-document.js +68 -0
  33. package/dist/tools/get-document.js.map +1 -0
  34. package/dist/tools/get-project-memory.d.ts +47 -0
  35. package/dist/tools/get-project-memory.d.ts.map +1 -0
  36. package/dist/tools/get-project-memory.js +53 -0
  37. package/dist/tools/get-project-memory.js.map +1 -0
  38. package/dist/tools/get-related-entities.d.ts +44 -0
  39. package/dist/tools/get-related-entities.d.ts.map +1 -0
  40. package/dist/tools/get-related-entities.js +60 -0
  41. package/dist/tools/get-related-entities.js.map +1 -0
  42. package/dist/tools/governance.d.ts +90 -0
  43. package/dist/tools/governance.d.ts.map +1 -0
  44. package/dist/tools/governance.js +124 -0
  45. package/dist/tools/governance.js.map +1 -0
  46. package/dist/tools/ingest-document.d.ts +40 -0
  47. package/dist/tools/ingest-document.d.ts.map +1 -0
  48. package/dist/tools/ingest-document.js +48 -0
  49. package/dist/tools/ingest-document.js.map +1 -0
  50. package/dist/tools/letter-inbox.d.ts +80 -0
  51. package/dist/tools/letter-inbox.d.ts.map +1 -0
  52. package/dist/tools/letter-inbox.js +118 -0
  53. package/dist/tools/letter-inbox.js.map +1 -0
  54. package/dist/tools/letters.d.ts +91 -0
  55. package/dist/tools/letters.d.ts.map +1 -0
  56. package/dist/tools/letters.js +112 -0
  57. package/dist/tools/letters.js.map +1 -0
  58. package/dist/tools/project-list.d.ts +28 -0
  59. package/dist/tools/project-list.d.ts.map +1 -0
  60. package/dist/tools/project-list.js +43 -0
  61. package/dist/tools/project-list.js.map +1 -0
  62. package/dist/tools/reviews.d.ts +145 -0
  63. package/dist/tools/reviews.d.ts.map +1 -0
  64. package/dist/tools/reviews.js +216 -0
  65. package/dist/tools/reviews.js.map +1 -0
  66. package/dist/tools/search-knowledge.d.ts +48 -0
  67. package/dist/tools/search-knowledge.d.ts.map +1 -0
  68. package/dist/tools/search-knowledge.js +54 -0
  69. package/dist/tools/search-knowledge.js.map +1 -0
  70. package/dist/tools/sessions.d.ts +81 -0
  71. package/dist/tools/sessions.d.ts.map +1 -0
  72. package/dist/tools/sessions.js +120 -0
  73. package/dist/tools/sessions.js.map +1 -0
  74. package/dist/tools/skill-assign.d.ts +77 -0
  75. package/dist/tools/skill-assign.d.ts.map +1 -0
  76. package/dist/tools/skill-assign.js +108 -0
  77. package/dist/tools/skill-assign.js.map +1 -0
  78. package/dist/tools/skills.d.ts +138 -0
  79. package/dist/tools/skills.d.ts.map +1 -0
  80. package/dist/tools/skills.js +192 -0
  81. package/dist/tools/skills.js.map +1 -0
  82. package/dist/tools/update-task-status.d.ts +48 -0
  83. package/dist/tools/update-task-status.d.ts.map +1 -0
  84. package/dist/tools/update-task-status.js +51 -0
  85. package/dist/tools/update-task-status.js.map +1 -0
  86. package/package.json +30 -0
  87. package/src/__tests__/auth.test.ts +162 -0
  88. package/src/__tests__/decision-comments.test.ts +173 -0
  89. package/src/__tests__/helpers.ts +58 -0
  90. package/src/__tests__/layer1-knowledge.test.ts +302 -0
  91. package/src/__tests__/layer2-coordination.test.ts +775 -0
  92. package/src/__tests__/layer3-governance.test.ts +205 -0
  93. package/src/__tests__/project-list-and-skill-assign.test.ts +282 -0
  94. package/src/__tests__/reviews.test.ts +420 -0
  95. package/src/__tests__/server.test.ts +238 -0
  96. package/src/__tests__/setup.ts +15 -0
  97. package/src/auth.ts +81 -0
  98. package/src/nexus-api.ts +110 -0
  99. package/src/server.ts +499 -0
  100. package/src/tools/add-task-note.ts +50 -0
  101. package/src/tools/append-session-entry.ts +83 -0
  102. package/src/tools/create-task.ts +66 -0
  103. package/src/tools/decision-comments.ts +102 -0
  104. package/src/tools/get-document.ts +80 -0
  105. package/src/tools/get-project-memory.ts +65 -0
  106. package/src/tools/get-related-entities.ts +73 -0
  107. package/src/tools/governance.ts +162 -0
  108. package/src/tools/ingest-document.ts +64 -0
  109. package/src/tools/letter-inbox.ts +157 -0
  110. package/src/tools/letters.ts +144 -0
  111. package/src/tools/project-list.ts +52 -0
  112. package/src/tools/reviews.ts +277 -0
  113. package/src/tools/search-knowledge.ts +68 -0
  114. package/src/tools/sessions.ts +154 -0
  115. package/src/tools/skill-assign.ts +142 -0
  116. package/src/tools/skills.ts +252 -0
  117. package/src/tools/update-task-status.ts +64 -0
  118. package/tsconfig.json +20 -0
  119. package/vitest.config.ts +8 -0
@@ -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().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,154 @@
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().describe('Session title (e.g., "Architecture review")'),
21
+ agent_id: z
22
+ .string()
23
+ .optional()
24
+ .describe('Agent identifier starting this session'),
25
+ }
26
+
27
+ type CreateSessionArgs = {
28
+ project_id: string
29
+ title: string
30
+ agent_id?: string
31
+ user_id: string
32
+ }
33
+
34
+ export async function createSession(args: CreateSessionArgs) {
35
+ const result = await nexusPost('/api/mcp/sessions', {
36
+ action: 'session_create',
37
+ project_id: args.project_id,
38
+ title: args.title,
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
+ }
59
+
60
+ // ---------------------------------------------------------------------------
61
+ // close_session -> session_close
62
+ // ---------------------------------------------------------------------------
63
+
64
+ export const closeSessionSchema = {
65
+ session_id: z.string().uuid().describe('Session UUID to close'),
66
+ summary: z
67
+ .string()
68
+ .optional()
69
+ .describe('Summary of what was accomplished in the session'),
70
+ next_entry_point: z
71
+ .string()
72
+ .optional()
73
+ .describe('Suggested starting point for the next session'),
74
+ }
75
+
76
+ type CloseSessionArgs = {
77
+ session_id: string
78
+ summary?: string
79
+ next_entry_point?: string
80
+ user_id: string
81
+ }
82
+
83
+ export async function closeSession(args: CloseSessionArgs) {
84
+ const result = await nexusPost('/api/mcp/sessions', {
85
+ action: 'session_close',
86
+ session_id: args.session_id,
87
+ summary: args.summary,
88
+ next_entry_point: args.next_entry_point,
89
+ })
90
+
91
+ if (!result.ok) {
92
+ return {
93
+ content: [
94
+ {
95
+ type: 'text' as const,
96
+ text: JSON.stringify({ error: result.error }, null, 2),
97
+ },
98
+ ],
99
+ isError: true,
100
+ }
101
+ }
102
+
103
+ return {
104
+ content: [
105
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
106
+ ],
107
+ }
108
+ }
109
+
110
+ // ---------------------------------------------------------------------------
111
+ // list_open_sessions -> session_list
112
+ // ---------------------------------------------------------------------------
113
+
114
+ export const listOpenSessionsSchema = {
115
+ project_id: z.string().uuid().describe('Project UUID'),
116
+ limit: z
117
+ .number()
118
+ .int()
119
+ .min(1)
120
+ .max(100)
121
+ .default(25)
122
+ .describe('Maximum number of sessions to return (default 25)'),
123
+ }
124
+
125
+ type ListOpenSessionsArgs = {
126
+ project_id: string
127
+ limit?: number
128
+ }
129
+
130
+ export async function listOpenSessions(args: ListOpenSessionsArgs) {
131
+ const result = await nexusPost('/api/mcp/sessions', {
132
+ action: 'session_list',
133
+ project_id: args.project_id,
134
+ limit: args.limit ?? 25,
135
+ })
136
+
137
+ if (!result.ok) {
138
+ return {
139
+ content: [
140
+ {
141
+ type: 'text' as const,
142
+ text: JSON.stringify({ error: result.error }, null, 2),
143
+ },
144
+ ],
145
+ isError: true,
146
+ }
147
+ }
148
+
149
+ return {
150
+ content: [
151
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
152
+ ],
153
+ }
154
+ }
@@ -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().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().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
+ }
@@ -0,0 +1,252 @@
1
+ /**
2
+ * sk_list + sk_get + sk_create + sk_update + sk_activate -- Layer 2 Coordination
3
+ *
4
+ * Skill management tools for the Nexus platform.
5
+ * Skills are tenant-scoped instruction sets for agent sessions.
6
+ * Delegates to POST /api/mcp/skills.
7
+ */
8
+
9
+ import { z } from 'zod'
10
+ import { nexusPost } from '../nexus-api.js'
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // sk_list
14
+ // ---------------------------------------------------------------------------
15
+
16
+ export const skListSchema = {
17
+ status_filter: z
18
+ .array(z.enum(['draft', 'active', 'archived']))
19
+ .optional()
20
+ .describe('Filter by skill status (default: draft, active)'),
21
+ limit: z
22
+ .number()
23
+ .min(1)
24
+ .max(100)
25
+ .default(50)
26
+ .describe('Max number of skills to return'),
27
+ }
28
+
29
+ type SkListArgs = {
30
+ status_filter?: string[]
31
+ limit?: number
32
+ user_id: string
33
+ }
34
+
35
+ export async function skList(args: SkListArgs) {
36
+ const result = await nexusPost('/api/mcp/skills', {
37
+ action: 'sk_list',
38
+ status_filter: args.status_filter,
39
+ limit: args.limit ?? 50,
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
+ // sk_get
63
+ // ---------------------------------------------------------------------------
64
+
65
+ export const skGetSchema = {
66
+ skill_id: z
67
+ .string()
68
+ .describe('Skill identifier (e.g., nx-init-nexus) or UUID'),
69
+ }
70
+
71
+ type SkGetArgs = {
72
+ skill_id: string
73
+ user_id: string
74
+ }
75
+
76
+ export async function skGet(args: SkGetArgs) {
77
+ const result = await nexusPost('/api/mcp/skills', {
78
+ action: 'sk_get',
79
+ skill_id: args.skill_id,
80
+ })
81
+
82
+ if (!result.ok) {
83
+ return {
84
+ content: [
85
+ {
86
+ type: 'text' as const,
87
+ text: JSON.stringify({ error: result.error }, null, 2),
88
+ },
89
+ ],
90
+ isError: true,
91
+ }
92
+ }
93
+
94
+ return {
95
+ content: [
96
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
97
+ ],
98
+ }
99
+ }
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // sk_create
103
+ // ---------------------------------------------------------------------------
104
+
105
+ export const skCreateSchema = {
106
+ skill_id: z.string().describe('Skill identifier (e.g., nx-init-nexus)'),
107
+ name: z.string().describe('Human-readable skill name'),
108
+ description: z.string().optional().describe('Short description'),
109
+ body: z.string().describe('Full markdown instruction content'),
110
+ auto_generate_command: z
111
+ .boolean()
112
+ .default(true)
113
+ .describe('Auto-generate an OpenCode command (default: true)'),
114
+ }
115
+
116
+ type SkCreateArgs = {
117
+ skill_id: string
118
+ name: string
119
+ description?: string
120
+ body: string
121
+ auto_generate_command?: boolean
122
+ user_id: string
123
+ }
124
+
125
+ export async function skCreate(args: SkCreateArgs) {
126
+ const result = await nexusPost('/api/mcp/skills', {
127
+ action: 'sk_create',
128
+ skill_id: args.skill_id,
129
+ name: args.name,
130
+ description: args.description,
131
+ body: args.body,
132
+ auto_generate_command: args.auto_generate_command ?? true,
133
+ })
134
+
135
+ if (!result.ok) {
136
+ return {
137
+ content: [
138
+ {
139
+ type: 'text' as const,
140
+ text: JSON.stringify({ error: result.error }, null, 2),
141
+ },
142
+ ],
143
+ isError: true,
144
+ }
145
+ }
146
+
147
+ return {
148
+ content: [
149
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
150
+ ],
151
+ }
152
+ }
153
+
154
+ // ---------------------------------------------------------------------------
155
+ // sk_update
156
+ // ---------------------------------------------------------------------------
157
+
158
+ export const skUpdateSchema = {
159
+ skill_id: z
160
+ .string()
161
+ .describe('Skill identifier (e.g., nx-init-nexus) or UUID'),
162
+ name: z.string().optional().describe('Updated name'),
163
+ description: z.string().optional().describe('Updated description'),
164
+ body: z.string().optional().describe('Updated markdown content'),
165
+ auto_generate_command: z
166
+ .boolean()
167
+ .optional()
168
+ .describe('Toggle command auto-generation'),
169
+ }
170
+
171
+ type SkUpdateArgs = {
172
+ skill_id: string
173
+ name?: string
174
+ description?: string
175
+ body?: string
176
+ auto_generate_command?: boolean
177
+ user_id: string
178
+ }
179
+
180
+ export async function skUpdate(args: SkUpdateArgs) {
181
+ const result = await nexusPost('/api/mcp/skills', {
182
+ action: 'sk_update',
183
+ skill_id: args.skill_id,
184
+ name: args.name,
185
+ description: args.description,
186
+ body: args.body,
187
+ auto_generate_command: args.auto_generate_command,
188
+ })
189
+
190
+ if (!result.ok) {
191
+ return {
192
+ content: [
193
+ {
194
+ type: 'text' as const,
195
+ text: JSON.stringify({ error: result.error }, null, 2),
196
+ },
197
+ ],
198
+ isError: true,
199
+ }
200
+ }
201
+
202
+ return {
203
+ content: [
204
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
205
+ ],
206
+ }
207
+ }
208
+
209
+ // ---------------------------------------------------------------------------
210
+ // sk_activate
211
+ // ---------------------------------------------------------------------------
212
+
213
+ export const skActivateSchema = {
214
+ skill_id: z
215
+ .string()
216
+ .describe('Skill identifier (e.g., nx-init-nexus) or UUID'),
217
+ status: z
218
+ .enum(['active', 'archived', 'draft'])
219
+ .describe('New status for the skill'),
220
+ }
221
+
222
+ type SkActivateArgs = {
223
+ skill_id: string
224
+ status: string
225
+ user_id: string
226
+ }
227
+
228
+ export async function skActivate(args: SkActivateArgs) {
229
+ const result = await nexusPost('/api/mcp/skills', {
230
+ action: 'sk_activate',
231
+ skill_id: args.skill_id,
232
+ status: args.status,
233
+ })
234
+
235
+ if (!result.ok) {
236
+ return {
237
+ content: [
238
+ {
239
+ type: 'text' as const,
240
+ text: JSON.stringify({ error: result.error }, null, 2),
241
+ },
242
+ ],
243
+ isError: true,
244
+ }
245
+ }
246
+
247
+ return {
248
+ content: [
249
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
250
+ ],
251
+ }
252
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * task_update -- Layer 2 Coordination
3
+ *
4
+ * Updates the status (and optionally priority/assignee) of an existing task.
5
+ * Delegates to POST /api/mcp/tasks (action: task_update).
6
+ */
7
+
8
+ import { z } from 'zod'
9
+ import { nexusPost } from '../nexus-api.js'
10
+
11
+ export const updateTaskStatusSchema = {
12
+ task_id: z.string().uuid().describe('Task UUID to update'),
13
+ status: z
14
+ .enum(['open', 'in_progress', 'blocked', 'done', 'cancelled'])
15
+ .describe('New task status'),
16
+ priority: z
17
+ .enum(['low', 'medium', 'high', 'urgent'])
18
+ .optional()
19
+ .describe('Updated priority (optional)'),
20
+ assignee: z
21
+ .string()
22
+ .uuid()
23
+ .optional()
24
+ .describe('UUID of the newly assigned user (optional)'),
25
+ agent_id: z.string().optional().describe('Agent identifier if applicable'),
26
+ }
27
+
28
+ type UpdateTaskStatusArgs = {
29
+ task_id: string
30
+ status: string
31
+ priority?: string
32
+ assignee?: string
33
+ user_id: string
34
+ agent_id?: string
35
+ }
36
+
37
+ export async function updateTaskStatus(args: UpdateTaskStatusArgs) {
38
+ const result = await nexusPost('/api/mcp/tasks', {
39
+ action: 'task_update',
40
+ task_id: args.task_id,
41
+ status: args.status,
42
+ priority: args.priority,
43
+ assignee: args.assignee,
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
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
+ "lib": ["ES2022"],
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": ["src/**/*.ts"],
19
+ "exclude": ["node_modules", "dist", "src/__tests__"]
20
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config'
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ setupFiles: ['./src/__tests__/setup.ts'],
7
+ },
8
+ })