enrichment-mcp
Provides a durable lead store (Postgres) for storing and retrieving qualified leads across sessions, with tools to add, list, get, update status, and retrieve uncontacted leads.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@enrichment-mcpSearch for custom webshop leads without bug bounty programs"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
enrichment-mcp: Depth-First Lead Discovery for a Bug-Bounty Offering
Project Overview
Selling a penetration-testing / bug-bounty service is a high-consideration, low-volume sale. Spraying hundreds of generic emails is the wrong shape for it -- the win is a few right companies, each reached through the right person, not a big funnel of weak contacts. Most lead-gen tooling optimises for the opposite: discover everything, enrich everything, auto-send. That produces volume and burns goodwill.
enrichment-mcp inverts that. It is a depth-first lead finder: per run it surfaces a handful of candidate custom-built B2B / high-blast-radius commerce operators (distributors, wholesalers, B2B webshops, marketplaces, trade platforms holding valuable/sensitive customer data -- not low-stakes B2C consumer-hobby shops), qualifies them hard, and for each keeper resolves the single best decision-maker. The deliverable stops at a stored, qualified lead carrying lean context -- enough to recognise the company, one verified contact, and a one-line "why". A human decides what to do next; the system never reaches out and never tests anything.
The design splits cleanly across two execution contexts. Claude (in claude.ai or Claude Code) runs discovery and qualification in-session using its own web_search / web_fetch -- no third-party search API, no LLM key pool. A thin FastMCP server does only the two things the chat sandbox cannot: paid contact resolution through an enrichment chain -- Prospeo primary, Apollo failover (outbound APIs the sandbox blocks) and a durable lead store that remembers state across sessions. This is a ground-up rebuild of an older volume-funnel pipeline (clay-enrichment); roughly 5,000 lines of key-pool and worker machinery were dropped, four assets salvaged.
Related MCP server: LeadClaw
How It Works
For each run, Claude drives the loop and calls the server only when it must:
Claude session (lead-finder skill)
web_search / web_fetch ── discovery, hard qualification, NO_MATCH fallback mining
│ tool calls over HTTPS (static bearer)
▼
https://enrichment-mcp-<num>.<region>.run.app/mcp (Cloud Run — auto-HTTPS, scales to zero)
│
Cloud Run container (GCP) — env from Secret Manager
FastMCP server ── 7 tools, bearer auth, Streamable HTTP at /mcp
│
▼
Supabase Postgres Prospeo enrich-person ─┐ MyEmailVerifier
(leads + prospeo_usage) (X-KEY multi-key pool) ├─► (validate_single)
Apollo people/match ─┘
(x-api-key, failover)The qualification loop is deliberately discard-heavy:
Discover -- run one to three angles via
web_searchto surface a handful of candidates (not a funnel).Qualify hard --
web_fetcheach site and score it 0-10 against the ICP: is it a custom (non-platform) stack, is it receptive (no existing public bounty program, no in-house AppSec), is its breach blast-radius high (B2B / distributor / marketplace holding valuable/sensitive customer data -- a gated criterion; low-stakes B2C hobby shops are out), is it right-sized to pay and stay unwatched, is there a reachable technical decision-maker.Keep only winners -- discard anything under the
>=7gate immediately and explicitly. Quality over count.Resolve one contact -- name the single best decision-maker, then call
resolve_contact; the server runs the enrichment chain (Prospeo, then Apollo if Prospeo is out of quota or has no record) and returns one verified email + LinkedIn + title, tagged with the provider that found it.Fallback on miss -- on
reason: no_match(every provider answered, none had the person), mine the site's team/about pages in-session, guess the email pattern, and confirm withverify_email; accept only aValidresult.Store lean -- write the lead via
add_qualified_lead. If no contact resolves, the company is still stored (flagged), never thrown away.
Distinguish no_match from reason: provider_unavailable: the latter means every provider was out of quota or unreachable, so nothing was learned about the person -- top up credits rather than falling back to a guess.
Data-flow invariant: web tools run in the session; enrichment and state run on the server. The server holds no loop, no scheduler, no autonomous discovery -- it only acts when Claude calls a tool.
Targeting Scope
Dimension | In scope | Out of scope |
Stack | Custom / bespoke webshops (own checkout, APIs, accounts) | Templated SaaS stores whose security is the platform's problem |
Size | Mid-market: big enough to pay a bounty | Large enterprises with in-house security teams |
Security posture | No existing public bounty program; signs of receptiveness | Companies already on HackerOne / Bugcrowd / Intigriti |
Contact | One reachable decision-maker (CTO / lead dev / founder) | Bulk people enumeration; every employee |
The qualification rubric scores five criteria 0-2 each (custom-stack confidence, receptiveness, attack surface, ability to pay, reachable decision-maker) and sums to a 0-10 bounty_fit_score. The keep-gate is >=7 and custom-stack >=1 and receptiveness >=1, so a clear platform store or an existing bounty program is an automatic discard regardless of total.
Quick Start
Requirements: Python 3.10+ and a Postgres instance (the design targets Supabase; any Postgres works).
# 1. Create a virtualenv and install dependencies
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
# 2. Configure environment
cp .env.example .env
# Edit .env and fill in the values (see the table below)
# 3. Apply the database schema (SUPABASE_DB_URL must be set) -- run EVERY numbered
# file in order; each is idempotent, so re-running is safe.
psql "$SUPABASE_DB_URL" -f schema/001_leads.sql
psql "$SUPABASE_DB_URL" -f schema/002_engagement_statuses.sql
psql "$SUPABASE_DB_URL" -f schema/003_nudge_channels.sql
psql "$SUPABASE_DB_URL" -f schema/004_project_partition.sql
psql "$SUPABASE_DB_URL" -f schema/005_provider_column.sql
# 4. Run the server
.venv/bin/python -m src.mcp_server
# Serves Streamable HTTP at http://MCP_HOST:MCP_PORT/mcp (default 0.0.0.0:8000)Environment variables (.env.example is the authoritative list):
Variable | Purpose |
| Full Postgres DSN to the lead store (required) |
| Comma-separated Prospeo keys (free-tier pool, rotated round-robin) -- primary tier |
|
|
| Comma-separated Apollo keys -- failover tier. Empty = Prospeo-only. Needs a paid Apollo plan; free/trial keys 403 on |
|
|
| MyEmailVerifier key for the guess-and-verify fallback |
| Static bearer the server requires on every request |
| Bind address / port (default |
Usage
Connecting Claude
Claude Code (default path -- static bearer):
claude mcp add --transport http enrichment-mcp \
https://enrichment-mcp-<num>.<region>.run.app/mcp \
--header "Authorization: Bearer <MCP_BEARER_TOKEN>"Use the live Cloud Run service URL (printed by the deploy) with /mcp appended, and the MCP_BEARER_TOKEN from Secret Manager.
claude.ai web connector (OAuth). The web app cannot send a bearer header, so it uses OAuth. The server supports it via MCP_OAUTH_PROVIDER (see auth.py):
workos(recommended) -- WorkOS AuthKit via the fullWorkOSProvider: FastMCP serves the OAuth + DCR endpoints to claude.ai itself and proxies the login to AuthKit with a pre-registered client (so it works even though AuthKit's metadata omits a registration endpoint). SetMCP_OAUTH_PROVIDER=workos,WORKOS_AUTHKIT_DOMAIN=https://<name>.authkit.app,WORKOS_CLIENT_ID,WORKOS_CLIENT_SECRET(the WorkOS API key), andMCP_BASE_URL=<public run.app URL>, then redeploy. Add<MCP_BASE_URL>/auth/callbackto the WorkOS application's redirect URIs. claude.ai (Settings -> Connectors -> Add custom connector -> paste<base>/mcp) then drives the login.oidc-- any OIDC provider (Descope, Auth0, Google, ...) viaOIDCProxy: setMCP_OIDC_CONFIG_URL,MCP_OIDC_CLIENT_ID(+ secret), andMCP_BASE_URL.supabase-- reuse the project's own Supabase Auth, but only if that project advertises an OAuth registration endpoint (many do not -- preferworkos).
Switching modes is pure config -- no code change. Bearer mode (empty MCP_OAUTH_PROVIDER) stays available for Claude Code.
Running a lead hunt
The skills/lead-finder/ skill drives the depth-first workflow end-to-end. In a Claude session with the connector attached, give it a brief ("independent EU streetwear shops on custom stacks") and it runs discovery, qualifies, resolves contacts, and stores keepers -- calling the tools below. Across sessions, get_uncontacted is the durable memory of who is qualified but not yet acted on.
Tools
Lead store (CRM / state)
Tool | Purpose |
| Upsert a qualified lead within a |
| List leads (COMPACT rows) for a |
| Fetch one lead (full row) by domain within a |
| Advance the status enum for a domain within a |
| Leads (compact) at |
Contact resolution (server-side network)
Tool | Purpose |
| Run the Prospeo |
| Verify a guessed address via MyEmailVerifier; the fallback accepts only |
Status flow: qualified --> contact_resolved --> contacted --> replied --> agreement_sent --> signed --> authorized_ready --> running --> reported --> closed / rejected.
Project partition. The leads table is shared by more than one outreach
pipeline (pentest / bug-bounty and the Avelero licensing pipeline). Every row
carries a project tag (pentest | avelero) and every lead-store tool is scoped
to it: reads filter by it, writes stamp it, and a domain owned by one project can't
be taken by the other. The scope is the LEADS_PROJECT env default (pentest),
overridable per call via the tools' project argument. list_leads /
get_uncontacted return a COMPACT projection (scan fields + a truncated summary) so
large lists stay under the MCP output cap; get_lead returns the full row.
Technical Details
Module breakdown
Path | Responsibility |
| FastMCP app, pluggable bearer auth ( |
| Typed config -- plain |
| asyncpg pool built from |
| The five lead-store operations (parametrized, dict returns) |
| Shared |
| Multi-key Prospeo |
| Multi-key Apollo |
| MyEmailVerifier client (inlined |
| Write-free |
|
|
| The Claude-side skill: |
The lead record (intentionally lean)
One leads table, keyed on domain:
Column | Notes |
| Primary key |
| Enough to recognise the lead |
|
|
| The 0-10 qualification score |
| One-line rationale (receptiveness evidence folded in) |
| The funnel enum above |
| The one best contact -- all nullable |
|
|
A second table, prospeo_usage, meters credit burn across the key pools. Its provider column (schema 005) splits Prospeo spend from Apollo spend; the table keeps its original name for migration safety.
Credit model
Call | Cost on hit | Cost on miss |
Prospeo | 1 credit | NO_MATCH is free |
Prospeo | 10 credits | free |
Prospeo duplicate within ~90 days | free | -- |
Apollo | 1 credit | no-data is free |
Apollo | up to 9 credits | free |
MyEmailVerifier | 1 credit | 1 credit (still returns a status) |
Depth-first targeting keeps these low by design -- one resolution per kept lead, not per candidate.
Hosting
The server runs on Google Cloud Run as a container: automatic HTTPS, a public *.run.app URL, and scale-to-zero (no cost when idle). Secrets live in Secret Manager and are injected as env vars; the app-layer bearer is what actually protects the public endpoint (--allow-unauthenticated at the IAM layer so claude.ai, which carries no Google identity, can reach it).
deploy/deploy-cloudrun.sh is the reproducible runbook (project, APIs, secrets, deploy). The Dockerfile builds the image; Cloud Run injects $PORT, which config.py honors. One-liner to redeploy after a code change:
gcloud run deploy enrichment-mcp --source . --region <region> \
--allow-unauthenticated --max-instances 1 \
--set-secrets=MCP_BEARER_TOKEN=MCP_BEARER_TOKEN:latest,SUPABASE_DB_URL=SUPABASE_DB_URL:latest,PROSPEO_API_KEYS=PROSPEO_API_KEYS:latest,APOLLO_API_KEYS=APOLLO_API_KEYS:latest,MYEMAILVERIFIER_API_KEY=MYEMAILVERIFIER_API_KEY:latestCloud Run pins secret versions per revision, so after updating a secret value, redeploy (or roll a new revision) to pick it up.
Roadmap
Platform fingerprint tool -- an optional server-side check (
cdn.shopify.com,/wp-content/, platform headers) if Claude's page-judgment of custom-vs-platform proves unreliable. Deliberately deferred; Claude judges from the page for now.OAuth path for the claude.ai web connector -- FastMCP
OIDCProxy+ a hosted IdP, swappable into the existing auth layer.domain-searchassist -- fall back to Prospeo's domain search when naming the decision-maker is hard (currently out of scope to preserve the one-best principle).
Disclaimer
This is a sales-qualification tool, not a reconnaissance or testing tool. It discovers publicly listed companies, judges their fit for a security-research engagement, and identifies one business contact for a human to approach. It does not contact prospects, does not send email, and does not run or trigger any security test -- those remain separate, human-gated actions. Process contact data in line with GDPR and applicable anti-spam rules, and only pursue testing against a target with explicit written authorization. Built for the author's own bug-bounty offering; not licensed for external distribution.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceA comprehensive B2B intelligence server providing over 48 tools for lead generation, company research, and sales automation via the Model Context Protocol. It enables AI-powered prospect discovery, enrichment, and competitive analysis through seamless integrations with Make.com, Claude Desktop, and Apify.Last updated2MIT
- Alicense-qualityAmaintenanceMCP server that enables AI agents to discover and qualify B2B leads from Leadbay's knowledge base, with tools for lead research, enrichment, and outreach logging.Last updatedMIT
- Alicense-qualityDmaintenanceLead generation MCP server for AI agents. Find emails, verify contacts, enrich profiles, and search prospects using Hunter.io, Apollo.io, and Abstract API.Last updated6MIT
- Alicense-qualityBmaintenanceMCP-native sales intelligence server enabling prospect enrichment, LinkedIn scraping, and CRM push to HubSpot/Salesforce via natural language.Last updated91Mozilla Public 2.0
Related MCP Connectors
B2B lead generation, email verification, company enrichment, and agentic GTM Ops.
Managed LinkedIn MCP server for AI agents: search, connect, message and enrich on accounts you own.
Stealth scraping & search. Bypasses Cloudflare, DataDome & LinkedIn via Cyborg HITL approach.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tr4m0ryp/enrichment-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server