Skip to main content
Glama
truls27a

wint-mcp

by truls27a
README.md
# wint-mcp

An [MCP](https://modelcontextprotocol.io) server that lets an AI assistant handle the day-to-day of your
[Wint](https://www.wint.se) bookkeeping. It reads to-dos, receipts, supplier invoices, ledger transactions,
reports and bank balances. It can finish and submit receipts, send in new receipts and documents, approve
supplier invoices, and attach documents to payments that are missing one. You log in with BankID through
a small login panel shown right in the chat.

It covers the everyday work of a small company owner, not all of Wint. Customer invoicing, salaries,
annual accounts and settings are not included. Contributions that add them are welcome.

> **Unofficial.** This is not affiliated with Wint or BankID. Wint publishes an
> [OpenAPI description](https://api.wint.se/swagger/v1/swagger.json) of its API, but the BankID login and
> the to-do list used here come from Wint's own web app and are not documented. Either can change or
> break at any time. Automated use may be against Wint's terms. Use at your own risk.

## What it can do

| Tool | What it does |
|---|---|
| `connect_wint` | Shows the BankID login panel |
| `wint_status` / `disconnect_wint` | Shows whether you're logged in / deletes the stored session |
| `list_companies` | Lists every company your Wint user can access |
| `list_todos` | Lists open to-dos: missing documents, supplier invoices to approve, receipts, messages… |
| `list_missing_documents` | Lists payments that are missing a receipt or invoice |
| `get_receipts` / `get_receipt` | Lists receipts, or shows one in detail |
| `get_supplier_invoices` / `get_supplier_invoice` | Lists supplier invoices, or shows one in detail |
| `get_transactions` / `get_voucher` | Lists ledger transactions by date, account or text, or shows one voucher |
| `get_accounts` | Shows the chart of accounts |
| `get_financial_report` | Shows a result report (P&L) or balance report over whole months |
| `get_bank_balances` | Shows bank balances and the date bookkeeping is done until |
| `search_wint` | Searches suppliers, customers, invoices and receipts |
| `upload_document` / `list_uploads` | Shows an upload panel for a receipt or invoice file, or lists uploaded files |
| `get_receipt_options` | Shows receipt categories, your payment methods, and whether you can approve invoices |

**Tools that change things** (marked ✎):

| Tool | What it does |
|---|---|
| ✎ `update_receipt` | Edits a receipt (category, purpose, files, …) and optionally submits it, e.g. a Wint card draft |
| ✎ `create_receipt` | Sends in a new receipt, e.g. something you paid with your own money |
| ✎ `upload_supplier_invoice` | Sends a supplier invoice file to Wint, which then reads it |
| ✎ `upload_other_document` | Sends any other document (contract, statement…) to Wint |
| ✎ `approve_supplier_invoice` | Approves a supplier invoice. Wint then pays it on the due date |
| ✎ `attach_missing_document` | Attaches documents to a payment that is missing one |

Every change takes two steps. Without `confirm` the tool only returns a preview of what would be sent.
With `confirm=true` it is sent to Wint, and that changes the company's bookkeeping. Nothing can be paid
with BankID, sent to customers or deleted, except attachments on a receipt you are editing. The file can
come from:

- the **upload panel** (`upload_document`), which gives each file an `upload_id`
- `file_url`, an `https://` link the server downloads (public addresses only)
- `file_base64`, the file content itself

Files are PDFs or images, up to 10 MB each. Uploaded files are kept for one hour.

## The login panel

`connect_wint` returns an interactive [MCP Apps](https://modelcontextprotocol.io/docs/extensions/apps)
panel instead of a link:

- **On a computer** it shows a live BankID QR code. Scan it with the BankID app.
- **On a phone** it shows an **Open BankID** button that opens the BankID app on the same device.

The login only starts when the panel asks for it, because BankID cancels a login the app hasn't picked
up within about 30 seconds. A new QR code is started automatically if nobody scans in time.

After the login, the server keeps Wint's refresh token and gets a new access token when the old one
expires (about every 10 minutes). You stay logged in for as long as Wint keeps accepting the refresh
token, or until `--max-session-hours` has passed.

You need a client that renders MCP Apps panels, such as ChatGPT. In other clients you can log in by
running the server locally once in a client that has panels. The session is stored in the data
directory, so other clients that use the same directory get the same session.

## Install

Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/).

```sh
git clone https://github.com/truls27a/wint-mcp.git
cd wint-mcp
uv sync
uv run wint-mcp --help
```

### Local clients (stdio)

For a client that starts the server itself, add something like this to its MCP config:

```json
{
  "mcpServers": {
    "wint": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/wint-mcp", "wint-mcp"]
    }
  }
}
```

### Remote clients (HTTP)

```sh
WINT_MCP_TOKEN="$(openssl rand -hex 32)" uv run wint-mcp --transport http --port 8000
```

The MCP endpoint is `http://127.0.0.1:8000/mcp`, and `/healthz` is a health check.

- By default it listens on `127.0.0.1` only.
- If `WINT_MCP_TOKEN` is set, every request must send `Authorization: Bearer <token>`.
- It refuses to listen on a non-loopback address without a token. The exception is
  `--allow-unauthenticated`, meant for a private container network where the only way in is a tunnel
  you control.

ChatGPT needs to reach the server over the internet. Put it behind a tunnel or reverse proxy that
handles authentication, and never expose an unauthenticated port.

### Docker

```sh
docker build -t wint-mcp .
docker run -d --name wint-mcp -p 127.0.0.1:8000:8000 \
  -e WINT_MCP_TOKEN=change-me -v wint-mcp-data:/data wint-mcp
```

## Configuration

| Setting | Default | Meaning |
|---|---|---|
| `--transport` | `stdio` | `stdio` or `http` |
| `--host` / `--port` | `127.0.0.1` / `8000` | HTTP only |
| `--data-dir` / `WINT_MCP_DATA_DIR` | `~/.local/state/wint-mcp` | Where the session and uploads are stored |
| `--max-session-hours` / `WINT_MCP_MAX_SESSION_HOURS` | no limit | Forget the session this long after login |
| `WINT_MCP_TOKEN` | unset | Bearer token required on HTTP |
| `--allow-unauthenticated` | off | Allows a non-loopback HTTP address without a token |

## Security

Read this before you run it.

- **One user per server.** The server stores one Wint session. Anyone who can call the server can read
  that person's bookkeeping for every company they have in Wint, and can attach documents to missing
  documents, submit receipts and approve supplier invoices. Run your own instance and keep it private.
- **The stored session can do more than this server does.** The refresh token belongs to a normal Wint
  web session, which can also approve invoices and change bookkeeping data. In Wint, payouts and salaries
  need a separate BankID signature. Anyone who gets hold of the data directory can use the session until
  Wint stops accepting it. The directory is created `0700` and the database `0600`. Use
  `disconnect_wint`, and consider `--max-session-hours`.
- **No credentials are stored.** Login is BankID only. The server never sees a password, and it does not
  store your personal identity number.
- **Prompt injection.** Supplier names, receipt texts and file names come from Wint and from documents.
  The server tells the model to treat them as data, and every change needs an explicit confirmation.

## Limitations

- Endpoints and response shapes are reverse-engineered and may change without notice.
- Dimensions (cost centres, projects) and invoice periodisation can't be set. If Wint requires them for
  a company, finish that item in Wint.
- Supplier invoices can be approved, not rejected or sent back.
- Wint has no logout endpoint for this kind of session. `disconnect_wint` deletes the stored tokens,
  and Wint expires them on its own.

## License

[MIT](LICENSE)

TDQS

B3.2/5.0

Scored across 28 tools

Disambiguation4/5

Most tools target clearly distinct resources and actions, especially receipts, supplier invoices, ledger data, reports, and uploads. Minor ambiguity remains among the BankID/login-panel tools and the upload-panel tools, though the descriptions usually clarify when to use each.

Naming Consistency4/5

Tool names are consistently snake_case and mostly follow an action_resource pattern such as list_todos, get_receipt, and approve_supplier_invoice. A few names, like wint_status and bankid_login_start, deviate from the verb_noun pattern but remain readable.

Tool Count3/5

The server exposes 28 tools, which is on the heavy side, but the underlying Wint accounting domain is broad and includes auth, uploads, receipts, invoices, ledger, reports, and search. Several low-level panel/auth tools could potentially be consolidated, making the count borderline rather than clearly well-scoped.

Completeness3/5

Core workflows are covered: session handling, missing-document attachment, receipt creation/update, supplier invoice upload/approval, and financial reporting. However, notable lifecycle gaps remain, such as todo completion/snoozing, supplier invoice rejection/editing, and richer entity lookup beyond broad search.

Maintenance

ActivityMaintained
ResponsivenessNo issues