Skip to main content
Glama
stornoro

Storno CLI

Official
by stornoro
README.md
# Storno CLI — MCP Server

A **Model Context Protocol (MCP) server** that exposes the entire [Storno.ro](https://storno.ro) e-invoicing API as AI-callable tools. Enables Claude Code, Cursor, Windsurf, and any MCP-compatible AI assistant to manage invoices, clients, companies, ANAF e-Factura, and more.

## Features

- **237 tools** covering all Storno.ro API endpoints
- Full invoice lifecycle: create, issue, submit to ANAF, email, download PDF/XML
- Proforma invoices, recurring invoices, delivery notes, credit notes
- Client & product catalog, payment tracking, VAT rates
- ANAF e-Factura integration (sync, token management, message retrieval)
- Multi-company support with company switching
- Automatic JWT token refresh
- Webhooks, API keys, team member management
- Exchange rates (BNR), reports, exports

## Quick Start

### Hosted Server (recommended)

Storno hosts a public MCP server at **https://mcp.storno.ro/mcp** with OAuth authentication — no API keys or tokens to manage.

Visit **[mcp.storno.ro](https://mcp.storno.ro)** for setup instructions and a one-click "Add to Claude" button.

**Claude (claude.ai):**

1. Copy the URL: `https://mcp.storno.ro/mcp`
2. Go to [claude.ai/settings/connectors](https://claude.ai/settings/connectors)
3. Click "Add" and paste the URL
4. Authorize via OAuth

**Claude Code:**

```bash
claude mcp add storno --transport http https://mcp.storno.ro/mcp
```

**Cursor / Windsurf:**

```json
{
  "mcpServers": {
    "storno": {
      "url": "https://mcp.storno.ro/mcp"
    }
  }
}
```

**Claude Desktop:**

```json
{
  "mcpServers": {
    "storno": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.storno.ro/mcp"]
    }
  }
}
```

### Self-hosted / Token-based Setup

If you prefer to use a JWT token directly (e.g. for self-hosted Storno instances):

#### 1. Install

```bash
npm install -g storno-cli
```

Or use directly with `npx` — no install needed.

#### 2. Configure for Claude Code

Add to your project's `.claude/settings.json` or global `~/.claude/settings.json`:

```json
{
  "mcpServers": {
    "storno": {
      "command": "npx",
      "args": ["-y", "storno-cli"],
      "env": {
        "STORNO_TOKEN": "your-jwt-token",
        "STORNO_COMPANY_ID": "your-company-uuid"
      }
    }
  }
}
```

#### 3. Configure for Cursor

Add to `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "storno": {
      "command": "npx",
      "args": ["-y", "storno-cli"],
      "env": {
        "STORNO_TOKEN": "your-jwt-token",
        "STORNO_COMPANY_ID": "your-company-uuid"
      }
    }
  }
}
```

#### 4. Configure for Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "storno": {
      "command": "npx",
      "args": ["-y", "storno-cli"],
      "env": {
        "STORNO_TOKEN": "your-jwt-token",
        "STORNO_COMPANY_ID": "your-company-uuid"
      }
    }
  }
}
```

## Environment Variables

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `STORNO_BASE_URL` | No | `https://api.storno.ro` | API base URL |
| `STORNO_TOKEN` | No* | — | JWT access token |
| `STORNO_REFRESH_TOKEN` | No | — | JWT refresh token (for auto-renewal) |
| `STORNO_COMPANY_ID` | No* | — | Default company UUID |
| `STORNO_EMAIL` | No | — | Email for auto-login (if no token) |
| `STORNO_PASSWORD` | No | — | Password for auto-login (if no token) |
| `STORNO_HTTP_PORT` | No | — | If set, starts Streamable HTTP transport on this port |
| `STORNO_HTTP_HOST` | No | `127.0.0.1` | HTTP bind address (used with `STORNO_HTTP_PORT`) |

\* You can authenticate at runtime using the `auth_login` tool instead.

## Authentication

Three ways to authenticate:

### Option A: Pre-configured token (recommended for production)

Set `STORNO_TOKEN` in your MCP server environment config.

### Option B: Auto-login on startup

Set `STORNO_EMAIL` and `STORNO_PASSWORD`. The server will automatically log in when it starts and keep the token refreshed.

### Option C: Interactive login via AI

Ask the AI: *"Log me in to Storno with email user@example.com and password mypassword"*

The AI will call the `auth_login` tool, which stores the token in memory for the session.

## Multi-Company Support

All company-scoped tools require a company context. Three ways to provide it:

1. **Environment variable**: Set `STORNO_COMPANY_ID` in your MCP config
2. **Select command**: Ask the AI to call `companies_select` with a company UUID
3. **Per-request override**: Every company-scoped tool accepts an optional `companyId` parameter

Example AI conversation:
```
You: List my companies
AI: [calls companies_list] You have 2 companies:
  - ABC SRL (uuid: 550e8400...)
  - XYZ SRL (uuid: 661f9500...)

You: Switch to XYZ SRL
AI: [calls companies_select with uuid] Done, now using XYZ SRL

You: Show me recent invoices
AI: [calls invoices_list — automatically uses XYZ SRL context]
```

## Tool Reference

See [TOOLS.md](./TOOLS.md) for the complete reference of all 237 tools with descriptions and parameters.

### Tool Categories

| Category | Tools | Description |
|----------|-------|-------------|
| `auth_*` | 7 | Login, register, refresh tokens, profile management |
| `companies_*` | 8 | Company CRUD + context switching + ANAF settings |
| `invoices_*` | 32 | Full invoice lifecycle (create → issue → submit → email → PDF/XML) |
| `clients_*` | 10 | Client management (synced from e-Factura) |
| `products_*` | 2 | Product catalog |
| `payments_*` | 3 | Payment recording and tracking |
| `proforma_invoices_*` | 12 | Proforma lifecycle (create → send → accept/reject → convert) |
| `recurring_invoices_*` | 10 | Recurring invoice schedules |
| `delivery_notes_*` | 18 | Delivery note lifecycle + status management |
| `receipts_*` | 13 | Fiscal receipts (bonuri fiscale) + conversion to invoices |
| `vat_rates_*` | 4 | VAT rate CRUD |
| `bank_accounts_*` | 4 | Bank account CRUD |
| `document_series_*` | 5 | Invoice number series management |
| `suppliers_*` | 8 | Supplier management |
| `exchange_rates_*` | 2 | BNR exchange rates + currency conversion |
| `email_templates_*` | 4 | Email template CRUD |
| `anaf_*` | 8 | ANAF token management + e-Factura sync + validation |
| `efactura_messages_*` | 2 | e-Factura message retrieval |
| `einvoice_*` | 6 | Multi-country e-invoicing (EU-wide) |
| `dashboard_*` | 1 | Dashboard statistics |
| `defaults_*` | 1 | Invoice defaults (currencies, units, VAT rates) |
| `members_*` | 3 | Organization team members |
| `invitations_*` | 4 | Team invitations |
| `notifications_*` | 6 | Notification management + preferences |
| `webhooks_*` | 10 | Webhook CRUD + testing + delivery logs |
| `api_keys_*` | 5 | API token management |
| `reports_*` | 7 | VAT reports + financial reports |
| `exports_*` | 1 | Export file downloads |
| `import_*` | 8 | CSV/XLSX/XML import for clients, products, invoices |
| `borderou_*` | 8 | Bank reconciliation (borderou) |
| `backup_*` | 6 | Backup creation + restore |
| `admin_*` | 3 | System administration (requires admin role) |
| `licensing_*` | 4 | License key management |
| `pdf_template_*` | 4 | PDF invoice template customization |
| `storage_config_*` | 5 | File storage configuration |
| `accounting_export_*` | 3 | Export to accounting formats |
| `company_registry_*` | 2 | Company registry lookups |
| `cpv_codes_*` | 1 | CPV code lookup |
| `nc_codes_*` | 1 | NC code lookup |
| `system_*` | 2 | System health + version info |

## Common AI Workflows

### Create and send an invoice

```
You: Create an invoice for client Acme SRL, 10 hours web development at 100 RON/hour, due in 30 days

AI: [calls clients_list to find Acme SRL]
    [calls invoices_create with clientId, lines, dates]
    [calls invoices_issue to mark as issued]
    [calls invoices_email to send to client]
    Invoice FAC-2024-042 created, issued, and emailed to contact@acme.ro
```

### Check ANAF sync status

```
You: What's the ANAF sync status for my company?

AI: [calls anaf_status]
    Last sync: 2 hours ago, 156 invoices synced, token valid until March 16
```

### Generate a monthly report

```
You: Show me all invoices from January 2024

AI: [calls invoices_list with from=2024-01-01, to=2024-01-31]
    Found 23 invoices, total: 45,230 RON
    - 18 issued, 3 paid, 2 overdue
```

## HTTP Transport

By default, storno-cli uses **stdio transport** for local MCP clients. Set `STORNO_HTTP_PORT` to enable **Streamable HTTP transport** for remote access.

```bash
# Start HTTP server on port 3000
STORNO_TOKEN=your-token STORNO_COMPANY_ID=your-company-uuid \
  STORNO_HTTP_PORT=3000 node dist/index.js

# Bind to all interfaces (for production behind a reverse proxy)
STORNO_HTTP_PORT=3000 STORNO_HTTP_HOST=0.0.0.0 node dist/index.js
```

The server exposes a single `/mcp` endpoint supporting POST, GET, and DELETE per the MCP Streamable HTTP spec. Each client connection creates an isolated stateful session.

**Initialize a session:**

```bash
curl -X POST http://127.0.0.1:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
# Response includes mcp-session-id header
```

**Call a tool:**

```bash
curl -X POST http://127.0.0.1:3000/mcp \
  -H "Content-Type: application/json" \
  -H "mcp-session-id: <session-id>" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"system_health","arguments":{}}}'
```

## Development

```bash
npm run dev      # Watch mode (recompile on changes)
npm run build    # Production build
npm run start    # Start MCP server (stdio)
```

## Architecture

```
storno-cli/
├── src/
│   ├── index.ts          # Entry point — dispatches to stdio or HTTP transport
│   ├── server.ts         # McpServer factory (creates server + registers all tools)
│   ├── http-server.ts    # Streamable HTTP transport with session management
│   ├── config.ts         # Environment configuration
│   ├── client.ts         # HTTP client with JWT auth + auto-refresh
│   ├── tools/            # 40 tool domain files (237 tools total)
│   │   ├── auth.ts
│   │   ├── invoices.ts   # Largest: 32 tools for full invoice lifecycle
│   │   ├── companies.ts
│   │   └── ...           # 37 more domain files
│   └── utils/
│       ├── errors.ts     # AI-readable error formatting
│       └── pagination.ts # Pagination helpers
├── dist/                 # Compiled JavaScript output
├── package.json
├── tsconfig.json
├── README.md             # This file
└── TOOLS.md              # Complete tool reference
```

## Requirements

- Node.js >= 20.0.0
- npm

## License

[Elastic License 2.0 (ELv2)](LICENSE)

## Tool annotations

All tools carry explicit MCP annotations (`title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`), so a client can tell reads from writes and writes from deletes before calling anything. See the *Tool annotations* section of [TOOLS.md](TOOLS.md); `npm run check:annotations -- --table` prints the table.

TDQS

B3.4/5.0

Scored across 374 tools

Disambiguation3/5

Most tools are scoped to a clear resource and action, and the descriptions are detailed enough to separate similar operations. However, the sheer number produces several near-overlapping flows (companies_select vs companies_set_active, declarations_submit vs declarations_file_via_agent vs agent_submit_declaration_pdf, retired declarations_sync vs spv_sync_prepare) that an agent can easily misselect.

Naming Consistency3/5

Names mostly follow a resource_action snake_case pattern, but prefixes mix singular and plural forms (company_registry_search vs clients_list, product_categories_list), and some tools are noun phrases rather than verb-led (dashboard_stats, balance_analysis, fiscal_calendar). The surface remains readable but is not fully predictable at 374 tools.

Tool Count1/5

374 tools is an extreme mismatch for a single MCP server, far beyond the 50+ threshold for severe overload. Even for a large ERP, this many tools overwhelms selection and violates the principle that each tool should clearly earn its place in a focused set.

Completeness5/5

The surface covers full lifecycle operations for invoices, proformas, delivery notes, receipts, payments, clients, suppliers, bank/cash registers, VAT, declarations, SPV, e-Factura, e-Transport, imports/exports, backups, admin, webhooks, and licensing. Almost every domain an agent would need is represented, with only intentional constraints such as sync-only product creation.

Maintenance

ActivityActive
ResponsivenessNo issues