screenpipe-mcp 0.18.7 → 0.18.9

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
@@ -148,7 +148,7 @@ Get a lightweight compressed activity overview for a time range:
148
148
  - Audio speaker summary
149
149
 
150
150
  ### list-meetings
151
- List detected meetings with duration, app, and attendees.
151
+ List detected meetings with duration, app, and attendees. Pass `q` to filter by substring (title, attendees, notes).
152
152
 
153
153
  ### search-elements
154
154
  Search structured UI elements (accessibility tree nodes and OCR text blocks):
package/dist/index.js CHANGED
@@ -326,13 +326,15 @@ const TOOLS = [
326
326
  {
327
327
  name: "list-meetings",
328
328
  description: "List detected meetings (Zoom, Teams, Meet, etc.) with duration, app, and attendees. " +
329
- "Only available when screenpipe runs in smart transcription mode.",
329
+ "Only available when screenpipe runs in smart transcription mode. " +
330
+ "Pass `q` to filter by substring match against title, attendees, and notes (e.g. an email or name).",
330
331
  annotations: { title: "List Meetings", readOnlyHint: true, openWorldHint: false, idempotentHint: true },
331
332
  inputSchema: {
332
333
  type: "object",
333
334
  properties: {
334
335
  start_time: { type: "string", description: "ISO 8601 UTC or relative (e.g. '1d ago')" },
335
336
  end_time: { type: "string", description: "ISO 8601 UTC or relative" },
337
+ q: { type: "string", description: "Case-insensitive substring filter on title, attendees, and note" },
336
338
  limit: { type: "integer", description: "Max results (default 20)", default: 20 },
337
339
  offset: { type: "integer", description: "Pagination offset", default: 0 },
338
340
  },
@@ -683,24 +685,46 @@ const TEAM_TOOLS = [
683
685
  },
684
686
  {
685
687
  name: "team-records",
686
- description: "Chronological raw dump of the org's telemetry for a time window. " +
687
- "Returns oldest newest (vs team-search which is recency-ranked). " +
688
- "Use for ETL or \"walk me through X from Y to Z\" — NOT for question-answering, use team-search for that. " +
688
+ description: "Chronological dump of the org's data for a time window — both raw " +
689
+ "telemetry (frame/audio) and the structured outputs of the enterprise-" +
690
+ "worker pipes (sop/skill/trajectory/memory/workflow). " +
691
+ "Raw kinds return oldest → newest (vs team-search which is recency-ranked). " +
692
+ "Synthesized kinds return one record per device's latest run by default " +
693
+ "(set latest_only=false to walk run history). " +
694
+ "Use raw for ETL / \"walk me through X from Y to Z\". " +
695
+ "Use synthesized for \"what SOPs / skills / trajectories / memories did " +
696
+ "we extract from my team's work\" — each item carries evidence-cited " +
697
+ "event_ids/frame_ids that team-search can resolve back to raw records. " +
689
698
  "Auth: enterprise admin token.",
690
699
  annotations: { title: "Team Records", readOnlyHint: true, openWorldHint: true, idempotentHint: true },
691
700
  inputSchema: {
692
701
  type: "object",
693
702
  properties: {
694
- device_id: { type: "string", description: "Restrict to one device (optional)." },
695
- kind: { type: "string", enum: ["frame", "audio", "all"], description: "Record kind filter. Default: all.", default: "all" },
696
- since: { type: "string", description: "ISO 8601 lower bound." },
697
- until: { type: "string", description: "ISO 8601 upper bound." },
698
- since_hours_ago: { type: "integer", description: "Convenience: equivalent to since=now-N*h." },
699
- limit: { type: "integer", description: "Max records (default 50, max 200).", default: 50 },
703
+ device_id: { type: "string", description: "Restrict to one device (optional). Raw kinds only." },
704
+ kind: {
705
+ type: "string",
706
+ enum: ["frame", "audio", "all", "sop", "skill", "trajectory", "memory", "workflow"],
707
+ description: "What to return. Raw: frame|audio|all (telemetry). " +
708
+ "Synthesized: sop|skill|trajectory|memory|workflow (pipe outputs). " +
709
+ "Default: all.",
710
+ default: "all",
711
+ },
712
+ since: { type: "string", description: "ISO 8601 lower bound. Raw kinds only." },
713
+ until: { type: "string", description: "ISO 8601 upper bound. Raw kinds only." },
714
+ since_hours_ago: { type: "integer", description: "Convenience: equivalent to since=now-N*h. Raw kinds only." },
715
+ limit: { type: "integer", description: "Max records (default 50, max 200). Raw kinds only.", default: 50 },
716
+ latest_only: {
717
+ type: "boolean",
718
+ description: "Synthesized kinds only: if true (default), collapse to the newest " +
719
+ "run per device. Set false to walk run history.",
720
+ default: true,
721
+ },
700
722
  },
701
723
  },
702
724
  },
703
725
  ];
726
+ // Pipe-output kinds map to /workflows/generated, raw kinds map to /records.
727
+ const SYNTHESIZED_KINDS = new Set(["sop", "skill", "trajectory", "memory", "workflow"]);
704
728
  server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
705
729
  // Team tools only surface when an enterprise token was discovered at boot.
706
730
  // No token = consumer / non-admin user; their MCP looks identical to today.
@@ -1554,7 +1578,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1554
1578
  };
1555
1579
  }
1556
1580
  const response = await callAPI(`/meetings/${meetingId}`, {
1557
- method: "PATCH",
1581
+ method: "PUT",
1558
1582
  headers: { "Content-Type": "application/json" },
1559
1583
  body: JSON.stringify(body),
1560
1584
  });
@@ -1679,10 +1703,15 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1679
1703
  ],
1680
1704
  };
1681
1705
  }
1682
- // Map MCP tool name → /api/enterprise/v1 path
1706
+ // Map MCP tool name → /api/enterprise/v1 path. team-records also
1707
+ // routes synthesized pipe outputs (kind=sop|skill|...) to the
1708
+ // workflows endpoint so callers see one tool surface for "give me
1709
+ // the org's data."
1710
+ const kindArg = typeof args.kind === "string" ? args.kind : "";
1683
1711
  const subpath = name === "team-search" ? "/search"
1684
1712
  : name === "team-devices" ? "/devices"
1685
- : "/records";
1713
+ : name === "team-records" && SYNTHESIZED_KINDS.has(kindArg) ? "/workflows/generated"
1714
+ : "/records";
1686
1715
  // Forward every primitive arg as a query param. The server validates;
1687
1716
  // unknown params are ignored, so we don't need to gatekeep here.
1688
1717
  const params = new URLSearchParams();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screenpipe-mcp",
3
- "version": "0.18.7",
3
+ "version": "0.18.9",
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
@@ -314,13 +314,15 @@ const TOOLS: Tool[] = [
314
314
  name: "list-meetings",
315
315
  description:
316
316
  "List detected meetings (Zoom, Teams, Meet, etc.) with duration, app, and attendees. " +
317
- "Only available when screenpipe runs in smart transcription mode.",
317
+ "Only available when screenpipe runs in smart transcription mode. " +
318
+ "Pass `q` to filter by substring match against title, attendees, and notes (e.g. an email or name).",
318
319
  annotations: { title: "List Meetings", readOnlyHint: true, openWorldHint: false, idempotentHint: true },
319
320
  inputSchema: {
320
321
  type: "object",
321
322
  properties: {
322
323
  start_time: { type: "string", description: "ISO 8601 UTC or relative (e.g. '1d ago')" },
323
324
  end_time: { type: "string", description: "ISO 8601 UTC or relative" },
325
+ q: { type: "string", description: "Case-insensitive substring filter on title, attendees, and note" },
324
326
  limit: { type: "integer", description: "Max results (default 20)", default: 20 },
325
327
  offset: { type: "integer", description: "Pagination offset", default: 0 },
326
328
  },
@@ -688,25 +690,50 @@ const TEAM_TOOLS: Tool[] = [
688
690
  {
689
691
  name: "team-records",
690
692
  description:
691
- "Chronological raw dump of the org's telemetry for a time window. " +
692
- "Returns oldest newest (vs team-search which is recency-ranked). " +
693
- "Use for ETL or \"walk me through X from Y to Z\" — NOT for question-answering, use team-search for that. " +
693
+ "Chronological dump of the org's data for a time window — both raw " +
694
+ "telemetry (frame/audio) and the structured outputs of the enterprise-" +
695
+ "worker pipes (sop/skill/trajectory/memory/workflow). " +
696
+ "Raw kinds return oldest → newest (vs team-search which is recency-ranked). " +
697
+ "Synthesized kinds return one record per device's latest run by default " +
698
+ "(set latest_only=false to walk run history). " +
699
+ "Use raw for ETL / \"walk me through X from Y to Z\". " +
700
+ "Use synthesized for \"what SOPs / skills / trajectories / memories did " +
701
+ "we extract from my team's work\" — each item carries evidence-cited " +
702
+ "event_ids/frame_ids that team-search can resolve back to raw records. " +
694
703
  "Auth: enterprise admin token.",
695
704
  annotations: { title: "Team Records", readOnlyHint: true, openWorldHint: true, idempotentHint: true },
696
705
  inputSchema: {
697
706
  type: "object",
698
707
  properties: {
699
- device_id: { type: "string", description: "Restrict to one device (optional)." },
700
- kind: { type: "string", enum: ["frame", "audio", "all"], description: "Record kind filter. Default: all.", default: "all" },
701
- since: { type: "string", description: "ISO 8601 lower bound." },
702
- until: { type: "string", description: "ISO 8601 upper bound." },
703
- since_hours_ago: { type: "integer", description: "Convenience: equivalent to since=now-N*h." },
704
- limit: { type: "integer", description: "Max records (default 50, max 200).", default: 50 },
708
+ device_id: { type: "string", description: "Restrict to one device (optional). Raw kinds only." },
709
+ kind: {
710
+ type: "string",
711
+ enum: ["frame", "audio", "all", "sop", "skill", "trajectory", "memory", "workflow"],
712
+ description:
713
+ "What to return. Raw: frame|audio|all (telemetry). " +
714
+ "Synthesized: sop|skill|trajectory|memory|workflow (pipe outputs). " +
715
+ "Default: all.",
716
+ default: "all",
717
+ },
718
+ since: { type: "string", description: "ISO 8601 lower bound. Raw kinds only." },
719
+ until: { type: "string", description: "ISO 8601 upper bound. Raw kinds only." },
720
+ since_hours_ago: { type: "integer", description: "Convenience: equivalent to since=now-N*h. Raw kinds only." },
721
+ limit: { type: "integer", description: "Max records (default 50, max 200). Raw kinds only.", default: 50 },
722
+ latest_only: {
723
+ type: "boolean",
724
+ description:
725
+ "Synthesized kinds only: if true (default), collapse to the newest " +
726
+ "run per device. Set false to walk run history.",
727
+ default: true,
728
+ },
705
729
  },
706
730
  },
707
731
  },
708
732
  ];
709
733
 
734
+ // Pipe-output kinds map to /workflows/generated, raw kinds map to /records.
735
+ const SYNTHESIZED_KINDS = new Set(["sop", "skill", "trajectory", "memory", "workflow"]);
736
+
710
737
  server.setRequestHandler(ListToolsRequestSchema, async () => {
711
738
  // Team tools only surface when an enterprise token was discovered at boot.
712
739
  // No token = consumer / non-admin user; their MCP looks identical to today.
@@ -1693,7 +1720,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1693
1720
  };
1694
1721
  }
1695
1722
  const response = await callAPI(`/meetings/${meetingId}`, {
1696
- method: "PATCH",
1723
+ method: "PUT",
1697
1724
  headers: { "Content-Type": "application/json" },
1698
1725
  body: JSON.stringify(body),
1699
1726
  });
@@ -1818,10 +1845,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1818
1845
  ],
1819
1846
  };
1820
1847
  }
1821
- // Map MCP tool name → /api/enterprise/v1 path
1848
+ // Map MCP tool name → /api/enterprise/v1 path. team-records also
1849
+ // routes synthesized pipe outputs (kind=sop|skill|...) to the
1850
+ // workflows endpoint so callers see one tool surface for "give me
1851
+ // the org's data."
1852
+ const kindArg = typeof args.kind === "string" ? args.kind : "";
1822
1853
  const subpath =
1823
1854
  name === "team-search" ? "/search"
1824
1855
  : name === "team-devices" ? "/devices"
1856
+ : name === "team-records" && SYNTHESIZED_KINDS.has(kindArg) ? "/workflows/generated"
1825
1857
  : "/records";
1826
1858
  // Forward every primitive arg as a query param. The server validates;
1827
1859
  // unknown params are ignored, so we don't need to gatekeep here.