outreacher
Provides LLM-based extraction of lead data from CSV files in unknown formats using OpenAI's API.
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., "@outreacherfind leads in the 'Q1 Outreach' campaign"
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.
Outreacher
An AI-powered lead qualification system with an MCP server for Claude Desktop and a Next.js SaaS frontend — built within 3 days.
All dev tooling runs via Docker. You do not need Go, Node, Bun, goose, or sqlc installed locally.
Developers: see
CLAUDE.mdfor commands, conventions, and test instructions.
This project demonstrates and acts as a foundation boilerplate for 2-mode operation of an AI MCP as:
Single-tenant Claude Desktop Go binary (individual use)
Multi-tenant Next.js SaaS + chat LLM + MCP Go server (hosted environment)
The project architecture includes:
AI SDK + assistant-ui chat
Example MCP development
Shared backend code for both binary and server operation
Claude Code (and other development agent) usage and best practices
Docker best practices for development and production
Database security role/schema best practices (adopted early for scale)
📸 Demo & Walkthrough
See the full demo with screenshots and flows here:
👉 View Demo Docs
Related MCP server: atiendo24-mcp-server
Architecture
Claude Desktop
└── bin/outreacher-mcp-0.1.0-linux-amd64 (Go stdio binary, WSL)
└── localhost:5432 (standalone postgres, volume: outreacher_standalone_data)
Browser / Next.js frontend
└── app (Next.js, :3000)
└── mcp (:3001, Go SSE server, air hot reload)
└── postgres (internal only, volume: outreacher_postgres-data)Two runtime modes — standalone binary for Claude Desktop, Docker Compose for development. Important: use separate named volumes for each mode to avoid data directory conflicts.
Tech Stack
Next.js 15 (App Router, Bun)
Go MCP server (
mcp/) — stdio + SSE transports, pgx/v5, sqlc, goose migrationsPostgreSQL 16 —
appschema, named Docker volumeDocker Compose — dev stack with air hot reload on the Go server
DB Users
User | Password | Role |
|
| Owns schema, runs DDL and migrations |
|
| Next.js runtime — member of |
|
| MCP server runtime — member of |
|
| Read-only access — member of |
Group roles (no LOGIN) — DEFAULT PRIVILEGES auto-cover new tables/sequences/types:
app_crud— SELECT/INSERT/UPDATE/DELETE on app schemaapp_read— SELECT on app schema
DATABASE_URL → mcp user (MCP server) or app user (Next.js). DATABASE_ADMIN_URL → admin user (goose only).
Schema (app)
Multi-tenancy
Table | Key fields |
| id, name, slug (unique), is_system |
| id, organization_id, name, slug, is_default |
| id, email†, slug (unique), name, is_system |
| organization_id, user_id, role (owner|admin|member) |
| campaign_id, user_id, role (admin|member|viewer) |
Domain (scoped to campaign_id)
Table | Key fields |
| id, campaign_id, name, domain, industry, linkedin_url |
| id, description — global, no campaign scope |
| signal_id, keyword — global |
| company_id, signal_id |
| id, campaign_id, name, email†, linkedin_url†, company_id, title, status, score, location, phone |
| id, lead_id, content, created_at |
| campaign_id, type, value — dedup key, PK is (campaign_id, type, value) |
†nullable. Leads are deduplicated by contact_identifiers, not by email.
Lead status flow: new → contacted → qualified → disqualified → converted
MCP Tools
Domain tools (all accept optional campaign_id; defaults to startup campaign)
Tool | Description |
| Filter by name, email, status, company, campaign_id |
| Full lead detail with company and notes |
| Advance a lead through the status flow |
| Append a note to a lead |
| Import from CSV text (auto-detects Gojiberry, Revli formats) |
| Search companies by name or domain |
| Full company detail with signals |
Campaign management (stdio binary only)
Tool | Description |
| List all campaigns for the current org |
| Get campaign details by id |
| Create a new campaign under the current org |
| Rename a campaign's display name |
Mode 1 — Claude Desktop (Go binary via WSL)
Build the binary:
npm run build:mcp
# outputs bin/outreacher-mcp-0.1.0-linux-amd64 (stdio, WSL)
# bin/outreacher-mcp-0.1.0-darwin-arm64 (stdio, macOS Apple Silicon)
# bin/outreacher-mcp-0.1.0-darwin-amd64 (stdio, macOS Intel)
# bin/outreacher-mcp-0.1.0-windows-amd64.exe
# bin/outreacher-server-0.1.0 (SSE server)Start standalone postgres:
docker run -d --name outreacher-pg --restart always \
-p 5432:5432 \
-e POSTGRES_DB=outreacher \
-e POSTGRES_USER=admin \
-e POSTGRES_PASSWORD=admin \
-v outreacher_standalone_data:/var/lib/postgresql/data \
-v "$(pwd)/postgres/init:/docker-entrypoint-initdb.d" \
postgres:16-alpineRun migrations:
PG_IP=$(docker inspect outreacher-pg --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}')
docker run --rm \
-v "$(pwd)/mcp:/src" -w /src \
--add-host=postgres:$PG_IP \
golang:1.24-alpine \
sh -c 'go run github.com/pressly/goose/v3/cmd/goose@latest \
-dir migrations postgres \
"postgresql://admin:admin@postgres:5432/outreacher" up'Claude Desktop config (Settings → Developer → Edit Config):
{
"mcpServers": {
"Outreacher": {
"command": "wsl.exe",
"args": [
"~/Code/outreacher/bin/outreacher-mcp-0.1.0-linux-amd64",
"--database-url", "postgresql://mcp:mcp@localhost:5432/outreacher",
"--openai-api-key", "sk-proj-..."
]
}
}
}Replace <user> with your WSL username. ANTHROPIC_API_KEY enables LLM-based CSV extraction for unknown formats; omit to use the built-in parsers only. Restart Claude Desktop after saving — the hammer icon confirms tools are connected.
The binary idempotently bootstraps system_default_org, system_default_user, and the Default campaign on first run.
Mode 2 — Docker Compose (dev stack)
Copy .env.example to .env and fill in API keys, then:
docker compose up --build -dService | Host port | Notes |
| 3000 | Next.js dev server |
| 3001 | Go SSE server, air hot reload |
| — | Internal only |
First-time migrations:
docker run --rm --network outreacher_default \
-v "$(pwd)/mcp:/src" -w /src \
golang:1.24-alpine \
sh -c 'go run github.com/pressly/goose/v3/cmd/goose@latest \
-dir migrations postgres \
"postgresql://admin:admin@outreacher-postgres-1:5432/outreacher" up'If the mcp container exited while waiting for migrations, restart it:
docker compose restart mcpImports
fixtures/imports/ is gitignored — it contains live personal data used for local development and debugging only. Supported formats: Gojiberry, Revli startup contacts, Revli investor contacts, Revli startup companies, Revli investor companies.
© Copyright
© 2026 Vitruvian Technology, Corp. All rights reserved.
This code is provided under a noncommercial license for evaluation and research purposes only.
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.
Latest Blog Posts
- 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/technicallypete/outreacher'
If you have feedback or need assistance with the MCP directory API, please join our Discord server