PowerOffice Go MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PowerOffice Go MCPShow me the outstanding balance on invoice 1023."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
PowerOffice Go MCP — utvidet fork
Dette er en fork. Originalen er smplas/poweroffice-go-mcp, bygget av SmplCo til en demonstrasjon på Tech-Forum Stavanger. MIT-lisensiert, opphavsrett SmplCo AS — se LICENSE. Denne forken er til internt bruk, ikke et kommersielt produkt.
Hva som er lagt til her (0.4.0):
Støtte for flere selskaper i samme server, med streng isolasjon mellom dem (én klientnøkkel per Go-klient, eget token-lager per selskap).
Bokføring: bilagsutkast, postering til hovedbok, tilbakeføring, bilagsgodkjenning.
Hovedbok: saldobalanse, hovedbokstransaksjoner, kontoplan, bokføringssperre, MVA-innstillinger.
Leverandør: leverandører, leverandørreskontro, inngående faktura.
Lønn og timeføring.
Bank: kun lesing.
35 → 103 verktøy.
Sikkerhetsgrensen er flyttet. Originalen var utkast-only: ingenting den gjorde traff hovedboken. Det er bevisst gitt opp her — bokføring var poenget — og erstattet med en smalere garanti: ingen ekstern effekt, ingen pengeflytting. Les «The safety boundary in 0.4.0» før du peker denne mot et ekte regnskap.
Kom i gang: OPPSETT.md — nøkler, konfigurasjon, tilkobling til Claude Code, feilsøking.
An MCP (Model Context Protocol) server that exposes a curated subset of the PowerOffice Go API to AI assistants such as Claude Code, Cursor, Cline, and GitHub Copilot. In this fork that subset covers bookkeeping as well as sales; see the safety boundary below for where it stops.
The original was built by SmplCo for the demonstration at Tech-Forum Stavanger, 4 June 2026 with CMS Kluge Advokatfirma, where it was reviewed publicly by Norwegian tech lawyers. The sections below are SmplCo's, except where they describe 0.4.0.
Why this exists
We wanted to find out, in public, how far a small business can take AI-assisted automation of an accounting workflow — and what the legal and practical limits actually are.
Rather than running the experiment behind closed doors and presenting a polished outcome, we built a working integration against the real PowerOffice Go API, opened up the source code, and invited Norwegian tech lawyers to stress-test it live.
Related MCP server: fiken-mcp
Design principles
The server is built around four deliberate constraints:
No external effect. The server cannot send invoices, issue invoices, send payment reminders, or take any other action visible outside the client's own books. A human must log into PowerOffice Go's UI to do that. The relevant tools simply do not exist in the code — see Why there is no
send_invoice. (In 0.3.0 this constraint was stricter still — draft-only, nothing reaching the general ledger. 0.4.0 posts to the ledger on purpose; see the safety boundary.)Human-in-the-loop by architecture, not by promise. The safety guarantee is enforced by the absence of the tools, not by a configuration flag or system prompt. Confirm flags on posting and deletion are a second, weaker layer on top — a speed bump, not the guarantee.
Auditable by default. Every tool call is appended to an audit log (
~/.poweroffice-mcp/audit.log) with timestamp, tool name, arguments, outcome and duration. See Audit logging.No secrets in the repo. Credentials are passed via environment variables. The repo is safe to share.
Data flow
Setup A — Cloud frontier model (Anthropic Claude)
flowchart LR
User([Andreas / user])
CC[Claude Code<br/>CLI]
CL[Claude API<br/>Anthropic, US]
MCP[poweroffice-go MCP<br/>local Node.js process]
PO[PowerOffice Go API<br/>EU]
User -- "natural-language prompt" --> CC
CC -- "prompt + tool results<br/>HTTPS" --> CL
CL -- "tool calls<br/>(JSON)" --> CC
CC -- "stdio JSON-RPC" --> MCP
MCP -- "HTTPS REST<br/>OAuth 2.0" --> PO
PO -- "JSON response" --> MCP
MCP -- "stdio JSON-RPC" --> CC
classDef us fill:#fde2e2,stroke:#c00
classDef eu fill:#d9ead3,stroke:#274e13
classDef local fill:#cfe2f3,stroke:#0b5394
class CL us
class PO eu
class CC,MCP,User localWhat crosses the Atlantic: every user message, every tool input, and every tool output (customer names, invoice amounts, etc.) — sent to Claude so it can reason over them.
Setup B — Local model (Mistral Small via Ollama)
flowchart LR
User([Andreas / user])
Cline[Cline<br/>VS Code extension]
Ollama[Ollama runtime<br/>local]
Mistral[Mistral Small 24B<br/>local weights]
MCP[poweroffice-go MCP<br/>local Node.js process]
PO[PowerOffice Go API<br/>EU]
User -- "natural-language prompt" --> Cline
Cline -- "HTTP localhost:11434" --> Ollama
Ollama -- "model inference" --> Mistral
Mistral -- "tool calls" --> Cline
Cline -- "stdio JSON-RPC" --> MCP
MCP -- "HTTPS REST<br/>OAuth 2.0" --> PO
PO -- "JSON response" --> MCP
classDef eu fill:#d9ead3,stroke:#274e13
classDef local fill:#cfe2f3,stroke:#0b5394
class PO eu
class Cline,Ollama,Mistral,MCP,User localWhat crosses the Atlantic: nothing. The model runs on the user's laptop. The only outbound traffic is to PowerOffice Go's EU-based API.
What the server can do
As of 0.4.0 the server covers sales, purchases, bookkeeping, payroll, time tracking and bank reading, across one or many Go clients.
Area | Read | Write |
Companies |
| (none) |
Customers |
|
|
Products |
|
|
Sales orders |
|
|
Outgoing invoices (sent) |
| (none — strictly read-only) |
Customer ledger |
| (none) |
Suppliers |
|
|
Supplier ledger |
| (none) |
Incoming invoices |
| (none — record purchases as supplier-invoice vouchers) |
Voucher drafts |
|
|
Posting to the ledger |
|
|
Voucher approval |
|
|
General ledger |
|
|
Payroll |
|
|
Time tracking |
|
|
Bank |
| (none — read-only by design) |
Employees |
| (none) |
Dimensions |
|
|
Settings |
| (none) |
Prospects |
|
|
Validation |
| (read-only) |
The safety boundary in 0.4.0
0.3.0 was draft-only: nothing it did changed the general ledger. 0.4.0 deliberately
crosses that line — post_voucher books entries, and create_salary_line feeds
payroll — because bookkeeping was the point. The boundary moved; it did not vanish:
No external effect. Nothing is sent to a customer, a supplier or a debt collector. No invoices, no credit notes, no reminders.
No money movement.
POST/DELETE /BankTransfersand every write to/ClientBankAccountsare absent. Bank data is read-only: every API call insrc/tools/bank.tsis a read.Posting and deleting require
confirm=true. A speed bump against a misread instruction, not a security control. The control is the absence above.Reversal, not deletion. A posted voucher is corrected with
reverse_voucher, which is what Norwegian bookkeeping rules require.
The list of what is deliberately absent is in src/utils/safety.ts and is returned
by list_companies, so an assistant can read its own limits.
Multiple companies (multi-tenant)
PowerOffice issues one client key per Go client, and an access token belongs to exactly one client key. PowerOffice's own guidance warns that sharing token state between clients risks reading or writing the wrong company's books — so isolation here is structural rather than careful:
One
PowerOfficeClientper configured company, each with its own token cache and rate limiter. Nothing is shared between them.The company is resolved once per tool call and carried in an
AsyncLocalStoragecontext for that call's whole async extent. Concurrent calls for different companies cannot observe each other (tests/registry.test.tsasserts this under deliberate interleaving).Every tool takes a
clientargument. Writes must name the company explicitly whenever more than one is configured — even if a default is set. A read may use the default; booking to the wrong company may not be guessed at.A tool that somehow runs without a resolved company throws rather than falling back to one.
Point POWEROFFICE_CLIENTS at a JSON file:
{
"apiUrl": "https://goapi.poweroffice.net",
"appKey": "...",
"subscriptionKey": "...",
"defaultClient": "acme",
"clients": {
"acme": { "label": "Acme AS", "clientKey": "..." },
"bolig": { "label": "Bolig AS", "clientKey": "..." }
}
}Call list_companies to see the aliases. The single-client environment variables
still work unchanged when POWEROFFICE_CLIENTS is not set.
If the key belongs to a PowerOffice partner (an accounting firm),
list_partner_clients enumerates the clients the partner can reach via
/ClientAdmin/Clients. On an ordinary client key PowerOffice rejects it, which is
the correct answer rather than a bug.
Why there is no send_invoice
PowerOffice Go's API supports sending invoices and other state-changing operations. We deliberately did not expose them as MCP tools.
The architectural choice is:
Tools that have no external visible effect (drafts, internal records) are exposed.
Tools that create external obligations (invoices sent to customers, payment reminders, debt collection notices) are not exposed.
A reviewer can verify this by searching the codebase for send, issue, finalize, remind or collect — no such tools exist. (Since 0.4.0 the codebase does contain post_voucher, which posts to the general ledger; see the safety boundary above for what that does and does not allow.) If we wanted to add them later, it would require an explicit code change, a code review, and a deliberate redeployment.
Audit logging
Every tool invocation is logged as one JSON line in ~/.poweroffice-mcp/audit.log (configurable via the POWEROFFICE_AUDIT_LOG environment variable). Format:
{"ts":"2026-05-27T07:14:22.118Z","tool":"create_draft_invoice","args":{"customerId":27469244,"lines":[...]},"status":"ok","durationMs":634}The log records:
Timestamp (UTC, ISO-8601)
Tool name
Input arguments (after Zod validation)
Outcome (
okorerror)Duration in milliseconds
Error message on failure
The log is append-only from the server's side. It is not uploaded anywhere — it lives on the machine running the MCP server.
Testing and continuous integration
The repository ships with a Vitest test suite. Run it locally with:
npm testTests cover the rate limiter, the audit log, the JSON-Patch body conversion, the URL-encoding helper, and the invoice validator. The full test suite runs on every push and pull request via GitHub Actions, along with npm audit, tsc, and the npm run build step.
CodeQL static analysis was removed in favour of leaving CI meaningful: code scanning needs GitHub Code Security on a private repository, so the workflow analysed the source and then failed on the upload, every run. A check that is always red hides the ones that are newly red. Turn code scanning on — or make the repository public — and the workflow is worth restoring; it is in the history at .github/workflows/codeql.yml.
Dependabot opens weekly PRs for npm updates and monthly PRs for GitHub Actions updates.
Dependencies
Two runtime dependencies, both MIT licensed:
@modelcontextprotocol/sdk— the official MCP SDK from Anthropiczod— schema validation
No code was copied from third-party repositories. Everything in src/ was written for this project. All HTTP calls use the platform-native fetch API in Node.js 20+.
Running it
git clone <this-repo>
cd PoGoMCP
npm install
npm run build
export POWEROFFICE_API_URL="https://goapi.poweroffice.net/Demo"
export POWEROFFICE_APP_KEY="..."
export POWEROFFICE_CLIENT_KEY="..."
export POWEROFFICE_SUBSCRIPTION_KEY="..."
node dist/index.jsTo connect from Claude Code, add the following block to ~/.claude.json under mcpServers:
"poweroffice-go": {
"command": "node",
"args": ["/absolute/path/to/PoGoMCP/dist/index.js"],
"env": {
"POWEROFFICE_API_URL": "https://goapi.poweroffice.net/Demo",
"POWEROFFICE_APP_KEY": "...",
"POWEROFFICE_CLIENT_KEY": "...",
"POWEROFFICE_SUBSCRIPTION_KEY": "..."
}
}For Cline (VS Code / Cursor), see cline_mcp_settings.json under the Cline extension's global storage directory.
How it was built
The entire codebase was developed by Andreas Melvær (a designer, not a full-time developer) through natural-language conversation with Claude Code (Anthropic), on a Claude Max plan with training-data sharing disabled.
The development process itself is part of the demonstration: how far can a non-developer take a real API integration, with current AI tooling, in a single working session?
Acknowledgements
Thank you to PowerOffice Go for providing API access for this experiment and for being genuinely open to customers and partners building on top of their platform.
Thank you to CMS Kluge Advokatfirma, in particular Ove André Vanebo and Bernt Olav Thorsheim, for agreeing to scrutinise this in public.
Terms, data, and privacy
Use of the PowerOffice Go API through this integration is governed by the Visma Developer Terms. Production data access requires the customer's authorisation, and the integration's registered "intended use" forms part of that agreement.
For any customer-facing deployment, SmplCo AS provides its own end-user terms and privacy policy describing the integration and the data it processes. In line with the Developer Terms, Data is kept to the minimum required, used only for the customer's own purposes, not shared with third parties except as needed to operate the integration, and deleted when the customer's use ends.
Important: when the integration is driven by a cloud LLM, tool inputs and outputs are processed by that model provider (see Setup A under Data flow). For real personal data, use an enterprise LLM plan with a data processing agreement, or a local model, as described in SECURITY.md.
Trademarks
PowerOffice Go and Visma are trademarks of Visma AS. This is an independent integration built by SmplCo AS. It is not made, sponsored, or endorsed by Visma AS or PowerOffice AS.
License
MIT — see LICENSE.
This code is provided for educational and demonstrative purposes. It is not a production-ready integration and should not be deployed against live financial data without independent review.
This server cannot be deployed
Maintenance
Related MCP Connectors
Connect Exact Online accounting to Claude, ChatGPT and Copilot. 114 tools, OAuth 2.1, EU-hosted.
Document sharing, invoicing, and personal finance platform. 15+ AI tools via OAuth 2.1.
GDPR-compliant calendar access for AI assistants: read, create, edit, RSVP. Google, MS 365, Apple.
Connect your AI to your Well financial data - invoices, companies, contacts.
Related MCP Servers
- FlicenseBqualityDmaintenanceEnables AI assistants to interact with the Tripletex accounting API to manage time tracking, projects, and timesheet approvals through natural language. It also supports searching and managing outgoing invoices and processing supplier invoice approvals.312-
- AlicenseCqualityCmaintenanceEnables AI assistants to manage invoices, contacts, purchases, journal entries, and other accounting operations via the Fiken API.10010 npm1MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to interact with the Tripletex accounting system via 56 tools and 18 skills for orders, invoices, bookkeeping, reports, projects, and travel expenses.23MIT
- FlicenseAqualityCmaintenanceEnables Codex to securely access PowerOffice Go API v2 with read-only tools and write operations that require explicit confirmation for customers and general ledger accounts.10-