feat(mcp): add a typed PostHog wrapper module for packages/loopover-mcp - #6368
Conversation
Mirrors the remote wrapper's recordMcpToolCall shape (JSONbored#6235) for the local stdio server, but gated on an explicit, persisted opt-in flag (default OFF) rather than mere API-key presence, since a locally-run CLI is a different trust posture than the hosted remote server. The module stays a pure lib/ helper -- the caller resolves the opt-in flag from CLI config and passes it in -- and never throws. Closes JSONbored#6236
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
check-mcp-package.mjs's dry-run gate rejects any file the workspace's "files" glob would ship that isn't on this shared allowlist -- the new lib/telemetry.js wrapper (JSONbored#6236) needed adding here too.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6368 +/- ##
=======================================
Coverage 95.60% 95.60%
=======================================
Files 599 599
Lines 47221 47221
Branches 15024 15024
=======================================
Hits 45147 45147
Misses 1290 1290
Partials 784 784
Flags with carried forward coverage won't be shown. Click here to find out more. |
|
Warning ⏸️ LoopOver review result - manual review recommendedReview updated: 2026-07-16 05:40:24 UTC
Review summary Nits — 6 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
apps/loopover-ui/.source (the collections/* alias apps/loopover-ui/ tsconfig.json depends on) is produced by npm ci's own postinstall, which the validate-code job's node_modules cache hit skips entirely -- .source/ lives outside node_modules, so it never gets generated on a cache-hit run and ui:typecheck fails with "Cannot find module 'collections/browser'/'collections/server'". Confirmed this reproduces identically on main regardless of PR contents. Regenerating it explicitly here is cheap and a harmless no-op re-run on cache miss.
Summary
packages/loopover-mcp/lib/telemetry.js, a typedrecordMcpToolCall({ tool, callerType, ok, durationMs })wrapper for the local stdio MCP server, mirroring the already-merged remote wrapper's shape (src/mcp/telemetry.ts, feat(mcp): add a typed PostHog wrapper module for src/mcp/server.ts (remote) #6235) and PostHog event schema so both servers report consistent data.POSTHOG_API_KEYpresence alone), this one is gated on an explicit, persisted opt-in flag —options.telemetryEnabledmust be exactlytrue— before it even looks at an API key. This matches Spec: usage-telemetry instrumentation strategy for MCP (PostHog) #6228's stated privacy decision: a locally-run CLI needs opt-in, not opt-out, since it executes on a user's own machine. The already-mergedloopover-mcp telemetry enable|disablecommand (feat(mcp): add telemetry enable/disable CLI command with persisted opt-in #6348) is the mechanism that persists this flag; this module stays a purelib/helper and never reads CLI config itself — the caller resolves the flag and passes it in.LOOPOVER_MCP_POSTHOG_API_KEY/LOOPOVER_MCP_POSTHOG_HOSTenv vars, mirroring the remote wrapper's env-based configuration approach. No key configured ⇒ safe no-op, same as the remote side.posthog-nodeas a dependency ofpackages/loopover-mcp(a separately-published npm package, so it needs its own explicit dependency declaration) and wired the newlib/telemetry.jsinto the package's existingnode --check-per-filebuildscript.Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #123) — a linked open issue is required for every contributor PR.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally;codecov/patchrequires ≥99% coverage of the lines AND branches you changed (aim for 100% on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate.npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderateIf any required check was skipped, explain why:
wrangler(cf-typegen:checkfails with a pre-existing, change-unrelatedspawnSync wrangler ENOENT), which blocks the chainednpm run test:cifrom reaching later steps locally. Each step was therefore run individually:git diff --check,actionlint,db:migrations:check,db:schema-drift:check,selfhost:env-reference:check,miner:env-reference:check,selfhost:validate-observability,build:mcp, engine build,typecheck,test:engine-parity,test:live-gate-parity, andtest:driver-parityall pass clean on this branch.test:mcp-packalso fails locally with a pre-existing, change-unrelatedspawnSync npm ERR_INVALID_ARG_TYPE(confirmed identical on a cleanupstream/maincheckout viagit stash) — the same class of Windows-onlyspawnSynccross-platform issue ascf-typegen. The new module and its 11 tests (test/unit/mcp-local-telemetry.test.ts) pass cleanly and cover both the opted-in and default-off no-op paths, the missing/blank-API-key no-op paths, host override/trim/default-fallback, and both PostHog init- and capture-failure never-throw paths — mirroringtest/unit/mcp-telemetry.test.ts's coverage of the sibling remote wrapper. The broadermcp-cli-*sweep passes cleanly aside from 3 pre-existing, change-unrelated Windows-only symlink-permission failures (EPERM: operation not permitted, symlink).Safety
UI Evidencesection below — N/A, no UI change.UI Evidence
N/A — backend-only observability change, no visible UI change.
Notes
src/mcp/telemetry.ts) and feat(mcp): add telemetry enable/disable CLI command with persisted opt-in #6348 (loopover-mcp telemetry enable|disablepersisted opt-in). Wiring this wrapper into the local tool-dispatch chokepoint is the separate feat(mcp): instrument the local MCP tool-dispatch chokepoint with PostHog events (opt-in) #6238.