{"_id":"@aiwerk/mcp-server-smallinvoice","_rev":"2-bd5671b3ead663e21e4fe6ea13974cc6","name":"@aiwerk/mcp-server-smallinvoice","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@aiwerk/mcp-server-smallinvoice","version":"0.1.0","keywords":["mcp","mcp-server","smallinvoice","aiwerk","swiss","invoicing","accounting"],"author":{"name":"AIWerk","email":"kontakt@aiwerk.ch"},"license":"MIT","_id":"@aiwerk/mcp-server-smallinvoice@0.1.0","maintainers":[{"name":"agbergsmann","email":"kontakt@aiwerk.ch"}],"homepage":"https://aiwerkmcp.com","bugs":{"url":"https://github.com/AIWerk/mcp-server-smallinvoice/issues"},"bin":{"mcp-server-smallinvoice":"dist/src/server.js"},"dist":{"shasum":"89a8c29f49139d004d09a373feb7d50cdab98d73","tarball":"https://registry.npmjs.org/@aiwerk/mcp-server-smallinvoice/-/mcp-server-smallinvoice-0.1.0.tgz","fileCount":10,"integrity":"sha512-gi5XQHIVhnyoh6mwudJewxP8ypaesnpMTrNEqx1NcfO0F1W0h2R/zohYhJ/ZvMIc0SC+ljAUloSTLJv9Wkt9WA==","signatures":[{"sig":"MEQCICovGGrfhb7qka9dOlMzJHWx9mb21iO8EBSk87ziCxQrAiBETancesJhLffvy42qEfF5ozD3a8cxowPunHBWE3nE9A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":176472},"main":"dist/src/server.js","type":"module","engines":{"node":">=18.0.0"},"gitHead":"3dbaa0f9ae6fb9b8a7d19595d28ca618443a1aee","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc -p tsconfig.json","start":"node dist/src/server.js","predev":"npm run gen-version","pretest":"npm run gen-version","prebuild":"npm run gen-version","gen-version":"node scripts/gen-version.mjs","prepublishOnly":"bash scripts/prepublish-safety.sh && npm run build && npm test"},"_npmUser":{"name":"agbergsmann","email":"kontakt@aiwerk.ch"},"repository":{"url":"git+https://github.com/AIWerk/mcp-server-smallinvoice.git","type":"git"},"_npmVersion":"9.2.0","description":"smallinvoice.ch API MCP server — Swiss SME invoicing and accounting (146 tools, OAuth2 BYOC)","directories":{},"_nodeVersion":"18.19.1","dependencies":{"zod":"^3.25.76","@modelcontextprotocol/sdk":"^1.19.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.1","typescript":"^5.5.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-server-smallinvoice_0.1.0_1778330060723_0.7891814042986955","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@aiwerk/mcp-server-smallinvoice","version":"0.2.0","description":"smallinvoice.ch API MCP server — Swiss SME invoicing and accounting (146 tools, OAuth2 BYOC)","type":"module","main":"dist/src/server.js","bin":{"mcp-server-smallinvoice":"dist/src/server.js"},"scripts":{"gen-version":"node scripts/gen-version.mjs","prebuild":"npm run gen-version","build":"tsc -p tsconfig.json","start":"node dist/src/server.js","predev":"npm run gen-version","dev":"tsc --watch","pretest":"npm run gen-version && bash -c 'pkill -9 -f \"[n]ode.*vitest\" 2>/dev/null; pkill -9 -f \"[e]sbuild.*--service\" 2>/dev/null; true'","test":"vitest run","posttest":"bash -c 'pkill -9 -f \"[n]ode.*vitest\" 2>/dev/null; pkill -9 -f \"[e]sbuild.*--service\" 2>/dev/null; true'","prepublishOnly":"bash scripts/prepublish-safety.sh && npm run build && npm test"},"engines":{"node":">=18.0.0"},"keywords":["mcp","mcp-server","smallinvoice","aiwerk","swiss","invoicing","accounting"],"author":{"name":"AIWerk","email":"kontakt@aiwerk.ch"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/AIWerk/mcp-server-smallinvoice.git"},"homepage":"https://aiwerkmcp.com","bugs":{"url":"https://github.com/AIWerk/mcp-server-smallinvoice/issues"},"publishConfig":{"access":"public"},"dependencies":{"@modelcontextprotocol/sdk":"^1.19.1","zod":"^3.25.76"},"devDependencies":{"@types/node":"^22.0.0","typescript":"^5.5.0","vitest":"^3.2.1"},"gitHead":"fecd68d8022025266faca1d1f8454c0529ae47f7","_id":"@aiwerk/mcp-server-smallinvoice@0.2.0","_nodeVersion":"18.19.1","_npmVersion":"9.2.0","dist":{"integrity":"sha512-KMhYwRgRv3w+iRqxk+XwlJ+RKdAyOyUafYhAvRMmvgdCBmIEjFFM8XwaOD17BshtC7cC+fGlm+VNjzVWBY3tuw==","shasum":"11a6ae709656f9a41c798892c5d06dab42717ddd","tarball":"https://registry.npmjs.org/@aiwerk/mcp-server-smallinvoice/-/mcp-server-smallinvoice-0.2.0.tgz","fileCount":10,"unpackedSize":177889,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCrYnQ9V0YVPgjbDFI94gbYx6NgBPc/PiiiF+1k7Ez4ggIhAMc7XplKS0vGtFDQeqoeRsM3NmtYZNEto/r2eFAjFIyS"}]},"_npmUser":{"name":"agbergsmann","email":"kontakt@aiwerk.ch"},"directories":{},"maintainers":[{"name":"agbergsmann","email":"kontakt@aiwerk.ch"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-server-smallinvoice_0.2.0_1781439714014_0.09911178127786013"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-09T12:34:20.597Z","modified":"2026-06-14T12:21:54.330Z","0.1.0":"2026-05-09T12:34:20.852Z","0.2.0":"2026-06-14T12:21:54.156Z"},"bugs":{"url":"https://github.com/AIWerk/mcp-server-smallinvoice/issues"},"author":{"name":"AIWerk","email":"kontakt@aiwerk.ch"},"license":"MIT","homepage":"https://aiwerkmcp.com","keywords":["mcp","mcp-server","smallinvoice","aiwerk","swiss","invoicing","accounting"],"repository":{"type":"git","url":"git+https://github.com/AIWerk/mcp-server-smallinvoice.git"},"description":"smallinvoice.ch API MCP server — Swiss SME invoicing and accounting (146 tools, OAuth2 BYOC)","maintainers":[{"name":"agbergsmann","email":"kontakt@aiwerk.ch"}],"readme":"# @aiwerk/mcp-server-smallinvoice\n\nMCP server for [smallinvoice.ch](https://smallinvoice.ch) — Swiss SME invoicing and accounting (146 tools, OAuth2 BYOC).\n\n## Install\n\n```bash\nnpx -y @aiwerk/mcp-server-smallinvoice\n```\n\n## Configure\n\n| Variable | Required | Description |\n|---|---|---|\n| `SMALLINVOICE_CLIENT_ID` | ✅ | OAuth2 client ID — smallinvoice Home → Users → API V2 → New client |\n| `SMALLINVOICE_CLIENT_SECRET` | ✅ | OAuth2 client secret |\n| `SMALLINVOICE_REFRESH_TOKEN` | ✅ | Initial refresh token from the OAuth bootstrap flow (rotates per call) |\n| `SMALLINVOICE_ACCESS_TOKEN` | optional | Pre-loaded access token; lazily refreshed if absent or expired |\n| `SMALLINVOICE_TOKEN_FILE` | optional | Path to persist rotating tokens (default: `~/.aiwerk/smallinvoice-tokens.json`) |\n| `SMALLINVOICE_DRY_RUN` | optional | Set to `1` to prevent write operations from reaching the API |\n| `SMALLINVOICE_NO_SNAPSHOT` | optional | Set to `1` to disable pre-write entity snapshots |\n| `SMALLINVOICE_SNAPSHOT_DIR` | optional | Directory for pre-write snapshots (default: `~/.aiwerk/smallinvoice-snapshots`) |\n| `SMALLINVOICE_SNAPSHOT_FAIL_OPEN` | optional | Set to `1` to log a warning instead of blocking when a snapshot fails |\n| `SMALLINVOICE_API_TIMEOUT_MS` | optional | Request timeout in ms (default: `30000`) |\n\n### MCP client config example (Claude Desktop / OpenClaw)\n\n```json\n{\n  \"mcpServers\": {\n    \"smallinvoice\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@aiwerk/mcp-server-smallinvoice\"],\n      \"env\": {\n        \"SMALLINVOICE_CLIENT_ID\": \"your-client-id\",\n        \"SMALLINVOICE_CLIENT_SECRET\": \"your-client-secret\",\n        \"SMALLINVOICE_REFRESH_TOKEN\": \"your-initial-refresh-token\"\n      }\n    }\n  }\n}\n```\n\n## Auth setup\n\n> **Requires smallinvoice Starter plan or higher (CHF 15/mo). The free tier blocks API access.**\n\n1. In your smallinvoice account: **Home → Users → API V2 → New client**\n   - Grant type: **Authorization Code**\n   - Redirect URI: `http://127.0.0.1:8765/callback` (must be registered in the client config)\n   - Copy `client_id` and `client_secret`\n\n2. Run the authorization URL in your browser:\n   ```\n   https://api.smallinvoice.com/v2/auth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&scope=profile+contact+contact_reminder+letter+configuration+catalog+invoice+offer+delivery_note+order_confirmation+project+cost_unit+working_hours+activity+effort\n   ```\n   Log in and approve. You receive a `code`.\n\n3. Exchange the code for tokens:\n   ```bash\n   curl -X POST https://api.smallinvoice.com/v2/auth/access-tokens \\\n     -H 'Content-Type: application/json' \\\n     -d '{\"grant_type\":\"authorization_code\",\"client_id\":\"...\",\"client_secret\":\"...\",\"code\":\"...\",\"redirect_uri\":\"http://127.0.0.1:8765/callback\"}'\n   ```\n   The response contains `access_token` and `refresh_token`.\n\n4. Set `SMALLINVOICE_REFRESH_TOKEN` to the returned `refresh_token`. The server persists new tokens automatically after each refresh.\n\n> **Token file is source of truth after first refresh.** Once the server performs its first token rotation, the persisted `SMALLINVOICE_TOKEN_FILE` takes priority over `SMALLINVOICE_REFRESH_TOKEN` env var. If you rotate the refresh token manually, update or delete the token file.\n\n## Tools\n\n**146 tools total** across 6 groups.\n\n| Group | Count | Representative tools |\n|---|---|---|\n| **auth** | 2 | `get_owner`, `get_profile` |\n| **contacts** | 42 | `list_contacts`, `get_contact`, `create_contact`, `update_contact`, `delete_contacts`; sub-resources: accounts, addresses, people, groups, letters, reminders |\n| **catalog** | 22 | `list_products`, `create_product`, `list_services`, `create_service`; categories (product & service), units |\n| **receivables** | 47 | `list_invoices`, `create_invoice`, `download_invoice_pdf`, `change_invoice_status`, `send_invoice_by_email`, `record_invoice_payment`; offers, order-confirmations, delivery-notes, payments, ISRs |\n| **reporting** | 23 | `list_projects`, `list_working_hours`; efforts, activities, cost-units |\n| **configuration** | 10 | `list_bank_accounts`, `create_bank_account`; `list_exchange_rates`, `create_exchange_rate` |\n\nAll `delete_*` tools are marked `destructiveHint: true`. All `list_*` / `get_*` / `download_*` tools are `readOnlyHint: true`.\n\n## Important notes\n\n**Refresh token rotation.** Smallinvoice revokes the old refresh token the moment it issues a new one. The server uses atomic write (content fsync + atomic rename + dir fsync best-effort) to persist the new token before using it. If the process crashes after the API rotation but before persist completes, the OAuth chain is broken — re-run the bootstrap flow from step 2 above.\n\n**Cross-process refresh safety.** Multiple MCP server instances sharing the same token file are protected by an O_EXCL file lock. A double-check after acquiring the lock avoids redundant refreshes when another process already rotated the token.\n\n**`SMALLINVOICE_DRY_RUN=1`.** All write tools (`create_*`, `update_*`, `delete_*`, `change_*`, `send_*`, `record_*`) return a stub response without contacting smallinvoice:\n```json\n{ \"_dry_run\": true, \"_would_call\": { \"method\": \"POST\", \"path\": \"/receivables/invoices\", \"body\": { ... } } }\n```\nUse this when testing against a production account.\n\n**Pre-write snapshots.** Before each mutating operation, the current entity state is fetched and saved to `~/.aiwerk/smallinvoice-snapshots/`. The tool result includes a `_snapshot` field with the file path.\n\n- **PUT / PATCH** — snapshots the entity being updated\n- **DELETE** — snapshots each entity being deleted (batch-aware: all IDs fetched in parallel, saved as one JSON file with partial-failure tolerance)\n- **send_by_email / send_by_post** — snapshots the parent document before sending ⚠️ IRREVERSIBLE: sends real email/post — pre-state snapshotted under `~/.aiwerk/smallinvoice-snapshots/`\n- **Sub-resource POST** (e.g. `record_invoice_payment`, `create_contact_account`) — snapshots the parent entity before modifying it\n\nDisable snapshots with `SMALLINVOICE_NO_SNAPSHOT=1`. By default, a snapshot failure **blocks the write** (fail-closed). Set `SMALLINVOICE_SNAPSHOT_FAIL_OPEN=1` to downgrade to a warning and continue.\n\n**Rate limit.** The actual limit is **360 requests/minute** (not 1000 as stated in the public documentation). The server logs a warning to stderr when `X-Rate-Limit-Remaining` drops below 30.\n\n**Date formats.** Use `YYYY-MM-DD` for date fields and `YYYY-MM-DD HH:MM:SS` for timestamp fields (no timezone — Europe/Zurich assumed).\n\n## License\n\nMIT — [AIWerk](https://aiwerkmcp.com)\n","readmeFilename":"README.md"}