@speakai/mcp-server 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.
Files changed (3) hide show
  1. package/README.md +329 -0
  2. package/dist/index.js +1688 -0
  3. package/package.json +39 -0
package/dist/index.js ADDED
@@ -0,0 +1,1688 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ createSpeakClient: () => createSpeakClient,
35
+ formatAxiosError: () => formatAxiosError,
36
+ registerAllTools: () => registerAllTools
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
40
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
41
+
42
+ // src/tools/media.ts
43
+ var media_exports = {};
44
+ __export(media_exports, {
45
+ register: () => register
46
+ });
47
+ var import_zod = require("zod");
48
+
49
+ // src/client.ts
50
+ var import_axios = __toESM(require("axios"));
51
+ var BASE_URL = process.env.SPEAK_BASE_URL ?? "https://api.speakai.co";
52
+ var API_KEY = process.env.SPEAK_API_KEY ?? "";
53
+ if (!API_KEY && !process.env.SPEAK_MCP_LIBRARY_MODE) {
54
+ process.stderr.write(
55
+ "[speak-mcp] Warning: SPEAK_API_KEY is not set. All requests will fail.\n"
56
+ );
57
+ }
58
+ var accessToken = process.env.SPEAK_ACCESS_TOKEN ?? "";
59
+ var refreshToken = "";
60
+ var tokenExpiresAt = 0;
61
+ async function authenticate() {
62
+ try {
63
+ const res = await import_axios.default.post(
64
+ `${BASE_URL}/v1/auth/accessToken`,
65
+ {},
66
+ {
67
+ headers: {
68
+ "Content-Type": "application/json",
69
+ "x-speakai-key": API_KEY
70
+ }
71
+ }
72
+ );
73
+ if (res.data?.data?.accessToken) {
74
+ accessToken = res.data.data.accessToken;
75
+ refreshToken = res.data.data.refreshToken ?? "";
76
+ tokenExpiresAt = Date.now() + 50 * 60 * 1e3;
77
+ process.stderr.write("[speak-mcp] Authenticated successfully\n");
78
+ }
79
+ } catch (err) {
80
+ process.stderr.write(
81
+ `[speak-mcp] Authentication failed: ${err instanceof Error ? err.message : err}
82
+ `
83
+ );
84
+ }
85
+ }
86
+ async function refreshAccessToken() {
87
+ if (!refreshToken) {
88
+ return authenticate();
89
+ }
90
+ try {
91
+ const res = await import_axios.default.post(
92
+ `${BASE_URL}/v1/auth/refreshToken`,
93
+ { refreshToken },
94
+ {
95
+ headers: {
96
+ "Content-Type": "application/json",
97
+ "x-speakai-key": API_KEY,
98
+ "x-access-token": accessToken
99
+ }
100
+ }
101
+ );
102
+ if (res.data?.data?.accessToken) {
103
+ accessToken = res.data.data.accessToken;
104
+ refreshToken = res.data.data.refreshToken ?? refreshToken;
105
+ tokenExpiresAt = Date.now() + 50 * 60 * 1e3;
106
+ process.stderr.write("[speak-mcp] Token refreshed\n");
107
+ }
108
+ } catch {
109
+ return authenticate();
110
+ }
111
+ }
112
+ async function ensureAuthenticated() {
113
+ if (!accessToken || Date.now() >= tokenExpiresAt) {
114
+ if (accessToken && refreshToken) {
115
+ await refreshAccessToken();
116
+ } else {
117
+ await authenticate();
118
+ }
119
+ }
120
+ }
121
+ var speakClient = import_axios.default.create({
122
+ baseURL: BASE_URL,
123
+ headers: { "Content-Type": "application/json" },
124
+ timeout: 6e4
125
+ });
126
+ speakClient.interceptors.request.use(
127
+ async (config) => {
128
+ await ensureAuthenticated();
129
+ config.headers.set("x-speakai-key", API_KEY);
130
+ config.headers.set("x-access-token", accessToken);
131
+ return config;
132
+ }
133
+ );
134
+ speakClient.interceptors.response.use(
135
+ (response) => response,
136
+ async (error) => {
137
+ const originalRequest = error.config;
138
+ if (error.response?.status === 401 && !originalRequest._retried) {
139
+ originalRequest._retried = true;
140
+ tokenExpiresAt = 0;
141
+ await ensureAuthenticated();
142
+ originalRequest.headers["x-speakai-key"] = API_KEY;
143
+ originalRequest.headers["x-access-token"] = accessToken;
144
+ return speakClient(originalRequest);
145
+ }
146
+ return Promise.reject(error);
147
+ }
148
+ );
149
+ function createSpeakClient(options) {
150
+ return import_axios.default.create({
151
+ baseURL: options.baseUrl,
152
+ headers: {
153
+ "Content-Type": "application/json",
154
+ "x-speakai-key": options.apiKey,
155
+ "x-access-token": options.accessToken
156
+ },
157
+ timeout: 6e4
158
+ });
159
+ }
160
+ function formatAxiosError(error) {
161
+ if (import_axios.default.isAxiosError(error)) {
162
+ const status = error.response?.status;
163
+ const data = error.response?.data;
164
+ const message = typeof data === "object" && data !== null ? JSON.stringify(data, null, 2) : String(data ?? error.message);
165
+ return status ? `HTTP ${status}: ${message}` : `Request failed: ${message}`;
166
+ }
167
+ if (error instanceof Error) return error.message;
168
+ return String(error);
169
+ }
170
+
171
+ // src/tools/media.ts
172
+ function register(server2, client) {
173
+ const api = client ?? speakClient;
174
+ server2.tool(
175
+ "get_signed_upload_url",
176
+ "Get a pre-signed S3 URL for direct media file upload. Use this before uploading a file directly to Speak AI storage.",
177
+ {
178
+ isVideo: import_zod.z.boolean().describe("Set true for video files, false for audio files"),
179
+ filename: import_zod.z.string().describe("Original filename including extension"),
180
+ mimeType: import_zod.z.string().describe('MIME type of the file, e.g. "audio/mp4" or "video/mp4"')
181
+ },
182
+ async ({ isVideo, filename, mimeType }) => {
183
+ try {
184
+ const result = await api.get("/v1/media/upload/signedurl", {
185
+ params: { isVideo, filename, mimeType }
186
+ });
187
+ return {
188
+ content: [
189
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
190
+ ]
191
+ };
192
+ } catch (err) {
193
+ return {
194
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
195
+ isError: true
196
+ };
197
+ }
198
+ }
199
+ );
200
+ server2.tool(
201
+ "upload_media",
202
+ "Upload a media file to Speak AI by providing a publicly accessible URL. Speak AI will fetch and process the file asynchronously.",
203
+ {
204
+ name: import_zod.z.string().describe("Display name for the media file"),
205
+ url: import_zod.z.string().describe("Publicly accessible URL of the media file (or pre-signed S3 URL)"),
206
+ mediaType: import_zod.z.enum(["audio", "video"]).describe('Type of media: "audio" or "video"'),
207
+ description: import_zod.z.string().optional().describe("Description of the media file"),
208
+ sourceLanguage: import_zod.z.string().optional().describe('BCP-47 language code for transcription, e.g. "en-US" or "he-IL"'),
209
+ tags: import_zod.z.string().optional().describe("Comma-separated tags for the media"),
210
+ folderId: import_zod.z.string().optional().describe("ID of the folder to place the media in"),
211
+ callbackUrl: import_zod.z.string().optional().describe("Webhook callback URL for this specific upload"),
212
+ fields: import_zod.z.array(
213
+ import_zod.z.object({
214
+ id: import_zod.z.string().describe("Custom field ID"),
215
+ value: import_zod.z.string().describe("Custom field value")
216
+ })
217
+ ).optional().describe("Custom field values to attach to the media")
218
+ },
219
+ async (body) => {
220
+ try {
221
+ const result = await api.post("/v1/media/upload", body);
222
+ return {
223
+ content: [
224
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
225
+ ]
226
+ };
227
+ } catch (err) {
228
+ return {
229
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
230
+ isError: true
231
+ };
232
+ }
233
+ }
234
+ );
235
+ server2.tool(
236
+ "list_media",
237
+ "List all media files in the workspace with optional filtering, pagination, and sorting.",
238
+ {
239
+ mediaType: import_zod.z.enum(["audio", "video", "text"]).optional().describe('Filter by media type: "audio", "video", or "text"'),
240
+ page: import_zod.z.number().int().positive().optional().describe("Page number for pagination (default: 1)"),
241
+ pageSize: import_zod.z.number().int().positive().optional().describe("Number of results per page (default: 20)"),
242
+ sortBy: import_zod.z.string().optional().describe('Sort field and direction, e.g. "createdAt:desc" or "name:asc"'),
243
+ filterMedia: import_zod.z.number().int().optional().describe("Filter: 0=Uploaded, 1=Assigned, 2=Both (default: 2)"),
244
+ filterName: import_zod.z.string().optional().describe("Filter media by partial name match"),
245
+ folderId: import_zod.z.string().optional().describe("Filter media within a specific folder"),
246
+ from: import_zod.z.string().optional().describe("Start date for date range filter (ISO 8601)"),
247
+ to: import_zod.z.string().optional().describe("End date for date range filter (ISO 8601)"),
248
+ isFavorites: import_zod.z.boolean().optional().describe("Filter to only show favorited media")
249
+ },
250
+ async (params) => {
251
+ try {
252
+ const result = await api.get("/v1/media", { params });
253
+ return {
254
+ content: [
255
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
256
+ ]
257
+ };
258
+ } catch (err) {
259
+ return {
260
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
261
+ isError: true
262
+ };
263
+ }
264
+ }
265
+ );
266
+ server2.tool(
267
+ "get_media_insights",
268
+ "Retrieve AI-generated insights for a media file, including topics, sentiment, action items, and summaries.",
269
+ {
270
+ mediaId: import_zod.z.string().describe("Unique identifier of the media file")
271
+ },
272
+ async ({ mediaId }) => {
273
+ try {
274
+ const result = await api.get(`/v1/media/insight/${mediaId}`);
275
+ return {
276
+ content: [
277
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
278
+ ]
279
+ };
280
+ } catch (err) {
281
+ return {
282
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
283
+ isError: true
284
+ };
285
+ }
286
+ }
287
+ );
288
+ server2.tool(
289
+ "get_transcript",
290
+ "Retrieve the full transcript for a media file, including speaker labels and timestamps.",
291
+ {
292
+ mediaId: import_zod.z.string().describe("Unique identifier of the media file")
293
+ },
294
+ async ({ mediaId }) => {
295
+ try {
296
+ const result = await api.get(`/v1/media/transcript/${mediaId}`);
297
+ return {
298
+ content: [
299
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
300
+ ]
301
+ };
302
+ } catch (err) {
303
+ return {
304
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
305
+ isError: true
306
+ };
307
+ }
308
+ }
309
+ );
310
+ server2.tool(
311
+ "update_transcript_speakers",
312
+ "Update or rename speaker labels in a media transcript.",
313
+ {
314
+ mediaId: import_zod.z.string().describe("Unique identifier of the media file"),
315
+ speakers: import_zod.z.array(
316
+ import_zod.z.object({
317
+ id: import_zod.z.string().describe("Speaker identifier from the transcript"),
318
+ name: import_zod.z.string().describe("Display name to assign to the speaker")
319
+ })
320
+ ).describe("Array of speaker ID to name mappings")
321
+ },
322
+ async ({ mediaId, speakers }) => {
323
+ try {
324
+ const result = await api.put(
325
+ `/v1/media/speakers/${mediaId}`,
326
+ speakers
327
+ );
328
+ return {
329
+ content: [
330
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
331
+ ]
332
+ };
333
+ } catch (err) {
334
+ return {
335
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
336
+ isError: true
337
+ };
338
+ }
339
+ }
340
+ );
341
+ server2.tool(
342
+ "get_media_status",
343
+ "Check the processing status of a media file (e.g. pending, transcribing, completed, failed).",
344
+ {
345
+ mediaId: import_zod.z.string().describe("Unique identifier of the media file")
346
+ },
347
+ async ({ mediaId }) => {
348
+ try {
349
+ const result = await api.get(`/v1/media/status/${mediaId}`);
350
+ return {
351
+ content: [
352
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
353
+ ]
354
+ };
355
+ } catch (err) {
356
+ return {
357
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
358
+ isError: true
359
+ };
360
+ }
361
+ }
362
+ );
363
+ server2.tool(
364
+ "update_media_metadata",
365
+ "Update metadata fields (name, description, tags, status) for an existing media file.",
366
+ {
367
+ mediaId: import_zod.z.string().describe("Unique identifier of the media file"),
368
+ name: import_zod.z.string().optional().describe("New display name for the media"),
369
+ description: import_zod.z.string().optional().describe("Description or notes for the media"),
370
+ folderId: import_zod.z.string().optional().describe("Move media to this folder ID"),
371
+ tags: import_zod.z.array(import_zod.z.string()).optional().describe("Array of tags to assign to the media"),
372
+ status: import_zod.z.string().optional().describe("Media status value"),
373
+ remark: import_zod.z.string().optional().describe("Internal remark or note"),
374
+ manageBy: import_zod.z.string().optional().describe("User ID to assign management of this media to")
375
+ },
376
+ async ({ mediaId, ...body }) => {
377
+ try {
378
+ const result = await api.put(`/v1/media/${mediaId}`, body);
379
+ return {
380
+ content: [
381
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
382
+ ]
383
+ };
384
+ } catch (err) {
385
+ return {
386
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
387
+ isError: true
388
+ };
389
+ }
390
+ }
391
+ );
392
+ server2.tool(
393
+ "delete_media",
394
+ "Permanently delete a media file and all associated transcripts and insights.",
395
+ {
396
+ mediaId: import_zod.z.string().describe("Unique identifier of the media file to delete")
397
+ },
398
+ async ({ mediaId }) => {
399
+ try {
400
+ const result = await api.delete(`/v1/media/${mediaId}`);
401
+ return {
402
+ content: [
403
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
404
+ ]
405
+ };
406
+ } catch (err) {
407
+ return {
408
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
409
+ isError: true
410
+ };
411
+ }
412
+ }
413
+ );
414
+ }
415
+
416
+ // src/tools/text.ts
417
+ var text_exports = {};
418
+ __export(text_exports, {
419
+ register: () => register2
420
+ });
421
+ var import_zod2 = require("zod");
422
+ function register2(server2, client) {
423
+ const api = client ?? speakClient;
424
+ server2.tool(
425
+ "create_text_note",
426
+ "Create a new text note in Speak AI for analysis. The content will be analyzed for insights, topics, and sentiment.",
427
+ {
428
+ name: import_zod2.z.string().describe("Title/name for the text note"),
429
+ text: import_zod2.z.string().optional().describe("Full text content to analyze"),
430
+ description: import_zod2.z.string().optional().describe("Description for the text note"),
431
+ folderId: import_zod2.z.string().optional().describe("ID of the folder to place the note in"),
432
+ tags: import_zod2.z.string().optional().describe("Comma-separated tags or array of tag strings"),
433
+ callbackUrl: import_zod2.z.string().optional().describe("Webhook callback URL for completion notification"),
434
+ fields: import_zod2.z.array(
435
+ import_zod2.z.object({
436
+ id: import_zod2.z.string().describe("Custom field ID"),
437
+ value: import_zod2.z.string().describe("Custom field value")
438
+ })
439
+ ).optional().describe("Custom field values to attach to the text note")
440
+ },
441
+ async (body) => {
442
+ try {
443
+ const result = await api.post("/v1/text/create", body);
444
+ return {
445
+ content: [
446
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
447
+ ]
448
+ };
449
+ } catch (err) {
450
+ return {
451
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
452
+ isError: true
453
+ };
454
+ }
455
+ }
456
+ );
457
+ server2.tool(
458
+ "get_text_insight",
459
+ "Retrieve AI-generated insights for a text note, including topics, sentiment, summaries, and action items.",
460
+ {
461
+ mediaId: import_zod2.z.string().describe("Unique identifier of the text note")
462
+ },
463
+ async ({ mediaId }) => {
464
+ try {
465
+ const result = await api.get(`/v1/text/insight/${mediaId}`);
466
+ return {
467
+ content: [
468
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
469
+ ]
470
+ };
471
+ } catch (err) {
472
+ return {
473
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
474
+ isError: true
475
+ };
476
+ }
477
+ }
478
+ );
479
+ server2.tool(
480
+ "reanalyze_text",
481
+ "Trigger a re-analysis of an existing text note to regenerate insights with the latest AI models.",
482
+ {
483
+ mediaId: import_zod2.z.string().describe("Unique identifier of the text note to reanalyze")
484
+ },
485
+ async ({ mediaId }) => {
486
+ try {
487
+ const result = await api.get(`/v1/text/reanalyze/${mediaId}`);
488
+ return {
489
+ content: [
490
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
491
+ ]
492
+ };
493
+ } catch (err) {
494
+ return {
495
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
496
+ isError: true
497
+ };
498
+ }
499
+ }
500
+ );
501
+ server2.tool(
502
+ "update_text_note",
503
+ "Update an existing text note's name, content, or metadata. Updating text content will trigger re-analysis.",
504
+ {
505
+ mediaId: import_zod2.z.string().describe("Unique identifier of the text note"),
506
+ name: import_zod2.z.string().optional().describe("New name for the text note"),
507
+ text: import_zod2.z.string().optional().describe("New text content (will trigger re-analysis)"),
508
+ description: import_zod2.z.string().optional().describe("Updated description"),
509
+ folderId: import_zod2.z.string().optional().describe("Move to a different folder"),
510
+ tags: import_zod2.z.string().optional().describe("Updated comma-separated tags")
511
+ },
512
+ async ({ mediaId, ...body }) => {
513
+ try {
514
+ const result = await api.put(
515
+ `/v1/text/update/${mediaId}`,
516
+ body
517
+ );
518
+ return {
519
+ content: [
520
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
521
+ ]
522
+ };
523
+ } catch (err) {
524
+ return {
525
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
526
+ isError: true
527
+ };
528
+ }
529
+ }
530
+ );
531
+ }
532
+
533
+ // src/tools/exports.ts
534
+ var exports_exports = {};
535
+ __export(exports_exports, {
536
+ register: () => register3
537
+ });
538
+ var import_zod3 = require("zod");
539
+ function register3(server2, client) {
540
+ const api = client ?? speakClient;
541
+ server2.tool(
542
+ "export_media",
543
+ "Export a media file's transcript or insights in various formats (pdf, docx, srt, vtt, txt, csv, md).",
544
+ {
545
+ mediaId: import_zod3.z.string().describe("Unique identifier of the media file"),
546
+ fileType: import_zod3.z.enum(["pdf", "docx", "srt", "vtt", "txt", "csv", "md"]).describe("Desired export format"),
547
+ isSpeakerNames: import_zod3.z.boolean().optional().describe("Include speaker names in export"),
548
+ isSpeakerEmail: import_zod3.z.boolean().optional().describe("Include speaker emails in export"),
549
+ isTimeStamps: import_zod3.z.boolean().optional().describe("Include timestamps in export"),
550
+ isInsightVisualized: import_zod3.z.boolean().optional().describe("Include insight visualizations"),
551
+ isRedacted: import_zod3.z.boolean().optional().describe("Apply PII redaction to export"),
552
+ redactedCategories: import_zod3.z.array(import_zod3.z.string()).optional().describe("Specific categories to redact")
553
+ },
554
+ async ({ mediaId, fileType, ...query }) => {
555
+ try {
556
+ const result = await api.post(
557
+ `/v1/media/export/${mediaId}/${fileType}`,
558
+ null,
559
+ { params: query }
560
+ );
561
+ return {
562
+ content: [
563
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
564
+ ]
565
+ };
566
+ } catch (err) {
567
+ return {
568
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
569
+ isError: true
570
+ };
571
+ }
572
+ }
573
+ );
574
+ server2.tool(
575
+ "export_multiple_media",
576
+ "Export multiple media files at once, optionally merged into a single file.",
577
+ {
578
+ mediaIds: import_zod3.z.array(import_zod3.z.string()).describe("Array of media IDs to export"),
579
+ fileType: import_zod3.z.enum(["pdf", "docx", "srt", "vtt", "txt", "csv", "md"]).describe("Desired export format"),
580
+ isSpeakerNames: import_zod3.z.boolean().optional().describe("Include speaker names in export"),
581
+ isSpeakerEmail: import_zod3.z.boolean().optional().describe("Include speaker emails in export"),
582
+ isTimeStamps: import_zod3.z.boolean().optional().describe("Include timestamps in export"),
583
+ isInsightVisualized: import_zod3.z.boolean().optional().describe("Include insight visualizations"),
584
+ isRedacted: import_zod3.z.boolean().optional().describe("Apply PII redaction to export"),
585
+ isMerged: import_zod3.z.boolean().optional().describe("Merge all exports into a single file"),
586
+ folderId: import_zod3.z.string().optional().describe("Folder ID for the merged export")
587
+ },
588
+ async (body) => {
589
+ try {
590
+ const result = await api.post(
591
+ "/v1/media/exportMultiple",
592
+ body
593
+ );
594
+ return {
595
+ content: [
596
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
597
+ ]
598
+ };
599
+ } catch (err) {
600
+ return {
601
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
602
+ isError: true
603
+ };
604
+ }
605
+ }
606
+ );
607
+ }
608
+
609
+ // src/tools/folders.ts
610
+ var folders_exports = {};
611
+ __export(folders_exports, {
612
+ register: () => register4
613
+ });
614
+ var import_zod4 = require("zod");
615
+ function register4(server2, client) {
616
+ const api = client ?? speakClient;
617
+ server2.tool(
618
+ "get_all_folder_views",
619
+ "Retrieve all saved views across all folders.",
620
+ {},
621
+ async () => {
622
+ try {
623
+ const result = await api.get("/v1/folders/views");
624
+ return {
625
+ content: [
626
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
627
+ ]
628
+ };
629
+ } catch (err) {
630
+ return {
631
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
632
+ isError: true
633
+ };
634
+ }
635
+ }
636
+ );
637
+ server2.tool(
638
+ "get_folder_views",
639
+ "Retrieve all saved views for a specific folder.",
640
+ {
641
+ folderId: import_zod4.z.string().describe("Unique identifier of the folder")
642
+ },
643
+ async ({ folderId }) => {
644
+ try {
645
+ const result = await api.get(`/v1/folders/${folderId}/views`);
646
+ return {
647
+ content: [
648
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
649
+ ]
650
+ };
651
+ } catch (err) {
652
+ return {
653
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
654
+ isError: true
655
+ };
656
+ }
657
+ }
658
+ );
659
+ server2.tool(
660
+ "create_folder_view",
661
+ "Create a new saved view for a folder with custom filters and display settings.",
662
+ {
663
+ folderId: import_zod4.z.string().describe("Unique identifier of the folder"),
664
+ name: import_zod4.z.string().optional().describe("Display name for the view"),
665
+ filters: import_zod4.z.record(import_zod4.z.unknown()).optional().describe("Filter configuration object")
666
+ },
667
+ async ({ folderId, ...body }) => {
668
+ try {
669
+ const result = await api.post(
670
+ `/v1/folders/${folderId}/views`,
671
+ body
672
+ );
673
+ return {
674
+ content: [
675
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
676
+ ]
677
+ };
678
+ } catch (err) {
679
+ return {
680
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
681
+ isError: true
682
+ };
683
+ }
684
+ }
685
+ );
686
+ server2.tool(
687
+ "update_folder_view",
688
+ "Update an existing saved view's name, filters, or display settings.",
689
+ {
690
+ folderId: import_zod4.z.string().describe("Unique identifier of the folder"),
691
+ viewId: import_zod4.z.string().describe("Unique identifier of the view to update"),
692
+ name: import_zod4.z.string().optional().describe("New display name for the view"),
693
+ filters: import_zod4.z.record(import_zod4.z.unknown()).optional().describe("Updated filter configuration")
694
+ },
695
+ async ({ folderId, viewId, ...body }) => {
696
+ try {
697
+ const result = await api.put(
698
+ `/v1/folders/${folderId}/views/${viewId}`,
699
+ body
700
+ );
701
+ return {
702
+ content: [
703
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
704
+ ]
705
+ };
706
+ } catch (err) {
707
+ return {
708
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
709
+ isError: true
710
+ };
711
+ }
712
+ }
713
+ );
714
+ server2.tool(
715
+ "clone_folder_view",
716
+ "Duplicate an existing folder view.",
717
+ {
718
+ viewId: import_zod4.z.string().describe("Unique identifier of the view to clone")
719
+ },
720
+ async (body) => {
721
+ try {
722
+ const result = await api.post("/v1/folders/views/clone", body);
723
+ return {
724
+ content: [
725
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
726
+ ]
727
+ };
728
+ } catch (err) {
729
+ return {
730
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
731
+ isError: true
732
+ };
733
+ }
734
+ }
735
+ );
736
+ server2.tool(
737
+ "list_folders",
738
+ "List all folders in the workspace with pagination and sorting.",
739
+ {
740
+ page: import_zod4.z.number().int().optional().describe("Page number (0-based)"),
741
+ pageSize: import_zod4.z.number().int().optional().describe("Results per page"),
742
+ sortBy: import_zod4.z.string().optional().describe('Sort field and direction, e.g. "createdAt:desc"')
743
+ },
744
+ async (params) => {
745
+ try {
746
+ const result = await api.get("/v1/folder", { params });
747
+ return {
748
+ content: [
749
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
750
+ ]
751
+ };
752
+ } catch (err) {
753
+ return {
754
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
755
+ isError: true
756
+ };
757
+ }
758
+ }
759
+ );
760
+ server2.tool(
761
+ "get_folder_info",
762
+ "Get detailed information about a specific folder including its contents.",
763
+ {
764
+ folderId: import_zod4.z.string().describe("Unique identifier of the folder")
765
+ },
766
+ async ({ folderId }) => {
767
+ try {
768
+ const result = await api.get(`/v1/folder/${folderId}`);
769
+ return {
770
+ content: [
771
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
772
+ ]
773
+ };
774
+ } catch (err) {
775
+ return {
776
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
777
+ isError: true
778
+ };
779
+ }
780
+ }
781
+ );
782
+ server2.tool(
783
+ "create_folder",
784
+ "Create a new folder in the workspace.",
785
+ {
786
+ name: import_zod4.z.string().describe("Display name for the new folder"),
787
+ parentFolderId: import_zod4.z.string().optional().describe("ID of the parent folder for nesting")
788
+ },
789
+ async (body) => {
790
+ try {
791
+ const result = await api.post("/v1/folder", body);
792
+ return {
793
+ content: [
794
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
795
+ ]
796
+ };
797
+ } catch (err) {
798
+ return {
799
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
800
+ isError: true
801
+ };
802
+ }
803
+ }
804
+ );
805
+ server2.tool(
806
+ "clone_folder",
807
+ "Duplicate an existing folder and all of its contents.",
808
+ {
809
+ folderId: import_zod4.z.string().describe("ID of the folder to clone")
810
+ },
811
+ async (body) => {
812
+ try {
813
+ const result = await api.post("/v1/folder/clone", body);
814
+ return {
815
+ content: [
816
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
817
+ ]
818
+ };
819
+ } catch (err) {
820
+ return {
821
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
822
+ isError: true
823
+ };
824
+ }
825
+ }
826
+ );
827
+ server2.tool(
828
+ "update_folder",
829
+ "Update a folder's name or other properties.",
830
+ {
831
+ folderId: import_zod4.z.string().describe("Unique identifier of the folder"),
832
+ name: import_zod4.z.string().optional().describe("New display name for the folder")
833
+ },
834
+ async ({ folderId, ...body }) => {
835
+ try {
836
+ const result = await api.put(`/v1/folder/${folderId}`, body);
837
+ return {
838
+ content: [
839
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
840
+ ]
841
+ };
842
+ } catch (err) {
843
+ return {
844
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
845
+ isError: true
846
+ };
847
+ }
848
+ }
849
+ );
850
+ server2.tool(
851
+ "delete_folder",
852
+ "Permanently delete a folder. Media within the folder will be moved, not deleted.",
853
+ {
854
+ folderId: import_zod4.z.string().describe("Unique identifier of the folder to delete")
855
+ },
856
+ async ({ folderId }) => {
857
+ try {
858
+ const result = await api.delete(`/v1/folder/${folderId}`);
859
+ return {
860
+ content: [
861
+ { type: "text", text: JSON.stringify(result.data, null, 2) }
862
+ ]
863
+ };
864
+ } catch (err) {
865
+ return {
866
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
867
+ isError: true
868
+ };
869
+ }
870
+ }
871
+ );
872
+ }
873
+
874
+ // src/tools/recorder.ts
875
+ var recorder_exports = {};
876
+ __export(recorder_exports, {
877
+ register: () => register5
878
+ });
879
+ var import_zod5 = require("zod");
880
+ function register5(server2, client) {
881
+ const api = client ?? speakClient;
882
+ server2.tool(
883
+ "check_recorder_status",
884
+ "Check whether a recorder/survey is active and accepting submissions.",
885
+ {
886
+ token: import_zod5.z.string().describe("Unique token identifying the recorder")
887
+ },
888
+ async ({ token }) => {
889
+ try {
890
+ const result = await api.get(`/v1/recorder/status/${token}`);
891
+ return {
892
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
893
+ };
894
+ } catch (err) {
895
+ return {
896
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
897
+ isError: true
898
+ };
899
+ }
900
+ }
901
+ );
902
+ server2.tool(
903
+ "create_recorder",
904
+ "Create a new recorder or survey for collecting audio/video submissions.",
905
+ {
906
+ name: import_zod5.z.string().optional().describe("Display name for the recorder"),
907
+ folderId: import_zod5.z.string().optional().describe("Folder to store recordings in"),
908
+ settings: import_zod5.z.record(import_zod5.z.unknown()).optional().describe("Recorder configuration settings")
909
+ },
910
+ async (body) => {
911
+ try {
912
+ const result = await api.post("/v1/recorder/create", body);
913
+ return {
914
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
915
+ };
916
+ } catch (err) {
917
+ return {
918
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
919
+ isError: true
920
+ };
921
+ }
922
+ }
923
+ );
924
+ server2.tool(
925
+ "list_recorders",
926
+ "List all recorders/surveys in the workspace.",
927
+ {
928
+ page: import_zod5.z.number().int().optional().describe("Page number (0-based)"),
929
+ pageSize: import_zod5.z.number().int().optional().describe("Results per page"),
930
+ sortBy: import_zod5.z.string().optional().describe('Sort field, e.g. "createdAt:desc"')
931
+ },
932
+ async (params) => {
933
+ try {
934
+ const result = await api.get("/v1/recorder", { params });
935
+ return {
936
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
937
+ };
938
+ } catch (err) {
939
+ return {
940
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
941
+ isError: true
942
+ };
943
+ }
944
+ }
945
+ );
946
+ server2.tool(
947
+ "clone_recorder",
948
+ "Duplicate an existing recorder including all its settings and questions.",
949
+ {
950
+ recorderId: import_zod5.z.string().describe("ID of the recorder to clone")
951
+ },
952
+ async (body) => {
953
+ try {
954
+ const result = await api.post("/v1/recorder/clone", body);
955
+ return {
956
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
957
+ };
958
+ } catch (err) {
959
+ return {
960
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
961
+ isError: true
962
+ };
963
+ }
964
+ }
965
+ );
966
+ server2.tool(
967
+ "get_recorder_info",
968
+ "Get detailed information about a specific recorder including its settings and questions.",
969
+ {
970
+ recorderId: import_zod5.z.string().describe("Unique identifier of the recorder")
971
+ },
972
+ async ({ recorderId }) => {
973
+ try {
974
+ const result = await api.get(`/v1/recorder/${recorderId}`);
975
+ return {
976
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
977
+ };
978
+ } catch (err) {
979
+ return {
980
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
981
+ isError: true
982
+ };
983
+ }
984
+ }
985
+ );
986
+ server2.tool(
987
+ "get_recorder_recordings",
988
+ "List all submissions/recordings collected by a specific recorder.",
989
+ {
990
+ recorderId: import_zod5.z.string().describe("Unique identifier of the recorder")
991
+ },
992
+ async ({ recorderId }) => {
993
+ try {
994
+ const result = await api.get(`/v1/recorder/recordings/${recorderId}`);
995
+ return {
996
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
997
+ };
998
+ } catch (err) {
999
+ return {
1000
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1001
+ isError: true
1002
+ };
1003
+ }
1004
+ }
1005
+ );
1006
+ server2.tool(
1007
+ "generate_recorder_url",
1008
+ "Generate a shareable public URL for a recorder/survey.",
1009
+ {
1010
+ recorderId: import_zod5.z.string().describe("Unique identifier of the recorder")
1011
+ },
1012
+ async ({ recorderId }) => {
1013
+ try {
1014
+ const result = await api.get(`/v1/recorder/url/${recorderId}`);
1015
+ return {
1016
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1017
+ };
1018
+ } catch (err) {
1019
+ return {
1020
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1021
+ isError: true
1022
+ };
1023
+ }
1024
+ }
1025
+ );
1026
+ server2.tool(
1027
+ "update_recorder_settings",
1028
+ "Update configuration settings for a recorder (branding, permissions, etc.).",
1029
+ {
1030
+ recorderId: import_zod5.z.string().describe("Unique identifier of the recorder"),
1031
+ settings: import_zod5.z.record(import_zod5.z.unknown()).describe("Settings object with updated values")
1032
+ },
1033
+ async ({ recorderId, settings }) => {
1034
+ try {
1035
+ const result = await api.put(`/v1/recorder/settings/${recorderId}`, settings);
1036
+ return {
1037
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1038
+ };
1039
+ } catch (err) {
1040
+ return {
1041
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1042
+ isError: true
1043
+ };
1044
+ }
1045
+ }
1046
+ );
1047
+ server2.tool(
1048
+ "update_recorder_questions",
1049
+ "Update the survey questions for a recorder.",
1050
+ {
1051
+ recorderId: import_zod5.z.string().describe("Unique identifier of the recorder"),
1052
+ questions: import_zod5.z.array(import_zod5.z.record(import_zod5.z.unknown())).describe("Array of question objects")
1053
+ },
1054
+ async ({ recorderId, questions }) => {
1055
+ try {
1056
+ const result = await api.put(`/v1/recorder/questions/${recorderId}`, { questions });
1057
+ return {
1058
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1059
+ };
1060
+ } catch (err) {
1061
+ return {
1062
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1063
+ isError: true
1064
+ };
1065
+ }
1066
+ }
1067
+ );
1068
+ server2.tool(
1069
+ "delete_recorder",
1070
+ "Permanently delete a recorder/survey. Existing recordings are preserved.",
1071
+ {
1072
+ recorderId: import_zod5.z.string().describe("Unique identifier of the recorder to delete")
1073
+ },
1074
+ async ({ recorderId }) => {
1075
+ try {
1076
+ const result = await api.delete(`/v1/recorder/${recorderId}`);
1077
+ return {
1078
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1079
+ };
1080
+ } catch (err) {
1081
+ return {
1082
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1083
+ isError: true
1084
+ };
1085
+ }
1086
+ }
1087
+ );
1088
+ }
1089
+
1090
+ // src/tools/embed.ts
1091
+ var embed_exports = {};
1092
+ __export(embed_exports, {
1093
+ register: () => register6
1094
+ });
1095
+ var import_zod6 = require("zod");
1096
+ function register6(server2, client) {
1097
+ const api = client ?? speakClient;
1098
+ server2.tool(
1099
+ "create_embed",
1100
+ "Create an embeddable player/transcript widget for a media file.",
1101
+ {
1102
+ mediaId: import_zod6.z.string().describe("Unique identifier of the media file"),
1103
+ settings: import_zod6.z.record(import_zod6.z.unknown()).optional().describe("Embed configuration settings")
1104
+ },
1105
+ async (body) => {
1106
+ try {
1107
+ const result = await api.post("/v1/embed", body);
1108
+ return {
1109
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1110
+ };
1111
+ } catch (err) {
1112
+ return {
1113
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1114
+ isError: true
1115
+ };
1116
+ }
1117
+ }
1118
+ );
1119
+ server2.tool(
1120
+ "update_embed",
1121
+ "Update settings for an existing embed widget.",
1122
+ {
1123
+ embedId: import_zod6.z.string().describe("Unique identifier of the embed"),
1124
+ settings: import_zod6.z.record(import_zod6.z.unknown()).optional().describe("Updated embed settings")
1125
+ },
1126
+ async ({ embedId, ...body }) => {
1127
+ try {
1128
+ const result = await api.put(`/v1/embed/${embedId}`, body);
1129
+ return {
1130
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1131
+ };
1132
+ } catch (err) {
1133
+ return {
1134
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1135
+ isError: true
1136
+ };
1137
+ }
1138
+ }
1139
+ );
1140
+ server2.tool(
1141
+ "check_embed",
1142
+ "Check if an embed exists for a media file and retrieve its configuration.",
1143
+ {
1144
+ mediaId: import_zod6.z.string().describe("Unique identifier of the media file")
1145
+ },
1146
+ async ({ mediaId }) => {
1147
+ try {
1148
+ const result = await api.get(`/v1/embed/${mediaId}`);
1149
+ return {
1150
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1151
+ };
1152
+ } catch (err) {
1153
+ return {
1154
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1155
+ isError: true
1156
+ };
1157
+ }
1158
+ }
1159
+ );
1160
+ server2.tool(
1161
+ "get_embed_iframe_url",
1162
+ "Get the iframe URL for embedding a media player/transcript on a webpage.",
1163
+ {
1164
+ mediaId: import_zod6.z.string().describe("Unique identifier of the media file")
1165
+ },
1166
+ async ({ mediaId }) => {
1167
+ try {
1168
+ const result = await api.get("/v1/embed/iframe", {
1169
+ params: { mediaId }
1170
+ });
1171
+ return {
1172
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1173
+ };
1174
+ } catch (err) {
1175
+ return {
1176
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1177
+ isError: true
1178
+ };
1179
+ }
1180
+ }
1181
+ );
1182
+ }
1183
+
1184
+ // src/tools/prompt.ts
1185
+ var prompt_exports = {};
1186
+ __export(prompt_exports, {
1187
+ register: () => register7
1188
+ });
1189
+ var import_zod7 = require("zod");
1190
+ function register7(server2, client) {
1191
+ const api = client ?? speakClient;
1192
+ server2.tool(
1193
+ "list_prompts",
1194
+ "List all available Magic Prompt templates for AI-powered questions about your media.",
1195
+ {},
1196
+ async () => {
1197
+ try {
1198
+ const result = await api.get("/v1/prompt");
1199
+ return {
1200
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1201
+ };
1202
+ } catch (err) {
1203
+ return {
1204
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1205
+ isError: true
1206
+ };
1207
+ }
1208
+ }
1209
+ );
1210
+ server2.tool(
1211
+ "ask_magic_prompt",
1212
+ "Ask an AI-powered question about a specific media file using Speak AI's Magic Prompt.",
1213
+ {
1214
+ mediaId: import_zod7.z.string().describe("Unique identifier of the media file to query"),
1215
+ prompt: import_zod7.z.string().describe("The question or prompt to ask about the media"),
1216
+ promptId: import_zod7.z.string().optional().describe("ID of a predefined prompt template to use")
1217
+ },
1218
+ async (body) => {
1219
+ try {
1220
+ const result = await api.post("/v1/prompt", body);
1221
+ return {
1222
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1223
+ };
1224
+ } catch (err) {
1225
+ return {
1226
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1227
+ isError: true
1228
+ };
1229
+ }
1230
+ }
1231
+ );
1232
+ }
1233
+
1234
+ // src/tools/meeting.ts
1235
+ var meeting_exports = {};
1236
+ __export(meeting_exports, {
1237
+ register: () => register8
1238
+ });
1239
+ var import_zod8 = require("zod");
1240
+ function register8(server2, client) {
1241
+ const api = client ?? speakClient;
1242
+ server2.tool(
1243
+ "list_meeting_events",
1244
+ "List scheduled or completed meeting assistant events with filtering and pagination.",
1245
+ {
1246
+ platformType: import_zod8.z.string().optional().describe("Filter by platform (e.g. zoom, teams, meet)"),
1247
+ meetingStatus: import_zod8.z.string().optional().describe("Filter by status (e.g. scheduled, completed, cancelled)"),
1248
+ page: import_zod8.z.number().int().optional().describe("Page number (0-based)"),
1249
+ pageSize: import_zod8.z.number().int().optional().describe("Results per page")
1250
+ },
1251
+ async (params) => {
1252
+ try {
1253
+ const result = await api.get("/v1/meeting-assistant/events", {
1254
+ params
1255
+ });
1256
+ return {
1257
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1258
+ };
1259
+ } catch (err) {
1260
+ return {
1261
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1262
+ isError: true
1263
+ };
1264
+ }
1265
+ }
1266
+ );
1267
+ server2.tool(
1268
+ "schedule_meeting_event",
1269
+ "Schedule the Speak AI meeting assistant to join and record an upcoming meeting.",
1270
+ {
1271
+ meetingUrl: import_zod8.z.string().describe("URL of the meeting to join"),
1272
+ title: import_zod8.z.string().optional().describe("Display title for the event"),
1273
+ scheduledAt: import_zod8.z.string().optional().describe("ISO 8601 datetime for when the meeting starts")
1274
+ },
1275
+ async (body) => {
1276
+ try {
1277
+ const result = await api.post(
1278
+ "/v1/meeting-assistant/events/schedule",
1279
+ body
1280
+ );
1281
+ return {
1282
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1283
+ };
1284
+ } catch (err) {
1285
+ return {
1286
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1287
+ isError: true
1288
+ };
1289
+ }
1290
+ }
1291
+ );
1292
+ server2.tool(
1293
+ "remove_assistant_from_meeting",
1294
+ "Remove the Speak AI assistant from an active or scheduled meeting.",
1295
+ {
1296
+ meetingAssistantEventId: import_zod8.z.string().describe("Unique identifier of the meeting assistant event")
1297
+ },
1298
+ async ({ meetingAssistantEventId }) => {
1299
+ try {
1300
+ const result = await api.put(
1301
+ "/v1/meeting-assistant/events/remove",
1302
+ null,
1303
+ { params: { meetingAssistantEventId } }
1304
+ );
1305
+ return {
1306
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1307
+ };
1308
+ } catch (err) {
1309
+ return {
1310
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1311
+ isError: true
1312
+ };
1313
+ }
1314
+ }
1315
+ );
1316
+ server2.tool(
1317
+ "delete_scheduled_assistant",
1318
+ "Cancel and delete a scheduled meeting assistant event.",
1319
+ {
1320
+ meetingAssistantEventId: import_zod8.z.string().describe("Unique identifier of the meeting assistant event to cancel")
1321
+ },
1322
+ async ({ meetingAssistantEventId }) => {
1323
+ try {
1324
+ const result = await api.delete(
1325
+ "/v1/meeting-assistant/events",
1326
+ { params: { meetingAssistantEventId } }
1327
+ );
1328
+ return {
1329
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1330
+ };
1331
+ } catch (err) {
1332
+ return {
1333
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1334
+ isError: true
1335
+ };
1336
+ }
1337
+ }
1338
+ );
1339
+ }
1340
+
1341
+ // src/tools/fields.ts
1342
+ var fields_exports = {};
1343
+ __export(fields_exports, {
1344
+ register: () => register9
1345
+ });
1346
+ var import_zod9 = require("zod");
1347
+ function register9(server2, client) {
1348
+ const api = client ?? speakClient;
1349
+ server2.tool(
1350
+ "list_fields",
1351
+ "List all custom fields defined in the workspace.",
1352
+ {},
1353
+ async () => {
1354
+ try {
1355
+ const result = await api.get("/v1/fields");
1356
+ return {
1357
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1358
+ };
1359
+ } catch (err) {
1360
+ return {
1361
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1362
+ isError: true
1363
+ };
1364
+ }
1365
+ }
1366
+ );
1367
+ server2.tool(
1368
+ "create_field",
1369
+ "Create a new custom field for categorizing and tagging media.",
1370
+ {
1371
+ name: import_zod9.z.string().describe("Display name for the field"),
1372
+ type: import_zod9.z.string().optional().describe("Field type (text, number, select, etc.)"),
1373
+ options: import_zod9.z.array(import_zod9.z.string()).optional().describe("Options for select/multi-select field types")
1374
+ },
1375
+ async (body) => {
1376
+ try {
1377
+ const result = await api.post("/v1/fields", body);
1378
+ return {
1379
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1380
+ };
1381
+ } catch (err) {
1382
+ return {
1383
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1384
+ isError: true
1385
+ };
1386
+ }
1387
+ }
1388
+ );
1389
+ server2.tool(
1390
+ "update_multiple_fields",
1391
+ "Update multiple custom fields in a single batch operation.",
1392
+ {
1393
+ fields: import_zod9.z.array(import_zod9.z.record(import_zod9.z.unknown())).describe("Array of field objects to update")
1394
+ },
1395
+ async ({ fields }) => {
1396
+ try {
1397
+ const result = await api.post("/v1/fields/multi", { fields });
1398
+ return {
1399
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1400
+ };
1401
+ } catch (err) {
1402
+ return {
1403
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1404
+ isError: true
1405
+ };
1406
+ }
1407
+ }
1408
+ );
1409
+ server2.tool(
1410
+ "update_field",
1411
+ "Update a specific custom field by ID.",
1412
+ {
1413
+ id: import_zod9.z.string().describe("Unique identifier of the field"),
1414
+ name: import_zod9.z.string().optional().describe("New display name"),
1415
+ type: import_zod9.z.string().optional().describe("New field type"),
1416
+ options: import_zod9.z.array(import_zod9.z.string()).optional().describe("Updated options for select types")
1417
+ },
1418
+ async ({ id, ...body }) => {
1419
+ try {
1420
+ const result = await api.put(`/v1/fields/${id}`, body);
1421
+ return {
1422
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1423
+ };
1424
+ } catch (err) {
1425
+ return {
1426
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1427
+ isError: true
1428
+ };
1429
+ }
1430
+ }
1431
+ );
1432
+ }
1433
+
1434
+ // src/tools/automations.ts
1435
+ var automations_exports = {};
1436
+ __export(automations_exports, {
1437
+ register: () => register10
1438
+ });
1439
+ var import_zod10 = require("zod");
1440
+ function register10(server2, client) {
1441
+ const api = client ?? speakClient;
1442
+ server2.tool(
1443
+ "list_automations",
1444
+ "List all automation rules configured in the workspace.",
1445
+ {},
1446
+ async () => {
1447
+ try {
1448
+ const result = await api.get("/v1/automations");
1449
+ return {
1450
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1451
+ };
1452
+ } catch (err) {
1453
+ return {
1454
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1455
+ isError: true
1456
+ };
1457
+ }
1458
+ }
1459
+ );
1460
+ server2.tool(
1461
+ "get_automation",
1462
+ "Get detailed information about a specific automation rule.",
1463
+ {
1464
+ automationId: import_zod10.z.string().describe("Unique identifier of the automation")
1465
+ },
1466
+ async ({ automationId }) => {
1467
+ try {
1468
+ const result = await api.get(`/v1/automations/${automationId}`);
1469
+ return {
1470
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1471
+ };
1472
+ } catch (err) {
1473
+ return {
1474
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1475
+ isError: true
1476
+ };
1477
+ }
1478
+ }
1479
+ );
1480
+ server2.tool(
1481
+ "create_automation",
1482
+ "Create a new automation rule for automatic media processing workflows.",
1483
+ {
1484
+ name: import_zod10.z.string().optional().describe("Display name for the automation"),
1485
+ trigger: import_zod10.z.record(import_zod10.z.unknown()).optional().describe("Trigger configuration"),
1486
+ actions: import_zod10.z.array(import_zod10.z.record(import_zod10.z.unknown())).optional().describe("Array of action configurations"),
1487
+ config: import_zod10.z.record(import_zod10.z.unknown()).optional().describe("Full automation configuration object")
1488
+ },
1489
+ async (body) => {
1490
+ try {
1491
+ const result = await api.post("/v1/automations/", body);
1492
+ return {
1493
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1494
+ };
1495
+ } catch (err) {
1496
+ return {
1497
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1498
+ isError: true
1499
+ };
1500
+ }
1501
+ }
1502
+ );
1503
+ server2.tool(
1504
+ "update_automation",
1505
+ "Update an existing automation rule's configuration.",
1506
+ {
1507
+ automationId: import_zod10.z.string().describe("Unique identifier of the automation"),
1508
+ name: import_zod10.z.string().optional().describe("New display name"),
1509
+ trigger: import_zod10.z.record(import_zod10.z.unknown()).optional().describe("Updated trigger configuration"),
1510
+ actions: import_zod10.z.array(import_zod10.z.record(import_zod10.z.unknown())).optional().describe("Updated action configurations"),
1511
+ config: import_zod10.z.record(import_zod10.z.unknown()).optional().describe("Full updated configuration object")
1512
+ },
1513
+ async ({ automationId, ...body }) => {
1514
+ try {
1515
+ const result = await api.put(
1516
+ `/v1/automations/${automationId}`,
1517
+ body
1518
+ );
1519
+ return {
1520
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1521
+ };
1522
+ } catch (err) {
1523
+ return {
1524
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1525
+ isError: true
1526
+ };
1527
+ }
1528
+ }
1529
+ );
1530
+ server2.tool(
1531
+ "toggle_automation_status",
1532
+ "Enable or disable an automation rule.",
1533
+ {
1534
+ automationId: import_zod10.z.string().describe("Unique identifier of the automation"),
1535
+ enabled: import_zod10.z.boolean().describe("Set to true to enable, false to disable")
1536
+ },
1537
+ async ({ automationId, enabled }) => {
1538
+ try {
1539
+ const result = await api.put(
1540
+ `/v1/automations/status/${automationId}`,
1541
+ { enabled }
1542
+ );
1543
+ return {
1544
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1545
+ };
1546
+ } catch (err) {
1547
+ return {
1548
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1549
+ isError: true
1550
+ };
1551
+ }
1552
+ }
1553
+ );
1554
+ }
1555
+
1556
+ // src/tools/webhooks.ts
1557
+ var webhooks_exports = {};
1558
+ __export(webhooks_exports, {
1559
+ register: () => register11
1560
+ });
1561
+ var import_zod11 = require("zod");
1562
+ function register11(server2, client) {
1563
+ const api = client ?? speakClient;
1564
+ server2.tool(
1565
+ "create_webhook",
1566
+ "Create a new webhook to receive real-time notifications when events occur in Speak AI.",
1567
+ {
1568
+ url: import_zod11.z.string().url().describe("HTTPS endpoint URL to receive webhook payloads"),
1569
+ events: import_zod11.z.array(import_zod11.z.string()).optional().describe("Array of event types to subscribe to")
1570
+ },
1571
+ async (body) => {
1572
+ try {
1573
+ const result = await api.post("/v1/webhook", body);
1574
+ return {
1575
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1576
+ };
1577
+ } catch (err) {
1578
+ return {
1579
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1580
+ isError: true
1581
+ };
1582
+ }
1583
+ }
1584
+ );
1585
+ server2.tool(
1586
+ "list_webhooks",
1587
+ "List all configured webhooks in the workspace.",
1588
+ {},
1589
+ async () => {
1590
+ try {
1591
+ const result = await api.get("/v1/webhook");
1592
+ return {
1593
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1594
+ };
1595
+ } catch (err) {
1596
+ return {
1597
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1598
+ isError: true
1599
+ };
1600
+ }
1601
+ }
1602
+ );
1603
+ server2.tool(
1604
+ "update_webhook",
1605
+ "Update an existing webhook's URL or subscribed events.",
1606
+ {
1607
+ webhookId: import_zod11.z.string().describe("Unique identifier of the webhook"),
1608
+ url: import_zod11.z.string().url().optional().describe("New endpoint URL"),
1609
+ events: import_zod11.z.array(import_zod11.z.string()).optional().describe("Updated array of event types")
1610
+ },
1611
+ async ({ webhookId, ...body }) => {
1612
+ try {
1613
+ const result = await api.put(`/v1/webhook/${webhookId}`, body);
1614
+ return {
1615
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1616
+ };
1617
+ } catch (err) {
1618
+ return {
1619
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1620
+ isError: true
1621
+ };
1622
+ }
1623
+ }
1624
+ );
1625
+ server2.tool(
1626
+ "delete_webhook",
1627
+ "Delete a webhook and stop receiving notifications at its endpoint.",
1628
+ {
1629
+ webhookId: import_zod11.z.string().describe("Unique identifier of the webhook to delete")
1630
+ },
1631
+ async ({ webhookId }) => {
1632
+ try {
1633
+ const result = await api.delete(`/v1/webhook/${webhookId}`);
1634
+ return {
1635
+ content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
1636
+ };
1637
+ } catch (err) {
1638
+ return {
1639
+ content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
1640
+ isError: true
1641
+ };
1642
+ }
1643
+ }
1644
+ );
1645
+ }
1646
+
1647
+ // src/tools/index.ts
1648
+ var modules = [
1649
+ media_exports,
1650
+ text_exports,
1651
+ exports_exports,
1652
+ folders_exports,
1653
+ recorder_exports,
1654
+ embed_exports,
1655
+ prompt_exports,
1656
+ meeting_exports,
1657
+ fields_exports,
1658
+ automations_exports,
1659
+ webhooks_exports
1660
+ ];
1661
+ function registerAllTools(server2, client) {
1662
+ for (const mod of modules) {
1663
+ mod.register(server2, client);
1664
+ }
1665
+ }
1666
+
1667
+ // src/index.ts
1668
+ var server = new import_mcp.McpServer({
1669
+ name: "speak-ai",
1670
+ version: "1.0.0"
1671
+ });
1672
+ registerAllTools(server);
1673
+ async function main() {
1674
+ const transport = new import_stdio.StdioServerTransport();
1675
+ await server.connect(transport);
1676
+ process.stderr.write("[speak-mcp] Server started on stdio transport\n");
1677
+ }
1678
+ main().catch((err) => {
1679
+ process.stderr.write(`[speak-mcp] Fatal error: ${err}
1680
+ `);
1681
+ process.exit(1);
1682
+ });
1683
+ // Annotate the CommonJS export names for ESM import in node:
1684
+ 0 && (module.exports = {
1685
+ createSpeakClient,
1686
+ formatAxiosError,
1687
+ registerAllTools
1688
+ });