Skip to main content
Glama
bhairavaa

Local MCP CRM

by bhairavaa
README.md
# 🧩 Local MCP CRM

> A local-first CRM built on the **Model Context Protocol (MCP)** β€” customer & project
> management exposed as MCP tools, driven by either a custom LlamaIndex ReAct agent
> or directly from **Claude Code**.

<p>
  <img alt="python" src="https://img.shields.io/badge/Python-3.13-3776AB?logo=python&logoColor=white">
  <img alt="mcp" src="https://img.shields.io/badge/Protocol-MCP-6f42c1">
  <img alt="sqlite" src="https://img.shields.io/badge/Database-SQLite-003B57?logo=sqlite&logoColor=white">
  <img alt="llamaindex" src="https://img.shields.io/badge/Agent-LlamaIndex-black">
  <img alt="status" src="https://img.shields.io/badge/status-active-success">
</p>

## πŸ“Έ Screenshots

**Both servers connected inside Claude Code (VS Code extension):**

![MCP servers overview](assets/mcp-servers-overview.png)

**CRM server tools:**

![CRM server tools](assets/crm-server-tools.png)

**Analytics server tools:**

![Analytics server tools](assets/crm-analytics-tools.png)

## πŸ“– Table of Contents

- [Screenshots](#-screenshots)
- [Why this project](#-why-this-project)
- [Architecture](#-architecture)
- [Features](#-features)
- [Tech Stack](#-tech-stack)
- [MCP Tools Reference](#-mcp-tools-reference)
- [Getting Started](#-getting-started)
- [Project Structure](#-project-structure)
- [Roadmap](#-roadmap)

## 🎯 Why this project

This is a small, deliberately layered CRM that doubles as a hands-on demonstration of the
**Model Context Protocol** β€” the emerging standard for connecting LLMs to tools and data.
It ships **two independent MCP servers** (`crm` and `crm-analytics`), each exposing a clean
set of tools over stdio, and **two different clients** talking to them:

1. A **custom agent** (`client/`) β€” a LlamaIndex `ReActAgent` wired to a free OpenRouter
   model, with its own MCP client, tool-schema translation, and a simple multi-turn
   "collect missing fields" workflow.
2. **Claude Code itself** β€” via `.mcp.json`, the same servers plug straight into Claude
   Code (or any other MCP-compatible client) with zero extra glue code.

The point isn't the CRM domain (customers/projects are intentionally simple) β€” it's the
architecture underneath: a clean **repository β†’ service β†’ MCP tool β†’ server** pipeline that
keeps business logic, data access, and protocol plumbing separate and independently
testable.

## πŸ—οΈ Architecture

```mermaid
flowchart LR
    subgraph Clients
        A["Custom ReAct Agent\n(client/chat.py)"]
        B["Claude Code /\nany MCP client"]
    end

    subgraph Servers["MCP Servers (stdio)"]
        C["CRM Server\nservers/crm_server"]
        D["Analytics Server\nservers/analytics_server"]
    end

    subgraph Domain["Domain Layer"]
        E["Services\n(validation & business rules)"]
        F["Repositories\n(data access)"]
    end

    G[("SQLite\ncrm.db")]

    A -- MCP --> C
    A -- MCP --> D
    B -- MCP --> C
    B -- MCP --> D
    C --> E
    D --> E
    E --> F
    F --> G
```

Each layer has one job:

- **Repositories** β€” raw SQL against SQLite, nothing else.
- **Services** β€” validation and business rules (e.g. "can't create a project for a
  customer that doesn't exist").
- **MCP tools** β€” translate service calls into the `{success, data/error, message}`
  shape every tool returns.
- **Servers** β€” register those tools on a `FastMCP` instance and speak stdio.

## ✨ Features

- βœ… Customer CRUD β€” create, look up by name or ID
- βœ… Project lifecycle β€” create, update status (`Active` / `Delayed` / `Completed`), list by customer
- βœ… Analytics β€” aggregate stats, delayed-project tracking, per-customer reports
- βœ… Two independent MCP servers, each with a focused tool surface
- βœ… Works as a drop-in MCP integration for **Claude Code** β€” no adapter code needed
- βœ… Standalone chat agent with tool-calling via LlamaIndex `ReActAgent`
- βœ… Layered architecture (repository / service / tool / server) β€” each piece testable in isolation

## πŸ› οΈ Tech Stack

| Layer | Technology |
|---|---|
| Protocol | [Model Context Protocol](https://modelcontextprotocol.io) (`mcp` Python SDK, `FastMCP`) |
| Agent / LLM orchestration | [LlamaIndex](https://www.llamaindex.ai/) `ReActAgent` |
| LLM | OpenRouter (free-tier model) / LM Studio (local, optional) |
| Database | SQLite |
| Language | Python 3.13 |

## πŸ”§ MCP Tools Reference

### `crm` server

| Tool | Description |
|---|---|
| `create_customer` | Create a customer (`name`, `email`, `company`) |
| `get_customer_by_name` | Look up a customer by name |
| `get_customer_by_id` | Look up a customer by ID |
| `create_project` | Create a project under a customer |
| `update_project_status` | Update a project's status |
| `get_projects_by_customer` | List all projects for a customer |

### `crm-analytics` server

| Tool | Description |
|---|---|
| `get_customer_statistics` | Aggregate counts β€” total customers, total projects, delayed projects |
| `get_delayed_projects` | List every project currently marked `Delayed` |
| `generate_project_report` | Full project report for a single customer |

## πŸš€ Getting Started

### Prerequisites

- Python 3.13+
- An [OpenRouter](https://openrouter.ai) API key (free tier works) β€” only needed for the
  standalone chat agent, **not** for using the servers from Claude Code

### 1. Clone & set up a virtual environment

```bash
git clone <your-repo-url>
cd local-mcp-crm

python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate

pip install -r requirements.txt
```

### 2. Configure environment variables

```bash
cp .env.example .env
# then fill in OPENROUTER_API_KEY (and LM Studio settings, if you use them)
```

### 3. Initialize the database

```bash
python -m database.schema
```

### 4. Run it

**Option A β€” standalone chat agent:**

```bash
python -m client.chat
```

**Option B β€” plug into Claude Code:**

```bash
cp .mcp.json.example .mcp.json
# replace <ABSOLUTE_PATH_TO_PROJECT> with this project's absolute path
# (on macOS/Linux, point "command" at .venv/bin/python instead of .venv/Scripts/python.exe)
```

Reload Claude Code / run `/mcp` β€” you should see `crm` and `crm-analytics` connected, as
in the screenshots above.

## πŸ“‚ Project Structure

```
local-mcp-crm/
β”œβ”€β”€ servers/
β”‚   β”œβ”€β”€ crm_server/          # MCP server: customers & projects
β”‚   └── analytics_server/    # MCP server: aggregate analytics
β”œβ”€β”€ services/                # Business rules & validation
β”œβ”€β”€ repositories/            # SQLite data access
β”œβ”€β”€ database/                # Schema + connection helper
β”œβ”€β”€ client/                  # Standalone LlamaIndex ReAct agent
β”œβ”€β”€ models/                  # (reserved for typed domain models)
β”œβ”€β”€ tests/                   # Manual verification scripts
β”œβ”€β”€ .env.example
β”œβ”€β”€ .mcp.json.example
└── requirements.txt
```

## πŸ—ΊοΈ Roadmap

- [ ] Convert the manual scripts in `tests/` into a real `pytest` suite
- [ ] Pydantic-based input validation at the MCP tool boundary
- [ ] Package `crm_server` and `analytics_server` into a single MCP server with resource-based tool grouping
- [ ] CI (lint + tests) on push

---

<p align="center">Built as a hands-on exploration of the Model Context Protocol.</p>