Skip to main content
Glama
binyaminboukaya

smart-npv-mcp

README.md
# smart-npv-mcp

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)
[![Node >= 18](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)
[![MCP](https://img.shields.io/badge/MCP-server-8A2BE2.svg)](https://modelcontextprotocol.io)

> **An [MCP](https://modelcontextprotocol.io) server that turns the [Smart NPV](https://www.snpv.co.il) mortgage-advisor CRM into tools your AI agent can call.**
>
> שרת MCP שמחבר סוכני AI (Claude, Cursor, Hermes ועוד) ישירות למערכת Smart NPV, כדי לקרוא ולעדכן תיקי לקוחות, סטטוסים, מסמכים וסימולציות בשפה טבעית.

Built at [BeAi](https://github.com/binyaminboukaya). Works with any Smart NPV account.

> ⚠️ **Community project.** Not affiliated with or endorsed by Smart NPV. Built against their public API documentation.

---

## Table of contents
- [What is this?](#what-is-this)
- [Why would I want it?](#why-would-i-want-it)
- [How it works](#how-it-works)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Connecting to an MCP client](#connecting-to-an-mcp-client)
- [The authentication model](#the-authentication-model)
- [Tool reference (32 tools)](#tool-reference-32-tools)
- [Worked example: a pipeline guardian](#worked-example-a-pipeline-guardian)
- [Example calls and responses](#example-calls-and-responses)
- [Error handling](#error-handling)
- [Troubleshooting](#troubleshooting)
- [Development](#development)
- [Project status and roadmap](#project-status-and-roadmap)
- [Contributing](#contributing)
- [License](#license)

---

## What is this?

Three pieces come together here:

- **[Smart NPV](https://www.snpv.co.il)** is a CRM built for Israeli mortgage advisors: it manages client files, mortgage calculations, document checklists, and workflow stages. It exposes a REST API (behind a paid tier).
- **[MCP (Model Context Protocol)](https://modelcontextprotocol.io)** is an open standard that lets AI agents call external tools through a uniform interface. Instead of hand-writing HTTP requests, an agent gets a clean, typed set of tools it can reason about and call.
- **This server** is the bridge. It wraps every documented Smart NPV endpoint as an MCP tool, so any MCP-capable agent can operate the CRM: list clients, read a client's status and documents, add a status, upload a file, record a payment, run simulations, and more.

In one sentence: **it lets an AI agent operate Smart NPV for you, safely and deterministically, instead of clicking through the UI.**

## Why would I want it?

A mortgage advisor working solo juggles dozens of active files, each moving through an 8-stage workflow that can take months. Files fall through the cracks. An AI agent connected through this server can, for example:

- **Watch the pipeline.** Every morning, list all active clients, read each one's status and predicted stage date, and flag the ones that have stalled: "3 files are past their stage deadline. Client X has had no movement for 12 days."
- **Chase missing documents.** Read a client's document list, compare against the required checklist, and draft a reminder for exactly what is missing.
- **Keep the CRM tidy.** Record a status change or file an uploaded document back into the right client, automatically.
- **Answer questions.** "How many leads came in this month?" "What is the status of the Cohen file?"

The agent decides *what* to do; this server gives it the *hands* to do it in Smart NPV.

## How it works

```mermaid
flowchart LR
    A["AI agent<br/>(Claude / Cursor / Hermes)"] -- "MCP (stdio)" --> B["smart-npv-mcp<br/>server"]
    B -- "HTTPS + api_key" --> C["Smart NPV API<br/>www.snpv.co.il"]
    C -- "JSON" --> B
    B -- "tool result" --> A
```

The agent speaks MCP over stdio. This server translates each tool call into the correct Smart NPV HTTP request (injecting your `api_key`), and returns the JSON response back to the agent.

## Requirements

- **Node.js 18+** (uses the built-in `fetch`, `FormData`, and `Blob`).
- **A Smart NPV account with API access.** The API sits behind Smart NPV's **extended (paid) subscription**. You will need an **API key** from them. Some tools also require the **Premium** tier (marked below).

## Installation

### Option A: via npx (recommended, once published to npm)
No install needed; your MCP client runs it on demand:
```bash
npx -y smart-npv-mcp
```

### Option B: from source
```bash
git clone https://github.com/binyaminboukaya/smart-npv-mcp.git
cd smart-npv-mcp
npm install
npm run build
```

## Configuration

The server reads four environment variables:

| Variable | Required | Default | Notes |
|----------|----------|---------|-------|
| `SMARTNPV_API_KEY` | for API calls | (none) | Your key from the extended subscription. The server still starts and lists its tools without it, but every call will error until it is set. |
| `SMARTNPV_BASE_URL` | no | `https://www.snpv.co.il` | The API host. Must be `https://` (plain `http://` is rejected, except for localhost) — the api_key travels with every request. **Note:** `api.snpv.co.il` only serves the docs; the API itself is on `www.snpv.co.il`. |
| `SMARTNPV_TIMEOUT_MS` | no | `60000` | Per-request timeout in milliseconds. |
| `SMARTNPV_UPLOAD_DIR` | no, **recommended** | (unrestricted) | Confines the three upload tools to files inside this directory. Without it, any `.pdf`/`.png`/`.jpg`/`.jpeg` readable by the process can be uploaded to Smart NPV's servers by the calling agent — set it if the agent runs with any autonomy. |

For local development, copy the template:
```bash
cp .env.example .env
# then edit .env and paste your key
```

> How to get a key: contact Smart NPV support / your account manager and ask to enable API access on the extended subscription. They issue the `api_key`.

## Connecting to an MCP client

Add an entry to your client's MCP config. The examples below assume the key is in `SMARTNPV_API_KEY`.

<details>
<summary><b>Claude Desktop</b> (<code>claude_desktop_config.json</code>)</summary>

```json
{
  "mcpServers": {
    "smart-npv": {
      "command": "npx",
      "args": ["-y", "smart-npv-mcp"],
      "env": { "SMARTNPV_API_KEY": "your-key-here" }
    }
  }
}
```
</details>

<details>
<summary><b>Cursor</b> (<code>.cursor/mcp.json</code>)</summary>

```json
{
  "mcpServers": {
    "smart-npv": {
      "command": "npx",
      "args": ["-y", "smart-npv-mcp"],
      "env": { "SMARTNPV_API_KEY": "your-key-here" }
    }
  }
}
```
</details>

<details>
<summary><b>From source</b> (any client, absolute path to the build)</summary>

```json
{
  "mcpServers": {
    "smart-npv": {
      "command": "node",
      "args": ["/absolute/path/to/smart-npv-mcp/dist/index.js"],
      "env": {
        "SMARTNPV_BASE_URL": "https://www.snpv.co.il",
        "SMARTNPV_API_KEY": "your-key-here"
      }
    }
  }
}
```
</details>

After adding the config, restart the client. You should see the `smart-npv` tools appear.

## The authentication model

Smart NPV passes the `api_key` differently depending on the request type. This server handles it for you automatically; **you never pass `api_key` as a tool argument.**

| Request type | Where `api_key` goes |
|--------------|----------------------|
| `GET` tools | query parameter |
| `POST` tools | field in the JSON body |
| Upload tools | multipart form field |

## Tool reference (32 tools)

Legend: **Premium** = requires the Premium tier of the subscription. Required arguments are in **bold**.

> **Working with client data?** See [docs/client-fields.md](docs/client-fields.md) for the full
> client field schema — including the `_1` / `_2` two-borrower model that every personal field uses.

<details open>
<summary><b>Clients</b> (8 tools)</summary>

| Tool | Arguments | What it does |
|------|-----------|--------------|
| `list_clients` | `limit`, `offset`, `range_type`, `from` (DD/MM/YYYY), `until`, `lead` (bool), `reference` | List clients or leads, paged and date-filtered. |
| `get_client` | `type` (`uuid`\|`phone`), `uuid`, `phone` | Fetch one client by uuid or phone. |
| `get_client_documentations` | **`uuid`** | List the documents attached to a client. |
| `create_client` | **`params`** | Create a client (fields inside `params`). |
| `update_client` | **`uuid`**, `params` | Update a client. |
| `delete_client` | **`uuid`** | Delete a client (irreversible). |
| `add_documentation` | **`uuid`**, **`params`** | Add a documentation record. |
| `upload_document` | **`uuid`**, **`file_name`**, **`file_path`** | Upload a PDF/PNG/JPG file to a client. |

</details>

<details>
<summary><b>Status</b> (3 tools)</summary>

| Tool | Arguments | What it does |
|------|-----------|--------------|
| `get_client_status` | **`uuid`** | Current status/stage of a client. Core for pipeline monitoring. |
| `get_status_list` | (none) | The status/stage definitions in the account. |
| `add_status` | **`params`** | Add/set a status on a client. |

</details>

<details>
<summary><b>Simulation</b> (5 tools)</summary>

| Tool | Arguments | What it does |
|------|-----------|--------------|
| `get_client_simulations` | **`uuid`** | List a client's mortgage simulations. |
| `get_simulation` | **`uuid`**, `simulation_uuid` | Fetch a specific simulation. |
| `add_simulation` | **`uuid`**, **`simulation_name`**, `note`, `current_mix_toolbar`, `current_mix`, `mixes` | Add a mortgage mix. |
| `delete_simulation` | **`uuid`** | Delete a simulation. |
| `calc_simulation` **(Premium)** | **`request`** | Run the reform/recalculation engine. |

</details>

<details>
<summary><b>Payments</b> (3 tools)</summary>

| Tool | Arguments | What it does |
|------|-----------|--------------|
| `get_payments` | **`uuid`** | List a client's payments. |
| `add_payment` | **`uuid`**, `params` | Record a payment (e.g. a retainer). |
| `update_payment` | **`payment_uuid`**, `params` | Update a payment. |

</details>

<details>
<summary><b>Contacts</b> (4 tools)</summary>

| Tool | Arguments | What it does |
|------|-----------|--------------|
| `get_contact_groups` | (none) | List contact groups. |
| `get_contacts` | (none) | List contacts (bankers, appraisers, etc.). |
| `add_contact` | **`params`** | Add a contact. |
| `add_contact_group` | **`params`** | Add a contact group. |

</details>

<details>
<summary><b>Products, Networks, Services, Data</b> (9 tools)</summary>

| Tool | Arguments | What it does |
|------|-----------|--------------|
| `create_product` | **`params`** | Create a product. |
| `get_sources` **(Premium)** | (none) | List lead sources / networks. |
| `add_source` **(Premium)** | **`params`** | Add a lead source. |
| `update_source` **(Premium)** | **`params`** | Update a lead source. |
| `balance_report_parsing` **(Premium)** | **`bank_id`**, **`file_path`** | Upload a bank balance-report PDF for parsing. |
| `get_banks` **(Premium)** | (none) | Banks supported by the balance-report service. |
| `check_bank_availability` **(Premium)** | **`bank_id`** | Is a bank supported by the service. |
| `approval_in_principle_scanning` **(Premium)** | **`bank_id`**, **`file_path`** | Upload an approval-in-principle PDF for scanning. |
| `get_cities` | (none) | Reference list of cities. |

</details>

## Worked example: a pipeline guardian

The most valuable pattern. Goal: every morning, surface files that have stalled.

**What you say to the agent:**
> "Go over all my active clients and tell me which ones have not moved recently or are past their stage deadline."

**What the agent does with these tools:**
1. `list_clients` with `lead: false` to get active files.
2. For each client, `get_client_status` to read the current stage and its predicted date.
3. Compares dates, and reports the stalled ones back to you in plain language.

**What you get back:**
> "3 files need attention: Levi (stage 2, 11 days no movement), Cohen (past the appraisal deadline by 4 days), Mizrahi (documents requested 8 days ago, none received)."

Then, still in the same conversation:
> "Draft a WhatsApp reminder to Mizrahi for the missing documents."

The agent uses `get_client_documentations` to see what is missing and drafts the message. You approve and send. No file falls through the cracks.

## Example calls and responses

Tool arguments are plain JSON. A few illustrative calls (exact response shape depends on your Smart NPV account, since this is built against the documented API):

**List the 25 most recent active clients**
```json
// tool: list_clients
{ "limit": 25, "offset": 0, "lead": false }
```

**Read one client's status**
```json
// tool: get_client_status
{ "uuid": "12345678-1234-1234-1234-123456789109" }
```

**Add a status to a client**
```json
// tool: add_status
{ "params": { "uuid": "12345678-...", "status_id": 4, "note": "Documents received" } }
```

**Upload a document**
```json
// tool: upload_document
{
  "uuid": "12345678-...",
  "file_name": "tabu_nispach.pdf",
  "file_path": "/Users/me/Downloads/tabu_nispach.pdf"
}
```

**Record a retainer payment**
```json
// tool: add_payment
{ "uuid": "12345678-...", "params": { "amount": 2000, "type": "retainer" } }
```

A successful call returns the API's JSON as text. On failure the result is marked as an error (see below).

> Note on `params`: several write endpoints accept a free-form `params` object whose exact inner fields are defined by Smart NPV and are not fully published. Pass the fields the CRM expects. Once you have a live key, inspect a real record (e.g. `get_client`) to learn the field names.

## Error handling

Every tool catches failures and returns an MCP error result rather than crashing the server:

```
Error: Smart NPV /api/v2/clients/get_client_status -> HTTP 401: {"message":"invalid api_key"}
```

Common cases:
- **Key missing:** `SMARTNPV_API_KEY is not set.`
- **Auth failure:** HTTP 401/403 (bad or unauthorized key, or a Premium tool on a non-Premium plan).
- **Bad arguments:** the API returns a 4xx with a message; it is surfaced verbatim.

## Troubleshooting

| Symptom | Likely cause / fix |
|---------|--------------------|
| Every call returns "api_key is not set" | `SMARTNPV_API_KEY` is not in the server's env. Put it in your MCP client config's `env`. |
| 401 / 403 on every call | Wrong key, or API access not enabled on your subscription. |
| 404 on all calls | Wrong base URL. Ensure it is `https://www.snpv.co.il` (not `api.snpv.co.il`). |
| A specific tool 403s | It is a **Premium** tool and your plan is not Premium. |
| Tools do not appear in the client | Restart the client after editing the config; check the command/path is correct. |
| Upload fails | Ensure `file_path` is an absolute path the server process can read. |

## Development

```bash
npm install
npm run dev        # run from source with tsx (no build)
npm run build      # compile TypeScript to dist/
npm run typecheck  # type-check only
npm start          # run the built server
```

Project layout:
```
src/
  index.ts       MCP server: registers every tool, wires stdio transport
  endpoints.ts   the 32 endpoint definitions (path, method, zod input schema)
  client.ts      HTTP client: GET (query), POST (json body), multipart upload
```

Adding a tool is one entry in `endpoints.ts`. The server registers it automatically.

Quick smoke test (lists tools over the MCP protocol):
```bash
printf '%s\n' \
 '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}' \
 '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
 '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
 | SMARTNPV_API_KEY=test node dist/index.js
```

## Project status and roadmap

- ✅ All 32 documented endpoints wrapped as tools.
- ✅ Type-checks, builds, and passes an MCP `tools/list` smoke test.
- ⏳ **Not yet live-tested** against a real account (needs an API key). Until then, treat response shapes as indicative.
- 🔜 Tighten the free-form `params` schemas once real field names are confirmed against a live key.
- 🔜 Optional: publish to npm so `npx smart-npv-mcp` works with no clone.

## Contributing

Issues and pull requests welcome. Good first contributions: confirming real field names for the `params` payloads, adding response examples from a live account, or improving tool descriptions.

## License

[MIT](./LICENSE) © 2026 Binyamin Boukaya (BeAi).

Smart NPV is a trademark of its respective owner. This is an independent, unofficial integration.

TDQS

B3.1/5.0

Scored across 32 tools

Disambiguation4/5

Most tools target distinct resources and actions (clients, payments, simulations, contacts). A few document-related tools (upload_document, add_documentation, balance_report_parsing, approval_in_principle_scanning) could cause confusion, but descriptions clarify their specific purposes.

Naming Consistency3/5

The set uses a mix of get_/list_/check_ and noun-based names (balance_report_parsing), plus add_/update_/create_/delete_. While readable, there is no single consistent verb_noun pattern (e.g., list_clients vs get_banks, check_bank_availability vs get_banks).

Tool Count2/5

32 tools is heavy, exceeding the typical well-scoped range for an MCP server. The server covers many subdomains, but the count feels bloated and detracts from coherence.

Completeness3/5

Core client lifecycle is covered (CRUD, status, payments, simulations), but there are gaps: no delete_source, no contact update/delete, no payment delete, and some endpoints are unverified. These gaps might force workarounds but do not break the main workflows.

Maintenance

ActivitySlowing
ResponsivenessNo issues