This is a remote MCP server for logging final agent completion events (for Cursor or any MCP client) into Cloudflare D1.
A full frontend app is scaffolded in frontend/.
- Feed route:
frontend/src/routes/index.tsx - Convex schema/functions:
frontend/convex/schema.ts,frontend/convex/posts.ts,frontend/convex/http.ts
To run it:
cd frontend
npx convex dev
npm run devAfter Convex is configured, open http://localhost:3000.
The frontend now requires Convex Auth with GitHub to issue user API keys.
Set these Convex environment variables:
npx convex env set SITE_URL http://localhost:3000
npx convex env set AUTH_GITHUB_ID <github-client-id>
npx convex env set AUTH_GITHUB_SECRET <github-client-secret>Also ensure JWT_PRIVATE_KEY and JWKS are configured (used by Convex Auth sessions).
- Exposes exactly one MCP tool:
save - Stores completion analytics into D1
- Rejects
/mcprequests unless they include a Bearer token (MCP_SHARED_SECRET) - Exposes public paginated read endpoints for your future UI:
GET /api/stats/usersGET /api/stats/eventsGET /api/stats/summary
save expects:
api_key(string, required) — generated in the frontend UI after GitHub logincompletion_type(clarifying_question | plan | plan_succeeded | changes_made | answer_only | error)completion_status(completed | failed)completion_word_count(integer)prompt_summary(string, required) — a 2-3 sentence human-readable summary of the latest user prompt. Should not contain code or secrets.- optional:
event_id,files_edited_count,files_edited,project,client,metadata
event_id is used for idempotency. If the same event_id is sent again, it is ignored.
No remote MCP endpoint can cryptographically prove "this call came from Cursor only." A caller can always mimic an MCP request.
This server reduces spam with:
- shared secret requirement on
/mcp - API key resolution against Convex Auth users (GitHub-linked identity)
- idempotent event insertion with unique
event_id
If you need stronger protection, add OAuth (Cloudflare Access or third-party OAuth).
- Install dependencies:
npm install- Create D1 database:
npx wrangler d1 create worldcommits-analytics-
Copy the returned
database_idintowrangler.jsonc. -
Apply migration:
npx wrangler d1 migrations apply worldcommits-analytics --local- Create local secrets:
cp .dev.vars.example .dev.varsSet MCP_SHARED_SECRET, CONVEX_SITE_URL, and CONVEX_INGEST_TOKEN in .dev.vars.
- Run locally:
npm run devSet the shared secret:
npx wrangler secret put MCP_SHARED_SECRETApply migration to remote D1:
npx wrangler d1 migrations apply worldcommits-analytics --remoteDeploy:
npm run deployTop users by words:
curl "https://<your-worker>.workers.dev/api/stats/users?sortBy=words&order=desc&page=1&pageSize=20"Events for one user:
curl "https://<your-worker>.workers.dev/api/stats/events?git_email=user@example.com&page=1&pageSize=50"Use your remote server URL and send authorization header:
- URL:
https://<your-worker>.workers.dev/mcp - Header:
Authorization: Bearer <MCP_SHARED_SECRET>
Your MCP client or wrapper should call save only after completion is finalized, and pass the user-issued api_key. GitHub identity is resolved server-side from Convex Auth, not from client-provided git config values.