Skip to main content

zero-mcp

MCP server for the German broker Finanzen.net ZERO 🇩🇪
Local stdio MCP server wrapping the unofficial Python client finanzen-zero-api.

CI PyPI Python 3.13+ mypy: strict Tests: offline only License: MIT Status: alpha

Unofficial and unsupported. Finanzen.net ZERO has no public API. This server wraps finanzen-zero-api, which mimics the broker's private web/app endpoints; they can change at any time. Use it only on an account you are allowed to automate, and never with money you cannot afford to lose. Order tools move real money.

zero-mcp turns the finanzen-zero-api Python client into a local Model Context Protocol server. It is published on PyPI as finanzen-zero-mcp and installs the zero-mcp console script. An MCP host such as Claude Desktop, Claude Code or Cursor starts the server over stdio; an assistant can then read the account, search instruments, inspect charts, list depot positions and watchlist entries, review orders, and place or cancel orders. ZERO_MODE controls whether the mutating tools are exposed and whether orders need confirmation — see Configuration.

Contents

Features

  • Full library coverage. Account, instrument search/master data/detail/charts, depot positions, watchlist, orders, and the app-push 2FA that unlocks order execution.
  • Local stdio only. The MCP host spawns the process; there is no listening port, no browser and no Playwright/Selenium dependency.
  • One serialized session. All tools share a single lock-protected ZeroClient; broker calls are serialized so concurrent requests cannot race the login, session refresh, 2FA unlock or order flow.
  • Errors meant for a model. Missing configuration, bad credentials, 2FA timeouts, broker rejections and network failures become actionable MCP tool errors instead of stack traces.
  • Offline test suite. A mocked broker client and a real stdio subprocess test; no live calls and no credentials needed in CI.

Tools

Fifteen tools are registered in the default mode. The ten read tools are always available; the five write tools are absent from tools/list when ZERO_MODE=READ.

Tool Kind What it does
get_account read Cash account (Verrechnungskonto): buying/transfer power, IBAN, saldo, closing date.
search_instruments read Typeahead search by name, WKN or ISIN; per-asset-class hit counts.
get_instrument read Master record: asset class, trading state, fees, venues and MIC codes.
get_instrument_detail read Market data and fundamentals: quote, ranges, volume, profile, dividends.
get_chart read Price history for one scale (Intraday … Maximum).
get_positions read Depot positions with quantity, latest quote and entry quotes.
get_watchlist read Watchlist entries with quotes and metadata.
list_orders read Orders from one filter bucket (the broker's UI tabs) — Open (working, default), Filled (executed) or Canceled — with has_next pagination info.
get_session_status read Whether the session is unlocked for order execution.
list_enrolled_devices read Devices that can receive the 2FA push (with serials).
add_to_watchlist write Add an instrument by ISIN.
remove_from_watchlist write Remove an instrument by ISIN.
unlock_order_execution write Send the app push and wait for approval.
place_order write, real money Place a market/limit/stop-limit/OCO/trailing-stop order.
cancel_order write, real money Cancel an open order by its order_id.

Order tools unlock the 2FA session automatically and can block for up to 60 seconds while the push is approved. Their confirmation policy is set by ZERO_MODE (see Configuration); for device selection see Authentication and 2FA.

Requirements

Requirement Why
Python 3.13+ The project targets 3.13 and is strictly typed.
A Finanzen.net ZERO account Email + password login is the only supported method.
The ZERO mobile app Needed only for order execution: the 2FA push is approved on a paired device. Read-only tools work without it.
Network access to mein.finanzen-zero.net Every endpoint lives there. There is no sandbox.
An MCP host Claude Desktop, Claude Code, Cursor, or any client that launches local stdio servers.

Installation

From this checkout, with uv:

git clone https://github.com/wtfuii/zero-mcp.git
cd zero-mcp
uv sync

uv sync installs the server and its dependencies into .venv. The MCP host should run the zero-mcp console script through uv run (see Connect an MCP host).

With pip:

pip install finanzen-zero-mcp
zero-mcp

Or run it without installing, with uv:

uvx --from finanzen-zero-mcp zero-mcp

The PyPI distribution is finanzen-zero-mcp; the console script keeps the shorter name zero-mcp. zero-mcp reads MCP messages from stdin and writes them to stdout. Running it directly in a terminal will appear to hang; that is expected — an MCP host normally owns the process.

Configuration

Configuration is read from environment variables, which the MCP host passes to the stdio process.

Variable Required Default Meaning
ZERO_USERNAME for any broker call — The ZERO login e-mail address (the client's email).
ZERO_PASSWORD for any broker call — The ZERO account password.
ZERO_DEFAULT_DEVICE no — 2FA device serial used when several devices are enrolled.
ZERO_MODE no WRITE READ, WRITE or YOLO; see below. Case-insensitive.

Startup and tools/list work without credentials; a tool call then fails with a clear not configured message. Credentials are held in memory by the ZeroClient, are never written to disk by this server, and are never logged. The password is stored as a SecretStr.

Environment variables are visible to the spawned process and (depending on the host) to other local processes. Do not commit an MCP config containing your password, and prefer ZERO_MODE=READ unless you actively want trading tools.

Safety modes (ZERO_MODE)

ZERO_MODE is one switch with three mutually exclusive, case-insensitive values:

Value Registered tools Order confirmation
READ read tools only; the five write tools (watchlist edits, 2FA unlock, place/cancel order) are not registered not applicable
WRITE (default) all fifteen tools the model must obtain the user's explicit confirmation before place_order or cancel_order
YOLO all fifteen tools no confirmation requirement in the server instructions or order tool descriptions

Tools removed in READ never appear in tools/list. WRITE and YOLO differ only in the instruction attached to the order tools; neither changes tool annotations. In every mode the broker's app-push 2FA and any tool-approval prompt configured in the MCP host still apply — the server cannot override its host.

YOLO is a footgun. It removes the model-level requirement to ask before placing or cancelling an order. Use it only on an account and with amounts you can afford to trade without a human in the loop.

Connect an MCP host

Use an absolute path to this checkout:

{
  "mcpServers": {
    "finanzen-zero": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/to/zero-mcp", "zero-mcp"],
      "env": {
        "ZERO_USERNAME": "you@example.com",
        "ZERO_PASSWORD": "your-password",
        "ZERO_DEFAULT_DEVICE": "optional-device-serial",
        "ZERO_MODE": "WRITE"
      }
    }
  }
}
  • Claude Desktop: claude_desktop_config.json (Settings → Developer → Edit Config).
  • Cursor: .cursor/mcp.json (project) or ~/.cursor/mcp.json (global).
  • Any host that accepts command/args/env.

GUI hosts often start with a minimal PATH that does not contain uv. After uv sync, point the config at the console script directly instead:

{
  "mcpServers": {
    "finanzen-zero": {
      "command": "/absolute/path/to/zero-mcp/.venv/bin/zero-mcp",
      "env": {
        "ZERO_USERNAME": "you@example.com",
        "ZERO_PASSWORD": "your-password"
      }
    }
  }
}

On Windows the script is .venv\Scripts\zero-mcp.exe.

Claude Code

claude mcp add finanzen-zero \
  --env ZERO_USERNAME=you@example.com \
  --env ZERO_PASSWORD=your-password \
  --env ZERO_MODE=WRITE \
  -- uv run --directory /absolute/path/to/zero-mcp zero-mcp

Read-only setup

Enable only the ten read tools and keep the trading surface out of the model's context entirely:

{
  "mcpServers": {
    "finanzen-zero": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/to/zero-mcp", "zero-mcp"],
      "env": {
        "ZERO_USERNAME": "you@example.com",
        "ZERO_PASSWORD": "your-password",
        "ZERO_MODE": "READ"
      }
    }
  }
}

Restart the MCP host after changing environment variables. The process logs its mode and whether credentials are configured to stderr on startup, never to stdout.

Usage examples

Once the server is connected, ask the assistant in natural language:

  • “What is my current buying power and next closing date?”
  • “Search for Apple and show me the one-year chart.”
  • “Which positions do I hold and what are they worth at the latest quote?”
  • “List my open orders and cancel order ID GBR….”
  • “Place a limit buy for 1 share of Apple at €200 on gettex.”
  • “I approved the push — check whether order execution is unlocked.”

The assistant discovers the account through the read tools. There is no separate login tool, and the shared session is reused across calls.

Authentication and 2FA

Login is handled entirely by finanzen-zero-api:

  1. The first broker call performs a Cognito SRP login over HTTP through the broker's /apic/authc proxy. No browser and no API key are involved.
  2. The one-hour IdToken is refreshed with the refresh-token cookie; a rejected session is re-established once and the request retried.
  3. Sessions are in memory. Restarting the MCP server logs in again; no cookies are persisted.

Order execution additionally requires the app-push session TAN unlock:

  1. place_order / cancel_order probe is_authorized; when locked they request a push to the configured device and wait for approval.
  2. unlock_order_execution exposes that step explicitly, with a configurable timeout and no-op when already unlocked. It is useful only for pre-authorizing a batch or waiting longer than the order tools' built-in 60 seconds.
  3. If exactly one device is enrolled it is used automatically. With several devices, set ZERO_DEFAULT_DEVICE or call list_enrolled_devices and pass a serial; otherwise the call fails rather than guessing.

Keep the host clock synchronized (NTP): SRP signs a UTC timestamp, and large clock skew makes the login fail.

Output conventions

  • Tool results are JSON objects. Lists are nested under a descriptive key (positions, orders, entries, devices, bars) and usually come with a count.
  • Keys use the Python client's snake_case field names (the names documented in the finanzen-zero-api README), not the broker's camelCase wire aliases.
  • Account, position, order and watchlist amounts are decimal strings (e.g. "1000.50") so precision survives the JSON round-trip. Parse them before doing arithmetic. Market-data values such as chart bars and instrument detail quotes keep the broker's wire floats and are numbers.
  • Timestamps are ISO 8601 strings; dates use YYYY-MM-DD. Account amounts are EUR; instrument and order prices use the instrument's quote currency (quote_currency_code), not necessarily EUR.
  • Failures are MCP isError results with a human/model-readable message, including the broker's HTTP status, error code and field errors when available.

Safety and security

  • Real orders. place_order and cancel_order are marked destructiveHint and readOnlyHint=false. A market order can fill immediately and cannot be undone. If a placement fails after submission (timeout or network error), check list_orders before retrying — the order may already exist.
  • Credentials. Passwords arrive via environment variables and stay in memory. This server does not read .env files, keychains or config files. Treat MCP host config files as secrets when they contain ZERO_PASSWORD.
  • Unofficial endpoints. The broker can change or block these private endpoints at any time; schema drift is surfaced as a tool error rather than silently wrong data. Automating a brokerage account may violate the broker's terms — use only an account you are allowed to automate.

Architecture

src/zero_mcp/
├── server.py          # MCPServer (MCP SDK v2), dynamic tool registration, stdio main()
├── config.py          # ZERO_* env settings, lazy credential validation
├── client.py          # ClientProvider + lazy, lock-protected shared ZeroClient
├── errors.py          # zero_api/httpx exceptions → actionable ToolError
├── serialization.py   # Pydantic model → JSON-safe dict
├── __main__.py        # python -m zero_mcp
└── tools/             # vertical slices, one module per broker area
    ├── account.py
    ├── instrument.py
    ├── portfolio.py
    ├── watchlist.py
    ├── orders.py
    └── sessiontan.py

The MCP server is deliberately thin: it owns argument mapping, error translation, tool annotations, ZERO_MODE gating and the confirmation/YOLO instructions. Everything else — HTTP, SRP login, refresh, 2FA, Pydantic models — belongs to finanzen-zero-api.

Development

uv sync
uv run mypy .          # strict; run first
uv run pytest          # offline; no broker calls
uv build               # wheel + sdist
uvx twine check --strict dist/*

To exercise the server by hand, launch it through any MCP client or the MCP Inspector:

npx @modelcontextprotocol/inspector uv run --directory . zero-mcp

Set ZERO_USERNAME/ZERO_PASSWORD in the inspector's environment only if you intend to make live (read-only) calls. There is no live smoke test in CI and tests must never contact the broker.

See AGENTS.md for the architecture rules, MCP SDK conventions and contribution constraints. Releases are cut from a vX.Y.Z tag and published to PyPI through Trusted Publishing; see RELEASING.md for the registry setup and release checklist.

Limitations

  • Version coupling. The wrapper pins finanzen-zero-api>=0.1.0,<0.2.0. Model or endpoint changes in the alpha client can break tool output until the wrapper is updated.
  • stdio only. No HTTP/SSE transport, no multi-user server, no OAuth. One process, one account.
  • No order modification. The broker client supports placing and cancelling, not amending.
  • Blocking 2FA. place_order, cancel_order and unlock_order_execution wait for the phone approval; MCP hosts with a short tool timeout may abort the call before the push is accepted.
  • No streaming quotes. Charts and details are snapshots returned by the private endpoints.
  • One page of orders. list_orders returns a single page plus has_next; the page size is bounded by the tool's size argument (max 1000).
  • Unknown rate limits. The broker publishes none; avoid tight polling loops.

Project status

Alpha (0.1.0). All slices currently supported by finanzen-zero-api are wrapped: account, instruments, portfolio, watchlist, orders and session TAN/2FA. The tool surface may change between minor versions while the wrapper stabilizes. Pin the version you depend on.

License

MIT — see LICENSE. This project is not affiliated with Finanzen.net, Finanzen.net ZERO, or Baader Bank.

Metadata

Release files for finanzen-zero-mcp 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for finanzen-zero-mcp 0.1.0
File Size Uploaded Provenance
finanzen_zero_mcp-0.1.0.tar.gz 22.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for finanzen-zero-mcp 0.1.0
File Interpreter ABI Platform
finanzen_zero_mcp-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 51.7 kB

Release files / finanzen_zero_mcp-0.1.0.tar.gz

Download URL finanzen_zero_mcp-0.1.0.tar.gz
Size 22.1 kB
Tags Source
SHA-256 checksum
How to use checksums
80cc47e90ee800352e488a7ab39b6c071f361d9f7e5264f4f504d255bb21b87b
BLAKE2b-256 checksum
How to use checksums
a924c12e5eec208433b011eb97c86c26ee6d1b88e6a877999fd568049ae95e84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

Release files / finanzen_zero_mcp-0.1.0-py3-none-any.whl

Download URL finanzen_zero_mcp-0.1.0-py3-none-any.whl
Size 29.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4939f62cc754842e902d66f6ad21329e8b90afb45af6343f0d47c0be16c08d47
BLAKE2b-256 checksum
How to use checksums
47cb5c25fb7e45c888c32622416c8a21b62b6902ee485dd9bb4ff2118267b8f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

Security for finanzen-zero-mcp 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for finanzen_zero_mcp-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page