simpro-claude-connector
README.md
# Simpro → Claude Connector
An MCP server that lets Claude read and act on a [Simpro](https://www.simprogroup.com/)
instance. Ask Claude about your jobs, customers and quotes in plain language and
it queries Simpro directly — no exports, no copy-paste.
```
You: Which Harborview jobs are still open, and what's holding up the board upgrade?
Claude: [calls search_customers, then list_jobs, then get_job]
Two open for Harborview Property Group:
#20841 Annual fixed wire testing In Progress £4,820.00 due 4 Sep
#20871 Distribution board upgrade Pending £6,390.00 due 25 Sep
The board upgrade is waiting on parts — purchasing noted a three week
lead time on 26 August, with the board due the week of 16 September.
```
**Writes are off by default.** Out of the box Claude can read Simpro and nothing
else. The two tools that change data — adding a note and moving a job's stage —
are only advertised when you explicitly enable them. An assistant that can read
your job list is useful; one that can quietly change it is a liability.
**It runs before you have a token.** Demo mode serves realistic built-in data, so
you can install it, open Claude and see exactly how it behaves before handing
over API credentials.
---
## Tools
| Tool | What Claude uses it for |
| --- | --- |
| `list_jobs` | "What's open for this customer", "what's due next week", "what's awaiting parts" |
| `get_job` | Full record for one job, including its note history |
| `search_customers` | Resolve a customer name to an id before the other calls |
| `get_customer` | Contact details and address for one customer |
| `list_quotes` | Pipeline questions: outstanding, approved, expiring |
| `add_job_note` * | Append a note to a job's history |
| `set_job_stage` * | Move a job to a different stage |
\* Only offered when `SIMPRO_ALLOW_WRITES=true`.
## Install
Requires Python 3.10 or newer.
```bash
git clone https://github.com/memethzmli-ctrl/simpro-claude-connector.git
cd simpro-claude-connector
pip install -e .
```
## Try it without a Simpro account
```bash
simpro-connector demo
```
This runs a scripted set of tool calls against the bundled sample data and prints
exactly what Claude receives:
```
simpro-claude-connector 1.0.0 - demo mode (built-in sample data, no network calls)
search_customers(search='harborview')
[
{
"id": 4101,
"name": "Harborview Property Group",
"type": "Company",
"email": "facilities@harborview.example",
"phone": "+44 1482 555 0117",
"address": "Unit 7, Prospect Business Park, Hull HU2 8PZ",
"archived": false
}
]
list_jobs(stage='Pending')
[
{
"id": 20860,
"name": "Emergency lighting installation - science block",
"customer_name": "St Chad's Academy Trust",
"stage": "Pending",
"status": "Awaiting customer approval",
"due_date": "2026-10-16",
"total_ex_tax": 18740.0,
"currency": "GBP"
},
...
]
```
Two other commands help when something looks wrong:
```bash
simpro-connector check # print the resolved config and make one real call
simpro-connector tools # print the tool schemas exactly as Claude sees them
```
## Connect it to Claude Desktop
Add this to `claude_desktop_config.json` and restart Claude Desktop. The full
annotated version is in [`examples/`](examples/claude_desktop_config.json).
```json
{
"mcpServers": {
"simpro": {
"command": "simpro-connector",
"args": ["serve"],
"env": { "SIMPRO_MODE": "demo" }
}
}
}
```
Start in demo mode. Once Claude is answering from the sample data, switch to
live.
## Going live
| Variable | Required | Meaning |
| --- | --- | --- |
| `SIMPRO_MODE` | – | `demo` (default) or `live` |
| `SIMPRO_BASE_URL` | live | Your instance's API root, e.g. `https://acme.simprosuite.com/api/v1.0` |
| `SIMPRO_ACCESS_TOKEN` | live | Token generated in Simpro under **Setup → Integrations → API** |
| `SIMPRO_COMPANY_ID` | – | Which company within the instance. Default `0` |
| `SIMPRO_ALLOW_WRITES` | – | `true` to enable `add_job_note` and `set_job_stage`. Default off |
| `SIMPRO_PAGE_SIZE` | – | Rows fetched per API page, 1–100. Default 25 |
| `SIMPRO_TIMEOUT_SECONDS` | – | Per-request timeout. Default 30 |
Then confirm the connection before touching Claude:
```bash
SIMPRO_MODE=live \
SIMPRO_BASE_URL=https://acme.simprosuite.com/api/v1.0 \
SIMPRO_ACCESS_TOKEN=... \
simpro-connector check
```
A bad token, an unreachable host or a timeout each produce a plain sentence
saying what to fix, not a stack trace.
## Design notes
**Configuration, not hard-coding.** Simpro is tenant-hosted: every customer has
their own host, company id and credentials. Nothing outside `config.py` knows a
URL, so pointing this at a different instance is environment variables, not a
code change.
**Tolerant field mapping.** Simpro payloads vary slightly between instance
versions, so `client.py` accepts several plausible keys per field and normalises
them into one stable shape. Adapting to a specific customer's Simpro is a change
in one small module rather than a rewrite, and the tool layer never sees a raw
payload.
**Two guards on writes, not one.** Write tools are hidden from Claude when
writes are disabled *and* the dispatcher refuses them if called anyway. Each
write is narrow and validated — there is no generic "update job" accepting
arbitrary fields.
**Errors are answers.** A failed call returns readable text rather than raising,
so Claude can tell the person what went wrong and what to do about it instead of
just failing.
**Demo mode is a real rehearsal.** Both backends implement the same interface, so
a tool that works against the sample data works against a live instance.
## Tests
```bash
pip install -e ".[dev]"
pytest
```
45 tests covering configuration validation, tool schemas, read-only enforcement,
filtering and search, pagination against a stubbed transport, every HTTP error
path, field normalisation — and four end-to-end tests that launch the real MCP
server as a subprocess and drive it with an MCP client, exactly as Claude
Desktop does.
## Adapting it
- `simpro_connector/tools.py` — add or reshape the tools Claude is offered
- `simpro_connector/client.py` — endpoint paths and field mapping for a specific instance
- `simpro_connector/fixtures.py` — sample data for demo mode
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues