Ekwo OS
NPM · @EKWO-AI/MCP · SCANNED SEP 25
Open source accounting data infrastructure on your own Postgres, acting as the user under RLS.
Available components
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security99
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- No install/post-install scripts declared.Pass
- 31 of 112 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency48
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- Clear OSI-approved license (AGPL-3.0-only).Pass
- Actively maintained (last published 2 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability77
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 11217 tokens (~203/item across 55 items; 55 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management10
- Stability observed for 3 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage88
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 64% of tool parameters carry a description.Partial
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 4 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 56 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
How do I install the Ekwo OS MCP server?
Ekwo OS runs locally as an npm package, launched with npx -y @ekwo-ai/mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · @ekwo-ai/mcp
claude mcp add ai-ekwo-mcp -- npx -y @ekwo-ai/mcp
{
"mcpServers": {
"ai-ekwo-mcp": {
"command": "npx",
"args": [
"-y",
"@ekwo-ai/mcp"
]
}
}
} {
"servers": {
"ai-ekwo-mcp": {
"command": "npx",
"args": [
"-y",
"@ekwo-ai/mcp"
]
}
}
} codex mcp add ai-ekwo-mcp -- npx -y @ekwo-ai/mcp
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ai-ekwo-mcp": {
"type": "local",
"command": [
"npx",
"-y",
"@ekwo-ai/mcp"
],
"enabled": true
}
}
} openclaw mcp add ai-ekwo-mcp --command npx --arg -y --arg @ekwo-ai/mcp
mcp_servers:
ai-ekwo-mcp:
command: "npx"
args: ["-y", "@ekwo-ai/mcp"] {
"McpServers": {
"ai-ekwo-mcp": {
"Transport": "stdio",
"Command": "npx",
"Arguments": [
"-y",
"@ekwo-ai/mcp"
]
}
}
} assistant mcp add ai-ekwo-mcp -t stdio -c npx -a -y @ekwo-ai/mcp
{
"mcpServers": {
"ai-ekwo-mcp": {
"command": "npx",
"args": [
"-y",
"@ekwo-ai/mcp"
]
}
}
} Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 25 Sept 26 +1
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 23 Sept 26 +12
- Known CVEs: unverified → pass ▲ security
- Dependency health: unverified → 0.88 ▲ functional
- Stability: unverified → 0.03 ▲ functional
- Package version: 0.7.0 → 0.8.0 functional
- 22 Sept 26 59
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 25 Sept 2026 · Analysed npm/@ekwo-ai/mcp@0.8.0
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | npm |
Background: How many MCP packages publish verified provenance →
Dependencies 112 packages
| Packages resolved | 112 |
|---|---|
| Stale | 31 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
aged_balance Aged balance ~103
What customers still owe (or what is still owed to suppliers), bucketed by how overdue it is. It reads unmatched ledger lines, not invoices, so it ties back to the balance sheet: an invoice counts as settled only once its payment has been matched.
| Name | Type | Req | Description |
|---|---|---|---|
| at | string | – | The day to age at. Defaults to today. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| group | string | – | – |
No output schema declared.
No examples provided.
cancel_document Undo a posted invoice ~411
Undoes a posted sale or purchase invoice in one call, the one way its country and its facts allow, and says which in undone_by. 'draft': the country's posted_edit_policy lets a posted document go back to draft and nothing about this one has left — never sent nor on Peppol, not paid, not declared, its period open and, where numbering is gapless, its number the last one drawn; its entry is taken away, its number given back, and it is a draft to correct and post again. 'credit_note' otherwise, with the reason in why: its credit note — the same lines, taxes, accounts, contact, currency and rate — is issued naming it, posted and matched against it, and the invoice is cancelled, payment state reversed; the invoice keeps its number and its entry. Tell the user which it was. A date, or credit_note: true, asks for the credit note outright. Dated on the invoice's booking day unless you give a date; refused by name when that period is locked or closed (reversal_date_needed), and then you ask the user for a date rather than choosing one. Refused for a draft, a credit note, an invoice already cancelled or credited, and one that is paid in part or in full — the payment is unmatched first with unreconcile, and only when the user says so. Ask the user before calling it.
| Name | Type | Req | Description |
|---|---|---|---|
| credit_note | boolean | – | True: undo it with a credit note even where it could go back to draft — the user wants the correction on the record. |
| date | string | – | The day a credit note is issued and booked on. Given, it asks for the credit note. Left out: the invoice's own booking day, and refused by name (reversal_date_needed) when that period is no longer op… |
| document_id | string | yes | The posted sale or purchase invoice to undo. |
No output schema declared.
No examples provided.
close_fiscal_year Close a fiscal year ~138
Closes a year: the result of the year leaves the income statement the way the country model says — straight to retained earnings, into a current-year result account, or through the appropriation accounts — every income and expense account goes back to zero, and the year stops accepting entries. Refused while the year holds a draft entry, while an earlier year with entries is open, or when a later year is already closed. It never writes what a general meeting decides to do with the result. Always ask the user before calling it.
| Name | Type | Req | Description |
|---|---|---|---|
| fiscal_year_id | string | yes | The year to close. Every entry in it must be posted. |
No output schema declared.
No examples provided.
create_api_key Issue a key to a machine ~216
Issues a key so a script — a nightly import, a till, a bank feed — can work in one company without a person signing in. It carries an explicit list of capabilities and nothing else, it can never reach another company, and it cannot hold a capability you do not hold yourself. The secret comes back once and is stored only as a hash: show it to the user and say it cannot be read back. Prefer this to sharing anybody’s password, and never suggest a service key.
| Name | Type | Req | Description |
|---|---|---|---|
| capabilities | array | yes | Exactly what the machine may do, e.g. ["bank.write"]. You cannot put a capability on a key that you do not hold yourself. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| expires_at | string|null | – | When it stops working, as a timestamp. Left out, it does not expire on its own. |
| name | string | yes | What this key is for, in the words an operator will read a year from now. |
No output schema declared.
No examples provided.
create_bank_account Add a bank account ~286
Registers a bank account of the company from its IBAN, and wires it to the bank journal and to the ledger account behind it — both of which the country template has already chosen, so neither has to be given. Running it twice with the same IBAN returns the one that exists rather than creating a second. Do this once per account: until a company has one, an invoice carries no IBAN and record_payment can only book on the journal's default account.
| Name | Type | Req | Description |
|---|---|---|---|
| account_code | string | – | The ledger account behind it. Left out, the journal's default account — 550000 in Belgium, 512000 in France. |
| account_id | string | – | – |
| bank_name | string | – | – |
| bic | string | – | – |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| currency_code | string | – | Defaults to the company's own currency. |
| iban | string | yes | The IBAN. Spaces are removed and the value is upper-cased; it is the natural key of a bank account in a company. |
| journal_code | string | – | The financial journal it books through. Left out, the bank journal of the company. |
| journal_id | string | – | – |
| label | string | – | What it is called in the books. Defaults to the bank name, then to the IBAN. |
No output schema declared.
No examples provided.
create_bank_transaction Add a bank transaction ~189
Records one statement line by hand, for an installation without a bank feed. `amount` is signed: positive is money in. It books nothing — the line waits as pending until a payment is recorded.
| Name | Type | Req | Description |
|---|---|---|---|
| amount | string|number | yes | Signed: positive is money in, negative is money out. |
| bank_account_id | string | yes | – |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| contact_id | string | – | – |
| counterpart_iban | string | – | – |
| counterpart_name | string | – | – |
| description | string | – | – |
| reference | string | – | – |
| statement_id | string | – | – |
| structured_reference | string | – | A structured communication, e.g. +++000/0000/00000+++ or RF… |
| transaction_date | string | yes | – |
| value_date | string | – | – |
No output schema declared.
No examples provided.
create_company Create a company ~260
Creates a company on a country pack: its chart of accounts, its journals and its taxes are copied in, its first financial year is opened on the month that country opens one on, and you become its first member. Creating a company is an instance-level act — it needs an instance administrator, and being one is not the same as being on anybody’s books. Ask the user for the country rather than guessing: the wrong answer is a whole chart of accounts.
| Name | Type | Req | Description |
|---|---|---|---|
| chart_code | string | – | Which chart, where the country offers several. |
| country | string | yes | Which country pack: its chart of accounts, its taxes and its declaration form. list_companies shows what the installation already uses. |
| currency_code | string | – | Left out, the country pack's. |
| fiscal_year | integer | – | Calendar year the first financial year opens in. Default this year. |
| fiscal_year_start | string | – | First day of it. Left out, the month the country pack opens a year on — and a pack that names none is a refusal, not a January. |
| language | string | – | Language the books are kept in — it decides the labels of the chart. Left out, the country pack's. |
| name | string | yes | – |
No output schema declared.
No examples provided.
create_contact Create a contact ~225
Adds a customer, supplier or other third party to a company. Search first: a duplicate contact splits a customer account in two and the aged balance stops making sense. payment_terms_days drives the due date a posted invoice gets when none is given.
| Name | Type | Req | Description |
|---|---|---|---|
| address_line1 | string | – | – |
| auxiliary_code | string | – | Sub-ledger code; the French FEC reports it. |
| city | string | – | – |
| client_ref | string | – | Your own reference for this creation. Calling again with the same one returns what was created the first time (`replayed: true`) instead of creating a second — use it whenever a call might be repeate… |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| contact_type | string | yes | – |
| country | string | – | ISO country code, e.g. BE. |
| string | – | – | |
| name | string | yes | – |
| payment_terms_days | integer | – | – |
| postal_code | string | – | – |
| vat_number | string | – | – |
No output schema declared.
No examples provided.
create_document Create a draft invoice ~326
Creates a draft invoice, credit note or quote with its lines, and returns it with the totals the database computed — never with totals you supplied. A line may name a product_code, which fills in its text, price, unit, account and tax; anything the line carries wins over that. With no product and no account_code, the account falls back to the company default and then to its country model. A tax is different: a line with none is booked as a base with no VAT box, which is not the same as 0 %. Nothing is in the ledger yet; post_document is what books it.
| Name | Type | Req | Description |
|---|---|---|---|
| accounting_date | string | – | The date the entry is booked on, when it differs from the document date. |
| client_ref | string | – | Your own reference for this creation. Calling again with the same one returns what was created the first time (`replayed: true`) instead of creating a second — use it whenever a call might be repeate… |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| contact_id | string | yes | – |
| currency_code | string | – | – |
| doc_type | string | yes | – |
| document_date | string | yes | – |
| due_date | string | – | – |
| journal_id | string | – | – |
| lines | array | yes | – |
| number | string | – | Your own number. Left out, posting takes the entry number. |
| payment_reference | string | – | – |
| supplier_reference | string | – | The supplier's own invoice number, on a purchase. |
No output schema declared.
No examples provided.
create_product Add a product ~394
Adds an item to the catalogue: a code unique in the company, a name, a unit, a price, and optionally the account and the tax a sale or a purchase of it carries. It changes nothing already booked — a product is what a new line is filled in from, never a rule applied to the past. Search first: a second code for the same thing is how a price list stops being one.
| Name | Type | Req | Description |
|---|---|---|---|
| code | string | yes | Your own reference for the item. Unique in the company, and what EN 16931 calls the seller's item identifier (BT-155). |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| currency_code | string | – | – |
| description | string | – | The longer text under the name (BT-154). |
| kind | string | – | Defaults to service. Goods and services are not taxed alike and do not feed the same declaration boxes. |
| name | string | yes | What appears on the invoice line (BT-153). |
| purchase_account_code | string | – | Expense account a purchase of this books to. |
| purchase_account_id | string | – | – |
| purchase_price | string|number | – | – |
| purchase_tax_code | string | – | – |
| purchase_tax_id | string | – | – |
| sale_account_code | string | – | Income account a sale of this books to. |
| sale_account_id | string | – | – |
| sale_price | string|number | – | Net unit price on a sale. A line may still carry another. |
| sale_tax_code | string | – | Tax applied when it is sold, by code. |
| sale_tax_id | string | – | – |
| unit_code | string | – | UN/ECE recommendation 20: C62 a piece, HUR an hour, DAY a day, MON a month, KGM, LTR, MTR, KWH. Defaults to C62. |
No output schema declared.
No examples provided.
describe_pack Where a country pack comes from ~194
The country packs this installation holds, with their version, how much anyone has read them, and the register of texts each was built from — the title, the official publisher, an absolute link and the day somebody opened it, per text. Use it whenever you are asked where a rate, a chart of accounts or a box of the declaration comes from, and before repeating a figure a pack gave you: a community pack has not been read by an accountant, and the status says so. The article behind a single rule is on that rule itself — legal_reference on a tax or on a box — and the register is where that article can be read. It carries no copy of the law: a link that has gone quiet means the register is stale, never that the rule is wrong.
| Name | Type | Req | Description |
|---|---|---|---|
| country | string | – | ISO 3166-1 alpha-2, upper case. Left out, every pack this installation holds. |
No output schema declared.
No examples provided.
ec_sales_list Recapitulative statement of intra-Community supplies ~268
Who, in another Member State, was supplied without VAT over a period, and for how much: one line per customer VAT number and per nature — goods, services — read from the treatment of the tax on each sale line, with credit notes deducted. The totals tie back to the intra-Community boxes of vat_return for the same period. A line that carries an issue cannot be filed as it stands, most often because the customer has no VAT number recorded: say so rather than leaving it out of the answer. Name a report_code to have the period checked against the cadence this company files that statement on — it has one of its own, and it is rarely the cadence of the return. No country rule lives in this tool. It prepares a statement; it files nothing.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| from | string | yes | – |
| report_code | string | – | Which recapitulative statement form, when the installation carries one and you are filing it. Name it and the period is checked against the cadence this company files that statement on, which is not… |
| to | string | yes | – |
No output schema declared.
No examples provided.
financial_statement Financial statement ~181
A balance sheet or an income statement for a period, on the scheme the country pack declares — the Belgian abbreviated model, the French liasse — or on the generic framework by account type. Each line is summed from the accounts its rules catch and the totals are derived from the lines; no country rule lives in this tool. It also returns the accounts no line catches: if that list is not empty, say so instead of presenting a statement that does not tie out. It prepares figures; it files nothing.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| from | string | yes | – |
| statement_code | string | yes | Which scheme, from list_statements (BE-BNB-ABBR-BS, FR-2050, IFRS-SME-BS). |
| to | string | yes | – |
No output schema declared.
No examples provided.
general_ledger General ledger ~137
Every posted line of an account over a period, with the balance carried forward from before it and a running balance. Give account_code for one account; leave it out for all of them, which on a real company is a lot of lines.
| Name | Type | Req | Description |
|---|---|---|---|
| account_code | string | – | The account to detail, by its code, e.g. "400000". |
| account_ids | array | – | The accounts to detail, by id. Leave both out for every account. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| from | string | yes | – |
| to | string | yes | – |
No output schema declared.
No examples provided.
generate_fec Generate the French FEC ~118
The Fichier des Écritures Comptables for a period: the eighteen columns of the arrêté du 29 juillet 2013, as text, with the checks a tax inspector applies first (mandatory fields, one side per line, entries balancing) and the filename the format wants. The file comes back in the answer; writing it to disk is the caller's business.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| from | string | yes | – |
| to | string | yes | – |
No output schema declared.
No examples provided.
get_company Company settings ~90
Everything needed before booking in a company: its financial years and whether they are closed, its lock dates, its journals, and the accounts that play the receivable, payable, suspense and retained-earnings roles. Read this before creating a document if you do not already know the journals and the lock dates.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
No output schema declared.
No examples provided.
get_document Read a document ~91
One document with its lines, the account and tax of each line, the legal mentions its country requires on it, that country's payment and e-invoicing rules, and — when it has been posted — the ledger entry it produced with every ledger line. Use it to check what a document will book, what it did book, and what has to be printed on it.
| Name | Type | Req | Description |
|---|---|---|---|
| document_id | string | yes | – |
No output schema declared.
No examples provided.
get_preferences What this user prefers ~120
The signed-in user’s own preferences — which company an interface opens on, the language they read labels in, their timezone and how they like a date and a number written — and the language chain to read labels with: theirs, then the company’s, then the country pack’s. Every one of them may be null, and null means "take the next answer in the chain" rather than a default this installation picked.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | – | Resolve the language chain against this company. Left out, only what the user themselves chose is returned. |
No output schema declared.
No examples provided.
import_bank_statement Import a bank statement ~481
Reads a bank statement file and writes its statements and lines. `format` says what the file is — `camt.053` (the ISO 20022 XML statement), `coda` or `cfonb120`, which are the ones this server reads today — and `content` is the file as text. It is never guessed from the content. It books nothing: every line waits as pending, to be settled afterwards. Safe to repeat: the same file imported twice creates nothing the second time, and a statement overlapping an earlier one imports only the new lines. Refused by name, with nothing written: an account the company does not have (create it first with create_bank_account — an import never creates one), a statement whose opening balance plus lines is not its closing balance, a line in another currency. Signalled in `warnings`, not refused: an opening balance that is not the previous closing one, which means a statement is missing.
| Name | Type | Req | Description |
|---|---|---|---|
| bank_account_id | string | – | Only for a file of one statement whose account the company identifies otherwise than the file does. Left out, the account is found by the identifier the statement carries, and an unknown one is refus… |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| content | string | yes | The file itself, as text (UTF-8). |
| file_name | string | – | The name the file had, kept on the statement. |
| format | string | yes | What the file is. Required, and never guessed from the content: `camt.053` is the ISO 20022 XML statement, `coda` the coded statement of account of 128-character records, `cfonb120` the statement of… |
| iban_country | string | – | Only for `cfonb120`, which identifies an account by a bank code, a branch code and a number, and names no country. With the two letters of the country the account is held in, the statement is matched… |
| storage_path | string | – | Where the caller stored the file, if it did. With it the file is recorded in attachments, on the statement; this server stores no bytes. |
No output schema declared.
No examples provided.
import_books Import books from another system ~985
Takes over the books a user kept elsewhere — a FEC, an export of journal items, a journal report, a trial balance, or the export of odoo or xero by name — whole or not at all. Each file is read by the reader of its source; every account of the old chart is matched to one of this company's chart and every old journal to a journal of the company. The codes give a candidate (the same code, the same digits without the padding zeros, or the longest beginning of three digits or more), and what the files say of the old account — its type, its name, the side of its balance — is held against what the chart says the candidate is, never a country: only the same code, not contradicted, is `exact`; anything else is `suggested` with its reason, or `none`. Call it with dry_run first: it returns the correspondence proposed, the suggestions under mapping.suggested, what is unanswered, and — when everything is answered — what the database would write, rehearsed and rolled back. Show the user every suggested line and its reason first; nothing is posted while one is unconfirmed. Settle each by writing its code under mapping.accounts, or, once the user has read and approved them all, pass accept_suggestions. Every entry is posted through post_entry(); a trial balance becomes the opening entry. Imported lines carry no tax and feed no VAT box. The same files twice are refused. The files travel as text, up to 256 KiB in all: a larger export is imported from the terminal with `ekwo import`, which reads it from the disk. Ask the user before the real call.
| Name | Type | Req | Description |
|---|---|---|---|
| accept_suggestions | boolean | – | Take every account the proposal only suggested as the answer. Only after the user has read each suggested line and its reason, and said yes to all of them; left out, a suggestion stops the import. |
| allow_result_accounts | boolean | – | Let an opening balance carry income and expense accounts: books taken over in the middle of a year. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| date_order | string | – | For `journal-report`: the order of a date written only in digits, which the file does not say. |
| dry_run | boolean | – | Show what would be written — the correspondence proposed, the entries, the numbers — and write nothing. Always first, and the user reads it before the real call. |
| files | array | yes | The files of one source, in the order given. `journal-items` and `journal-report` take the chart of accounts and the parties beside the lines, each recognised by its header; the others take one file. |
| keep_numbers | boolean | – | Post each entry under the number it had. Where the country forbids a hole in the sequence it takes the entries.import capability; left out, the journal draws the numbers and the old one is kept as th… |
| mapping | object | – | The correspondence, as a previous call with dry_run returned it and the user completed it. What it answers wins over the proposal. |
| open_years | boolean | – | Open the fiscal years the entries fall in where the company has none, on the length and first day of its own. Off, such an entry is refused by name. |
| opening_date | string | – | For a trial balance: the first day of the fiscal year it opens. The file does not say it. |
| source | string | yes | What the files are, never guessed from their content: `trial-balance` — a trial balance as CSV — account, debit, credit, or a signed balance — which becomes the opening entry of a year; `fec` — a fic… |
No output schema declared.
No examples provided.
invite_member Invite somebody into a company ~241
Invites an address into a company with a preset — viewer reads, client reads and hands pieces over, accountant keeps the books, owner also administers — and any capability granted on top of it. It returns a token once and stores only its hash, so hand the token to the person you invited: they accept it themselves, signed in with that address. It does not send an e-mail, and it does not create an account. Inviting the same address again withdraws the invitation that was pending.
| Name | Type | Req | Description |
|---|---|---|---|
| capabilities | array | – | Capability codes granted on top of the preset, e.g. members.manage. get_company lists what this installation knows. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| string | yes | The address the invitation is for. Matched when it is accepted. | |
| role | string | – | The preset. Default viewer, which reads and changes nothing. client is the person whose company it is, invited by whoever keeps their books: it reads the same, and may also hand a file over (document… |
| valid_for_days | integer | – | Default 14. |
No output schema declared.
No examples provided.
list_accounts Chart of accounts ~352
The accounts a company actually works with, filtered by code prefix, by account type, or by a search on the name. Use it to find the income or expense account a document line should carry. By default it returns the working chart — the accounts that carry entries, that the company's settings or an enabled module point at, or that somebody pinned — because a country pack transcribes the whole regulation and a company uses a few dozen of its several hundred accounts; `in_use_from` and `in_use_to` narrow the movements to a period, `include_all` returns the whole chart, and `include_deprecated` returns it with the retired accounts too. This is a reading and not a restriction: any account of the chart that is not deprecated may still be booked on.
| Name | Type | Req | Description |
|---|---|---|---|
| account_type | string | – | One of the eighteen account types, e.g. asset_receivable. |
| code_prefix | string | – | Only accounts whose code starts with this, e.g. "70". |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| in_use_from | string | – | Narrows the movements to entries on or after this date. References and pinned accounts are not dated and stay in. |
| in_use_to | string | – | The other end of that period. |
| include_all | boolean | – | Return the whole chart instead of the accounts in use. Use it when a search over the working chart found nothing. |
| include_deprecated | boolean | – | Include deprecated accounts. A deprecated account is never in use, so this returns the whole chart. |
| limit | integer | – | – |
| search | string | – | Case-insensitive match on the account name. |
No output schema declared.
No examples provided.
list_api_keys Machine keys of a company ~101
The keys a company has issued to machines, what each one may do, when it was last used and whether it is still live. Only somebody who manages members sees them, and no secret is in here: a key is shown once, when it is issued.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| include_withdrawn | boolean | – | Also the ones withdrawn or expired. Default false. |
No output schema declared.
No examples provided.
list_bank_accounts Bank accounts ~87
The bank accounts of a company, with their IBAN, the journal they book through and the ledger account behind each. Read it before recording a payment on a particular account, and to find out whether the company has one at all.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| include_inactive | boolean | – | Default false. |
No output schema declared.
No examples provided.
list_bank_transactions Bank transactions ~124
Statement lines of a company, pending by default — the ones still waiting to be dealt with. `amount` is signed: positive is money in. A statement line is not a ledger entry; recording a payment is what books it.
| Name | Type | Req | Description |
|---|---|---|---|
| bank_account_id | string | – | – |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| from | string | – | – |
| limit | integer | – | – |
| state | string | – | Defaults to pending: what still has to be dealt with. |
| to | string | – | – |
No output schema declared.
No examples provided.
list_companies List companies ~68
The companies of this installation that you are a member of, with your role on each. Start here: every other tool needs a company_id. Returns id, name, country, currency and your role. It does not list companies you were never invited to — those are invisible, not hidden.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_documents List documents ~180
Invoices, credit notes and quotes of a company, filtered by type, state, settlement state, contact or date range. `state` is the document (draft, posted, cancelled) and `payment_state` is the settlement (not_paid, partially_paid, paid) — two different questions. Returns headers and totals, not lines; use get_document for those.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| contact_id | string | – | – |
| doc_type | string | – | – |
| from | string | – | Earliest document date. |
| limit | integer | – | – |
| payment_state | string | – | – |
| state | string | – | – |
| to | string | – | Latest document date. |
| unpaid | boolean | – | True: posted and still owed — not paid, or partially. |
No output schema declared.
No examples provided.
list_invitations Invitations into a company ~114
The people invited into a company and not yet on its books, with the preset and the capabilities each was invited with, and whether the invitation is still pending, expired, accepted or withdrawn. Only somebody who manages members sees them. The token is never in here: it is shown once, when the invitation is issued.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| include_settled | boolean | – | Also the ones already accepted or withdrawn. Default false. |
No output schema declared.
No examples provided.
list_shares Public links onto documents ~132
The links a company has published onto its own sales documents, with how many times each was opened and when it was last opened. No token is in here: a link is shown once, when it is made. Use it to answer "did the customer open the invoice?" and to find the link to withdraw.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| document_id | string | – | Only the links onto this document. Left out, the whole company. |
| include_withdrawn | boolean | – | Also the ones withdrawn or expired. Default false. |
No output schema declared.
No examples provided.
list_statements List financial statements ~92
The schemes this company can be presented on: those of its country and of its chart of accounts, plus the generic framework by account type that fits any chart. Ask this before financial_statement rather than guessing a code.
| Name | Type | Req | Description |
|---|---|---|---|
| at | string | – | The day to read the schemes in force at. Defaults to today. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
No output schema declared.
No examples provided.
lock_period Lock a period ~135
Moves the accounting lock date, the VAT lock date, or both. After this, nothing can be booked, changed or deleted on or before that date — including corrections you may want later. Only an owner of the company may do it. Always ask the user first, and never lock a period you have just posted into without being told to.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| lock_date | – | – | Nothing may be booked on or before this date. null lifts the lock. |
| tax_lock_date | – | – | Additionally freezes anything carrying a VAT box. null lifts it. |
No output schema declared.
No examples provided.
opening_balance Import an opening balance ~204
Turns the trial balance of whatever kept the books before into the opening entry of a fiscal year, on the opening journal, dated on its first day. Lines are {account_code, debit, credit}; total debit must equal total credit. Balance-sheet accounts only, unless allow_result_accounts is set, which is for taking books over in the middle of a year. A year holds one opening: a second call is refused rather than added to.
| Name | Type | Req | Description |
|---|---|---|---|
| allow_result_accounts | boolean | – | Default false: an opening balance is made of the balance sheet. Pass true only when taking books over in the middle of a year that has already run. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| fiscal_year_id | string | yes | The year the balance opens. The entry is dated on its first day. |
| lines | array | yes | The trial balance of the previous system, one entry per row. Total debit must equal total credit. |
No output schema declared.
No examples provided.
pin_accounts Pin accounts to the working chart ~133
Adds accounts to the working chart of a company, so list_accounts offers them whether or not anything has been booked on them. Pass pinned: false to take one back out. Pinning is display and nothing else: an unpinned account may still be booked on, and a pinned one is still hidden once it is deprecated.
| Name | Type | Req | Description |
|---|---|---|---|
| account_codes | array | yes | Codes in this company's chart. list_accounts with include_all says what exists. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| pinned | boolean | – | True pins, false unpins. Defaults to true. |
No output schema declared.
No examples provided.
portfolio_filings_touched_since Declared periods that moved, across your companies ~157
Which declarations, across your portfolio — every company you may read the declarations of, which for an accounting firm is its clients — had entries posted into their period after they were filed — with the company named, how many entries, and how many of the filed figures now disagree. A period stays open after its return has gone, on purpose; this is what keeps a late entry from going unnoticed. Companies with nothing to report are named too, with how many filed declarations were examined. It reads; whether a corrective is owed is for whoever keeps the books.
| Name | Type | Req | Description |
|---|---|---|---|
| from | string | – | Only declarations whose period ends on or after this day. |
| to | string | – | Only declarations whose period starts on or before this day. |
No output schema declared.
No examples provided.
portfolio_upcoming_filings Returns falling due, across your companies ~201
What falls due between two dates in every company you may read the declarations of — the question a firm asks of all the books it keeps, and the one a person asks of the single company they run. "Portfolio" is meant as an accounting firm means it — its client portfolio — and is nothing but that: the companies you hold filings.read on, worked out at each call, never a list anybody maintains. Every one of them is in the answer, including a company whose country pack names no deadline, which is listed without a date and says so; a company left out would be indistinguishable from one that was never looked at. No country rule lives in this tool. It reads a calendar; it prepares and files nothing.
| Name | Type | Req | Description |
|---|---|---|---|
| from | string | yes | First day a return may fall due on. Go back a few days to catch what is already late. |
| to | string | yes | Last day a return may fall due on. |
No output schema declared.
No examples provided.
post_document Post a document to the ledger ~156
Books a draft document: base lines, VAT lines from the tax configuration, and the customer or supplier counterpart, numbered and posted. A posted entry is never edited; a mistake is undone by cancel_document, which puts the document back to draft only where its country allows it and nothing has left, and issues a credit note otherwise. Ask the user before calling it. It refuses a locked period, a tax that is not in force, and a header total that disagrees with the lines.
| Name | Type | Req | Description |
|---|---|---|---|
| document_id | string | yes | – |
| dry_run | boolean | – | True: the database posts for real and takes it back, and the entry it would have written is returned. Nothing is written; a refusal is the one posting would give. |
No output schema declared.
No examples provided.
read_audit_log Audit trail ~400
Who changed what, and when. Every change to the configuration and reference data of a company — the chart of accounts, the journals, the taxes and the accounts they post to, the bank accounts, the contacts, the products, the financial years, the members and their roles, the country pack version — and every act that changes a state: a document posted or cancelled, an entry posted or reversed, a payment booked, matched or unmatched, a financial year closed or reopened. Filter by table, by natural key, by user, by act, or by date range. The ledger itself is not in here: a posted entry is immutable and is corrected by a reversal, so what is recorded is the act of posting and never the lines. Read-only, and there is no tool that writes it: the trail is append-only and even the operator cannot edit a row.
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | – | One act: document_posted, document_cancelled, entry_posted, entry_reversed, payment_posted, payment_reconciled, payment_unreconciled, fiscal_year_closed, fiscal_year_reopened, pack_upgraded. |
| actor_id | string | – | Only what this user changed. Their auth.users id. |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| from | string | – | Earliest date, inclusive. |
| limit | integer | – | – |
| operation | string | – | – |
| record_key | string | – | The natural key of one row — an account code, a tax code, an invoice number. |
| table | string | – | One table of the schema: accounts, journals, taxes, tax_postings, contacts, products, bank_accounts, companies, fiscal_years, company_members, company_packs, api_keys, documents, payments, entries, r… |
| to | string | – | Latest date, inclusive — the whole of that day. |
No output schema declared.
No examples provided.
reconcile Match two ledger lines ~130
Matches a debit line against a credit line on the same reconcilable account, for an amount, defaulting to the smaller of the two open amounts. Use it to settle an invoice against a payment by hand. Matching changes no account and stays possible after a period is locked.
| Name | Type | Req | Description |
|---|---|---|---|
| amount | string|number | – | Left out: the smaller of the two open amounts. |
| line_a | string | yes | A ledger line to match. Either side; the schema works out which is the debit. |
| line_b | string | yes | The line it settles. Both must be on the same reconcilable account. |
No output schema declared.
No examples provided.
record_payment Record a payment ~477
Records money in or out, books it (bank against the customer or supplier account) and, unless you say otherwise, matches it against that contact's oldest open invoices up to the amount paid. Matching is what makes an invoice count as paid. The entry it produces cannot be unposted, though the matching can be undone with unreconcile.
| Name | Type | Req | Description |
|---|---|---|---|
| amount | string|number | yes | A positive decimal string; the direction carries the sign. |
| bank_account_id | string | – | Which bank account the money moved on. list_bank_accounts says what exists. Given alone, it also names the journal; left out, the default account of the journal is used. |
| client_ref | string | – | Your own reference for this creation. Calling again with the same one returns what was created the first time (`replayed: true`) instead of creating a second — use it whenever a call might be repeate… |
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| contact_id | string | – | Who paid or was paid. Needed for the payment to be matched against their invoices. |
| currency_code | string | – | Left out: the currency the company keeps its books in. |
| direction | string | – | inbound: a customer paid you. outbound: you paid a supplier. May be left out when document_id is given. |
| document_id | string | – | The posted document this money pays. It names the contact and the direction, read off what is still open on it, and the matching is offered to that document alone rather than to the oldest open items. |
| exchange_rate | string|number | – | Units of the payment currency for one unit of the company currency, as a rate table states it. Only needed when the payment is in another currency; the realised difference against the invoice is book… |
| journal_code | string | – | The bank or cash journal, by code, e.g. BNK. Not needed when bank_account_id is given: the account knows its journal. |
| journal_id | string | – | – |
| match_open_items | boolean | – | Default true: match the payment against the oldest open invoices of that contact, up to the amount paid. |
| memo | string | – | – |
| payment_date | string | yes | – |
| reference | string | – | – |
No output schema declared.
No examples provided.
reopen_fiscal_year Re-open a closed fiscal year ~86
Undoes a close that was run too early: the entries it wrote are reversed, never deleted, and the year accepts entries again. Refused once a later year is closed or holds entries of its own, because re-opening changes a result those years stand on. Always ask the user before calling it.
| Name | Type | Req | Description |
|---|---|---|---|
| fiscal_year_id | string | yes | The closed year to open again. |
No output schema declared.
No examples provided.
reverse_entry Reverse a posted entry ~265
Undoes a posted entry in one call: writes its mirror in the same journal — every line on the other side — naming it, posts it under the next number, and matches the two. The original keeps its number and its lines. Dated on the original's day unless you give a date; refused by name when that period is locked or closed (reversal_date_needed), and then you ask the user for a date rather than choosing one. Refused for an entry a document wrote (use cancel_document), the entries of a close (reopen_fiscal_year), an opening, the entry of a payment, a bank transaction, a module or a matching, an entry already reversed or that is itself a reversal, and a matched entry — unmatch it first with unreconcile, and only when the user says so. Ask the user before calling it.
| Name | Type | Req | Description |
|---|---|---|---|
| date | string | – | The day the reversal is booked on. Left out: the original entry's day, and refused by name (reversal_date_needed) when that period is no longer open — then ask the user which open date to use; never… |
| entry_id | string | yes | The posted entry to undo. An entry a document wrote is undone with the document, by cancel_document. |
No output schema declared.
No examples provided.
revoke_api_key Withdraw a machine key ~68
Stops a key working, now and for good. There is no un-withdraw: a secret that has been out of the building is issued again rather than brought back. Whatever the machine was doing with it stops, so say so before calling it.
| Name | Type | Req | Description |
|---|---|---|---|
| api_key_id | string | yes | – |
No output schema declared.
No examples provided.
revoke_invitation Withdraw an invitation ~64
Withdraws an invitation that has not been accepted, so its token stops working. An invitation that has already become a membership is refused: a member is removed from the company, which is a different act and not one this server does.
| Name | Type | Req | Description |
|---|---|---|---|
| invitation_id | string | yes | – |
No output schema declared.
No examples provided.
revoke_share Withdraw a published link ~73
Stops a link working, now and for good. Whoever holds it sees exactly what they would see for a link that never existed. There is no un-withdraw: a secret that has been out of the building is issued again rather than brought back, so say so before calling it.
| Name | Type | Req | Description |
|---|---|---|---|
| share_id | string | yes | – |
No output schema declared.
No examples provided.
search_contacts Find a contact ~128
Customers, suppliers and other third parties of a company, by name, by type or by VAT number. Use it before creating a document: a document is booked against a contact, and creating a second contact for a customer who already exists splits their account.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| contact_type | string | – | – |
| limit | integer | – | – |
| query | string | – | Case-insensitive match on the contact name. |
| vat_number | string | – | Exact match, e.g. BE0123456749. |
No output schema declared.
No examples provided.
search_products Find a product ~155
The catalogue of a company: what it sells and buys, with the code, the unit, the price, the account each books to and the tax each carries. Search it before writing a line by hand — a product fills in the text, the price, the account and the tax, and keeps two invoices for the same thing consistent. Retired products are left out unless you ask for them.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| include_inactive | boolean | – | Default false: a retired product is hidden. |
| kind | string | – | – |
| limit | integer | – | – |
| query | string | – | Matches the code, the name or the description. |
No output schema declared.
No examples provided.
set_preferences Change what this user prefers ~168
Writes the signed-in user’s own preferences and nobody else’s. Only the fields you name change: leave one out and it is untouched, pass null and it is cleared, which puts that question back to the company and then to the country pack. It changes nothing in the books.
| Name | Type | Req | Description |
|---|---|---|---|
| date_display_format | string|null | – | How this person likes a date written. |
| language | string|null | – | Two letters, optionally a region. Labels are read in it first. |
| number_display_format | string|null | – | How this person likes a number written. Not the pattern a document number is built from, which belongs to the country. |
| preferred_company_id | – | – | The company to open on. |
| theme | string|null | – | – |
| timezone | string|null | – | An IANA name. |
No output schema declared.
No examples provided.
share_document Publish a document behind a link ~186
Publishes a posted sales invoice, credit note or quote behind a link the customer opens without an account and without a password: the token in the url is the whole secret. It returns that token once and stores only its hash, so give the url to the customer and say it cannot be read back. The page shows the document as it was sent and what is still owed on it today, so the link stays worth opening after a payment. A purchase document is refused — it is a third party’s own document — and so is a draft. A link is never edited: to change when it expires, withdraw it and make another.
| Name | Type | Req | Description |
|---|---|---|---|
| document_id | string | yes | The sales document to publish. A purchase document and a draft are refused. |
| expires_at | string|null | – | When the link stops answering, as a timestamp. Left out, it answers until it is withdrawn. |
No output schema declared.
No examples provided.
status Installation status ~61
The schema version, the instance this is, how this server is connected and as whom, and the companies you can see. Use it first when something does not add up — an empty company list usually means the user was never invited rather than that the books are empty.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
trial_balance Trial balance ~86
Opening balance, movements of the period and closing balance for every account, from posted entries only. The debit and credit totals are equal on a healthy ledger; if they are not, say so rather than explaining it away.
| Name | Type | Req | Description |
|---|---|---|---|
| company_id | string | yes | The company to work in. Ask list_companies if unsure. |
| from | string | yes | – |
| to | string | yes | – |
No output schema declared.
No examples provided.
What is the Ekwo OS MCP server?
Ekwo OS is an MCP server listed in the public MCP registry as ai.ekwo/mcp. Open source accounting data infrastructure on your own Postgres, acting as the user under RLS. This page covers its npm package (@ekwo-ai/mcp).
Is the Ekwo OS MCP server safe to use?
Ekwo OS scores 72 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 25 September 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Ekwo OS MCP server expose?
Ekwo OS exposes 55 tools: list_companies, get_company, list_accounts, search_contacts, list_documents, and 50 more. Their descriptions and schemas cost roughly 11,053 tokens of context every time the server is loaded.
Is the Ekwo OS MCP server still maintained?
Ekwo OS is still listed as active in the MCP registry. We last reached this channel on 25 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Ekwo OS MCP server under?
Ekwo OS declares the AGPL-3.0-only licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.