@speakai/mcp-server 1.9.0 → 1.10.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 +4 -2
- package/dist/index.js +95 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -272,7 +272,7 @@ Get a Speak AI API key at [app.speakai.co/developers/apikeys](https://app.speaka
|
|
|
272
272
|
|
|
273
273
|
The `@speakai/mcp-server` npm package provides:
|
|
274
274
|
|
|
275
|
-
- A CLI (`speakai-mcp`) for scripting and pipelines (
|
|
275
|
+
- A CLI (`speakai-mcp`) for scripting and pipelines (30 commands).
|
|
276
276
|
- A stdio-mode MCP server for clients that don't support remote HTTP transport.
|
|
277
277
|
- An auto-setup wizard that detects installed MCP clients and configures them.
|
|
278
278
|
|
|
@@ -638,7 +638,7 @@ Parameters: days (optional, default: 7), folder (optional)
|
|
|
638
638
|
|
|
639
639
|
**Example:** "Use the meeting-brief prompt with days=14 to cover the last two weeks"
|
|
640
640
|
|
|
641
|
-
### CLI (
|
|
641
|
+
### CLI (30 Commands)
|
|
642
642
|
|
|
643
643
|
Install globally and configure once:
|
|
644
644
|
|
|
@@ -703,7 +703,9 @@ npx @speakai/mcp-server config set-key
|
|
|
703
703
|
|---|---|
|
|
704
704
|
| `stats` | Show workspace media statistics |
|
|
705
705
|
| `languages` | List supported transcription languages |
|
|
706
|
+
| `list-meeting-events` | List scheduled/completed meeting events (`--platform`, `--status`, `--sort`) |
|
|
706
707
|
| `schedule-meeting <url>` | Schedule AI assistant to join a meeting |
|
|
708
|
+
| `live-transcript` | Fetch new sentences from an in-progress meeting (`--event-id` or `--media-id`, `--since-end-in-sec`) |
|
|
707
709
|
| `create-text <name>` | Create a text note (`--text` or pipe via stdin) |
|
|
708
710
|
|
|
709
711
|
#### CLI options
|
package/dist/index.js
CHANGED
|
@@ -3185,7 +3185,7 @@ function register8(server, client) {
|
|
|
3185
3185
|
"list_meeting_events",
|
|
3186
3186
|
"List scheduled or completed meeting assistant events with filtering and pagination.",
|
|
3187
3187
|
{
|
|
3188
|
-
platformType: import_zod9.z.string().optional().describe("Filter by platform
|
|
3188
|
+
platformType: import_zod9.z.string().optional().describe("Filter by platform. Allowed values: zoom, googleMeet, microsoftTeams, webex. Comma-separate for multiple. Must match these exact strings \u2014 server validates strictly."),
|
|
3189
3189
|
meetingStatus: import_zod9.z.string().optional().describe("Filter by status (e.g. scheduled, completed, cancelled)"),
|
|
3190
3190
|
page: import_zod9.z.number().int().min(0).optional().describe("Page number (0-based, default: 0)"),
|
|
3191
3191
|
pageSize: import_zod9.z.number().int().min(1).max(500).optional().describe("Results per page (default: 20, max: 500)")
|
|
@@ -3312,7 +3312,7 @@ function register8(server, client) {
|
|
|
3312
3312
|
registerSpeakTool(
|
|
3313
3313
|
server,
|
|
3314
3314
|
"get_live_meeting_transcript",
|
|
3315
|
-
"
|
|
3315
|
+
"Fetch new sentences from an in-progress or just-ended meeting transcript. Identify the meeting via meetingAssistantEventId (preferred) or mediaId. Pass back the previous response's nextCursor as sinceEndInSec to receive only what's been added since.",
|
|
3316
3316
|
{
|
|
3317
3317
|
meetingAssistantEventId: import_zod9.z.string().optional().describe("Meeting assistant event id from list_meeting_events. Either this or mediaId is required."),
|
|
3318
3318
|
mediaId: import_zod9.z.string().optional().describe("Media id of the live meeting. Either this or meetingAssistantEventId is required."),
|
|
@@ -3338,7 +3338,7 @@ function register8(server, client) {
|
|
|
3338
3338
|
let meetingName;
|
|
3339
3339
|
if (meetingAssistantEventId) {
|
|
3340
3340
|
const eventsRes = await api.get("/v1/meeting-assistant/events", {
|
|
3341
|
-
params: { pageSize:
|
|
3341
|
+
params: { pageSize: 50, sortBy: "startTime:desc" }
|
|
3342
3342
|
});
|
|
3343
3343
|
const events = eventsRes.data?.data?.events ?? eventsRes.data?.events ?? [];
|
|
3344
3344
|
const event = events.find((e) => e.meetingAssistantEventId === meetingAssistantEventId);
|
|
@@ -5464,6 +5464,38 @@ function createCli() {
|
|
|
5464
5464
|
process.exit(1);
|
|
5465
5465
|
}
|
|
5466
5466
|
});
|
|
5467
|
+
program.command("list-meeting-events").description("List scheduled or completed meeting assistant events").option("-P, --platform <type>", "Filter by platform: zoom, googleMeet, microsoftTeams, webex (comma-separate for multiple)").option("-S, --status <status>", "Filter by meeting status (comma-separate for multiple)").option("-p, --page <n>", "Page number (0-based)", "0").option("-s, --page-size <n>", "Results per page", "20").option("--sort <field>", "Sort field", "startTime:desc").option("--json", "Output raw JSON").action(async (opts) => {
|
|
5468
|
+
requireApiKey();
|
|
5469
|
+
const client = await getClient();
|
|
5470
|
+
try {
|
|
5471
|
+
const params = {
|
|
5472
|
+
page: parseInt(opts.page),
|
|
5473
|
+
pageSize: parseInt(opts.pageSize),
|
|
5474
|
+
sortBy: opts.sort
|
|
5475
|
+
};
|
|
5476
|
+
if (opts.platform) params.platformType = opts.platform;
|
|
5477
|
+
if (opts.status) params.meetingStatus = opts.status;
|
|
5478
|
+
const res = await client.get("/v1/meeting-assistant/events", { params });
|
|
5479
|
+
const data = res.data?.data;
|
|
5480
|
+
if (opts.json) {
|
|
5481
|
+
printJson(data);
|
|
5482
|
+
return;
|
|
5483
|
+
}
|
|
5484
|
+
const events = data?.events ?? [];
|
|
5485
|
+
console.log(`Total: ${data?.totalCount ?? events.length}
|
|
5486
|
+
`);
|
|
5487
|
+
printTable(events, [
|
|
5488
|
+
{ key: "meetingAssistantEventId", label: "Event ID", width: 24 },
|
|
5489
|
+
{ key: "title", label: "Title", width: 32 },
|
|
5490
|
+
{ key: "platform", label: "Platform", width: 16 },
|
|
5491
|
+
{ key: "currentStatus", label: "Status", width: 18 },
|
|
5492
|
+
{ key: "startTime", label: "Start", width: 20 }
|
|
5493
|
+
]);
|
|
5494
|
+
} catch (err) {
|
|
5495
|
+
printError(err.response?.data?.message ?? err.message);
|
|
5496
|
+
process.exit(1);
|
|
5497
|
+
}
|
|
5498
|
+
});
|
|
5467
5499
|
program.command("schedule-meeting").description("Schedule AI assistant to join a meeting").argument("<url>", "Meeting URL (Zoom, Meet, Teams)").option("-t, --title <title>", "Meeting title").option("-d, --date <datetime>", "Meeting date/time (ISO 8601, omit to join now)").option("-l, --language <lang>", "Meeting language", "en-US").option("--json", "Output raw JSON").action(async (url, opts) => {
|
|
5468
5500
|
requireApiKey();
|
|
5469
5501
|
const client = await getClient();
|
|
@@ -5490,6 +5522,66 @@ function createCli() {
|
|
|
5490
5522
|
process.exit(1);
|
|
5491
5523
|
}
|
|
5492
5524
|
});
|
|
5525
|
+
program.command("live-transcript").description("Fetch new sentences from an in-progress or just-ended meeting").option("-e, --event-id <id>", "Meeting assistant event id (use `speakai-mcp list-meeting-events` to find it)").option("-m, --media-id <id>", "Media id (alternative to --event-id)").option("-s, --since-end-in-sec <seconds>", "nextCursor from previous call; omit on first call", parseFloat).option("--json", "Output raw JSON").action(async (opts) => {
|
|
5526
|
+
requireApiKey();
|
|
5527
|
+
const client = await getClient();
|
|
5528
|
+
if (!opts.eventId && !opts.mediaId) {
|
|
5529
|
+
printError("Provide --event-id or --media-id");
|
|
5530
|
+
process.exit(1);
|
|
5531
|
+
}
|
|
5532
|
+
try {
|
|
5533
|
+
let resolvedMediaId = opts.mediaId;
|
|
5534
|
+
let meetingStatus = null;
|
|
5535
|
+
let meetingName;
|
|
5536
|
+
if (opts.eventId) {
|
|
5537
|
+
const eventsRes = await client.get("/v1/meeting-assistant/events", {
|
|
5538
|
+
params: { pageSize: 50, sortBy: "startTime:desc" }
|
|
5539
|
+
});
|
|
5540
|
+
const events = eventsRes.data?.data?.events ?? eventsRes.data?.events ?? [];
|
|
5541
|
+
const event = events.find((e) => e.meetingAssistantEventId === opts.eventId);
|
|
5542
|
+
if (!event) {
|
|
5543
|
+
printError(`Meeting event not found: ${opts.eventId}`);
|
|
5544
|
+
process.exit(1);
|
|
5545
|
+
}
|
|
5546
|
+
meetingStatus = event.currentStatus ?? null;
|
|
5547
|
+
meetingName = event.title;
|
|
5548
|
+
const mediaRef = event.mediaId;
|
|
5549
|
+
resolvedMediaId = typeof mediaRef === "string" ? mediaRef : mediaRef?.mediaId;
|
|
5550
|
+
if (!resolvedMediaId) {
|
|
5551
|
+
printError("Meeting has no linked media yet \u2014 bot has not joined or started recording.");
|
|
5552
|
+
process.exit(1);
|
|
5553
|
+
}
|
|
5554
|
+
}
|
|
5555
|
+
const transcriptRes = await client.get(`/v1/media/transcript/${resolvedMediaId}`, {
|
|
5556
|
+
params: Number.isFinite(opts.sinceEndInSec) ? { sinceEndInSec: opts.sinceEndInSec } : void 0
|
|
5557
|
+
});
|
|
5558
|
+
const data = transcriptRes.data?.data ?? transcriptRes.data ?? {};
|
|
5559
|
+
const sentences = data?.insight?.transcript ?? [];
|
|
5560
|
+
const maxEnd = sentences.reduce((m, s) => Math.max(m, s.instances?.[0]?.endInSec ?? 0), 0);
|
|
5561
|
+
const nextCursor = sentences.length > 0 ? maxEnd : opts.sinceEndInSec ?? 0;
|
|
5562
|
+
const payload = {
|
|
5563
|
+
mediaId: resolvedMediaId,
|
|
5564
|
+
name: data?.name ?? meetingName ?? null,
|
|
5565
|
+
meetingStatus,
|
|
5566
|
+
isLive: meetingStatus === "inCallRecording",
|
|
5567
|
+
newSentences: sentences,
|
|
5568
|
+
nextCursor
|
|
5569
|
+
};
|
|
5570
|
+
if (opts.json) {
|
|
5571
|
+
printJson(payload);
|
|
5572
|
+
} else {
|
|
5573
|
+
console.log(`Meeting: ${payload.name ?? resolvedMediaId}`);
|
|
5574
|
+
console.log(`Status: ${payload.meetingStatus ?? "unknown"} (isLive=${payload.isLive})`);
|
|
5575
|
+
console.log(`New sentences: ${sentences.length} \u2022 nextCursor: ${nextCursor}`);
|
|
5576
|
+
for (const s of sentences) {
|
|
5577
|
+
console.log(` [${s.speakerId ?? "?"}] ${s.text ?? ""}`);
|
|
5578
|
+
}
|
|
5579
|
+
}
|
|
5580
|
+
} catch (err) {
|
|
5581
|
+
printError(err.response?.data?.message ?? err.message);
|
|
5582
|
+
process.exit(1);
|
|
5583
|
+
}
|
|
5584
|
+
});
|
|
5493
5585
|
return program;
|
|
5494
5586
|
}
|
|
5495
5587
|
var import_commander, import_readline;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@speakai/mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"mcpName": "io.github.speakai/mcp-server",
|
|
5
5
|
"description": "Official Speak AI MCP Server — capture meetings, search thousands of recordings, run async voice and video surveys, create clips, and automate workflows from your AI assistant.",
|
|
6
6
|
"homepage": "https://mcp.speakai.co",
|