Skip to main content
Glama
yacrum-mcp

yacrum-mcp

README.md
# yacrum-mcp

An [MCP](https://modelcontextprotocol.io) server for the **Yacrum** CRM. It lets Claude Desktop, Claude Code
and other MCP clients search, create and update your CRM records, log activity, read the pipeline and the
forecast, and summarise a deal. Your own AI does the thinking; this server only fetches from Yacrum.

It talks to Yacrum through its public REST API, with **your own API key**. A key acts as the member it was
made for, with that member's role: the server can do exactly what that person could do in the app, and
nothing more. A *read* key cannot change anything.

## Setup

1. In Yacrum, an Admin opens **Administration → API Keys**, makes a key for you, and copies it. The key is
   shown only once. Choose **Read and write** if you want the AI to create and update records.
2. Add the server to your MCP client.

### Claude Desktop

Edit `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "yacrum": {
      "command": "npx",
      "args": ["-y", "yacrum-mcp"],
      "env": {
        "YACRUM_API_KEY": "yk_your_key_here",
        "YACRUM_URL": "https://yacrum--yacrum.us-central1.hosted.app"
      }
    }
  }
}
```

### Claude Code

```bash
claude mcp add yacrum --env YACRUM_API_KEY=yk_your_key_here -- npx -y yacrum-mcp
```

| Variable | |
|---|---|
| `YACRUM_API_KEY` | Required. A key from Administration → API Keys (`yk_…`). |
| `YACRUM_URL` | Your Yacrum address. Defaults to the Yacrum staging site. |

## Tools

| Tool | What it does |
|---|---|
| `whoami` | The workspace, the member the key acts as, its scope, and this month's API usage |
| `search` | Companies, contacts, opportunities and open leads by name |
| `list_companies`, `get_company`, `create_company`, `list_company_types` | Companies |
| `list_contacts`, `create_contact` | Contacts |
| `list_opportunities`, `create_opportunity`, `update_opportunity`, `move_opportunity_stage` | Deals |
| `set_sales_health` | A deal's Sales Health (G on track, Y at risk, R off track) and the note saying why, always together |
| `log_activity` | A note on a company, contact, deal or lead: a call, a meeting, a decision |
| `create_action_item`, `list_action_items`, `update_action_item` | Tasks, optionally on a record, with a due date; complete or reopen one |
| `list_quotes`, `get_quote` | Quotes, with their lines, totals, taxes and status (read only) |
| `get_signals` | What is worth doing now, and why: quiet and expiring quotes, stale and slipping deals, lost and paused deals to revisit, dormant customers, renewals and referrals |
| `snooze_signal`, `unsnooze_signal` | Hide a signal from yourself until a day, or bring it back. Works with a read key |
| `get_outreach_settings` | The address to BCC on a draft so the sent mail is logged, and the workspace's style guide |
| `pipeline_changes` | What changed since last week's pipeline snapshot: new, advanced, slipped, won, lost and the totals then and now |
| `get_pipeline`, `pipeline_summary` | The stages, and open deals by stage (totals kept per currency) |
| `forecast` | Bookings, billings and cash by month (Admin, Management and Sales) |
| `qualification_score` | A deal's score: answers, scores, percent of its template's maximum, and tier |
| `list_scoring_templates` | The workspace's scoring templates: questions, choices, weights, tiers, maximums and stage gates |
| `score_opportunity` | Score a deal, or change its answers or template (switching template deletes the old answers) |
| `stage_readiness` | The stage gates ahead of a deal, met or not, and the next stage when all of its gates are met |
| `deal_context` | Everything about one deal in one read, to summarise it or draft to it, with the CASL consent facts for its contacts |
| `list_profiles`, `get_workspace_setup` | The seven Profiles, and how far the workspace is set up (Admin) |
| `apply_profile` | Apply a Profile. `dryRun` is required: `true` answers with the diff and changes nothing (Admin) |
| `set_workspace_features` | Show or hide Quotes, Forecast, Deal team and CASL. Hiding authorizes nothing (Admin) |
| `get_import_templates` | The spreadsheet templates, and what each CRM's export looks like (Admin) |
| `preview_import` | Upload an export or spreadsheet from this computer, save the answers, and see what the import would do. Nothing reaches the workspace's records (Admin) |
| `import_records`, `get_import_status`, `undo_import` | Run an import (call again while `more` is true), see where it has got, and undo it, all or none (Admin) |

There is also a **`summarize_deal`** prompt that reads a deal's context and asks for a summary and next steps.

Every tool says what it does, so your AI client can ask before a write:

| Kind | Tools | Annotations |
|---|---|---|
| Reads | `whoami`, `search`, every `list_…` and `get_…`, `pipeline_summary`, `forecast`, `qualification_score`, `deal_context`, `pipeline_changes`, `stage_readiness` | read only |
| Additions | `create_company`, `create_contact`, `create_opportunity`, `create_action_item`, `log_activity`, `preview_import` | not destructive |
| Updates | `update_opportunity`, `set_sales_health`, `update_action_item`, `snooze_signal`, `unsnooze_signal`, `set_workspace_features` | not destructive, idempotent |
| A stage move | `move_opportunity_stage` | **destructive**: a lost or paused stage records a reason and changes the forecast. A stage gate can refuse it (409 `stage_gate`); an Admin or Management member may override it with `overrideReason` |
| Scoring | `score_opportunity` | **destructive**, idempotent: switching a scored deal's template deletes its answers |
| Setup and imports | `apply_profile`, `import_records`, `undo_import` | **destructive**: each changes the workspace's stages or many records at once. Show the diff or preview and get a yes first |

**Files for an import are read from your computer.** `preview_import` takes full paths and reads only regular `.csv`
and `.xlsx` files, never through a symlink, at most 12 files, 10 MB each and 25 MB together. Anything else is refused
before a byte is read or sent.

Yacrum never sends email. To draft outreach, pair this server with your own Gmail or Microsoft 365
connector: draft in your mailbox with the BCC from `get_outreach_settings`, and log it with `log_activity`.

## The Claude plugin

[`plugin/`](./plugin) packages this server with five sales routines: morning signals, re-engaging a deal,
an account pulse before a meeting, the weekly pipeline review and qualifying an opportunity. Outreach is drafted
in your own mailbox with your workspace's logging address in BCC. Nothing is sent.

It also has two for an Admin: `/yacrum:setup` interviews you, shows a Profile's diff and applies it once you agree,
and `/yacrum:import` brings in a Pipedrive or HubSpot export or a spreadsheet. Both need an Admin's write key and a
local server, so they work in Claude Code and Claude Desktop, and not on claude.ai on the web.

```bash
claude plugin marketplace add david-loadman/yacrum-mcp
claude plugin install yacrum@yacrum
```

Setup, including the Gmail and Microsoft 365 connectors and email logging, is in
[`plugin/SETUP.md`](./plugin/SETUP.md).

## Limits

Every call counts against your workspace plan's monthly API calls. One key may make 120 requests a minute.
An import uses about one call per 200 records.
When a limit is reached, Yacrum's refusal says so, and the server passes it on to the AI as a tool error.

## Releasing

npm releases are **staged** and need a maintainer's approval with 2FA. A version goes live in three steps:

1. **Bump the version** in `package.json` and `VERSION` in `src/index.ts`, and merge.
2. **Publish a GitHub release** tagged `v<version>`. The *Stage on npm* workflow checks that the tag matches,
   builds, tests, and runs `npm stage publish`. It has no token: it authenticates through npm's trusted
   publishing, and npm attaches provenance automatically.
3. **Approve it with 2FA**, either on the package's page at npmjs.com, or with:

   ```bash
   npm stage list
   npm stage approve <stage-id>
   ```

   `npm stage reject <stage-id>` discards a staged version instead.

The trusted publisher on npmjs.com (user `david-loadman`, repository `yacrum-mcp`, workflow `publish.yml`)
does **not** allow `npm publish`. Leave it that way: a compromised workflow can then stage a version but never
ship one.

## Development

```bash
npm install
npm test        # against a fake Yacrum; nothing leaves the machine
npm run build
YACRUM_API_KEY=yk_… node dist/index.js
```

The Yacrum API is described at `<YACRUM_URL>/api/v1/openapi.json`.

⚠️ **`npx yacrum-mcp` fails inside a clone of this repository**, including when Claude Code is started in it:
npm resolves `yacrum-mcp` to the local package instead of the published one, and finds no command to run. Start
Claude Code, or `npx`, from another directory, or point the MCP config at `node <clone>/dist/index.js`.

## Licence

MIT