@speakai/mcp-server 1.1.0 → 1.2.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 CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  <p align="center">
8
8
  Connect Claude, Cursor, Windsurf, and other AI assistants to your <a href="https://speakai.co">Speak AI</a> workspace.<br/>
9
- 82 tools, 5 resources, 3 prompts, 28 CLI commands — transcribe, analyze, search, and manage media at scale.
9
+ 83 tools, 5 resources, 3 prompts, 28 CLI commands — transcribe, analyze, search, and manage media at scale.
10
10
  </p>
11
11
 
12
12
  <p align="center">
@@ -160,10 +160,10 @@ SPEAK_API_KEY=your-key npx @speakai/mcp-server
160
160
 
161
161
  ---
162
162
 
163
- ## MCP Tools (82)
163
+ ## MCP Tools (83)
164
164
 
165
165
  <details>
166
- <summary>Media (15 tools)</summary>
166
+ <summary>Media (16 tools)</summary>
167
167
 
168
168
  | Tool | Description |
169
169
  |---|---|
@@ -171,11 +171,12 @@ SPEAK_API_KEY=your-key npx @speakai/mcp-server
171
171
  | `upload_media` | Upload media from a public URL for transcription |
172
172
  | `upload_local_file` | Upload a local file directly from disk |
173
173
  | `upload_and_analyze` | Upload, wait for processing, return transcript + insights in one call |
174
- | `list_media` | List and search media files with filters and pagination |
174
+ | `list_media` | List and search media files with filters, pagination, and optional inline data (transcripts, speakers, keywords) via `include` param |
175
175
  | `get_media_insights` | Get AI insights — topics, sentiment, summaries, action items |
176
176
  | `get_transcript` | Get full transcript with speaker labels and timestamps |
177
177
  | `get_captions` | Get subtitle-formatted captions for a media file |
178
178
  | `update_transcript_speakers` | Rename speaker labels in a transcript |
179
+ | `bulk_update_transcript_speakers` | Rename speaker labels across multiple media files in one call (max 500) |
179
180
  | `get_media_status` | Check processing status (pending -> processed) |
180
181
  | `update_media_metadata` | Update name, description, tags, or folder |
181
182
  | `delete_media` | Permanently delete a media file |
@@ -658,6 +659,8 @@ curl -X POST https://api.speakai.co/v1/auth/refreshToken \
658
659
  - Use `export_multiple_media` over individual exports for batch operations
659
660
  - Use `upload_and_analyze` instead of manual upload + poll + fetch loops
660
661
  - Use `bulk_move_media` to move multiple items at once instead of updating one by one
662
+ - Use `bulk_update_transcript_speakers` to rename speakers across many files instead of calling `update_transcript_speakers` per file
663
+ - Use `list_media` with `include: ["transcription"]` to fetch media with transcripts inline, avoiding N+1 calls to `get_transcript`
661
664
 
662
665
  ### Error Format
663
666
 
package/dist/index.js CHANGED
@@ -1145,7 +1145,7 @@ function register(server, client) {
1145
1145
  );
1146
1146
  server.tool(
1147
1147
  "list_media",
1148
- "List and search media files in the workspace with filtering, pagination, and sorting. Use filterName for text search, mediaType to filter by audio/video/text, folderId for folder-specific results, and from/to for date ranges. Returns mediaIds you can pass to get_transcript, get_media_insights, or ask_magic_prompt. For deep full-text search across transcripts, use search_media instead.",
1148
+ "List and search media files in the workspace with filtering, pagination, and sorting. Use filterName for text search, mediaType to filter by audio/video/text, folderId for folder-specific results, and from/to for date ranges. Use the include param to embed additional data (transcripts, speakers, keywords) inline with each result, avoiding N+1 API calls. Returns mediaIds you can pass to get_transcript, get_media_insights, or ask_magic_prompt. For deep full-text search across transcripts, use search_media instead.",
1149
1149
  {
1150
1150
  mediaType: import_zod.z.enum([MediaType.AUDIO, MediaType.VIDEO, MediaType.TEXT]).optional().describe('Filter by media type: "audio", "video", or "text"'),
1151
1151
  page: import_zod.z.number().int().min(0).optional().describe("Page number for pagination (0-based, default: 0)"),
@@ -1156,11 +1156,27 @@ function register(server, client) {
1156
1156
  folderId: import_zod.z.string().optional().describe("Filter media within a specific folder"),
1157
1157
  from: import_zod.z.string().optional().describe("Start date for date range filter (ISO 8601)"),
1158
1158
  to: import_zod.z.string().optional().describe("End date for date range filter (ISO 8601)"),
1159
- isFavorites: import_zod.z.boolean().optional().describe("Filter to only show favorited media")
1159
+ isFavorites: import_zod.z.boolean().optional().describe("Filter to only show favorited media"),
1160
+ include: import_zod.z.array(
1161
+ import_zod.z.enum([
1162
+ "transcription",
1163
+ "keywords",
1164
+ "speakers",
1165
+ "sentiment",
1166
+ "custom",
1167
+ "fields"
1168
+ ])
1169
+ ).optional().describe(
1170
+ "Additional data to include with each media item. Without this, only metadata is returned. Use 'transcription' to include full transcripts inline, 'speakers' for speaker details, 'keywords' for extracted keywords, etc. Avoids N+1 API calls when you need data for multiple files."
1171
+ )
1160
1172
  },
1161
- async (params) => {
1173
+ async ({ include, ...params }) => {
1162
1174
  try {
1163
- const result = await api.get("/v1/media", { params });
1175
+ const queryParams = { ...params };
1176
+ if (include?.length) {
1177
+ queryParams.requestTypes = include.join(",");
1178
+ }
1179
+ const result = await api.get("/v1/media", { params: queryParams });
1164
1180
  return {
1165
1181
  content: [
1166
1182
  { type: "text", text: JSON.stringify(result.data, null, 2) }
@@ -1428,6 +1444,45 @@ function register(server, client) {
1428
1444
  }
1429
1445
  }
1430
1446
  );
1447
+ server.tool(
1448
+ "bulk_update_transcript_speakers",
1449
+ "Update or rename speaker labels across multiple media files in a single operation. Applies the same speaker mappings to every specified media file. Use this instead of calling update_transcript_speakers repeatedly when renaming speakers across a project or folder.",
1450
+ {
1451
+ mediaIds: import_zod.z.array(import_zod.z.string().min(1)).min(1).max(500).describe("Array of media IDs to update speakers for (max 500 per call)"),
1452
+ speakers: import_zod.z.array(
1453
+ import_zod.z.object({
1454
+ id: import_zod.z.string().min(1).describe("Speaker identifier from the transcript"),
1455
+ name: import_zod.z.string().min(1).describe("Display name to assign to the speaker")
1456
+ })
1457
+ ).describe("Array of speaker ID to name mappings to apply to all specified media files")
1458
+ },
1459
+ async ({ mediaIds, speakers }) => {
1460
+ const results = [];
1461
+ for (const mediaId of mediaIds) {
1462
+ try {
1463
+ await api.put(`/v1/media/speakers/${mediaId}`, { speakers });
1464
+ results.push({ mediaId, success: true });
1465
+ } catch (err) {
1466
+ results.push({ mediaId, success: false, error: formatAxiosError(err) });
1467
+ }
1468
+ }
1469
+ const succeeded = results.filter((r) => r.success).length;
1470
+ const failed = results.filter((r) => !r.success).length;
1471
+ return {
1472
+ content: [
1473
+ {
1474
+ type: "text",
1475
+ text: JSON.stringify(
1476
+ { summary: { total: mediaIds.length, succeeded, failed }, results },
1477
+ null,
1478
+ 2
1479
+ )
1480
+ }
1481
+ ],
1482
+ isError: failed === mediaIds.length
1483
+ };
1484
+ }
1485
+ );
1431
1486
  server.tool(
1432
1487
  "bulk_move_media",
1433
1488
  "Move multiple media files to a folder in a single operation. Use this for batch reorganization instead of updating media one by one.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@speakai/mcp-server",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Official Speak AI MCP Server — connect Claude and other AI assistants to Speak AI's transcription, insights, and media management API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -27,7 +27,7 @@
27
27
  "author": "Speak AI",
28
28
  "license": "MIT",
29
29
  "engines": {
30
- "node": ">=20"
30
+ "node": ">=22"
31
31
  },
32
32
  "files": [
33
33
  "dist"
@@ -40,7 +40,7 @@
40
40
  "zod": "^3.22.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@speakai/shared": "^1.5.1",
43
+ "@speakai/shared": "^1.6.2",
44
44
  "@types/node": "^20.0.0",
45
45
  "@vitest/coverage-v8": "^4.1.2",
46
46
  "tsup": "^8.5.1",