Files
accounted/packages/gnubok-mcp
Jakob WennbergandClaude Fable 5 205610d200 feat(mcp): distribution-channel client marker in MCP telemetry (#706)
* feat(mcp): distribution-channel client marker in MCP telemetry

Record an optional client marker on mcp.tool_called, mcp.tools_list_called
and mcp.resource_read events so per-channel adoption (e.g. the OpenClaw
skill) is measurable in event_log (180-day TTL).

- Server reads X-Gnubok-Client header, falling back to a ?client= query
  param on the endpoint URL. Sanitized ([A-Za-z0-9._-]{1,64}, lowercased),
  telemetry-only — same trust level as Mcp-Session-Id, never auth.
- The query param works with the already-published gnubok-mcp 1.0.1 via
  GNUBOK_URL, so no npm release is required to start measuring.
- Bridge 1.1.0 additionally forwards GNUBOK_CLIENT as X-Gnubok-Client.

OAuth-path attribution via DCR client_name is a possible follow-up — DCR
is stateless today, so client_name isn't recoverable at token time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(mcp): address PR #706 compliance findings

- ropa.yaml: declare the distribution-channel marker in the mcp.telemetry
  processing activity (GDPR Art. 30 — RoPA was drifting from actual flow)
- bridge: mirror the server's allow-list on GNUBOK_CLIENT so an invalid
  value degrades to no header instead of fetch() rejecting every request
- lib/events/types.ts: annotate client as client-supplied/telemetry-only
- test: pin that the allow-list runs on the percent-decoded ?client= value

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 14:33:24 +02:00
..

gnubok-mcp

Connect Claude Desktop (or any stdio MCP client) to your Accounted bookkeeping account. This is a thin stdio → HTTPS bridge: it forwards JSON-RPC over stdio to the hosted Accounted MCP server, which exposes 90+ bookkeeping tools (invoices, transactions, VAT/momsdeklaration, payroll, reports, year-end).

Write tools stage a pending operation that you confirm before anything is booked — the bridge never books on its own.

Quickstart

  1. Mint an API key in the Accounted dashboard at /settings/api. Use a gnubok_sk_test_* key against the sandbox while you evaluate; switch to gnubok_sk_live_* for real data. The key's scopes gate which tools are callable.

  2. Run the bridge with the key in the environment:

    GNUBOK_API_KEY=gnubok_sk_test_... npx gnubok-mcp
    

    It reads JSON-RPC from stdin and writes responses to stdout, so you normally point an MCP client at it rather than running it by hand.

Claude Desktop config

Add the bridge to your claude_desktop_config.json:

{
  "mcpServers": {
    "gnubok": {
      "command": "npx",
      "args": ["gnubok-mcp"],
      "env": {
        "GNUBOK_API_KEY": "gnubok_sk_test_..."
      }
    }
  }
}

Restart Claude Desktop. The Accounted tools appear in the client and you can start asking questions like "Show my uncategorized bank transactions and suggest categories."

Environment variables

Variable Required Default Purpose
GNUBOK_API_KEY yes — Your gnubok_sk_* API key.
GNUBOK_URL no https://app.gnubok.se/api/extensions/ext/mcp-server/mcp Override the MCP endpoint (e.g. for self-hosted Accounted).
GNUBOK_CLIENT no — Distribution-channel marker (e.g. openclaw), sent as X-Gnubok-Client. Telemetry only — never affects auth or behavior.

Alternative: claude.ai connector (no API key)

If you use claude.ai or Claude Desktop's custom-connector flow, you can skip this bridge entirely and add Accounted as an OAuth 2.1 custom connector instead — paste the connector URL https://app.gnubok.se/api/extensions/ext/mcp-server/mcp and authorise on the Accounted consent screen (read-only scopes by default; write scopes are ticked explicitly).

Docs

Full setup, sample prompts, and a 10-minute reviewer test: Connect with Claude.

License

MIT