@extenshi/mcp 0.5.0 → 0.5.2

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/telemetry.js CHANGED
@@ -164,10 +164,15 @@ function sanitizeError(err) {
164
164
  }
165
165
  /**
166
166
  * The HTTP status an error carries, whichever shape it arrived in:
167
- * - `status` — MCP ScanError, thrown by ./scan.ts.
167
+ * - `status` — the MCP package's ScanError (@extenshi/mcp scan.ts).
168
168
  * - `data.httpStatus` — @trpc/client's TRPCClientError, i.e. every catalog BFF
169
- * read. tRPC puts the status inside `data` and has NO top-level `status`, so
170
- * reading only `status` left the entire read path to message heuristics.
169
+ * read on EITHER surface. tRPC puts the status inside `data` and has NO
170
+ * top-level `status`, so reading only `status` left the entire read path to
171
+ * message heuristics.
172
+ *
173
+ * Surface-neutral on purpose: this file is vendored byte-identical into both
174
+ * packages (see the header), so it must describe both. Neither branch costs the
175
+ * surface that cannot produce that shape anything — the check simply never fires.
171
176
  */
172
177
  function statusOf(err) {
173
178
  const e = err;
@@ -216,15 +221,16 @@ function classifyOne(err) {
216
221
  const MAX_CAUSE_DEPTH = 4;
217
222
  /**
218
223
  * Coarse error bucket. Driven by a numeric status when the error carries one
219
- * (ScanError `status`, tRPC `data.httpStatus`), else by message patterns (the
220
- * CLI throws plain Errors). Order matters — status first, then transport, then
221
- * semantic buckets.
224
+ * (ScanError `status`, tRPC `data.httpStatus`), else by message patterns (both
225
+ * surfaces also throw plain Errors). Order matters — status first, then
226
+ * transport, then semantic buckets.
222
227
  *
223
- * Follows the `cause` chain: the tool layer re-throws failures wrapped in a
224
- * `UserError` so fastmcp renders them for the caller (see readError() in
225
- * ./tools.ts), and that wrapper's own message can carry no status. The origin
226
- * hangs off `cause`, so an unclassifiable wrapper defers to what it wraps —
227
- * without it, a BFF 500 behind a UserError reads as `unexpected`.
228
+ * Follows the `cause` chain, because both surfaces re-throw a failure wrapped in
229
+ * an error of their own so it renders for the caller — the MCP tool layer wraps
230
+ * in fastmcp's `UserError` (readError() in its tools.ts) — and the wrapper's own
231
+ * message can carry no status. The origin hangs off `cause`, so an
232
+ * unclassifiable wrapper defers to what it wraps; without this, a BFF 500 behind
233
+ * a wrapper reads as `unexpected`.
228
234
  */
229
235
  export function classifyError(err) {
230
236
  let cur = err;
@@ -233,9 +239,12 @@ export function classifyError(err) {
233
239
  if (kind !== 'unexpected')
234
240
  return kind;
235
241
  const next = cur.cause;
236
- // An error that causes itself has no origin left to consult, which is a
237
- // different thing from running out of depth budget. MAX_CAUSE_DEPTH would
238
- // bound this anyway — stopping here just says so at the point it's true.
242
+ // Handles the DIRECT cycle only (`a.cause === a`): such an error has no
243
+ // origin left to consult, which is a different thing from running out of
244
+ // depth budget, so stopping here says so at the point it's true. A longer
245
+ // cycle (A → B → A) is not detected and is not meant to be — it terminates
246
+ // on MAX_CAUSE_DEPTH like any other over-deep chain, which is why the
247
+ // bound, not this check, is what guarantees termination.
239
248
  if (next === cur)
240
249
  break;
241
250
  cur = next;
@@ -255,12 +264,30 @@ export function flagsFromArgv(argv = process.argv.slice(2)) {
255
264
  }
256
265
  return [...flags];
257
266
  }
258
- export function captureEvent(event, properties = {}) {
267
+ /**
268
+ * `distinctId` overrides the per-install anonymous id. The CLI never passes it —
269
+ * one install IS one identity there. The hosted MCP connector must: it is one
270
+ * process serving many accounts, so the install id would collapse every user of
271
+ * the service into a single person and re-mint on each redeploy. It passes the
272
+ * authenticated account id instead (never an email — that stays in our own
273
+ * database, see tools/extenshi-mcp-server/src/legal.ts).
274
+ */
275
+ export function captureEvent(event, properties = {}, distinctId) {
259
276
  const c = getClient();
260
277
  if (!c)
261
278
  return;
279
+ // Empty is treated as ABSENT, not as an id. PostHog accepts "" and mints a
280
+ // person nobody can resolve, so a caller bug would turn into permanently
281
+ // unattributable rows; degrading to the install id keeps the event readable.
282
+ // attribution() already filters empties — this restates the contract at the
283
+ // sink so it does not depend on the caller doing so.
284
+ const id = distinctId?.trim() || anonId();
262
285
  try {
263
- c.capture({ distinctId: anonId(), event, properties: { ...baseProps(), ...properties } });
286
+ c.capture({
287
+ distinctId: id,
288
+ event,
289
+ properties: { ...baseProps(), ...properties },
290
+ });
264
291
  }
265
292
  catch {
266
293
  // Telemetry must never throw into the command path.
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The extension-type catalog, rendered for an agent building an extension.
3
+ *
4
+ * Why a tool and not documentation: an agent asked to "build a Chrome extension
5
+ * that helps fill forms" has to decide a shape before it writes a line, and the
6
+ * decision it makes badly is permissions — either padding the manifest to look
7
+ * capable, or missing the one key without which the chosen shape cannot work.
8
+ * This hands it the four shapes with their REQUIRED permissions attached, so the
9
+ * minimum is the easy path rather than the researched one.
10
+ *
11
+ * Free and keyless by construction: the catalog is compiled in, so this answers
12
+ * without touching the BFF, without an API key, and without spending a credit —
13
+ * the same reasoning as `search_docs`.
14
+ */
15
+ /** Where a developer picks the same types in the UI, so the two surfaces meet. */
16
+ export declare const MANIFEST_GENERATOR_URL = "https://dojo.extenshi.io/manifest-generator";
17
+ /**
18
+ * Render one or all templates.
19
+ *
20
+ * Combinations are described rather than enumerated: the four types compose, so
21
+ * listing every pair would be sixteen entries saying the same thing about union.
22
+ */
23
+ export declare function renderExtensionTemplates(ids?: readonly string[]): string;
24
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,kFAAkF;AAClF,eAAO,MAAM,sBAAsB,gDAAgD,CAAA;AAMnF;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAwDxE"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The extension-type catalog, rendered for an agent building an extension.
3
+ *
4
+ * Why a tool and not documentation: an agent asked to "build a Chrome extension
5
+ * that helps fill forms" has to decide a shape before it writes a line, and the
6
+ * decision it makes badly is permissions — either padding the manifest to look
7
+ * capable, or missing the one key without which the chosen shape cannot work.
8
+ * This hands it the four shapes with their REQUIRED permissions attached, so the
9
+ * minimum is the easy path rather than the researched one.
10
+ *
11
+ * Free and keyless by construction: the catalog is compiled in, so this answers
12
+ * without touching the BFF, without an API key, and without spending a credit —
13
+ * the same reasoning as `search_docs`.
14
+ */
15
+ import { EXTENSION_BACKGROUND_PATH, EXTENSION_TEMPLATE_CATALOG, extensionTemplateFiles, extensionTemplateRequiredPermissions, isExtensionTemplateId, } from './extension-templates.js';
16
+ /** Where a developer picks the same types in the UI, so the two surfaces meet. */
17
+ export const MANIFEST_GENERATOR_URL = 'https://dojo.extenshi.io/manifest-generator';
18
+ function permissionLine(label, permissions) {
19
+ return permissions.length > 0 ? `${label}: ${permissions.join(', ')}` : `${label}: none`;
20
+ }
21
+ /**
22
+ * Render one or all templates.
23
+ *
24
+ * Combinations are described rather than enumerated: the four types compose, so
25
+ * listing every pair would be sixteen entries saying the same thing about union.
26
+ */
27
+ export function renderExtensionTemplates(ids) {
28
+ const wanted = (ids ?? []).filter(isExtensionTemplateId);
29
+ const shown = wanted.length > 0
30
+ ? EXTENSION_TEMPLATE_CATALOG.filter((t) => wanted.includes(t.id))
31
+ : EXTENSION_TEMPLATE_CATALOG;
32
+ const lines = [
33
+ '# Extension types',
34
+ '',
35
+ 'Each type is a shape an extension can take. They COMBINE — a side panel that',
36
+ 'also runs on the page is one extension with both capabilities, and the required',
37
+ 'permissions are the union. Pick the smallest set that does the job: reviewers',
38
+ 'read every permission as a claim you have to justify.',
39
+ '',
40
+ ];
41
+ for (const template of shown) {
42
+ lines.push(`## ${template.label} (\`${template.id}\`)`, '', template.summary, '', `- ${permissionLine('Required permissions (cannot be dropped)', template.requiredPermissions)}`, `- ${permissionLine('Suggested, removable', template.recommendedPermissions)}`, `- Manifest components: ${template.requires.join(', ')}`, `- Files this type needs: ${template.emits.join(', ')}`);
43
+ if (template.defaultMatches && template.defaultMatches.length > 0) {
44
+ lines.push(`- Default \`content_scripts.matches\`: ${template.defaultMatches.join(', ')} — replace with the exact sites you need; \`<all_urls>\` triggers in-depth store review.`);
45
+ }
46
+ lines.push('');
47
+ }
48
+ lines.push('## Rules that hold for every type', '', `- Every extension gets a background service worker at \`${EXTENSION_BACKGROUND_PATH}\`; it is where startup-time registrations belong (for example the uninstall survey, which the browser reads at removal time when no other code of yours can run).`, '- Chromium reads `side_panel.default_path` and needs the `sidePanel` permission; Firefox reads `sidebar_action` and has no such permission. Emit the one that matches the browser you are building for.', '- MV3 forbids inline script: a panel or popup with its logic in a `<script>` block renders blank. Ship the logic as a file.', '- Never declare a path the package does not contain — a missing content script or icon makes the browser refuse the whole extension, not just that feature.', '', `A developer can pick the same types in the UI at ${MANIFEST_GENERATOR_URL}, and a project's chosen types come back from \`get_project_state\`.`);
49
+ const only = shown.length === 1 ? shown[0] : undefined;
50
+ if (only) {
51
+ lines.push('', `Full file set for this type: ${extensionTemplateFiles([only.id]).join(', ')}.`);
52
+ lines.push(`Union of required permissions: ${extensionTemplateRequiredPermissions([only.id]).join(', ') || 'none'}.`);
53
+ }
54
+ return lines.join('\n');
55
+ }
56
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"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"}
package/dist/tools.d.ts CHANGED
@@ -23,7 +23,7 @@
23
23
  * ─────────────────────────────────────────────────────────────
24
24
  * 'read' → search_extensions, get_extension, get_reviews,
25
25
  * get_security, get_risk_by_store_ids, market_overview
26
- * 'docs' → search_docs, generate_icon_workflow,
26
+ * 'docs' → search_docs, list_extension_templates, generate_icon_workflow,
27
27
  * generate_welcome_page_workflow (free; no key)
28
28
  * 'scan' → scan_extension (local artifact; stdio only)
29
29
  * 'publish' → publish_extension (local creds; stdio only)
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,kBAAkB,EAA6C,MAAM,SAAS,CAAA;AAE1G,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAmBnC,eAAO,MAAM,QAAQ,sCAAsC,CAAA;AAC3D,eAAO,MAAM,WAAW,oCAAoC,CAAA;AAC5D,eAAO,MAAM,YAAY,qCAAqC,CAAA;AAE9D,eAAO,MAAM,mBAAmB,QAWS,CAAA;AAEzC;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC,eAAO,MAAM,WAAW,aAAa,CAAA;AAErC,eAAO,MAAM,mBAAmB,QAmBe,CAAA;AAI/C,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC5B;AAED,MAAM,WAAW,QAAQ;IACxB,kEAAkE;IAClE,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IACzD,+BAA+B;IAC/B,YAAY,EAAE,WAAW,CAAC,UAAU,CAAC,CAAA;IACrC;;;;;OAKG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,GAAG,CAAA;IACrC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,CAAA;IAChD;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,GAAG,SAAS,CAAA;IACxD,sFAAsF;IACtF,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAiFD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,GAAE,MAA2B,GAAG,OAAO,CAGxF;AA6ND;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CA2nBnE"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,kBAAkB,EAA6C,MAAM,SAAS,CAAA;AAE1G,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAoBnC,eAAO,MAAM,QAAQ,sCAAsC,CAAA;AAC3D,eAAO,MAAM,WAAW,oCAAoC,CAAA;AAC5D,eAAO,MAAM,YAAY,qCAAqC,CAAA;AAE9D,eAAO,MAAM,mBAAmB,QAWS,CAAA;AAEzC;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC,eAAO,MAAM,WAAW,aAAa,CAAA;AAErC,eAAO,MAAM,mBAAmB,QA2Be,CAAA;AAI/C,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC5B;AAED,MAAM,WAAW,QAAQ;IACxB,kEAAkE;IAClE,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IACzD,+BAA+B;IAC/B,YAAY,EAAE,WAAW,CAAC,UAAU,CAAC,CAAA;IACrC;;;;;OAKG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,GAAG,CAAA;IACrC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,CAAA;IAChD;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,GAAG,SAAS,CAAA;IACxD,sFAAsF;IACtF,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAiFD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,GAAE,MAA2B,GAAG,OAAO,CAGxF;AAqRD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,CA+uBnE"}
package/dist/tools.js CHANGED
@@ -23,7 +23,7 @@
23
23
  * ─────────────────────────────────────────────────────────────
24
24
  * 'read' → search_extensions, get_extension, get_reviews,
25
25
  * get_security, get_risk_by_store_ids, market_overview
26
- * 'docs' → search_docs, generate_icon_workflow,
26
+ * 'docs' → search_docs, list_extension_templates, generate_icon_workflow,
27
27
  * generate_welcome_page_workflow (free; no key)
28
28
  * 'scan' → scan_extension (local artifact; stdio only)
29
29
  * 'publish' → publish_extension (local creds; stdio only)
@@ -40,6 +40,7 @@ import { ScanError, scanArtifact } from './scan.js';
40
40
  import { describeStoreConstraints, validateSearchFilters } from './search-filters.js';
41
41
  import { shapeExtension, shapeReviews, shapeSearch, shapeSecurity, shapeStoreRiskBatch } from './shape.js';
42
42
  import { captureError, captureEvent, classifyError } from './telemetry.js';
43
+ import { renderExtensionTemplates } from './templates.js';
43
44
  import { renderCatalogPayload } from './untrusted.js';
44
45
  import { renderWelcomeWorkflow } from './welcome-workflow.js';
45
46
  // ── Public links (shared by tool bodies + server instructions) ──────────────
@@ -80,7 +81,15 @@ export const SERVER_INSTRUCTIONS = 'Extenshi catalog tools for extension develop
80
81
  'after install — it returns which illustrations to produce for the chosen goal, how to mark ' +
81
82
  'up where to click, and the block JSON to hand back. Call ' +
82
83
  'get_credit_balance (free — it never spends a credit) to check remaining read/scan credits ' +
83
- 'before a large batch instead of guessing whether it is safe. In get_extension / get_reviews / ' +
84
+ 'before a large batch instead of guessing whether it is safe. When the developer is BUILDING ' +
85
+ 'an extension: call list_extension_templates (free, no key) for the four shapes and the ' +
86
+ 'permissions each one requires before writing a manifest, and — when they mention "my ' +
87
+ 'extension" or "my project" — list_my_projects then get_project_state (both free) to read the ' +
88
+ 'types, manifest and hosted URLs they already configured on extenshi.io instead of asking them ' +
89
+ 'to repeat it. Re-read get_project_state after they change something on the site, and write its ' +
90
+ '`integration.file` verbatim rather than hand-assembling the same values — that is what keeps the ' +
91
+ 'site and the extension in sync. ' +
92
+ 'In get_extension / get_reviews / ' +
84
93
  'get_security you can identify an extension either by its numeric catalog id or by its store id ' +
85
94
  '(the id in the store URL; add the store for a Chrome/Edge id). To check a LIST of installed ' +
86
95
  `extensions by store id, use get_risk_by_store_ids — up to ${MAX_BATCH_EXTENSIONS} per call for one ` +
@@ -191,10 +200,36 @@ export function isExpectedError(err, kind = classifyError(err)) {
191
200
  return err instanceof UserError && err.cause === undefined;
192
201
  }
193
202
  /**
194
- * Wrap a tool definition so every call emits anonymous telemetry: which tool
195
- * ran, how long it took, and how it failed (coarse error_kind + sanitized
196
- * exception). The generic preserves the Zod-inferred `args` type — `parameters`
197
- * fixes Params, so the inner execute stays as strongly typed as before.
203
+ * Attribution for a tool call, lifted from the session the surface supplies.
204
+ *
205
+ * Local stdio has no session at all, so both fields come back undefined and
206
+ * captureEvent falls back to the per-install anonymous id — unchanged behaviour.
207
+ * The hosted connector authenticates every request, so it supplies both: the
208
+ * account id becomes the PostHog distinct_id, and the connection id threads one
209
+ * client's calls together (see tools/extenshi-mcp-server/src/identity.ts, which
210
+ * mints it per `authenticate()` — i.e. per connection, NOT per cached token).
211
+ *
212
+ * Read defensively: `session` is FastMCP's opaque auth record, and a surface
213
+ * that carries neither field must degrade to the local behaviour rather than
214
+ * throw inside instrumentation.
215
+ */
216
+ function attribution(session) {
217
+ if (!session || typeof session !== 'object')
218
+ return {};
219
+ const s = session;
220
+ return {
221
+ userId: typeof s.userId === 'string' && s.userId ? s.userId : undefined,
222
+ sessionId: typeof s.sessionId === 'string' && s.sessionId ? s.sessionId : undefined,
223
+ };
224
+ }
225
+ /**
226
+ * Wrap a tool definition so every call is reported: which tool ran, how long it
227
+ * took, and how it failed (coarse error_kind + sanitized exception). On the
228
+ * hosted connector the report also carries WHO — the authenticated account id —
229
+ * and which connection it belonged to; on local stdio it stays anonymous. Never
230
+ * the arguments, never the result. The generic preserves the Zod-inferred
231
+ * `args` type — `parameters` fixes Params, so the inner execute stays as
232
+ * strongly typed as before.
198
233
  * Fail-soft: telemetry never alters the tool's result or its thrown error.
199
234
  */
200
235
  function instrument(tool) {
@@ -204,10 +239,12 @@ function instrument(tool) {
204
239
  ...tool,
205
240
  execute: async (args, context) => {
206
241
  const startedAt = Date.now();
207
- captureEvent('mcp_tool_called', { tool: name });
242
+ const { userId, sessionId } = attribution(context.session);
243
+ const props = { tool: name, ...(sessionId ? { mcp_session_id: sessionId } : {}) };
244
+ captureEvent('mcp_tool_called', props, userId);
208
245
  try {
209
246
  const result = await original(args, context);
210
- captureEvent('mcp_tool_succeeded', { tool: name, duration_ms: Date.now() - startedAt });
247
+ captureEvent('mcp_tool_succeeded', { ...props, duration_ms: Date.now() - startedAt }, userId);
211
248
  return result;
212
249
  }
213
250
  catch (err) {
@@ -217,7 +254,7 @@ function instrument(tool) {
217
254
  const kind = classifyError(err);
218
255
  // The failure count is always tracked, so we keep visibility into
219
256
  // how often callers hit each condition (incl. the billing gate).
220
- captureEvent('mcp_tool_failed', { tool: name, error_kind: kind, duration_ms: Date.now() - startedAt });
257
+ captureEvent('mcp_tool_failed', { ...props, error_kind: kind, duration_ms: Date.now() - startedAt }, userId);
221
258
  // …but only genuine faults are shipped as exceptions. Expected
222
259
  // user-facing conditions (a quota gate, a bad key, a message we
223
260
  // authored) are not bugs and must not open error-tracking issues.
@@ -359,6 +396,30 @@ const TOOL_ANNOTATIONS = {
359
396
  idempotentHint: true,
360
397
  openWorldHint: true,
361
398
  },
399
+ list_extension_templates: {
400
+ title: 'Extension types and their permissions',
401
+ readOnlyHint: true,
402
+ idempotentHint: true,
403
+ openWorldHint: false,
404
+ },
405
+ list_my_projects: {
406
+ title: 'List my extension projects',
407
+ readOnlyHint: true,
408
+ idempotentHint: true,
409
+ openWorldHint: true,
410
+ },
411
+ get_project_state: {
412
+ title: 'Read my project state',
413
+ readOnlyHint: true,
414
+ idempotentHint: true,
415
+ openWorldHint: true,
416
+ },
417
+ get_project_scaffold: {
418
+ title: 'Get my starter extension files',
419
+ readOnlyHint: true,
420
+ idempotentHint: true,
421
+ openWorldHint: true,
422
+ },
362
423
  generate_icon_workflow: {
363
424
  title: 'Icon design workflow guide',
364
425
  readOnlyHint: true,
@@ -747,6 +808,97 @@ export function registerTools(server, deps) {
747
808
  }
748
809
  },
749
810
  });
811
+ // ── The developer's OWN projects ───────────────────────────────────────
812
+ //
813
+ // Extenshi holds the state of an extension project — its type, its
814
+ // manifest, its live hosted pages — so an agent can read that instead of
815
+ // being told it again in prose, and so what it builds matches what the
816
+ // developer already configured. Both are FREE: credits pay for catalog
817
+ // data about other people's extensions, never for your own work.
818
+ add({
819
+ name: 'list_my_projects',
820
+ description: "List the extension projects owned by this API key — the developer's own workspaces on " +
821
+ 'extenshi.io. Returns id, name, status, target browsers, the bound GitHub repo (if any) and ' +
822
+ 'the claimed store listing (if any). Start here when the developer says "my extension" or ' +
823
+ '"my project": the id you get back is what get_project_state takes. FREE — reading your own ' +
824
+ 'projects never spends a credit.',
825
+ parameters: z.object({}),
826
+ execute: async (_args, context) => {
827
+ try {
828
+ return JSON.stringify(await bff(context).listMyProjects(), null, 2);
829
+ }
830
+ catch (err) {
831
+ return readError(err, missingKeyMessage);
832
+ }
833
+ },
834
+ });
835
+ add({
836
+ name: 'get_project_state',
837
+ description: "Read one of the developer's own projects as state you can build from: the extension TYPES " +
838
+ 'they picked (popup / side panel / page enhancer / in-page assistant), the required ' +
839
+ 'permissions those types force, the exact manifest.json the project produces for each target ' +
840
+ 'browser, the files that type needs, live hosted URLs (uninstall survey), and an index of ' +
841
+ 'every saved tool state with its size. Use it before writing code so the manifest you ship ' +
842
+ 'matches what the developer configured on the site — and re-read it after they change ' +
843
+ 'something rather than assuming. It also returns the integration contract: write ' +
844
+ '`integration.file` to `integration.path` VERBATIM to wire the extension to this project — ' +
845
+ "those bytes carry a fingerprint extenshi.io uses to tell the developer's edits from its " +
846
+ 'own, so an equivalent file you assemble yourself makes the site stop managing every value ' +
847
+ 'in it. `integration.unwired` names the links this project has not set up yet — offer them ' +
848
+ 'rather than inventing URLs. Tool-state payloads are NOT inlined by default (a single ' +
849
+ 'row can be 256 KiB); name the keys you actually need in includeToolStates. FREE — never ' +
850
+ 'spends a credit. Combine with list_extension_templates for what each type means.',
851
+ parameters: z.object({
852
+ projectId: z.string().describe('Project id from list_my_projects.'),
853
+ includeToolStates: z
854
+ .array(z.string())
855
+ .optional()
856
+ .describe('Tool keys whose saved payload to inline, e.g. ["manifest-generator", "privacy-policy-generator"]. Omit to get the index only.'),
857
+ }),
858
+ execute: async (args, context) => {
859
+ try {
860
+ const state = await bff(context).getMyProjectState({
861
+ projectId: args.projectId,
862
+ includeToolStates: args.includeToolStates,
863
+ });
864
+ return JSON.stringify(state, null, 2);
865
+ }
866
+ catch (err) {
867
+ return readError(err, missingKeyMessage);
868
+ }
869
+ },
870
+ });
871
+ add({
872
+ name: 'get_project_scaffold',
873
+ description: "The starter extension one of the developer's own projects produces, as FILES ready to " +
874
+ 'write: manifest.json for the target browser, the background worker, the panel or ' +
875
+ "content-script files that project's types need, placeholder icons, and " +
876
+ 'src/extenshi.config.js. Write the files VERBATIM — the config carries a fingerprint ' +
877
+ "that lets extenshi.io keep recognising the repository as this project's, and rebuilding " +
878
+ 'it by hand makes the site stop managing those values. Prefer this over writing a manifest ' +
879
+ 'yourself: it is the same set the site commits, so what you write and what the site ' +
880
+ "expects cannot disagree. One browser per call (default: the project's first target). " +
881
+ 'FREE — never spends a credit.',
882
+ parameters: z.object({
883
+ projectId: z.string().describe('Project id from list_my_projects.'),
884
+ browser: z
885
+ .enum(['chrome', 'firefox', 'edge'])
886
+ .optional()
887
+ .describe("Target browser. Omit for the project's first declared target."),
888
+ }),
889
+ execute: async (args, context) => {
890
+ try {
891
+ const scaffold = await bff(context).getMyProjectScaffold({
892
+ projectId: args.projectId,
893
+ browser: args.browser,
894
+ });
895
+ return JSON.stringify(scaffold, null, 2);
896
+ }
897
+ catch (err) {
898
+ return readError(err, missingKeyMessage);
899
+ }
900
+ },
901
+ });
750
902
  }
751
903
  // ── Documentation (free; no API key required) ──────────────────────────────
752
904
  if (caps.has('docs')) {
@@ -857,6 +1009,24 @@ export function registerTools(server, deps) {
857
1009
  accentColor: args.accent_color,
858
1010
  }),
859
1011
  });
1012
+ add({
1013
+ name: 'list_extension_templates',
1014
+ description: 'The kinds of browser extension you can build, with the permissions each one REQUIRES: ' +
1015
+ 'Popup (toolbar window), Side panel (docked beside the page), Page enhancer (runs on sites ' +
1016
+ 'you list), In-page assistant (your own UI over any site). Types combine, and the required ' +
1017
+ 'permissions are the union. Call this BEFORE writing a manifest so you request the minimum ' +
1018
+ 'a shape actually needs instead of guessing — padded permissions are what store review ' +
1019
+ 'pushes back on. Also states the cross-browser rules (Chromium side_panel vs Firefox ' +
1020
+ 'sidebar_action) and the rule that a manifest must never name a file the package lacks. ' +
1021
+ "FREE: no API key, no quota. For a specific project's chosen types use get_project_state.",
1022
+ parameters: z.object({
1023
+ types: z
1024
+ .array(z.string())
1025
+ .optional()
1026
+ .describe('Limit to these type ids (popup, sidepanel, content, overlay). Omit for all four.'),
1027
+ }),
1028
+ execute: async (args) => renderExtensionTemplates(args.types),
1029
+ });
860
1030
  }
861
1031
  // ── Action tool (paid; key + LOCAL filesystem required; stdio only) ─────────
862
1032
  if (caps.has('scan')) {