Skip to main content
Glama
horatiuvlad

oblio-mcp-server

by horatiuvlad
README.md
# oblio-mcp-server

[![CI](https://github.com/horatiuvlad/oblio-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/horatiuvlad/oblio-mcp-server/actions/workflows/ci.yml)
[![npm version](https://img.shields.io/npm/v/oblio-mcp-server.svg)](https://www.npmjs.com/package/oblio-mcp-server)
[![node](https://img.shields.io/node/v/oblio-mcp-server.svg)](https://www.npmjs.com/package/oblio-mcp-server)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

A [Model Context Protocol](https://modelcontextprotocol.io) server for [Oblio.eu](https://www.oblio.eu) — issue invoices, proformas and delivery notices, collect payments, submit e-Factura to Romania's SPV, and query your account's reference data through natural language, from Claude Desktop or any MCP client.

> Unofficial community project. Not affiliated with or endorsed by Oblio Software; it builds on their public API and official Node SDK.

## Features

- **Built on Oblio's official SDK** ([`@obliosoftware/oblioapi`](https://www.npmjs.com/package/@obliosoftware/oblioapi)) — no hand-rolled HTTP layer for the core API
- **Full document lifecycle** — create, fetch, list, cancel, restore and delete invoices, proformas and delivery notices (avize)
- **Payments** — record collections (incasari) against invoices, with all Oblio payment methods
- **e-Factura / SPV** — submit invoices to ANAF's SPV and poll their processing status
- **Nomenclatures** — discover valid series names, VAT rates, saved clients, products, languages and management units before issuing documents
- **Webhooks** — subscribe external endpoints to Oblio events (stock changes, document drafts/updates/cancellations, recorded payments)
- **Multi-company** — switch the active company CIF at runtime via `set_cif`
- **Client-side idempotency guard** — pass an `idempotencyKey` to `create_document` and retries won't double-issue a document
- **Zod-validated inputs** — every tool input is schema-checked with descriptive field docs
- **MCP tool annotations** — read-only / destructive / idempotent hints on every tool, so clients can gate confirmations appropriately

## Prerequisites

- Node.js >= 20
- An Oblio.eu account with API access

## Getting API credentials

In Oblio, go to **Setari > Date Cont**. You need:

- the **account email** (acts as the OAuth client id)
- the **API secret** (acts as the OAuth client secret)
- your **company CIF** (e.g. `RO12345678`) — optional at startup; it can also be set at runtime with the `set_cif` tool

## Installation

### Claude Desktop / MCP clients — via npx

Add to your MCP client configuration (e.g. `claude_desktop_config.json`). Straight from GitHub (npx builds it on first run):

```json
{
  "mcpServers": {
    "oblio": {
      "command": "npx",
      "args": ["-y", "github:horatiuvlad/oblio-mcp-server"],
      "env": {
        "OBLIO_API_EMAIL": "you@example.com",
        "OBLIO_API_SECRET": "your-api-secret",
        "OBLIO_CIF": "RO12345678"
      }
    }
  }
}
```

Once the package is published to npm, `"args": ["-y", "oblio-mcp-server"]` will work as well.

### From a local build

```bash
git clone https://github.com/horatiuvlad/oblio-mcp-server.git
cd oblio-mcp-server
npm install
npm run build
```

```json
{
  "mcpServers": {
    "oblio": {
      "command": "node",
      "args": ["/path/to/oblio-mcp-server/dist/index.js"],
      "env": {
        "OBLIO_API_EMAIL": "you@example.com",
        "OBLIO_API_SECRET": "your-api-secret",
        "OBLIO_CIF": "RO12345678"
      }
    }
  }
}
```

### Environment variables

| Variable | Required | Description |
| --- | --- | --- |
| `OBLIO_API_EMAIL` | yes | Oblio account email (Setari > Date Cont) |
| `OBLIO_API_SECRET` | yes | Oblio API secret (Setari > Date Cont) |
| `OBLIO_CIF` | no | Default company CIF; can be changed at runtime with `set_cif` |
| `OBLIO_TOKEN_FILE` | no | Path where the OAuth access token is persisted so it survives restarts (defaults to in-memory only) |

## Tools

### Documents

| Tool | Description |
| --- | --- |
| `create_document` | Issue an invoice, proforma or delivery notice (aviz); supports an optional `idempotencyKey` to guard against double-issue on retries |
| `get_document` | Fetch a single document by series name and number, with totals, status and a link |
| `list_documents` | List documents with filters: series, number, client (cif/email/phone/code), issue-date range, draft/cancelled/collected flags, optional line items / payments / SPV status, sorting and pagination |
| `cancel_document` | Cancel (annul) a document; it stays in Oblio and can be restored later |
| `restore_document` | Restore a previously cancelled document to its active state |
| `delete_document` | Permanently delete a document (Oblio only allows deleting the last one in a series) |

### Payments

| Tool | Description |
| --- | --- |
| `collect_payment` | Record a payment (incasare) against an existing invoice; defaults to the full remaining amount when no value is given |

### Nomenclatures

| Tool | Description |
| --- | --- |
| `get_nomenclatures` | Fetch reference data: companies, saved clients, products, VAT rates, document series, languages, or management units (gestiuni) |

### e-Factura

| Tool | Description |
| --- | --- |
| `create_einvoice` | Submit an issued invoice to Romania's SPV (e-Factura / ANAF) |
| `get_einvoice` | Fetch the SPV status and archive for a submitted invoice (0 = processing, 1 = success, 2 = errors, -1 = not sent) |

### Webhooks

| Tool | Description |
| --- | --- |
| `create_webhook` | Subscribe an endpoint to an Oblio event: `stock`, `<Doc>/SaveDraft`, `<Doc>/Update`, `<Doc>/Cancel` (Doc = Invoice/Proforma/Notice/TaxReceipt) or `Collect/Inserted`. The endpoint must answer 200 and echo the base64 of the `X-Oblio-Request-Id` header |
| `list_webhooks` | List all webhook subscriptions with topic, endpoint and id |
| `delete_webhook` | Delete a webhook subscription by id |

### Company

| Tool | Description |
| --- | --- |
| `set_cif` | Set the active company CIF used for subsequent requests (switch between companies on one account) |
| `get_cif` | Return the company CIF currently in effect |

## Why another Oblio MCP?

- It sits on Oblio's **official SDK** rather than reimplementing the API surface
- It ships with a **test suite** and strict typechecking
- `create_document` has a **client-side idempotency guard**, so agent retries don't silently issue duplicate invoices
- **Full e-Factura / SPV coverage** — submit and track invoices with ANAF, not just issue them locally

## Development

```bash
npm run build      # compile to dist/
npm test           # run the test suite
npm run typecheck  # tsc --noEmit
```

### Keeping up with the Oblio API (docs drift)

Oblio publishes no machine-readable API spec — the HTML docs at
[oblio.eu/api](https://www.oblio.eu/api) are the de-facto contract that
`src/schemas.ts` hand-encodes. Three layers guard against silent drift:

1. **Docs snapshot** — `scripts/oblio-docs-snapshot.mjs` extracts the
   contract-bearing parts of the docs page (endpoints, parameter tables,
   response samples) into `docs/oblio-api.snapshot.md`. The
   [`oblio-docs-drift` workflow](.github/workflows/oblio-docs-drift.yml)
   re-fetches weekly and, on any change, opens a PR with the refreshed
   snapshot and the diff.
2. **Agent draft** — when the `ANTHROPIC_API_KEY` repo secret is configured,
   the same workflow runs Claude Code on the drift PR branch to translate the
   docs diff into real `src/schemas.ts` / tool changes (including
   `.describe()` text), verified with typecheck + tests and pushed as a
   commit on the PR. A human still reviews and merges; without the secret the
   PR is opened with a manual checklist instead.
3. **SDK tripwire** — [Renovate](renovate.json) flags releases of
   `@obliosoftware/oblioapi`, which usually accompany API changes.

```bash
node scripts/oblio-docs-snapshot.mjs --check    # exit 3 + diff on drift
node scripts/oblio-docs-snapshot.mjs --update   # refresh the snapshot
```

## License

[MIT](LICENSE)

TDQS

A4.2/5.0

Scored across 12 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: document lifecycle (create, get, list, cancel, restore, delete, collect payment), e-invoice (create, get status), company configuration (get/set CIF, get nomenclatures). No overlapping functionality that would confuse an agent.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in lowercase_snake_case (e.g., cancel_document, create_einvoice, list_documents). No mixing of conventions or confusing abbreviations.

Tool Count5/5

With 12 tools, the server is well-scoped for a document management system. Each tool covers a necessary operation without redundancy or excess. The count is appropriate for the domain.

Completeness4/5

The tool set covers the core lifecycle of fiscal documents: create, read, list, cancel, restore, delete, and payment collection, plus e-invoice integration. A minor gap is the lack of an update tool, but this is typical for fiscal documents that cannot be modified after issuance. Overall sufficiently complete.

Maintenance

ActivitySlowing
ResponsivenessNo issues