MCPInstall
Ekwo OS — open source accounting: ledger, invoices and VAT on your own Supabase or Postgres logo

Ekwo OS — open source accounting: ledger, invoices and VAT on your own Supabase or Postgres

by Ekwo-ai 40 stars ekwo-ai/ekwo-os

Double-entry books an agent keeps as the user: invoices, VAT returns, 174 country packs.

READMEHEAD

@ekwo-ai/mcp

The Model Context Protocol server for Ekwo OS. It lets an AI agent work on the books in your own Postgres: read the ledger, raise an invoice, post it, match a payment, prepare the VAT return — as you, under the row level security of your own installation.

There are two ways to reach it, and they are the same server.

Hosted, at https://mcp.ekwo.ai/mcp

For a client that adds remote servers rather than launching them — claude.ai, or any other that speaks Streamable HTTP. Nothing is installed, and no password or key is written into a configuration file.

https://mcp.ekwo.ai/mcp

Point a client at that address and it discovers the rest. An unauthenticated call is answered with 401 and a WWW-Authenticate header naming the server's protected-resource metadata (RFC 9728); the client follows it to the authorization server (RFC 8414), registers itself (RFC 7591, so it needs no credentials of its own) and sends the person to their browser to approve the connection. The scope asked for is books.

An agent reading this without a browser can start from /.well-known/oauth-protected-resource.

The books stay where they are: the hosted server holds none, and connects to the instance the person chooses when they approve it. On the same screen they decide whether the agent may write; otherwise it reads. The hosted server is operated by Ekwo Cloud, and signing in there needs an account — a free one, opened with an address and a six-digit code, which also gives the web application on the same books and a nightly backup of every company it links.

Locally, over stdio

npx -y @ekwo-ai/mcp@latest

For a client that launches its own servers — Claude Desktop, Claude Code, any editor that reads .mcp.json — against any installation, with no account. Keep @latest in the command: from inside a clone of the repository, a bare npx @ekwo-ai/mcp finds the unbuilt workspace package and answers ekwo-mcp: command not found.

With the command line installed, ekwo mcp starts the same server — the same entry point, runStdio(), the same flags (--autopilot, --review) and the same environment: "command": "ekwo", "args": ["mcp"].

What it is, and what it is not

The server holds no privileges of its own. It signs in as the person using it, or is handed their access token, and everything it can do afterwards is exactly what that person can do: a viewer reads and cannot write, a member of one company cannot see another, a locked period refuses a posting. None of that is checked in this package — the policies and the triggers in the schema decide, and this server reports what they answered.

Three things it will never do:

  • Write a ledger line. Every entry comes out of the schema's own functions, which carry the accounting rules. Direct inserts are for the objects a person types: contacts, draft documents and their lines, payments, bank transactions.
  • Delete or edit a posted entry. No tool removes one. A posted invoice is undone the one way its country allows — back to draft where nothing about it has left, otherwise by the credit note that names it — and an entry keyed by hand by its reversal.
  • Use a service_role key. It would work, and that is the objection: it bypasses every policy, so the agent would answer for companies its user was never invited to. The server refuses to start with one.

Configuration

The recommended route: PostgREST, as the signed-in user

{
  "mcpServers": {
    "ekwo": {
      "command": "npx",
      "args": ["-y", "@ekwo-ai/mcp@latest"],
      "env": {
        "SUPABASE_URL": "https://YOURREF.supabase.co",
        "SUPABASE_ANON_KEY": "your anon (publishable) key",
        "EKWO_EMAIL": "you@example.com",
        "EKWO_PASSWORD": "your password"
      }
    }
  }
}

That block goes in claude_desktop_config.json for Claude Desktop, or in .mcp.json at the root of a project for Claude Code. EKWO_ACCESS_TOKEN replaces the address and the password when you already hold a session; with the password, the session is kept in memory and refreshed, and nothing is written to disk.

The fallback: a direct Postgres connection

For a self-hosted installation with no PostgREST in front of the database, or for tests.

{
  "env": {
    "EKWO_DB_URL": "postgresql://…",
    "EKWO_ACT_AS_USER_ID": "the auth.users id this server acts for"
  }
}

EKWO_ACT_AS_USER_ID is required, and that is the whole point of this mode. A database connection is nobody: auth.uid() is null, row level security is bypassed rather than satisfied, and a server running that way would be a way round the policies rather than a client of them. So every query runs inside a transaction that sets request.jwt.claims to that user and switches to the authenticated role, and the policies bind exactly as they do over the API. This mode needs the postgres package installed alongside the server; the recommended route needs no driver at all.

VariableMeaning
SUPABASE_URLhttps://<ref>.supabase.co
SUPABASE_ANON_KEYThe anon (publishable) key. A service_role key is refused.
EKWO_EMAIL / EKWO_PASSWORDThe user this agent acts as
EKWO_ACCESS_TOKENA session already in hand, instead of the two above
EKWO_DB_URLA direct Postgres connection, for a self-hosted installation
EKWO_ACT_AS_USER_IDRequired with EKWO_DB_URL: the auth.users id to act for
EKWO_NO_REGISTER_INVITEOptional. 1 leaves the invitation to register out of the instructions
EKWO_NO_CLOUD_OFFEROptional. 1 leaves the offer of a free Ekwo Cloud account out of the instructions; so does CI
EKWO_AGENT_POSTINGOptional. autopilot or review: how this session posts, as --autopilot and --review choose it. Unset, each company's agent_posting decides. See Review or autopilot
EKWO_EINVOICE_DIRECTORYOptional. The folder electronic invoices are sent to by einvoicing_issue with send. Unset, files are issued and kept, and sending is refused as no_transport
EKWO_FISCAL_SYSTEMOptional. The invoicing system einvoicing_fiscalise chains fiscal records under, as JSON: name, id, version, installation, producerName, producerTaxId, and the booleans a regime may ask (verifactuOnly, multipleTaxpayers, multipleTaxpayersNow). Unset, fiscalising is refused as no_fiscal_system; malformed, the server does not start

Started with nothing set

A client lists a server's tools as soon as it is added, and so do the directories that index MCP servers. So with none of the variables above — or with half of them — the server still starts, still answers the list of tools, and every tool call returns a not_configured error that names the variables to set and where. It connects nowhere until then, and it offers the tools of the socle only: which modules an installation carries is read from its database.

Only absence is forgiven. A service_role key, in either slot, and an EKWO_ACT_AS_USER_ID that is not a uuid are values somebody wrote, and the server still refuses to start with them.

npm run build -w @ekwo-ai/mcp
node packages/mcp/scripts/introspect.mjs     # starts it with no environment and lists the tools

The Dockerfile at the root of the repository builds the same server from the checkout; docker run -i --rm <image> speaks MCP over stdio, with the variables passed as -e.

Over HTTP: hosting it for others

The same server, reached by URL instead of started by a client: handleHttpRequest answers the Streamable HTTP transport of MCP. It is stateless — each request builds a server, answers in JSON and closes it, with no session id and nothing kept — so it runs on a function platform, behind a load balancer, or in one process. A GET is answered 405: this server never speaks first, so there is no stream to open.

It does not decide who is calling: the host authenticates the request its own way, then hands in the connection that request may use.

import { handleHttpRequest } from '@ekwo-ai/mcp';

export default async function (request: Request): Promise<Response> {
  const who = await yourOwnAuthentication(request);      // a token you issued
  if (who === undefined) return new Response(null, { status: 401 });
  return handleHttpRequest(request, {
    supabaseUrl: who.supabaseUrl,                         // https://<ref>.supabase.co
    anonKey: who.publishableKey,                          // never the service_role key
    apiKey: who.ekwoKey,                                  // or: accessToken: who.session
  });
}

A connection is one of two things, never both:

  • A person's access token on the instance. Row level security decides, exactly as for that person in a browser.
  • A key of Ekwo OS, as create_api_key() issues it. It travels in the X-Ekwo-Api-Key header with no Authorization beside it, the schema's pre-request hook presents it (decision 0062), and the caller is on that key's one company with that key's capabilities. A key issued without a capability that writes gives an agent that reads.

A service_role key is refused in all three slots, as on stdio. For node:http (or anything built on it), handleNodeRequest(req, res, connection, { origin }) is the same handler.

Putting it in front of people: authorization

A remote MCP client expects the server to follow the authorization part of the MCP specification: OAuth 2.1 with PKCE, protected resource metadata (RFC 9728), authorization server metadata (RFC 8414) and dynamic client registration (RFC 7591). That belongs to the host, not to this package: the host signs the person in, issues its own tokens, and maps each one to a connection above. The database stays the only place that decides what may be read or written.

The tools

Every write names its company explicitly.

ToolWhat it does
list_companiesThe companies you are a member of, with your role on each
get_companyFinancial years, lock dates, journals, default accounts
list_accountsThe accounts a company works with, by code prefix, type or name. include_all for the whole chart
search_contactsCustomers and suppliers, by name, type or VAT number
suggest_duplicate_contactsThe contacts that are probably one party, strongest first, one row per contact to absorb — the rows of one kept contact being one party: the contact to keep, a score, the evidence (the same VAT or registration number, the same bank account, the words of the name weighed by how few contacts carry them) and the simplest name the group carries, proposed for the kept contact. Writes nothing; merge_contacts joins a pair the user confirms
search_productsThe catalogue: code, unit, price, account and tax of what is sold and bought
list_documentsInvoices, credit notes and quotes, filtered
get_documentOne document with its lines and the entry it produced
render_invoice_pdfThe PDF of a sale invoice or credit note, as a PDF resource (base64) beside a JSON summary, rendered from the books by @ekwo-ai/invoice-pdf. factur_x embeds the CII of a posted sale (Factur-X, EN 16931, PDF/A-3) and returns the rules it breaks; labels gives the words of the layout in the document's language. The logo is fetched by the server from the company's logo_url, never from a local or private address. Records nothing
list_bank_accountsThe bank accounts of a company, with the journal and ledger account behind each
list_bank_transactionsStatement lines, pending by default
trial_balanceOpening, movements and closing per account
general_ledgerEvery posted line of an account, with a running balance
journal_bookThe book of one journal, or of all of them: every posted line of the period in the order a book is read, with the totals of each journal at the head
suggest_line_contactsThe contacts an open receivable or payable line that names nobody could be, best first, each with its evidence and how many contacts that evidence reached. Writes nothing
suggest_item_combinationsFor each open receivable or payable line of one counterparty, the lines of the other side that settle it: an exact pair, several lines to the cent, or within the company's difference tolerance, with the difference. Writes nothing
matching_difference_optionsThe reasons a difference may be booked for, with the account the pack gives for each, and the company's tolerance
aged_balanceWhat is still owed, bucketed by age, read from the ledger
vat_returnThe boxes for a period, summed from the ledger
instalment_planThe payments on account the VAT scheme of a company asks for in a period: due, paid, outstanding
ec_sales_listThe recapitulative statement of European Union supplies: one line per customer VAT number and per nature
portfolio_upcoming_filingsPortfolio = the companies you may read: for an accounting firm, its clients (docs/firms.md). What falls due between two dates in every company you hold filings.read on. One row per company at least: a pack that names no deadline is listed without a date, and says so
portfolio_filings_touched_sinceDeclarations that have gone and whose period received entries afterwards, across the same companies, with the company named
list_statements / financial_statementThe schemes a company can be presented on, and one statement
financial_analysisRevenue, net result, equity, total and current assets, cash, receivables, payables and the other aggregates of an analysis, each with the accounts that make it, as the country pack defines them, or read by account type through the generic framework where it defines none — source says which (docs/analysis.md)
list_analytic_axesThe analytic axes of a company — a cost centre, a project, a site — and the values of each, which may nest, with required_on, the lines that must carry the axis whole at posting
analytic_reportThe income, expense, result and fixed-asset movement of each value of one axis over a period, from the posted ledger, the whole income statement included, a parent with the subtotal of the values below it, unassigned, the part no share of the axis reaches, and total (decision 0076)
generate_fecThe French FEC as text, with its checks and its filename, for a company that keeps French books
read_audit_logWho changed what and when: the configuration of a company, and the acts that change a state. Append-only for every client; only the database writes it
get_preferencesWhat you prefer, and the language chain to read labels with
list_invitationsWho has been invited into a company and not yet joined
list_api_keysThe machine keys of a company, and what each may do
describe_packWhich country packs this installation holds: their version, how much anyone has read them, the register of texts each was built from — title, official publisher, link and the day it was opened — and, for a proven pack, its evidence: per scope, the kind of filing, the year, what was reproduced and what was not tested
statusSchema version, instance, connection, companies
create_contactA customer, supplier or other third party
merge_contactsJoins two contacts that are one party: everything naming the absorbed one, posted lines and issued documents included, names the kept one, whose empty fields are filled; the absorbed one is retired. Refused by name for two different VAT or registration numbers, a contact merged before, or a matching that would span two parties
create_productA catalogue row: code, name, unit, price, account, tax
update_productChanges one, or retires it with active: false
pin_accountsAdds accounts to the working chart a company sees first, or takes one back out with pinned: false
create_documentA draft invoice, credit note or quote, with its lines. With client_ref, calling twice creates once
update_document_linesReplaces the lines of a draft
post_documentBooks it, in review or autopilot (below): in review, only once a person approved the draft as it stands, refused with approval_required otherwise; in autopilot, directly. dry_run: true returns the entry the database would write, and writes nothing, in both
cancel_documentUndoes a posted invoice, and says how in undone_by: back to draft where its country's posted_edit_policy allows it and nothing about it has left (unpost_document()), otherwise a credit_note that names it, posted and matched against it, and the invoice cancelled (cancel_document()), with why the draft was ruled out. A credit note is dated on the invoice's day while that period is open; otherwise the caller gives a date. A date, or credit_note: true, asks for the credit note
reverse_entryUndoes a posted entry keyed by hand: its mirror, posted under the next number and matched against it. Same rule for the date
record_paymentBooks money in or out and matches it against open invoices — or, with document_id, against that document alone, which then names the contact and the direction. With client_ref, recording twice records once
set_line_contactNames the contact of such a line, once, from nothing to a contact of the company, and learns the label as a motif. Refused by name for a line that names somebody, is matched, is not on a receivable or payable account, or a contact of another company
leave_line_unnamed / undo_leave_line_unnamedLeaves such a line without a contact on purpose, with the reason, so it is no longer suggested; or takes that back
reconcile_manyMatches several lines of one counterparty and one account together, their open debits and credits equal to the cent, under one letter
reconcile_with_differenceThe same with a small difference, booked on the account the pack gives for the reason (rounding, exchange_difference) within the company's tolerance, then matched
reconcile / unreconcileMatches two ledger lines, or undoes one matching
create_bank_accountRegisters an account from its identifier, in the scheme the company's country uses (an IBAN, a routing number and an account number, a sort code and an account number…), and wires it to the bank journal. Running it twice with the same identifier creates nothing
create_bank_transactionOne statement line by hand, for an installation with no feed
settle_from_statementBooks a statement line as the payment it is and matches it against the documents or open items named, in one entry — with amounts, how much settles each; with extra_lines, the fee a payment provider kept or the charges of a bank, on the account and with the tax the user names. The line balances to the cent or is refused (settlement_unbalanced); extra lines alone settle a bank charge
import_bank_statementA statement file (camt.053, coda, cfonb120) into statements and pending lines. Books nothing; the same file twice creates nothing; an unknown account or a statement that does not add up is refused by name, a missing statement is signalled
lock_periodMoves the accounting and VAT lock dates. Needs company.write.
opening_balanceThe trial balance of whatever kept the books before, as the opening entry — of the first day of the year, or of opening_date, the day inside it the books were taken over. items are the invoices and credit notes still open that day: each a posted document with its number, payment reference and due date, which statement matching finds like an invoice issued here; the items of an account must add up to its line
import_booksBooks kept elsewhere — a FEC, an export of journal items, a journal report, a trial balance — whole or not at all, with open_items beside a trial balance. dry_run: true first: the correspondence proposed for every account and journal — exact only for the same code the files do not contradict, otherwise suggested with its reason, or none — what has no answer, and the import rehearsed by the database and taken back. Then again with the completed mapping, or accept_suggestions once the user has read every suggestion; nothing is posted while one is unconfirmed. Every entry through post_entry(); no tax; the same files twice refused, saying when and what. The files travel as text, 256 KiB at most: beyond, the tool answers with the ekwo import command that reads them from the disk. ekwo import is the same function
close_fiscal_year / reopen_fiscal_yearCloses a year the way the country pack says — with final_close, whether the country also requires a final close and by when — or reopens it to correct it, whatever later years hold; a later closed year is reopened first
close_fiscal_year_finallyThe final close of a closed year: nobody reopens it afterwards, the operator included. Only on the user's explicit request
create_companyA company on a country pack, with its chart and its first financial year. An instance-level act
update_company_profileWhat a company says about itself on its documents, and the pattern of its document numbers
set_number_prefixWhat one journal prints in place of {CODE} in its numbers
set_preferencesYour own language, timezone, formats and default company
invite_member / revoke_invitationInvites an address into a company, or withdraws the invitation. The token is shown once
remove_member / set_member_roleTakes a member out of a company — leaving oneself needs no members.manage — or moves them to another preset, clearing their per-member adjustments. The last owner is neither removed nor demoted
create_api_key / revoke_api_keyA key for a machine, scoped to one company and a list of capabilities
share_document / list_shares / revoke_sharePublishes a posted sales document behind a link the customer opens without an account, lists the links with how often each was opened, or withdraws one (docs/sharing.md)

list_accounts answers with the working chart, not the whole one. A country pack transcribes the regulation — sometimes more than a thousand accounts — and a company works with a few dozen. The default is the accounts with posted entries, those the company's settings or an enabled module point at, and those somebody pinned with pin_accounts. include_all returns the whole chart, and every write tool still accepts any account of it.

post_document, cancel_document, reverse_entry, record_payment, update_document_lines, unreconcile, settle_from_statement, lock_period, opening_balance, import_books, close_fiscal_year, reopen_fiscal_year, close_fiscal_year_finally, revoke_invitation, remove_member, set_member_role, revoke_api_key and revoke_share are annotated destructive in the protocol, so a client can ask before calling them.

What a tool may do is the capability the user holds, not the tool's own right: the server acts as the person it signed in as, so post_document works for an accountant and is refused to a viewer, by the database, with the database's own words. get_company returns your_capabilities for exactly that reason.

The modules. A module of this installation gets its own tools, under the prefix its module.json declares, and the server reads public.modules at startup to know which: fixed_assets_list, fixed_assets_create, fixed_assets_schedule, fixed_assets_run_depreciation, fixed_assets_dispose, budgets_list, budgets_upsert_lines, budgets_variance, einvoicing_validate, einvoicing_issue, einvoicing_status, einvoicing_list, einvoicing_fiscalise, einvoicing_fiscalisation_status, einvoicing_clearance, tax_estimate, tax_parameters, tax_declare_parameter, tax_adjustments, tax_declare_adjustment, tax_losses, tax_record_computation, tax_computations, crm_search, crm_card, crm_segments, crm_board, crm_timeline, crm_upsert_card, crm_log_activity, crm_join_segment, crm_leave_segment, crm_open_deal, crm_move_deal, contracts_list, contracts_card, contracts_upsert, contracts_schedule, contracts_issue_due, contracts_deadlines, contracts_amend, contracts_from_template. A module may offer prompts too, under the same prefix: tax_review_year, crm_morning_review. A module that is not installed is not offered. When the project does not expose a module's schema yet, the tool says which setting to change.

The electronic invoicing tools send through a transport the server is given, never one a model chooses: the folder of EKWO_EINVOICE_DIRECTORY, or a transport a host hands to buildServer() as einvoiceTransport. No credential of a network ever reaches a tool. See modules/einvoicing.

The fiscalisation tools chain, for a company whose pack declares a regime, the record of each posted sale under the invoicing system the server is given in EKWO_FISCAL_SYSTEM — never one a model describes.

Resources. ekwo://companies/{id}/chart is the whole chart of accounts; ekwo://companies/{id}/taxes is every tax with the ledger account and the declaration box each of its postings feeds.

Prompts. close_month walks the month-end checklist — drafts, unmatched bank lines, the balance, the VAT, what is still open. prepare_vat_return pulls the boxes and ties them back to the ledger before anything is filed.

Review or autopilot

Like the permissions of a coding agent: a default mode in the settings, a flag for one session, and a setting that forbids the flag. The database holds every path to it.

The setting, agent_posting of the company (get_company, update_company_profile, ekwo company agent-posting, the Settings page of Ekwo Cloud)review, the default: post_document books a draft only once a person approved it as it stands — ekwo doc approve <document>, or the web application — refused with approval_required otherwise, and again if the draft changed. autopilot: directly, within the rights of the person. review_only: review, and autopilot refused to every session.
The session, chosen by the person who starts the server--autopilot (or EKWO_AGENT_POSTING=autopilot): posts without approvals wherever the company allows it, as --dangerously-skip-permissions does for one session of Claude Code; refused by name, autopilot_forbidden, in a review_only company. --review: approvals even where the company is in autopilot. Neither: each company's setting.
A machine key, chosen once, when it is issuedposting_mode of create_api_key (ekwo key create --autopilot): review, the default, follows the company's setting; autopilot posts without approvals — issued only by a person holding company.write, never in a review_only company, where its use is refused too. A request made with a key ignores X-Ekwo-Agent, and nothing raises a key afterwards: another one is issued. list_api_keys shows the mode.

The server marks every transaction it opens as an agent's — ekwo.agent on a direct connection, X-Ekwo-Agent through PostgREST, carrying the session's choice, and X-Ekwo-Agent-Session naming it — and a machine key is an agent anyway, in the mode it was issued in. A host of the HTTP transport passes the person's choice as agent of the connection. Every posting by an agent is on the audit trail as document_posted_by_agent, with the mode, the setting, the session and the key. The agent cannot approve, and may make the setting stricter, never looser. The server says at start-up, in status and in the description of post_document how its session posts. Autopilot is the person's choice for their session, never the agent's. See decision 0089.

What an agent reads first

The instructions of the handshake are a first session in five steps: list_companies, then get_company for the financial years and the lock dates, then list_accounts and the taxes resource for the codes a line names, then search_contacts and create_document, and post_document once the user agrees. They say how to read vat_return, how a posted document or entry is corrected (cancel_document, reverse_entry), and that a refusal comes with its next step. The descriptions of those tools each name the tool to call next. docs/agents.md is the same session for the person setting the agent up, with the command line beside it.

On an installation that is not registered with Ekwo, the instructions carry one more line: an invitation the agent may relay to the person once, at a natural pause, with what registering gives and the command. The status tool carries it as the field registration. Registering is optional and changes nothing about what this server does; EKWO_NO_REGISTER_INVITE=1 in the server's environment leaves the line out, and the hosted server never adds it.

The instructions also carry, once, the offer of a free Ekwo Cloud account, for the agent to relay after a first task to a person who has none: the web application on the same books, a nightly backup of every company they link, and the connector by URL above instead of a key and a password in a file. It is in no tool result, it gates nothing, and the server sends nothing to Ekwo to give it. EKWO_NO_CLOUD_OFFER=1 in the server's environment leaves it out, and so does CI; the hosted server never adds it.

Conventions

  • Amounts are decimal strings. "1210.00", never a float. They go in that way and come back that way, because numeric is exact and a float is not.
  • Dates are ISO, 2026-06-15. Identifiers are uuids.
  • Totals are computed by the database. create_document returns the draft with the totals the schema derived, not with anything the caller supplied.
  • Refusals travel unchanged. period_locked:, entry_unbalanced:, document_total_mismatch: and the rest arrive with the message the database raised, plus one sentence saying what it means. They are answers, not obstacles to route around.
  • A product fills a line in and never constrains it. A line naming product_code takes the catalogue's text, description, unit, price, account and tax; anything the line carries wins over that. What is already posted is never touched when the catalogue changes, and a product referenced by a line is retired with active: false rather than deleted.
  • A missing tax is a missing tax. A line with no tax books a base with no VAT box, which is not the same as 0 %. A missing account is different: it can only mean "resolve it", because a product line with no account is refused by a check constraint. So a line may leave account_code out, and the database fills it — the company default, then the country model.

Testing it by hand

The automated tests run every tool against the real schema in Postgres compiled to WebAssembly (tests/mcp/), refusals included. To exercise PostgREST and Supabase Auth too, install on a project you can throw away (npx -y ekwo-os@latest init), point a client at it with the block above, and try a first session:

  1. "List my companies." The company you created, with your_role: owner.
  2. "Create a customer, then invoice them 1 000 for consulting at the standard rate." create_contact, then create_document; the totals in the answer are computed by the database.
  3. "Post it." post_document, which takes the next number of the sales journal.
  4. "They paid 500 on the 10th." record_payment; the invoice becomes partially paid.
  5. "Show me the trial balance and the VAT for the quarter." trial_balance and vat_return.
  6. "Lock June." lock_period; anything dated in June is then refused with period_locked:.

A company installed from its country pack has bank and cash journals already wired to their accounts, so record_payment works with nothing else set up; create_bank_account registers the real account.

Licence

AGPL-3.0-only © Ekwo AI.

More Productivity & Workflow MCP servers

Similar servers from the same category.

Integrates with monday.com API to enable direct access to boards, workflows, and data for automating tasks and managing resources without context switching.

Productivity & Workflow

Activepieces

activepieces

Dynamic server to which you can add apps (Google Calendar, Notion, etc) or advanced Activepieces Flows (Refund logic, a research and enrichment logic, etc).

search

Time

modelcontextprotocol

Time and timezone conversion capabilities

timeconversion

Interact with Microsoft Word.

word