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 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. Pass `q` to filter by substring (title, attendees, notes).
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 any
194
- data on its own.
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
- **None by this MCP server.** No analytics, no telemetry, no usage tracking.
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
- None. The MCP server only talks to `localhost:3030`. It does not
219
- contact Anthropic, Screenpipe's servers, or any other external service.
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
  });
@@ -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 attendees. " +
356
- "Only available when screenpipe runs in smart transcription mode. " +
357
- "Pass `q` to filter by substring match against title, attendees, and notes (e.g. an email or name).",
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: "Pipe name to run (type=pipe)" },
486
- context: { type: "object", description: "Context passed to pipe (type=pipe)" },
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 details of a specific meeting by ID, including transcription and attendees.",
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 search-content with audio + that time range
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: "No meetings found in the given time range." }],
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
- return `[${m.detection_source}] ${app}${title}\n ${start} → ${end}${attendees}`;
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: JSON.stringify(meeting, null, 2) }],
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 {};