Skip to main content
Glama
mansisonani07

LeadMind MCP

LeadMind MCP

An MCP (Model Context Protocol) server that turns an AI lead management system into a conversational tool any MCP-compatible AI client (like Claude Desktop) can control directly.

Free-tier only. Production-grade reliability. Built for a public GitHub demo.

LeadMind demonstrates four things at once:

  1. Practical MCP implementation using all three MCP primitives — tools, resources, and prompts — with the official Python SDK.

  2. Agentic reasoning beyond CRUD — the server classifies, suggests next actions, and synthesizes weekly reviews, not just stores records.

  3. Production-grade reliability engineering — caching, graceful degradation, and rate-limit handling, all of which are underrated but highly valued skills.

  4. Zero-cost architecture — every layer of the stack runs on a genuinely free tier (Groq LLM, SQLite, no external paid services). Suitable for a public GitHub demo with unlimited concurrent visitors.


Table of Contents


Related MCP server: PipeDrive MCP Server

Architecture

┌────────────────────────────────────────────────────────────────────────────┐
│                         MCP CLIENT (e.g. Claude Desktop)                   │
│                                                                            │
│  User says: "Show me all hot leads and suggest next action for the top."   │
└──────────────────────────────┬─────────────────────────────────────────────┘
                               │  MCP protocol (JSON-RPC over stdio or SSE)
                               ▼
┌────────────────────────────────────────────────────────────────────────────┐
│                          LEADMIND MCP SERVER                               │
│                          (mcp_server.py, FastMCP)                          │
│                                                                            │
│   ┌─────────────┐   ┌─────────────┐   ┌──────────────────────────────┐    │
│   │  8 Tools    │   │ 2 Resources │   │  1 Prompt Template           │    │
│   │  (tools.py) │   │             │   │  (weekly_lead_review)        │    │
│   └──────┬──────┘   └──────┬──────┘   └───────────────┬──────────────┘    │
│          │                 │                          │                    │
│          └────────────────┬┴──────────────────────────┘                    │
│                           ▼                                                │
│   ┌───────────────────────────────────────────────────────────────────┐    │
│   │                     Reliability Layer                              │    │
│   │                                                                   │    │
│   │   ┌────────────┐    ┌────────────────────┐    ┌──────────────┐    │    │
│   │   │  cache.py  │───▶│ groq_classifier.py │───▶│ fallback_    │    │    │
│   │   │  TTL+LRU   │    │  (Groq + counter)  │    │ classifier   │    │    │
│   │   └────────────┘    └─────────┬──────────┘    └──────────────┘    │    │
│   │                               │ rate-limit / error                   │    │
│   │                               ▼  → fallback                         │    │
│   └───────────────────────────────────────────────────────────────────┘    │
└──────────────────────────────┬─────────────────────────────────────────────┘
                               │
                ┌──────────────┴───────────────┐
                ▼                              ▼
   ┌─────────────────────────┐   ┌──────────────────────────────────┐
   │   SQLite (leadmind.db)  │   │   Groq API (free tier)           │
   │                         │   │   Llama-3.3-70b-versatile        │
   │   - leads               │   │   30 req/min free                │
   │   - lead_history        │   └──────────────────────────────────┘
   │   - audit_log           │
   │   - meta                │
   └─────────────────────────┘

Data flow for classify_lead(text):

classify_lead(text)
       │
       ▼
   cache.get()  ────────hit─────────▶  return cached (source="cache")
       │
       miss
       │
       ▼
   Groq API call  ─────success──────▶  return LLM result (source="groq")
       │
       429 / timeout / error
       │
       ▼
   fallback_classifier.classify()  ──▶  return rule-based (source="fallback")
       │
       ▼
   cache.set()  (so subsequent identical calls are free)

The Free-Tier-Only Stack

Every component runs on a genuinely free tier. No credit-card trials, no paid APIs, no surprise bills.

Layer

Choice

Free-tier details

LLM

Groq API (llama-3.3-70b-versatile)

Free forever; ~30 req/min, 14,500 req/day. Get a key.

Database

SQLite (local file)

Zero cost, zero ops, zero hosting. Lives in leadmind.db.

MCP SDK

modelcontextprotocol/python-sdk

Open-source (MIT).

Web framework

FastAPI (optional, webhook only)

Open-source.

Transport

stdio (local) or SSE (remote)

Built into the MCP SDK.

Hosting

Any free host (Render, Fly.io, Railway free tier, your laptop)

Static process; no special infra.

What's intentionally NOT used:

  • OpenAI / Anthropic APIs (paid, even with free credits they require a card).

  • Hosted Postgres / Supabase / PlanetScale (free tiers exist but require sign-up + card).

  • Any external SaaS for caching, queueing, or monitoring.


Setup

Prerequisites

Install

git clone <your-fork-url>
cd leadmind-mcp

python -m venv .venv
source .venv/bin/activate     # on Windows: .venv\Scripts\activate

pip install -r requirements.txt

Configure

cp .env.example .env
# Edit .env and optionally fill in GROQ_API_KEY

The server works without a Groq key — it will use the rule-based fallback classifier for everything. The Groq key just upgrades the classification quality.

Run

# Default: stdio transport (for Claude Desktop)
python mcp_server.py

# Or: SSE transport (for remote clients)
MCP_TRANSPORT=sse MCP_PORT=8080 python mcp_server.py

On first run, the server:

  1. Creates leadmind.db (SQLite).

  2. Seeds it with 18 realistic demo leads.

  3. Starts listening on stdio (or SSE).


Connecting to Claude Desktop

  1. Open Claude Desktop → Settings → Developer → Edit Config.

  2. Add LeadMind to claude_desktop_config.json:

    {
      "mcpServers": {
        "leadmind": {
          "command": "python",
          "args": ["/absolute/path/to/leadmind-mcp/mcp_server.py"],
          "env": {
            "GROQ_API_KEY": "your_key_here_or_leave_empty",
            "DEMO_MODE": "true"
          }
        }
      }
    }

    (See claude_desktop_config.example.json for a template.)

  3. Restart Claude Desktop. You should see leadmind under Settings → Developer → MCP Servers with a green "connected" indicator.

  4. Try the demo script in demo_script.md.


MCP Primitives Reference

Tools (8)

#

Tool

Description

Example call

1

tool_get_leads(status="")

Returns all leads, optionally filtered by Hot/Warm/Cold/Converted/Lost.

tool_get_leads(status="Hot")

2

tool_classify_lead(text)

Classifies a message into Hot/Warm/Cold with confidence + reasoning. Uses cache → Groq → fallback.

tool_classify_lead("Need a CRM urgently, budget approved")

3

tool_add_lead(name, contact_info, message, source="manual")

Adds a lead and auto-classifies on insert.

tool_add_lead(name="John", contact_info="john@x.com", message="...", source="Website Form")

4

tool_update_lead_status(id, status)

Manually overrides status; logs change with timestamp.

tool_update_lead_status(id=1, status="Converted")

5

tool_get_lead_stats()

Aggregate stats: totals, breakdown by status/source, avg response time, conversion rate, Groq usage.

tool_get_lead_stats()

6

tool_get_lead_history(id)

Full timeline of a lead's status changes and interactions.

tool_get_lead_history(id=1)

7

tool_suggest_next_action(id)

AI-generated next-action recommendation (with fallback).

tool_suggest_next_action(id=1)

8

tool_bulk_import_leads(csv_data)

Parses CSV text and batch-classifies + inserts. Uses cache to avoid redundant API calls on duplicates.

tool_bulk_import_leads("name,message\nJohn,...")

Example tool response (tool_classify_lead)

{
  "status": "Hot",
  "confidence": 0.85,
  "reasoning": "Hot because urgent language detected and budget mentioned — prioritize outreach.",
  "source": "groq"
}

Resources (2)

Resources are read-only data the MCP client can "read" like a file.

URI

Description

leads://dashboard

Live-updating summary snapshot of the whole pipeline — totals, breakdown, recent leads, Groq usage monitoring.

audit://recent

Last 30 tool-call audit entries with which path was used (groq/fallback/cache). Demonstrates observability.

Prompt Templates (1)

Prompt

Description

weekly_lead_review

Pre-packages a structured prompt for the AI client to generate a full weekly performance summary. Auto-injects current pipeline stats and instructs the AI to fetch more details via the tools.


Demo-Safety Design

This project is built to be deployed publicly on GitHub with a live demo link. Multiple strangers may open and test it simultaneously. The system must not break, get rate-limited into failure, or run out of quota. Here's how each risk is mitigated:

1. Response Caching (rate-limit prevention)

  • cache.py implements a thread-safe TTL cache (5-minute default, 500 entries max).

  • Cache key is a SHA-256 hash of the normalized message text.

  • Identical classify_lead(text) calls within the TTL window return cached results — zero Groq API calls burned.

  • Bulk imports of similar messages also benefit (a common pattern in real CRM data).

  • The cache is shared across all tool calls in the process.

  • Cache hits are tagged source: "cache" so they're visible in the audit log.

2. Graceful Fallback (zero-downtime under load)

  • fallback_classifier.py implements a transparent keyword/heuristic classifier with the same input/output contract as the Groq path.

  • If Groq returns 429 (rate limit), 5xx, times out, or any other error — the request transparently falls back to the rule-based classifier.

  • The response always includes source: "groq" | "fallback" | "cache" so the caller knows which path was used.

  • The fallback is explainable: every decision returns a human-readable reasoning string like "Hot because 3 urgent/intent signal(s) detected (budget, asap, decision-ready) — prioritize outreach.".

3. Seeded Demo Data (no empty-state embarrassment)

  • seed_data.py defines 18 realistic demo leads spanning Hot/Warm/Cold and 8 different sources.

  • On first run, the DB is seeded automatically.

  • Every seed lead's message is written to exercise both the Groq classifier and the fallback (so the demo is interesting even without a Groq key).

4. Demo Mode Auto-Reset (self-healing dataset)

  • When DEMO_MODE=true (default), the DB is reset to seed data every 6 hours (configurable via DEMO_RESET_INTERVAL_SEC).

  • Reset is triggered lazily on the next tool call after the interval expires — no background threads required.

  • The reset preserves the audit_log table so observability data accumulates across resets.

  • This means: even if 50 visitors add junk leads, call tool_bulk_import_leads with garbage, or tool_update_lead_status on everything — the demo self-heals within hours.

5. Groq Usage Monitoring (free-tier visibility)

  • Every Groq call increments an in-process counter (groq_classifier.get_call_count()).

  • Every call is also logged to groq_usage.log with status (success, rate_limited, error).

  • The leads://dashboard resource shows: calls this session, total logged, rate-limited count, error count.

  • tool_get_lead_stats() returns a groq_usage block in its response.

  • The audit_log table records every tool call with flags: used_groq, used_fallback, used_cache — so you can answer "what fraction of my demo traffic used the LLM?" with a single SQL query.

6. Optional Authentication (not just a local toy)

  • Set LEADMIND_AUTH_ENABLED=true and LEADMIND_API_KEY=<secret> for SSE / webhook deployments.

  • For stdio (Claude Desktop), auth is typically off because the transport is local.

  • The webhook receiver (webhook_receiver.py) validates X-API-Key on every request.


Project Structure

leadmind-mcp/
├── mcp_server.py             # FastMCP server: registers tools, resources, prompts
├── tools.py                  # 8 MCP tool implementations (with audit logging)
├── db.py                     # SQLite schema, CRUD, audit, demo-reset logic
├── groq_classifier.py        # Groq API + caching + fallback chain + usage counter
├── fallback_classifier.py    # Rule-based keyword classifier (negation-aware, weighted)
├── cache.py                  # Thread-safe TTL+LRU cache
├── seed_data.py              # 18 realistic demo leads + idempotent seeder
├── webhook_receiver.py       # Optional FastAPI app for n8n/Gmail integration
├── config.py                 # Central env-driven configuration
├── test_leadmind.py          # End-to-end tool tests (no Groq key needed)
├── test_mcp_protocol.py      # Real MCP JSON-RPC protocol smoke test
├── Makefile                  # install / test / run shortcuts
│
├── requirements.txt          # Python deps (all free / open-source)
├── .env.example              # Environment variable template
├── .gitignore
├── LICENSE                   # MIT
├── claude_desktop_config.example.json
├── demo_script.md            # Example conversation flow walkthrough
└── README.md                 # (this file)

Optional Integrations (n8n + Gmail)

n8n Webhook Trigger

webhook_receiver.py exposes an HTTP endpoint that n8n workflows can POST to:

# Start the webhook receiver (separate process from MCP server)
pip install fastapi uvicorn
python webhook_receiver.py   # listens on :8000

In n8n, add an HTTP Request node that POSTs to http://your-host:8000/webhook/lead:

{
  "name": "Lead from n8n",
  "contact_info": "lead@example.com",
  "message": "Interested in your product, saw it on the webinar",
  "source": "n8n Workflow"
}

The webhook receiver uses the same tools.add_lead() function, so the lead is auto-classified and inserted with full history.

Gmail Notification Hook (free tier)

Gmail's free tier allows ~20k emails/day — plenty for a demo. The recommended pattern:

  1. Create a Gmail filter that forwards matching emails (e.g. subject contains "Lead Inquiry") to a Gmail Apps Script.

  2. The Apps Script parses the email and POSTs to your /webhook/lead endpoint.

  3. (Optional) Set GMAIL_NOTIFY_TO env var to enable outbound notifications on new Hot leads.

The actual Gmail API integration is intentionally not bundled — it would require OAuth setup that breaks the zero-config demo. The webhook contract is documented so anyone can plug in their own Gmail bridge.


Demo Walkthrough

See demo_script.md for a full conversation-flow walkthrough. The short version:

  1. "Read the leads://dashboard resource." → Live pipeline snapshot.

  2. "Show me all hot leads and suggest next action for the top one." → Two tool calls chained automatically.

  3. "Add a new lead: John Smith, john@smith.com, 'Need CRM urgently, budget approved, this week', Cold Outreach." → Auto-classified as Hot.

  4. "Bulk import these CSV leads..." → Bulk path, cached classification.

  5. "Mark lead id=1 as Converted." → Manual override, logged in history.

  6. "Generate the weekly_lead_review prompt." → Template auto-injects stats; Claude calls further tools as instructed.


Testing

Two test suites are included. Both run without a Groq API key (they exercise the fallback path), so they're safe to run in CI.

1. End-to-end tool tests

make test        # or: python test_leadmind.py

Calls every tool directly (bypassing MCP transport), verifies the cache hit on second classify_lead call, asserts that add_lead auto-classifies correctly, and checks that resources/prompts return expected content.

2. Real MCP protocol smoke test

make test-proto  # or: python test_mcp_protocol.py

Spawns mcp_server.py as a subprocess, speaks the actual MCP JSON-RPC protocol over stdio, and verifies:

  • initialize handshake succeeds

  • tools/list returns 8 tools

  • resources/list returns 2 resources

  • prompts/list returns 1 prompt

  • tools/call returns real lead data

  • resources/read returns the dashboard text

  • prompts/get returns the weekly review template

This proves the server is connectable from any real MCP client (Claude Desktop, Cursor, etc.), not just callable as Python functions.


Troubleshooting

Server doesn't connect in Claude Desktop

  • Check the path in claude_desktop_config.json is absolute.

  • Check python is on your PATH (or use the full path to the Python binary).

  • Restart Claude Desktop fully (not just reload).

  • Look at Claude Desktop's developer logs: ~/Library/Logs/Claude/mcp-server-leadmind.log (macOS).

ModuleNotFoundError: No module named 'mcp'

  • Activate your virtualenv: source .venv/bin/activate.

  • Reinstall: pip install -r requirements.txt.

Classifications always say source: "fallback"

  • Either GROQ_API_KEY is not set, or Groq is rate-limiting you.

  • Check groq_usage.log — if you see lots of rate_limited lines, the fallback is doing its job.

  • The fallback is fully functional; classifications are still correct, just less nuanced.

Database is empty after cloning

  • Run python mcp_server.py once to trigger initial seeding.

  • Or run python -c "from seed_data import seed_database; seed_database()".

Demo mode keeps resetting my changes

  • That's intentional. Set DEMO_MODE=false in .env if you want your changes to persist.


License

MIT — see LICENSE.


Why this project exists

Built as a portfolio piece for an AI Automation Developer / Multi-Agent Systems role. It demonstrates:

  • MCP mastery — all three primitives (tools, resources, prompts) used appropriately.

  • Agentic design — the server doesn't just CRUD; it classifies, recommends, and synthesizes.

  • Reliability engineering — caching, graceful degradation, rate-limit handling. This is the part most portfolio projects skip, and the part hiring managers care about most for production roles.

  • Cost discipline — a real, usable AI product running on $0/month of infrastructure, suitable for unlimited public testing.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

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/mansisonani07/leadmind-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server