@gwdn/nexus-mcp 0.7.0 → 0.8.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directives.js","sourceRoot":"","sources":["../../src/tools/directives.ts"],"names":[],"mappings":"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"}
@@ -86,11 +86,11 @@ export declare const rvDecideSchema: {
86
86
  review_id: z.ZodString;
87
87
  transition: z.ZodEnum<{
88
88
  accept: "accept";
89
+ archive: "archive";
89
90
  submit: "submit";
90
91
  reject: "reject";
91
92
  request_revision: "request_revision";
92
93
  resubmit: "resubmit";
93
- archive: "archive";
94
94
  }>;
95
95
  rationale: z.ZodOptional<z.ZodString>;
96
96
  };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * doc_update -- Layer 2 Coordination
3
+ *
4
+ * Update title, body, or source_url of an ingest item.
5
+ * Supports full body replacement or append mode.
6
+ * Delegates to POST /api/mcp/documents (action: doc_update).
7
+ */
8
+ import { z } from 'zod';
9
+ export declare const updateDocumentSchema: {
10
+ document_id: z.ZodString;
11
+ title: z.ZodOptional<z.ZodString>;
12
+ body: z.ZodOptional<z.ZodString>;
13
+ source_url: z.ZodOptional<z.ZodString>;
14
+ append_body: z.ZodOptional<z.ZodString>;
15
+ };
16
+ type UpdateDocumentArgs = {
17
+ document_id: string;
18
+ title?: string;
19
+ body?: string;
20
+ source_url?: string;
21
+ append_body?: string;
22
+ user_id: string;
23
+ };
24
+ export declare function updateDocument(args: UpdateDocumentArgs): Promise<{
25
+ content: {
26
+ type: "text";
27
+ text: string;
28
+ }[];
29
+ isError: boolean;
30
+ } | {
31
+ content: {
32
+ type: "text";
33
+ text: string;
34
+ }[];
35
+ isError?: undefined;
36
+ }>;
37
+ export {};
38
+ //# sourceMappingURL=update-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-document.d.ts","sourceRoot":"","sources":["../../src/tools/update-document.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,oBAAoB;;;;;;CAgBhC,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB;;;;;;;;;;;;GA2B5D"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * doc_update -- Layer 2 Coordination
3
+ *
4
+ * Update title, body, or source_url of an ingest item.
5
+ * Supports full body replacement or append mode.
6
+ * Delegates to POST /api/mcp/documents (action: doc_update).
7
+ */
8
+ import { z } from 'zod';
9
+ import { nexusPost } from '../nexus-api.js';
10
+ export const updateDocumentSchema = {
11
+ document_id: z.string().uuid().describe('Document UUID to update'),
12
+ title: z.string().max(500).optional().describe('New document title'),
13
+ body: z
14
+ .string()
15
+ .max(100_000)
16
+ .optional()
17
+ .describe('New document body (replaces existing content)'),
18
+ source_url: z.string().url().optional().describe('Updated source URL'),
19
+ append_body: z
20
+ .string()
21
+ .max(100_000)
22
+ .optional()
23
+ .describe('Content to append to existing body (ignored if body is also provided)'),
24
+ };
25
+ export async function updateDocument(args) {
26
+ const result = await nexusPost('/api/mcp/documents', {
27
+ action: 'doc_update',
28
+ document_id: args.document_id,
29
+ title: args.title,
30
+ body: args.body,
31
+ source_url: args.source_url,
32
+ append_body: args.append_body,
33
+ });
34
+ if (!result.ok) {
35
+ return {
36
+ content: [
37
+ {
38
+ type: 'text',
39
+ text: JSON.stringify({ error: result.error }, null, 2),
40
+ },
41
+ ],
42
+ isError: true,
43
+ };
44
+ }
45
+ return {
46
+ content: [
47
+ { type: 'text', text: JSON.stringify(result.data, null, 2) },
48
+ ],
49
+ };
50
+ }
51
+ //# sourceMappingURL=update-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-document.js","sourceRoot":"","sources":["../../src/tools/update-document.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IAClE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IACpE,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,GAAG,CAAC,OAAO,CAAC;SACZ,QAAQ,EAAE;SACV,QAAQ,CAAC,+CAA+C,CAAC;IAC5D,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IACtE,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,GAAG,CAAC,OAAO,CAAC;SACZ,QAAQ,EAAE;SACV,QAAQ,CACP,uEAAuE,CACxE;CACJ,CAAA;AAWD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAwB;IAC3D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,oBAAoB,EAAE;QACnD,MAAM,EAAE,YAAY;QACpB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC,CAAA;IAEF,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvD;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAA;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;SACtE;KACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gwdn/nexus-mcp",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "MCP server for the Nexus platform",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",
@@ -78,9 +78,9 @@ describe('MCP Server: withIdentity wrapper', () => {
78
78
  })
79
79
 
80
80
  describe('MCP Server: Schema exports', () => {
81
- const EXPECTED_TOOL_COUNT = 38
81
+ const EXPECTED_TOOL_COUNT = 48
82
82
 
83
- it('should register exactly 38 tools in server.ts', () => {
83
+ it('should register exactly 48 tools in server.ts', () => {
84
84
  // Static analysis: count server.tool( calls in server.ts as a regression guard.
85
85
  // If you add or remove a tool, update EXPECTED_TOOL_COUNT above.
86
86
  const serverSource = readFileSync(
package/src/server.ts CHANGED
@@ -38,6 +38,13 @@
38
38
  * - sk_assign: Assign a skill to a project
39
39
  * - sk_unassign: Remove a skill assignment from a project
40
40
  * - sk_export: Export all skill assignments for a project
41
+ * - pd_list: List project directives
42
+ * - pd_get: Get a specific directive
43
+ * - pd_create: Create a new directive
44
+ * - pd_update: Update an existing directive
45
+ * - pd_delete: Delete a directive
46
+ * - pd_toggle: Toggle directive enabled/disabled
47
+ * - directive_export: Export enabled directives (CLI format)
41
48
  * - doc_ingest: Push text/markdown content into project knowledge base
42
49
  * - doc_list: List ingested documents for a project
43
50
  * - session_append: Append to a session (write-isolated)
@@ -102,6 +109,18 @@ import {
102
109
  ingestDocument,
103
110
  ingestDocumentSchema,
104
111
  } from './tools/ingest-document.js'
112
+ import {
113
+ classifyDocument,
114
+ classifyDocumentSchema,
115
+ } from './tools/classify-document.js'
116
+ import {
117
+ updateDocument,
118
+ updateDocumentSchema,
119
+ } from './tools/update-document.js'
120
+ import {
121
+ deleteDocument,
122
+ deleteDocumentSchema,
123
+ } from './tools/delete-document.js'
105
124
  import {
106
125
  acknowledgeLetter,
107
126
  acknowledgeLetterSchema,
@@ -149,6 +168,22 @@ import {
149
168
  skUnassign,
150
169
  skUnassignSchema,
151
170
  } from './tools/skill-assign.js'
171
+ import {
172
+ pdList,
173
+ pdListSchema,
174
+ pdGet,
175
+ pdGetSchema,
176
+ pdCreate,
177
+ pdCreateSchema,
178
+ pdUpdate,
179
+ pdUpdateSchema,
180
+ pdDelete,
181
+ pdDeleteSchema,
182
+ pdToggle,
183
+ pdToggleSchema,
184
+ directiveExport,
185
+ directiveExportSchema,
186
+ } from './tools/directives.js'
152
187
  import {
153
188
  updateTaskStatus,
154
189
  updateTaskStatusSchema,
@@ -202,7 +237,7 @@ function withIdentity(handler: (args: any) => Promise<any>) {
202
237
  const server = new McpServer(
203
238
  {
204
239
  name: 'nexus-mcp',
205
- version: '0.6.1',
240
+ version: '0.8.0',
206
241
  },
207
242
  {
208
243
  capabilities: {
@@ -331,6 +366,27 @@ server.tool(
331
366
  withIdentity(listDocuments),
332
367
  )
333
368
 
369
+ server.tool(
370
+ 'doc_classify',
371
+ 'Update the classification of an ingest item. Valid classifications: unclassified, research_note, planning_item, decision_input, reference, archive.',
372
+ classifyDocumentSchema,
373
+ withIdentity(classifyDocument),
374
+ )
375
+
376
+ server.tool(
377
+ 'doc_update',
378
+ 'Update title, body, or source_url of an ingest item. Supports full body replacement or append mode via append_body. At least one field must be provided.',
379
+ updateDocumentSchema,
380
+ withIdentity(updateDocument),
381
+ )
382
+
383
+ server.tool(
384
+ 'doc_delete',
385
+ 'Delete an ingest item from a project knowledge base. This action is irreversible.',
386
+ deleteDocumentSchema,
387
+ withIdentity(deleteDocument),
388
+ )
389
+
334
390
  server.tool(
335
391
  'session_append',
336
392
  'Append an entry to an existing session. Enforces session write isolation: only the session creator can append entries.',
@@ -437,6 +493,59 @@ server.tool(
437
493
  withIdentity(skExport),
438
494
  )
439
495
 
496
+ // ---------------------------------------------------------------------------
497
+ // Layer 2 (continued): Project Directives tools
498
+ // ---------------------------------------------------------------------------
499
+
500
+ server.tool(
501
+ 'pd_list',
502
+ 'List project directives with optional enabled filter. Returns directives ordered by priority and creation date.',
503
+ pdListSchema,
504
+ withIdentity(pdList),
505
+ )
506
+
507
+ server.tool(
508
+ 'pd_get',
509
+ 'Get a specific project directive by UUID. Returns full directive details.',
510
+ pdGetSchema,
511
+ withIdentity(pdGet),
512
+ )
513
+
514
+ server.tool(
515
+ 'pd_create',
516
+ 'Create a new project directive. Directives are project-scoped rules/policies that guide agent behavior.',
517
+ pdCreateSchema,
518
+ withIdentity(pdCreate),
519
+ )
520
+
521
+ server.tool(
522
+ 'pd_update',
523
+ 'Update an existing project directive. Supports partial updates for title, body, category, priority, and enabled state.',
524
+ pdUpdateSchema,
525
+ withIdentity(pdUpdate),
526
+ )
527
+
528
+ server.tool(
529
+ 'pd_delete',
530
+ 'Delete a project directive by UUID.',
531
+ pdDeleteSchema,
532
+ withIdentity(pdDelete),
533
+ )
534
+
535
+ server.tool(
536
+ 'pd_toggle',
537
+ 'Toggle a project directive enabled/disabled. Omit enabled parameter to invert current state.',
538
+ pdToggleSchema,
539
+ withIdentity(pdToggle),
540
+ )
541
+
542
+ server.tool(
543
+ 'directive_export',
544
+ 'Export all enabled directives for a project in CLI-compatible format.',
545
+ directiveExportSchema,
546
+ withIdentity(directiveExport),
547
+ )
548
+
440
549
  // ---------------------------------------------------------------------------
441
550
  // Layer 3: Governance tools
442
551
  // ---------------------------------------------------------------------------
@@ -0,0 +1,55 @@
1
+ /**
2
+ * doc_classify -- Layer 2 Coordination
3
+ *
4
+ * Update the classification of an ingest item.
5
+ * Delegates to POST /api/mcp/documents (action: doc_classify).
6
+ */
7
+
8
+ import { z } from 'zod'
9
+ import { nexusPost } from '../nexus-api.js'
10
+
11
+ export const classifyDocumentSchema = {
12
+ document_id: z.string().uuid().describe('Document UUID to classify'),
13
+ classification: z
14
+ .enum([
15
+ 'unclassified',
16
+ 'research_note',
17
+ 'planning_item',
18
+ 'decision_input',
19
+ 'reference',
20
+ 'archive',
21
+ ])
22
+ .describe('New classification for the document'),
23
+ }
24
+
25
+ type ClassifyDocumentArgs = {
26
+ document_id: string
27
+ classification: string
28
+ user_id: string
29
+ }
30
+
31
+ export async function classifyDocument(args: ClassifyDocumentArgs) {
32
+ const result = await nexusPost('/api/mcp/documents', {
33
+ action: 'doc_classify',
34
+ document_id: args.document_id,
35
+ classification: args.classification,
36
+ })
37
+
38
+ if (!result.ok) {
39
+ return {
40
+ content: [
41
+ {
42
+ type: 'text' as const,
43
+ text: JSON.stringify({ error: result.error }, null, 2),
44
+ },
45
+ ],
46
+ isError: true,
47
+ }
48
+ }
49
+
50
+ return {
51
+ content: [
52
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
53
+ ],
54
+ }
55
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * doc_delete -- Layer 2 Coordination
3
+ *
4
+ * Delete an ingest item from a project's knowledge base.
5
+ * Delegates to POST /api/mcp/documents (action: doc_delete).
6
+ */
7
+
8
+ import { z } from 'zod'
9
+ import { nexusPost } from '../nexus-api.js'
10
+
11
+ export const deleteDocumentSchema = {
12
+ document_id: z.string().uuid().describe('Document UUID to delete'),
13
+ }
14
+
15
+ type DeleteDocumentArgs = {
16
+ document_id: string
17
+ user_id: string
18
+ }
19
+
20
+ export async function deleteDocument(args: DeleteDocumentArgs) {
21
+ const result = await nexusPost('/api/mcp/documents', {
22
+ action: 'doc_delete',
23
+ document_id: args.document_id,
24
+ })
25
+
26
+ if (!result.ok) {
27
+ return {
28
+ content: [
29
+ {
30
+ type: 'text' as const,
31
+ text: JSON.stringify({ error: result.error }, null, 2),
32
+ },
33
+ ],
34
+ isError: true,
35
+ }
36
+ }
37
+
38
+ return {
39
+ content: [
40
+ { type: 'text' as const, text: JSON.stringify(result.data, null, 2) },
41
+ ],
42
+ }
43
+ }
@@ -0,0 +1,303 @@
1
+ /**
2
+ * pd_list + pd_get + pd_create + pd_update + pd_delete + pd_toggle + directive_export
3
+ *
4
+ * Project Directives management tools for the Nexus platform.
5
+ * Directives are project-scoped rules/policies that guide agent behavior.
6
+ * Delegates to POST /api/mcp/directives.
7
+ */
8
+
9
+ import { z } from 'zod'
10
+ import { nexusPost } from '../nexus-api.js'
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Shared helpers
14
+ // ---------------------------------------------------------------------------
15
+
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ function errorResult(result: { error: string | null }) {
18
+ return {
19
+ content: [
20
+ {
21
+ type: 'text' as const,
22
+ text: JSON.stringify({ error: result.error }, null, 2),
23
+ },
24
+ ],
25
+ isError: true,
26
+ }
27
+ }
28
+
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ function okResult(data: any) {
31
+ return {
32
+ content: [
33
+ { type: 'text' as const, text: JSON.stringify(data, null, 2) },
34
+ ],
35
+ }
36
+ }
37
+
38
+ // ---------------------------------------------------------------------------
39
+ // pd_list
40
+ // ---------------------------------------------------------------------------
41
+
42
+ export const pdListSchema = {
43
+ project_id: z
44
+ .string()
45
+ .uuid()
46
+ .describe('Project UUID'),
47
+ enabled: z
48
+ .boolean()
49
+ .optional()
50
+ .describe('Filter by enabled status'),
51
+ limit: z
52
+ .number()
53
+ .min(1)
54
+ .max(100)
55
+ .default(50)
56
+ .describe('Maximum results to return'),
57
+ }
58
+
59
+ type PdListArgs = {
60
+ project_id: string
61
+ enabled?: boolean
62
+ limit?: number
63
+ user_id: string
64
+ }
65
+
66
+ export async function pdList(args: PdListArgs) {
67
+ const result = await nexusPost('/api/mcp/directives', {
68
+ action: 'pd_list',
69
+ project_id: args.project_id,
70
+ enabled: args.enabled,
71
+ limit: args.limit ?? 50,
72
+ })
73
+
74
+ if (!result.ok) return errorResult(result)
75
+ return okResult(result.data)
76
+ }
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // pd_get
80
+ // ---------------------------------------------------------------------------
81
+
82
+ export const pdGetSchema = {
83
+ directive_id: z
84
+ .string()
85
+ .uuid()
86
+ .describe('Directive UUID'),
87
+ }
88
+
89
+ type PdGetArgs = {
90
+ directive_id: string
91
+ user_id: string
92
+ }
93
+
94
+ export async function pdGet(args: PdGetArgs) {
95
+ const result = await nexusPost('/api/mcp/directives', {
96
+ action: 'pd_get',
97
+ directive_id: args.directive_id,
98
+ })
99
+
100
+ if (!result.ok) return errorResult(result)
101
+ return okResult(result.data)
102
+ }
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // pd_create
106
+ // ---------------------------------------------------------------------------
107
+
108
+ export const pdCreateSchema = {
109
+ project_id: z
110
+ .string()
111
+ .uuid()
112
+ .describe('Project UUID'),
113
+ title: z
114
+ .string()
115
+ .max(500)
116
+ .describe('Directive title'),
117
+ body: z
118
+ .string()
119
+ .max(10000)
120
+ .optional()
121
+ .describe('Directive body (markdown)'),
122
+ category: z
123
+ .string()
124
+ .max(100)
125
+ .default('general')
126
+ .describe('Directive category (e.g. general, security, deployment)'),
127
+ priority: z
128
+ .enum(['low', 'medium', 'high'])
129
+ .default('medium')
130
+ .describe('Directive priority'),
131
+ enabled: z
132
+ .boolean()
133
+ .default(true)
134
+ .describe('Whether the directive is enabled'),
135
+ }
136
+
137
+ type PdCreateArgs = {
138
+ project_id: string
139
+ title: string
140
+ body?: string
141
+ category?: string
142
+ priority?: string
143
+ enabled?: boolean
144
+ user_id: string
145
+ }
146
+
147
+ export async function pdCreate(args: PdCreateArgs) {
148
+ const result = await nexusPost('/api/mcp/directives', {
149
+ action: 'pd_create',
150
+ project_id: args.project_id,
151
+ title: args.title,
152
+ body: args.body,
153
+ category: args.category ?? 'general',
154
+ priority: args.priority ?? 'medium',
155
+ enabled: args.enabled !== false,
156
+ })
157
+
158
+ if (!result.ok) return errorResult(result)
159
+ return okResult(result.data)
160
+ }
161
+
162
+ // ---------------------------------------------------------------------------
163
+ // pd_update
164
+ // ---------------------------------------------------------------------------
165
+
166
+ export const pdUpdateSchema = {
167
+ directive_id: z
168
+ .string()
169
+ .uuid()
170
+ .describe('Directive UUID'),
171
+ title: z
172
+ .string()
173
+ .max(500)
174
+ .optional()
175
+ .describe('Updated title'),
176
+ body: z
177
+ .string()
178
+ .max(10000)
179
+ .optional()
180
+ .describe('Updated body (markdown)'),
181
+ category: z
182
+ .string()
183
+ .max(100)
184
+ .optional()
185
+ .describe('Updated category'),
186
+ priority: z
187
+ .enum(['low', 'medium', 'high'])
188
+ .optional()
189
+ .describe('Updated priority'),
190
+ enabled: z
191
+ .boolean()
192
+ .optional()
193
+ .describe('Updated enabled state'),
194
+ }
195
+
196
+ type PdUpdateArgs = {
197
+ directive_id: string
198
+ title?: string
199
+ body?: string
200
+ category?: string
201
+ priority?: string
202
+ enabled?: boolean
203
+ user_id: string
204
+ }
205
+
206
+ export async function pdUpdate(args: PdUpdateArgs) {
207
+ const result = await nexusPost('/api/mcp/directives', {
208
+ action: 'pd_update',
209
+ directive_id: args.directive_id,
210
+ title: args.title,
211
+ body: args.body,
212
+ category: args.category,
213
+ priority: args.priority,
214
+ enabled: args.enabled,
215
+ })
216
+
217
+ if (!result.ok) return errorResult(result)
218
+ return okResult(result.data)
219
+ }
220
+
221
+ // ---------------------------------------------------------------------------
222
+ // pd_delete
223
+ // ---------------------------------------------------------------------------
224
+
225
+ export const pdDeleteSchema = {
226
+ directive_id: z
227
+ .string()
228
+ .uuid()
229
+ .describe('Directive UUID to delete'),
230
+ }
231
+
232
+ type PdDeleteArgs = {
233
+ directive_id: string
234
+ user_id: string
235
+ }
236
+
237
+ export async function pdDelete(args: PdDeleteArgs) {
238
+ const result = await nexusPost('/api/mcp/directives', {
239
+ action: 'pd_delete',
240
+ directive_id: args.directive_id,
241
+ })
242
+
243
+ if (!result.ok) return errorResult(result)
244
+ return okResult(result.data)
245
+ }
246
+
247
+ // ---------------------------------------------------------------------------
248
+ // pd_toggle
249
+ // ---------------------------------------------------------------------------
250
+
251
+ export const pdToggleSchema = {
252
+ directive_id: z
253
+ .string()
254
+ .uuid()
255
+ .describe('Directive UUID to toggle'),
256
+ enabled: z
257
+ .boolean()
258
+ .optional()
259
+ .describe('Explicit enabled state (omit to invert current)'),
260
+ }
261
+
262
+ type PdToggleArgs = {
263
+ directive_id: string
264
+ enabled?: boolean
265
+ user_id: string
266
+ }
267
+
268
+ export async function pdToggle(args: PdToggleArgs) {
269
+ const result = await nexusPost('/api/mcp/directives', {
270
+ action: 'pd_toggle',
271
+ directive_id: args.directive_id,
272
+ enabled: args.enabled,
273
+ })
274
+
275
+ if (!result.ok) return errorResult(result)
276
+ return okResult(result.data)
277
+ }
278
+
279
+ // ---------------------------------------------------------------------------
280
+ // directive_export
281
+ // ---------------------------------------------------------------------------
282
+
283
+ export const directiveExportSchema = {
284
+ project_id: z
285
+ .string()
286
+ .uuid()
287
+ .describe('Project UUID'),
288
+ }
289
+
290
+ type DirectiveExportArgs = {
291
+ project_id: string
292
+ user_id: string
293
+ }
294
+
295
+ export async function directiveExport(args: DirectiveExportArgs) {
296
+ const result = await nexusPost('/api/mcp/directives', {
297
+ action: 'directive_export',
298
+ project_id: args.project_id,
299
+ })
300
+
301
+ if (!result.ok) return errorResult(result)
302
+ return okResult(result.data)
303
+ }