screenpipe-mcp 0.18.14 → 0.18.15
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 +17 -6
- package/bun.lock +59 -0
- package/dist/cli.js +5 -1
- package/dist/http-server.js +6 -0
- package/dist/index.js +89 -16
- package/dist/telemetry.d.ts +21 -0
- package/dist/telemetry.js +199 -0
- package/dist/telemetry.test.d.ts +1 -0
- package/dist/telemetry.test.js +61 -0
- package/manifest.json +1 -1
- package/package.json +3 -2
- package/server.json +2 -2
- package/src/cli.ts +10 -1
- package/src/http-server.ts +11 -0
- package/src/index.ts +98 -16
- package/src/telemetry.test.ts +70 -0
- package/src/telemetry.ts +192 -0
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
|
|
151
|
+
List detected meetings with id, duration, app, attendees, and note snippet. Pass `q` to filter by substring (title, attendees, notes) — `q` searches all meeting history, so omit the time range when looking for a person or topic. Follow up with `get-meeting` (optionally `include_transcript: true`) for the full note and speaker-attributed transcript.
|
|
152
152
|
|
|
153
153
|
### search-elements
|
|
154
154
|
Search structured UI elements (accessibility tree nodes and OCR text blocks):
|
|
@@ -190,8 +190,9 @@ Get accessibility text, parsed tree nodes, and extracted URLs for a specific fra
|
|
|
190
190
|
## Privacy Policy
|
|
191
191
|
|
|
192
192
|
The Screenpipe MCP server is a local-only bridge between Claude and your
|
|
193
|
-
local Screenpipe instance. It does not collect, transmit, or store
|
|
194
|
-
|
|
193
|
+
local Screenpipe instance. It does not collect, transmit, or store tool
|
|
194
|
+
results, recordings, OCR text, audio transcripts, screenshots, or UI events
|
|
195
|
+
on its own.
|
|
195
196
|
|
|
196
197
|
### What this MCP server does
|
|
197
198
|
When Claude invokes a tool (`search-content`, `activity-summary`, etc.)
|
|
@@ -200,7 +201,16 @@ Screenpipe daemon running on your machine — and returns the response.
|
|
|
200
201
|
That's the entire data path.
|
|
201
202
|
|
|
202
203
|
### Data collection
|
|
203
|
-
|
|
204
|
+
The MCP server sends privacy-preserving crash and error reports to Screenpipe's
|
|
205
|
+
Sentry project so we can diagnose startup failures like "server disconnected"
|
|
206
|
+
or "could not attach to MCP server". These reports include the MCP package
|
|
207
|
+
version, runtime, transport mode, and sanitized exception details. They do not
|
|
208
|
+
include tool arguments, tool results, screen content, audio, transcripts,
|
|
209
|
+
screenshots, API tokens, or your home-directory path.
|
|
210
|
+
|
|
211
|
+
To disable crash/error reporting, set any of:
|
|
212
|
+
`SCREENPIPE_MCP_SENTRY_DISABLED=1`, `SCREENPIPE_TELEMETRY_DISABLED=1`, or
|
|
213
|
+
`SCREENPIPE_DISABLE_TELEMETRY=1` in the MCP launch environment.
|
|
204
214
|
|
|
205
215
|
### Data usage
|
|
206
216
|
Tool calls are passed straight through to your local Screenpipe daemon
|
|
@@ -215,8 +225,9 @@ whatever you configure inside the Screenpipe app — typically you
|
|
|
215
225
|
control it via the storage settings panel.
|
|
216
226
|
|
|
217
227
|
### Third-party sharing
|
|
218
|
-
|
|
219
|
-
|
|
228
|
+
The MCP server talks to `localhost:3030` for tool calls and to Screenpipe's
|
|
229
|
+
Sentry project for sanitized crash/error reports unless disabled as above.
|
|
230
|
+
It does not contact Anthropic or send recorded content to Screenpipe's servers.
|
|
220
231
|
If you choose to enable optional cloud features inside the Screenpipe
|
|
221
232
|
app itself (e.g. cloud sync, cloud AI), those are governed by the
|
|
222
233
|
Screenpipe app's privacy policy, not this MCP server's data flow.
|
package/bun.lock
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"name": "screenpipe-mcp",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
9
|
+
"@sentry/node": "^10.64.0",
|
|
9
10
|
},
|
|
10
11
|
"devDependencies": {
|
|
11
12
|
"@types/node": "^25.3.5",
|
|
@@ -16,6 +17,12 @@
|
|
|
16
17
|
},
|
|
17
18
|
},
|
|
18
19
|
"packages": {
|
|
20
|
+
"@apm-js-collab/code-transformer": ["@apm-js-collab/code-transformer@0.15.0", "", { "dependencies": { "@types/estree": "^1.0.8", "astring": "^1.9.0", "esquery": "^1.7.0", "meriyah": "^6.1.4", "semifies": "^1.0.0", "source-map": "^0.6.0" }, "bin": { "code-transformer": "cli.js" } }, "sha512-XmXYVs8CzJ1Aj79noVbn2weUO/XWtRyURpGqx7aU7DOXlUQhR0WKOQNF0okh7PCeY37vxf7kU3v57OAkEPm3ww=="],
|
|
21
|
+
|
|
22
|
+
"@apm-js-collab/code-transformer-bundler-plugins": ["@apm-js-collab/code-transformer-bundler-plugins@0.5.0", "", { "dependencies": { "@apm-js-collab/code-transformer": "^0.15.0", "es-module-lexer": "^2.1.0", "magic-string": "^0.30.21", "module-details-from-path": "^1.0.4" } }, "sha512-YxLBY5nGlurL7QeJLq6e5g0ouBpAp0pwgyA/5rHXEXwhiPLn9ZHbT+Y2LlP90GT872cSocfjWRYu/fnpuBudNQ=="],
|
|
23
|
+
|
|
24
|
+
"@apm-js-collab/tracing-hooks": ["@apm-js-collab/tracing-hooks@0.10.1", "", { "dependencies": { "@apm-js-collab/code-transformer": "^0.15.0", "debug": "^4.4.1", "module-details-from-path": "^1.0.4" } }, "sha512-w2OWXR7FWrKqSziuE9+QclaZrStxO/8+OwbXM635s/zs0Eez1Qo3ivSPdB2WsaPY/iznKTytONPx/PitD7IXcA=="],
|
|
25
|
+
|
|
19
26
|
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
|
|
20
27
|
|
|
21
28
|
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
|
|
@@ -80,6 +87,22 @@
|
|
|
80
87
|
|
|
81
88
|
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.27.1", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA=="],
|
|
82
89
|
|
|
90
|
+
"@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="],
|
|
91
|
+
|
|
92
|
+
"@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.220.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-CmVa4ImJ+ynfrPMNaAXHET6Bhb44SwzmfyVJFq9ni2jgXJR/l7C6gfVFddNmHP+ZOkP9cf4f9DBe68qVLTHc9w=="],
|
|
93
|
+
|
|
94
|
+
"@opentelemetry/core": ["@opentelemetry/core@2.9.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-m2nckMT80NnmjTYSPjJQObBJ+8dgkoajEOUbznL8AHZ3T3yHRk2P7gI1PhEBc1+lOnrYE9UWrWHqJDsmqjmNbw=="],
|
|
95
|
+
|
|
96
|
+
"@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.220.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.220.0", "import-in-the-middle": "^3.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-xQx3E2WxP1mDvKzxLxX+CTCtNLa560YJZ3087qYHerl2YmiKpv7AH+dAy7vmx+eVrZ5BwhfWUAVoKOoxCNHcpw=="],
|
|
97
|
+
|
|
98
|
+
"@opentelemetry/resources": ["@opentelemetry/resources@2.9.0", "", { "dependencies": { "@opentelemetry/core": "2.9.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-jyA5MBLQ+Dkl3+JsZkUoUvL7yHvU64kLsvpXKarWm6347Sl1t1bXFTFykUePNpT5WH5pm9a2Qtt03iIYQhZ1Fg=="],
|
|
99
|
+
|
|
100
|
+
"@opentelemetry/sdk-trace": ["@opentelemetry/sdk-trace@2.9.0", "", { "dependencies": { "@opentelemetry/core": "2.9.0", "@opentelemetry/resources": "2.9.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-sGA19HvtrrSKYsseHphluH6j3p6Xa3fqc7c7y8f/7mYWejc1lyDFcpSdD1kYa50HCLUeEo4zA5bW0pniaPszuw=="],
|
|
101
|
+
|
|
102
|
+
"@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.9.0", "", { "dependencies": { "@opentelemetry/core": "2.9.0", "@opentelemetry/resources": "2.9.0", "@opentelemetry/sdk-trace": "2.9.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-cp9zmTl62R8PJrpvFcmc8N2JQU/xfa0S+61q511Nji+QxCfZ8Ifvg7H27G8cANe4crg4RTrWsVvanHiXjSp6ag=="],
|
|
103
|
+
|
|
104
|
+
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.42.0", "", {}, "sha512-icc5xCzndZfhuJMy5oqk5AvloWquR7jtae74qzpkKkhGp8BivK+oCcEXgGnjCdTfp8hA44l+w8gE8yYJbocJJw=="],
|
|
105
|
+
|
|
83
106
|
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.56.0", "", { "os": "android", "cpu": "arm" }, "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw=="],
|
|
84
107
|
|
|
85
108
|
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.56.0", "", { "os": "android", "cpu": "arm64" }, "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q=="],
|
|
@@ -130,6 +153,18 @@
|
|
|
130
153
|
|
|
131
154
|
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.56.0", "", { "os": "win32", "cpu": "x64" }, "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g=="],
|
|
132
155
|
|
|
156
|
+
"@sentry/conventions": ["@sentry/conventions@0.15.1", "", {}, "sha512-ZLP8bRdMON3prWE2tJyImuYscCxdcJeIPIhrOs/rgyFm3C1nCh1B6gdvPj3AZ5zW08oSFFCsq7T+tYEW3h8MNA=="],
|
|
157
|
+
|
|
158
|
+
"@sentry/core": ["@sentry/core@10.64.0", "", { "dependencies": { "@sentry/conventions": "^0.15.1" } }, "sha512-HjojJcXD1l2qZ1AXje2s0XY/nYsaUt00wsM1HMBImA8vAClyPisFE/CC0/UD6pEvsGFhVgi8Dcxo7EN41uyeFw=="],
|
|
159
|
+
|
|
160
|
+
"@sentry/node": ["@sentry/node@10.64.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/instrumentation": "^0.220.0", "@opentelemetry/sdk-trace-base": "^2.9.0", "@sentry/conventions": "^0.15.1", "@sentry/core": "10.64.0", "@sentry/node-core": "10.64.0", "@sentry/opentelemetry": "10.64.0", "@sentry/server-utils": "10.64.0", "import-in-the-middle": "^3.0.0" } }, "sha512-rhNZ3CTqwdTQHo9Zd+NsoLyW69VIzbMcGMRX9y8W1A6runT4YH/MDhmT0U9oWfNZKN8ngqR/gfVMTnlYVQliCA=="],
|
|
161
|
+
|
|
162
|
+
"@sentry/node-core": ["@sentry/node-core@10.64.0", "", { "dependencies": { "@sentry/conventions": "^0.15.1", "@sentry/core": "10.64.0", "@sentry/opentelemetry": "10.64.0", "import-in-the-middle": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/core", "@opentelemetry/exporter-trace-otlp-http", "@opentelemetry/instrumentation", "@opentelemetry/sdk-trace-base"] }, "sha512-dcma5uEWl0SXywY4vzrlOwuz4NBPyPhrzqL1NjlU6Di/OVbyYAZJPCwsR8XYDz73PGc5sU3qKSRoXWX56Ip0wA=="],
|
|
163
|
+
|
|
164
|
+
"@sentry/opentelemetry": ["@sentry/opentelemetry@10.64.0", "", { "dependencies": { "@sentry/conventions": "^0.15.1", "@sentry/core": "10.64.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0" } }, "sha512-hXw8dwSSA9/9r3VGy0PO2SJp7g5/yH2+7Bak60EkOT21AT1BwFnVEsVQyZb+UHjG7UWne/jDbwdWPSUm/rtovw=="],
|
|
165
|
+
|
|
166
|
+
"@sentry/server-utils": ["@sentry/server-utils@10.64.0", "", { "dependencies": { "@apm-js-collab/code-transformer": "^0.15.0", "@apm-js-collab/code-transformer-bundler-plugins": "^0.5.0", "@apm-js-collab/tracing-hooks": "^0.10.1", "@sentry/conventions": "^0.15.1", "@sentry/core": "10.64.0", "magic-string": "~0.30.0" } }, "sha512-d568Jhn3WBfm07dsdPsLh0q+qRj71xZEDZFsA33kizD0UuSCR8axtc2YW6aKdPhtuqgm9tHjSX35Q9vK/XmujA=="],
|
|
167
|
+
|
|
133
168
|
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
|
134
169
|
|
|
135
170
|
"@tsconfig/node10": ["@tsconfig/node10@1.0.12", "", {}, "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ=="],
|
|
@@ -176,6 +211,8 @@
|
|
|
176
211
|
|
|
177
212
|
"assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
|
|
178
213
|
|
|
214
|
+
"astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="],
|
|
215
|
+
|
|
179
216
|
"body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
|
|
180
217
|
|
|
181
218
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
|
@@ -186,6 +223,8 @@
|
|
|
186
223
|
|
|
187
224
|
"chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
|
|
188
225
|
|
|
226
|
+
"cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="],
|
|
227
|
+
|
|
189
228
|
"content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
|
|
190
229
|
|
|
191
230
|
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
|
@@ -224,6 +263,10 @@
|
|
|
224
263
|
|
|
225
264
|
"escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
|
|
226
265
|
|
|
266
|
+
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
|
267
|
+
|
|
268
|
+
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
|
269
|
+
|
|
227
270
|
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
|
228
271
|
|
|
229
272
|
"etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
|
|
@@ -270,6 +313,8 @@
|
|
|
270
313
|
|
|
271
314
|
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
|
272
315
|
|
|
316
|
+
"import-in-the-middle": ["import-in-the-middle@3.3.1", "", { "dependencies": { "cjs-module-lexer": "^2.2.0", "es-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-0rymlHSFLwZ0ixx8DaQkoIyZojJPY2a0K2nEYslhKJ6jIYO/m0IcCb7iQsFPmS7WmKwISZiIrv5Icstrw/CmqA=="],
|
|
317
|
+
|
|
273
318
|
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
|
274
319
|
|
|
275
320
|
"ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
|
|
@@ -296,10 +341,14 @@
|
|
|
296
341
|
|
|
297
342
|
"merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
|
|
298
343
|
|
|
344
|
+
"meriyah": ["meriyah@6.1.4", "", {}, "sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ=="],
|
|
345
|
+
|
|
299
346
|
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
|
300
347
|
|
|
301
348
|
"mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
|
302
349
|
|
|
350
|
+
"module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="],
|
|
351
|
+
|
|
303
352
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
304
353
|
|
|
305
354
|
"nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
|
@@ -342,12 +391,16 @@
|
|
|
342
391
|
|
|
343
392
|
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
|
|
344
393
|
|
|
394
|
+
"require-in-the-middle": ["require-in-the-middle@8.0.1", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3" } }, "sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ=="],
|
|
395
|
+
|
|
345
396
|
"rollup": ["rollup@4.56.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.56.0", "@rollup/rollup-android-arm64": "4.56.0", "@rollup/rollup-darwin-arm64": "4.56.0", "@rollup/rollup-darwin-x64": "4.56.0", "@rollup/rollup-freebsd-arm64": "4.56.0", "@rollup/rollup-freebsd-x64": "4.56.0", "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", "@rollup/rollup-linux-arm-musleabihf": "4.56.0", "@rollup/rollup-linux-arm64-gnu": "4.56.0", "@rollup/rollup-linux-arm64-musl": "4.56.0", "@rollup/rollup-linux-loong64-gnu": "4.56.0", "@rollup/rollup-linux-loong64-musl": "4.56.0", "@rollup/rollup-linux-ppc64-gnu": "4.56.0", "@rollup/rollup-linux-ppc64-musl": "4.56.0", "@rollup/rollup-linux-riscv64-gnu": "4.56.0", "@rollup/rollup-linux-riscv64-musl": "4.56.0", "@rollup/rollup-linux-s390x-gnu": "4.56.0", "@rollup/rollup-linux-x64-gnu": "4.56.0", "@rollup/rollup-linux-x64-musl": "4.56.0", "@rollup/rollup-openbsd-x64": "4.56.0", "@rollup/rollup-openharmony-arm64": "4.56.0", "@rollup/rollup-win32-arm64-msvc": "4.56.0", "@rollup/rollup-win32-ia32-msvc": "4.56.0", "@rollup/rollup-win32-x64-gnu": "4.56.0", "@rollup/rollup-win32-x64-msvc": "4.56.0", "fsevents": "~2.3.2" }, "bin": "dist/bin/rollup" }, "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg=="],
|
|
346
397
|
|
|
347
398
|
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
|
|
348
399
|
|
|
349
400
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
|
350
401
|
|
|
402
|
+
"semifies": ["semifies@1.0.0", "", {}, "sha512-xXR3KGeoxTNWPD4aBvL5NUpMTT7WMANr3EWnaS190QVkY52lqqcVRD7Q05UVbBhiWDGWMlJEUam9m7uFFGVScw=="],
|
|
403
|
+
|
|
351
404
|
"send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
|
|
352
405
|
|
|
353
406
|
"serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
|
|
@@ -368,6 +421,8 @@
|
|
|
368
421
|
|
|
369
422
|
"siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
|
|
370
423
|
|
|
424
|
+
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
|
425
|
+
|
|
371
426
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
|
372
427
|
|
|
373
428
|
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
|
@@ -415,5 +470,9 @@
|
|
|
415
470
|
"zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="],
|
|
416
471
|
|
|
417
472
|
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
|
473
|
+
|
|
474
|
+
"@apm-js-collab/code-transformer-bundler-plugins/es-module-lexer": ["es-module-lexer@2.3.0", "", {}, "sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw=="],
|
|
475
|
+
|
|
476
|
+
"import-in-the-middle/es-module-lexer": ["es-module-lexer@2.3.0", "", {}, "sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw=="],
|
|
418
477
|
}
|
|
419
478
|
}
|
package/dist/cli.js
CHANGED
|
@@ -24,8 +24,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
24
24
|
* or `dist/http-server.js`); this dispatcher just gives users the
|
|
25
25
|
* working one-liner they expected.
|
|
26
26
|
*/
|
|
27
|
+
const telemetry_js_1 = require("./telemetry.js");
|
|
27
28
|
async function main() {
|
|
28
29
|
const argv = process.argv.slice(2);
|
|
30
|
+
(0, telemetry_js_1.initMcpTelemetry)({ transport: argv.includes("--http") ? "http" : "stdio" });
|
|
29
31
|
if (argv.includes("--http")) {
|
|
30
32
|
const { runFromArgv } = await import("./http-server.js");
|
|
31
33
|
// Pass through every flag — http-server's parser ignores unknowns
|
|
@@ -37,7 +39,9 @@ async function main() {
|
|
|
37
39
|
// connects the stdio transport.
|
|
38
40
|
await import("./index.js");
|
|
39
41
|
}
|
|
40
|
-
main().catch((error) => {
|
|
42
|
+
main().catch(async (error) => {
|
|
43
|
+
(0, telemetry_js_1.captureMcpException)(error, { phase: "cli_startup" });
|
|
44
|
+
await (0, telemetry_js_1.flushMcpTelemetry)();
|
|
41
45
|
console.error("Fatal error:", error);
|
|
42
46
|
process.exit(1);
|
|
43
47
|
});
|
package/dist/http-server.js
CHANGED
|
@@ -28,6 +28,7 @@ const http_1 = require("http");
|
|
|
28
28
|
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
29
29
|
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
30
30
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
31
|
+
const telemetry_1 = require("./telemetry");
|
|
31
32
|
class CliError extends Error {
|
|
32
33
|
}
|
|
33
34
|
exports.CliError = CliError;
|
|
@@ -311,6 +312,7 @@ function buildHttpServer(config) {
|
|
|
311
312
|
* below.
|
|
312
313
|
*/
|
|
313
314
|
function runFromArgv(argv) {
|
|
315
|
+
(0, telemetry_1.initMcpTelemetry)({ transport: "http" });
|
|
314
316
|
let config;
|
|
315
317
|
try {
|
|
316
318
|
config = parseArgs(argv);
|
|
@@ -323,6 +325,10 @@ function runFromArgv(argv) {
|
|
|
323
325
|
throw e;
|
|
324
326
|
}
|
|
325
327
|
const server = buildHttpServer(config);
|
|
328
|
+
server.on("error", async (error) => {
|
|
329
|
+
(0, telemetry_1.captureMcpException)(error, { phase: "http_server" });
|
|
330
|
+
await (0, telemetry_1.flushMcpTelemetry)();
|
|
331
|
+
});
|
|
326
332
|
server.listen(config.mcpPort, config.host, () => {
|
|
327
333
|
const printable = config.host === "0.0.0.0" ? "0.0.0.0 (LAN)" : config.host;
|
|
328
334
|
console.log(`Screenpipe MCP HTTP server listening on ${printable}:${config.mcpPort}`);
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,8 @@ const fs = __importStar(require("fs"));
|
|
|
44
44
|
const path = __importStar(require("path"));
|
|
45
45
|
const os = __importStar(require("os"));
|
|
46
46
|
const notification_request_1 = require("./notification-request");
|
|
47
|
+
const telemetry_1 = require("./telemetry");
|
|
48
|
+
(0, telemetry_1.initMcpTelemetry)({ transport: "stdio" });
|
|
47
49
|
// Parse command line arguments
|
|
48
50
|
const args = process.argv.slice(2);
|
|
49
51
|
let port = 3030;
|
|
@@ -229,6 +231,7 @@ function discoverApiKey() {
|
|
|
229
231
|
"or install the screenpipe desktop app (https://screenpi.pe).",
|
|
230
232
|
"",
|
|
231
233
|
].join("\n"));
|
|
234
|
+
(0, telemetry_1.captureMcpMessage)("api key discovery failed", "warning", { phase: "api_key_discovery" });
|
|
232
235
|
return "";
|
|
233
236
|
}
|
|
234
237
|
const API_KEY = discoverApiKey();
|
|
@@ -352,16 +355,19 @@ const TOOLS = [
|
|
|
352
355
|
},
|
|
353
356
|
{
|
|
354
357
|
name: "list-meetings",
|
|
355
|
-
description: "List detected meetings (Zoom, Teams, Meet, etc.) with duration, app, and
|
|
356
|
-
"
|
|
357
|
-
"
|
|
358
|
+
description: "List detected meetings (Zoom, Teams, Meet, etc.) with id, duration, app, attendees, and note status. " +
|
|
359
|
+
"Pass `q` to substring-match title, attendee names/emails, and notes — `q` searches ALL meeting history, so when " +
|
|
360
|
+
"looking for a meeting with a person or on a topic ('when did I last talk to Noah?'), pass `q` and OMIT start_time. " +
|
|
361
|
+
"Only constrain the time range when the question itself is time-bound. Results are newest-first; without `q`, old " +
|
|
362
|
+
"meetings only surface via time range or offset pagination. Follow up with get-meeting (id from results) for the " +
|
|
363
|
+
"full note and transcript.",
|
|
358
364
|
annotations: { title: "List Meetings", readOnlyHint: true, openWorldHint: false, idempotentHint: true },
|
|
359
365
|
inputSchema: {
|
|
360
366
|
type: "object",
|
|
361
367
|
properties: {
|
|
362
|
-
start_time: { type: "string", description: "ISO 8601 UTC or relative (e.g. '1d ago')" },
|
|
368
|
+
start_time: { type: "string", description: "ISO 8601 UTC or relative (e.g. '1d ago'). Omit when searching by q — it filters all history." },
|
|
363
369
|
end_time: { type: "string", description: "ISO 8601 UTC or relative" },
|
|
364
|
-
q: { type: "string", description: "Case-insensitive substring filter on title, attendees, and note" },
|
|
370
|
+
q: { type: "string", description: "Case-insensitive substring filter on title, attendees (names/emails), and note. Searches all history." },
|
|
365
371
|
limit: { type: "integer", description: "Max results (default 20)", default: 20 },
|
|
366
372
|
offset: { type: "integer", description: "Pagination offset", default: 0 },
|
|
367
373
|
},
|
|
@@ -475,15 +481,17 @@ const TOOLS = [
|
|
|
475
481
|
timeout_secs: { type: "integer", description: "Auto-dismiss after N seconds (default 20). Use 0 for persistent.", default: 20 },
|
|
476
482
|
actions: {
|
|
477
483
|
type: "array",
|
|
478
|
-
description: "Up to 5 action buttons. Each needs id, label, type ('pipe'|'api'|'deeplink'|'dismiss').",
|
|
484
|
+
description: "Up to 5 action buttons. Each needs id, label, type ('pipe'|'chat'|'api'|'deeplink'|'dismiss').",
|
|
479
485
|
items: {
|
|
480
486
|
type: "object",
|
|
481
487
|
properties: {
|
|
482
488
|
id: { type: "string", description: "Unique action ID" },
|
|
483
489
|
label: { type: "string", description: "Button label" },
|
|
484
|
-
type: { type: "string", enum: ["pipe", "api", "deeplink", "dismiss"], description: "Action type" },
|
|
485
|
-
pipe: { type: "string", description: "
|
|
486
|
-
|
|
490
|
+
type: { type: "string", enum: ["pipe", "chat", "api", "deeplink", "dismiss"], description: "Action type. 'pipe' runs an installed pipe; 'chat' runs an inline prompt in a fresh chat session (no installed pipe needed)." },
|
|
491
|
+
pipe: { type: "string", description: "Target pipe to run when clicked (type=pipe). Set this explicitly — e.g. a 'share-data' pipe. If omitted it falls back to the sending pipe, which usually does nothing useful." },
|
|
492
|
+
prompt: { type: "string", description: "Instruction to run in a fresh chat session when clicked (type=chat). Write the whole task inline — no pre-installed pipe required." },
|
|
493
|
+
auto_send: { type: "boolean", description: "type=chat: auto-send the prompt (default true). Set false to pre-fill chat for the user to review before sending." },
|
|
494
|
+
context: { type: "object", description: "Data passed to the action (type=pipe → injected into the pipe prompt; type=chat → included as background context)" },
|
|
487
495
|
open_in_chat: { type: "boolean", description: "Open pipe run in chat UI instead of background (type=pipe)" },
|
|
488
496
|
url: { type: "string", description: "URL for api/deeplink actions" },
|
|
489
497
|
},
|
|
@@ -601,12 +609,24 @@ const TOOLS = [
|
|
|
601
609
|
},
|
|
602
610
|
{
|
|
603
611
|
name: "get-meeting",
|
|
604
|
-
description: "Get
|
|
612
|
+
description: "Get a meeting by ID: title, attendees, times, and the full note. " +
|
|
613
|
+
"Pass include_transcript=true to also get the speaker-attributed transcript segments — do this when the note is " +
|
|
614
|
+
"empty and you need to reconstruct what was said (much better than searching raw audio by time range).",
|
|
605
615
|
annotations: { title: "Get Meeting", readOnlyHint: true, openWorldHint: false, idempotentHint: true },
|
|
606
616
|
inputSchema: {
|
|
607
617
|
type: "object",
|
|
608
618
|
properties: {
|
|
609
|
-
id: { type: "integer", description: "Meeting ID" },
|
|
619
|
+
id: { type: "integer", description: "Meeting ID (from list-meetings results)" },
|
|
620
|
+
include_transcript: {
|
|
621
|
+
type: "boolean",
|
|
622
|
+
description: "Also return the meeting's transcript segments with speaker names and timestamps.",
|
|
623
|
+
default: false,
|
|
624
|
+
},
|
|
625
|
+
transcript_offset: {
|
|
626
|
+
type: "integer",
|
|
627
|
+
description: "Skip this many transcript segments (pagination for long meetings).",
|
|
628
|
+
default: 0,
|
|
629
|
+
},
|
|
610
630
|
},
|
|
611
631
|
required: ["id"],
|
|
612
632
|
},
|
|
@@ -931,7 +951,8 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
|
|
|
931
951
|
## Common Patterns
|
|
932
952
|
|
|
933
953
|
- "What was I doing for the last 2 hours?" → activity-summary with start_time='2h ago'
|
|
934
|
-
- "What did I discuss in my meeting?" → list-meetings to find it, then
|
|
954
|
+
- "What did I discuss in my meeting?" → list-meetings to find it, then get-meeting with include_transcript=true
|
|
955
|
+
- "When did I last talk to <person>?" → list-meetings with q=<name or email>, NO start_time (q searches all history)
|
|
935
956
|
- "Find when I was on Twitter" → search-content with app_name='Arc' (or the browser name), q='twitter'
|
|
936
957
|
- "Remember that I prefer X" → update-memory with content describing the preference
|
|
937
958
|
- "What do you remember about X?" → search-content with content_type='memory', q='X'
|
|
@@ -1405,8 +1426,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1405
1426
|
const response = await callAPI(`/meetings?${params.toString()}`);
|
|
1406
1427
|
const meetings = await response.json();
|
|
1407
1428
|
if (!Array.isArray(meetings) || meetings.length === 0) {
|
|
1429
|
+
const hadTimeFilter = normalized.start_time || normalized.end_time;
|
|
1430
|
+
const hint = normalized.q
|
|
1431
|
+
? hadTimeFilter
|
|
1432
|
+
? " Retry the same q WITHOUT start_time/end_time — q searches all meeting history."
|
|
1433
|
+
: " Try a shorter substring (single first name, email fragment) — matching is exact-substring, not fuzzy."
|
|
1434
|
+
: " Pass q (name/email/topic, searches all history) or widen the time range.";
|
|
1408
1435
|
return {
|
|
1409
|
-
content: [{ type: "text", text:
|
|
1436
|
+
content: [{ type: "text", text: `No meetings matched.${hint}` }],
|
|
1410
1437
|
};
|
|
1411
1438
|
}
|
|
1412
1439
|
const formatted = meetings.map((m) => {
|
|
@@ -1415,7 +1442,11 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1415
1442
|
const app = m.meeting_app;
|
|
1416
1443
|
const title = m.title ? ` — ${m.title}` : "";
|
|
1417
1444
|
const attendees = m.attendees ? `\nAttendees: ${m.attendees}` : "";
|
|
1418
|
-
|
|
1445
|
+
const noteStr = typeof m.note === "string" ? m.note.trim() : "";
|
|
1446
|
+
const note = noteStr
|
|
1447
|
+
? `\nNote: ${noteStr.length > 200 ? `${noteStr.slice(0, 200)}…` : noteStr}`
|
|
1448
|
+
: "\nNote: (none — use get-meeting with include_transcript to reconstruct)";
|
|
1449
|
+
return `[id ${m.id}] [${m.detection_source}] ${app}${title}\n ${start} → ${end}${attendees}${note}`;
|
|
1419
1450
|
});
|
|
1420
1451
|
return {
|
|
1421
1452
|
content: [
|
|
@@ -1794,8 +1825,45 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1794
1825
|
}
|
|
1795
1826
|
const response = await callAPI(`/meetings/${meetingId}`);
|
|
1796
1827
|
const meeting = await response.json();
|
|
1828
|
+
let text = JSON.stringify(meeting, null, 2);
|
|
1829
|
+
if (args.include_transcript) {
|
|
1830
|
+
const tRes = await callAPI(`/meetings/${meetingId}/transcript`);
|
|
1831
|
+
const segments = await tRes.json();
|
|
1832
|
+
if (!Array.isArray(segments) || segments.length === 0) {
|
|
1833
|
+
text += "\n\nTranscript: (no segments recorded for this meeting)";
|
|
1834
|
+
}
|
|
1835
|
+
else {
|
|
1836
|
+
// Cap the payload: long meetings can have hundreds of segments.
|
|
1837
|
+
const offset = Math.max(0, args.transcript_offset || 0);
|
|
1838
|
+
const MAX_SEGMENTS = 200;
|
|
1839
|
+
const MAX_CHARS = 40_000;
|
|
1840
|
+
const page = segments.slice(offset, offset + MAX_SEGMENTS);
|
|
1841
|
+
const lines = [];
|
|
1842
|
+
let chars = 0;
|
|
1843
|
+
let shown = 0;
|
|
1844
|
+
for (const s of page) {
|
|
1845
|
+
// MeetingTranscriptSegment serializes camelCase (unlike MeetingRecord)
|
|
1846
|
+
const capturedAt = (s.capturedAt ?? s.captured_at);
|
|
1847
|
+
const when = typeof capturedAt === "string" ? capturedAt.slice(11, 19) : "";
|
|
1848
|
+
const speaker = (s.speakerName ?? s.speaker_name) ||
|
|
1849
|
+
(s.deviceType ?? s.device_type) ||
|
|
1850
|
+
"unknown";
|
|
1851
|
+
const line = `[${when}] ${speaker}: ${s.transcript}`;
|
|
1852
|
+
if (chars + line.length > MAX_CHARS)
|
|
1853
|
+
break;
|
|
1854
|
+
lines.push(line);
|
|
1855
|
+
chars += line.length;
|
|
1856
|
+
shown++;
|
|
1857
|
+
}
|
|
1858
|
+
const remaining = segments.length - offset - shown;
|
|
1859
|
+
const more = remaining > 0
|
|
1860
|
+
? `\n… ${remaining} more segments — call again with transcript_offset=${offset + shown}.`
|
|
1861
|
+
: "";
|
|
1862
|
+
text += `\n\nTranscript (${segments.length} segments, showing ${offset + 1}-${offset + shown}):\n${lines.join("\n")}${more}`;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1797
1865
|
return {
|
|
1798
|
-
content: [{ type: "text", text
|
|
1866
|
+
content: [{ type: "text", text }],
|
|
1799
1867
|
};
|
|
1800
1868
|
}
|
|
1801
1869
|
case "update-meeting": {
|
|
@@ -1978,6 +2046,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1978
2046
|
}
|
|
1979
2047
|
catch (error) {
|
|
1980
2048
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2049
|
+
if (!(error instanceof BackendDownError) && !(error instanceof BackendHttpError)) {
|
|
2050
|
+
(0, telemetry_1.captureMcpMessage)("tool call failed", "error", { phase: "tool_call", tool: name });
|
|
2051
|
+
}
|
|
1981
2052
|
// isError flags the result as a failure so the model retries with a
|
|
1982
2053
|
// different approach instead of treating the error text as data.
|
|
1983
2054
|
return {
|
|
@@ -1992,7 +2063,9 @@ async function main() {
|
|
|
1992
2063
|
await server.connect(transport);
|
|
1993
2064
|
console.error("Screenpipe MCP server running on stdio");
|
|
1994
2065
|
}
|
|
1995
|
-
main().catch((error) => {
|
|
2066
|
+
main().catch(async (error) => {
|
|
2067
|
+
(0, telemetry_1.captureMcpException)(error, { phase: "stdio_startup" });
|
|
2068
|
+
await (0, telemetry_1.flushMcpTelemetry)();
|
|
1996
2069
|
console.error("Fatal error:", error);
|
|
1997
2070
|
process.exit(1);
|
|
1998
2071
|
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Sentry from "@sentry/node";
|
|
2
|
+
type TelemetryContext = {
|
|
3
|
+
transport?: "stdio" | "http";
|
|
4
|
+
phase?: string;
|
|
5
|
+
tool?: string;
|
|
6
|
+
};
|
|
7
|
+
type SanitizableEvent = {
|
|
8
|
+
request?: unknown;
|
|
9
|
+
user?: unknown;
|
|
10
|
+
extra?: unknown;
|
|
11
|
+
breadcrumbs?: unknown[];
|
|
12
|
+
contexts?: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
export declare function isMcpTelemetryDisabled(env?: NodeJS.ProcessEnv): boolean;
|
|
15
|
+
export declare function scrubSensitiveValue(value: string): string;
|
|
16
|
+
export declare function sanitizeSentryEvent<T extends SanitizableEvent>(event: T): T | null;
|
|
17
|
+
export declare function initMcpTelemetry(context?: TelemetryContext): boolean;
|
|
18
|
+
export declare function captureMcpException(error: unknown, context?: TelemetryContext): void;
|
|
19
|
+
export declare function captureMcpMessage(message: string, level?: Sentry.SeverityLevel, context?: TelemetryContext): void;
|
|
20
|
+
export declare function flushMcpTelemetry(timeoutMs?: number): Promise<void>;
|
|
21
|
+
export {};
|