Salesmate MCP Server
A production-ready Model Context Protocol (MCP) server that exposes the Salesmate CRM to Claude Desktop (and any other MCP client). Built with FastMCP, HTTPX, Pydantic, and python-dotenv.
It lets Claude search contacts, inspect and update deals, create tasks and notes, and review recent activity — all through clean, typed, validated tools.
---
Get started
There are two ways to install. Pick one.
Option A - One-click install (.mcpb, no terminal)
The cleanest end-user experience. Anyone can install with no clone, no virtualenv, no JSON editing - just a click and a form.
- Download the
.mcpbbundle for your platform from the project's
GitHub Releases page (or build it yourself - see below).
- In Claude Desktop, go to Settings -> Extensions -> Install Extension...
and pick the .mcpb file.
- When prompted, enter:
- Salesmate Session Key (the field is masked; stored in your OS keychain).
- Salesmate Workspace URL, e.g.
https://yourcompany.salesmate.io.
- Done. No restart needed - the
salesmatetools appear in the tool picker.
Use the Session Key. Salesmate shows three keys - Access Key, Secret Key, and Session Key (Setup -> Integrations -> API & Webhooks). The v4 API used here authenticates with the Session Key; the other two return
AuthorizationFailed.
Build the bundle yourself
The .mcpb is platform-specific (Python wheels contain compiled binaries), so build it on the OS you'll install it on:
git clone https://github.com/arnav-chauhan-kgpian/salesmate-mcp.git
cd salesmate-mcp
python -m venv .venv
# Windows: .\.venv\Scripts\activate macOS/Linux: source .venv/bin/activate
pip install -e .
python build_mcpb.py
# Output: dist/salesmate-mcp-<platform>-py<ver>.mcpb
Then install the resulting .mcpb as in step 2 above.
---
Option B - Clone & connect (manual)
A new user with no copy of the code connects in four steps:
# 1. Clone the repo
git clone https://github.com/arnav-chauhan-kgpian/salesmate-mcp.git
cd salesmate-mcp
# 2. Create a virtualenv and install
python -m venv .venv
# Windows: .\.venv\Scripts\activate macOS/Linux: source .venv/bin/activate
pip install -e .
# 3. Connect to Claude Desktop (writes .env + Claude config, verifies live)
python setup_salesmate.py --verify
# 4. Fully quit and reopen Claude Desktop
You must provide your own secrets
This repository ships no credentials. Every user supplies their own Salesmate keys once. The setup_salesmate.py script will prompt for them and write them into a local .env file (which is git-ignored and never committed):
SALESMATE_API_KEY=<your Salesmate SESSION KEY>
SALESMATE_BASE_URL=https://yourcompany.salesmate.io
You can also create this .env by hand (copy .env.example to .env and fill it in) instead of letting the script prompt you — then run python setup_salesmate.py --no-input --verify.
Use the Session Key. Salesmate shows three keys — Access Key, Secret Key, and Session Key (Setup → Integrations → API & Webhooks). The v4 API used here authenticates with the Session Key; the other two return
AuthorizationFailed.
The setup script:
- Collects your Session Key + workspace URL (or reuses an existing
.env). - Writes them to
.env. - Registers the
salesmateserver in your Claude Desktop config — preserving
any servers you already have, with a .bak backup. No secrets are written into the Claude config; the server reads them from your .env.
- With
--verify, runs a live read-only check so you know it works before
opening Claude.
Non-interactive form (e.g. for scripted installs):
python setup_salesmate.py --api-key <SESSION_KEY> --base-url https://yourcompany.salesmate.io --verify
---
Features
- 🔌 8 MCP tools covering contacts, deals, tasks, notes and activities.
- 🧱 Modular architecture — config, client, models and exceptions are
cleanly separated; each tool group lives in its own module.
- 🔁 Resilient HTTP client — async HTTPX with a 30s timeout, automatic
retries and exponential backoff (honouring Retry-After) for transient 429/5xx/network failures.
- 🧪 Typed Pydantic models for every resource; structured JSON is always
returned — never raw HTTP responses.
- 🛡️ Robust error handling — every failure is mapped to a structured error
object (SalesmateAuthError, SalesmateNotFoundError, ...).
- 🪵 Structured logging to stderr (stdout is reserved for the MCP transport).
- ✅ Full unit-test suite covering every tool and the HTTP client.
---
Tools
| Tool | Signature | Description | | --- | --- | --- | | search_contacts | (query: str) | Search contacts by name, email or company. | | get_contact | (contact_id: int) | Fetch a contact's full details. | | list_deals | (contact_id: int \| None) | List deals, optionally for one contact. | | get_deal | (deal_id: int) | Fetch a deal's full details. | | update_deal_stage | (deal_id: int, stage: str) | Move a deal to a new stage. | | create_task | (title: str, due_date: str, contact_id: int \| None) | Create a task. | | create_note | (contact_id: int, note: str) | Attach a note to a contact. | | get_recent_activities | (contact_id: int) | Recent activities for a contact. |
Every tool returns a JSON object. On success the payload contains "ok": true plus the requested data; on failure it contains "error": true with a type and message (and status_code for API errors).
---
Project structure
salesmate-mcp/
├── server.py # FastMCP entrypoint
├── salesmate/
│ ├── __init__.py
│ ├── config.py # env loading + validation
│ ├── client.py # async HTTPX client (retries, errors)
│ ├── models.py # Pydantic response models
│ └── exceptions.py # exception hierarchy
├── tools/
│ ├── __init__.py # registration + error mapping
│ ├── contacts.py
│ ├── deals.py
│ ├── tasks.py
│ ├── notes.py
│ └── activities.py
├── tests/ # pytest suite (tools + client + config)
├── .env.example
├── pyproject.toml
├── README.md
└── claude_desktop_config_example.json
---
Installation
1. Prerequisites
- Python 3.12+
- A Salesmate account with an API Session Key
(Setup → Integrations → API & Webhooks). Salesmate shows three keys — Access Key, Secret Key and Session Key — and the v4 API used here authenticates with the Session Key.
2. Get the code
cd salesmate-mcp
3. Create and activate a virtual environment
macOS / Linux:
python3.12 -m venv .venv
source .venv/bin/activate
Windows (PowerShell):
py -3.12 -m venv .venv
.\.venv\Scripts\Activate.ps1
4. Install dependencies
# runtime only
pip install -e .
# runtime + dev/test tools
pip install -e ".[dev]"
Prefer not to install the project as a package? You can instead run:
pip install mcp httpx pydantic python-dotenv
5. Configure environment variables
Copy the example file and fill in your credentials:
macOS / Linux:
cp .env.example .env
Windows (PowerShell):
Copy-Item .env.example .env
Then edit .env:
SALESMATE_API_KEY=your-salesmate-access-token
SALESMATE_BASE_URL=https://yourcompany.salesmate.io
All other variables are optional — see .env.example for the full list.
6. Run the server
python server.py
The server communicates over stdio. When launched manually it will simply wait for an MCP client to connect; logs are printed to stderr. Use the Claude Desktop integration below for normal use.
---
Claude Desktop integration
- Locate your Claude Desktop config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- Add the Salesmate server (see
claude_desktop_config_example.json):
{
"mcpServers": {
"salesmate": {
"command": "python",
"args": ["C:\\absolute\\path\\to\\salesmate-mcp\\server.py"],
"env": {
"SALESMATE_API_KEY": "your-salesmate-access-token",
"SALESMATE_BASE_URL": "https://yourcompany.salesmate.io"
}
}
}
}
Notes:
- Use the absolute path to
server.py. - If you use a virtual environment, point
commandat that env's Python
(e.g. C:\\path\\to\\salesmate-mcp\\.venv\\Scripts\\python.exe on Windows or /path/to/salesmate-mcp/.venv/bin/python on macOS/Linux).
- Credentials can be supplied either via the
envblock above or via a
.env file next to server.py.
- Restart Claude Desktop. The Salesmate tools will appear in the tool picker.
---
Usage examples (in Claude)
- "Search Salesmate for contacts at Acme."
- "Show me deals for contact 1024."
- "Move deal 555 to the Negotiation stage."
- "Create a task to follow up with contact 1024 due 2026-07-01."
- "Add a note to contact 1024: spoke with procurement, decision by Q3."
- "What are the recent activities for contact 1024?"
---
Configuration reference
| Variable | Required | Default | Description | | --- | --- | --- | --- | | SALESMATE_API_KEY | ✅ | — | Salesmate Session Key (not the Access/Secret key). | | SALESMATE_BASE_URL | ✅ | — | Workspace base URL (https://...). | | SALESMATE_AUTH_HEADER | | accessToken | Auth header name. | | SALESMATE_LINKNAME | | derived from base_url | Value for the required x-linkname header. | | SALESMATE_TIMEOUT | | 30 | Per-request timeout (seconds). | | SALESMATE_MAX_RETRIES | | 3 | Retry attempts for transient errors. | | SALESMATE_BACKOFF_FACTOR | | 0.5 | Base backoff delay (seconds). | | SALESMATE_LOG_LEVEL | | INFO | Logging verbosity. |
---
Running the tests
pip install -e ".[dev]"
pytest
The suite uses pytest-asyncio and an in-memory httpx.MockTransport, so it runs fully offline and never touches the real Salesmate API.
---
Adapting to your Salesmate API version
Salesmate exposes several API versions and the exact endpoint paths and search payloads can differ between workspaces. All endpoint paths are centralised in salesmate/client.py in the ENDPOINTS dictionary, and the request bodies for search operations are small and self-contained — adjust them there if your workspace expects a different shape. The auth header name can be changed without code edits via SALESMATE_AUTH_HEADER.
---
License
MIT












