@powerhousedao/reactor-mcp 4.1.0-dev.4 → 4.1.0-dev.7

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.
@@ -1,271 +1,29 @@
1
- import { McpServer, ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { generateFromDocument, validateDocumentModelState, } from "@powerhousedao/codegen";
3
- import { getConfig } from "@powerhousedao/config/utils";
4
- import * as documentModelZ from "document-model/document-model/gen/schema/zod";
5
- import { z } from "zod";
6
- // Discriminated union schema that ties each action type to its specific input schema
7
- const DocumentModelActionSchema = z.discriminatedUnion("type", [
8
- // Versioning and Change Log Operations
9
- z.object({
10
- type: z
11
- .literal("ADD_CHANGE_LOG_ITEM")
12
- .describe("Add a new item to the version change log"),
13
- input: documentModelZ.AddChangeLogItemInputSchema(),
14
- }),
15
- z.object({
16
- type: z
17
- .literal("DELETE_CHANGE_LOG_ITEM")
18
- .describe("Remove an item from the version change log"),
19
- input: documentModelZ.DeleteChangeLogItemInputSchema(),
20
- }),
21
- z.object({
22
- type: z
23
- .literal("UPDATE_CHANGE_LOG_ITEM")
24
- .describe("Update an existing change log item"),
25
- input: documentModelZ.UpdateChangeLogItemInputSchema(),
26
- }),
27
- z.object({
28
- type: z
29
- .literal("REORDER_CHANGE_LOG_ITEMS")
30
- .describe("Reorder items in the change log"),
31
- input: documentModelZ.ReorderChangeLogItemsInputSchema(),
32
- }),
33
- z.object({
34
- type: z
35
- .literal("RELEASE_NEW_VERSION")
36
- .describe("Release a new version of the document model"),
37
- input: z.object({}), // No input required for version release
38
- }),
39
- // Model Header Operations
40
- z.object({
41
- type: z
42
- .literal("SET_MODEL_NAME")
43
- .describe("Set the name of the document model"),
44
- input: documentModelZ.SetModelNameInputSchema(),
45
- }),
46
- z.object({
47
- type: z
48
- .literal("SET_MODEL_ID")
49
- .describe("Set the unique identifier for the document model"),
50
- input: documentModelZ.SetModelIdInputSchema(),
51
- }),
52
- z.object({
53
- type: z
54
- .literal("SET_MODEL_DESCRIPTION")
55
- .describe("Set the description of the document model"),
56
- input: documentModelZ.SetModelDescriptionInputSchema(),
57
- }),
58
- z.object({
59
- type: z
60
- .literal("SET_MODEL_EXTENSION")
61
- .describe("Set the file extension for document model files"),
62
- input: documentModelZ.SetModelExtensionInputSchema(),
63
- }),
64
- z.object({
65
- type: z
66
- .literal("SET_AUTHOR_NAME")
67
- .describe("Set the author name for the document model"),
68
- input: documentModelZ.SetAuthorNameInputSchema(),
69
- }),
70
- z.object({
71
- type: z
72
- .literal("SET_AUTHOR_WEBSITE")
73
- .describe("Set the author website for the document model"),
74
- input: documentModelZ.SetAuthorWebsiteInputSchema(),
75
- }),
76
- // Module Operations
77
- z.object({
78
- type: z
79
- .literal("ADD_MODULE")
80
- .describe("Add a new module to the document model"),
81
- input: documentModelZ.AddModuleInputSchema(),
82
- }),
83
- z.object({
84
- type: z
85
- .literal("DELETE_MODULE")
86
- .describe("Remove a module from the document model"),
87
- input: documentModelZ.DeleteModuleInputSchema(),
88
- }),
89
- z.object({
90
- type: z
91
- .literal("REORDER_MODULES")
92
- .describe("Reorder modules in the document model"),
93
- input: documentModelZ.ReorderModulesInputSchema(),
94
- }),
95
- z.object({
96
- type: z
97
- .literal("SET_MODULE_NAME")
98
- .describe("Set the name of a specific module"),
99
- input: documentModelZ.SetModuleNameInputSchema(),
100
- }),
101
- z.object({
102
- type: z
103
- .literal("SET_MODULE_DESCRIPTION")
104
- .describe("Set the description of a specific module"),
105
- input: documentModelZ.SetModuleDescriptionInputSchema(),
106
- }),
107
- // Operation Operations
108
- z.object({
109
- type: z
110
- .literal("ADD_OPERATION")
111
- .describe("Add a new operation to a module"),
112
- input: documentModelZ.AddOperationInputSchema(),
113
- }),
114
- z.object({
115
- type: z
116
- .literal("DELETE_OPERATION")
117
- .describe("Remove an operation from a module"),
118
- input: documentModelZ.DeleteOperationInputSchema(),
119
- }),
120
- z.object({
121
- type: z
122
- .literal("MOVE_OPERATION")
123
- .describe("Move an operation between modules"),
124
- input: documentModelZ.MoveOperationInputSchema(),
125
- }),
126
- z.object({
127
- type: z
128
- .literal("REORDER_MODULE_OPERATIONS")
129
- .describe("Reorder operations within a module"),
130
- input: documentModelZ.ReorderModuleOperationsInputSchema(),
131
- }),
132
- z.object({
133
- type: z
134
- .literal("SET_OPERATION_NAME")
135
- .describe("Set the name of an operation"),
136
- input: documentModelZ.SetOperationNameInputSchema(),
137
- }),
138
- z.object({
139
- type: z
140
- .literal("SET_OPERATION_DESCRIPTION")
141
- .describe("Set the description of an operation"),
142
- input: documentModelZ.SetOperationDescriptionInputSchema(),
143
- }),
144
- z.object({
145
- type: z
146
- .literal("SET_OPERATION_SCHEMA")
147
- .describe("Set the input schema for an operation"),
148
- input: documentModelZ.SetOperationSchemaInputSchema(),
149
- }),
150
- z.object({
151
- type: z
152
- .literal("SET_OPERATION_SCOPE")
153
- .describe("Set the scope (global/local) of an operation"),
154
- input: documentModelZ.SetOperationScopeInputSchema(),
155
- }),
156
- z.object({
157
- type: z
158
- .literal("SET_OPERATION_TEMPLATE")
159
- .describe("Set the template for an operation"),
160
- input: documentModelZ.SetOperationTemplateInputSchema(),
161
- }),
162
- z.object({
163
- type: z
164
- .literal("SET_OPERATION_REDUCER")
165
- .describe("Set the reducer function for an operation"),
166
- input: documentModelZ.SetOperationReducerInputSchema(),
167
- }),
168
- // Operation Error Operations
169
- z.object({
170
- type: z
171
- .literal("ADD_OPERATION_ERROR")
172
- .describe("Add an error definition to an operation"),
173
- input: documentModelZ.AddOperationErrorInputSchema(),
174
- }),
175
- z.object({
176
- type: z
177
- .literal("DELETE_OPERATION_ERROR")
178
- .describe("Remove an error definition from an operation"),
179
- input: documentModelZ.DeleteOperationErrorInputSchema(),
180
- }),
181
- z.object({
182
- type: z
183
- .literal("REORDER_OPERATION_ERRORS")
184
- .describe("Reorder error definitions for an operation"),
185
- input: documentModelZ.ReorderOperationErrorsInputSchema(),
186
- }),
187
- z.object({
188
- type: z
189
- .literal("SET_OPERATION_ERROR_CODE")
190
- .describe("Set the error code for an operation error"),
191
- input: documentModelZ.SetOperationErrorCodeInputSchema(),
192
- }),
193
- z.object({
194
- type: z
195
- .literal("SET_OPERATION_ERROR_NAME")
196
- .describe("Set the name for an operation error"),
197
- input: documentModelZ.SetOperationErrorNameInputSchema(),
198
- }),
199
- // Operation Example Operations
200
- z.object({
201
- type: z
202
- .literal("ADD_OPERATION_EXAMPLE")
203
- .describe("Add an example to an operation"),
204
- input: documentModelZ.AddOperationExampleInputSchema(),
205
- }),
206
- z.object({
207
- type: z
208
- .literal("DELETE_OPERATION_EXAMPLE")
209
- .describe("Remove an example from an operation"),
210
- input: documentModelZ.DeleteOperationExampleInputSchema(),
211
- }),
212
- z.object({
213
- type: z
214
- .literal("UPDATE_OPERATION_EXAMPLE")
215
- .describe("Update an existing operation example"),
216
- input: documentModelZ.UpdateOperationExampleInputSchema(),
217
- }),
218
- z.object({
219
- type: z
220
- .literal("REORDER_OPERATION_EXAMPLES")
221
- .describe("Reorder examples for an operation"),
222
- input: documentModelZ.ReorderOperationExamplesInputSchema(),
223
- }),
224
- // State Operations
225
- z.object({
226
- type: z
227
- .literal("SET_STATE_SCHEMA")
228
- .describe("Set the state schema for global or local state"),
229
- input: documentModelZ.SetStateSchemaInputSchema(),
230
- }),
231
- z.object({
232
- type: z
233
- .literal("SET_INITIAL_STATE")
234
- .describe("Set the initial state value for global or local state"),
235
- input: documentModelZ.SetInitialStateInputSchema(),
236
- }),
237
- z.object({
238
- type: z
239
- .literal("ADD_STATE_EXAMPLE")
240
- .describe("Add an example to state schema"),
241
- input: documentModelZ.AddStateExampleInputSchema(),
242
- }),
243
- z.object({
244
- type: z
245
- .literal("DELETE_STATE_EXAMPLE")
246
- .describe("Remove an example from state schema"),
247
- input: documentModelZ.DeleteStateExampleInputSchema(),
248
- }),
249
- z.object({
250
- type: z
251
- .literal("UPDATE_STATE_EXAMPLE")
252
- .describe("Update an existing state example"),
253
- input: documentModelZ.UpdateStateExampleInputSchema(),
254
- }),
255
- z.object({
256
- type: z
257
- .literal("REORDER_STATE_EXAMPLES")
258
- .describe("Reorder examples for state schema"),
259
- input: documentModelZ.ReorderStateExamplesInputSchema(),
260
- }),
261
- ]);
262
- export function createServer(reactor) {
1
+ import { createReactorMcpProvider } from "#mcp/reactor.js";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ export const ReactorMcpInstructions = `MUST BE USED when creating, updating or deleting documents or document-models for the Powerhouse/Vetra ecosystem.
4
+ There are 5 main concepts to know of:
5
+ - Document Model: A template for creating documents. It defines the schema and allowed operations for a type of document.
6
+ - Document: An instance of a document model. It contains actual data following the structure defined by the document model and can be changed using operations.
7
+ - Drive: A document of type "powerhouse/document-drive" which represents a collection of documents and folders. To add documents to a drive, use the "addActions" tool with an "ADD_FILE" action.
8
+ - Action: A proposed change to a document. It is a JSON object with the action name and input that defines the action to be taken on the document. Should be dispatched by calling the "addActions" tool.
9
+ - Operation: A change done to a document. It contains the action object plus additional metadata such as the index of the operation in the document history, the timestamp it was added, the hash of the resulting document data, the number of operations skipped, and the error message if the operation failed. Actions dispatched with "addActions" get converted into an operation.
10
+
11
+ When planning to add multiple actions to a document, try to reduce the number of "addActions" calls to a minimum by adding multiple actions at once.
12
+ Unless the user specifies otherwise, and a drive with slug "vetra" is available, add newly created documents to it.
13
+
14
+ Examples:
15
+ <example>Context: User needs to create a new document model for their application. user: 'I need to create a user profile document model with fields for name, email, and preferences' assistant: 'I'll use the reactor-mcp-server to help you create this document model.' <commentary>Since the user is requesting document model creation, use the reactor-mcp-document-expert agent to ensure proper reactor-mcp tool usage.</commentary></example> <example>Context: User is building a content management system and needs create documents for certain types of document models. user: 'Can you help me create example documents for blog posts and categories document models?' assistant: 'Let me use the reactor-mcp-server to create these documents using the appropriate reactor-mcp tool calls.' <commentary>Document model creation requires the reactor-mcp-server tool calls to ensure compliance.</commentary></example>
16
+ <example>Context: User needs to create a new document instance of a given document model. user: 'I need to create a demo user profile document' assistant: 'I'll use the reactor-mcp-server to help you create this document with example values.' <commentary>Since the user is requesting document model creation, use the reactor-mcp-document-expert agent to ensure proper reactor-mcp tool usage.</commentary></example> <example>Context: User is building a content management system and needs create documents for certain types of document models. user: 'Can you help me create example documents for blog posts and categories document models?' assistant: 'Let me use the reactor-mcp-server to create these documents using the appropriate reactor-mcp tool calls.' <commentary>Document creation requires the reactor-mcp-server tool calls to ensure compliance.</commentary></example>
17
+ `;
18
+ export async function createServer(reactor) {
263
19
  // Create an MCP server for document model operations.
264
20
  // For document model creation tasks, consider using the document-model-creator agent
265
21
  // which provides a more guided experience.
266
22
  const server = new McpServer({
267
23
  name: "reactor-mcp-server",
268
24
  version: "1.0.0",
25
+ description: ReactorMcpInstructions,
26
+ instructions: ReactorMcpInstructions,
269
27
  }, {
270
28
  capabilities: {
271
29
  tools: {},
@@ -278,503 +36,24 @@ export function createServer(reactor) {
278
36
  },
279
37
  },
280
38
  });
281
- server.registerTool("createDocumentModel", {
282
- title: "Create Document Model",
283
- description: "Create a new document model. For document model creation tasks, consider using the document-model-creator agent which provides a more guided experience.",
284
- inputSchema: {
285
- name: z.string(),
286
- },
287
- }, async ({ name }) => {
288
- try {
289
- await reactor.createDocumentModel(name);
290
- return {
291
- content: [],
292
- };
293
- }
294
- catch (error) {
295
- const errorString = error instanceof Error ? error.message : String(error);
296
- return {
297
- isError: true,
298
- content: [{ type: "text", text: `Error: ${errorString}` }],
299
- };
300
- }
301
- });
302
- server.registerTool("addDocumentModelAction", {
303
- title: "Add Document Model Action",
304
- description: "Add an action to a document model. For document model design and modification tasks, consider using the document-model-creator agent which provides a more guided experience.",
305
- inputSchema: {
306
- documentModelName: z
307
- .string()
308
- .describe("Name of the document model to modify"),
309
- action: DocumentModelActionSchema.describe("Action with its specific input data to perform on the document model"),
310
- },
311
- }, async ({ documentModelName, action }) => {
312
- try {
313
- const result = await reactor.addDocumentModelAction(documentModelName, {
314
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
315
- type: action.type,
316
- scope: "global",
317
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
318
- input: action.input,
319
- });
320
- const errors = result.operations.reduce((errors, op) => {
321
- if (op.error) {
322
- errors.push(op.error);
323
- }
324
- return errors;
325
- }, []);
326
- const causeString = result.error?.cause instanceof Error
327
- ? ` (${result.error.cause.message})`
328
- : result.error?.cause
329
- ? // eslint-disable-next-line @typescript-eslint/no-base-to-string
330
- String(result.error.cause)
331
- : errors.length > 0
332
- ? errors.join("\n- ")
333
- : undefined;
334
- const errorString = result.error
335
- ? `Error: ${result.error.message}${causeString ? ` (${causeString})` : ""}`
336
- : undefined;
337
- return {
338
- isError: result.status !== "SUCCESS",
339
- content: [
340
- {
341
- type: "text",
342
- text: `Status: ${result.status}${errorString ? "\n" + errorString : ""}`,
343
- },
344
- ],
345
- };
346
- }
347
- catch (error) {
348
- const errorString = error instanceof Error ? error.message : String(error);
349
- return {
350
- isError: true,
351
- content: [{ type: "text", text: `Error: ${errorString}` }],
352
- };
353
- }
354
- });
355
- // server.registerTool(
356
- // "getDocument",
357
- // {
358
- // title: "Get Document",
359
- // description: "Get a document by id",
360
- // inputSchema: { id: z.string() },
361
- // outputSchema: documentModelZ.DocumentModelStateSchema().shape,
362
- // },
363
- // async ({ id }) => {
364
- // try {
365
- // const documentModel = await reactor.getDocumentModel(name);
366
- // return {
367
- // content: [],
368
- // structuredContent: documentModel,
369
- // };
370
- // } catch (error) {
371
- // const errorString =
372
- // error instanceof Error ? error.message : String(error);
373
- // return {
374
- // isError: true,
375
- // content: [{ type: "text", text: `Error: ${errorString}` }],
376
- // };
377
- // }
378
- // },
379
- // );
380
- // server.registerTool(
381
- // "getDocumentModels",
382
- // {
383
- // title: "Get Document Models",
384
- // description: "Get all document models",
385
- // inputSchema: {},
386
- // outputSchema: {
387
- // documentModels: z.record(
388
- // z.string(),
389
- // documentModelZ.DocumentModelStateSchema(),
390
- // ),
391
- // },
392
- // },
393
- // async () => {
394
- // try {
395
- // const documentModels = await reactor.getDocumentModels();
396
- // return {
397
- // content: [],
398
- // structuredContent: {
399
- // documentModels,
400
- // },
401
- // };
402
- // } catch (error) {
403
- // const errorString =
404
- // error instanceof Error ? error.message : String(error);
405
- // return {
406
- // isError: true,
407
- // content: [{ type: "text", text: `Error: ${errorString}` }],
408
- // };
409
- // }
410
- // },
411
- // );
412
- server.registerTool("generateDocumentModel", {
413
- title: "Generate Document Model",
414
- description: "Generate a document model. For document model creation and generation tasks, consider using the document-model-creator agent which provides a more guided experience.",
415
- inputSchema: {
416
- name: z.string(),
417
- },
418
- }, async ({ name }) => {
419
- try {
420
- const config = getConfig();
421
- const documentModel = await reactor.getDocumentModel(name);
422
- const validationResult = validateDocumentModelState(documentModel);
423
- if (!validationResult.isValid) {
424
- return {
425
- isError: true,
426
- content: validationResult.errors.map((error) => ({
427
- type: "text",
428
- text: `Error: ${error}`,
429
- })),
430
- };
431
- }
432
- try {
433
- await generateFromDocument(documentModel, config);
434
- }
435
- catch (error) {
436
- const errorString = error instanceof Error ? error.message : String(error);
437
- return {
438
- isError: true,
439
- content: [{ type: "text", text: `Error: ${errorString}` }],
440
- };
441
- }
442
- return {
443
- content: [],
444
- };
445
- }
446
- catch (error) {
447
- const errorString = error instanceof Error ? error.message : String(error);
448
- return {
449
- isError: true,
450
- content: [{ type: "text", text: `Error: ${errorString}` }],
451
- };
452
- }
453
- });
454
- // Register resources for document model schemas and metadata
455
- server.registerResource("document-model-schema", new ResourceTemplate("document-model://schema/{name}", {
456
- list: async () => {
457
- try {
458
- const documentModels = await reactor.getDocumentModels();
459
- return {
460
- resources: Object.keys(documentModels).map((name) => ({
461
- uri: `document-model://schema/${name}`,
462
- name: `${name} Schema`,
463
- description: documentModels[name].description ||
464
- `Schema for the ${name} document model`,
465
- mimeType: "application/json",
466
- })),
467
- };
468
- }
469
- catch (error) {
470
- // Return empty list on error to avoid breaking the listing
471
- return { resources: [] };
472
- }
473
- },
474
- }), {
475
- title: "Document Model Schema",
476
- description: "Get the schema of a specific document model",
477
- mimeType: "application/json",
478
- }, async (uri, { name }) => {
479
- try {
480
- const modelName = Array.isArray(name) ? name[0] : name;
481
- const documentModel = await reactor.getDocumentModel(modelName);
482
- return {
483
- contents: [
484
- {
485
- uri: uri.href,
486
- text: JSON.stringify(documentModel, null, 2),
487
- mimeType: "application/json",
488
- },
489
- ],
490
- };
491
- }
492
- catch (error) {
493
- const errorString = error instanceof Error ? error.message : String(error);
494
- return {
495
- contents: [
496
- {
497
- uri: uri.href,
498
- text: `Error retrieving document model schema: ${errorString}`,
499
- mimeType: "text/plain",
500
- },
501
- ],
502
- };
503
- }
504
- });
505
- server.registerResource("document-models-list", "document-model://list", {
506
- title: "Document Models List",
507
- description: "Get a list of all available document models",
508
- mimeType: "application/json",
509
- }, async (uri) => {
510
- try {
511
- const documentModels = await reactor.getDocumentModels();
512
- const modelList = Object.keys(documentModels).map((name) => ({
513
- name,
514
- id: documentModels[name].id,
515
- description: documentModels[name].description || "No description",
516
- }));
517
- return {
518
- contents: [
519
- {
520
- uri: uri.href,
521
- text: JSON.stringify(modelList, null, 2),
522
- mimeType: "application/json",
523
- },
524
- ],
525
- };
526
- }
527
- catch (error) {
528
- const errorString = error instanceof Error ? error.message : String(error);
529
- return {
530
- contents: [
531
- {
532
- uri: uri.href,
533
- text: `Error retrieving document models list: ${errorString}`,
534
- mimeType: "text/plain",
535
- },
536
- ],
537
- };
538
- }
539
- });
540
- server.registerTool("createDocument", {
541
- title: "Create Document",
542
- description: "Create a new document of a specific document model type with a given name.",
543
- inputSchema: {
544
- documentType: z.string().describe("The document model type to create"),
545
- name: z.string().describe("The name for the new document"),
546
- },
547
- }, async ({ documentType, name }) => {
548
- try {
549
- const result = await reactor.createDocument(documentType, name);
550
- return {
551
- content: [
552
- {
553
- type: "text",
554
- text: `Document created successfully with ID: ${result.id}`,
555
- },
556
- ],
557
- structuredContent: {
558
- id: result.id,
559
- name: result.document.header.name,
560
- documentType: result.document.header.documentType,
561
- },
562
- };
563
- }
564
- catch (error) {
565
- const errorString = error instanceof Error ? error.message : String(error);
566
- return {
567
- isError: true,
568
- content: [{ type: "text", text: `Error: ${errorString}` }],
569
- };
570
- }
571
- });
572
- server.registerTool("addAction", {
573
- title: "Add Action",
574
- description: "Add an action to any document by ID. Actions are operations that modify document state.",
575
- inputSchema: {
576
- documentId: z.string().describe("ID of the document to modify"),
577
- action: z
578
- .object({
579
- type: z.string().describe("The action type"),
580
- input: z
581
- .unknown()
582
- .transform((input) => input || {})
583
- .describe("The action input"),
584
- scope: z
585
- .enum(["global", "local"])
586
- .describe("The scope of the action"),
587
- })
588
- .describe("The action to perform on the document"),
589
- },
590
- }, async ({ documentId, action }) => {
591
- try {
592
- const result = await reactor.addAction(documentId, action);
593
- const errors = result.operations.reduce((errors, op) => {
594
- if (op.error) {
595
- errors.push(op.error);
596
- }
597
- return errors;
598
- }, []);
599
- const causeString = result.error?.cause instanceof Error
600
- ? ` (${result.error.cause.message})`
601
- : result.error?.cause
602
- ? // eslint-disable-next-line @typescript-eslint/no-base-to-string
603
- String(result.error.cause)
604
- : errors.length > 0
605
- ? errors.join("\n- ")
606
- : undefined;
607
- const errorString = result.error
608
- ? `Error: ${result.error.message}${causeString ? ` (${causeString})` : ""}`
609
- : undefined;
610
- return {
611
- isError: result.status !== "SUCCESS",
612
- content: [
613
- {
614
- type: "text",
615
- text: `Status: ${result.status}${errorString ? "\n" + errorString : ""}`,
616
- },
617
- ],
618
- };
619
- }
620
- catch (error) {
621
- const errorString = error instanceof Error ? error.message : String(error);
622
- return {
623
- isError: true,
624
- content: [{ type: "text", text: `Error: ${errorString}` }],
625
- };
626
- }
627
- });
628
- // Register resource for individual documents
629
- server.registerResource("document", new ResourceTemplate("document://{id}", {
630
- list: async () => {
631
- try {
632
- const documentIds = await reactor.getDocuments();
633
- return {
634
- resources: documentIds.map((id) => ({
635
- uri: `document://${id}`,
636
- name: `Document ${id}`,
637
- description: `Document with ID ${id}`,
638
- mimeType: "application/json",
639
- })),
640
- };
641
- }
642
- catch (error) {
643
- // Return empty list on error to avoid breaking the listing
644
- return { resources: [] };
645
- }
646
- },
647
- }), {
648
- title: "Document",
649
- description: "Get a specific document by ID",
650
- mimeType: "application/json",
651
- }, async (uri, { id }) => {
652
- try {
653
- const documentId = Array.isArray(id) ? id[0] : id;
654
- const document = await reactor.getDocument(documentId);
655
- return {
656
- contents: [
657
- {
658
- uri: uri.href,
659
- text: JSON.stringify(document, null, 2),
660
- mimeType: "application/json",
661
- },
662
- ],
663
- };
664
- }
665
- catch (error) {
666
- const errorString = error instanceof Error ? error.message : String(error);
667
- return {
668
- contents: [
669
- {
670
- uri: uri.href,
671
- text: `Error retrieving document: ${errorString}`,
672
- mimeType: "text/plain",
673
- },
674
- ],
675
- };
676
- }
677
- });
678
- server.registerResource("documents-list", "documents://list", {
679
- title: "Documents List",
680
- description: "Get a list of all available document IDs",
681
- mimeType: "application/json",
682
- }, async (uri) => {
683
- try {
684
- const documentIds = await reactor.getDocuments();
685
- return {
686
- contents: [
687
- {
688
- uri: uri.href,
689
- text: JSON.stringify(documentIds, null, 2),
690
- mimeType: "application/json",
691
- },
692
- ],
693
- };
694
- }
695
- catch (error) {
696
- const errorString = error instanceof Error ? error.message : String(error);
697
- return {
698
- contents: [
699
- {
700
- uri: uri.href,
701
- text: `Error retrieving documents list: ${errorString}`,
702
- mimeType: "text/plain",
703
- },
704
- ],
705
- };
706
- }
707
- });
708
- // Register prompts for document model operations
709
- server.registerPrompt("analyze-document-model", {
710
- title: "Analyze Document Model",
711
- description: "Analyze a document model structure and suggest improvements",
712
- argsSchema: {
713
- modelName: z.string().describe("Name of the document model to analyze"),
714
- },
715
- }, async ({ modelName }) => {
716
- try {
717
- const documentModel = await reactor.getDocumentModel(modelName);
718
- return {
719
- messages: [
720
- {
721
- role: "user",
722
- content: {
723
- type: "text",
724
- text: `Please analyze this document model structure and suggest improvements for maintainability, performance, and best practices:\n\nModel Name: ${modelName}\n\nStructure:\n${JSON.stringify(documentModel, null, 2)}`,
725
- },
726
- },
727
- ],
728
- };
729
- }
730
- catch (error) {
731
- const errorString = error instanceof Error ? error.message : String(error);
732
- return {
733
- messages: [
734
- {
735
- role: "user",
736
- content: {
737
- type: "text",
738
- text: `Error analyzing document model "${modelName}": ${errorString}`,
739
- },
740
- },
741
- ],
742
- };
743
- }
744
- });
745
- server.registerPrompt("create-document-model-template", {
746
- title: "Create Document Model Template",
747
- description: "Generate a template for creating a new document model",
748
- argsSchema: {
749
- purpose: z
750
- .string()
751
- .describe("The purpose or use case for the document model"),
752
- domain: z
753
- .string()
754
- .optional()
755
- .describe("The business domain (e.g., finance, content, project management)"),
756
- },
757
- }, async ({ purpose, domain }) => {
758
- const domainContext = domain ? ` in the ${domain} domain` : "";
759
- return {
760
- messages: [
761
- {
762
- role: "user",
763
- content: {
764
- type: "text",
765
- text: `Please help me create a document model template for: ${purpose}${domainContext}
766
-
767
- Please provide:
768
- 1. A suggested document model structure with state schema
769
- 2. Key operations that should be supported
770
- 3. Business logic considerations
771
- 4. Best practices for this type of document model
772
-
773
- Focus on creating a well-structured, maintainable design that follows Powerhouse document model conventions.`,
774
- },
775
- },
776
- ],
777
- };
39
+ server.registerResource("instructions", "reactor://instructions", {
40
+ title: "Instructions",
41
+ description: "General instructions on how to use the tools of this MCP",
42
+ mimeType: "text/plain",
43
+ }, (uri) => ({
44
+ contents: [
45
+ {
46
+ uri: uri.href,
47
+ text: ReactorMcpInstructions,
48
+ },
49
+ ],
50
+ }));
51
+ const reactorProvider = await createReactorMcpProvider(reactor);
52
+ const { callback, ...toolSchema } = reactorProvider.tools.getDocumentModels;
53
+ // server.registerTool("getDocumentModels", toolSchema, callback);
54
+ Object.entries(reactorProvider.tools).forEach(([toolName, { callback, ...schema }]) => {
55
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
56
+ server.registerTool(toolName, schema, callback);
778
57
  });
779
58
  return server;
780
59
  }