@spooky-sync/devtools-mcp 0.0.1-canary.69 → 0.0.1-canary.71

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/AGENTS.md CHANGED
@@ -26,7 +26,8 @@ Wire into Claude / your agent via the MCP server config (`.mcp.json` at the repo
26
26
  - **`list_connections`** — which browser tabs are currently bridged.
27
27
  - **`get_state` `[tabId]`** — full devtools state: events, queries, auth, database tables (extension only).
28
28
  - **`get_auth_state` `[tabId]`** — current auth subject + scope (extension only).
29
- - **`get_active_queries` `[tabId]`** — registered live queries and their last result hashes.
29
+ - **`get_active_queries` `[tabId]`** — registered live queries, their last result hashes, and a per-query `timings` breakdown.
30
+ - **`get_query_timings` `[tabId]`** — per-query processing-time breakdown (SSP parse/plan/snapshot + store-apply/circuit-step/transform, local & remote record fetch, frontend reconcile; each as last/p50/p90/p99), sorted slowest-first. For debugging perf.
30
31
  - **`get_events` `[eventType] [limit]`** — recent event log, optionally filtered.
31
32
  - **`clear_history` `[tabId]`** — wipe the in-tab event log (extension only).
32
33
 
package/dist/server.js CHANGED
@@ -106,6 +106,35 @@ export function createServer(bridge, surreal) {
106
106
  }
107
107
  throw new Error('No extension connected and no direct database configured.');
108
108
  });
109
+ server.tool('get_query_timings', 'Per-query processing-time breakdown for debugging: SSP phases (parse/plan/snapshot at registration; store-apply/circuit-step/transform per ingest, plus whole-ingest `ssp` wall time), local & remote record-fetch, and frontend reconcile — each as { lastMs, p50, p90, p99, count } — sorted slowest-first. Requires the Sp00ky DevTools browser extension. The SurrealDB fallback only exposes persisted materialization percentiles (the per-phase samples are in-memory).', { tabId: z.number().optional().describe('Browser tab ID') }, async ({ tabId }) => {
110
+ if (bridge.isConnected) {
111
+ const state = (await bridge.request(BRIDGE_METHODS.GET_STATE, {}, tabId));
112
+ const queries = state?.activeQueries
113
+ ? Object.values(state.activeQueries)
114
+ : [];
115
+ // Rank by the dominant phases' p90 (fall back to last) so the slowest
116
+ // query/phase surfaces first.
117
+ const scoreOf = (t) => ['ssp', 'localFetch', 'remoteFetch', 'frontend'].reduce((s, k) => s + (t?.[k]?.p90 ?? t?.[k]?.lastMs ?? 0), 0);
118
+ const rows = queries
119
+ .map((q) => ({
120
+ queryHash: q.queryHash,
121
+ query: q.query,
122
+ updateCount: q.timings?.updateCount ?? q.updateCount,
123
+ errorCount: q.timings?.errorCount,
124
+ timings: q.timings ?? null,
125
+ _score: scoreOf(q.timings),
126
+ }))
127
+ .sort((a, b) => b._score - a._score)
128
+ // oxlint-disable-next-line no-unused-vars -- strip the internal sort key
129
+ .map(({ _score, ...rest }) => rest);
130
+ return json(rows);
131
+ }
132
+ if (surreal) {
133
+ const result = await surreal.query('SELECT * FROM _00_query;');
134
+ return json(result);
135
+ }
136
+ throw new Error('No extension connected and no direct database configured.');
137
+ });
109
138
  server.tool('get_events', 'Get event history, optionally filtered by type', {
110
139
  eventType: z.string().optional().describe('Filter by event type'),
111
140
  limit: z.number().optional().default(50).describe('Max number of events to return'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spooky-sync/devtools-mcp",
3
- "version": "0.0.1-canary.69",
3
+ "version": "0.0.1-canary.71",
4
4
  "description": "MCP server for Sp00ky Sync devtools",
5
5
  "license": "MIT",
6
6
  "type": "module",