Skip to content

Releases: benethos-hub/lexware-office-mcp

0.2.3 — error messages reach the model again

Choose a tag to compare

@BeneODev BeneODev released this 02 Sep 11:26
fcc8881

A patch, and a correction. No tool, parameter or answer changed, and nothing is enabled that was not enabled before.

Fixed

Error messages reach the model again on MCP SDK 2.1. The SDK sorts a failing tool call by the type of what was raised: its own ToolError is a failure the server anticipated and its message is handed to the model, while anything else counts as a crash and the model is told only Error executing tool <name>. This server's error classes derived from plain Exception, so on 2.1 every message it sends — no API key configured, key rejected, record not found, rate limit, tool not enabled for this installation — was replaced by that one sentence.

This affected installations of 0.2.2 and earlier, not only the repository. The declared range is mcp>=2.0.0,<3, so anyone installing after the SDK's 2.1.0 release resolved to it and lost the messages. Measured over real stdio against 2.1.1, before and after.

Changed

  • MCP SDK raised to 2.1.1, from 2.0.0. The tool list a client receives is byte-for-byte unchanged, and so is its size. A crash inside a tool no longer puts the exception's own text on the wire.
  • Dependencies refreshed: cryptography 50.0.1, platformdirs 4.11.7, pydantic 2.13.5, and click, coverage, ruff and typer to their current releases.
  • The package description names the transports.

Upgrading

Nothing to do. Pin an exact version if you depend on one:

uvx benethos-lexware-office-mcp==0.2.3
docker pull ghcr.io/benethos-hub/lexware-office-mcp:0.2.3

The :0.2 minor line and latest move to this release as well.

Full notes in CHANGELOG.md.

0.2.2 — one file, and two things the API changed its mind about

Choose a tag to compare

@BeneODev BeneODev released this 23 Aug 17:38
36f44a5

A patch release with one correction, one parameter removed because the API
stopped accepting it, and one that should always have been required.

--env-file reads that file and no other

Its help has said "instead of looking for one" since the day the flag was
added, and the code read the named file after everything the search found -
so a setting the named file omitted was still answered by whatever was on the
machine, and a flag meant to make one client entry self-contained isolated
nothing.

One .env applies now: the highest-precedence file that exists, and the ones
below it are not read. Naming one skips the search entirely, which is what
--tools-file has always done for the policy file. A real environment
variable still beats the file, so a container keeps passing its transport
settings while the key lives in the mounted volume.

If your settings live in more than one file, put them in the one that wins.
The configuration interface now says so on the overview when it is editing a
.env that a server would not read.

create_voucher lost unchecked, because the API took it away

It worked on 2026-08-20 - vouchers created that day are still in the test
account saying so. On 2026-08-23 the same call is refused with
voucherStatus: invalid_value, across three voucher types. Nothing changed on
this side. A parameter that fails every time is worse than an absent one.

To record a receipt for review rather than book it, upload_file still files
the document as an unchecked purchase invoice.

create_voucher requires voucher_number

The API refuses a voucher without one, for all four types. It was optional, so
a call that omitted it spent a request to be told no.

Also

The package index now says Beta rather than Alpha. Twenty-five tools, each
exercised against a live account, two transports, a published image.

Every tool was called against a live account for this release: twenty-five of
twenty-five, no failures.

Upgrading from 0.2.1 is a pull or a reinstall.

0.2.1 — the image on Python 3.14

Choose a tag to compare

@BeneODev BeneODev released this 23 Aug 09:34
1baa807

A patch release for the image. Nothing in the package itself changed, and
nothing new is enabled: the policy file remains the only thing that decides
which tools exist.

The published image runs Python 3.14

The newest version this package supports and is tested against, up from 3.13.
It reaches whoever pulls the image. An installation from the package index is
unaffected and keeps running on whatever Python it is installed into, 3.11 or
newer.

The tags a user pulls are derived from this release tag, so the base image
moves only when a version number is spent on it.

Pinning, now written down

The registry has carried a minor-line tag since the first image and nothing
said so. All four of these exist:

docker pull ghcr.io/benethos-hub/lexware-office-mcp:0.2.1   # one release
docker pull ghcr.io/benethos-hub/lexware-office-mcp:0.2     # follows its patches
docker pull ghcr.io/benethos-hub/lexware-office-mcp:latest  # moves every release
docker pull ghcr.io/benethos-hub/lexware-office-mcp:edge    # built on demand, not a release

Pin one of the first two for anything you depend on. The README and
compose.yaml say the same beside the line where the tag is actually typed.

Also

Locked development dependencies refreshed - ruff 0.16.3 to 0.16.4, which
reaches the development environment and CI only.

Upgrading from 0.2.0 is a pull or a reinstall. No setting, tool, argument
or output changed.

0.2.0 — an HTTP transport, and a container to run it in

Choose a tag to compare

@BeneODev BeneODev released this 22 Aug 19:34
2e76a20

The server learns a second transport and gets a container to run in. Everything from 0.1.0 is unchanged: nothing is enabled until the policy file names it.

An HTTP transport

--transport streamable-http or sse, beside the stdio one that stays the default. A bearer token is required, not offered — without LXO_MCP_BEARER_TOKEN an HTTP transport refuses to start, because anyone who can reach the port would otherwise be reaching an accounting API. The SDK's DNS-rebinding guard checks Host and Origin on top, with the loopback names always allowed and --allowed-hosts adding a container or proxy name.

stdio is untouched: there the client owns the process and nothing else can reach it.

A container

docker pull ghcr.io/benethos-hub/lexware-office-mcp:0.2.0
docker compose up -d                      # the server, on 127.0.0.1:8770
docker compose --profile setup up -d      # add the configuration interface

Published for linux/amd64 and linux/arm64. The README covers both Compose and plain docker run.

  • Nothing has to be prepared. The container generates its own bearer token on first start and writes it into the config volume — no secret is baked into an image that every copy would share.
  • A setting saved in the browser reaches the running server. Settings are read once at startup, so the container ends its process when its settings file changes and Compose starts it again.
  • The configuration interface is a second container behind a setup profile. It has no login and it takes an API key, so a plain up leaves it out.

For the client and the type checker

Every tool now carries the MCP annotations — readOnlyHint, and for a writing tool whether it destroys what was there and whether calling it twice is safe. They are derived from the same classification the policy file is written against, and they decide nothing: the file remains the only gate, consulted twice, reading no annotation.

The package also ships py.typed, so code importing it gets its annotations checked instead of skipped.

Verified

Against a live account, including a client reaching it through the pulled image over HTTP, and against a fresh installation that offers no tools until a policy file says otherwise.

The full list of changes is in CHANGELOG.md.

v0.1.0 — the first release

Choose a tag to compare

@BeneODev BeneODev released this 22 Aug 14:03
1fb7787

An unofficial MCP server for the Lexware Office public
API
, over stdio.

uv tool install benethos-lexware-office-mcp
benethos-lexware-office-mcp setup

Twenty-five tools across contacts, articles, bookkeeping vouchers, sales
documents, files and master data: search them, read them, create them, change
them, see what is still unpaid, download a PDF and upload a receipt.

Nothing is enabled until you say so. A fresh installation has no policy
file, and a server without one offers no tools at all. One flag per tool, not
a level and not a group, checked when the list is built and again when a call
arrives. The client is told when that set changes, so a permission takes
effect without a restart.

A configuration interface in the browser, setup, on the loopback address
only: which files are in effect and where every setting came from, the API key
checked before it is written, and one checkbox per tool with what it costs the
assistant in context.

Run it read-only unless you have a reason not to. This server reaches real
accounting records, and it is the assistant that decides when to call a tool
that writes.

The full list is in CHANGELOG.md,
the design and the measurements behind it in
SPECS.md.

Not affiliated with, endorsed by, or sponsored by Lexware or Haufe-Lexware
GmbH & Co. KG.