@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.
- package/README.md +329 -0
- package/dist/index.js +1688 -0
- 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
|
+
});
|