@mediagraph/mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,3185 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import {
7
+ CallToolRequestSchema,
8
+ ListResourcesRequestSchema,
9
+ ListResourceTemplatesRequestSchema,
10
+ ListToolsRequestSchema,
11
+ ReadResourceRequestSchema
12
+ } from "@modelcontextprotocol/sdk/types.js";
13
+
14
+ // src/auth/oauth.ts
15
+ import { createHash, randomBytes } from "crypto";
16
+ import { createServer } from "http";
17
+ import { URL as URL2 } from "url";
18
+ var OAuthHandler = class {
19
+ config;
20
+ codeVerifier = null;
21
+ state = null;
22
+ callbackServer = null;
23
+ constructor(config2) {
24
+ this.config = {
25
+ clientId: config2.clientId,
26
+ clientSecret: config2.clientSecret,
27
+ oauthUrl: config2.oauthUrl || "https://mediagraph.io",
28
+ redirectPort: config2.redirectPort || 52584,
29
+ scopes: config2.scopes || ["read", "write"]
30
+ };
31
+ }
32
+ /**
33
+ * Generate PKCE code verifier and challenge
34
+ */
35
+ generatePKCE() {
36
+ const verifier = randomBytes(32).toString("base64url");
37
+ const challenge = createHash("sha256").update(verifier).digest("base64url");
38
+ return { verifier, challenge };
39
+ }
40
+ /**
41
+ * Generate a random state parameter
42
+ */
43
+ generateState() {
44
+ return randomBytes(16).toString("base64url");
45
+ }
46
+ /**
47
+ * Get the redirect URI
48
+ */
49
+ getRedirectUri() {
50
+ return `http://localhost:${this.config.redirectPort}/callback`;
51
+ }
52
+ /**
53
+ * Build the authorization URL for OAuth flow
54
+ */
55
+ getAuthorizationUrl() {
56
+ const { verifier, challenge } = this.generatePKCE();
57
+ this.codeVerifier = verifier;
58
+ this.state = this.generateState();
59
+ const params = new URLSearchParams({
60
+ response_type: "code",
61
+ client_id: this.config.clientId,
62
+ redirect_uri: this.getRedirectUri(),
63
+ scope: this.config.scopes.join(" "),
64
+ state: this.state,
65
+ code_challenge: challenge,
66
+ code_challenge_method: "S256"
67
+ });
68
+ return `${this.config.oauthUrl}/oauth/authorize?${params.toString()}`;
69
+ }
70
+ /**
71
+ * Start a local HTTP server to receive the OAuth callback
72
+ */
73
+ async waitForCallback() {
74
+ return new Promise((resolve, reject) => {
75
+ this.callbackServer = createServer((req, res) => {
76
+ const url = new URL2(req.url || "/", `http://localhost:${this.config.redirectPort}`);
77
+ if (url.pathname === "/callback") {
78
+ const code = url.searchParams.get("code");
79
+ const state = url.searchParams.get("state");
80
+ const error = url.searchParams.get("error");
81
+ const errorDescription = url.searchParams.get("error_description");
82
+ if (error) {
83
+ res.writeHead(400, { "Content-Type": "text/html" });
84
+ res.end(`
85
+ <html>
86
+ <body style="font-family: sans-serif; padding: 40px; text-align: center;">
87
+ <h1 style="color: #dc3545;">Authorization Failed</h1>
88
+ <p>${errorDescription || error}</p>
89
+ <p>You can close this window.</p>
90
+ </body>
91
+ </html>
92
+ `);
93
+ this.stopCallbackServer();
94
+ reject(new Error(errorDescription || error));
95
+ return;
96
+ }
97
+ if (!code || !state) {
98
+ res.writeHead(400, { "Content-Type": "text/html" });
99
+ res.end(`
100
+ <html>
101
+ <body style="font-family: sans-serif; padding: 40px; text-align: center;">
102
+ <h1 style="color: #dc3545;">Invalid Callback</h1>
103
+ <p>Missing authorization code or state.</p>
104
+ <p>You can close this window.</p>
105
+ </body>
106
+ </html>
107
+ `);
108
+ this.stopCallbackServer();
109
+ reject(new Error("Missing authorization code or state"));
110
+ return;
111
+ }
112
+ if (state !== this.state) {
113
+ res.writeHead(400, { "Content-Type": "text/html" });
114
+ res.end(`
115
+ <html>
116
+ <body style="font-family: sans-serif; padding: 40px; text-align: center;">
117
+ <h1 style="color: #dc3545;">Security Error</h1>
118
+ <p>State parameter mismatch. This could indicate a CSRF attack.</p>
119
+ <p>You can close this window.</p>
120
+ </body>
121
+ </html>
122
+ `);
123
+ this.stopCallbackServer();
124
+ reject(new Error("State parameter mismatch"));
125
+ return;
126
+ }
127
+ res.writeHead(200, { "Content-Type": "text/html" });
128
+ res.end(`
129
+ <html>
130
+ <body style="font-family: sans-serif; padding: 40px; text-align: center;">
131
+ <h1 style="color: #28a745;">Authorization Successful</h1>
132
+ <p>You have successfully connected to Mediagraph.</p>
133
+ <p>You can close this window and return to your application.</p>
134
+ </body>
135
+ </html>
136
+ `);
137
+ this.stopCallbackServer();
138
+ resolve({ code, state });
139
+ } else {
140
+ res.writeHead(404);
141
+ res.end("Not found");
142
+ }
143
+ });
144
+ this.callbackServer.listen(this.config.redirectPort, () => {
145
+ });
146
+ setTimeout(() => {
147
+ this.stopCallbackServer();
148
+ reject(new Error("Authorization timed out"));
149
+ }, 5 * 60 * 1e3);
150
+ });
151
+ }
152
+ /**
153
+ * Stop the callback server
154
+ */
155
+ stopCallbackServer() {
156
+ if (this.callbackServer) {
157
+ this.callbackServer.close();
158
+ this.callbackServer = null;
159
+ }
160
+ }
161
+ /**
162
+ * Exchange authorization code for tokens
163
+ */
164
+ async exchangeCode(code) {
165
+ if (!this.codeVerifier) {
166
+ throw new Error("No code verifier available. Start authorization flow first.");
167
+ }
168
+ const params = new URLSearchParams({
169
+ grant_type: "authorization_code",
170
+ code,
171
+ redirect_uri: this.getRedirectUri(),
172
+ client_id: this.config.clientId,
173
+ code_verifier: this.codeVerifier
174
+ });
175
+ if (this.config.clientSecret) {
176
+ params.append("client_secret", this.config.clientSecret);
177
+ }
178
+ const response = await fetch(`${this.config.oauthUrl}/oauth/token`, {
179
+ method: "POST",
180
+ headers: {
181
+ "Content-Type": "application/x-www-form-urlencoded"
182
+ },
183
+ body: params.toString()
184
+ });
185
+ if (!response.ok) {
186
+ const error = await response.json().catch(() => ({ error: "unknown_error" }));
187
+ throw new Error(`Token exchange failed: ${error.error_description || error.error}`);
188
+ }
189
+ const tokenData = await response.json();
190
+ this.codeVerifier = null;
191
+ this.state = null;
192
+ return {
193
+ ...tokenData,
194
+ expires_at: Date.now() + tokenData.expires_in * 1e3
195
+ };
196
+ }
197
+ /**
198
+ * Refresh an access token using a refresh token
199
+ */
200
+ async refreshToken(refreshToken) {
201
+ const params = new URLSearchParams({
202
+ grant_type: "refresh_token",
203
+ refresh_token: refreshToken,
204
+ client_id: this.config.clientId
205
+ });
206
+ if (this.config.clientSecret) {
207
+ params.append("client_secret", this.config.clientSecret);
208
+ }
209
+ const response = await fetch(`${this.config.oauthUrl}/oauth/token`, {
210
+ method: "POST",
211
+ headers: {
212
+ "Content-Type": "application/x-www-form-urlencoded"
213
+ },
214
+ body: params.toString()
215
+ });
216
+ if (!response.ok) {
217
+ const error = await response.json().catch(() => ({ error: "unknown_error" }));
218
+ throw new Error(`Token refresh failed: ${error.error_description || error.error}`);
219
+ }
220
+ const tokenData = await response.json();
221
+ return {
222
+ ...tokenData,
223
+ expires_at: Date.now() + tokenData.expires_in * 1e3
224
+ };
225
+ }
226
+ /**
227
+ * Revoke a token
228
+ */
229
+ async revokeToken(token) {
230
+ const params = new URLSearchParams({
231
+ token,
232
+ client_id: this.config.clientId
233
+ });
234
+ if (this.config.clientSecret) {
235
+ params.append("client_secret", this.config.clientSecret);
236
+ }
237
+ await fetch(`${this.config.oauthUrl}/oauth/revoke`, {
238
+ method: "POST",
239
+ headers: {
240
+ "Content-Type": "application/x-www-form-urlencoded"
241
+ },
242
+ body: params.toString()
243
+ });
244
+ }
245
+ };
246
+
247
+ // src/auth/token-store.ts
248
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
249
+ import { createCipheriv, createDecipheriv, randomBytes as randomBytes2, scryptSync } from "crypto";
250
+ import { homedir } from "os";
251
+ import { join, dirname } from "path";
252
+ var ALGORITHM = "aes-256-gcm";
253
+ var SALT_LENGTH = 16;
254
+ var IV_LENGTH = 12;
255
+ var TAG_LENGTH = 16;
256
+ var TokenStore = class {
257
+ filePath;
258
+ encryptionKey = null;
259
+ constructor(filePath) {
260
+ this.filePath = filePath || join(homedir(), ".mediagraph", "tokens.enc");
261
+ }
262
+ /**
263
+ * Derive encryption key from a passphrase
264
+ * In production, this should use system keychain or secure enclave
265
+ */
266
+ getEncryptionKey() {
267
+ if (this.encryptionKey) {
268
+ return this.encryptionKey;
269
+ }
270
+ const machineId = `${homedir()}-mediagraph-mcp`;
271
+ this.encryptionKey = scryptSync(machineId, "mediagraph-mcp-salt", 32);
272
+ return this.encryptionKey;
273
+ }
274
+ /**
275
+ * Encrypt data
276
+ */
277
+ encrypt(data) {
278
+ const key = this.getEncryptionKey();
279
+ const iv = randomBytes2(IV_LENGTH);
280
+ const salt = randomBytes2(SALT_LENGTH);
281
+ const cipher = createCipheriv(ALGORITHM, key, iv);
282
+ const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
283
+ const tag = cipher.getAuthTag();
284
+ return Buffer.concat([salt, iv, tag, encrypted]);
285
+ }
286
+ /**
287
+ * Decrypt data
288
+ */
289
+ decrypt(encryptedBuffer) {
290
+ const key = this.getEncryptionKey();
291
+ const salt = encryptedBuffer.subarray(0, SALT_LENGTH);
292
+ const iv = encryptedBuffer.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);
293
+ const tag = encryptedBuffer.subarray(SALT_LENGTH + IV_LENGTH, SALT_LENGTH + IV_LENGTH + TAG_LENGTH);
294
+ const encrypted = encryptedBuffer.subarray(SALT_LENGTH + IV_LENGTH + TAG_LENGTH);
295
+ const decipher = createDecipheriv(ALGORITHM, key, iv);
296
+ decipher.setAuthTag(tag);
297
+ return decipher.update(encrypted) + decipher.final("utf8");
298
+ }
299
+ /**
300
+ * Save tokens to encrypted file
301
+ */
302
+ save(data) {
303
+ const dir = dirname(this.filePath);
304
+ if (!existsSync(dir)) {
305
+ mkdirSync(dir, { recursive: true, mode: 448 });
306
+ }
307
+ const encrypted = this.encrypt(JSON.stringify(data));
308
+ writeFileSync(this.filePath, encrypted, { mode: 384 });
309
+ }
310
+ /**
311
+ * Load tokens from encrypted file
312
+ */
313
+ load() {
314
+ if (!existsSync(this.filePath)) {
315
+ return null;
316
+ }
317
+ try {
318
+ const encrypted = readFileSync(this.filePath);
319
+ const decrypted = this.decrypt(encrypted);
320
+ return JSON.parse(decrypted);
321
+ } catch (error) {
322
+ console.error("Failed to load tokens:", error);
323
+ return null;
324
+ }
325
+ }
326
+ /**
327
+ * Delete stored tokens
328
+ */
329
+ clear() {
330
+ if (existsSync(this.filePath)) {
331
+ writeFileSync(this.filePath, "", { mode: 384 });
332
+ }
333
+ }
334
+ /**
335
+ * Check if tokens exist
336
+ */
337
+ hasTokens() {
338
+ return existsSync(this.filePath) && this.load() !== null;
339
+ }
340
+ /**
341
+ * Check if access token is expired or about to expire
342
+ */
343
+ isTokenExpired(bufferSeconds = 300) {
344
+ const data = this.load();
345
+ if (!data || !data.tokens) {
346
+ return true;
347
+ }
348
+ return Date.now() >= data.tokens.expires_at - bufferSeconds * 1e3;
349
+ }
350
+ /**
351
+ * Get access token, returning null if expired
352
+ */
353
+ getAccessToken() {
354
+ const data = this.load();
355
+ if (!data || !data.tokens) {
356
+ return null;
357
+ }
358
+ if (this.isTokenExpired()) {
359
+ return null;
360
+ }
361
+ return data.tokens.access_token;
362
+ }
363
+ /**
364
+ * Get refresh token
365
+ */
366
+ getRefreshToken() {
367
+ const data = this.load();
368
+ return data?.tokens?.refresh_token || null;
369
+ }
370
+ };
371
+
372
+ // src/api/client.ts
373
+ var MediagraphApiError = class extends Error {
374
+ constructor(statusCode, errorBody) {
375
+ super(errorBody.message || errorBody.error || "API Error");
376
+ this.statusCode = statusCode;
377
+ this.errorBody = errorBody;
378
+ this.name = "MediagraphApiError";
379
+ }
380
+ };
381
+ var MediagraphClient = class {
382
+ apiUrl;
383
+ getAccessToken;
384
+ maxRetries = 3;
385
+ retryDelay = 1e3;
386
+ constructor(config2) {
387
+ this.apiUrl = config2.apiUrl || "https://api.mediagraph.io";
388
+ this.getAccessToken = config2.getAccessToken;
389
+ }
390
+ async request(method, path, options = {}) {
391
+ const token = await this.getAccessToken();
392
+ if (!token) {
393
+ throw new Error("Not authenticated. Please authorize with Mediagraph first.");
394
+ }
395
+ let url = `${this.apiUrl}${path}`;
396
+ if (options.params && method === "GET") {
397
+ const searchParams = new URLSearchParams();
398
+ for (const [key, value] of Object.entries(options.params)) {
399
+ if (value !== void 0 && value !== null) {
400
+ if (Array.isArray(value)) {
401
+ value.forEach((v) => searchParams.append(`${key}[]`, String(v)));
402
+ } else {
403
+ searchParams.append(key, String(value));
404
+ }
405
+ }
406
+ }
407
+ const queryString = searchParams.toString();
408
+ if (queryString) {
409
+ url += `?${queryString}`;
410
+ }
411
+ }
412
+ let lastError = null;
413
+ for (let attempt = 0; attempt < this.maxRetries; attempt++) {
414
+ try {
415
+ const headers = {
416
+ Authorization: `Bearer ${token}`,
417
+ "Content-Type": "application/json",
418
+ Accept: "application/json"
419
+ };
420
+ const fetchOptions = {
421
+ method,
422
+ headers
423
+ };
424
+ if (options.body && method !== "GET") {
425
+ fetchOptions.body = JSON.stringify(options.body);
426
+ } else if (options.params && method !== "GET") {
427
+ fetchOptions.body = JSON.stringify(options.params);
428
+ }
429
+ const response = await fetch(url, fetchOptions);
430
+ if (response.status === 401) {
431
+ throw new MediagraphApiError(401, {
432
+ error: "unauthorized",
433
+ message: "Access token expired or invalid. Please re-authorize."
434
+ });
435
+ }
436
+ if (response.status === 403) {
437
+ throw new MediagraphApiError(403, {
438
+ error: "forbidden",
439
+ message: "You do not have permission to perform this action."
440
+ });
441
+ }
442
+ if (response.status === 404) {
443
+ throw new MediagraphApiError(404, {
444
+ error: "not_found",
445
+ message: "The requested resource was not found."
446
+ });
447
+ }
448
+ if (response.status === 429) {
449
+ const retryAfter = response.headers.get("Retry-After");
450
+ const delay = retryAfter ? parseInt(retryAfter, 10) * 1e3 : this.retryDelay * Math.pow(2, attempt);
451
+ await this.sleep(delay);
452
+ continue;
453
+ }
454
+ if (!response.ok) {
455
+ let errorBody;
456
+ try {
457
+ errorBody = await response.json();
458
+ } catch {
459
+ errorBody = { error: "unknown_error", message: response.statusText };
460
+ }
461
+ throw new MediagraphApiError(response.status, errorBody);
462
+ }
463
+ const contentType = response.headers.get("Content-Type");
464
+ if (!contentType?.includes("application/json")) {
465
+ return {};
466
+ }
467
+ const data = await response.json();
468
+ return data;
469
+ } catch (error) {
470
+ lastError = error;
471
+ if (error instanceof MediagraphApiError && [401, 403, 404].includes(error.statusCode)) {
472
+ throw error;
473
+ }
474
+ if (attempt < this.maxRetries - 1) {
475
+ await this.sleep(this.retryDelay * Math.pow(2, attempt));
476
+ continue;
477
+ }
478
+ }
479
+ }
480
+ throw lastError || new Error("Request failed after retries");
481
+ }
482
+ sleep(ms) {
483
+ return new Promise((resolve) => setTimeout(resolve, ms));
484
+ }
485
+ // ============================================================================
486
+ // User & Organization
487
+ // ============================================================================
488
+ async whoami() {
489
+ return this.request("GET", "/api/whoami");
490
+ }
491
+ async getOrganization(id) {
492
+ return this.request("GET", `/api/organizations/${id}`);
493
+ }
494
+ async findOrganization(params) {
495
+ return this.request("GET", "/api/organizations/find", { params });
496
+ }
497
+ // ============================================================================
498
+ // Memberships
499
+ // ============================================================================
500
+ async listMemberships(params) {
501
+ return this.request("GET", "/api/memberships", { params });
502
+ }
503
+ async getMembership(id) {
504
+ return this.request("GET", `/api/memberships/${id}`);
505
+ }
506
+ async updateMembership(id, data) {
507
+ return this.request("PUT", `/api/memberships/${id}`, { body: { membership: data } });
508
+ }
509
+ async updateMembershipStatus(id, status) {
510
+ return this.request("PUT", `/api/memberships/${id}/update_status`, { body: { status } });
511
+ }
512
+ async deleteMembership(id) {
513
+ await this.request("DELETE", `/api/memberships/${id}`);
514
+ }
515
+ // ============================================================================
516
+ // Assets
517
+ // ============================================================================
518
+ async searchAssets(params = {}) {
519
+ const apiParams = {
520
+ page: params.page || 1,
521
+ per_page: params.per_page || 25
522
+ };
523
+ const searchKeys = [
524
+ "q",
525
+ "ids",
526
+ "guids",
527
+ "upload_id",
528
+ "upload_guid",
529
+ "storage_folder_id",
530
+ "omit_child_storage_folders",
531
+ "collection_id",
532
+ "omit_child_collections",
533
+ "lightbox_id",
534
+ "omit_child_lightboxes",
535
+ "lightbox_folder_id",
536
+ "omit_child_lightbox_folders",
537
+ "tags",
538
+ "hide_tags",
539
+ "taxonomy",
540
+ "hide_taxonomy",
541
+ "taxonomy_filter_mode",
542
+ "exts",
543
+ "rating",
544
+ "rights",
545
+ "rights_code",
546
+ "aspect",
547
+ "has_people",
548
+ "has_alt_text",
549
+ "file_size_range",
550
+ "gps",
551
+ "bounds",
552
+ "captured_at",
553
+ "missing_captured_at",
554
+ "created_at",
555
+ "updated_at",
556
+ "snapshot_timestamp",
557
+ "proximity_field",
558
+ "proximity_word_1",
559
+ "proximity_word_2",
560
+ "proximity_max_gaps",
561
+ "user_ids",
562
+ "creator_ids",
563
+ "include_totals",
564
+ "as_filters",
565
+ "include_renditions",
566
+ "include_meta"
567
+ ];
568
+ for (const key of searchKeys) {
569
+ if (params[key] !== void 0) {
570
+ apiParams[key] = params[key];
571
+ }
572
+ }
573
+ const response = await this.request(
574
+ "GET",
575
+ "/api/assets/search",
576
+ { params: apiParams }
577
+ );
578
+ return {
579
+ assets: response.assets || [],
580
+ total: response.total || response.assets?.length || 0,
581
+ page: params.page || 1,
582
+ per_page: params.per_page || 25,
583
+ total_pages: Math.ceil((response.total || response.assets?.length || 0) / (params.per_page || 25)),
584
+ aggs: response.aggs
585
+ };
586
+ }
587
+ async getAsset(id, options) {
588
+ const params = {};
589
+ if (options?.include_renditions) params.include_renditions = true;
590
+ if (options?.include_meta) params.include_meta = true;
591
+ if (options?.sync) params.sync = true;
592
+ return this.request("GET", `/api/assets/${id}`, { params });
593
+ }
594
+ async updateAsset(id, data) {
595
+ return this.request("PUT", `/api/assets/${id}`, { body: { asset: data } });
596
+ }
597
+ async deleteAsset(id) {
598
+ await this.request("DELETE", `/api/assets/${id}`);
599
+ }
600
+ async getAssetCounts(params) {
601
+ return this.request("GET", "/api/assets/counts", { params });
602
+ }
603
+ async getTrashedAssets(params) {
604
+ return this.request("GET", "/api/assets/trashed", { params });
605
+ }
606
+ async getPopularAssets(params) {
607
+ return this.request("GET", "/api/assets/popular", { params });
608
+ }
609
+ async getUpdatedAssetsSinceLastSync(params) {
610
+ return this.request("GET", "/api/assets/updated_since_last_sync", { params });
611
+ }
612
+ async addTagsToAsset(id, tags) {
613
+ return this.request("POST", `/api/assets/${id}/tag`, { body: { tags } });
614
+ }
615
+ async getAssetAutoTags(id) {
616
+ return this.request("GET", `/api/assets/${id}/auto_tags`);
617
+ }
618
+ async getAssetFaceTaggings(id) {
619
+ return this.request("GET", `/api/assets/${id}/face_taggings`);
620
+ }
621
+ async getAssetDownload(id, rendition) {
622
+ const params = {};
623
+ if (rendition) params.rendition = rendition;
624
+ return this.request("GET", `/api/assets/${id}/download`, { params });
625
+ }
626
+ async addAssetVersion(id, data) {
627
+ return this.request("POST", `/api/assets/${id}/add_version`, { body: data });
628
+ }
629
+ async revertAsset(id, versionNumber) {
630
+ return this.request("POST", `/api/assets/${id}/revert`, { body: { version_number: versionNumber } });
631
+ }
632
+ async requestAssetOptimization(id) {
633
+ return this.request("POST", `/api/assets/${id}/request_optimization`);
634
+ }
635
+ async completeAssetOptimization(id) {
636
+ return this.request("POST", `/api/assets/${id}/complete_optimization`);
637
+ }
638
+ async removeAssetOptimizationRequest(id) {
639
+ return this.request("DELETE", `/api/assets/${id}/remove_optimization_request`);
640
+ }
641
+ async updateAssetCollectiveWork(id, data) {
642
+ return this.request("PUT", `/api/assets/${id}/update_collective_work`, { body: data });
643
+ }
644
+ async addAssetsToGroup(assetIds, groupId, groupType) {
645
+ await this.request("POST", "/api/assets/add_group", {
646
+ body: { asset_ids: assetIds, group_id: groupId, group_type: groupType }
647
+ });
648
+ }
649
+ // ============================================================================
650
+ // Asset Data Versions
651
+ // ============================================================================
652
+ async getAssetDataVersions(assetId) {
653
+ return this.request("GET", `/api/assets/${assetId}/asset_data_versions`);
654
+ }
655
+ async getAssetDataVersion(assetId, versionNumber) {
656
+ return this.request("GET", `/api/assets/${assetId}/asset_data_versions/${versionNumber}`);
657
+ }
658
+ // ============================================================================
659
+ // Collections
660
+ // ============================================================================
661
+ async listCollections(params) {
662
+ return this.request("GET", "/api/collections", { params });
663
+ }
664
+ async getCollection(id) {
665
+ return this.request("GET", `/api/collections/${id}`);
666
+ }
667
+ async createCollection(data) {
668
+ return this.request("POST", "/api/collections", { body: { collection: data } });
669
+ }
670
+ async updateCollection(id, data) {
671
+ return this.request("PUT", `/api/collections/${id}`, { body: { collection: data } });
672
+ }
673
+ async deleteCollection(id) {
674
+ await this.request("DELETE", `/api/collections/${id}`);
675
+ }
676
+ async findCollection(params) {
677
+ return this.request("GET", "/api/collections/find", { params });
678
+ }
679
+ async getCollectionsTree() {
680
+ return this.request("GET", "/api/collections/tree");
681
+ }
682
+ async getCollectionVisibleAssetCounts(ids) {
683
+ return this.request("GET", "/api/collections/visible_asset_counts", { params: { ids } });
684
+ }
685
+ async addAssetToCollection(collectionId, assetId) {
686
+ await this.request("POST", `/api/collections/${collectionId}/add_asset`, { body: { asset_id: assetId } });
687
+ }
688
+ // ============================================================================
689
+ // Lightboxes
690
+ // ============================================================================
691
+ async listLightboxes(params) {
692
+ return this.request("GET", "/api/lightboxes", { params });
693
+ }
694
+ async getLightbox(id) {
695
+ return this.request("GET", `/api/lightboxes/${id}`);
696
+ }
697
+ async createLightbox(data) {
698
+ return this.request("POST", "/api/lightboxes", { body: { lightbox: data } });
699
+ }
700
+ async updateLightbox(id, data) {
701
+ return this.request("PUT", `/api/lightboxes/${id}`, { body: { lightbox: data } });
702
+ }
703
+ async deleteLightbox(id) {
704
+ await this.request("DELETE", `/api/lightboxes/${id}`);
705
+ }
706
+ async getLightboxesTree() {
707
+ return this.request("GET", "/api/lightboxes/tree");
708
+ }
709
+ async transferLightboxOwnership(id, userId) {
710
+ return this.request("POST", `/api/lightboxes/${id}/transfer_ownership`, { body: { user_id: userId } });
711
+ }
712
+ async addAssetToLightbox(lightboxId, assetId) {
713
+ await this.request("POST", `/api/lightboxes/${lightboxId}/add_asset`, { body: { asset_id: assetId } });
714
+ }
715
+ // ============================================================================
716
+ // Storage Folders
717
+ // ============================================================================
718
+ async listStorageFolders(params) {
719
+ return this.request("GET", "/api/storage_folders", { params });
720
+ }
721
+ async getStorageFolder(id) {
722
+ return this.request("GET", `/api/storage_folders/${id}`);
723
+ }
724
+ async createStorageFolder(data) {
725
+ return this.request("POST", "/api/storage_folders", { body: { storage_folder: data } });
726
+ }
727
+ async updateStorageFolder(id, data) {
728
+ return this.request("PUT", `/api/storage_folders/${id}`, { body: { storage_folder: data } });
729
+ }
730
+ async deleteStorageFolder(id) {
731
+ await this.request("DELETE", `/api/storage_folders/${id}`);
732
+ }
733
+ async getStorageFoldersTree() {
734
+ return this.request("GET", "/api/storage_folders/tree");
735
+ }
736
+ async getStorageFolderAssetIds(id) {
737
+ return this.request("GET", `/api/storage_folders/${id}/asset_ids`);
738
+ }
739
+ // ============================================================================
740
+ // Tags
741
+ // ============================================================================
742
+ async listTags(params) {
743
+ return this.request("GET", "/api/tags", { params });
744
+ }
745
+ async getTag(id) {
746
+ return this.request("GET", `/api/tags/${id}`);
747
+ }
748
+ async createTag(data) {
749
+ return this.request("POST", "/api/tags", { body: { tag: data } });
750
+ }
751
+ async updateTag(id, data) {
752
+ return this.request("PUT", `/api/tags/${id}`, { body: { tag: data } });
753
+ }
754
+ async deleteTag(id) {
755
+ await this.request("DELETE", `/api/tags/${id}`);
756
+ }
757
+ async bulkFindTags(names) {
758
+ return this.request("POST", "/api/tags/bulk_find", { body: { names } });
759
+ }
760
+ async addTagToTaxonomy(id, taxonomyId) {
761
+ return this.request("POST", `/api/tags/${id}/add_taxonomy`, { body: { taxonomy_id: taxonomyId } });
762
+ }
763
+ async mergeTagInto(id, targetTagId) {
764
+ await this.request("POST", `/api/tags/${id}/merge_into`, { body: { target_tag_id: targetTagId } });
765
+ }
766
+ async getTagEvents(params) {
767
+ return this.request("GET", "/api/tags/events", { params });
768
+ }
769
+ // ============================================================================
770
+ // Auto Tags
771
+ // ============================================================================
772
+ async listAutoTags(params) {
773
+ return this.request("GET", "/api/auto_tags", { params });
774
+ }
775
+ async getAutoTag(id) {
776
+ return this.request("GET", `/api/auto_tags/${id}`);
777
+ }
778
+ async bulkFindAutoTags(names) {
779
+ return this.request("POST", "/api/auto_tags/bulk_find", { body: { names } });
780
+ }
781
+ // ============================================================================
782
+ // Taggings
783
+ // ============================================================================
784
+ async getTagging(id) {
785
+ return this.request("GET", `/api/taggings/${id}`);
786
+ }
787
+ async deleteTagging(id) {
788
+ await this.request("DELETE", `/api/taggings/${id}`);
789
+ }
790
+ // ============================================================================
791
+ // Taxonomies
792
+ // ============================================================================
793
+ async listTaxonomies(params) {
794
+ return this.request("GET", "/api/taxonomies", { params });
795
+ }
796
+ async getTaxonomy(id) {
797
+ return this.request("GET", `/api/taxonomies/${id}`);
798
+ }
799
+ async createTaxonomy(data) {
800
+ return this.request("POST", "/api/taxonomies", { body: { taxonomy: data } });
801
+ }
802
+ async updateTaxonomy(id, data) {
803
+ return this.request("PUT", `/api/taxonomies/${id}`, { body: { taxonomy: data } });
804
+ }
805
+ async deleteTaxonomy(id) {
806
+ await this.request("DELETE", `/api/taxonomies/${id}`);
807
+ }
808
+ // ============================================================================
809
+ // Taxonomy Tags
810
+ // ============================================================================
811
+ async listTaxonomyTags(taxonomyId, params) {
812
+ return this.request("GET", `/api/taxonomies/${taxonomyId}/taxonomy_tags`, { params });
813
+ }
814
+ async getTaxonomyTag(taxonomyId, id) {
815
+ return this.request("GET", `/api/taxonomies/${taxonomyId}/taxonomy_tags/${id}`);
816
+ }
817
+ async createTaxonomyTag(taxonomyId, data) {
818
+ return this.request("POST", `/api/taxonomies/${taxonomyId}/taxonomy_tags`, { body: { taxonomy_tag: data } });
819
+ }
820
+ async updateTaxonomyTag(taxonomyId, id, data) {
821
+ return this.request("PUT", `/api/taxonomies/${taxonomyId}/taxonomy_tags/${id}`, { body: { taxonomy_tag: data } });
822
+ }
823
+ async deleteTaxonomyTag(taxonomyId, id) {
824
+ await this.request("DELETE", `/api/taxonomies/${taxonomyId}/taxonomy_tags/${id}`);
825
+ }
826
+ async getTaxonomyTagsTree(taxonomyId) {
827
+ return this.request("GET", `/api/taxonomies/${taxonomyId}/taxonomy_tags/tree`);
828
+ }
829
+ // ============================================================================
830
+ // Creator Tags
831
+ // ============================================================================
832
+ async listCreatorTags(params) {
833
+ return this.request("GET", "/api/creator_tags", { params });
834
+ }
835
+ async getCreatorTag(id) {
836
+ return this.request("GET", `/api/creator_tags/${id}`);
837
+ }
838
+ async createCreatorTag(data) {
839
+ return this.request("POST", "/api/creator_tags", { body: { creator_tag: data } });
840
+ }
841
+ async updateCreatorTag(id, data) {
842
+ return this.request("PUT", `/api/creator_tags/${id}`, { body: { creator_tag: data } });
843
+ }
844
+ async deleteCreatorTag(id) {
845
+ await this.request("DELETE", `/api/creator_tags/${id}`);
846
+ }
847
+ async findCreatorTag(params) {
848
+ return this.request("GET", "/api/creator_tags/find", { params });
849
+ }
850
+ // ============================================================================
851
+ // Rights Packages
852
+ // ============================================================================
853
+ async listRightsPackages(params) {
854
+ return this.request("GET", "/api/rights_packages", { params });
855
+ }
856
+ async getRightsPackage(id) {
857
+ return this.request("GET", `/api/rights_packages/${id}`);
858
+ }
859
+ async createRightsPackage(data) {
860
+ return this.request("POST", "/api/rights_packages", { body: { rights_package: data } });
861
+ }
862
+ async updateRightsPackage(id, data) {
863
+ return this.request("PUT", `/api/rights_packages/${id}`, { body: { rights_package: data } });
864
+ }
865
+ async deleteRightsPackage(id) {
866
+ await this.request("DELETE", `/api/rights_packages/${id}`);
867
+ }
868
+ async bulkFindRightsPackages(ids) {
869
+ return this.request("POST", "/api/rights_packages/bulk_find", { body: { ids } });
870
+ }
871
+ // ============================================================================
872
+ // Permissions
873
+ // ============================================================================
874
+ async listPermissions(params) {
875
+ return this.request("GET", "/api/permissions", { params });
876
+ }
877
+ async getPermission(id) {
878
+ return this.request("GET", `/api/permissions/${id}`);
879
+ }
880
+ async createPermission(data) {
881
+ return this.request("POST", "/api/permissions", { body: { permission: data } });
882
+ }
883
+ async updatePermission(id, data) {
884
+ return this.request("PUT", `/api/permissions/${id}`, { body: { permission: data } });
885
+ }
886
+ async deletePermission(id) {
887
+ await this.request("DELETE", `/api/permissions/${id}`);
888
+ }
889
+ // ============================================================================
890
+ // Share Links
891
+ // ============================================================================
892
+ async listShareLinks(params) {
893
+ return this.request("GET", "/api/share_links", { params });
894
+ }
895
+ async getShareLink(id) {
896
+ return this.request("GET", `/api/share_links/${id}`);
897
+ }
898
+ async createShareLink(data) {
899
+ return this.request("POST", "/api/share_links", { body: { share_link: data } });
900
+ }
901
+ async updateShareLink(id, data) {
902
+ return this.request("PUT", `/api/share_links/${id}`, { body: { share_link: data } });
903
+ }
904
+ async deleteShareLink(id) {
905
+ await this.request("DELETE", `/api/share_links/${id}`);
906
+ }
907
+ async getAssetGroupShareLinks(assetGroupId) {
908
+ return this.request("GET", `/api/asset_groups/${assetGroupId}/share_links`);
909
+ }
910
+ // ============================================================================
911
+ // Shares
912
+ // ============================================================================
913
+ async listShares(params) {
914
+ return this.request("GET", "/api/shares", { params });
915
+ }
916
+ async getShare(id) {
917
+ return this.request("GET", `/api/shares/${id}`);
918
+ }
919
+ async createShare(data) {
920
+ return this.request("POST", "/api/shares", { body: { share: data } });
921
+ }
922
+ async deleteShare(id) {
923
+ await this.request("DELETE", `/api/shares/${id}`);
924
+ }
925
+ // ============================================================================
926
+ // Collection Shares
927
+ // ============================================================================
928
+ async listCollectionShares(params) {
929
+ return this.request("GET", "/api/collection_shares", { params });
930
+ }
931
+ async getCollectionShare(id) {
932
+ return this.request("GET", `/api/collection_shares/${id}`);
933
+ }
934
+ async createCollectionShare(data) {
935
+ return this.request("POST", "/api/collection_shares", { body: { collection_share: data } });
936
+ }
937
+ async deleteCollectionShare(id) {
938
+ await this.request("DELETE", `/api/collection_shares/${id}`);
939
+ }
940
+ async getCollectionSharesTree() {
941
+ return this.request("GET", "/api/collection_shares/tree");
942
+ }
943
+ // ============================================================================
944
+ // Access Requests
945
+ // ============================================================================
946
+ async listAccessRequests(params) {
947
+ return this.request("GET", "/api/access_requests", { params });
948
+ }
949
+ async getAccessRequest(id) {
950
+ return this.request("GET", `/api/access_requests/${id}`);
951
+ }
952
+ async createAccessRequest(data) {
953
+ return this.request("POST", "/api/access_requests", { body: { access_request: data } });
954
+ }
955
+ async updateAccessRequest(id, data) {
956
+ return this.request("PUT", `/api/access_requests/${id}`, { body: { access_request: data } });
957
+ }
958
+ async deleteAccessRequest(id) {
959
+ await this.request("DELETE", `/api/access_requests/${id}`);
960
+ }
961
+ async submitAccessRequest(id) {
962
+ return this.request("POST", `/api/access_requests/${id}/submit`);
963
+ }
964
+ async findAccessRequest(params) {
965
+ return this.request("GET", "/api/access_requests/find", { params });
966
+ }
967
+ async getAccessRequestsTree() {
968
+ return this.request("GET", "/api/access_requests/tree");
969
+ }
970
+ // ============================================================================
971
+ // Uploads
972
+ // ============================================================================
973
+ async listUploads(params) {
974
+ return this.request("GET", "/api/uploads", { params });
975
+ }
976
+ async createUpload() {
977
+ return this.request("POST", "/api/uploads");
978
+ }
979
+ async getUploadAssets(guid, params) {
980
+ return this.request("GET", `/api/uploads/${guid}/assets`, { params });
981
+ }
982
+ async addAssetsToUpload(guid, assetIds) {
983
+ await this.request("POST", `/api/uploads/${guid}/assets`, { body: { asset_ids: assetIds } });
984
+ }
985
+ async setUploadDone(id) {
986
+ return this.request("POST", `/api/uploads/${id}/set_done`);
987
+ }
988
+ async canUpload() {
989
+ return this.request("GET", "/api/can_upload");
990
+ }
991
+ // ============================================================================
992
+ // Contributions
993
+ // ============================================================================
994
+ async listContributions(params) {
995
+ return this.request("GET", "/api/contributions", { params });
996
+ }
997
+ async getContribution(id) {
998
+ return this.request("GET", `/api/contributions/${id}`);
999
+ }
1000
+ async createContribution(data) {
1001
+ return this.request("POST", "/api/contributions", { body: { contribution: data } });
1002
+ }
1003
+ async updateContribution(id, data) {
1004
+ return this.request("PUT", `/api/contributions/${id}`, { body: { contribution: data } });
1005
+ }
1006
+ async deleteContribution(id) {
1007
+ await this.request("DELETE", `/api/contributions/${id}`);
1008
+ }
1009
+ async findContribution(params) {
1010
+ return this.request("GET", "/api/contributions/find", { params });
1011
+ }
1012
+ async getFeaturedContributions() {
1013
+ return this.request("GET", "/api/contributions/featured");
1014
+ }
1015
+ async getContributionUploads(contributionId, params) {
1016
+ return this.request("GET", `/api/contributions/${contributionId}/uploads`, { params });
1017
+ }
1018
+ async getContributionGroup() {
1019
+ return this.request("GET", "/api/contributions/group");
1020
+ }
1021
+ async getContributionLightbox() {
1022
+ return this.request("GET", "/api/contributions/lightbox");
1023
+ }
1024
+ async getContributionLink() {
1025
+ return this.request("GET", "/api/contributions/link");
1026
+ }
1027
+ // ============================================================================
1028
+ // Bulk Jobs
1029
+ // ============================================================================
1030
+ async listBulkJobs(params) {
1031
+ return this.request("GET", "/api/bulk_jobs", { params });
1032
+ }
1033
+ async getBulkJob(id) {
1034
+ return this.request("GET", `/api/bulk_jobs/${id}`);
1035
+ }
1036
+ async createBulkJob(data) {
1037
+ return this.request("POST", "/api/bulk_jobs", { body: { bulk_job: data } });
1038
+ }
1039
+ async getBulkJobAssets(id, params) {
1040
+ return this.request("GET", `/api/bulk_jobs/${id}/assets`, { params });
1041
+ }
1042
+ async cancelBulkJob(id) {
1043
+ return this.request("POST", `/api/bulk_jobs/${id}/cancel`);
1044
+ }
1045
+ async getBulkJobQueuePosition(id) {
1046
+ return this.request("GET", `/api/bulk_jobs/${id}/queue_position`);
1047
+ }
1048
+ async getProcessingBulkJobs() {
1049
+ return this.request("GET", "/api/bulk_jobs/processing");
1050
+ }
1051
+ async previewCaiBulkJob(data) {
1052
+ return this.request("POST", "/api/bulk_jobs/cai_preview", { body: data });
1053
+ }
1054
+ // ============================================================================
1055
+ // Custom Meta Fields
1056
+ // ============================================================================
1057
+ async listCustomMetaFields(params) {
1058
+ return this.request("GET", "/api/custom_meta_fields", { params });
1059
+ }
1060
+ async getCustomMetaField(id) {
1061
+ return this.request("GET", `/api/custom_meta_fields/${id}`);
1062
+ }
1063
+ async createCustomMetaField(data) {
1064
+ return this.request("POST", "/api/custom_meta_fields", { body: { custom_meta_field: data } });
1065
+ }
1066
+ async updateCustomMetaField(id, data) {
1067
+ return this.request("PUT", `/api/custom_meta_fields/${id}`, { body: { custom_meta_field: data } });
1068
+ }
1069
+ async deleteCustomMetaField(id) {
1070
+ await this.request("DELETE", `/api/custom_meta_fields/${id}`);
1071
+ }
1072
+ async exportCustomMetaField(id) {
1073
+ return this.request("GET", `/api/custom_meta_fields/${id}/export`);
1074
+ }
1075
+ async importCustomMetaFields(data) {
1076
+ return this.request("POST", "/api/custom_meta_fields/import", { body: data });
1077
+ }
1078
+ async getAccessRequestCustomMetaFields() {
1079
+ return this.request("GET", "/api/custom_meta_fields/access_requests");
1080
+ }
1081
+ // ============================================================================
1082
+ // Workflows
1083
+ // ============================================================================
1084
+ async listWorkflows(params) {
1085
+ return this.request("GET", "/api/workflows", { params });
1086
+ }
1087
+ async getWorkflow(id) {
1088
+ return this.request("GET", `/api/workflows/${id}`);
1089
+ }
1090
+ async createWorkflow(data) {
1091
+ return this.request("POST", "/api/workflows", { body: { workflow: data } });
1092
+ }
1093
+ async updateWorkflow(id, data) {
1094
+ return this.request("PUT", `/api/workflows/${id}`, { body: { workflow: data } });
1095
+ }
1096
+ async deleteWorkflow(id) {
1097
+ await this.request("DELETE", `/api/workflows/${id}`);
1098
+ }
1099
+ // ============================================================================
1100
+ // Workflow Steps
1101
+ // ============================================================================
1102
+ async listWorkflowSteps(params) {
1103
+ return this.request("GET", "/api/workflow_steps", { params });
1104
+ }
1105
+ async getWorkflowStep(id) {
1106
+ return this.request("GET", `/api/workflow_steps/${id}`);
1107
+ }
1108
+ async createWorkflowStep(data) {
1109
+ return this.request("POST", "/api/workflow_steps", { body: { workflow_step: data } });
1110
+ }
1111
+ async updateWorkflowStep(id, data) {
1112
+ return this.request("PUT", `/api/workflow_steps/${id}`, { body: { workflow_step: data } });
1113
+ }
1114
+ async deleteWorkflowStep(id) {
1115
+ await this.request("DELETE", `/api/workflow_steps/${id}`);
1116
+ }
1117
+ async approveWorkflowStep(id) {
1118
+ return this.request("POST", `/api/workflow_steps/${id}/approve`);
1119
+ }
1120
+ // ============================================================================
1121
+ // Comments
1122
+ // ============================================================================
1123
+ async listComments(params) {
1124
+ return this.request("GET", "/api/comments", { params });
1125
+ }
1126
+ async getComment(id) {
1127
+ return this.request("GET", `/api/comments/${id}`);
1128
+ }
1129
+ async createComment(data) {
1130
+ return this.request("POST", "/api/comments", { body: { comment: data } });
1131
+ }
1132
+ async updateComment(id, data) {
1133
+ return this.request("PUT", `/api/comments/${id}`, { body: { comment: data } });
1134
+ }
1135
+ async deleteComment(id) {
1136
+ await this.request("DELETE", `/api/comments/${id}`);
1137
+ }
1138
+ // ============================================================================
1139
+ // Notifications
1140
+ // ============================================================================
1141
+ async listNotifications(params) {
1142
+ return this.request("GET", "/api/notifications", { params });
1143
+ }
1144
+ async getNotificationCount() {
1145
+ return this.request("GET", "/api/notifications/count");
1146
+ }
1147
+ // ============================================================================
1148
+ // Downloads
1149
+ // ============================================================================
1150
+ async listDownloads(params) {
1151
+ return this.request("GET", "/api/downloads", { params });
1152
+ }
1153
+ async getDownload(token) {
1154
+ return this.request("GET", `/api/downloads/${token}`);
1155
+ }
1156
+ async createDownload(data) {
1157
+ return this.request("POST", "/api/downloads", { body: { download: data } });
1158
+ }
1159
+ // ============================================================================
1160
+ // Webhooks
1161
+ // ============================================================================
1162
+ async listWebhooks(params) {
1163
+ return this.request("GET", "/api/webhooks", { params });
1164
+ }
1165
+ async getWebhook(id) {
1166
+ return this.request("GET", `/api/webhooks/${id}`);
1167
+ }
1168
+ async createWebhook(data) {
1169
+ return this.request("POST", "/api/webhooks", { body: { webhook: data } });
1170
+ }
1171
+ async updateWebhook(id, data) {
1172
+ return this.request("PUT", `/api/webhooks/${id}`, { body: { webhook: data } });
1173
+ }
1174
+ async deleteWebhook(id) {
1175
+ await this.request("DELETE", `/api/webhooks/${id}`);
1176
+ }
1177
+ async getWebhookLogs(id, params) {
1178
+ return this.request("GET", `/api/webhooks/${id}/logs`, { params });
1179
+ }
1180
+ async testWebhook(data) {
1181
+ return this.request("POST", "/api/webhooks/test", { body: data });
1182
+ }
1183
+ async getWebhookPayload() {
1184
+ return this.request("GET", "/api/webhooks/payload");
1185
+ }
1186
+ async getWebhookResponseData() {
1187
+ return this.request("GET", "/api/webhooks/response_data");
1188
+ }
1189
+ // ============================================================================
1190
+ // User Groups
1191
+ // ============================================================================
1192
+ async listUserGroups(params) {
1193
+ return this.request("GET", "/api/user_groups", { params });
1194
+ }
1195
+ async getUserGroup(id) {
1196
+ return this.request("GET", `/api/user_groups/${id}`);
1197
+ }
1198
+ async createUserGroup(data) {
1199
+ return this.request("POST", "/api/user_groups", { body: { user_group: data } });
1200
+ }
1201
+ async updateUserGroup(id, data) {
1202
+ return this.request("PUT", `/api/user_groups/${id}`, { body: { user_group: data } });
1203
+ }
1204
+ async deleteUserGroup(id) {
1205
+ await this.request("DELETE", `/api/user_groups/${id}`);
1206
+ }
1207
+ // ============================================================================
1208
+ // Invites
1209
+ // ============================================================================
1210
+ async listInvites(params) {
1211
+ return this.request("GET", "/api/invites", { params });
1212
+ }
1213
+ async getInvite(id) {
1214
+ return this.request("GET", `/api/invites/${id}`);
1215
+ }
1216
+ async createInvite(data) {
1217
+ return this.request("POST", "/api/invites", { body: { invite: data } });
1218
+ }
1219
+ async updateInvite(id, data) {
1220
+ return this.request("PUT", `/api/invites/${id}`, { body: { invite: data } });
1221
+ }
1222
+ async deleteInvite(id) {
1223
+ await this.request("DELETE", `/api/invites/${id}`);
1224
+ }
1225
+ async resendInvite(id) {
1226
+ return this.request("POST", `/api/invites/${id}/resend`);
1227
+ }
1228
+ async findInvite(params) {
1229
+ return this.request("GET", "/api/invites/find", { params });
1230
+ }
1231
+ async checkInviteEmail(email) {
1232
+ return this.request("GET", "/api/invites/check_email", { params: { email } });
1233
+ }
1234
+ async getAvailableRoleLevels() {
1235
+ return this.request("GET", "/api/invites/available_role_levels");
1236
+ }
1237
+ // ============================================================================
1238
+ // Filter Groups
1239
+ // ============================================================================
1240
+ async listFilterGroups(params) {
1241
+ return this.request("GET", "/api/filter_groups", { params });
1242
+ }
1243
+ async getFilterGroup(id) {
1244
+ return this.request("GET", `/api/filter_groups/${id}`);
1245
+ }
1246
+ async createFilterGroup(data) {
1247
+ return this.request("POST", "/api/filter_groups", { body: { filter_group: data } });
1248
+ }
1249
+ async updateFilterGroup(id, data) {
1250
+ return this.request("PUT", `/api/filter_groups/${id}`, { body: { filter_group: data } });
1251
+ }
1252
+ async deleteFilterGroup(id) {
1253
+ await this.request("DELETE", `/api/filter_groups/${id}`);
1254
+ }
1255
+ async updateFilterGroupVisibility(id, shared) {
1256
+ return this.request("PUT", `/api/filter_groups/${id}/update_visibility`, { body: { shared } });
1257
+ }
1258
+ // ============================================================================
1259
+ // Search Queries
1260
+ // ============================================================================
1261
+ async listSearchQueries(params) {
1262
+ return this.request("GET", "/api/search_queries", { params });
1263
+ }
1264
+ async getSearchQuery(id) {
1265
+ return this.request("GET", `/api/search_queries/${id}`);
1266
+ }
1267
+ async createSearchQuery(data) {
1268
+ return this.request("POST", "/api/search_queries", { body: { search_query: data } });
1269
+ }
1270
+ async updateSearchQuery(id, data) {
1271
+ return this.request("PUT", `/api/search_queries/${id}`, { body: { search_query: data } });
1272
+ }
1273
+ async deleteSearchQuery(id) {
1274
+ await this.request("DELETE", `/api/search_queries/${id}`);
1275
+ }
1276
+ // ============================================================================
1277
+ // Crop Presets
1278
+ // ============================================================================
1279
+ async listCropPresets(params) {
1280
+ return this.request("GET", "/api/crop_presets", { params });
1281
+ }
1282
+ async getCropPreset(id) {
1283
+ return this.request("GET", `/api/crop_presets/${id}`);
1284
+ }
1285
+ async createCropPreset(data) {
1286
+ return this.request("POST", "/api/crop_presets", { body: { crop_preset: data } });
1287
+ }
1288
+ async updateCropPreset(id, data) {
1289
+ return this.request("PUT", `/api/crop_presets/${id}`, { body: { crop_preset: data } });
1290
+ }
1291
+ async deleteCropPreset(id) {
1292
+ await this.request("DELETE", `/api/crop_presets/${id}`);
1293
+ }
1294
+ async updateCropPresetPosition(id, position) {
1295
+ return this.request("PUT", "/api/crop_presets/update_position", { body: { id, position } });
1296
+ }
1297
+ // ============================================================================
1298
+ // Ingestions
1299
+ // ============================================================================
1300
+ async listIngestions(params) {
1301
+ return this.request("GET", "/api/ingestions", { params });
1302
+ }
1303
+ // ============================================================================
1304
+ // Meta Imports
1305
+ // ============================================================================
1306
+ async listMetaImports(params) {
1307
+ return this.request("GET", "/api/meta_imports", { params });
1308
+ }
1309
+ async getMetaImport(id) {
1310
+ return this.request("GET", `/api/meta_imports/${id}`);
1311
+ }
1312
+ async createMetaImport(data) {
1313
+ return this.request("POST", "/api/meta_imports", { body: { meta_import: data } });
1314
+ }
1315
+ async getMetaImportAssets(id, params) {
1316
+ return this.request("GET", `/api/meta_imports/${id}/assets`, { params });
1317
+ }
1318
+ async getMetaImportMapping(id) {
1319
+ return this.request("GET", `/api/meta_imports/${id}/mapping`);
1320
+ }
1321
+ async updateMetaImportMapping(id, mapping) {
1322
+ return this.request("PUT", `/api/meta_imports/${id}/mapping`, { body: { mapping } });
1323
+ }
1324
+ async startMetaImportProcess(id) {
1325
+ return this.request("POST", `/api/meta_imports/${id}/start_process`);
1326
+ }
1327
+ // ============================================================================
1328
+ // Personal Access Tokens
1329
+ // ============================================================================
1330
+ async listPersonalAccessTokens(params) {
1331
+ return this.request("GET", "/api/personal_access_tokens", { params });
1332
+ }
1333
+ async getPersonalAccessToken(id) {
1334
+ return this.request("GET", `/api/personal_access_tokens/${id}`);
1335
+ }
1336
+ async createPersonalAccessToken(data) {
1337
+ return this.request("POST", "/api/personal_access_tokens", { body: { personal_access_token: data } });
1338
+ }
1339
+ async deletePersonalAccessToken(id) {
1340
+ await this.request("DELETE", `/api/personal_access_tokens/${id}`);
1341
+ }
1342
+ };
1343
+
1344
+ // src/tools/shared.ts
1345
+ function successResult(data) {
1346
+ return {
1347
+ content: [
1348
+ {
1349
+ type: "text",
1350
+ text: typeof data === "string" ? data : JSON.stringify(data, null, 2)
1351
+ }
1352
+ ]
1353
+ };
1354
+ }
1355
+ function errorResult(message) {
1356
+ return {
1357
+ content: [
1358
+ {
1359
+ type: "text",
1360
+ text: message
1361
+ }
1362
+ ],
1363
+ isError: true
1364
+ };
1365
+ }
1366
+ var idParam = {
1367
+ type: ["number", "string"],
1368
+ description: "ID of the resource"
1369
+ };
1370
+ var paginationParams = {
1371
+ page: { type: "number", description: "Page number" },
1372
+ per_page: { type: "number", description: "Results per page (max 100)" }
1373
+ };
1374
+
1375
+ // src/tools/users.ts
1376
+ var userTools = {
1377
+ definitions: [
1378
+ {
1379
+ name: "whoami",
1380
+ description: "Get information about the currently authenticated user and organization",
1381
+ inputSchema: { type: "object", properties: {}, required: [] }
1382
+ },
1383
+ {
1384
+ name: "get_organization",
1385
+ description: "Get details about an organization by ID",
1386
+ inputSchema: {
1387
+ type: "object",
1388
+ properties: { id: idParam },
1389
+ required: ["id"]
1390
+ }
1391
+ },
1392
+ {
1393
+ name: "list_memberships",
1394
+ description: "List organization memberships",
1395
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
1396
+ },
1397
+ {
1398
+ name: "get_membership",
1399
+ description: "Get membership details by ID",
1400
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1401
+ },
1402
+ {
1403
+ name: "update_membership",
1404
+ description: "Update a membership",
1405
+ inputSchema: {
1406
+ type: "object",
1407
+ properties: {
1408
+ id: idParam,
1409
+ role: { type: "string", enum: ["admin", "global_content", "global_library", "global_tagger", "general", "restricted"] }
1410
+ },
1411
+ required: ["id"]
1412
+ }
1413
+ }
1414
+ ],
1415
+ handlers: {
1416
+ async whoami(args, { client: client2 }) {
1417
+ return successResult(await client2.whoami());
1418
+ },
1419
+ async get_organization(args, { client: client2 }) {
1420
+ return successResult(await client2.getOrganization(args.id));
1421
+ },
1422
+ async list_memberships(args, { client: client2 }) {
1423
+ return successResult(await client2.listMemberships(args));
1424
+ },
1425
+ async get_membership(args, { client: client2 }) {
1426
+ return successResult(await client2.getMembership(args.id));
1427
+ },
1428
+ async update_membership(args, { client: client2 }) {
1429
+ const { id, ...data } = args;
1430
+ return successResult(await client2.updateMembership(id, data));
1431
+ }
1432
+ }
1433
+ };
1434
+
1435
+ // src/tools/assets.ts
1436
+ var assetTools = {
1437
+ definitions: [
1438
+ {
1439
+ name: "search_assets",
1440
+ description: `Search for assets using filters and advanced query operators.
1441
+
1442
+ ADVANCED SEARCH QUERY SYNTAX (for the 'q' parameter):
1443
+ - Basic: Just type a term to search all fields (e.g., "dog")
1444
+ - Exclude: Use NOT or minus to exclude (e.g., "NOT dog" or "-dog")
1445
+ - Combine: Use AND, OR, NOT (e.g., "dog AND cat", "dog OR cat", "dog NOT cat")
1446
+ - Field search: Use field:value syntax (e.g., "tag_text:nature", "filename.keyword:IMG_1234.jpg")
1447
+ - Wildcards: Use * (zero or more chars) or ? (single char) (e.g., "tag_text:part*", "tag_text:?artial")
1448
+ - Existence: Use field:** to find assets with any value, NOT field:** for empty (e.g., "NOT tag_text:**" finds untagged assets)
1449
+ - Complex: Use parentheses for grouping (e.g., "(dog OR cat) AND ext:jpg")
1450
+
1451
+ COMMON SEARCH FIELDS:
1452
+ - tag_text: Keywords/tags
1453
+ - filename.keyword: Exact filename
1454
+ - description: Asset description
1455
+ - title: Asset title
1456
+ - ext: File extension
1457
+ - creator_text: Creator/photographer name
1458
+ - copyright: Copyright text
1459
+ - city, state, country: Location fields`,
1460
+ inputSchema: {
1461
+ type: "object",
1462
+ properties: {
1463
+ q: { type: "string", description: "Search query with optional advanced operators (AND, OR, NOT, field:value, wildcards)" },
1464
+ ...paginationParams,
1465
+ ids: { type: "array", items: { type: "number" }, description: "Filter by specific asset IDs" },
1466
+ guids: { type: "array", items: { type: "string" }, description: "Filter by specific asset GUIDs" },
1467
+ tags: { type: "array", items: { type: "string" }, description: "Filter by tags" },
1468
+ collection_id: { type: "number", description: "Filter by collection ID" },
1469
+ storage_folder_id: { type: "number", description: "Filter by storage folder ID" },
1470
+ lightbox_id: { type: "number", description: "Filter by lightbox ID" },
1471
+ exts: { type: "array", items: { type: "string" }, description: "Filter by file extensions" },
1472
+ rating: { type: "array", items: { type: "number" }, description: "Filter by rating range [min, max]" },
1473
+ aspect: { type: "string", enum: ["square", "portrait", "landscape", "panorama"] },
1474
+ has_people: { type: "string", enum: ["yes", "no", "untagged"] },
1475
+ has_alt_text: { type: "string", enum: ["yes", "no"] },
1476
+ gps: { type: "boolean", description: "Filter for assets with GPS data" },
1477
+ captured_at: { type: "array", items: { type: "string" }, description: "Date range [start, end] in ISO 8601" },
1478
+ created_at: { type: "array", items: { type: "string" }, description: "Date range [start, end] in ISO 8601" },
1479
+ include_totals: { type: "boolean", description: "Include aggregate counts" },
1480
+ include_renditions: { type: "boolean", description: "Include available sizes/formats" },
1481
+ include_meta: { type: "boolean", description: "Include full EXIF/IPTC metadata" }
1482
+ },
1483
+ required: []
1484
+ }
1485
+ },
1486
+ {
1487
+ name: "get_asset",
1488
+ description: "Get detailed information about a specific asset",
1489
+ inputSchema: {
1490
+ type: "object",
1491
+ properties: {
1492
+ id: idParam,
1493
+ include_renditions: { type: "boolean" },
1494
+ include_meta: { type: "boolean" }
1495
+ },
1496
+ required: ["id"]
1497
+ }
1498
+ },
1499
+ {
1500
+ name: "update_asset",
1501
+ description: "Update asset metadata",
1502
+ inputSchema: {
1503
+ type: "object",
1504
+ properties: {
1505
+ id: idParam,
1506
+ title: { type: "string" },
1507
+ description: { type: "string" },
1508
+ alt_text: { type: "string" },
1509
+ caption: { type: "string" },
1510
+ credit: { type: "string" },
1511
+ copyright: { type: "string" },
1512
+ rating: { type: "number", minimum: 0, maximum: 5 },
1513
+ headline: { type: "string" },
1514
+ city: { type: "string" },
1515
+ state: { type: "string" },
1516
+ country: { type: "string" },
1517
+ notes: { type: "string" }
1518
+ },
1519
+ required: ["id"]
1520
+ }
1521
+ },
1522
+ {
1523
+ name: "delete_asset",
1524
+ description: "Delete (trash) an asset",
1525
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1526
+ },
1527
+ {
1528
+ name: "add_tags_to_asset",
1529
+ description: "Add tags to an asset",
1530
+ inputSchema: {
1531
+ type: "object",
1532
+ properties: {
1533
+ id: idParam,
1534
+ tags: { type: "array", items: { type: "string" }, description: "Tags to add" }
1535
+ },
1536
+ required: ["id", "tags"]
1537
+ }
1538
+ },
1539
+ {
1540
+ name: "get_asset_download",
1541
+ description: "Get a download URL for an asset",
1542
+ inputSchema: {
1543
+ type: "object",
1544
+ properties: {
1545
+ id: idParam,
1546
+ rendition: { type: "string", description: "Specific rendition (original, full, medium, small)" }
1547
+ },
1548
+ required: ["id"]
1549
+ }
1550
+ },
1551
+ {
1552
+ name: "get_asset_auto_tags",
1553
+ description: "Get AI-generated auto tags for an asset",
1554
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1555
+ },
1556
+ {
1557
+ name: "get_asset_face_taggings",
1558
+ description: "Get face taggings for an asset",
1559
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1560
+ },
1561
+ {
1562
+ name: "get_asset_versions",
1563
+ description: "Get version history for an asset",
1564
+ inputSchema: { type: "object", properties: { asset_id: idParam }, required: ["asset_id"] }
1565
+ },
1566
+ {
1567
+ name: "revert_asset",
1568
+ description: "Revert an asset to a previous version",
1569
+ inputSchema: {
1570
+ type: "object",
1571
+ properties: {
1572
+ id: idParam,
1573
+ version_number: { type: "number", description: "Version number to revert to" }
1574
+ },
1575
+ required: ["id", "version_number"]
1576
+ }
1577
+ },
1578
+ {
1579
+ name: "get_asset_counts",
1580
+ description: "Get asset counts with optional filters",
1581
+ inputSchema: {
1582
+ type: "object",
1583
+ properties: {
1584
+ collection_id: { type: "number" },
1585
+ storage_folder_id: { type: "number" },
1586
+ tags: { type: "array", items: { type: "string" } }
1587
+ },
1588
+ required: []
1589
+ }
1590
+ },
1591
+ {
1592
+ name: "get_trashed_assets",
1593
+ description: "Get trashed assets",
1594
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
1595
+ },
1596
+ {
1597
+ name: "get_popular_assets",
1598
+ description: "Get popular assets",
1599
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
1600
+ }
1601
+ ],
1602
+ handlers: {
1603
+ async search_assets(args, { client: client2 }) {
1604
+ return successResult(await client2.searchAssets(args));
1605
+ },
1606
+ async get_asset(args, { client: client2 }) {
1607
+ return successResult(await client2.getAsset(args.id, {
1608
+ include_renditions: args.include_renditions,
1609
+ include_meta: args.include_meta
1610
+ }));
1611
+ },
1612
+ async update_asset(args, { client: client2 }) {
1613
+ const { id, ...data } = args;
1614
+ return successResult(await client2.updateAsset(id, data));
1615
+ },
1616
+ async delete_asset(args, { client: client2 }) {
1617
+ await client2.deleteAsset(args.id);
1618
+ return successResult({ success: true });
1619
+ },
1620
+ async add_tags_to_asset(args, { client: client2 }) {
1621
+ return successResult(await client2.addTagsToAsset(args.id, args.tags));
1622
+ },
1623
+ async get_asset_download(args, { client: client2 }) {
1624
+ return successResult(await client2.getAssetDownload(args.id, args.rendition));
1625
+ },
1626
+ async get_asset_auto_tags(args, { client: client2 }) {
1627
+ return successResult(await client2.getAssetAutoTags(args.id));
1628
+ },
1629
+ async get_asset_face_taggings(args, { client: client2 }) {
1630
+ return successResult(await client2.getAssetFaceTaggings(args.id));
1631
+ },
1632
+ async get_asset_versions(args, { client: client2 }) {
1633
+ return successResult(await client2.getAssetDataVersions(args.asset_id));
1634
+ },
1635
+ async revert_asset(args, { client: client2 }) {
1636
+ return successResult(await client2.revertAsset(args.id, args.version_number));
1637
+ },
1638
+ async get_asset_counts(args, { client: client2 }) {
1639
+ return successResult(await client2.getAssetCounts(args));
1640
+ },
1641
+ async get_trashed_assets(args, { client: client2 }) {
1642
+ return successResult(await client2.getTrashedAssets(args));
1643
+ },
1644
+ async get_popular_assets(args, { client: client2 }) {
1645
+ return successResult(await client2.getPopularAssets(args));
1646
+ }
1647
+ }
1648
+ };
1649
+
1650
+ // src/tools/groups.ts
1651
+ var groupTools = {
1652
+ definitions: [
1653
+ // Collections
1654
+ {
1655
+ name: "list_collections",
1656
+ description: "List collections in the organization",
1657
+ inputSchema: {
1658
+ type: "object",
1659
+ properties: { ...paginationParams, parent_id: { type: "number" } },
1660
+ required: []
1661
+ }
1662
+ },
1663
+ {
1664
+ name: "get_collection",
1665
+ description: "Get collection details",
1666
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1667
+ },
1668
+ {
1669
+ name: "create_collection",
1670
+ description: "Create a new collection",
1671
+ inputSchema: {
1672
+ type: "object",
1673
+ properties: {
1674
+ name: { type: "string" },
1675
+ description: { type: "string" },
1676
+ parent_id: { type: "number" }
1677
+ },
1678
+ required: ["name"]
1679
+ }
1680
+ },
1681
+ {
1682
+ name: "update_collection",
1683
+ description: "Update a collection",
1684
+ inputSchema: {
1685
+ type: "object",
1686
+ properties: {
1687
+ id: idParam,
1688
+ name: { type: "string" },
1689
+ description: { type: "string" }
1690
+ },
1691
+ required: ["id"]
1692
+ }
1693
+ },
1694
+ {
1695
+ name: "delete_collection",
1696
+ description: "Delete a collection",
1697
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1698
+ },
1699
+ {
1700
+ name: "add_asset_to_collection",
1701
+ description: "Add an asset to a collection",
1702
+ inputSchema: {
1703
+ type: "object",
1704
+ properties: { collection_id: idParam, asset_id: idParam },
1705
+ required: ["collection_id", "asset_id"]
1706
+ }
1707
+ },
1708
+ {
1709
+ name: "get_collections_tree",
1710
+ description: "Get collections hierarchy as a tree",
1711
+ inputSchema: { type: "object", properties: {}, required: [] }
1712
+ },
1713
+ // Lightboxes
1714
+ {
1715
+ name: "list_lightboxes",
1716
+ description: "List lightboxes in the organization",
1717
+ inputSchema: {
1718
+ type: "object",
1719
+ properties: { ...paginationParams, parent_id: { type: "number" } },
1720
+ required: []
1721
+ }
1722
+ },
1723
+ {
1724
+ name: "get_lightbox",
1725
+ description: "Get lightbox details",
1726
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1727
+ },
1728
+ {
1729
+ name: "create_lightbox",
1730
+ description: "Create a new lightbox",
1731
+ inputSchema: {
1732
+ type: "object",
1733
+ properties: {
1734
+ name: { type: "string" },
1735
+ description: { type: "string" },
1736
+ parent_id: { type: "number" }
1737
+ },
1738
+ required: ["name"]
1739
+ }
1740
+ },
1741
+ {
1742
+ name: "update_lightbox",
1743
+ description: "Update a lightbox",
1744
+ inputSchema: {
1745
+ type: "object",
1746
+ properties: { id: idParam, name: { type: "string" }, description: { type: "string" } },
1747
+ required: ["id"]
1748
+ }
1749
+ },
1750
+ {
1751
+ name: "delete_lightbox",
1752
+ description: "Delete a lightbox",
1753
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1754
+ },
1755
+ {
1756
+ name: "add_asset_to_lightbox",
1757
+ description: "Add an asset to a lightbox",
1758
+ inputSchema: {
1759
+ type: "object",
1760
+ properties: { lightbox_id: idParam, asset_id: idParam },
1761
+ required: ["lightbox_id", "asset_id"]
1762
+ }
1763
+ },
1764
+ {
1765
+ name: "get_lightboxes_tree",
1766
+ description: "Get lightboxes hierarchy as a tree",
1767
+ inputSchema: { type: "object", properties: {}, required: [] }
1768
+ },
1769
+ // Storage Folders
1770
+ {
1771
+ name: "list_storage_folders",
1772
+ description: "List storage folders",
1773
+ inputSchema: {
1774
+ type: "object",
1775
+ properties: { ...paginationParams, parent_id: { type: "number" } },
1776
+ required: []
1777
+ }
1778
+ },
1779
+ {
1780
+ name: "get_storage_folder",
1781
+ description: "Get storage folder details",
1782
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1783
+ },
1784
+ {
1785
+ name: "create_storage_folder",
1786
+ description: "Create a new storage folder",
1787
+ inputSchema: {
1788
+ type: "object",
1789
+ properties: { name: { type: "string" }, description: { type: "string" }, parent_id: { type: "number" } },
1790
+ required: ["name"]
1791
+ }
1792
+ },
1793
+ {
1794
+ name: "get_storage_folders_tree",
1795
+ description: "Get storage folders hierarchy as a tree",
1796
+ inputSchema: { type: "object", properties: {}, required: [] }
1797
+ }
1798
+ ],
1799
+ handlers: {
1800
+ // Collections
1801
+ async list_collections(args, { client: client2 }) {
1802
+ return successResult(await client2.listCollections(args));
1803
+ },
1804
+ async get_collection(args, { client: client2 }) {
1805
+ return successResult(await client2.getCollection(args.id));
1806
+ },
1807
+ async create_collection(args, { client: client2 }) {
1808
+ return successResult(await client2.createCollection(args));
1809
+ },
1810
+ async update_collection(args, { client: client2 }) {
1811
+ const { id, ...data } = args;
1812
+ return successResult(await client2.updateCollection(id, data));
1813
+ },
1814
+ async delete_collection(args, { client: client2 }) {
1815
+ await client2.deleteCollection(args.id);
1816
+ return successResult({ success: true });
1817
+ },
1818
+ async add_asset_to_collection(args, { client: client2 }) {
1819
+ await client2.addAssetToCollection(args.collection_id, args.asset_id);
1820
+ return successResult({ success: true });
1821
+ },
1822
+ async get_collections_tree(_args, { client: client2 }) {
1823
+ return successResult(await client2.getCollectionsTree());
1824
+ },
1825
+ // Lightboxes
1826
+ async list_lightboxes(args, { client: client2 }) {
1827
+ return successResult(await client2.listLightboxes(args));
1828
+ },
1829
+ async get_lightbox(args, { client: client2 }) {
1830
+ return successResult(await client2.getLightbox(args.id));
1831
+ },
1832
+ async create_lightbox(args, { client: client2 }) {
1833
+ return successResult(await client2.createLightbox(args));
1834
+ },
1835
+ async update_lightbox(args, { client: client2 }) {
1836
+ const { id, ...data } = args;
1837
+ return successResult(await client2.updateLightbox(id, data));
1838
+ },
1839
+ async delete_lightbox(args, { client: client2 }) {
1840
+ await client2.deleteLightbox(args.id);
1841
+ return successResult({ success: true });
1842
+ },
1843
+ async add_asset_to_lightbox(args, { client: client2 }) {
1844
+ await client2.addAssetToLightbox(args.lightbox_id, args.asset_id);
1845
+ return successResult({ success: true });
1846
+ },
1847
+ async get_lightboxes_tree(_args, { client: client2 }) {
1848
+ return successResult(await client2.getLightboxesTree());
1849
+ },
1850
+ // Storage Folders
1851
+ async list_storage_folders(args, { client: client2 }) {
1852
+ return successResult(await client2.listStorageFolders(args));
1853
+ },
1854
+ async get_storage_folder(args, { client: client2 }) {
1855
+ return successResult(await client2.getStorageFolder(args.id));
1856
+ },
1857
+ async create_storage_folder(args, { client: client2 }) {
1858
+ return successResult(await client2.createStorageFolder(args));
1859
+ },
1860
+ async get_storage_folders_tree(_args, { client: client2 }) {
1861
+ return successResult(await client2.getStorageFoldersTree());
1862
+ }
1863
+ }
1864
+ };
1865
+
1866
+ // src/tools/tags.ts
1867
+ var tagTools = {
1868
+ definitions: [
1869
+ // Tags
1870
+ {
1871
+ name: "list_tags",
1872
+ description: "List tags in the organization",
1873
+ inputSchema: {
1874
+ type: "object",
1875
+ properties: { ...paginationParams, q: { type: "string", description: "Search query" } },
1876
+ required: []
1877
+ }
1878
+ },
1879
+ {
1880
+ name: "get_tag",
1881
+ description: "Get tag details",
1882
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1883
+ },
1884
+ {
1885
+ name: "create_tag",
1886
+ description: "Create a new tag",
1887
+ inputSchema: {
1888
+ type: "object",
1889
+ properties: { name: { type: "string" }, parent_id: { type: "number" } },
1890
+ required: ["name"]
1891
+ }
1892
+ },
1893
+ {
1894
+ name: "update_tag",
1895
+ description: "Update a tag",
1896
+ inputSchema: {
1897
+ type: "object",
1898
+ properties: { id: idParam, name: { type: "string" } },
1899
+ required: ["id"]
1900
+ }
1901
+ },
1902
+ {
1903
+ name: "delete_tag",
1904
+ description: "Delete a tag",
1905
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1906
+ },
1907
+ {
1908
+ name: "merge_tags",
1909
+ description: "Merge one tag into another",
1910
+ inputSchema: {
1911
+ type: "object",
1912
+ properties: { id: idParam, target_tag_id: { type: "number" } },
1913
+ required: ["id", "target_tag_id"]
1914
+ }
1915
+ },
1916
+ // Taggings
1917
+ {
1918
+ name: "get_tagging",
1919
+ description: "Get details of a specific tagging (tag-to-asset relationship)",
1920
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1921
+ },
1922
+ // Auto Tags
1923
+ {
1924
+ name: "list_auto_tags",
1925
+ description: "List AI-generated auto tags",
1926
+ inputSchema: {
1927
+ type: "object",
1928
+ properties: { ...paginationParams, q: { type: "string" } },
1929
+ required: []
1930
+ }
1931
+ },
1932
+ // Taxonomies
1933
+ {
1934
+ name: "list_taxonomies",
1935
+ description: "List taxonomies (controlled vocabularies)",
1936
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
1937
+ },
1938
+ {
1939
+ name: "get_taxonomy",
1940
+ description: "Get taxonomy details",
1941
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
1942
+ },
1943
+ {
1944
+ name: "create_taxonomy",
1945
+ description: "Create a new taxonomy",
1946
+ inputSchema: {
1947
+ type: "object",
1948
+ properties: { name: { type: "string" }, description: { type: "string" } },
1949
+ required: ["name"]
1950
+ }
1951
+ },
1952
+ {
1953
+ name: "list_taxonomy_tags",
1954
+ description: "List tags within a taxonomy",
1955
+ inputSchema: {
1956
+ type: "object",
1957
+ properties: { taxonomy_id: idParam, ...paginationParams, parent_id: { type: "number" } },
1958
+ required: ["taxonomy_id"]
1959
+ }
1960
+ },
1961
+ {
1962
+ name: "create_taxonomy_tag",
1963
+ description: "Create a tag within a taxonomy",
1964
+ inputSchema: {
1965
+ type: "object",
1966
+ properties: { taxonomy_id: idParam, name: { type: "string" }, parent_id: { type: "number" } },
1967
+ required: ["taxonomy_id", "name"]
1968
+ }
1969
+ },
1970
+ // Creator Tags
1971
+ {
1972
+ name: "list_creator_tags",
1973
+ description: "List creator/photographer tags",
1974
+ inputSchema: {
1975
+ type: "object",
1976
+ properties: { ...paginationParams, q: { type: "string" } },
1977
+ required: []
1978
+ }
1979
+ },
1980
+ {
1981
+ name: "create_creator_tag",
1982
+ description: "Create a new creator tag",
1983
+ inputSchema: {
1984
+ type: "object",
1985
+ properties: { name: { type: "string" } },
1986
+ required: ["name"]
1987
+ }
1988
+ }
1989
+ ],
1990
+ handlers: {
1991
+ // Tags
1992
+ async list_tags(args, { client: client2 }) {
1993
+ return successResult(await client2.listTags(args));
1994
+ },
1995
+ async get_tag(args, { client: client2 }) {
1996
+ return successResult(await client2.getTag(args.id));
1997
+ },
1998
+ async create_tag(args, { client: client2 }) {
1999
+ return successResult(await client2.createTag(args));
2000
+ },
2001
+ async update_tag(args, { client: client2 }) {
2002
+ const { id, ...data } = args;
2003
+ return successResult(await client2.updateTag(id, data));
2004
+ },
2005
+ async delete_tag(args, { client: client2 }) {
2006
+ await client2.deleteTag(args.id);
2007
+ return successResult({ success: true });
2008
+ },
2009
+ async merge_tags(args, { client: client2 }) {
2010
+ await client2.mergeTagInto(args.id, args.target_tag_id);
2011
+ return successResult({ success: true });
2012
+ },
2013
+ // Taggings
2014
+ async get_tagging(args, { client: client2 }) {
2015
+ return successResult(await client2.getTagging(args.id));
2016
+ },
2017
+ // Auto Tags
2018
+ async list_auto_tags(args, { client: client2 }) {
2019
+ return successResult(await client2.listAutoTags(args));
2020
+ },
2021
+ // Taxonomies
2022
+ async list_taxonomies(args, { client: client2 }) {
2023
+ return successResult(await client2.listTaxonomies(args));
2024
+ },
2025
+ async get_taxonomy(args, { client: client2 }) {
2026
+ return successResult(await client2.getTaxonomy(args.id));
2027
+ },
2028
+ async create_taxonomy(args, { client: client2 }) {
2029
+ return successResult(await client2.createTaxonomy(args));
2030
+ },
2031
+ async list_taxonomy_tags(args, { client: client2 }) {
2032
+ return successResult(await client2.listTaxonomyTags(args.taxonomy_id, args));
2033
+ },
2034
+ async create_taxonomy_tag(args, { client: client2 }) {
2035
+ return successResult(await client2.createTaxonomyTag(args.taxonomy_id, args));
2036
+ },
2037
+ // Creator Tags
2038
+ async list_creator_tags(args, { client: client2 }) {
2039
+ return successResult(await client2.listCreatorTags(args));
2040
+ },
2041
+ async create_creator_tag(args, { client: client2 }) {
2042
+ return successResult(await client2.createCreatorTag(args));
2043
+ }
2044
+ }
2045
+ };
2046
+
2047
+ // src/tools/rights.ts
2048
+ var rightsTools = {
2049
+ definitions: [
2050
+ {
2051
+ name: "list_rights_packages",
2052
+ description: "List rights packages for managing asset usage rights",
2053
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2054
+ },
2055
+ {
2056
+ name: "get_rights_package",
2057
+ description: "Get rights package details",
2058
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2059
+ },
2060
+ {
2061
+ name: "create_rights_package",
2062
+ description: "Create a new rights package",
2063
+ inputSchema: {
2064
+ type: "object",
2065
+ properties: {
2066
+ name: { type: "string" },
2067
+ rights_class: { type: "string", enum: ["owned", "unlimited", "some", "library", "none"] },
2068
+ description: { type: "string" },
2069
+ expires: { type: "boolean" },
2070
+ expires_at: { type: "string" }
2071
+ },
2072
+ required: ["name", "rights_class"]
2073
+ }
2074
+ }
2075
+ ],
2076
+ handlers: {
2077
+ async list_rights_packages(args, { client: client2 }) {
2078
+ return successResult(await client2.listRightsPackages(args));
2079
+ },
2080
+ async get_rights_package(args, { client: client2 }) {
2081
+ return successResult(await client2.getRightsPackage(args.id));
2082
+ },
2083
+ async create_rights_package(args, { client: client2 }) {
2084
+ return successResult(await client2.createRightsPackage(args));
2085
+ }
2086
+ }
2087
+ };
2088
+
2089
+ // src/tools/sharing.ts
2090
+ var sharingTools = {
2091
+ definitions: [
2092
+ // Share Links
2093
+ {
2094
+ name: "list_share_links",
2095
+ description: "List share links",
2096
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2097
+ },
2098
+ {
2099
+ name: "get_share_link",
2100
+ description: "Get share link details",
2101
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2102
+ },
2103
+ {
2104
+ name: "create_share_link",
2105
+ description: "Create a share link for assets, collection, or lightbox",
2106
+ inputSchema: {
2107
+ type: "object",
2108
+ properties: {
2109
+ asset_ids: { type: "array", items: { type: "number" } },
2110
+ collection_id: { type: "number" },
2111
+ lightbox_id: { type: "number" },
2112
+ name: { type: "string" },
2113
+ password: { type: "string" },
2114
+ expires_at: { type: "string" }
2115
+ },
2116
+ required: []
2117
+ }
2118
+ },
2119
+ {
2120
+ name: "delete_share_link",
2121
+ description: "Delete a share link",
2122
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2123
+ },
2124
+ // Access Requests
2125
+ {
2126
+ name: "list_access_requests",
2127
+ description: "List access requests and grants",
2128
+ inputSchema: {
2129
+ type: "object",
2130
+ properties: {
2131
+ ...paginationParams,
2132
+ type: { type: "string", enum: ["grant", "request"] },
2133
+ aasm_state: { type: "string", enum: ["pending", "submitted", "finalized"] }
2134
+ },
2135
+ required: []
2136
+ }
2137
+ },
2138
+ {
2139
+ name: "get_access_request",
2140
+ description: "Get access request details",
2141
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2142
+ },
2143
+ {
2144
+ name: "submit_access_request",
2145
+ description: "Submit an access request",
2146
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2147
+ }
2148
+ ],
2149
+ handlers: {
2150
+ // Share Links
2151
+ async list_share_links(args, { client: client2 }) {
2152
+ return successResult(await client2.listShareLinks(args));
2153
+ },
2154
+ async get_share_link(args, { client: client2 }) {
2155
+ return successResult(await client2.getShareLink(args.id));
2156
+ },
2157
+ async create_share_link(args, { client: client2 }) {
2158
+ return successResult(await client2.createShareLink(args));
2159
+ },
2160
+ async delete_share_link(args, { client: client2 }) {
2161
+ await client2.deleteShareLink(args.id);
2162
+ return successResult({ success: true });
2163
+ },
2164
+ // Access Requests
2165
+ async list_access_requests(args, { client: client2 }) {
2166
+ return successResult(await client2.listAccessRequests(args));
2167
+ },
2168
+ async get_access_request(args, { client: client2 }) {
2169
+ return successResult(await client2.getAccessRequest(args.id));
2170
+ },
2171
+ async submit_access_request(args, { client: client2 }) {
2172
+ return successResult(await client2.submitAccessRequest(args.id));
2173
+ }
2174
+ }
2175
+ };
2176
+
2177
+ // src/tools/jobs.ts
2178
+ var jobTools = {
2179
+ definitions: [
2180
+ // Bulk Jobs
2181
+ {
2182
+ name: "list_bulk_jobs",
2183
+ description: "List bulk jobs",
2184
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2185
+ },
2186
+ {
2187
+ name: "get_bulk_job",
2188
+ description: "Get bulk job details and status",
2189
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2190
+ },
2191
+ {
2192
+ name: "create_bulk_job",
2193
+ description: "Create a bulk job for batch operations on assets",
2194
+ inputSchema: {
2195
+ type: "object",
2196
+ properties: {
2197
+ asset_ids: { type: "array", items: { type: "number" }, description: "Asset IDs to process" },
2198
+ action: { type: "string", description: "Bulk action (add_tags, remove_tags, add_to_collection, etc.)" },
2199
+ params: { type: "object", description: "Action parameters" }
2200
+ },
2201
+ required: ["asset_ids", "action"]
2202
+ }
2203
+ },
2204
+ {
2205
+ name: "cancel_bulk_job",
2206
+ description: "Cancel a running bulk job",
2207
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2208
+ },
2209
+ {
2210
+ name: "get_bulk_job_queue_position",
2211
+ description: "Get queue position for a bulk job",
2212
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2213
+ },
2214
+ // Meta Imports
2215
+ {
2216
+ name: "list_meta_imports",
2217
+ description: "List metadata import jobs",
2218
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2219
+ },
2220
+ {
2221
+ name: "get_meta_import",
2222
+ description: "Get metadata import job details",
2223
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2224
+ },
2225
+ // Ingestions
2226
+ {
2227
+ name: "list_ingestions",
2228
+ description: "List ingestion jobs",
2229
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2230
+ }
2231
+ ],
2232
+ handlers: {
2233
+ // Bulk Jobs
2234
+ async list_bulk_jobs(args, { client: client2 }) {
2235
+ return successResult(await client2.listBulkJobs(args));
2236
+ },
2237
+ async get_bulk_job(args, { client: client2 }) {
2238
+ return successResult(await client2.getBulkJob(args.id));
2239
+ },
2240
+ async create_bulk_job(args, { client: client2 }) {
2241
+ return successResult(await client2.createBulkJob(args));
2242
+ },
2243
+ async cancel_bulk_job(args, { client: client2 }) {
2244
+ return successResult(await client2.cancelBulkJob(args.id));
2245
+ },
2246
+ async get_bulk_job_queue_position(args, { client: client2 }) {
2247
+ return successResult(await client2.getBulkJobQueuePosition(args.id));
2248
+ },
2249
+ // Meta Imports
2250
+ async list_meta_imports(args, { client: client2 }) {
2251
+ return successResult(await client2.listMetaImports(args));
2252
+ },
2253
+ async get_meta_import(args, { client: client2 }) {
2254
+ return successResult(await client2.getMetaImport(args.id));
2255
+ },
2256
+ // Ingestions
2257
+ async list_ingestions(args, { client: client2 }) {
2258
+ return successResult(await client2.listIngestions(args));
2259
+ }
2260
+ }
2261
+ };
2262
+
2263
+ // src/tools/meta.ts
2264
+ var metaTools = {
2265
+ definitions: [
2266
+ {
2267
+ name: "list_custom_meta_fields",
2268
+ description: "List custom metadata fields",
2269
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2270
+ },
2271
+ {
2272
+ name: "get_custom_meta_field",
2273
+ description: "Get custom meta field details",
2274
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2275
+ },
2276
+ {
2277
+ name: "create_custom_meta_field",
2278
+ description: "Create a custom metadata field",
2279
+ inputSchema: {
2280
+ type: "object",
2281
+ properties: {
2282
+ name: { type: "string" },
2283
+ field_type: { type: "string", enum: ["text", "textarea", "select", "multiselect", "date", "number", "boolean"] },
2284
+ description: { type: "string" },
2285
+ required: { type: "boolean" },
2286
+ searchable: { type: "boolean" },
2287
+ filterable: { type: "boolean" },
2288
+ options: { type: "array", items: { type: "string" } },
2289
+ enable_ai: { type: "boolean" },
2290
+ ai_prompt: { type: "string" }
2291
+ },
2292
+ required: ["name", "field_type"]
2293
+ }
2294
+ }
2295
+ ],
2296
+ handlers: {
2297
+ async list_custom_meta_fields(args, { client: client2 }) {
2298
+ return successResult(await client2.listCustomMetaFields(args));
2299
+ },
2300
+ async get_custom_meta_field(args, { client: client2 }) {
2301
+ return successResult(await client2.getCustomMetaField(args.id));
2302
+ },
2303
+ async create_custom_meta_field(args, { client: client2 }) {
2304
+ return successResult(await client2.createCustomMetaField(args));
2305
+ }
2306
+ }
2307
+ };
2308
+
2309
+ // src/tools/workflows.ts
2310
+ var workflowTools = {
2311
+ definitions: [
2312
+ {
2313
+ name: "list_workflows",
2314
+ description: "List workflows",
2315
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2316
+ },
2317
+ {
2318
+ name: "get_workflow",
2319
+ description: "Get workflow details",
2320
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2321
+ },
2322
+ {
2323
+ name: "approve_workflow_step",
2324
+ description: "Approve a workflow step",
2325
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2326
+ }
2327
+ ],
2328
+ handlers: {
2329
+ async list_workflows(args, { client: client2 }) {
2330
+ return successResult(await client2.listWorkflows(args));
2331
+ },
2332
+ async get_workflow(args, { client: client2 }) {
2333
+ return successResult(await client2.getWorkflow(args.id));
2334
+ },
2335
+ async approve_workflow_step(args, { client: client2 }) {
2336
+ return successResult(await client2.approveWorkflowStep(args.id));
2337
+ }
2338
+ }
2339
+ };
2340
+
2341
+ // src/tools/social.ts
2342
+ var socialTools = {
2343
+ definitions: [
2344
+ // Comments
2345
+ {
2346
+ name: "list_comments",
2347
+ description: "List comments on a resource",
2348
+ inputSchema: {
2349
+ type: "object",
2350
+ properties: {
2351
+ commentable_type: { type: "string", enum: ["Asset", "Collection", "Lightbox"] },
2352
+ commentable_id: { type: "number" },
2353
+ ...paginationParams
2354
+ },
2355
+ required: ["commentable_type", "commentable_id"]
2356
+ }
2357
+ },
2358
+ {
2359
+ name: "create_comment",
2360
+ description: "Create a comment",
2361
+ inputSchema: {
2362
+ type: "object",
2363
+ properties: {
2364
+ body: { type: "string" },
2365
+ commentable_type: { type: "string", enum: ["Asset", "Collection", "Lightbox"] },
2366
+ commentable_id: { type: "number" },
2367
+ parent_id: { type: "number" }
2368
+ },
2369
+ required: ["body", "commentable_type", "commentable_id"]
2370
+ }
2371
+ },
2372
+ {
2373
+ name: "delete_comment",
2374
+ description: "Delete a comment",
2375
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2376
+ },
2377
+ // Notifications
2378
+ {
2379
+ name: "list_notifications",
2380
+ description: "List notifications",
2381
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2382
+ },
2383
+ {
2384
+ name: "get_notification_count",
2385
+ description: "Get unread notification count",
2386
+ inputSchema: { type: "object", properties: {}, required: [] }
2387
+ }
2388
+ ],
2389
+ handlers: {
2390
+ // Comments
2391
+ async list_comments(args, { client: client2 }) {
2392
+ return successResult(await client2.listComments(args));
2393
+ },
2394
+ async create_comment(args, { client: client2 }) {
2395
+ return successResult(await client2.createComment(args));
2396
+ },
2397
+ async delete_comment(args, { client: client2 }) {
2398
+ await client2.deleteComment(args.id);
2399
+ return successResult({ success: true });
2400
+ },
2401
+ // Notifications
2402
+ async list_notifications(args, { client: client2 }) {
2403
+ return successResult(await client2.listNotifications(args));
2404
+ },
2405
+ async get_notification_count(_args, { client: client2 }) {
2406
+ return successResult(await client2.getNotificationCount());
2407
+ }
2408
+ }
2409
+ };
2410
+
2411
+ // src/tools/downloads.ts
2412
+ var downloadTools = {
2413
+ definitions: [
2414
+ {
2415
+ name: "create_download",
2416
+ description: "Create a batch download for multiple assets",
2417
+ inputSchema: {
2418
+ type: "object",
2419
+ properties: {
2420
+ asset_ids: { type: "array", items: { type: "number" } },
2421
+ rendition: { type: "string" }
2422
+ },
2423
+ required: ["asset_ids"]
2424
+ }
2425
+ },
2426
+ {
2427
+ name: "get_download",
2428
+ description: "Get download status and URL",
2429
+ inputSchema: { type: "object", properties: { token: { type: "string" } }, required: ["token"] }
2430
+ }
2431
+ ],
2432
+ handlers: {
2433
+ async create_download(args, { client: client2 }) {
2434
+ return successResult(await client2.createDownload(args));
2435
+ },
2436
+ async get_download(args, { client: client2 }) {
2437
+ return successResult(await client2.getDownload(args.token));
2438
+ }
2439
+ }
2440
+ };
2441
+
2442
+ // src/tools/webhooks.ts
2443
+ var webhookTools = {
2444
+ definitions: [
2445
+ {
2446
+ name: "list_webhooks",
2447
+ description: "List webhooks",
2448
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2449
+ },
2450
+ {
2451
+ name: "get_webhook",
2452
+ description: "Get webhook details",
2453
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2454
+ },
2455
+ {
2456
+ name: "create_webhook",
2457
+ description: "Create a webhook",
2458
+ inputSchema: {
2459
+ type: "object",
2460
+ properties: {
2461
+ name: { type: "string" },
2462
+ url: { type: "string" },
2463
+ events: { type: "array", items: { type: "string" } }
2464
+ },
2465
+ required: ["name", "url", "events"]
2466
+ }
2467
+ },
2468
+ {
2469
+ name: "delete_webhook",
2470
+ description: "Delete a webhook",
2471
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2472
+ },
2473
+ {
2474
+ name: "get_webhook_logs",
2475
+ description: "Get webhook delivery logs",
2476
+ inputSchema: { type: "object", properties: { id: idParam, ...paginationParams }, required: ["id"] }
2477
+ }
2478
+ ],
2479
+ handlers: {
2480
+ async list_webhooks(args, { client: client2 }) {
2481
+ return successResult(await client2.listWebhooks(args));
2482
+ },
2483
+ async get_webhook(args, { client: client2 }) {
2484
+ return successResult(await client2.getWebhook(args.id));
2485
+ },
2486
+ async create_webhook(args, { client: client2 }) {
2487
+ return successResult(await client2.createWebhook(args));
2488
+ },
2489
+ async delete_webhook(args, { client: client2 }) {
2490
+ await client2.deleteWebhook(args.id);
2491
+ return successResult({ success: true });
2492
+ },
2493
+ async get_webhook_logs(args, { client: client2 }) {
2494
+ return successResult(await client2.getWebhookLogs(args.id, args));
2495
+ }
2496
+ }
2497
+ };
2498
+
2499
+ // src/tools/admin.ts
2500
+ var adminTools = {
2501
+ definitions: [
2502
+ // User Groups
2503
+ {
2504
+ name: "list_user_groups",
2505
+ description: "List user groups",
2506
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2507
+ },
2508
+ {
2509
+ name: "create_user_group",
2510
+ description: "Create a user group",
2511
+ inputSchema: {
2512
+ type: "object",
2513
+ properties: { name: { type: "string" }, description: { type: "string" } },
2514
+ required: ["name"]
2515
+ }
2516
+ },
2517
+ // Invites
2518
+ {
2519
+ name: "list_invites",
2520
+ description: "List pending invites",
2521
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2522
+ },
2523
+ {
2524
+ name: "create_invite",
2525
+ description: "Invite a user to the organization",
2526
+ inputSchema: {
2527
+ type: "object",
2528
+ properties: {
2529
+ email: { type: "string" },
2530
+ role: { type: "string", enum: ["admin", "global_content", "global_library", "global_tagger", "general", "restricted"] }
2531
+ },
2532
+ required: ["email", "role"]
2533
+ }
2534
+ },
2535
+ {
2536
+ name: "update_invite",
2537
+ description: "Update an invite (change email or role)",
2538
+ inputSchema: {
2539
+ type: "object",
2540
+ properties: {
2541
+ id: idParam,
2542
+ email: { type: "string" },
2543
+ role: { type: "string", enum: ["admin", "global_content", "global_library", "global_tagger", "general", "restricted"] }
2544
+ },
2545
+ required: ["id"]
2546
+ }
2547
+ },
2548
+ {
2549
+ name: "resend_invite",
2550
+ description: "Resend an invite email",
2551
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2552
+ },
2553
+ // Filter Groups
2554
+ {
2555
+ name: "list_filter_groups",
2556
+ description: "List saved filter groups",
2557
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2558
+ },
2559
+ {
2560
+ name: "create_filter_group",
2561
+ description: "Save a filter group",
2562
+ inputSchema: {
2563
+ type: "object",
2564
+ properties: {
2565
+ name: { type: "string" },
2566
+ filters: { type: "object", description: "Filter parameters to save" }
2567
+ },
2568
+ required: ["name", "filters"]
2569
+ }
2570
+ },
2571
+ // Search Queries
2572
+ {
2573
+ name: "list_search_queries",
2574
+ description: "List saved search queries",
2575
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2576
+ },
2577
+ {
2578
+ name: "create_search_query",
2579
+ description: "Save a search query",
2580
+ inputSchema: {
2581
+ type: "object",
2582
+ properties: {
2583
+ name: { type: "string" },
2584
+ query: { type: "string" },
2585
+ filters: { type: "object" }
2586
+ },
2587
+ required: ["name", "query"]
2588
+ }
2589
+ },
2590
+ // Crop Presets
2591
+ {
2592
+ name: "list_crop_presets",
2593
+ description: "List crop presets",
2594
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2595
+ },
2596
+ {
2597
+ name: "create_crop_preset",
2598
+ description: "Create a crop preset",
2599
+ inputSchema: {
2600
+ type: "object",
2601
+ properties: {
2602
+ name: { type: "string" },
2603
+ width: { type: "number" },
2604
+ height: { type: "number" }
2605
+ },
2606
+ required: ["name", "width", "height"]
2607
+ }
2608
+ },
2609
+ // Uploads
2610
+ {
2611
+ name: "can_upload",
2612
+ description: "Check if uploads are allowed (storage quota)",
2613
+ inputSchema: { type: "object", properties: {}, required: [] }
2614
+ },
2615
+ {
2616
+ name: "list_uploads",
2617
+ description: "List upload sessions",
2618
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2619
+ },
2620
+ {
2621
+ name: "add_assets_to_upload",
2622
+ description: "Add assets to an upload session",
2623
+ inputSchema: {
2624
+ type: "object",
2625
+ properties: {
2626
+ guid: { type: "string", description: "Upload session GUID" },
2627
+ asset_ids: { type: "array", items: { type: "number" }, description: "Asset IDs to add" }
2628
+ },
2629
+ required: ["guid", "asset_ids"]
2630
+ }
2631
+ },
2632
+ // Contributions
2633
+ {
2634
+ name: "list_contributions",
2635
+ description: "List contribution portals",
2636
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2637
+ },
2638
+ {
2639
+ name: "get_contribution",
2640
+ description: "Get contribution details",
2641
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2642
+ },
2643
+ // Personal Access Tokens
2644
+ {
2645
+ name: "list_personal_access_tokens",
2646
+ description: "List personal access tokens",
2647
+ inputSchema: { type: "object", properties: { ...paginationParams }, required: [] }
2648
+ },
2649
+ {
2650
+ name: "create_personal_access_token",
2651
+ description: "Create a personal access token",
2652
+ inputSchema: {
2653
+ type: "object",
2654
+ properties: {
2655
+ name: { type: "string" },
2656
+ scopes: { type: "array", items: { type: "string" } }
2657
+ },
2658
+ required: ["name"]
2659
+ }
2660
+ },
2661
+ {
2662
+ name: "delete_personal_access_token",
2663
+ description: "Delete a personal access token",
2664
+ inputSchema: { type: "object", properties: { id: idParam }, required: ["id"] }
2665
+ }
2666
+ ],
2667
+ handlers: {
2668
+ // User Groups
2669
+ async list_user_groups(args, { client: client2 }) {
2670
+ return successResult(await client2.listUserGroups(args));
2671
+ },
2672
+ async create_user_group(args, { client: client2 }) {
2673
+ return successResult(await client2.createUserGroup(args));
2674
+ },
2675
+ // Invites
2676
+ async list_invites(args, { client: client2 }) {
2677
+ return successResult(await client2.listInvites(args));
2678
+ },
2679
+ async create_invite(args, { client: client2 }) {
2680
+ return successResult(await client2.createInvite(args));
2681
+ },
2682
+ async update_invite(args, { client: client2 }) {
2683
+ const { id, ...data } = args;
2684
+ return successResult(await client2.updateInvite(id, data));
2685
+ },
2686
+ async resend_invite(args, { client: client2 }) {
2687
+ return successResult(await client2.resendInvite(args.id));
2688
+ },
2689
+ // Filter Groups
2690
+ async list_filter_groups(args, { client: client2 }) {
2691
+ return successResult(await client2.listFilterGroups(args));
2692
+ },
2693
+ async create_filter_group(args, { client: client2 }) {
2694
+ return successResult(await client2.createFilterGroup(args));
2695
+ },
2696
+ // Search Queries
2697
+ async list_search_queries(args, { client: client2 }) {
2698
+ return successResult(await client2.listSearchQueries(args));
2699
+ },
2700
+ async create_search_query(args, { client: client2 }) {
2701
+ return successResult(await client2.createSearchQuery(args));
2702
+ },
2703
+ // Crop Presets
2704
+ async list_crop_presets(args, { client: client2 }) {
2705
+ return successResult(await client2.listCropPresets(args));
2706
+ },
2707
+ async create_crop_preset(args, { client: client2 }) {
2708
+ return successResult(await client2.createCropPreset(args));
2709
+ },
2710
+ // Uploads
2711
+ async can_upload(_args, { client: client2 }) {
2712
+ return successResult(await client2.canUpload());
2713
+ },
2714
+ async list_uploads(args, { client: client2 }) {
2715
+ return successResult(await client2.listUploads(args));
2716
+ },
2717
+ async add_assets_to_upload(args, { client: client2 }) {
2718
+ await client2.addAssetsToUpload(args.guid, args.asset_ids);
2719
+ return successResult({ success: true });
2720
+ },
2721
+ // Contributions
2722
+ async list_contributions(args, { client: client2 }) {
2723
+ return successResult(await client2.listContributions(args));
2724
+ },
2725
+ async get_contribution(args, { client: client2 }) {
2726
+ return successResult(await client2.getContribution(args.id));
2727
+ },
2728
+ // Personal Access Tokens
2729
+ async list_personal_access_tokens(args, { client: client2 }) {
2730
+ return successResult(await client2.listPersonalAccessTokens(args));
2731
+ },
2732
+ async create_personal_access_token(args, { client: client2 }) {
2733
+ return successResult(await client2.createPersonalAccessToken(args));
2734
+ },
2735
+ async delete_personal_access_token(args, { client: client2 }) {
2736
+ await client2.deletePersonalAccessToken(args.id);
2737
+ return successResult({ success: true });
2738
+ }
2739
+ }
2740
+ };
2741
+
2742
+ // src/tools/index.ts
2743
+ var allToolModules = [
2744
+ userTools,
2745
+ assetTools,
2746
+ groupTools,
2747
+ tagTools,
2748
+ rightsTools,
2749
+ sharingTools,
2750
+ jobTools,
2751
+ metaTools,
2752
+ workflowTools,
2753
+ socialTools,
2754
+ downloadTools,
2755
+ webhookTools,
2756
+ adminTools
2757
+ ];
2758
+ var toolDefinitions = allToolModules.flatMap((m) => m.definitions);
2759
+ var allHandlers = {};
2760
+ for (const module of allToolModules) {
2761
+ Object.assign(allHandlers, module.handlers);
2762
+ }
2763
+ async function handleTool(name, args, context) {
2764
+ const handler = allHandlers[name];
2765
+ if (!handler) {
2766
+ return errorResult(`Unknown tool: ${name}`);
2767
+ }
2768
+ try {
2769
+ return await handler(args, context);
2770
+ } catch (error) {
2771
+ const message = error instanceof Error ? error.message : "Unknown error occurred";
2772
+ return errorResult(message);
2773
+ }
2774
+ }
2775
+
2776
+ // src/resources/index.ts
2777
+ var resourceTemplates = [
2778
+ {
2779
+ uriTemplate: "mediagraph://asset/{id}",
2780
+ name: "Mediagraph Asset",
2781
+ description: "Get details about a specific asset by ID or GUID",
2782
+ mimeType: "application/json"
2783
+ },
2784
+ {
2785
+ uriTemplate: "mediagraph://collection/{id}",
2786
+ name: "Mediagraph Collection",
2787
+ description: "Get details about a specific collection",
2788
+ mimeType: "application/json"
2789
+ },
2790
+ {
2791
+ uriTemplate: "mediagraph://lightbox/{id}",
2792
+ name: "Mediagraph Lightbox",
2793
+ description: "Get details about a specific lightbox",
2794
+ mimeType: "application/json"
2795
+ },
2796
+ {
2797
+ uriTemplate: "mediagraph://search",
2798
+ name: "Mediagraph Search",
2799
+ description: "Search for assets with query parameters",
2800
+ mimeType: "application/json"
2801
+ }
2802
+ ];
2803
+ function parseUri(uri) {
2804
+ const url = new URL(uri);
2805
+ const pathParts = url.pathname.split("/").filter(Boolean);
2806
+ if (pathParts.length === 0) {
2807
+ throw new Error("Invalid resource URI");
2808
+ }
2809
+ const type = pathParts[0];
2810
+ const id = pathParts[1];
2811
+ const query = url.searchParams;
2812
+ return { type, id, query };
2813
+ }
2814
+ async function readResource(uri, context) {
2815
+ const { client: client2 } = context;
2816
+ const { type, id, query } = parseUri(uri);
2817
+ try {
2818
+ switch (type) {
2819
+ case "asset": {
2820
+ if (!id) {
2821
+ throw new Error("Asset ID is required");
2822
+ }
2823
+ const asset = await client2.getAsset(id, {
2824
+ include_renditions: true,
2825
+ include_meta: true
2826
+ });
2827
+ return {
2828
+ uri,
2829
+ mimeType: "application/json",
2830
+ text: JSON.stringify(asset, null, 2)
2831
+ };
2832
+ }
2833
+ case "collection": {
2834
+ if (!id) {
2835
+ throw new Error("Collection ID is required");
2836
+ }
2837
+ const collection = await client2.getCollection(id);
2838
+ const assets = await client2.searchAssets({
2839
+ collection_id: parseInt(id, 10),
2840
+ per_page: 50
2841
+ });
2842
+ return {
2843
+ uri,
2844
+ mimeType: "application/json",
2845
+ text: JSON.stringify({ ...collection, assets: assets.assets }, null, 2)
2846
+ };
2847
+ }
2848
+ case "lightbox": {
2849
+ if (!id) {
2850
+ throw new Error("Lightbox ID is required");
2851
+ }
2852
+ const lightbox = await client2.getLightbox(id);
2853
+ const assets = await client2.searchAssets({
2854
+ lightbox_id: parseInt(id, 10),
2855
+ per_page: 50
2856
+ });
2857
+ return {
2858
+ uri,
2859
+ mimeType: "application/json",
2860
+ text: JSON.stringify({ ...lightbox, assets: assets.assets }, null, 2)
2861
+ };
2862
+ }
2863
+ case "search": {
2864
+ const searchParams = {
2865
+ q: query?.get("q") || void 0,
2866
+ page: query?.has("page") ? parseInt(query.get("page"), 10) : void 0,
2867
+ per_page: query?.has("per_page") ? parseInt(query.get("per_page"), 10) : 25,
2868
+ tags: query?.getAll("tags") || void 0,
2869
+ collection_id: query?.has("collection_id") ? parseInt(query.get("collection_id"), 10) : void 0,
2870
+ storage_folder_id: query?.has("storage_folder_id") ? parseInt(query.get("storage_folder_id"), 10) : void 0
2871
+ };
2872
+ const results = await client2.searchAssets(searchParams);
2873
+ return {
2874
+ uri,
2875
+ mimeType: "application/json",
2876
+ text: JSON.stringify(results, null, 2)
2877
+ };
2878
+ }
2879
+ default:
2880
+ throw new Error(`Unknown resource type: ${type}`);
2881
+ }
2882
+ } catch (error) {
2883
+ const message = error instanceof Error ? error.message : "Unknown error";
2884
+ return {
2885
+ uri,
2886
+ mimeType: "text/plain",
2887
+ text: `Error reading resource: ${message}`
2888
+ };
2889
+ }
2890
+ }
2891
+ async function listResources(context) {
2892
+ const resources = [];
2893
+ try {
2894
+ const recentAssets = await context.client.searchAssets({ per_page: 10 });
2895
+ for (const asset of recentAssets.assets) {
2896
+ resources.push({
2897
+ uri: `mediagraph://asset/${asset.guid}`,
2898
+ name: `Asset: ${asset.filename}`,
2899
+ description: asset.title || asset.description || `${asset.file_type} file`,
2900
+ mimeType: "application/json"
2901
+ });
2902
+ }
2903
+ const collections = await context.client.listCollections({ per_page: 10 });
2904
+ for (const collection of collections) {
2905
+ resources.push({
2906
+ uri: `mediagraph://collection/${collection.id}`,
2907
+ name: `Collection: ${collection.name}`,
2908
+ description: collection.description || `Collection with ${collection.visible_assets_count || 0} assets`,
2909
+ mimeType: "application/json"
2910
+ });
2911
+ }
2912
+ const lightboxes = await context.client.listLightboxes({ per_page: 10 });
2913
+ for (const lightbox of lightboxes) {
2914
+ resources.push({
2915
+ uri: `mediagraph://lightbox/${lightbox.id}`,
2916
+ name: `Lightbox: ${lightbox.name}`,
2917
+ description: lightbox.description || `Lightbox with ${lightbox.visible_assets_count || 0} assets`,
2918
+ mimeType: "application/json"
2919
+ });
2920
+ }
2921
+ } catch (error) {
2922
+ console.error("Error listing resources:", error);
2923
+ }
2924
+ return resources;
2925
+ }
2926
+
2927
+ // src/index.ts
2928
+ var config = {
2929
+ clientId: process.env.MEDIAGRAPH_CLIENT_ID || "",
2930
+ clientSecret: process.env.MEDIAGRAPH_CLIENT_SECRET,
2931
+ apiUrl: process.env.MEDIAGRAPH_API_URL || "https://api.mediagraph.io",
2932
+ oauthUrl: process.env.MEDIAGRAPH_OAUTH_URL || "https://mediagraph.io",
2933
+ redirectPort: parseInt(process.env.MEDIAGRAPH_REDIRECT_PORT || "52584", 10)
2934
+ };
2935
+ var tokenStore = new TokenStore();
2936
+ var oauthHandler = new OAuthHandler({
2937
+ clientId: config.clientId,
2938
+ clientSecret: config.clientSecret,
2939
+ oauthUrl: config.oauthUrl,
2940
+ redirectPort: config.redirectPort
2941
+ });
2942
+ var currentTokens = null;
2943
+ async function getAccessToken() {
2944
+ if (currentTokens && Date.now() < currentTokens.expires_at - 3e5) {
2945
+ return currentTokens.access_token;
2946
+ }
2947
+ const stored = tokenStore.load();
2948
+ if (stored?.tokens) {
2949
+ if (Date.now() < stored.tokens.expires_at - 3e5) {
2950
+ currentTokens = stored.tokens;
2951
+ return currentTokens.access_token;
2952
+ }
2953
+ if (stored.tokens.refresh_token) {
2954
+ try {
2955
+ const newTokens = await oauthHandler.refreshToken(stored.tokens.refresh_token);
2956
+ currentTokens = newTokens;
2957
+ tokenStore.save({
2958
+ ...stored,
2959
+ tokens: newTokens
2960
+ });
2961
+ return newTokens.access_token;
2962
+ } catch (error) {
2963
+ console.error("Failed to refresh token:", error);
2964
+ }
2965
+ }
2966
+ }
2967
+ return null;
2968
+ }
2969
+ var client = new MediagraphClient({
2970
+ apiUrl: config.apiUrl,
2971
+ getAccessToken
2972
+ });
2973
+ var toolContext = { client };
2974
+ var resourceContext = { client };
2975
+ var server = new Server(
2976
+ {
2977
+ name: "mediagraph-mcp",
2978
+ version: "1.0.0"
2979
+ },
2980
+ {
2981
+ capabilities: {
2982
+ tools: {},
2983
+ resources: {}
2984
+ }
2985
+ }
2986
+ );
2987
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
2988
+ return {
2989
+ tools: toolDefinitions
2990
+ };
2991
+ });
2992
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2993
+ const { name, arguments: args } = request.params;
2994
+ const token = await getAccessToken();
2995
+ if (!token) {
2996
+ return {
2997
+ content: [
2998
+ {
2999
+ type: "text",
3000
+ text: `Not authenticated with Mediagraph. Please run the authorization flow first.
3001
+
3002
+ To authorize:
3003
+ 1. Run: npx @mediagraph/mcp authorize
3004
+ 2. Complete the OAuth flow in your browser
3005
+ 3. Return here and try again
3006
+
3007
+ Or set your credentials via environment variables:
3008
+ - MEDIAGRAPH_CLIENT_ID (required)
3009
+ - MEDIAGRAPH_CLIENT_SECRET (optional, for confidential clients)
3010
+ `
3011
+ }
3012
+ ],
3013
+ isError: true
3014
+ };
3015
+ }
3016
+ const result = await handleTool(name, args || {}, toolContext);
3017
+ return {
3018
+ content: result.content,
3019
+ isError: result.isError
3020
+ };
3021
+ });
3022
+ server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
3023
+ return {
3024
+ resourceTemplates
3025
+ };
3026
+ });
3027
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
3028
+ const token = await getAccessToken();
3029
+ if (!token) {
3030
+ return { resources: [] };
3031
+ }
3032
+ const resources = await listResources(resourceContext);
3033
+ return { resources };
3034
+ });
3035
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
3036
+ const { uri } = request.params;
3037
+ const token = await getAccessToken();
3038
+ if (!token) {
3039
+ return {
3040
+ contents: [
3041
+ {
3042
+ uri,
3043
+ mimeType: "text/plain",
3044
+ text: "Not authenticated with Mediagraph. Please authorize first."
3045
+ }
3046
+ ]
3047
+ };
3048
+ }
3049
+ const content = await readResource(uri, resourceContext);
3050
+ return {
3051
+ contents: [content]
3052
+ };
3053
+ });
3054
+ async function runAuthorize() {
3055
+ if (!config.clientId) {
3056
+ console.error("Error: MEDIAGRAPH_CLIENT_ID environment variable is required");
3057
+ console.error("");
3058
+ console.error("Get your client ID from your Mediagraph organization settings.");
3059
+ process.exit(1);
3060
+ }
3061
+ console.log("Starting Mediagraph OAuth authorization...");
3062
+ console.log("");
3063
+ const authUrl = oauthHandler.getAuthorizationUrl();
3064
+ console.log("Please open this URL in your browser:");
3065
+ console.log("");
3066
+ console.log(authUrl);
3067
+ console.log("");
3068
+ console.log("Waiting for authorization callback...");
3069
+ try {
3070
+ const { code } = await oauthHandler.waitForCallback();
3071
+ console.log("");
3072
+ console.log("Authorization code received. Exchanging for tokens...");
3073
+ const tokens = await oauthHandler.exchangeCode(code);
3074
+ console.log("Tokens received successfully.");
3075
+ currentTokens = tokens;
3076
+ const whoami = await client.whoami();
3077
+ const storedData = {
3078
+ tokens,
3079
+ organizationId: whoami.organization.id,
3080
+ organizationName: whoami.organization.name,
3081
+ userId: whoami.user.id,
3082
+ userEmail: whoami.user.email
3083
+ };
3084
+ tokenStore.save(storedData);
3085
+ console.log("");
3086
+ console.log("Successfully authorized!");
3087
+ console.log(`Organization: ${whoami.organization.name}`);
3088
+ console.log(`User: ${whoami.user.full_name} (${whoami.user.email})`);
3089
+ console.log("");
3090
+ console.log("You can now use the Mediagraph MCP server.");
3091
+ } catch (error) {
3092
+ console.error("Authorization failed:", error instanceof Error ? error.message : error);
3093
+ process.exit(1);
3094
+ }
3095
+ }
3096
+ async function runLogout() {
3097
+ const stored = tokenStore.load();
3098
+ if (stored?.tokens?.access_token) {
3099
+ try {
3100
+ await oauthHandler.revokeToken(stored.tokens.access_token);
3101
+ console.log("Token revoked successfully.");
3102
+ } catch (error) {
3103
+ console.error("Warning: Failed to revoke token:", error);
3104
+ }
3105
+ }
3106
+ tokenStore.clear();
3107
+ console.log("Logged out. Stored tokens have been cleared.");
3108
+ }
3109
+ async function runStatus() {
3110
+ const stored = tokenStore.load();
3111
+ if (!stored?.tokens) {
3112
+ console.log("Status: Not authenticated");
3113
+ console.log("");
3114
+ console.log("Run: npx @mediagraph/mcp authorize");
3115
+ return;
3116
+ }
3117
+ const isExpired = Date.now() >= stored.tokens.expires_at;
3118
+ const expiresIn = Math.round((stored.tokens.expires_at - Date.now()) / 1e3 / 60);
3119
+ console.log("Status: Authenticated");
3120
+ console.log(`Organization: ${stored.organizationName || "Unknown"}`);
3121
+ console.log(`User: ${stored.userEmail || "Unknown"}`);
3122
+ console.log(`Token Status: ${isExpired ? "Expired" : `Valid (expires in ${expiresIn} minutes)`}`);
3123
+ console.log(`Refresh Token: ${stored.tokens.refresh_token ? "Available" : "Not available"}`);
3124
+ }
3125
+ async function runServer() {
3126
+ const transport = new StdioServerTransport();
3127
+ await server.connect(transport);
3128
+ console.error("Mediagraph MCP server started");
3129
+ }
3130
+ async function main() {
3131
+ const args = process.argv.slice(2);
3132
+ const command = args[0];
3133
+ switch (command) {
3134
+ case "authorize":
3135
+ case "auth":
3136
+ case "login":
3137
+ await runAuthorize();
3138
+ break;
3139
+ case "logout":
3140
+ case "revoke":
3141
+ await runLogout();
3142
+ break;
3143
+ case "status":
3144
+ case "whoami":
3145
+ await runStatus();
3146
+ break;
3147
+ case "help":
3148
+ case "--help":
3149
+ case "-h":
3150
+ console.log(`
3151
+ Mediagraph MCP Server
3152
+
3153
+ Usage: npx @mediagraph/mcp [command]
3154
+
3155
+ Commands:
3156
+ (no command) Start the MCP server (for Claude Desktop)
3157
+ authorize Authorize with Mediagraph via OAuth
3158
+ logout Log out and revoke tokens
3159
+ status Show current authentication status
3160
+ help Show this help message
3161
+
3162
+ Environment Variables:
3163
+ MEDIAGRAPH_CLIENT_ID Your OAuth client ID (required)
3164
+ MEDIAGRAPH_CLIENT_SECRET Your OAuth client secret (optional)
3165
+ MEDIAGRAPH_API_URL API URL (default: https://api.mediagraph.io)
3166
+ MEDIAGRAPH_OAUTH_URL OAuth URL (default: https://mediagraph.io)
3167
+ MEDIAGRAPH_REDIRECT_PORT Local callback port (default: 52584)
3168
+
3169
+ Example:
3170
+ # First, authorize with Mediagraph
3171
+ MEDIAGRAPH_CLIENT_ID=your-client-id npx @mediagraph/mcp authorize
3172
+
3173
+ # Then configure Claude Desktop to use the MCP server
3174
+ # See README for configuration details
3175
+ `);
3176
+ break;
3177
+ default:
3178
+ await runServer();
3179
+ break;
3180
+ }
3181
+ }
3182
+ main().catch((error) => {
3183
+ console.error("Fatal error:", error);
3184
+ process.exit(1);
3185
+ });