lexware-php-mcp
# lexware-php-mcp
[English](README.md) | [Deutsch](README.de.md)
[](https://github.com/Stefan39/lexware-php-mcp/actions/workflows/ci.yml)
[](LICENSE)

> **Unofficial.** Not affiliated with Haufe Group. Lexware and lexoffice are trademarks of Haufe Group.
lexware-php-mcp is an unofficial, read-only [Model Context Protocol](https://modelcontextprotocol.io) server for
[Lexware Office](https://www.lexware.de/) (formerly lexoffice), written in PHP on top of the
official [PHP MCP SDK](https://github.com/modelcontextprotocol/php-sdk).
Ask Claude things like *"Which invoices are overdue?"* and get answers straight from your account.
**No PHP needed:** for Claude Desktop on macOS and Windows there is a one-click extension, see
[Quick start](#quick-start-claude-desktop-no-php-needed).
## Why a PHP server?
The existing Lexware MCP servers are written in TypeScript or Python. This one is the PHP-native option, and
that is the point: it is not a claim that PHP is technically better, but that PHP shops should not need a second
runtime to give an AI assistant access to their bookkeeping.
- **One runtime you already run, or none at all.** PHP 8.4 and Composer, nothing else. No Node.js or Python
toolchain, no `npx` downloading code at startup. Without PHP, use the standalone download, which has PHP
built in.
- **Small enough to audit.** The server has three runtime dependencies (`mcp/sdk`, `symfony/http-client`,
`symfony/clock`) and a handful of classes. Anyone handing an AI access to accounting data can read all of it
in an afternoon. It is checked with PHPStan level 8 including strict rules.
- **Built for the German Mittelstand stack.** Many agencies, freelancers and in-house IT teams around Lexware
work in PHP (Symfony, Laravel, WordPress, Shopware). Tools are plain classes, so they can later move into a
Symfony application via `symfony/mcp-bundle` (see [ADR 0001](docs/adr/0001-architecture.md)).
- **Lexware pitfalls handled, not left to you.** Invoices written in Lexware and booked sales vouchers are two
different voucher types; the server queries both. Lexware's 2 requests per second limit is throttled, and
Lexware's error messages are passed through so a failure is explainable.
## Example questions
- *Which invoices are overdue, and by how many days?*
- *Show open invoices for customer Müller, with totals per currency.*
## Status
v0.3.0, early but usable. See the [changelog](CHANGELOG.md). Currently available tool:
| Tool | What it does |
|---|---|
| `open_items` | Unpaid sales invoices (open and overdue), oldest due date first, with days overdue and totals per currency. Optional filters: `overdueOnly`, `contact`. Amounts are gross. |
Planned: voucher search, voucher detail with net amounts, contact search, revenue per period.
See [ADR 0001](docs/adr/0001-architecture.md).
## Safety
- **Read-only.** The server only sends `GET` requests; there are no tools that create or change data.
- The API key is read from the environment only and never appears in output or error messages.
- Bank details (IBAN, BIC, account data) are stripped from every response before it reaches the model.
- Requests are throttled to the Lexware limit of 2 per second, with retry and backoff on 429/5xx.
- Data returned by a tool is sent to the model provider of your MCP client (e.g. Anthropic for
Claude Desktop). Only use it with accounts whose data you may share with that provider.
Found a security problem? Please report it privately, see [SECURITY.md](SECURITY.md).
Use of the Lexware API is governed by the
[Public API Lizenz- und Nutzungsbedingungen](https://agb.lexware.de/lexware-office/public-api-lizenz--und-nutzungsbedingungen).
## Quick start: Claude Desktop, no PHP needed
You need a Lexware Office public API key: <https://app.lexware.de/addons/public-api>.
Nothing else has to be installed; the download contains everything, PHP included.
1. Download the extension for your system from the [latest release](https://github.com/Stefan39/lexware-php-mcp/releases/latest):
- macOS (Apple silicon and Intel): [`lexware-php-mcp-macos.mcpb`](https://github.com/Stefan39/lexware-php-mcp/releases/latest/download/lexware-php-mcp-macos.mcpb)
- Windows: [`lexware-php-mcp-windows.mcpb`](https://github.com/Stefan39/lexware-php-mcp/releases/latest/download/lexware-php-mcp-windows.mcpb)
2. Double-click the file. Claude Desktop opens and shows the extension. If double-clicking does not work,
open *Settings > Extensions > Advanced settings > Install Extension…* in Claude Desktop and pick the file.
3. Click *Install* and paste your API key when asked. Claude Desktop stores it in its secure storage;
it does not end up in a configuration file.
Claude Desktop shows a warning before installing because the extension is not signed. Signing costs
money for a certificate, which this free project does without; the code is open for review on GitHub.
Confirm with *Install*.
4. Make sure the extension is switched on, then ask: *"Which invoices are overdue?"*
To update, download the new `.mcpb` and install it the same way.
The Windows extension is built and tested automatically (start-up and a TLS connection to the Lexware API),
but the maintainer has not tried it on a Windows PC. Reports are welcome as an
[issue](https://github.com/Stefan39/lexware-php-mcp/issues).
## Standalone binary: Claude Code and other MCP clients
Every release also contains the server as a single executable file, again with PHP built in:
| System | File |
|---|---|
| macOS, Apple silicon | `lexware-php-mcp-macos-arm64` |
| macOS, Intel | `lexware-php-mcp-macos-x86_64` |
| Linux, x86_64 | `lexware-php-mcp-linux-x86_64` |
| Linux, ARM64 | `lexware-php-mcp-linux-arm64` |
| Windows, x86_64 | `lexware-php-mcp-windows-x86_64.exe` |
`SHA256SUMS` in the release lets you verify the download (`shasum -a 256 -c SHA256SUMS --ignore-missing`).
On macOS and Linux, make the file executable. The binaries are not signed, so on macOS also remove the
download quarantine, otherwise Gatekeeper refuses to start the file:
```bash
chmod +x lexware-php-mcp-macos-arm64
xattr -d com.apple.quarantine lexware-php-mcp-macos-arm64 # macOS only
```
Register it with Claude Code:
```bash
claude mcp add --env LEXWARE_API_KEY=your-api-key lexware-php-mcp -- /absolute/path/to/lexware-php-mcp-macos-arm64
```
By default the entry applies to the current project only. Add `--scope user` to make it available
everywhere. Check with `claude mcp list`, or run `/mcp` inside a session. The key is stored in plain text in
Claude Code's configuration; keep it private.
Linux needs the usual CA certificates for HTTPS (package `ca-certificates`, installed on desktop
systems anyway).
## Installation from source (PHP developers)
If you already work with PHP, you can run the server from source instead.
Requirements:
- PHP 8.4 or newer (CLI) with `ext-json`
- Composer
```bash
git clone --branch v0.3.0 https://github.com/Stefan39/lexware-php-mcp.git
cd lexware-php-mcp
composer install --no-dev
```
To update later: `git fetch --tags && git checkout <new-tag> && composer install --no-dev`.
A `lexware-php-mcp.phar` is attached to every release as well; it runs with `php lexware-php-mcp.phar`.
### Claude Desktop with a manual configuration
The extension above is the easier way. If you prefer to configure the server yourself, add **one entry**
under `mcpServers` in `claude_desktop_config.json`:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
The file usually contains other settings already. Do not paste a second `{ ... }` block at the end:
add the `"lexware-php-mcp"` entry inside the existing `"mcpServers"` object, or create
`"mcpServers"` as a new top-level key if it is missing. Check the result with
`python3 -m json.tool claude_desktop_config.json` before restarting Claude Desktop.
#### macOS: API key from the Keychain
Store the key once; the command prompts for it, so it never ends up in your shell history:
```bash
security add-generic-password -s lexware-php-mcp -a lexware -w
```
Entry for `mcpServers` (adjust both paths; `which php` shows yours). With a standalone binary, replace
`/opt/homebrew/bin/php /absolute/path/to/lexware-php-mcp/bin/lexware-php-mcp` by the path of the binary:
```json
"lexware-php-mcp": {
"command": "/bin/sh",
"args": ["-c", "LEXWARE_API_KEY=$(security find-generic-password -s lexware-php-mcp -w) exec /opt/homebrew/bin/php /absolute/path/to/lexware-php-mcp/bin/lexware-php-mcp"]
}
```
#### Other systems: API key in the config
```json
"lexware-php-mcp": {
"command": "php",
"args": ["/absolute/path/to/lexware-php-mcp/bin/lexware-php-mcp"],
"env": {
"LEXWARE_API_KEY": "your-api-key"
}
}
```
The key is then stored in plain text in that file; keep it private.
Quit Claude Desktop completely, start it again and ask: *"Which invoices are overdue?"*
If the server does not show up, check the log
(macOS: `~/Library/Logs/Claude/mcp-server-lexware-php-mcp.log`).
### Claude Code from source
```bash
claude mcp add --env LEXWARE_API_KEY=your-api-key lexware-php-mcp -- php /absolute/path/to/lexware-php-mcp/bin/lexware-php-mcp
```
## Configuration
| Variable | Required | Default |
|---|---|---|
| `LEXWARE_API_KEY` | yes | none |
| `LEXWARE_API_BASE_URL` | no | `https://api.lexware.io` |
## Development
```bash
composer install
composer check # php-cs-fixer (dry run), PHPStan level 8, PHPUnit
make cpd # duplication check (needs Node/npx)
```
Debug the server interactively with the MCP Inspector. The Inspector starts the server with a
minimal environment, so pass the key with `-e`; a variable set in your shell does not reach it:
```bash
npx @modelcontextprotocol/inspector -e LEXWARE_API_KEY=your-api-key php bin/lexware-php-mcp
```
Tests never touch the real API; they use Symfony's `MockHttpClient` and `MockClock`.
### Standalone builds
The workflow `.github/workflows/release.yml` builds the PHAR ([Box](https://github.com/box-project/box),
config `box.json`), the static binaries ([static-php-cli](https://github.com/crazywhalecc/static-php-cli):
PHP plus the PHAR in one file) and the Claude Desktop extensions (`build-tools/package-mcpb.sh`, manifest
in `build-tools/mcpb/`). It runs on pull requests that touch the build, and on a version tag it attaches
everything to a draft release. Check any build with `build-tools/smoke-test.sh <command>`; with
`SMOKE_TEST_TLS=1` it also sends one request with an invalid key to the real API and expects HTTP 401.
Keep `version` in `build-tools/mcpb/manifest.json` in line with `ServerFactory::VERSION` (a test checks it).
## License
MIT, see [LICENSE](LICENSE).
TDQS
Scored across 1 tool
There is only one tool, so there is nothing for an agent to confuse it with. Its purpose (listing unpaid sales invoices) is stated clearly and narrowly.
The single tool uses readable snake_case with a clear noun-phrase style. There is no set of names to check for pattern consistency, so it cannot reach a perfect 5.
One tool is far too thin for a Lexware Office integration, which would typically require invoices, vouchers, contacts, and payment operations. It reads like a partial slice of a much larger surface.
Only open receivables are exposed; there is no listing/detail for vouchers, contacts, invoices, or payables despite the description pointing to voucher detail for net amounts. Agents hitting those needs have no path forward.