screenpipe-mcp 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -437,6 +437,30 @@ const TOOLS = [
437
437
  required: ["id"],
438
438
  },
439
439
  },
440
+ {
441
+ name: "update-meeting",
442
+ description: "Update a meeting's mutable fields (title, attendees, note, app, start/end). Partial: only the fields you pass are written, " +
443
+ "others stay as-is. Use this to save an AI-generated summary into the meeting note — read the current note first via get-meeting " +
444
+ "and pass the existing notes plus your additions so you don't overwrite the user's writing. " +
445
+ "Convention: append AI-generated summary text under a `## Summary` heading at the bottom of the existing note.",
446
+ annotations: { title: "Update Meeting", readOnlyHint: false, destructiveHint: false, openWorldHint: false, idempotentHint: true },
447
+ inputSchema: {
448
+ type: "object",
449
+ properties: {
450
+ id: { type: "integer", description: "Meeting ID" },
451
+ title: { type: "string", description: "Meeting title" },
452
+ attendees: { type: "string", description: "Comma-separated attendee names" },
453
+ note: {
454
+ type: "string",
455
+ description: "Full new note body. To preserve existing notes, fetch them first via get-meeting and concatenate before passing.",
456
+ },
457
+ meeting_app: { type: "string", description: "App / source name (e.g. 'meet.google.com', 'manual')" },
458
+ meeting_start: { type: "string", description: "ISO 8601 start time (rarely needed)" },
459
+ meeting_end: { type: "string", description: "ISO 8601 end time (rarely needed)" },
460
+ },
461
+ required: ["id"],
462
+ },
463
+ },
440
464
  {
441
465
  name: "keyword-search",
442
466
  description: "Fast keyword search using FTS index. Faster than search-content for exact keyword matching. " +
@@ -1186,6 +1210,39 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1186
1210
  content: [{ type: "text", text: JSON.stringify(meeting, null, 2) }],
1187
1211
  };
1188
1212
  }
1213
+ case "update-meeting": {
1214
+ const meetingId = args.id;
1215
+ if (!meetingId) {
1216
+ return { content: [{ type: "text", text: "Error: id is required" }] };
1217
+ }
1218
+ // Build partial body — only forward fields the caller provided.
1219
+ const body = {};
1220
+ for (const k of ["title", "attendees", "note", "meeting_app", "meeting_start", "meeting_end"]) {
1221
+ if (args[k] !== undefined && args[k] !== null)
1222
+ body[k] = args[k];
1223
+ }
1224
+ if (Object.keys(body).length === 0) {
1225
+ return {
1226
+ content: [
1227
+ {
1228
+ type: "text",
1229
+ text: "Error: pass at least one field to update (title, attendees, note, meeting_app, meeting_start, meeting_end).",
1230
+ },
1231
+ ],
1232
+ };
1233
+ }
1234
+ const response = await fetchAPI(`/meetings/${meetingId}`, {
1235
+ method: "PATCH",
1236
+ headers: { "Content-Type": "application/json" },
1237
+ body: JSON.stringify(body),
1238
+ });
1239
+ if (!response.ok)
1240
+ throw new Error(`HTTP error: ${response.status}`);
1241
+ const updated = await response.json();
1242
+ return {
1243
+ content: [{ type: "text", text: JSON.stringify(updated, null, 2) }],
1244
+ };
1245
+ }
1189
1246
  case "keyword-search": {
1190
1247
  const params = new URLSearchParams();
1191
1248
  for (const [key, value] of Object.entries(args)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screenpipe-mcp",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "MCP server for screenpipe - search your screen recordings and audio transcriptions",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -426,6 +426,32 @@ const TOOLS: Tool[] = [
426
426
  required: ["id"],
427
427
  },
428
428
  },
429
+ {
430
+ name: "update-meeting",
431
+ description:
432
+ "Update a meeting's mutable fields (title, attendees, note, app, start/end). Partial: only the fields you pass are written, " +
433
+ "others stay as-is. Use this to save an AI-generated summary into the meeting note — read the current note first via get-meeting " +
434
+ "and pass the existing notes plus your additions so you don't overwrite the user's writing. " +
435
+ "Convention: append AI-generated summary text under a `## Summary` heading at the bottom of the existing note.",
436
+ annotations: { title: "Update Meeting", readOnlyHint: false, destructiveHint: false, openWorldHint: false, idempotentHint: true },
437
+ inputSchema: {
438
+ type: "object",
439
+ properties: {
440
+ id: { type: "integer", description: "Meeting ID" },
441
+ title: { type: "string", description: "Meeting title" },
442
+ attendees: { type: "string", description: "Comma-separated attendee names" },
443
+ note: {
444
+ type: "string",
445
+ description:
446
+ "Full new note body. To preserve existing notes, fetch them first via get-meeting and concatenate before passing.",
447
+ },
448
+ meeting_app: { type: "string", description: "App / source name (e.g. 'meet.google.com', 'manual')" },
449
+ meeting_start: { type: "string", description: "ISO 8601 start time (rarely needed)" },
450
+ meeting_end: { type: "string", description: "ISO 8601 end time (rarely needed)" },
451
+ },
452
+ required: ["id"],
453
+ },
454
+ },
429
455
  {
430
456
  name: "keyword-search",
431
457
  description:
@@ -1296,6 +1322,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1296
1322
  };
1297
1323
  }
1298
1324
 
1325
+ case "update-meeting": {
1326
+ const meetingId = args.id as number;
1327
+ if (!meetingId) {
1328
+ return { content: [{ type: "text", text: "Error: id is required" }] };
1329
+ }
1330
+ // Build partial body — only forward fields the caller provided.
1331
+ const body: Record<string, unknown> = {};
1332
+ for (const k of ["title", "attendees", "note", "meeting_app", "meeting_start", "meeting_end"] as const) {
1333
+ if (args[k] !== undefined && args[k] !== null) body[k] = args[k];
1334
+ }
1335
+ if (Object.keys(body).length === 0) {
1336
+ return {
1337
+ content: [
1338
+ {
1339
+ type: "text",
1340
+ text: "Error: pass at least one field to update (title, attendees, note, meeting_app, meeting_start, meeting_end).",
1341
+ },
1342
+ ],
1343
+ };
1344
+ }
1345
+ const response = await fetchAPI(`/meetings/${meetingId}`, {
1346
+ method: "PATCH",
1347
+ headers: { "Content-Type": "application/json" },
1348
+ body: JSON.stringify(body),
1349
+ });
1350
+ if (!response.ok) throw new Error(`HTTP error: ${response.status}`);
1351
+ const updated = await response.json();
1352
+ return {
1353
+ content: [{ type: "text", text: JSON.stringify(updated, null, 2) }],
1354
+ };
1355
+ }
1356
+
1299
1357
  case "keyword-search": {
1300
1358
  const params = new URLSearchParams();
1301
1359
  for (const [key, value] of Object.entries(args)) {