@burdenoff/mcp-libs 2026.627.2 → 2026.627.4

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 (61) hide show
  1. package/dist/modules/artistrybase/index.cjs +2112 -0
  2. package/dist/modules/artistrybase/index.cjs.map +1 -0
  3. package/dist/modules/artistrybase/index.d.cts +8 -0
  4. package/dist/modules/artistrybase/index.d.ts +8 -0
  5. package/dist/modules/artistrybase/index.js +2051 -0
  6. package/dist/modules/artistrybase/index.js.map +1 -0
  7. package/dist/modules/brainyrich/index.cjs +2148 -0
  8. package/dist/modules/brainyrich/index.cjs.map +1 -0
  9. package/dist/modules/brainyrich/index.d.cts +8 -0
  10. package/dist/modules/brainyrich/index.d.ts +8 -0
  11. package/dist/modules/brainyrich/index.js +2087 -0
  12. package/dist/modules/brainyrich/index.js.map +1 -0
  13. package/dist/modules/buildmyiq/index.cjs +1562 -0
  14. package/dist/modules/buildmyiq/index.cjs.map +1 -0
  15. package/dist/modules/buildmyiq/index.d.cts +8 -0
  16. package/dist/modules/buildmyiq/index.d.ts +8 -0
  17. package/dist/modules/buildmyiq/index.js +1501 -0
  18. package/dist/modules/buildmyiq/index.js.map +1 -0
  19. package/dist/modules/collabkin/index.cjs +1577 -0
  20. package/dist/modules/collabkin/index.cjs.map +1 -0
  21. package/dist/modules/collabkin/index.d.cts +8 -0
  22. package/dist/modules/collabkin/index.d.ts +8 -0
  23. package/dist/modules/collabkin/index.js +1516 -0
  24. package/dist/modules/collabkin/index.js.map +1 -0
  25. package/dist/modules/comradecircle/index.cjs +1817 -0
  26. package/dist/modules/comradecircle/index.cjs.map +1 -0
  27. package/dist/modules/comradecircle/index.d.cts +8 -0
  28. package/dist/modules/comradecircle/index.d.ts +8 -0
  29. package/dist/modules/comradecircle/index.js +1756 -0
  30. package/dist/modules/comradecircle/index.js.map +1 -0
  31. package/dist/modules/cosmicintersection/index.cjs +1984 -0
  32. package/dist/modules/cosmicintersection/index.cjs.map +1 -0
  33. package/dist/modules/cosmicintersection/index.d.cts +8 -0
  34. package/dist/modules/cosmicintersection/index.d.ts +8 -0
  35. package/dist/modules/cosmicintersection/index.js +1923 -0
  36. package/dist/modules/cosmicintersection/index.js.map +1 -0
  37. package/dist/modules/ecoimpacthub/index.cjs +2042 -0
  38. package/dist/modules/ecoimpacthub/index.cjs.map +1 -0
  39. package/dist/modules/ecoimpacthub/index.d.cts +8 -0
  40. package/dist/modules/ecoimpacthub/index.d.ts +8 -0
  41. package/dist/modules/ecoimpacthub/index.js +1981 -0
  42. package/dist/modules/ecoimpacthub/index.js.map +1 -0
  43. package/dist/modules/govcitizenhub/index.cjs +1686 -0
  44. package/dist/modules/govcitizenhub/index.cjs.map +1 -0
  45. package/dist/modules/govcitizenhub/index.d.cts +8 -0
  46. package/dist/modules/govcitizenhub/index.d.ts +8 -0
  47. package/dist/modules/govcitizenhub/index.js +1625 -0
  48. package/dist/modules/govcitizenhub/index.js.map +1 -0
  49. package/dist/modules/intelwatchtower/index.cjs +1919 -0
  50. package/dist/modules/intelwatchtower/index.cjs.map +1 -0
  51. package/dist/modules/intelwatchtower/index.d.cts +8 -0
  52. package/dist/modules/intelwatchtower/index.d.ts +8 -0
  53. package/dist/modules/intelwatchtower/index.js +1858 -0
  54. package/dist/modules/intelwatchtower/index.js.map +1 -0
  55. package/dist/modules/manufacturedops/index.cjs +1884 -0
  56. package/dist/modules/manufacturedops/index.cjs.map +1 -0
  57. package/dist/modules/manufacturedops/index.d.cts +8 -0
  58. package/dist/modules/manufacturedops/index.d.ts +8 -0
  59. package/dist/modules/manufacturedops/index.js +1823 -0
  60. package/dist/modules/manufacturedops/index.js.map +1 -0
  61. package/package.json +1 -1
@@ -0,0 +1,2112 @@
1
+ 'use strict';
2
+
3
+ var zod = require('zod');
4
+ require('graphql-request');
5
+ require('cross-fetch');
6
+ require('@modelcontextprotocol/sdk/server/mcp.js');
7
+ require('@modelcontextprotocol/sdk/types.js');
8
+
9
+ // src/modules/artistrybase/tools/library.ts
10
+
11
+ // src/core/errors.ts
12
+ var McpInternalError = class extends Error {
13
+ cause;
14
+ constructor(message, cause) {
15
+ super(message);
16
+ this.name = "McpInternalError";
17
+ this.cause = cause;
18
+ }
19
+ };
20
+
21
+ // src/core/result.ts
22
+ function jsonResult(data, structured) {
23
+ const result = {
24
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
25
+ };
26
+ return result;
27
+ }
28
+ function errorResult(message, hint) {
29
+ const text = hint ? `${message}
30
+
31
+ Hint: ${hint}` : message;
32
+ return { content: [{ type: "text", text }], isError: true };
33
+ }
34
+
35
+ // src/core/tool-name.ts
36
+ var MAX_TOOL_NAME_LENGTH = 63;
37
+ function assertSafeName(name, kind) {
38
+ if (name.length > MAX_TOOL_NAME_LENGTH) {
39
+ throw new McpInternalError(
40
+ `Tool name '${name}' exceeds ${MAX_TOOL_NAME_LENGTH} characters (some MCP clients truncate at 64).`
41
+ );
42
+ }
43
+ return name;
44
+ }
45
+ function mcpToolName(productName, ...parts) {
46
+ if (!productName) {
47
+ throw new McpInternalError("mcpToolName: productName is required");
48
+ }
49
+ const name = [productName, ...parts].filter(Boolean).join("_");
50
+ return assertSafeName(name);
51
+ }
52
+ function mcpResourceUri(productName, ...parts) {
53
+ if (!productName) {
54
+ throw new McpInternalError("mcpResourceUri: productName is required");
55
+ }
56
+ return `${productName}://${parts.filter(Boolean).join("/")}`;
57
+ }
58
+ function mcpPromptName(productName, ...parts) {
59
+ if (!productName) {
60
+ throw new McpInternalError("mcpPromptName: productName is required");
61
+ }
62
+ return [productName, ...parts].filter(Boolean).join("-");
63
+ }
64
+
65
+ // src/modules/artistrybase/operations.ts
66
+ var WORK_FIELDS = `
67
+ id title summary medium status visibility productionId creatorId
68
+ coverFileId currentVersionId durationMs tags publishedAt
69
+ workspaceId createdAt updatedAt
70
+ `;
71
+ var WORK_VERSION_FIELDS = `
72
+ id workId versionNo label notes fileId checksum sizeBytes isPublished
73
+ workspaceId createdAt updatedAt
74
+ `;
75
+ var ASSET_FIELDS = `
76
+ id workId versionId kind fileId mimeType sizeBytes width height durationMs
77
+ workspaceId createdAt updatedAt
78
+ `;
79
+ var COLLECTION_FIELDS = `
80
+ id title slug description medium visibility tags coverFileId
81
+ workspaceId createdAt updatedAt
82
+ `;
83
+ var PRODUCTION_FIELDS = `
84
+ id title slug synopsis medium status ownerId tags startDate targetDate
85
+ releasedAt workspaceId createdAt updatedAt
86
+ `;
87
+ var PRODUCTION_MEMBER_FIELDS = `
88
+ id productionId memberId role title isLead workspaceId createdAt updatedAt
89
+ `;
90
+ var REFERENCE_FIELDS = `
91
+ id productionId title note url fileId tags workspaceId createdAt updatedAt
92
+ `;
93
+ var REVIEW_ROUND_FIELDS = `
94
+ id workId versionId round status title dueDate openedById closedAt
95
+ workspaceId createdAt updatedAt
96
+ `;
97
+ var FEEDBACK_FIELDS = `
98
+ id reviewRoundId authorId body anchorType anchorValue status
99
+ resolvedAt resolvedById workspaceId createdAt updatedAt
100
+ `;
101
+ var APPROVAL_FIELDS = `
102
+ id reviewRoundId approverId decision comment decidedAt
103
+ workspaceId createdAt updatedAt
104
+ `;
105
+ var RELEASE_FIELDS = `
106
+ id workId versionId channel status visibility notes scheduledFor
107
+ publishedAt workspaceId createdAt updatedAt
108
+ `;
109
+ var PORTFOLIO_FIELDS = `
110
+ id handle displayName bio avatarFileId bannerFileId links featuredWorkIds
111
+ followerCount ownerId visibility workspaceId createdAt updatedAt
112
+ `;
113
+ var FOLLOW_FIELDS = `
114
+ id portfolioId followerId notify workspaceId createdAt
115
+ `;
116
+ var LICENSE_FIELDS = `
117
+ id workId name model status priceAmount currency spdx terms attribution
118
+ workspaceId createdAt updatedAt
119
+ `;
120
+ var GET_WORK = `
121
+ query ArtistrybaseGetWork($id: ID!) {
122
+ artWork(id: $id) {
123
+ ${WORK_FIELDS}
124
+ assets { ${ASSET_FIELDS} }
125
+ versions { ${WORK_VERSION_FIELDS} }
126
+ }
127
+ }
128
+ `;
129
+ var LIST_WORKS = `
130
+ query ArtistrybaseListWorks(
131
+ $medium: ArtMedium
132
+ $status: ArtWorkStatus
133
+ $productionId: ID
134
+ $pagination: PaginationInput
135
+ ) {
136
+ artListWorks(
137
+ medium: $medium
138
+ status: $status
139
+ productionId: $productionId
140
+ pagination: $pagination
141
+ ) {
142
+ items { ${WORK_FIELDS} }
143
+ pageInfo { cursor hasMore }
144
+ }
145
+ }
146
+ `;
147
+ var CREATE_WORK = `
148
+ mutation ArtistrybaseCreateWork($input: ArtCreateWorkInput!) {
149
+ artCreateWork(input: $input) {
150
+ ${WORK_FIELDS}
151
+ }
152
+ }
153
+ `;
154
+ var UPDATE_WORK = `
155
+ mutation ArtistrybaseUpdateWork($id: ID!, $input: ArtUpdateWorkInput!) {
156
+ artUpdateWork(id: $id, input: $input) {
157
+ ${WORK_FIELDS}
158
+ }
159
+ }
160
+ `;
161
+ var ARCHIVE_WORK = `
162
+ mutation ArtistrybaseArchiveWork($id: ID!) {
163
+ artArchiveWork(id: $id)
164
+ }
165
+ `;
166
+ var PUBLISH_WORK_VERSION = `
167
+ mutation ArtistrybasePublishWorkVersion($workId: ID!, $versionId: ID!) {
168
+ artPublishWorkVersion(workId: $workId, versionId: $versionId) {
169
+ ${WORK_FIELDS}
170
+ }
171
+ }
172
+ `;
173
+ var LIST_WORK_VERSIONS = `
174
+ query ArtistrybaseListWorkVersions($workId: ID!) {
175
+ artListWorkVersions(workId: $workId) {
176
+ ${WORK_VERSION_FIELDS}
177
+ }
178
+ }
179
+ `;
180
+ var ADD_WORK_VERSION = `
181
+ mutation ArtistrybaseAddWorkVersion($input: ArtCreateWorkVersionInput!) {
182
+ artAddWorkVersion(input: $input) {
183
+ ${WORK_VERSION_FIELDS}
184
+ }
185
+ }
186
+ `;
187
+ var LIST_ASSETS = `
188
+ query ArtistrybaseListAssets($workId: ID!) {
189
+ artListAssets(workId: $workId) {
190
+ ${ASSET_FIELDS}
191
+ }
192
+ }
193
+ `;
194
+ var ADD_ASSET = `
195
+ mutation ArtistrybaseAddAsset($input: ArtCreateAssetInput!) {
196
+ artAddAsset(input: $input) {
197
+ ${ASSET_FIELDS}
198
+ }
199
+ }
200
+ `;
201
+ var GET_COLLECTION = `
202
+ query ArtistrybaseGetCollection($id: ID!) {
203
+ artCollection(id: $id) {
204
+ ${COLLECTION_FIELDS}
205
+ works { ${WORK_FIELDS} }
206
+ }
207
+ }
208
+ `;
209
+ var LIST_COLLECTIONS = `
210
+ query ArtistrybaseListCollections(
211
+ $visibility: ArtVisibility
212
+ $pagination: PaginationInput
213
+ ) {
214
+ artListCollections(visibility: $visibility, pagination: $pagination) {
215
+ items { ${COLLECTION_FIELDS} }
216
+ pageInfo { cursor hasMore }
217
+ }
218
+ }
219
+ `;
220
+ var CREATE_COLLECTION = `
221
+ mutation ArtistrybaseCreateCollection($input: ArtCreateCollectionInput!) {
222
+ artCreateCollection(input: $input) {
223
+ ${COLLECTION_FIELDS}
224
+ }
225
+ }
226
+ `;
227
+ var UPDATE_COLLECTION = `
228
+ mutation ArtistrybaseUpdateCollection($id: ID!, $input: ArtUpdateCollectionInput!) {
229
+ artUpdateCollection(id: $id, input: $input) {
230
+ ${COLLECTION_FIELDS}
231
+ }
232
+ }
233
+ `;
234
+ var ADD_WORK_TO_COLLECTION = `
235
+ mutation ArtistrybaseAddWorkToCollection($collectionId: ID!, $workId: ID!) {
236
+ artAddWorkToCollection(collectionId: $collectionId, workId: $workId) {
237
+ ${COLLECTION_FIELDS}
238
+ works { id title medium status }
239
+ }
240
+ }
241
+ `;
242
+ var REMOVE_WORK_FROM_COLLECTION = `
243
+ mutation ArtistrybaseRemoveWorkFromCollection($collectionId: ID!, $workId: ID!) {
244
+ artRemoveWorkFromCollection(collectionId: $collectionId, workId: $workId) {
245
+ ${COLLECTION_FIELDS}
246
+ works { id title medium status }
247
+ }
248
+ }
249
+ `;
250
+ var GET_PRODUCTION = `
251
+ query ArtistrybaseGetProduction($id: ID!) {
252
+ artProduction(id: $id) {
253
+ ${PRODUCTION_FIELDS}
254
+ members { ${PRODUCTION_MEMBER_FIELDS} }
255
+ references { ${REFERENCE_FIELDS} }
256
+ }
257
+ }
258
+ `;
259
+ var LIST_PRODUCTIONS = `
260
+ query ArtistrybaseListProductions(
261
+ $status: ArtProductionStatus
262
+ $pagination: PaginationInput
263
+ ) {
264
+ artListProductions(status: $status, pagination: $pagination) {
265
+ items { ${PRODUCTION_FIELDS} }
266
+ pageInfo { cursor hasMore }
267
+ }
268
+ }
269
+ `;
270
+ var CREATE_PRODUCTION = `
271
+ mutation ArtistrybaseCreateProduction($input: ArtCreateProductionInput!) {
272
+ artCreateProduction(input: $input) {
273
+ ${PRODUCTION_FIELDS}
274
+ }
275
+ }
276
+ `;
277
+ var UPDATE_PRODUCTION = `
278
+ mutation ArtistrybaseUpdateProduction($id: ID!, $input: ArtUpdateProductionInput!) {
279
+ artUpdateProduction(id: $id, input: $input) {
280
+ ${PRODUCTION_FIELDS}
281
+ }
282
+ }
283
+ `;
284
+ var TRANSITION_PRODUCTION = `
285
+ mutation ArtistrybaseTransitionProduction($id: ID!, $status: ArtProductionStatus!) {
286
+ artTransitionProduction(id: $id, status: $status) {
287
+ ${PRODUCTION_FIELDS}
288
+ }
289
+ }
290
+ `;
291
+ var LIST_PRODUCTION_MEMBERS = `
292
+ query ArtistrybaseListProductionMembers($productionId: ID!) {
293
+ artListProductionMembers(productionId: $productionId) {
294
+ ${PRODUCTION_MEMBER_FIELDS}
295
+ }
296
+ }
297
+ `;
298
+ var ADD_PRODUCTION_MEMBER = `
299
+ mutation ArtistrybaseAddProductionMember($input: ArtAddProductionMemberInput!) {
300
+ artAddProductionMember(input: $input) {
301
+ ${PRODUCTION_MEMBER_FIELDS}
302
+ }
303
+ }
304
+ `;
305
+ var REMOVE_PRODUCTION_MEMBER = `
306
+ mutation ArtistrybaseRemoveProductionMember($id: ID!) {
307
+ artRemoveProductionMember(id: $id)
308
+ }
309
+ `;
310
+ var LIST_REFERENCES = `
311
+ query ArtistrybaseListReferences($productionId: ID!) {
312
+ artListReferences(productionId: $productionId) {
313
+ ${REFERENCE_FIELDS}
314
+ }
315
+ }
316
+ `;
317
+ var ADD_REFERENCE = `
318
+ mutation ArtistrybaseAddReference($input: ArtCreateReferenceInput!) {
319
+ artAddReference(input: $input) {
320
+ ${REFERENCE_FIELDS}
321
+ }
322
+ }
323
+ `;
324
+ var REMOVE_REFERENCE = `
325
+ mutation ArtistrybaseRemoveReference($id: ID!) {
326
+ artRemoveReference(id: $id)
327
+ }
328
+ `;
329
+ var GET_REVIEW_ROUND = `
330
+ query ArtistrybaseGetReviewRound($id: ID!) {
331
+ artReviewRound(id: $id) {
332
+ ${REVIEW_ROUND_FIELDS}
333
+ feedback { ${FEEDBACK_FIELDS} }
334
+ approvals { ${APPROVAL_FIELDS} }
335
+ }
336
+ }
337
+ `;
338
+ var LIST_REVIEW_ROUNDS = `
339
+ query ArtistrybaseListReviewRounds($workId: ID!, $status: ArtReviewStatus) {
340
+ artListReviewRounds(workId: $workId, status: $status) {
341
+ ${REVIEW_ROUND_FIELDS}
342
+ }
343
+ }
344
+ `;
345
+ var OPEN_REVIEW_ROUND = `
346
+ mutation ArtistrybaseOpenReviewRound($input: ArtOpenReviewRoundInput!) {
347
+ artOpenReviewRound(input: $input) {
348
+ ${REVIEW_ROUND_FIELDS}
349
+ }
350
+ }
351
+ `;
352
+ var TRANSITION_REVIEW_ROUND = `
353
+ mutation ArtistrybaseTransitionReviewRound($id: ID!, $status: ArtReviewStatus!) {
354
+ artTransitionReviewRound(id: $id, status: $status) {
355
+ ${REVIEW_ROUND_FIELDS}
356
+ }
357
+ }
358
+ `;
359
+ var ADD_FEEDBACK = `
360
+ mutation ArtistrybaseAddFeedback($input: ArtAddFeedbackInput!) {
361
+ artAddFeedback(input: $input) {
362
+ ${FEEDBACK_FIELDS}
363
+ }
364
+ }
365
+ `;
366
+ var RESOLVE_FEEDBACK = `
367
+ mutation ArtistrybaseResolveFeedback($id: ID!, $status: ArtFeedbackStatus!) {
368
+ artResolveFeedback(id: $id, status: $status) {
369
+ ${FEEDBACK_FIELDS}
370
+ }
371
+ }
372
+ `;
373
+ var RECORD_APPROVAL = `
374
+ mutation ArtistrybaseRecordApproval($input: ArtRecordApprovalInput!) {
375
+ artRecordApproval(input: $input) {
376
+ ${APPROVAL_FIELDS}
377
+ }
378
+ }
379
+ `;
380
+ var LIST_RELEASES = `
381
+ query ArtistrybaseListReleases($workId: ID!, $status: ArtReleaseStatus) {
382
+ artListReleases(workId: $workId, status: $status) {
383
+ ${RELEASE_FIELDS}
384
+ }
385
+ }
386
+ `;
387
+ var CREATE_RELEASE = `
388
+ mutation ArtistrybaseCreateRelease($input: ArtCreateReleaseInput!) {
389
+ artCreateRelease(input: $input) {
390
+ ${RELEASE_FIELDS}
391
+ }
392
+ }
393
+ `;
394
+ var PUBLISH_RELEASE = `
395
+ mutation ArtistrybasePublishRelease($id: ID!) {
396
+ artPublishRelease(id: $id) {
397
+ ${RELEASE_FIELDS}
398
+ }
399
+ }
400
+ `;
401
+ var GET_PORTFOLIO = `
402
+ query ArtistrybaseGetPortfolio($id: ID!) {
403
+ artPortfolio(id: $id) {
404
+ ${PORTFOLIO_FIELDS}
405
+ }
406
+ }
407
+ `;
408
+ var LIST_PORTFOLIOS = `
409
+ query ArtistrybaseListPortfolios(
410
+ $visibility: ArtVisibility
411
+ $pagination: PaginationInput
412
+ ) {
413
+ artListPortfolios(visibility: $visibility, pagination: $pagination) {
414
+ items { ${PORTFOLIO_FIELDS} }
415
+ pageInfo { cursor hasMore }
416
+ }
417
+ }
418
+ `;
419
+ var CREATE_PORTFOLIO = `
420
+ mutation ArtistrybaseCreatePortfolio($input: ArtCreatePortfolioInput!) {
421
+ artCreatePortfolio(input: $input) {
422
+ ${PORTFOLIO_FIELDS}
423
+ }
424
+ }
425
+ `;
426
+ var UPDATE_PORTFOLIO = `
427
+ mutation ArtistrybaseUpdatePortfolio($id: ID!, $input: ArtUpdatePortfolioInput!) {
428
+ artUpdatePortfolio(id: $id, input: $input) {
429
+ ${PORTFOLIO_FIELDS}
430
+ }
431
+ }
432
+ `;
433
+ var ARCHIVE_PORTFOLIO = `
434
+ mutation ArtistrybaseArchivePortfolio($id: ID!) {
435
+ artArchivePortfolio(id: $id)
436
+ }
437
+ `;
438
+ var FOLLOW_PORTFOLIO = `
439
+ mutation ArtistrybaseFollowPortfolio($portfolioId: ID!, $notify: Boolean) {
440
+ artFollowPortfolio(portfolioId: $portfolioId, notify: $notify) {
441
+ ${FOLLOW_FIELDS}
442
+ }
443
+ }
444
+ `;
445
+ var UNFOLLOW_PORTFOLIO = `
446
+ mutation ArtistrybaseUnfollowPortfolio($portfolioId: ID!) {
447
+ artUnfollowPortfolio(portfolioId: $portfolioId)
448
+ }
449
+ `;
450
+ var LIST_LICENSES = `
451
+ query ArtistrybaseListLicenses($workId: ID!) {
452
+ artListLicenses(workId: $workId) {
453
+ ${LICENSE_FIELDS}
454
+ }
455
+ }
456
+ `;
457
+ var CREATE_LICENSE = `
458
+ mutation ArtistrybaseCreateLicense($input: ArtCreateLicenseInput!) {
459
+ artCreateLicense(input: $input) {
460
+ ${LICENSE_FIELDS}
461
+ }
462
+ }
463
+ `;
464
+ var UPDATE_LICENSE = `
465
+ mutation ArtistrybaseUpdateLicense($id: ID!, $input: ArtUpdateLicenseInput!) {
466
+ artUpdateLicense(id: $id, input: $input) {
467
+ ${LICENSE_FIELDS}
468
+ }
469
+ }
470
+ `;
471
+ var ACTIVATE_LICENSE = `
472
+ mutation ArtistrybaseActivateLicense($id: ID!) {
473
+ artActivateLicense(id: $id) {
474
+ ${LICENSE_FIELDS}
475
+ }
476
+ }
477
+ `;
478
+ var HEALTH = `
479
+ query ArtistrybaseHealth {
480
+ artHealth
481
+ }
482
+ `;
483
+ var MediumEnum = zod.z.enum(["ART", "AUDIO", "MIXED", "STORY", "VIDEO"]).describe("Creative medium of a work, collection, or production");
484
+ var VisibilityEnum = zod.z.enum(["PRIVATE", "PUBLIC", "UNLISTED"]).describe("Visibility of a work, collection, portfolio, or release");
485
+ var WorkStatusEnum = zod.z.enum(["APPROVED", "ARCHIVED", "DRAFT", "IN_REVIEW", "RELEASED"]).describe("Lifecycle status of a work");
486
+ var AssetKindEnum = zod.z.enum(["ATTACHMENT", "CAPTION", "COVER", "MASTER", "PREVIEW", "SOURCE"]).describe("Kind of file asset attached to a work");
487
+ var ProductionStatusEnum = zod.z.enum(["CANCELLED", "IN_PRODUCTION", "ON_HOLD", "PLANNING", "POST", "RELEASED", "REVIEW"]).describe("Lifecycle status of a production");
488
+ var ProductionRoleEnum = zod.z.enum(["COLLABORATOR", "CREATOR", "EDITOR", "OWNER", "PRODUCER", "REVIEWER", "VIEWER"]).describe("Role of a member on a production team");
489
+ var ReviewStatusEnum = zod.z.enum(["APPROVED", "CHANGES_REQUESTED", "CLOSED", "OPEN"]).describe("Lifecycle status of a review round");
490
+ var FeedbackStatusEnum = zod.z.enum(["OPEN", "RESOLVED", "WONT_FIX"]).describe("Resolution status of a piece of feedback");
491
+ var AnchorTypeEnum = zod.z.enum(["CHAPTER", "GENERAL", "PAGE", "PIN", "TIMECODE"]).describe("Where in-context feedback is anchored");
492
+ var ApprovalDecisionEnum = zod.z.enum(["APPROVED", "PENDING", "REJECTED"]).describe("Decision recorded on a review round by an approver");
493
+ var ReleaseStatusEnum = zod.z.enum(["FAILED", "PUBLISHED", "SCHEDULED", "UNPUBLISHED"]).describe("Lifecycle status of a release");
494
+ var LicenseModelEnum = zod.z.enum(["FREE", "LICENSE", "MEMBERSHIP", "PURCHASE"]).describe("Commercial model of a license");
495
+ var JsonObject = zod.z.record(zod.z.string(), zod.z.unknown());
496
+
497
+ // src/modules/artistrybase/tools/library.ts
498
+ function registerLibraryTools(server, ctx, track) {
499
+ server.registerTool(
500
+ track(mcpToolName(ctx.productName, "works_get")),
501
+ {
502
+ title: "Get Work",
503
+ description: "Fetch a single creative work by ID, including its file assets and immutable version history.",
504
+ inputSchema: { id: zod.z.string().describe("Work ID") }
505
+ },
506
+ async ({ id }) => {
507
+ try {
508
+ const data = await ctx.gql.workspace.request(GET_WORK, { id });
509
+ if (!data.artWork) return errorResult(`Work ${id} not found`);
510
+ return jsonResult(data.artWork);
511
+ } catch (error) {
512
+ ctx.logger.error("artistrybase works_get failed", { error: String(error) });
513
+ return errorResult(
514
+ `Failed to get work: ${error instanceof Error ? error.message : String(error)}`
515
+ );
516
+ }
517
+ }
518
+ );
519
+ server.registerTool(
520
+ track(mcpToolName(ctx.productName, "works_list")),
521
+ {
522
+ title: "List Works",
523
+ description: "List creative works in the bound workspace with optional medium/status/production filters and cursor/offset pagination. Returns a connection ({ items, pageInfo }).",
524
+ inputSchema: {
525
+ medium: MediumEnum.optional().describe("Filter by medium"),
526
+ status: WorkStatusEnum.optional().describe("Filter by lifecycle status"),
527
+ productionId: zod.z.string().optional().describe("Filter to works of a production"),
528
+ limit: zod.z.number().int().optional().describe("Page size (default 50)"),
529
+ offset: zod.z.number().int().optional().describe("Pagination offset (default 0)"),
530
+ cursor: zod.z.string().optional().describe("Opaque pagination cursor")
531
+ }
532
+ },
533
+ async ({ medium, status, productionId, limit, offset, cursor }) => {
534
+ try {
535
+ const pagination = {
536
+ limit: limit ?? 50,
537
+ offset: offset ?? 0
538
+ };
539
+ if (cursor !== void 0) pagination.cursor = cursor;
540
+ const data = await ctx.gql.workspace.request(LIST_WORKS, { medium, status, productionId, pagination });
541
+ return jsonResult(data.artListWorks);
542
+ } catch (error) {
543
+ ctx.logger.error("artistrybase works_list failed", { error: String(error) });
544
+ return errorResult(
545
+ `Failed to list works: ${error instanceof Error ? error.message : String(error)}`
546
+ );
547
+ }
548
+ }
549
+ );
550
+ server.registerTool(
551
+ track(mcpToolName(ctx.productName, "works_create")),
552
+ {
553
+ title: "Create Work",
554
+ description: "Create a new creative work (any medium). Title is required; the work starts in DRAFT/PRIVATE unless overridden.",
555
+ inputSchema: {
556
+ title: zod.z.string().min(1).describe("Work title"),
557
+ medium: MediumEnum.optional().describe("Creative medium (default MIXED)"),
558
+ summary: zod.z.string().optional().describe("Short summary/description"),
559
+ productionId: zod.z.string().optional().describe("Owning production ID (optional)"),
560
+ coverFileId: zod.z.string().optional().describe("Cover image File ID (wspace-files-svc)"),
561
+ durationMs: zod.z.number().int().optional().describe("Duration in milliseconds (audio/video)"),
562
+ tags: zod.z.array(zod.z.string()).optional().describe("Free-form tags"),
563
+ visibility: VisibilityEnum.optional().describe("Visibility (default PRIVATE)")
564
+ }
565
+ },
566
+ async ({ title, medium, summary, productionId, coverFileId, durationMs, tags, visibility }) => {
567
+ try {
568
+ const input = { title };
569
+ if (medium !== void 0) input.medium = medium;
570
+ if (summary !== void 0) input.summary = summary;
571
+ if (productionId !== void 0) input.productionId = productionId;
572
+ if (coverFileId !== void 0) input.coverFileId = coverFileId;
573
+ if (durationMs !== void 0) input.durationMs = durationMs;
574
+ if (tags !== void 0) input.tags = tags;
575
+ if (visibility !== void 0) input.visibility = visibility;
576
+ const data = await ctx.gql.workspace.request(CREATE_WORK, { input });
577
+ return jsonResult(data.artCreateWork);
578
+ } catch (error) {
579
+ ctx.logger.error("artistrybase works_create failed", { error: String(error) });
580
+ return errorResult(
581
+ `Failed to create work: ${error instanceof Error ? error.message : String(error)}`
582
+ );
583
+ }
584
+ }
585
+ );
586
+ server.registerTool(
587
+ track(mcpToolName(ctx.productName, "works_update")),
588
+ {
589
+ title: "Update Work",
590
+ description: "Update a work. At least one mutable field must be provided. Use `visibility` to publish/unlist a work.",
591
+ inputSchema: {
592
+ id: zod.z.string().describe("Work ID"),
593
+ title: zod.z.string().optional().describe("Updated title"),
594
+ summary: zod.z.string().optional().describe("Updated summary"),
595
+ medium: MediumEnum.optional().describe("Updated medium"),
596
+ productionId: zod.z.string().optional().describe("Updated owning production ID"),
597
+ coverFileId: zod.z.string().optional().describe("Updated cover File ID"),
598
+ durationMs: zod.z.number().int().optional().describe("Updated duration in milliseconds"),
599
+ tags: zod.z.array(zod.z.string()).optional().describe("Updated tags"),
600
+ visibility: VisibilityEnum.optional().describe("Updated visibility")
601
+ }
602
+ },
603
+ async ({
604
+ id,
605
+ title,
606
+ summary,
607
+ medium,
608
+ productionId,
609
+ coverFileId,
610
+ durationMs,
611
+ tags,
612
+ visibility
613
+ }) => {
614
+ try {
615
+ const input = {};
616
+ if (title !== void 0) input.title = title;
617
+ if (summary !== void 0) input.summary = summary;
618
+ if (medium !== void 0) input.medium = medium;
619
+ if (productionId !== void 0) input.productionId = productionId;
620
+ if (coverFileId !== void 0) input.coverFileId = coverFileId;
621
+ if (durationMs !== void 0) input.durationMs = durationMs;
622
+ if (tags !== void 0) input.tags = tags;
623
+ if (visibility !== void 0) input.visibility = visibility;
624
+ if (Object.keys(input).length === 0) {
625
+ return errorResult(
626
+ "No updates specified \u2014 provide at least one of title/summary/medium/productionId/coverFileId/durationMs/tags/visibility"
627
+ );
628
+ }
629
+ const data = await ctx.gql.workspace.request(UPDATE_WORK, { id, input });
630
+ return jsonResult(data.artUpdateWork);
631
+ } catch (error) {
632
+ ctx.logger.error("artistrybase works_update failed", { error: String(error) });
633
+ return errorResult(
634
+ `Failed to update work: ${error instanceof Error ? error.message : String(error)}`
635
+ );
636
+ }
637
+ }
638
+ );
639
+ server.registerTool(
640
+ track(mcpToolName(ctx.productName, "works_archive")),
641
+ {
642
+ title: "Archive Work",
643
+ description: "Archive a work (soft delete). Returns whether the archive succeeded.",
644
+ inputSchema: { id: zod.z.string().describe("Work ID") }
645
+ },
646
+ async ({ id }) => {
647
+ try {
648
+ const data = await ctx.gql.workspace.request(
649
+ ARCHIVE_WORK,
650
+ { id }
651
+ );
652
+ return jsonResult({ ok: data.artArchiveWork });
653
+ } catch (error) {
654
+ ctx.logger.error("artistrybase works_archive failed", { error: String(error) });
655
+ return errorResult(
656
+ `Failed to archive work: ${error instanceof Error ? error.message : String(error)}`
657
+ );
658
+ }
659
+ }
660
+ );
661
+ server.registerTool(
662
+ track(mcpToolName(ctx.productName, "works_publish_version")),
663
+ {
664
+ title: "Publish Work Version",
665
+ description: "Promote a version to be the work's published current version.",
666
+ inputSchema: {
667
+ workId: zod.z.string().describe("Work ID"),
668
+ versionId: zod.z.string().describe("Version ID to promote as current")
669
+ }
670
+ },
671
+ async ({ workId, versionId }) => {
672
+ try {
673
+ const data = await ctx.gql.workspace.request(PUBLISH_WORK_VERSION, { workId, versionId });
674
+ return jsonResult(data.artPublishWorkVersion);
675
+ } catch (error) {
676
+ ctx.logger.error("artistrybase works_publish_version failed", { error: String(error) });
677
+ return errorResult(
678
+ `Failed to publish work version: ${error instanceof Error ? error.message : String(error)}`
679
+ );
680
+ }
681
+ }
682
+ );
683
+ server.registerTool(
684
+ track(mcpToolName(ctx.productName, "works_list_versions")),
685
+ {
686
+ title: "List Work Versions",
687
+ description: "List a work's immutable revision history (ordered version snapshots).",
688
+ inputSchema: { workId: zod.z.string().describe("Work ID") }
689
+ },
690
+ async ({ workId }) => {
691
+ try {
692
+ const data = await ctx.gql.workspace.request(LIST_WORK_VERSIONS, { workId });
693
+ return jsonResult(data.artListWorkVersions);
694
+ } catch (error) {
695
+ ctx.logger.error("artistrybase works_list_versions failed", { error: String(error) });
696
+ return errorResult(
697
+ `Failed to list work versions: ${error instanceof Error ? error.message : String(error)}`
698
+ );
699
+ }
700
+ }
701
+ );
702
+ server.registerTool(
703
+ track(mcpToolName(ctx.productName, "works_add_version")),
704
+ {
705
+ title: "Add Work Version",
706
+ description: "Upload a new immutable revision of a work (auto-increments the version number).",
707
+ inputSchema: {
708
+ workId: zod.z.string().min(1).describe("Work ID"),
709
+ fileId: zod.z.string().optional().describe("Source File ID for this revision (wspace-files-svc)"),
710
+ label: zod.z.string().optional().describe("Human label for the version"),
711
+ notes: zod.z.string().optional().describe("Revision notes / changelog"),
712
+ checksum: zod.z.string().optional().describe("Content checksum")
713
+ }
714
+ },
715
+ async ({ workId, fileId, label, notes, checksum }) => {
716
+ try {
717
+ const input = { workId };
718
+ if (fileId !== void 0) input.fileId = fileId;
719
+ if (label !== void 0) input.label = label;
720
+ if (notes !== void 0) input.notes = notes;
721
+ if (checksum !== void 0) input.checksum = checksum;
722
+ const data = await ctx.gql.workspace.request(ADD_WORK_VERSION, { input });
723
+ return jsonResult(data.artAddWorkVersion);
724
+ } catch (error) {
725
+ ctx.logger.error("artistrybase works_add_version failed", { error: String(error) });
726
+ return errorResult(
727
+ `Failed to add work version: ${error instanceof Error ? error.message : String(error)}`
728
+ );
729
+ }
730
+ }
731
+ );
732
+ server.registerTool(
733
+ track(mcpToolName(ctx.productName, "works_list_assets")),
734
+ {
735
+ title: "List Work Assets",
736
+ description: "List the file assets attached to a work (masters, previews, captions, etc.).",
737
+ inputSchema: { workId: zod.z.string().describe("Work ID") }
738
+ },
739
+ async ({ workId }) => {
740
+ try {
741
+ const data = await ctx.gql.workspace.request(LIST_ASSETS, { workId });
742
+ return jsonResult(data.artListAssets);
743
+ } catch (error) {
744
+ ctx.logger.error("artistrybase works_list_assets failed", { error: String(error) });
745
+ return errorResult(
746
+ `Failed to list assets: ${error instanceof Error ? error.message : String(error)}`
747
+ );
748
+ }
749
+ }
750
+ );
751
+ server.registerTool(
752
+ track(mcpToolName(ctx.productName, "works_add_asset")),
753
+ {
754
+ title: "Add Work Asset",
755
+ description: "Attach a file asset to a work. `fileId` references a wspace-files-svc File; `kind` defaults to SOURCE.",
756
+ inputSchema: {
757
+ workId: zod.z.string().min(1).describe("Work ID"),
758
+ fileId: zod.z.string().min(1).describe("Backing File ID (wspace-files-svc)"),
759
+ kind: AssetKindEnum.optional().describe("Asset kind (default SOURCE)"),
760
+ versionId: zod.z.string().optional().describe("Version this asset belongs to"),
761
+ mimeType: zod.z.string().optional().describe("MIME type"),
762
+ width: zod.z.number().int().optional().describe("Pixel width (image/video)"),
763
+ height: zod.z.number().int().optional().describe("Pixel height (image/video)"),
764
+ durationMs: zod.z.number().int().optional().describe("Duration in milliseconds (audio/video)")
765
+ }
766
+ },
767
+ async ({ workId, fileId, kind, versionId, mimeType, width, height, durationMs }) => {
768
+ try {
769
+ const input = { workId, fileId };
770
+ if (kind !== void 0) input.kind = kind;
771
+ if (versionId !== void 0) input.versionId = versionId;
772
+ if (mimeType !== void 0) input.mimeType = mimeType;
773
+ if (width !== void 0) input.width = width;
774
+ if (height !== void 0) input.height = height;
775
+ if (durationMs !== void 0) input.durationMs = durationMs;
776
+ const data = await ctx.gql.workspace.request(ADD_ASSET, { input });
777
+ return jsonResult(data.artAddAsset);
778
+ } catch (error) {
779
+ ctx.logger.error("artistrybase works_add_asset failed", { error: String(error) });
780
+ return errorResult(
781
+ `Failed to add asset: ${error instanceof Error ? error.message : String(error)}`
782
+ );
783
+ }
784
+ }
785
+ );
786
+ server.registerTool(
787
+ track(mcpToolName(ctx.productName, "collections_get")),
788
+ {
789
+ title: "Get Collection",
790
+ description: "Fetch a single collection by ID, including its member works.",
791
+ inputSchema: { id: zod.z.string().describe("Collection ID") }
792
+ },
793
+ async ({ id }) => {
794
+ try {
795
+ const data = await ctx.gql.workspace.request(GET_COLLECTION, { id });
796
+ if (!data.artCollection) return errorResult(`Collection ${id} not found`);
797
+ return jsonResult(data.artCollection);
798
+ } catch (error) {
799
+ ctx.logger.error("artistrybase collections_get failed", { error: String(error) });
800
+ return errorResult(
801
+ `Failed to get collection: ${error instanceof Error ? error.message : String(error)}`
802
+ );
803
+ }
804
+ }
805
+ );
806
+ server.registerTool(
807
+ track(mcpToolName(ctx.productName, "collections_list")),
808
+ {
809
+ title: "List Collections",
810
+ description: "List curated collections with optional visibility filter and cursor/offset pagination. Returns a connection ({ items, pageInfo }).",
811
+ inputSchema: {
812
+ visibility: VisibilityEnum.optional().describe("Filter by visibility"),
813
+ limit: zod.z.number().int().optional().describe("Page size (default 50)"),
814
+ offset: zod.z.number().int().optional().describe("Pagination offset (default 0)"),
815
+ cursor: zod.z.string().optional().describe("Opaque pagination cursor")
816
+ }
817
+ },
818
+ async ({ visibility, limit, offset, cursor }) => {
819
+ try {
820
+ const pagination = { limit: limit ?? 50, offset: offset ?? 0 };
821
+ if (cursor !== void 0) pagination.cursor = cursor;
822
+ const data = await ctx.gql.workspace.request(LIST_COLLECTIONS, { visibility, pagination });
823
+ return jsonResult(data.artListCollections);
824
+ } catch (error) {
825
+ ctx.logger.error("artistrybase collections_list failed", { error: String(error) });
826
+ return errorResult(
827
+ `Failed to list collections: ${error instanceof Error ? error.message : String(error)}`
828
+ );
829
+ }
830
+ }
831
+ );
832
+ server.registerTool(
833
+ track(mcpToolName(ctx.productName, "collections_create")),
834
+ {
835
+ title: "Create Collection",
836
+ description: "Create a curated collection. `slug` must be unique within the workspace.",
837
+ inputSchema: {
838
+ title: zod.z.string().min(1).describe("Collection title"),
839
+ slug: zod.z.string().min(1).describe("URL slug, unique within the workspace"),
840
+ description: zod.z.string().optional().describe("Collection description"),
841
+ medium: MediumEnum.optional().describe("Primary medium of the collection"),
842
+ tags: zod.z.array(zod.z.string()).optional().describe("Free-form tags"),
843
+ coverFileId: zod.z.string().optional().describe("Cover image File ID"),
844
+ visibility: VisibilityEnum.optional().describe("Visibility (default PRIVATE)")
845
+ }
846
+ },
847
+ async ({ title, slug, description, medium, tags, coverFileId, visibility }) => {
848
+ try {
849
+ const input = { title, slug };
850
+ if (description !== void 0) input.description = description;
851
+ if (medium !== void 0) input.medium = medium;
852
+ if (tags !== void 0) input.tags = tags;
853
+ if (coverFileId !== void 0) input.coverFileId = coverFileId;
854
+ if (visibility !== void 0) input.visibility = visibility;
855
+ const data = await ctx.gql.workspace.request(CREATE_COLLECTION, { input });
856
+ return jsonResult(data.artCreateCollection);
857
+ } catch (error) {
858
+ ctx.logger.error("artistrybase collections_create failed", { error: String(error) });
859
+ return errorResult(
860
+ `Failed to create collection: ${error instanceof Error ? error.message : String(error)}`
861
+ );
862
+ }
863
+ }
864
+ );
865
+ server.registerTool(
866
+ track(mcpToolName(ctx.productName, "collections_update")),
867
+ {
868
+ title: "Update Collection",
869
+ description: "Update a collection. At least one mutable field must be provided.",
870
+ inputSchema: {
871
+ id: zod.z.string().describe("Collection ID"),
872
+ title: zod.z.string().optional().describe("Updated title"),
873
+ description: zod.z.string().optional().describe("Updated description"),
874
+ medium: MediumEnum.optional().describe("Updated medium"),
875
+ tags: zod.z.array(zod.z.string()).optional().describe("Updated tags"),
876
+ coverFileId: zod.z.string().optional().describe("Updated cover File ID"),
877
+ visibility: VisibilityEnum.optional().describe("Updated visibility")
878
+ }
879
+ },
880
+ async ({ id, title, description, medium, tags, coverFileId, visibility }) => {
881
+ try {
882
+ const input = {};
883
+ if (title !== void 0) input.title = title;
884
+ if (description !== void 0) input.description = description;
885
+ if (medium !== void 0) input.medium = medium;
886
+ if (tags !== void 0) input.tags = tags;
887
+ if (coverFileId !== void 0) input.coverFileId = coverFileId;
888
+ if (visibility !== void 0) input.visibility = visibility;
889
+ if (Object.keys(input).length === 0) {
890
+ return errorResult(
891
+ "No updates specified \u2014 provide at least one of title/description/medium/tags/coverFileId/visibility"
892
+ );
893
+ }
894
+ const data = await ctx.gql.workspace.request(UPDATE_COLLECTION, { id, input });
895
+ return jsonResult(data.artUpdateCollection);
896
+ } catch (error) {
897
+ ctx.logger.error("artistrybase collections_update failed", { error: String(error) });
898
+ return errorResult(
899
+ `Failed to update collection: ${error instanceof Error ? error.message : String(error)}`
900
+ );
901
+ }
902
+ }
903
+ );
904
+ server.registerTool(
905
+ track(mcpToolName(ctx.productName, "collections_add_work")),
906
+ {
907
+ title: "Add Work to Collection",
908
+ description: "Add a work to a collection. Returns the updated collection.",
909
+ inputSchema: {
910
+ collectionId: zod.z.string().describe("Collection ID"),
911
+ workId: zod.z.string().describe("Work ID to add")
912
+ }
913
+ },
914
+ async ({ collectionId, workId }) => {
915
+ try {
916
+ const data = await ctx.gql.workspace.request(ADD_WORK_TO_COLLECTION, { collectionId, workId });
917
+ return jsonResult(data.artAddWorkToCollection);
918
+ } catch (error) {
919
+ ctx.logger.error("artistrybase collections_add_work failed", { error: String(error) });
920
+ return errorResult(
921
+ `Failed to add work to collection: ${error instanceof Error ? error.message : String(error)}`
922
+ );
923
+ }
924
+ }
925
+ );
926
+ server.registerTool(
927
+ track(mcpToolName(ctx.productName, "collections_remove_work")),
928
+ {
929
+ title: "Remove Work from Collection",
930
+ description: "Remove a work from a collection. Returns the updated collection.",
931
+ inputSchema: {
932
+ collectionId: zod.z.string().describe("Collection ID"),
933
+ workId: zod.z.string().describe("Work ID to remove")
934
+ }
935
+ },
936
+ async ({ collectionId, workId }) => {
937
+ try {
938
+ const data = await ctx.gql.workspace.request(REMOVE_WORK_FROM_COLLECTION, { collectionId, workId });
939
+ return jsonResult(data.artRemoveWorkFromCollection);
940
+ } catch (error) {
941
+ ctx.logger.error("artistrybase collections_remove_work failed", { error: String(error) });
942
+ return errorResult(
943
+ `Failed to remove work from collection: ${error instanceof Error ? error.message : String(error)}`
944
+ );
945
+ }
946
+ }
947
+ );
948
+ }
949
+ function registerProductionTools(server, ctx, track) {
950
+ server.registerTool(
951
+ track(mcpToolName(ctx.productName, "productions_get")),
952
+ {
953
+ title: "Get Production",
954
+ description: "Fetch a single production by ID, including its team members and reference material.",
955
+ inputSchema: { id: zod.z.string().describe("Production ID") }
956
+ },
957
+ async ({ id }) => {
958
+ try {
959
+ const data = await ctx.gql.workspace.request(GET_PRODUCTION, { id });
960
+ if (!data.artProduction) return errorResult(`Production ${id} not found`);
961
+ return jsonResult(data.artProduction);
962
+ } catch (error) {
963
+ ctx.logger.error("artistrybase productions_get failed", { error: String(error) });
964
+ return errorResult(
965
+ `Failed to get production: ${error instanceof Error ? error.message : String(error)}`
966
+ );
967
+ }
968
+ }
969
+ );
970
+ server.registerTool(
971
+ track(mcpToolName(ctx.productName, "productions_list")),
972
+ {
973
+ title: "List Productions",
974
+ description: "List productions with optional status filter and cursor/offset pagination. Returns a connection ({ items, pageInfo }).",
975
+ inputSchema: {
976
+ status: ProductionStatusEnum.optional().describe("Filter by lifecycle status"),
977
+ limit: zod.z.number().int().optional().describe("Page size (default 50)"),
978
+ offset: zod.z.number().int().optional().describe("Pagination offset (default 0)"),
979
+ cursor: zod.z.string().optional().describe("Opaque pagination cursor")
980
+ }
981
+ },
982
+ async ({ status, limit, offset, cursor }) => {
983
+ try {
984
+ const pagination = { limit: limit ?? 50, offset: offset ?? 0 };
985
+ if (cursor !== void 0) pagination.cursor = cursor;
986
+ const data = await ctx.gql.workspace.request(LIST_PRODUCTIONS, { status, pagination });
987
+ return jsonResult(data.artListProductions);
988
+ } catch (error) {
989
+ ctx.logger.error("artistrybase productions_list failed", { error: String(error) });
990
+ return errorResult(
991
+ `Failed to list productions: ${error instanceof Error ? error.message : String(error)}`
992
+ );
993
+ }
994
+ }
995
+ );
996
+ server.registerTool(
997
+ track(mcpToolName(ctx.productName, "productions_create")),
998
+ {
999
+ title: "Create Production",
1000
+ description: "Create a new production. `slug` must be unique within the workspace.",
1001
+ inputSchema: {
1002
+ title: zod.z.string().min(1).describe("Production title"),
1003
+ slug: zod.z.string().min(1).describe("URL slug, unique within the workspace"),
1004
+ synopsis: zod.z.string().optional().describe("Synopsis / description"),
1005
+ medium: MediumEnum.optional().describe("Primary medium (default MIXED)"),
1006
+ tags: zod.z.array(zod.z.string()).optional().describe("Free-form tags"),
1007
+ startDate: zod.z.string().optional().describe("Start date (ISO 8601)"),
1008
+ targetDate: zod.z.string().optional().describe("Target completion date (ISO 8601)")
1009
+ }
1010
+ },
1011
+ async ({ title, slug, synopsis, medium, tags, startDate, targetDate }) => {
1012
+ try {
1013
+ const input = { title, slug };
1014
+ if (synopsis !== void 0) input.synopsis = synopsis;
1015
+ if (medium !== void 0) input.medium = medium;
1016
+ if (tags !== void 0) input.tags = tags;
1017
+ if (startDate !== void 0) input.startDate = startDate;
1018
+ if (targetDate !== void 0) input.targetDate = targetDate;
1019
+ const data = await ctx.gql.workspace.request(CREATE_PRODUCTION, { input });
1020
+ return jsonResult(data.artCreateProduction);
1021
+ } catch (error) {
1022
+ ctx.logger.error("artistrybase productions_create failed", { error: String(error) });
1023
+ return errorResult(
1024
+ `Failed to create production: ${error instanceof Error ? error.message : String(error)}`
1025
+ );
1026
+ }
1027
+ }
1028
+ );
1029
+ server.registerTool(
1030
+ track(mcpToolName(ctx.productName, "productions_update")),
1031
+ {
1032
+ title: "Update Production",
1033
+ description: "Update a production. At least one mutable field must be provided.",
1034
+ inputSchema: {
1035
+ id: zod.z.string().describe("Production ID"),
1036
+ title: zod.z.string().optional().describe("Updated title"),
1037
+ synopsis: zod.z.string().optional().describe("Updated synopsis"),
1038
+ medium: MediumEnum.optional().describe("Updated medium"),
1039
+ tags: zod.z.array(zod.z.string()).optional().describe("Updated tags"),
1040
+ startDate: zod.z.string().optional().describe("Updated start date (ISO 8601)"),
1041
+ targetDate: zod.z.string().optional().describe("Updated target date (ISO 8601)")
1042
+ }
1043
+ },
1044
+ async ({ id, title, synopsis, medium, tags, startDate, targetDate }) => {
1045
+ try {
1046
+ const input = {};
1047
+ if (title !== void 0) input.title = title;
1048
+ if (synopsis !== void 0) input.synopsis = synopsis;
1049
+ if (medium !== void 0) input.medium = medium;
1050
+ if (tags !== void 0) input.tags = tags;
1051
+ if (startDate !== void 0) input.startDate = startDate;
1052
+ if (targetDate !== void 0) input.targetDate = targetDate;
1053
+ if (Object.keys(input).length === 0) {
1054
+ return errorResult(
1055
+ "No updates specified \u2014 provide at least one of title/synopsis/medium/tags/startDate/targetDate"
1056
+ );
1057
+ }
1058
+ const data = await ctx.gql.workspace.request(UPDATE_PRODUCTION, { id, input });
1059
+ return jsonResult(data.artUpdateProduction);
1060
+ } catch (error) {
1061
+ ctx.logger.error("artistrybase productions_update failed", { error: String(error) });
1062
+ return errorResult(
1063
+ `Failed to update production: ${error instanceof Error ? error.message : String(error)}`
1064
+ );
1065
+ }
1066
+ }
1067
+ );
1068
+ server.registerTool(
1069
+ track(mcpToolName(ctx.productName, "productions_transition")),
1070
+ {
1071
+ title: "Transition Production",
1072
+ description: "Advance a production through its lifecycle (validated transitions: PLANNING \u2192 IN_PRODUCTION \u2192 REVIEW \u2192 POST \u2192 RELEASED, or ON_HOLD/CANCELLED).",
1073
+ inputSchema: {
1074
+ id: zod.z.string().describe("Production ID"),
1075
+ status: ProductionStatusEnum.describe("Target lifecycle status")
1076
+ }
1077
+ },
1078
+ async ({ id, status }) => {
1079
+ try {
1080
+ const data = await ctx.gql.workspace.request(TRANSITION_PRODUCTION, { id, status });
1081
+ return jsonResult(data.artTransitionProduction);
1082
+ } catch (error) {
1083
+ ctx.logger.error("artistrybase productions_transition failed", { error: String(error) });
1084
+ return errorResult(
1085
+ `Failed to transition production: ${error instanceof Error ? error.message : String(error)}`
1086
+ );
1087
+ }
1088
+ }
1089
+ );
1090
+ server.registerTool(
1091
+ track(mcpToolName(ctx.productName, "productions_list_members")),
1092
+ {
1093
+ title: "List Production Members",
1094
+ description: "List the team members attached to a production.",
1095
+ inputSchema: { productionId: zod.z.string().describe("Production ID") }
1096
+ },
1097
+ async ({ productionId }) => {
1098
+ try {
1099
+ const data = await ctx.gql.workspace.request(LIST_PRODUCTION_MEMBERS, { productionId });
1100
+ return jsonResult(data.artListProductionMembers);
1101
+ } catch (error) {
1102
+ ctx.logger.error("artistrybase productions_list_members failed", { error: String(error) });
1103
+ return errorResult(
1104
+ `Failed to list production members: ${error instanceof Error ? error.message : String(error)}`
1105
+ );
1106
+ }
1107
+ }
1108
+ );
1109
+ server.registerTool(
1110
+ track(mcpToolName(ctx.productName, "productions_add_member")),
1111
+ {
1112
+ title: "Add Production Member",
1113
+ description: "Add a team member to a production with a role and optional title.",
1114
+ inputSchema: {
1115
+ productionId: zod.z.string().min(1).describe("Production ID"),
1116
+ memberId: zod.z.string().min(1).describe("User ID of the team member (wspace-auth-svc)"),
1117
+ role: ProductionRoleEnum.optional().describe("Member role (default COLLABORATOR)"),
1118
+ title: zod.z.string().optional().describe("Credit/title on the production"),
1119
+ isLead: zod.z.boolean().optional().describe("Whether the member is a lead (default false)")
1120
+ }
1121
+ },
1122
+ async ({ productionId, memberId, role, title, isLead }) => {
1123
+ try {
1124
+ const input = { productionId, memberId };
1125
+ if (role !== void 0) input.role = role;
1126
+ if (title !== void 0) input.title = title;
1127
+ if (isLead !== void 0) input.isLead = isLead;
1128
+ const data = await ctx.gql.workspace.request(ADD_PRODUCTION_MEMBER, { input });
1129
+ return jsonResult(data.artAddProductionMember);
1130
+ } catch (error) {
1131
+ ctx.logger.error("artistrybase productions_add_member failed", { error: String(error) });
1132
+ return errorResult(
1133
+ `Failed to add production member: ${error instanceof Error ? error.message : String(error)}`
1134
+ );
1135
+ }
1136
+ }
1137
+ );
1138
+ server.registerTool(
1139
+ track(mcpToolName(ctx.productName, "productions_remove_member")),
1140
+ {
1141
+ title: "Remove Production Member",
1142
+ description: "Remove a team member from a production. Returns whether removal succeeded.",
1143
+ inputSchema: { id: zod.z.string().describe("Production member ID") }
1144
+ },
1145
+ async ({ id }) => {
1146
+ try {
1147
+ const data = await ctx.gql.workspace.request(
1148
+ REMOVE_PRODUCTION_MEMBER,
1149
+ { id }
1150
+ );
1151
+ return jsonResult({ ok: data.artRemoveProductionMember });
1152
+ } catch (error) {
1153
+ ctx.logger.error("artistrybase productions_remove_member failed", { error: String(error) });
1154
+ return errorResult(
1155
+ `Failed to remove production member: ${error instanceof Error ? error.message : String(error)}`
1156
+ );
1157
+ }
1158
+ }
1159
+ );
1160
+ server.registerTool(
1161
+ track(mcpToolName(ctx.productName, "productions_list_references")),
1162
+ {
1163
+ title: "List References",
1164
+ description: "List reference material attached to a production (mood boards, links, files).",
1165
+ inputSchema: { productionId: zod.z.string().describe("Production ID") }
1166
+ },
1167
+ async ({ productionId }) => {
1168
+ try {
1169
+ const data = await ctx.gql.workspace.request(LIST_REFERENCES, { productionId });
1170
+ return jsonResult(data.artListReferences);
1171
+ } catch (error) {
1172
+ ctx.logger.error("artistrybase productions_list_references failed", {
1173
+ error: String(error)
1174
+ });
1175
+ return errorResult(
1176
+ `Failed to list references: ${error instanceof Error ? error.message : String(error)}`
1177
+ );
1178
+ }
1179
+ }
1180
+ );
1181
+ server.registerTool(
1182
+ track(mcpToolName(ctx.productName, "productions_add_reference")),
1183
+ {
1184
+ title: "Add Reference",
1185
+ description: "Attach reference material to a production. Provide a title and optionally a URL and/or a File ID.",
1186
+ inputSchema: {
1187
+ productionId: zod.z.string().min(1).describe("Production ID"),
1188
+ title: zod.z.string().min(1).describe("Reference title"),
1189
+ note: zod.z.string().optional().describe("Note about the reference"),
1190
+ url: zod.z.string().optional().describe("External URL"),
1191
+ fileId: zod.z.string().optional().describe("Attached File ID (wspace-files-svc)"),
1192
+ tags: zod.z.array(zod.z.string()).optional().describe("Free-form tags")
1193
+ }
1194
+ },
1195
+ async ({ productionId, title, note, url, fileId, tags }) => {
1196
+ try {
1197
+ const input = { productionId, title };
1198
+ if (note !== void 0) input.note = note;
1199
+ if (url !== void 0) input.url = url;
1200
+ if (fileId !== void 0) input.fileId = fileId;
1201
+ if (tags !== void 0) input.tags = tags;
1202
+ const data = await ctx.gql.workspace.request(ADD_REFERENCE, { input });
1203
+ return jsonResult(data.artAddReference);
1204
+ } catch (error) {
1205
+ ctx.logger.error("artistrybase productions_add_reference failed", { error: String(error) });
1206
+ return errorResult(
1207
+ `Failed to add reference: ${error instanceof Error ? error.message : String(error)}`
1208
+ );
1209
+ }
1210
+ }
1211
+ );
1212
+ server.registerTool(
1213
+ track(mcpToolName(ctx.productName, "productions_remove_reference")),
1214
+ {
1215
+ title: "Remove Reference",
1216
+ description: "Remove reference material from a production. Returns whether removal succeeded.",
1217
+ inputSchema: { id: zod.z.string().describe("Reference ID") }
1218
+ },
1219
+ async ({ id }) => {
1220
+ try {
1221
+ const data = await ctx.gql.workspace.request(
1222
+ REMOVE_REFERENCE,
1223
+ { id }
1224
+ );
1225
+ return jsonResult({ ok: data.artRemoveReference });
1226
+ } catch (error) {
1227
+ ctx.logger.error("artistrybase productions_remove_reference failed", {
1228
+ error: String(error)
1229
+ });
1230
+ return errorResult(
1231
+ `Failed to remove reference: ${error instanceof Error ? error.message : String(error)}`
1232
+ );
1233
+ }
1234
+ }
1235
+ );
1236
+ }
1237
+ function registerReviewTools(server, ctx, track) {
1238
+ server.registerTool(
1239
+ track(mcpToolName(ctx.productName, "reviews_get_round")),
1240
+ {
1241
+ title: "Get Review Round",
1242
+ description: "Fetch a single review round by ID, including its in-context feedback and approvals.",
1243
+ inputSchema: { id: zod.z.string().describe("Review round ID") }
1244
+ },
1245
+ async ({ id }) => {
1246
+ try {
1247
+ const data = await ctx.gql.workspace.request(GET_REVIEW_ROUND, { id });
1248
+ if (!data.artReviewRound) return errorResult(`Review round ${id} not found`);
1249
+ return jsonResult(data.artReviewRound);
1250
+ } catch (error) {
1251
+ ctx.logger.error("artistrybase reviews_get_round failed", { error: String(error) });
1252
+ return errorResult(
1253
+ `Failed to get review round: ${error instanceof Error ? error.message : String(error)}`
1254
+ );
1255
+ }
1256
+ }
1257
+ );
1258
+ server.registerTool(
1259
+ track(mcpToolName(ctx.productName, "reviews_list_rounds")),
1260
+ {
1261
+ title: "List Review Rounds",
1262
+ description: "List the review rounds for a work, optionally filtered by status.",
1263
+ inputSchema: {
1264
+ workId: zod.z.string().describe("Work ID"),
1265
+ status: ReviewStatusEnum.optional().describe("Filter by review status")
1266
+ }
1267
+ },
1268
+ async ({ workId, status }) => {
1269
+ try {
1270
+ const data = await ctx.gql.workspace.request(LIST_REVIEW_ROUNDS, { workId, status });
1271
+ return jsonResult(data.artListReviewRounds);
1272
+ } catch (error) {
1273
+ ctx.logger.error("artistrybase reviews_list_rounds failed", { error: String(error) });
1274
+ return errorResult(
1275
+ `Failed to list review rounds: ${error instanceof Error ? error.message : String(error)}`
1276
+ );
1277
+ }
1278
+ }
1279
+ );
1280
+ server.registerTool(
1281
+ track(mcpToolName(ctx.productName, "reviews_open_round")),
1282
+ {
1283
+ title: "Open Review Round",
1284
+ description: "Open a new review round on a work (optionally pinned to a specific version), with an optional title and due date.",
1285
+ inputSchema: {
1286
+ workId: zod.z.string().min(1).describe("Work ID"),
1287
+ versionId: zod.z.string().optional().describe("Version to review (defaults to current)"),
1288
+ title: zod.z.string().optional().describe("Round title"),
1289
+ dueDate: zod.z.string().optional().describe("Due date (ISO 8601)")
1290
+ }
1291
+ },
1292
+ async ({ workId, versionId, title, dueDate }) => {
1293
+ try {
1294
+ const input = { workId };
1295
+ if (versionId !== void 0) input.versionId = versionId;
1296
+ if (title !== void 0) input.title = title;
1297
+ if (dueDate !== void 0) input.dueDate = dueDate;
1298
+ const data = await ctx.gql.workspace.request(OPEN_REVIEW_ROUND, { input });
1299
+ return jsonResult(data.artOpenReviewRound);
1300
+ } catch (error) {
1301
+ ctx.logger.error("artistrybase reviews_open_round failed", { error: String(error) });
1302
+ return errorResult(
1303
+ `Failed to open review round: ${error instanceof Error ? error.message : String(error)}`
1304
+ );
1305
+ }
1306
+ }
1307
+ );
1308
+ server.registerTool(
1309
+ track(mcpToolName(ctx.productName, "reviews_transition_round")),
1310
+ {
1311
+ title: "Transition Review Round",
1312
+ description: "Advance a review round through its lifecycle (validated transitions: OPEN \u2192 CHANGES_REQUESTED/APPROVED \u2192 CLOSED).",
1313
+ inputSchema: {
1314
+ id: zod.z.string().describe("Review round ID"),
1315
+ status: ReviewStatusEnum.describe("Target review status")
1316
+ }
1317
+ },
1318
+ async ({ id, status }) => {
1319
+ try {
1320
+ const data = await ctx.gql.workspace.request(TRANSITION_REVIEW_ROUND, { id, status });
1321
+ return jsonResult(data.artTransitionReviewRound);
1322
+ } catch (error) {
1323
+ ctx.logger.error("artistrybase reviews_transition_round failed", { error: String(error) });
1324
+ return errorResult(
1325
+ `Failed to transition review round: ${error instanceof Error ? error.message : String(error)}`
1326
+ );
1327
+ }
1328
+ }
1329
+ );
1330
+ server.registerTool(
1331
+ track(mcpToolName(ctx.productName, "reviews_add_feedback")),
1332
+ {
1333
+ title: "Add Feedback",
1334
+ description: "Add a piece of in-context feedback to a review round. Anchor it to a timecode/page/chapter/pin via `anchorType` + `anchorValue` (defaults to GENERAL).",
1335
+ inputSchema: {
1336
+ reviewRoundId: zod.z.string().min(1).describe("Review round ID"),
1337
+ body: zod.z.string().min(1).describe("Feedback body"),
1338
+ anchorType: AnchorTypeEnum.optional().describe("Anchor type (default GENERAL)"),
1339
+ anchorValue: zod.z.string().optional().describe('Anchor value (e.g. timecode "00:01:23", page number, pin coordinates)')
1340
+ }
1341
+ },
1342
+ async ({ reviewRoundId, body, anchorType, anchorValue }) => {
1343
+ try {
1344
+ const input = { reviewRoundId, body };
1345
+ if (anchorType !== void 0) input.anchorType = anchorType;
1346
+ if (anchorValue !== void 0) input.anchorValue = anchorValue;
1347
+ const data = await ctx.gql.workspace.request(ADD_FEEDBACK, { input });
1348
+ return jsonResult(data.artAddFeedback);
1349
+ } catch (error) {
1350
+ ctx.logger.error("artistrybase reviews_add_feedback failed", { error: String(error) });
1351
+ return errorResult(
1352
+ `Failed to add feedback: ${error instanceof Error ? error.message : String(error)}`
1353
+ );
1354
+ }
1355
+ }
1356
+ );
1357
+ server.registerTool(
1358
+ track(mcpToolName(ctx.productName, "reviews_resolve_feedback")),
1359
+ {
1360
+ title: "Resolve Feedback",
1361
+ description: "Set the resolution status of a piece of feedback (RESOLVED / WONT_FIX / OPEN).",
1362
+ inputSchema: {
1363
+ id: zod.z.string().describe("Feedback ID"),
1364
+ status: FeedbackStatusEnum.describe("New feedback status")
1365
+ }
1366
+ },
1367
+ async ({ id, status }) => {
1368
+ try {
1369
+ const data = await ctx.gql.workspace.request(RESOLVE_FEEDBACK, { id, status });
1370
+ return jsonResult(data.artResolveFeedback);
1371
+ } catch (error) {
1372
+ ctx.logger.error("artistrybase reviews_resolve_feedback failed", { error: String(error) });
1373
+ return errorResult(
1374
+ `Failed to resolve feedback: ${error instanceof Error ? error.message : String(error)}`
1375
+ );
1376
+ }
1377
+ }
1378
+ );
1379
+ server.registerTool(
1380
+ track(mcpToolName(ctx.productName, "reviews_record_approval")),
1381
+ {
1382
+ title: "Record Approval",
1383
+ description: "Record an approval decision (APPROVED / REJECTED / PENDING) on a review round, with an optional comment.",
1384
+ inputSchema: {
1385
+ reviewRoundId: zod.z.string().min(1).describe("Review round ID"),
1386
+ decision: ApprovalDecisionEnum.describe("Approval decision"),
1387
+ comment: zod.z.string().optional().describe("Optional comment explaining the decision")
1388
+ }
1389
+ },
1390
+ async ({ reviewRoundId, decision, comment }) => {
1391
+ try {
1392
+ const input = { reviewRoundId, decision };
1393
+ if (comment !== void 0) input.comment = comment;
1394
+ const data = await ctx.gql.workspace.request(RECORD_APPROVAL, { input });
1395
+ return jsonResult(data.artRecordApproval);
1396
+ } catch (error) {
1397
+ ctx.logger.error("artistrybase reviews_record_approval failed", { error: String(error) });
1398
+ return errorResult(
1399
+ `Failed to record approval: ${error instanceof Error ? error.message : String(error)}`
1400
+ );
1401
+ }
1402
+ }
1403
+ );
1404
+ server.registerTool(
1405
+ track(mcpToolName(ctx.productName, "releases_list")),
1406
+ {
1407
+ title: "List Releases",
1408
+ description: "List the releases of a work, optionally filtered by status.",
1409
+ inputSchema: {
1410
+ workId: zod.z.string().describe("Work ID"),
1411
+ status: ReleaseStatusEnum.optional().describe("Filter by release status")
1412
+ }
1413
+ },
1414
+ async ({ workId, status }) => {
1415
+ try {
1416
+ const data = await ctx.gql.workspace.request(LIST_RELEASES, { workId, status });
1417
+ return jsonResult(data.artListReleases);
1418
+ } catch (error) {
1419
+ ctx.logger.error("artistrybase releases_list failed", { error: String(error) });
1420
+ return errorResult(
1421
+ `Failed to list releases: ${error instanceof Error ? error.message : String(error)}`
1422
+ );
1423
+ }
1424
+ }
1425
+ );
1426
+ server.registerTool(
1427
+ track(mcpToolName(ctx.productName, "releases_create")),
1428
+ {
1429
+ title: "Create Release",
1430
+ description: "Create a release for a work (optionally pinned to a version), with an optional channel, visibility, notes, and a scheduled time.",
1431
+ inputSchema: {
1432
+ workId: zod.z.string().min(1).describe("Work ID"),
1433
+ versionId: zod.z.string().optional().describe("Version to release (defaults to current)"),
1434
+ channel: zod.z.string().optional().describe('Release channel (e.g. "store", "preview")'),
1435
+ notes: zod.z.string().optional().describe("Release notes"),
1436
+ scheduledFor: zod.z.string().optional().describe("Scheduled release time (ISO 8601)"),
1437
+ visibility: VisibilityEnum.optional().describe("Visibility (default PUBLIC)")
1438
+ }
1439
+ },
1440
+ async ({ workId, versionId, channel, notes, scheduledFor, visibility }) => {
1441
+ try {
1442
+ const input = { workId };
1443
+ if (versionId !== void 0) input.versionId = versionId;
1444
+ if (channel !== void 0) input.channel = channel;
1445
+ if (notes !== void 0) input.notes = notes;
1446
+ if (scheduledFor !== void 0) input.scheduledFor = scheduledFor;
1447
+ if (visibility !== void 0) input.visibility = visibility;
1448
+ const data = await ctx.gql.workspace.request(CREATE_RELEASE, { input });
1449
+ return jsonResult(data.artCreateRelease);
1450
+ } catch (error) {
1451
+ ctx.logger.error("artistrybase releases_create failed", { error: String(error) });
1452
+ return errorResult(
1453
+ `Failed to create release: ${error instanceof Error ? error.message : String(error)}`
1454
+ );
1455
+ }
1456
+ }
1457
+ );
1458
+ server.registerTool(
1459
+ track(mcpToolName(ctx.productName, "releases_publish")),
1460
+ {
1461
+ title: "Publish Release",
1462
+ description: "Publish a scheduled/draft release now.",
1463
+ inputSchema: { id: zod.z.string().describe("Release ID") }
1464
+ },
1465
+ async ({ id }) => {
1466
+ try {
1467
+ const data = await ctx.gql.workspace.request(PUBLISH_RELEASE, { id });
1468
+ return jsonResult(data.artPublishRelease);
1469
+ } catch (error) {
1470
+ ctx.logger.error("artistrybase releases_publish failed", { error: String(error) });
1471
+ return errorResult(
1472
+ `Failed to publish release: ${error instanceof Error ? error.message : String(error)}`
1473
+ );
1474
+ }
1475
+ }
1476
+ );
1477
+ }
1478
+ function registerPortfolioTools(server, ctx, track) {
1479
+ server.registerTool(
1480
+ track(mcpToolName(ctx.productName, "portfolios_get")),
1481
+ {
1482
+ title: "Get Portfolio",
1483
+ description: "Fetch a single public portfolio by ID.",
1484
+ inputSchema: { id: zod.z.string().describe("Portfolio ID") }
1485
+ },
1486
+ async ({ id }) => {
1487
+ try {
1488
+ const data = await ctx.gql.workspace.request(GET_PORTFOLIO, { id });
1489
+ if (!data.artPortfolio) return errorResult(`Portfolio ${id} not found`);
1490
+ return jsonResult(data.artPortfolio);
1491
+ } catch (error) {
1492
+ ctx.logger.error("artistrybase portfolios_get failed", { error: String(error) });
1493
+ return errorResult(
1494
+ `Failed to get portfolio: ${error instanceof Error ? error.message : String(error)}`
1495
+ );
1496
+ }
1497
+ }
1498
+ );
1499
+ server.registerTool(
1500
+ track(mcpToolName(ctx.productName, "portfolios_list")),
1501
+ {
1502
+ title: "List Portfolios",
1503
+ description: "List public portfolios with optional visibility filter and cursor/offset pagination. Returns a connection ({ items, pageInfo }).",
1504
+ inputSchema: {
1505
+ visibility: VisibilityEnum.optional().describe("Filter by visibility"),
1506
+ limit: zod.z.number().int().optional().describe("Page size (default 50)"),
1507
+ offset: zod.z.number().int().optional().describe("Pagination offset (default 0)"),
1508
+ cursor: zod.z.string().optional().describe("Opaque pagination cursor")
1509
+ }
1510
+ },
1511
+ async ({ visibility, limit, offset, cursor }) => {
1512
+ try {
1513
+ const pagination = { limit: limit ?? 50, offset: offset ?? 0 };
1514
+ if (cursor !== void 0) pagination.cursor = cursor;
1515
+ const data = await ctx.gql.workspace.request(LIST_PORTFOLIOS, { visibility, pagination });
1516
+ return jsonResult(data.artListPortfolios);
1517
+ } catch (error) {
1518
+ ctx.logger.error("artistrybase portfolios_list failed", { error: String(error) });
1519
+ return errorResult(
1520
+ `Failed to list portfolios: ${error instanceof Error ? error.message : String(error)}`
1521
+ );
1522
+ }
1523
+ }
1524
+ );
1525
+ server.registerTool(
1526
+ track(mcpToolName(ctx.productName, "portfolios_create")),
1527
+ {
1528
+ title: "Create Portfolio",
1529
+ description: "Create a public portfolio. `handle` must be unique within the workspace; starts PUBLIC unless overridden.",
1530
+ inputSchema: {
1531
+ handle: zod.z.string().min(1).describe('Unique handle (e.g. "@anbu")'),
1532
+ displayName: zod.z.string().min(1).describe("Display name"),
1533
+ bio: zod.z.string().optional().describe("Short bio"),
1534
+ avatarFileId: zod.z.string().optional().describe("Avatar image File ID"),
1535
+ bannerFileId: zod.z.string().optional().describe("Banner image File ID"),
1536
+ featuredWorkIds: zod.z.array(zod.z.string()).optional().describe("Featured work IDs"),
1537
+ links: JsonObject.optional().describe("Social/external links JSON"),
1538
+ ownerId: zod.z.string().optional().describe("Owner User ID (defaults to the calling actor)"),
1539
+ visibility: VisibilityEnum.optional().describe("Visibility (default PUBLIC)")
1540
+ }
1541
+ },
1542
+ async ({
1543
+ handle,
1544
+ displayName,
1545
+ bio,
1546
+ avatarFileId,
1547
+ bannerFileId,
1548
+ featuredWorkIds,
1549
+ links,
1550
+ ownerId,
1551
+ visibility
1552
+ }) => {
1553
+ try {
1554
+ const input = { handle, displayName };
1555
+ if (bio !== void 0) input.bio = bio;
1556
+ if (avatarFileId !== void 0) input.avatarFileId = avatarFileId;
1557
+ if (bannerFileId !== void 0) input.bannerFileId = bannerFileId;
1558
+ if (featuredWorkIds !== void 0) input.featuredWorkIds = featuredWorkIds;
1559
+ if (links !== void 0) input.links = links;
1560
+ if (ownerId !== void 0) input.ownerId = ownerId;
1561
+ if (visibility !== void 0) input.visibility = visibility;
1562
+ const data = await ctx.gql.workspace.request(CREATE_PORTFOLIO, { input });
1563
+ return jsonResult(data.artCreatePortfolio);
1564
+ } catch (error) {
1565
+ ctx.logger.error("artistrybase portfolios_create failed", { error: String(error) });
1566
+ return errorResult(
1567
+ `Failed to create portfolio: ${error instanceof Error ? error.message : String(error)}`
1568
+ );
1569
+ }
1570
+ }
1571
+ );
1572
+ server.registerTool(
1573
+ track(mcpToolName(ctx.productName, "portfolios_update")),
1574
+ {
1575
+ title: "Update Portfolio",
1576
+ description: "Update a portfolio. At least one mutable field must be provided.",
1577
+ inputSchema: {
1578
+ id: zod.z.string().describe("Portfolio ID"),
1579
+ displayName: zod.z.string().optional().describe("Updated display name"),
1580
+ bio: zod.z.string().optional().describe("Updated bio"),
1581
+ avatarFileId: zod.z.string().optional().describe("Updated avatar File ID"),
1582
+ bannerFileId: zod.z.string().optional().describe("Updated banner File ID"),
1583
+ featuredWorkIds: zod.z.array(zod.z.string()).optional().describe("Updated featured work IDs"),
1584
+ links: JsonObject.optional().describe("Updated links JSON"),
1585
+ visibility: VisibilityEnum.optional().describe("Updated visibility")
1586
+ }
1587
+ },
1588
+ async ({
1589
+ id,
1590
+ displayName,
1591
+ bio,
1592
+ avatarFileId,
1593
+ bannerFileId,
1594
+ featuredWorkIds,
1595
+ links,
1596
+ visibility
1597
+ }) => {
1598
+ try {
1599
+ const input = {};
1600
+ if (displayName !== void 0) input.displayName = displayName;
1601
+ if (bio !== void 0) input.bio = bio;
1602
+ if (avatarFileId !== void 0) input.avatarFileId = avatarFileId;
1603
+ if (bannerFileId !== void 0) input.bannerFileId = bannerFileId;
1604
+ if (featuredWorkIds !== void 0) input.featuredWorkIds = featuredWorkIds;
1605
+ if (links !== void 0) input.links = links;
1606
+ if (visibility !== void 0) input.visibility = visibility;
1607
+ if (Object.keys(input).length === 0) {
1608
+ return errorResult(
1609
+ "No updates specified \u2014 provide at least one of displayName/bio/avatarFileId/bannerFileId/featuredWorkIds/links/visibility"
1610
+ );
1611
+ }
1612
+ const data = await ctx.gql.workspace.request(UPDATE_PORTFOLIO, { id, input });
1613
+ return jsonResult(data.artUpdatePortfolio);
1614
+ } catch (error) {
1615
+ ctx.logger.error("artistrybase portfolios_update failed", { error: String(error) });
1616
+ return errorResult(
1617
+ `Failed to update portfolio: ${error instanceof Error ? error.message : String(error)}`
1618
+ );
1619
+ }
1620
+ }
1621
+ );
1622
+ server.registerTool(
1623
+ track(mcpToolName(ctx.productName, "portfolios_archive")),
1624
+ {
1625
+ title: "Archive Portfolio",
1626
+ description: "Archive a portfolio (soft delete). Returns whether the archive succeeded.",
1627
+ inputSchema: { id: zod.z.string().describe("Portfolio ID") }
1628
+ },
1629
+ async ({ id }) => {
1630
+ try {
1631
+ const data = await ctx.gql.workspace.request(
1632
+ ARCHIVE_PORTFOLIO,
1633
+ { id }
1634
+ );
1635
+ return jsonResult({ ok: data.artArchivePortfolio });
1636
+ } catch (error) {
1637
+ ctx.logger.error("artistrybase portfolios_archive failed", { error: String(error) });
1638
+ return errorResult(
1639
+ `Failed to archive portfolio: ${error instanceof Error ? error.message : String(error)}`
1640
+ );
1641
+ }
1642
+ }
1643
+ );
1644
+ server.registerTool(
1645
+ track(mcpToolName(ctx.productName, "portfolios_follow")),
1646
+ {
1647
+ title: "Follow Portfolio",
1648
+ description: "Follow a portfolio as the calling actor (self-scoped). `notify` toggles new-work notifications (default true).",
1649
+ inputSchema: {
1650
+ portfolioId: zod.z.string().describe("Portfolio ID to follow"),
1651
+ notify: zod.z.boolean().optional().describe("Receive notifications (default true)")
1652
+ }
1653
+ },
1654
+ async ({ portfolioId, notify }) => {
1655
+ try {
1656
+ const data = await ctx.gql.workspace.request(FOLLOW_PORTFOLIO, { portfolioId, notify });
1657
+ return jsonResult(data.artFollowPortfolio);
1658
+ } catch (error) {
1659
+ ctx.logger.error("artistrybase portfolios_follow failed", { error: String(error) });
1660
+ return errorResult(
1661
+ `Failed to follow portfolio: ${error instanceof Error ? error.message : String(error)}`
1662
+ );
1663
+ }
1664
+ }
1665
+ );
1666
+ server.registerTool(
1667
+ track(mcpToolName(ctx.productName, "portfolios_unfollow")),
1668
+ {
1669
+ title: "Unfollow Portfolio",
1670
+ description: "Unfollow a portfolio as the calling actor (self-scoped). Returns whether the unfollow succeeded.",
1671
+ inputSchema: { portfolioId: zod.z.string().describe("Portfolio ID to unfollow") }
1672
+ },
1673
+ async ({ portfolioId }) => {
1674
+ try {
1675
+ const data = await ctx.gql.workspace.request(
1676
+ UNFOLLOW_PORTFOLIO,
1677
+ { portfolioId }
1678
+ );
1679
+ return jsonResult({ ok: data.artUnfollowPortfolio });
1680
+ } catch (error) {
1681
+ ctx.logger.error("artistrybase portfolios_unfollow failed", { error: String(error) });
1682
+ return errorResult(
1683
+ `Failed to unfollow portfolio: ${error instanceof Error ? error.message : String(error)}`
1684
+ );
1685
+ }
1686
+ }
1687
+ );
1688
+ server.registerTool(
1689
+ track(mcpToolName(ctx.productName, "licenses_list")),
1690
+ {
1691
+ title: "List Licenses",
1692
+ description: "List the license terms defined on a work.",
1693
+ inputSchema: { workId: zod.z.string().describe("Work ID") }
1694
+ },
1695
+ async ({ workId }) => {
1696
+ try {
1697
+ const data = await ctx.gql.workspace.request(LIST_LICENSES, { workId });
1698
+ return jsonResult(data.artListLicenses);
1699
+ } catch (error) {
1700
+ ctx.logger.error("artistrybase licenses_list failed", { error: String(error) });
1701
+ return errorResult(
1702
+ `Failed to list licenses: ${error instanceof Error ? error.message : String(error)}`
1703
+ );
1704
+ }
1705
+ }
1706
+ );
1707
+ server.registerTool(
1708
+ track(mcpToolName(ctx.productName, "licenses_create")),
1709
+ {
1710
+ title: "Create License",
1711
+ description: "Create a license on a work. `model` defaults to FREE; set `priceAmount`/`currency` for PURCHASE/LICENSE/MEMBERSHIP models.",
1712
+ inputSchema: {
1713
+ workId: zod.z.string().min(1).describe("Work ID the license applies to"),
1714
+ name: zod.z.string().min(1).describe("License name"),
1715
+ model: LicenseModelEnum.optional().describe("Commercial model (default FREE)"),
1716
+ priceAmount: zod.z.number().optional().describe("Price amount"),
1717
+ currency: zod.z.string().optional().describe('ISO currency code (e.g. "USD")'),
1718
+ spdx: zod.z.string().optional().describe('SPDX identifier (e.g. "CC-BY-4.0")'),
1719
+ terms: zod.z.string().optional().describe("Full license terms text"),
1720
+ attribution: zod.z.string().optional().describe("Required attribution string")
1721
+ }
1722
+ },
1723
+ async ({ workId, name, model, priceAmount, currency, spdx, terms, attribution }) => {
1724
+ try {
1725
+ const input = { workId, name };
1726
+ if (model !== void 0) input.model = model;
1727
+ if (priceAmount !== void 0) input.priceAmount = priceAmount;
1728
+ if (currency !== void 0) input.currency = currency;
1729
+ if (spdx !== void 0) input.spdx = spdx;
1730
+ if (terms !== void 0) input.terms = terms;
1731
+ if (attribution !== void 0) input.attribution = attribution;
1732
+ const data = await ctx.gql.workspace.request(CREATE_LICENSE, { input });
1733
+ return jsonResult(data.artCreateLicense);
1734
+ } catch (error) {
1735
+ ctx.logger.error("artistrybase licenses_create failed", { error: String(error) });
1736
+ return errorResult(
1737
+ `Failed to create license: ${error instanceof Error ? error.message : String(error)}`
1738
+ );
1739
+ }
1740
+ }
1741
+ );
1742
+ server.registerTool(
1743
+ track(mcpToolName(ctx.productName, "licenses_update")),
1744
+ {
1745
+ title: "Update License",
1746
+ description: "Update a license. At least one mutable field must be provided.",
1747
+ inputSchema: {
1748
+ id: zod.z.string().describe("License ID"),
1749
+ name: zod.z.string().optional().describe("Updated name"),
1750
+ model: LicenseModelEnum.optional().describe("Updated commercial model"),
1751
+ priceAmount: zod.z.number().optional().describe("Updated price amount"),
1752
+ currency: zod.z.string().optional().describe("Updated currency code"),
1753
+ spdx: zod.z.string().optional().describe("Updated SPDX identifier"),
1754
+ terms: zod.z.string().optional().describe("Updated terms text"),
1755
+ attribution: zod.z.string().optional().describe("Updated attribution string")
1756
+ }
1757
+ },
1758
+ async ({ id, name, model, priceAmount, currency, spdx, terms, attribution }) => {
1759
+ try {
1760
+ const input = {};
1761
+ if (name !== void 0) input.name = name;
1762
+ if (model !== void 0) input.model = model;
1763
+ if (priceAmount !== void 0) input.priceAmount = priceAmount;
1764
+ if (currency !== void 0) input.currency = currency;
1765
+ if (spdx !== void 0) input.spdx = spdx;
1766
+ if (terms !== void 0) input.terms = terms;
1767
+ if (attribution !== void 0) input.attribution = attribution;
1768
+ if (Object.keys(input).length === 0) {
1769
+ return errorResult(
1770
+ "No updates specified \u2014 provide at least one of name/model/priceAmount/currency/spdx/terms/attribution"
1771
+ );
1772
+ }
1773
+ const data = await ctx.gql.workspace.request(UPDATE_LICENSE, { id, input });
1774
+ return jsonResult(data.artUpdateLicense);
1775
+ } catch (error) {
1776
+ ctx.logger.error("artistrybase licenses_update failed", { error: String(error) });
1777
+ return errorResult(
1778
+ `Failed to update license: ${error instanceof Error ? error.message : String(error)}`
1779
+ );
1780
+ }
1781
+ }
1782
+ );
1783
+ server.registerTool(
1784
+ track(mcpToolName(ctx.productName, "licenses_activate")),
1785
+ {
1786
+ title: "Activate License",
1787
+ description: "Activate a draft license so it becomes purchasable/effective.",
1788
+ inputSchema: { id: zod.z.string().describe("License ID") }
1789
+ },
1790
+ async ({ id }) => {
1791
+ try {
1792
+ const data = await ctx.gql.workspace.request(ACTIVATE_LICENSE, { id });
1793
+ return jsonResult(data.artActivateLicense);
1794
+ } catch (error) {
1795
+ ctx.logger.error("artistrybase licenses_activate failed", { error: String(error) });
1796
+ return errorResult(
1797
+ `Failed to activate license: ${error instanceof Error ? error.message : String(error)}`
1798
+ );
1799
+ }
1800
+ }
1801
+ );
1802
+ }
1803
+
1804
+ // src/modules/artistrybase/tools/health.ts
1805
+ function registerHealthTools(server, ctx, track) {
1806
+ server.registerTool(
1807
+ track(mcpToolName(ctx.productName, "health")),
1808
+ {
1809
+ title: "Artistrybase Health Check",
1810
+ description: "Public health probe for the Artistrybase subgraph (artHealth). Requires no authentication.",
1811
+ inputSchema: {}
1812
+ },
1813
+ async () => {
1814
+ try {
1815
+ const data = await ctx.gql.workspace.request(HEALTH, {});
1816
+ return jsonResult({ ok: true, status: data.artHealth });
1817
+ } catch (error) {
1818
+ ctx.logger.error("artistrybase health failed", { error: String(error) });
1819
+ return errorResult(
1820
+ `Artistrybase health check failed: ${error instanceof Error ? error.message : String(error)}`
1821
+ );
1822
+ }
1823
+ }
1824
+ );
1825
+ }
1826
+
1827
+ // src/modules/artistrybase/resources.ts
1828
+ function registerArtistrybaseResources(server, ctx, track) {
1829
+ const schemaUri = track(mcpResourceUri(ctx.productName, "schema"));
1830
+ const worksUri = track(mcpResourceUri(ctx.productName, "works"));
1831
+ const productionsUri = track(mcpResourceUri(ctx.productName, "productions"));
1832
+ const portfoliosUri = track(mcpResourceUri(ctx.productName, "portfolios"));
1833
+ server.registerResource(
1834
+ "artistrybase-schema",
1835
+ schemaUri,
1836
+ {
1837
+ title: "Artistrybase Domain Schema",
1838
+ description: "Overview of the Artistrybase creative-platform domain \u2014 entities, enums, and the per-entity tool surface.",
1839
+ mimeType: "text/plain"
1840
+ },
1841
+ async () => {
1842
+ ctx.logger.debug(`Resource ${schemaUri} requested`);
1843
+ const schema = `# Artistrybase Domain (Overview)
1844
+
1845
+ Multi-medium creative platform (audio, video, stories, art) \u2014 the federated
1846
+ system of record for creative works, versions, collections, productions, the
1847
+ review/release pipeline, public portfolios, follows, and licensing.
1848
+
1849
+ ## Domains & entities
1850
+ - library: ArtWork (any medium), ArtWorkVersion (immutable history), ArtAsset (file assets), ArtCollection (curated)
1851
+ - production: ArtProduction (a film/album/graphic novel), ArtProductionMember (team), ArtReference (mood boards/links)
1852
+ - review: ArtReviewRound, ArtFeedback (timecode/chapter/pin anchors), ArtApproval, ArtRelease (draft\u2192released pipeline)
1853
+ - portfolio: ArtPortfolio (public, spans every medium), ArtFollow, ArtLicense (explicit terms on works)
1854
+
1855
+ File blobs are never stored here \u2014 works/versions/assets reference a wspace-files-svc File by id via federation.
1856
+
1857
+ ## Enums
1858
+ - ArtMedium: ART, AUDIO, MIXED, STORY, VIDEO
1859
+ - ArtVisibility: PRIVATE, PUBLIC, UNLISTED
1860
+ - ArtWorkStatus: APPROVED, ARCHIVED, DRAFT, IN_REVIEW, RELEASED
1861
+ - ArtAssetKind: ATTACHMENT, CAPTION, COVER, MASTER, PREVIEW, SOURCE
1862
+ - ArtProductionStatus: CANCELLED, IN_PRODUCTION, ON_HOLD, PLANNING, POST, RELEASED, REVIEW
1863
+ - ArtProductionRole: COLLABORATOR, CREATOR, EDITOR, OWNER, PRODUCER, REVIEWER, VIEWER
1864
+ - ArtReviewStatus: APPROVED, CHANGES_REQUESTED, CLOSED, OPEN
1865
+ - ArtFeedbackStatus: OPEN, RESOLVED, WONT_FIX
1866
+ - ArtAnchorType: CHAPTER, GENERAL, PAGE, PIN, TIMECODE
1867
+ - ArtApprovalDecision: APPROVED, PENDING, REJECTED
1868
+ - ArtReleaseStatus: FAILED, PUBLISHED, SCHEDULED, UNPUBLISHED
1869
+ - ArtLicenseModel: FREE, LICENSE, MEMBERSHIP, PURCHASE
1870
+
1871
+ ## Tool groups
1872
+ library (works/versions/assets/collections), production (productions/members/references),
1873
+ review (review_rounds/feedback/approvals/releases), portfolio (portfolios/follows/licenses), health.
1874
+ All run against the WORKSPACE gateway (workspace-scoped) except the public health probe.
1875
+ `;
1876
+ return {
1877
+ contents: [{ uri: schemaUri, text: schema, mimeType: "text/plain" }]
1878
+ };
1879
+ }
1880
+ );
1881
+ server.registerResource(
1882
+ "artistrybase-works",
1883
+ worksUri,
1884
+ {
1885
+ title: "Artistrybase Works",
1886
+ description: "The first 50 creative works in the bound workspace.",
1887
+ mimeType: "application/json"
1888
+ },
1889
+ async () => {
1890
+ ctx.logger.debug(`Resource ${worksUri} requested`);
1891
+ try {
1892
+ const data = await ctx.gql.workspace.request(LIST_WORKS, {
1893
+ pagination: { limit: 50, offset: 0 }
1894
+ });
1895
+ return {
1896
+ contents: [
1897
+ {
1898
+ uri: worksUri,
1899
+ text: JSON.stringify(data.artListWorks, null, 2),
1900
+ mimeType: "application/json"
1901
+ }
1902
+ ]
1903
+ };
1904
+ } catch (error) {
1905
+ return {
1906
+ contents: [
1907
+ {
1908
+ uri: worksUri,
1909
+ text: JSON.stringify({
1910
+ error: error instanceof Error ? error.message : String(error)
1911
+ }),
1912
+ mimeType: "application/json"
1913
+ }
1914
+ ]
1915
+ };
1916
+ }
1917
+ }
1918
+ );
1919
+ server.registerResource(
1920
+ "artistrybase-productions",
1921
+ productionsUri,
1922
+ {
1923
+ title: "Artistrybase Productions",
1924
+ description: "The first 50 productions in the bound workspace.",
1925
+ mimeType: "application/json"
1926
+ },
1927
+ async () => {
1928
+ ctx.logger.debug(`Resource ${productionsUri} requested`);
1929
+ try {
1930
+ const data = await ctx.gql.workspace.request(
1931
+ LIST_PRODUCTIONS,
1932
+ { pagination: { limit: 50, offset: 0 } }
1933
+ );
1934
+ return {
1935
+ contents: [
1936
+ {
1937
+ uri: productionsUri,
1938
+ text: JSON.stringify(data.artListProductions, null, 2),
1939
+ mimeType: "application/json"
1940
+ }
1941
+ ]
1942
+ };
1943
+ } catch (error) {
1944
+ return {
1945
+ contents: [
1946
+ {
1947
+ uri: productionsUri,
1948
+ text: JSON.stringify({
1949
+ error: error instanceof Error ? error.message : String(error)
1950
+ }),
1951
+ mimeType: "application/json"
1952
+ }
1953
+ ]
1954
+ };
1955
+ }
1956
+ }
1957
+ );
1958
+ server.registerResource(
1959
+ "artistrybase-portfolios",
1960
+ portfoliosUri,
1961
+ {
1962
+ title: "Artistrybase Portfolios",
1963
+ description: "The first 50 public portfolios in the bound workspace.",
1964
+ mimeType: "application/json"
1965
+ },
1966
+ async () => {
1967
+ ctx.logger.debug(`Resource ${portfoliosUri} requested`);
1968
+ try {
1969
+ const data = await ctx.gql.workspace.request(
1970
+ LIST_PORTFOLIOS,
1971
+ { pagination: { limit: 50, offset: 0 } }
1972
+ );
1973
+ return {
1974
+ contents: [
1975
+ {
1976
+ uri: portfoliosUri,
1977
+ text: JSON.stringify(data.artListPortfolios, null, 2),
1978
+ mimeType: "application/json"
1979
+ }
1980
+ ]
1981
+ };
1982
+ } catch (error) {
1983
+ return {
1984
+ contents: [
1985
+ {
1986
+ uri: portfoliosUri,
1987
+ text: JSON.stringify({
1988
+ error: error instanceof Error ? error.message : String(error)
1989
+ }),
1990
+ mimeType: "application/json"
1991
+ }
1992
+ ]
1993
+ };
1994
+ }
1995
+ }
1996
+ );
1997
+ }
1998
+ function registerArtistrybasePrompts(server, ctx, track) {
1999
+ const p = ctx.productName;
2000
+ const publishingName = track(mcpPromptName(p, "work-publishing"));
2001
+ const productionName = track(mcpPromptName(p, "production-ops"));
2002
+ server.registerPrompt(
2003
+ publishingName,
2004
+ {
2005
+ title: "Work Publishing",
2006
+ description: "Guide for taking a creative work from draft to released: create the work, upload a version, run a review round, record approval, then create and publish a release.",
2007
+ argsSchema: {
2008
+ title: zod.z.string().optional().describe("Work title"),
2009
+ medium: zod.z.string().optional().describe("Creative medium (ART/AUDIO/STORY/VIDEO/MIXED)")
2010
+ }
2011
+ },
2012
+ ({ title, medium }) => {
2013
+ ctx.logger.debug(`Prompt ${publishingName} called`, { title, medium });
2014
+ const titleNote = title ? `Use the work title "${title}".` : "Ask the user for the work title.";
2015
+ const mediumNote = medium ? `Use medium ${medium}.` : "Help the user pick an ArtMedium.";
2016
+ return {
2017
+ messages: [
2018
+ {
2019
+ role: "user",
2020
+ content: {
2021
+ type: "text",
2022
+ text: `Help me take an Artistrybase work from draft to released.
2023
+
2024
+ 1. **Create Work**: Use ${p}_works_create. ${titleNote} ${mediumNote} Optionally attach a coverFileId and tags.
2025
+ 2. **Upload a Version**: Use ${p}_versions_add with the workId and a source fileId (from wspace-files-svc) to create an immutable revision.
2026
+ 3. **Attach Assets**: Use ${p}_assets_add for masters/previews/captions as needed (kind=MASTER/PREVIEW/CAPTION).
2027
+ 4. **Open Review**: Use ${p}_review_rounds_open for the work (optionally pin a versionId, set a dueDate).
2028
+ 5. **Collect Feedback**: Use ${p}_feedback_add (anchorType=TIMECODE/PAGE/CHAPTER/PIN) and resolve with ${p}_feedback_resolve.
2029
+ 6. **Record Approval**: Use ${p}_approvals_record (decision=APPROVED) on the review round, then ${p}_review_rounds_transition to CLOSED.
2030
+ 7. **Publish Version**: Use ${p}_works_publish_version to promote the approved version as current.
2031
+ 8. **Release**: Use ${p}_releases_create (set channel/visibility), then ${p}_releases_publish.
2032
+
2033
+ Show results at each step and confirm before publishing.`
2034
+ }
2035
+ }
2036
+ ]
2037
+ };
2038
+ }
2039
+ );
2040
+ server.registerPrompt(
2041
+ productionName,
2042
+ {
2043
+ title: "Production Operations",
2044
+ description: "Workflow for running a production: assemble the team, gather references, track works through the pipeline, and advance the production lifecycle.",
2045
+ argsSchema: {
2046
+ productionId: zod.z.string().optional().describe("Production ID to operate")
2047
+ }
2048
+ },
2049
+ ({ productionId }) => {
2050
+ ctx.logger.debug(`Prompt ${productionName} called`, { productionId });
2051
+ const productionNote = productionId ? `Operate production "${productionId}".` : `First list productions with ${p}_productions_list and pick one (or create one with ${p}_productions_create).`;
2052
+ return {
2053
+ messages: [
2054
+ {
2055
+ role: "user",
2056
+ content: {
2057
+ type: "text",
2058
+ text: `Run Artistrybase production operations. ${productionNote}
2059
+
2060
+ 1. **Team**: Use ${p}_members_list to see the team; add collaborators with ${p}_members_add (role=EDITOR/PRODUCER/REVIEWER/...).
2061
+ 2. **References**: Use ${p}_references_list and ${p}_references_add to gather mood boards, links, and reference files.
2062
+ 3. **Works**: Use ${p}_works_list filtered by this productionId to track works; create new ones with ${p}_works_create (productionId set).
2063
+ 4. **Review**: For works in IN_REVIEW, use ${p}_review_rounds_list and ${p}_review_rounds_get to triage open feedback.
2064
+ 5. **Advance**: Use ${p}_productions_transition to move the production through PLANNING \u2192 IN_PRODUCTION \u2192 REVIEW \u2192 POST \u2192 RELEASED.
2065
+
2066
+ Summarize what needs attention after each step.`
2067
+ }
2068
+ }
2069
+ ]
2070
+ };
2071
+ }
2072
+ );
2073
+ }
2074
+
2075
+ // src/modules/artistrybase/index.ts
2076
+ var artistrybaseModule = {
2077
+ id: "artistrybase",
2078
+ version: "0.0.1",
2079
+ displayName: "Artistrybase",
2080
+ dependsOn: ["auth"],
2081
+ capabilities: { tools: {}, resources: {}, prompts: {} },
2082
+ register(server, ctx) {
2083
+ const tools = [];
2084
+ const resources = [];
2085
+ const prompts = [];
2086
+ const trackTool = (n) => {
2087
+ tools.push(n);
2088
+ return n;
2089
+ };
2090
+ const trackResource = (uri) => {
2091
+ resources.push(uri);
2092
+ return uri;
2093
+ };
2094
+ const trackPrompt = (n) => {
2095
+ prompts.push(n);
2096
+ return n;
2097
+ };
2098
+ registerLibraryTools(server, ctx, trackTool);
2099
+ registerProductionTools(server, ctx, trackTool);
2100
+ registerReviewTools(server, ctx, trackTool);
2101
+ registerPortfolioTools(server, ctx, trackTool);
2102
+ registerHealthTools(server, ctx, trackTool);
2103
+ registerArtistrybaseResources(server, ctx, trackResource);
2104
+ registerArtistrybasePrompts(server, ctx, trackPrompt);
2105
+ return { tools, resources, prompts };
2106
+ }
2107
+ };
2108
+ var artistrybase_default = artistrybaseModule;
2109
+
2110
+ module.exports = artistrybase_default;
2111
+ //# sourceMappingURL=index.cjs.map
2112
+ //# sourceMappingURL=index.cjs.map