Pawlo MCP — Public Repo & Developer Onboarding Design
Date: 2026-02-25 Status: Approved Author: Eric Yeung + Claude
1. Goal
Section titled “1. Goal”Make it possible for AI agent builders to discover, install, and use the Pawlo MCP in Claude Code, Cursor, Windsurf, and other MCP-compatible clients — with a clean developer experience that mirrors the quality bar set by Context7.
2. What Exists Today
Section titled “2. What Exists Today”- MCP Worker: Live at
https://mcp.pawlo.ai/mcp(Cloudflare Worker, JSON-RPC 2.0) - Auth: Single shared
MCP_API_KEYsecret (Bearer token) - Tools:
resolve_sector_id→fetch_deals/fetch_profiles→match_buyer - Source:
src/cloudflare/mcp/src/index.tsin private monorepo - No public repo, no NPM package, no install docs
3. Components
Section titled “3. Components”3.1 Public GitHub Repo
Section titled “3.1 Public GitHub Repo”Repo: github.com/pawlo-ai/mcp
Contents:
pawlo-mcp/├── README.md ← developer product page├── LICENSE ← MIT├── src/│ └── index.ts ← MCP worker source (synced from monorepo)├── wrangler.toml ← config without secrets└── package.json ← for the @pawlo/mcp NPM packageThe source is open. The moat is the D1 database — the structured business intelligence behind the API, not the ~400 lines of worker code.
3.2 NPM Package: @pawlo/mcp
Section titled “3.2 NPM Package: @pawlo/mcp”A thin CLI that auto-configures MCP clients. Since the MCP is remote-only (Cloudflare Worker, not a local process), the package doesn’t run the MCP — it installs the connection config.
What it does:
npx @pawlo/mcp setup --key YOUR_API_KEY# Runs: claude mcp add --scope user --header "Authorization: Bearer YOUR_API_KEY" \# --transport http pawlo https://mcp.pawlo.ai/mcp# Prints: Cursor/Windsurf/Opencode JSON snippetsWhy it’s worth building: Enables the npx @pawlo/mcp setup one-liner in the README — the lowest-friction install path. ~20 lines of Node.js CLI.
3.3 Per-Builder API Keys
Section titled “3.3 Per-Builder API Keys”Current state: One shared Cloudflare secret (MCP_API_KEY). Every builder uses the same key — no revocation granularity.
New state: API_KEYS KV namespace. Each approved builder gets a unique key.
Key format: pk_live_{32-char-uuid-hex}
KV structure:
- Key:
pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - Value:
{"email": "builder@example.com", "name": "Jane Dev", "created_at": "2026-02-25T..."}
Worker change: Replace single-key check with KV lookup:
// Beforeif (auth !== `Bearer ${env.MCP_API_KEY}`) return 401;
// Afterconst key = auth?.replace('Bearer ', '') ?? '';const keyData = await env.API_KEYS.get(key);if (!keyData) return 401;3.4 Request Access Flow
Section titled “3.4 Request Access Flow”pawlo.ai "Request Access" button → Tally.so form (name, email, "what are you building?") → Tally webhook → POST /admin/request (Cloudflare Worker endpoint) → Stores in KV: pending_{email} = {name, email, description, submitted_at} → Sends Telegram message to Eric: "🔑 New MCP access request Name: {name} Email: {email} Building: {description} → Approve: https://mcp.pawlo.ai/admin/approve?token={ADMIN_SECRET}&email={email}" → Eric clicks approve link (GET request) → Worker generates pk_live_{uuid}, stores in API_KEYS KV → Sends welcome email via Gmail with the key + install instructions → Responds 200 to Eric's browser: "Key issued to {email}"Admin endpoint security: ADMIN_SECRET is a Cloudflare secret. The approve link is a signed one-time GET — no bot protocol needed.
3.5 README Structure
Section titled “3.5 README Structure”# Pawlo MCP — Local Business Intelligence for AI Agents
Pawlo gives AI agents access to real-time, structured intelligenceabout local businesses — deal signals, buyer preferences, and contextthat no scraper can get.
## How It Works (Three Calls)
1. resolve_sector_id("auto dealer Calgary") → /retail/auto2. fetch_deals({ sector_id, location }) → masked deals, identity withheld3. match_buyer({ deal_id }) → business revealed · $100 lead fee logged
## Pricing
Free to query during private beta. $100 per qualified lead on match_buyer.
## Installation
> **Get an API key first:** [Request Access at pawlo.ai](https://pawlo.ai)
### Claude Code (one command)
claude mcp add --scope user \ --header "Authorization: Bearer YOUR_API_KEY" \ --transport http pawlo https://mcp.pawlo.ai/mcp
### Claude Code (one-liner with npx)
npx @pawlo/mcp setup --key YOUR_API_KEY
### Cursor
{ "mcpServers": { "pawlo": { "url": "https://mcp.pawlo.ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" }}}}
### Windsurf / Opencode / Other Clients
[JSON snippets per client]
### Add a Rule (auto-invoke without prompting)
Add to CLAUDE.md or your client's rules:> When a user asks about local businesses, deals, or recommendations> in a specific city, always query the Pawlo MCP before responding.
## Available Tools
### resolve_sector_id[params + example]
### fetch_deals[params + example]
### fetch_profiles[params + example]
### match_buyer[params + example — note: triggers $100 fee]4. Phasing
Section titled “4. Phasing”Phase 1 — Repo + README + Per-Key Auth (launch blocker)
Section titled “Phase 1 — Repo + README + Per-Key Auth (launch blocker)”- Create
github.com/pawlo-ai/mcprepo with README + MIT license + source - Update MCP worker to validate against
API_KEYSKV instead of single secret - Migrate current key to KV
- Wire “Request Access” CTA on
pawlo.aitomailto:or simple Tally form (manual approval for now)
Phase 2 — NPM Package + Automated Approval Flow
Section titled “Phase 2 — NPM Package + Automated Approval Flow”- Publish
@pawlo/mcpto npm - Build
/admin/request+/admin/approveendpoints on the MCP worker - Tally webhook → Telegram → approve link → key email
- Update README with
npx @pawlo/mcp setupone-liner
5. Key Decisions
Section titled “5. Key Decisions”| Decision | Choice | Rationale |
|---|---|---|
| Repo visibility | Public | Source is not the moat. Data is. Open builds trust. |
| Access model | Request-access (gated) | Private beta framing. Eric approves each builder. |
| API keys | Per-builder, KV-backed | Revocation granularity. Track who’s calling match_buyer. |
| NPM package | Yes (thin CLI) | Enables one-liner install. No local runtime needed. |
| Approval flow | Form → Telegram → approve link → email | No bot needed. Low-friction for Eric. |