@ekwo-ai/mcp 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +253 -0
- package/dist/backend.d.ts +24 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/backend.js +105 -0
- package/dist/backend.js.map +1 -0
- package/dist/bin.d.ts +15 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +75 -0
- package/dist/bin.js.map +1 -0
- package/dist/columns.d.ts +59 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +422 -0
- package/dist/columns.js.map +1 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +102 -0
- package/dist/config.js.map +1 -0
- package/dist/format.d.ts +21 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +49 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/postgrest.d.ts +35 -0
- package/dist/postgrest.d.ts.map +1 -0
- package/dist/postgrest.js +152 -0
- package/dist/postgrest.js.map +1 -0
- package/dist/rounding.d.ts +25 -0
- package/dist/rounding.d.ts.map +1 -0
- package/dist/rounding.js +35 -0
- package/dist/rounding.js.map +1 -0
- package/dist/schema.d.ts +28 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +51 -0
- package/dist/schema.js.map +1 -0
- package/dist/server.d.ts +33 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +521 -0
- package/dist/server.js.map +1 -0
- package/dist/sql.d.ts +36 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +214 -0
- package/dist/sql.js.map +1 -0
- package/dist/tools/modules.d.ts +61 -0
- package/dist/tools/modules.d.ts.map +1 -0
- package/dist/tools/modules.js +335 -0
- package/dist/tools/modules.js.map +1 -0
- package/dist/tools/read.d.ts +233 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +853 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/write.d.ts +343 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +814 -0
- package/dist/tools/write.js.map +1 -0
- package/package.json +69 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server itself: the tools, the resources and the two prompts.
|
|
3
|
+
*
|
|
4
|
+
* The descriptions here are written for a model rather than for a reference
|
|
5
|
+
* manual — when to reach for the tool, what comes back, and what it will not
|
|
6
|
+
* do. That last part is the one that earns its place: a model told that
|
|
7
|
+
* `post_document` cannot be undone asks before calling it, and a model told
|
|
8
|
+
* that a missing tax is not zero per cent stops inventing one.
|
|
9
|
+
*/
|
|
10
|
+
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import { EkwoMcpError } from './backend.js';
|
|
13
|
+
import { columns } from '@ekwo-ai/core';
|
|
14
|
+
import * as read from './tools/read.js';
|
|
15
|
+
import * as write from './tools/write.js';
|
|
16
|
+
import { toolsetsFor } from './tools/modules.js';
|
|
17
|
+
export const SERVER_NAME = '@ekwo-ai/mcp';
|
|
18
|
+
/**
|
|
19
|
+
* What this server tells a client it is, in the MCP handshake.
|
|
20
|
+
*
|
|
21
|
+
* Repeated here rather than read from `package.json`, for the reason
|
|
22
|
+
* `SCHEMA_MIN` is: a bundle that never ships a manifest still has to carry it.
|
|
23
|
+
* `tests/mcp/surface.test.ts` keeps the two equal, so a release that bumps one
|
|
24
|
+
* and forgets the other fails the build.
|
|
25
|
+
*/
|
|
26
|
+
export const SERVER_VERSION = '0.4.0';
|
|
27
|
+
/** Everything a tool returns: JSON, pretty-printed, as one text block. */
|
|
28
|
+
function ok(payload) {
|
|
29
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A failure, with the database's own words first.
|
|
33
|
+
*
|
|
34
|
+
* `period_locked: 2026-03-31 is on or before the accounting lock date` is
|
|
35
|
+
* more useful to a model than anything this package could paraphrase, so it
|
|
36
|
+
* leads; the sentence underneath says what to do about it.
|
|
37
|
+
*/
|
|
38
|
+
function fail(error) {
|
|
39
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
40
|
+
const hint = error instanceof EkwoMcpError ? error.hint : undefined;
|
|
41
|
+
return {
|
|
42
|
+
isError: true,
|
|
43
|
+
content: [{ type: 'text', text: hint === undefined ? message : `${message}\n\n${hint}` }],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function guard(run) {
|
|
47
|
+
try {
|
|
48
|
+
return ok(await run());
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return fail(error);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function buildServer(backend, options = {}) {
|
|
55
|
+
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, {
|
|
56
|
+
instructions: 'Ekwo OS keeps double-entry books in the user\'s own Postgres. You act as that user: everything you can see and change is what row level security lets them see and change. Amounts are decimal strings ("1210.00"), dates are ISO (2026-06-15), identifiers are uuids. Invoices are created as drafts and become ledger entries only when post_document is called; a posted entry is never deleted or edited, it is corrected with a credit note. When the database refuses — period_locked, entry_unbalanced, document_total_mismatch — report the refusal rather than working around it.',
|
|
57
|
+
});
|
|
58
|
+
// -------------------------------------------------------------------- read
|
|
59
|
+
server.registerTool('list_companies', {
|
|
60
|
+
title: 'List companies',
|
|
61
|
+
description: '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.',
|
|
62
|
+
inputSchema: read.ListCompaniesInput.shape,
|
|
63
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
64
|
+
}, async () => guard(() => read.listCompanies(backend)));
|
|
65
|
+
server.registerTool('get_company', {
|
|
66
|
+
title: 'Company settings',
|
|
67
|
+
description: '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.',
|
|
68
|
+
inputSchema: read.GetCompanyInput.shape,
|
|
69
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
70
|
+
}, async (args) => guard(() => read.getCompany(backend, args)));
|
|
71
|
+
server.registerTool('list_accounts', {
|
|
72
|
+
title: 'Chart of accounts',
|
|
73
|
+
description: '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.',
|
|
74
|
+
inputSchema: read.ListAccountsInput.shape,
|
|
75
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
76
|
+
}, async (args) => guard(() => read.listAccounts(backend, args)));
|
|
77
|
+
server.registerTool('search_contacts', {
|
|
78
|
+
title: 'Find a contact',
|
|
79
|
+
description: '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.',
|
|
80
|
+
inputSchema: read.SearchContactsInput.shape,
|
|
81
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
82
|
+
}, async (args) => guard(() => read.searchContacts(backend, args)));
|
|
83
|
+
server.registerTool('list_documents', {
|
|
84
|
+
title: 'List documents',
|
|
85
|
+
description: '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.',
|
|
86
|
+
inputSchema: read.ListDocumentsInput.shape,
|
|
87
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
88
|
+
}, async (args) => guard(() => read.listDocuments(backend, args)));
|
|
89
|
+
server.registerTool('get_document', {
|
|
90
|
+
title: 'Read a document',
|
|
91
|
+
description: '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.',
|
|
92
|
+
inputSchema: read.GetDocumentInput.shape,
|
|
93
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
94
|
+
}, async (args) => guard(() => read.getDocument(backend, args)));
|
|
95
|
+
server.registerTool('get_preferences', {
|
|
96
|
+
title: 'What this user prefers',
|
|
97
|
+
description: 'The signed-in user\u2019s 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\u2019s, then the country pack\u2019s. Every one of them may be null, and null means "take the next answer in the chain" rather than a default this installation picked.',
|
|
98
|
+
inputSchema: read.GetPreferencesInput.shape,
|
|
99
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
100
|
+
}, async (args) => guard(() => read.getPreferences(backend, args)));
|
|
101
|
+
server.registerTool('list_api_keys', {
|
|
102
|
+
title: 'Machine keys of a company',
|
|
103
|
+
description: '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.',
|
|
104
|
+
inputSchema: read.ListApiKeysInput.shape,
|
|
105
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
106
|
+
}, async (args) => guard(() => read.listApiKeys(backend, args)));
|
|
107
|
+
server.registerTool('list_invitations', {
|
|
108
|
+
title: 'Invitations into a company',
|
|
109
|
+
description: '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.',
|
|
110
|
+
inputSchema: read.ListInvitationsInput.shape,
|
|
111
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
112
|
+
}, async (args) => guard(() => read.listInvitations(backend, args)));
|
|
113
|
+
server.registerTool('list_shares', {
|
|
114
|
+
title: 'Public links onto documents',
|
|
115
|
+
description: '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.',
|
|
116
|
+
inputSchema: read.ListSharesInput.shape,
|
|
117
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
118
|
+
}, async (args) => guard(() => read.listShares(backend, args)));
|
|
119
|
+
server.registerTool('list_bank_transactions', {
|
|
120
|
+
title: 'Bank transactions',
|
|
121
|
+
description: '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.',
|
|
122
|
+
inputSchema: read.ListBankTransactionsInput.shape,
|
|
123
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
124
|
+
}, async (args) => guard(() => read.listBankTransactions(backend, args)));
|
|
125
|
+
server.registerTool('trial_balance', {
|
|
126
|
+
title: 'Trial balance',
|
|
127
|
+
description: '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.',
|
|
128
|
+
inputSchema: read.TrialBalanceInput.shape,
|
|
129
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
130
|
+
}, async (args) => guard(() => read.trialBalance(backend, args)));
|
|
131
|
+
server.registerTool('general_ledger', {
|
|
132
|
+
title: 'General ledger',
|
|
133
|
+
description: '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.',
|
|
134
|
+
inputSchema: read.GeneralLedgerInput.shape,
|
|
135
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
136
|
+
}, async (args) => guard(() => read.generalLedger(backend, args)));
|
|
137
|
+
server.registerTool('aged_balance', {
|
|
138
|
+
title: 'Aged balance',
|
|
139
|
+
description: '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.',
|
|
140
|
+
inputSchema: read.AgedBalanceInput.shape,
|
|
141
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
142
|
+
}, async (args) => guard(() => read.agedBalance(backend, args)));
|
|
143
|
+
server.registerTool('vat_return', {
|
|
144
|
+
title: 'VAT return',
|
|
145
|
+
description: 'The boxes of the VAT return for a period, with their names: the base and tax boxes are summed from what the postings wrote on the ledger lines, the totals are derived from them by the declaration form of the country pack. No country rule lives in this tool, nor in the function behind it. Name a report_code only where a country files several declarations. It prepares figures; it files nothing.',
|
|
146
|
+
inputSchema: read.VatReturnInput.shape,
|
|
147
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
148
|
+
}, async (args) => guard(() => read.vatReturn(backend, args)));
|
|
149
|
+
server.registerTool('ec_sales_list', {
|
|
150
|
+
title: 'Recapitulative statement of intra-Community supplies',
|
|
151
|
+
description: '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.',
|
|
152
|
+
inputSchema: read.EcSalesListInput.shape,
|
|
153
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
154
|
+
}, async (args) => guard(() => read.ecSalesList(backend, args)));
|
|
155
|
+
server.registerTool('portfolio_upcoming_filings', {
|
|
156
|
+
title: 'Returns falling due, across your companies',
|
|
157
|
+
description: '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.',
|
|
158
|
+
inputSchema: read.PortfolioUpcomingFilingsInput.shape,
|
|
159
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
160
|
+
}, async (args) => guard(() => read.portfolioUpcomingFilings(backend, args)));
|
|
161
|
+
server.registerTool('portfolio_filings_touched_since', {
|
|
162
|
+
title: 'Declared periods that moved, across your companies',
|
|
163
|
+
description: '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.',
|
|
164
|
+
inputSchema: read.PortfolioFilingsTouchedSinceInput.shape,
|
|
165
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
166
|
+
}, async (args) => guard(() => read.portfolioFilingsTouchedSince(backend, args)));
|
|
167
|
+
server.registerTool('list_statements', {
|
|
168
|
+
title: 'List financial statements',
|
|
169
|
+
description: '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.',
|
|
170
|
+
inputSchema: read.ListStatementsInput.shape,
|
|
171
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
172
|
+
}, async (args) => guard(() => read.listStatements(backend, args)));
|
|
173
|
+
server.registerTool('financial_statement', {
|
|
174
|
+
title: 'Financial statement',
|
|
175
|
+
description: '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.',
|
|
176
|
+
inputSchema: read.FinancialStatementInput.shape,
|
|
177
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
178
|
+
}, async (args) => guard(() => read.financialStatement(backend, args)));
|
|
179
|
+
server.registerTool('generate_fec', {
|
|
180
|
+
title: 'Generate the French FEC',
|
|
181
|
+
description: '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.',
|
|
182
|
+
inputSchema: read.GenerateFecInput.shape,
|
|
183
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
184
|
+
}, async (args) => guard(() => read.generateFec(backend, args)));
|
|
185
|
+
server.registerTool('describe_pack', {
|
|
186
|
+
title: 'Where a country pack comes from',
|
|
187
|
+
description: "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.",
|
|
188
|
+
inputSchema: read.DescribePackInput.shape,
|
|
189
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
190
|
+
}, async (args) => guard(() => read.describePack(backend, args)));
|
|
191
|
+
server.registerTool('status', {
|
|
192
|
+
title: 'Installation status',
|
|
193
|
+
description: '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.',
|
|
194
|
+
inputSchema: read.StatusInput.shape,
|
|
195
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
196
|
+
}, async () => guard(() => read.status(backend)));
|
|
197
|
+
server.registerTool('read_audit_log', {
|
|
198
|
+
title: 'Audit trail',
|
|
199
|
+
description: "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.",
|
|
200
|
+
inputSchema: read.ReadAuditLogInput.shape,
|
|
201
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
202
|
+
}, async (args) => guard(() => read.readAuditLog(backend, args)));
|
|
203
|
+
// ------------------------------------------------------------------- write
|
|
204
|
+
server.registerTool('search_products', {
|
|
205
|
+
title: 'Find a product',
|
|
206
|
+
description: '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.',
|
|
207
|
+
inputSchema: read.SearchProductsInput.shape,
|
|
208
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
209
|
+
}, async (args) => guard(() => read.searchProducts(backend, args)));
|
|
210
|
+
server.registerTool('create_product', {
|
|
211
|
+
title: 'Add a product',
|
|
212
|
+
description: '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.',
|
|
213
|
+
inputSchema: write.CreateProductInput.shape,
|
|
214
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
215
|
+
}, async (args) => guard(() => write.createProduct(backend, args)));
|
|
216
|
+
server.registerTool('update_product', {
|
|
217
|
+
title: 'Change a product',
|
|
218
|
+
description: "Changes a catalogue row — its name, price, unit, account, tax — or retires it with active: false. Documents already written keep the text, the price and the account they were invoiced with; an invoice is a statement about the day it was raised, and this tool cannot rewrite one. Retiring is the way to withdraw something: deleting is refused while any line still points at it.",
|
|
219
|
+
inputSchema: write.UpdateProductInput.shape,
|
|
220
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
221
|
+
}, async (args) => guard(() => write.updateProduct(backend, args)));
|
|
222
|
+
server.registerTool('create_contact', {
|
|
223
|
+
title: 'Create a contact',
|
|
224
|
+
description: '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.',
|
|
225
|
+
inputSchema: write.CreateContactInput.shape,
|
|
226
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
227
|
+
}, async (args) => guard(() => write.createContact(backend, args)));
|
|
228
|
+
server.registerTool('create_document', {
|
|
229
|
+
title: 'Create a draft invoice',
|
|
230
|
+
description: '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.',
|
|
231
|
+
inputSchema: write.CreateDocumentInput.shape,
|
|
232
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
233
|
+
}, async (args) => guard(() => write.createDocument(backend, args)));
|
|
234
|
+
server.registerTool('update_document_lines', {
|
|
235
|
+
title: 'Replace the lines of a draft',
|
|
236
|
+
description: 'Replaces every line of a draft document with the set you give, and returns the document with its recomputed totals. Lines take product_code the same way create_document does. Drafts only: a posted document is corrected with a credit note, never edited.',
|
|
237
|
+
inputSchema: write.UpdateDocumentLinesInput.shape,
|
|
238
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
239
|
+
}, async (args) => guard(() => write.updateDocumentLines(backend, args)));
|
|
240
|
+
server.registerTool('post_document', {
|
|
241
|
+
title: 'Post a document to the ledger',
|
|
242
|
+
description: 'Books a draft document: base lines, VAT lines from the tax configuration, and the customer or supplier counterpart, numbered and posted. This cannot be undone — there is no unpost, and a posted entry is never deleted; a mistake is corrected with a credit note. 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.',
|
|
243
|
+
inputSchema: write.PostDocumentInput.shape,
|
|
244
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
245
|
+
}, async (args) => guard(() => write.postDocument(backend, args)));
|
|
246
|
+
server.registerTool('record_payment', {
|
|
247
|
+
title: 'Record a payment',
|
|
248
|
+
description: '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.',
|
|
249
|
+
inputSchema: write.RecordPaymentInput.shape,
|
|
250
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
251
|
+
}, async (args) => guard(() => write.recordPayment(backend, args)));
|
|
252
|
+
server.registerTool('reconcile', {
|
|
253
|
+
title: 'Match two ledger lines',
|
|
254
|
+
description: '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.',
|
|
255
|
+
inputSchema: write.ReconcileInput.shape,
|
|
256
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
257
|
+
}, async (args) => guard(() => write.reconcile(backend, args)));
|
|
258
|
+
server.registerTool('unreconcile', {
|
|
259
|
+
title: 'Undo a matching',
|
|
260
|
+
description: 'Removes one matching, putting the residual back on both lines. The entries themselves are untouched. This is the only write in this server that undoes something.',
|
|
261
|
+
inputSchema: write.UnreconcileInput.shape,
|
|
262
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
263
|
+
}, async (args) => guard(() => write.unreconcile(backend, args)));
|
|
264
|
+
server.registerTool('create_bank_account', {
|
|
265
|
+
title: 'Add a bank account',
|
|
266
|
+
description: "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.",
|
|
267
|
+
inputSchema: write.CreateBankAccountInput.shape,
|
|
268
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
269
|
+
}, async (args) => guard(() => write.createBankAccount(backend, args)));
|
|
270
|
+
server.registerTool('list_bank_accounts', {
|
|
271
|
+
title: 'Bank accounts',
|
|
272
|
+
description: '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.',
|
|
273
|
+
inputSchema: read.ListBankAccountsInput.shape,
|
|
274
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
275
|
+
}, async (args) => guard(() => read.listBankAccounts(backend, args)));
|
|
276
|
+
server.registerTool('create_bank_transaction', {
|
|
277
|
+
title: 'Add a bank transaction',
|
|
278
|
+
description: '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.',
|
|
279
|
+
inputSchema: write.CreateBankTransactionInput.shape,
|
|
280
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
281
|
+
}, async (args) => guard(() => write.createBankTransaction(backend, args)));
|
|
282
|
+
server.registerTool('import_bank_statement', {
|
|
283
|
+
title: 'Import a bank statement',
|
|
284
|
+
description: '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.',
|
|
285
|
+
inputSchema: write.ImportBankStatementInput.shape,
|
|
286
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
287
|
+
}, async (args) => guard(() => write.importBankStatement(backend, args)));
|
|
288
|
+
server.registerTool('create_company', {
|
|
289
|
+
title: 'Create a company',
|
|
290
|
+
description: '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\u2019s books. Ask the user for the country rather than guessing: the wrong answer is a whole chart of accounts.',
|
|
291
|
+
inputSchema: write.CreateCompanyInput.shape,
|
|
292
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
293
|
+
}, async (args) => guard(() => write.createCompany(backend, args)));
|
|
294
|
+
server.registerTool('update_company_profile', {
|
|
295
|
+
title: 'Change the company itself',
|
|
296
|
+
description: 'Changes what a company says about itself on its documents: the names it goes by, its address and identifiers, its logo, its stated capital, its activity code and the bank account customers are asked to pay into. Only the fields you name change. It touches nothing in the ledger, and it needs company.write — the owner preset, not the accountant one.',
|
|
297
|
+
inputSchema: write.UpdateCompanyProfileInput.shape,
|
|
298
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
299
|
+
}, async (args) => guard(() => write.updateCompanyProfile(backend, args)));
|
|
300
|
+
server.registerTool('set_preferences', {
|
|
301
|
+
title: 'Change what this user prefers',
|
|
302
|
+
description: 'Writes the signed-in user\u2019s own preferences and nobody else\u2019s. 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.',
|
|
303
|
+
inputSchema: write.SetPreferencesInput.shape,
|
|
304
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
305
|
+
}, async (args) => guard(() => write.setPreferences(backend, args)));
|
|
306
|
+
server.registerTool('invite_member', {
|
|
307
|
+
title: 'Invite somebody into a company',
|
|
308
|
+
description: '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.',
|
|
309
|
+
inputSchema: write.InviteMemberInput.shape,
|
|
310
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
311
|
+
}, async (args) => guard(() => write.inviteMember(backend, args)));
|
|
312
|
+
server.registerTool('create_api_key', {
|
|
313
|
+
title: 'Issue a key to a machine',
|
|
314
|
+
description: '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\u2019s password, and never suggest a service key.',
|
|
315
|
+
inputSchema: write.CreateApiKeyInput.shape,
|
|
316
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
317
|
+
}, async (args) => guard(() => write.createApiKey(backend, args)));
|
|
318
|
+
server.registerTool('revoke_api_key', {
|
|
319
|
+
title: 'Withdraw a machine key',
|
|
320
|
+
description: '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.',
|
|
321
|
+
inputSchema: write.RevokeApiKeyInput.shape,
|
|
322
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
323
|
+
}, async (args) => guard(() => write.revokeApiKey(backend, args)));
|
|
324
|
+
server.registerTool('revoke_invitation', {
|
|
325
|
+
title: 'Withdraw an invitation',
|
|
326
|
+
description: '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.',
|
|
327
|
+
inputSchema: write.RevokeInvitationInput.shape,
|
|
328
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
329
|
+
}, async (args) => guard(() => write.revokeInvitation(backend, args)));
|
|
330
|
+
server.registerTool('share_document', {
|
|
331
|
+
title: 'Publish a document behind a link',
|
|
332
|
+
description: '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\u2019s own document — and so is a draft. A link is never edited: to change when it expires, withdraw it and make another.',
|
|
333
|
+
inputSchema: write.ShareDocumentInput.shape,
|
|
334
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
335
|
+
}, async (args) => guard(() => write.shareDocument(backend, args)));
|
|
336
|
+
server.registerTool('revoke_share', {
|
|
337
|
+
title: 'Withdraw a published link',
|
|
338
|
+
description: '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.',
|
|
339
|
+
inputSchema: write.RevokeShareInput.shape,
|
|
340
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
341
|
+
}, async (args) => guard(() => write.revokeShare(backend, args)));
|
|
342
|
+
server.registerTool('pin_accounts', {
|
|
343
|
+
title: 'Pin accounts to the working chart',
|
|
344
|
+
description: '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.',
|
|
345
|
+
inputSchema: write.PinAccountsInput.shape,
|
|
346
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
347
|
+
}, async (args) => guard(() => write.pinAccounts(backend, args)));
|
|
348
|
+
server.registerTool('lock_period', {
|
|
349
|
+
title: 'Lock a period',
|
|
350
|
+
description: '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.',
|
|
351
|
+
inputSchema: write.LockPeriodInput.shape,
|
|
352
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
|
|
353
|
+
}, async (args) => guard(() => write.lockPeriod(backend, args)));
|
|
354
|
+
server.registerTool('opening_balance', {
|
|
355
|
+
title: 'Import an opening balance',
|
|
356
|
+
description: '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.',
|
|
357
|
+
inputSchema: write.OpeningBalanceInput.shape,
|
|
358
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
359
|
+
}, async (args) => guard(() => write.openingBalance(backend, args)));
|
|
360
|
+
server.registerTool('close_fiscal_year', {
|
|
361
|
+
title: 'Close a fiscal year',
|
|
362
|
+
description: '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.',
|
|
363
|
+
inputSchema: write.CloseFiscalYearInput.shape,
|
|
364
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
365
|
+
}, async (args) => guard(() => write.closeFiscalYear(backend, args)));
|
|
366
|
+
server.registerTool('reopen_fiscal_year', {
|
|
367
|
+
title: 'Re-open a closed fiscal year',
|
|
368
|
+
description: '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.',
|
|
369
|
+
inputSchema: write.ReopenFiscalYearInput.shape,
|
|
370
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
371
|
+
}, async (args) => guard(() => write.reopenFiscalYear(backend, args)));
|
|
372
|
+
// --------------------------------------------------------------- resources
|
|
373
|
+
server.registerResource('chart-of-accounts', new ResourceTemplate('ekwo://companies/{companyId}/chart', { list: undefined }), {
|
|
374
|
+
title: 'Chart of accounts',
|
|
375
|
+
description: 'The whole chart of accounts of a company, as JSON, for when a search is not enough.',
|
|
376
|
+
mimeType: 'application/json',
|
|
377
|
+
}, async (uri, variables) => {
|
|
378
|
+
const companyId = String(variables['companyId']);
|
|
379
|
+
const accounts = await backend.select({
|
|
380
|
+
table: 'accounts',
|
|
381
|
+
columns: columns.ACCOUNT,
|
|
382
|
+
where: [{ column: 'company_id', op: 'eq', value: companyId }],
|
|
383
|
+
order: [{ column: 'code' }],
|
|
384
|
+
});
|
|
385
|
+
return {
|
|
386
|
+
contents: [
|
|
387
|
+
{
|
|
388
|
+
uri: uri.href,
|
|
389
|
+
mimeType: 'application/json',
|
|
390
|
+
text: JSON.stringify({ company_id: companyId, accounts }, null, 2),
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
};
|
|
394
|
+
});
|
|
395
|
+
server.registerResource('taxes', new ResourceTemplate('ekwo://companies/{companyId}/taxes', { list: undefined }), {
|
|
396
|
+
title: 'Taxes',
|
|
397
|
+
description: 'The taxes of a company with their rates, validity periods, kind and recoverability, and the ledger account and declaration box each posting feeds. A tax_on_base posting names no account: its share of the tax lands on the account of the document line, which is how non-deductible VAT is booked.',
|
|
398
|
+
mimeType: 'application/json',
|
|
399
|
+
}, async (uri, variables) => {
|
|
400
|
+
const companyId = String(variables['companyId']);
|
|
401
|
+
const taxes = await backend.select({
|
|
402
|
+
table: 'taxes',
|
|
403
|
+
columns: columns.TAX,
|
|
404
|
+
where: [{ column: 'company_id', op: 'eq', value: companyId }],
|
|
405
|
+
order: [{ column: 'code' }],
|
|
406
|
+
});
|
|
407
|
+
const postings = await backend.select({
|
|
408
|
+
table: 'tax_postings',
|
|
409
|
+
columns: [
|
|
410
|
+
'id',
|
|
411
|
+
'tax_id',
|
|
412
|
+
'document_kind',
|
|
413
|
+
'posting_type',
|
|
414
|
+
'factor_percent::text',
|
|
415
|
+
'account_id',
|
|
416
|
+
'declaration_box',
|
|
417
|
+
// Every box this one amount is printed in, not only the one the
|
|
418
|
+
// posting is known by: a client reading the first alone would
|
|
419
|
+
// under-report a form that prints a figure in two boxes at once.
|
|
420
|
+
'declaration_boxes',
|
|
421
|
+
'box_factor_percent::text',
|
|
422
|
+
'report_code',
|
|
423
|
+
'sequence',
|
|
424
|
+
],
|
|
425
|
+
where: [{ column: 'company_id', op: 'eq', value: companyId }],
|
|
426
|
+
order: [{ column: 'sequence' }],
|
|
427
|
+
});
|
|
428
|
+
return {
|
|
429
|
+
contents: [
|
|
430
|
+
{
|
|
431
|
+
uri: uri.href,
|
|
432
|
+
mimeType: 'application/json',
|
|
433
|
+
text: JSON.stringify({
|
|
434
|
+
company_id: companyId,
|
|
435
|
+
taxes: taxes.map((tax) => ({
|
|
436
|
+
...tax,
|
|
437
|
+
postings: postings.filter((posting) => posting['tax_id'] === tax['id']),
|
|
438
|
+
})),
|
|
439
|
+
}, null, 2),
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
};
|
|
443
|
+
});
|
|
444
|
+
// ----------------------------------------------------------------- prompts
|
|
445
|
+
server.registerPrompt('close_month', {
|
|
446
|
+
title: 'Close a month',
|
|
447
|
+
description: 'The checklist for closing a month: drafts, unmatched bank lines, the balance, the VAT.',
|
|
448
|
+
argsSchema: {
|
|
449
|
+
company_id: z.string().describe('The company to close.'),
|
|
450
|
+
from: z.string().describe('First day of the month, as YYYY-MM-DD.'),
|
|
451
|
+
to: z.string().describe('Last day of the month, as YYYY-MM-DD.'),
|
|
452
|
+
},
|
|
453
|
+
}, ({ company_id, from, to }) => ({
|
|
454
|
+
messages: [
|
|
455
|
+
{
|
|
456
|
+
role: 'user',
|
|
457
|
+
content: {
|
|
458
|
+
type: 'text',
|
|
459
|
+
text: [
|
|
460
|
+
`Close the month from ${from} to ${to} for company ${company_id}. Work through this in order and report what you find; change nothing without asking.`,
|
|
461
|
+
'',
|
|
462
|
+
`1. Documents still in draft: list_documents with state "draft" over the period. Each one is either waiting to be posted or waiting to be deleted — say which, do not decide.`,
|
|
463
|
+
`2. Bank lines still pending: list_bank_transactions. For each, say what it looks like (a customer payment, a supplier payment, something else) and whether a matching invoice exists.`,
|
|
464
|
+
`3. The trial balance over the period: trial_balance. Check that the debit and credit totals agree, and point out any suspense account that carries a balance.`,
|
|
465
|
+
`4. The VAT: vat_return over the period. Report the boxes and the balance due or refundable.`,
|
|
466
|
+
`5. What is still open: aged_balance at ${to}, receivable and payable.`,
|
|
467
|
+
'',
|
|
468
|
+
'Finish with a short list of what has to happen before this month can be locked, and ask before locking anything.',
|
|
469
|
+
].join('\n'),
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
],
|
|
473
|
+
}));
|
|
474
|
+
server.registerPrompt('prepare_vat_return', {
|
|
475
|
+
title: 'Prepare a VAT return',
|
|
476
|
+
description: 'Pull the boxes for a period and check them against the ledger before anything is filed.',
|
|
477
|
+
argsSchema: {
|
|
478
|
+
company_id: z.string().describe('The company to prepare the return for.'),
|
|
479
|
+
from: z.string().describe('First day of the period, as YYYY-MM-DD.'),
|
|
480
|
+
to: z.string().describe('Last day of the period, as YYYY-MM-DD.'),
|
|
481
|
+
},
|
|
482
|
+
}, ({ company_id, from, to }) => ({
|
|
483
|
+
messages: [
|
|
484
|
+
{
|
|
485
|
+
role: 'user',
|
|
486
|
+
content: {
|
|
487
|
+
type: 'text',
|
|
488
|
+
text: [
|
|
489
|
+
`Prepare the VAT return of company ${company_id} for ${from} to ${to}.`,
|
|
490
|
+
'',
|
|
491
|
+
'1. vat_return for the period. Report every box with its amount, and say which ones are computed from the others.',
|
|
492
|
+
'2. Check that nothing is missing: list_documents with state "draft" over the period. A draft invoice is in no box, and that is usually the error.',
|
|
493
|
+
'3. Tie the VAT accounts back to the ledger: general_ledger on the VAT payable and VAT recoverable accounts for the period, and compare with the boxes.',
|
|
494
|
+
'4. If the company supplied anything to another Member State: ec_sales_list for the period, and check its total against the intra-Community boxes of the return. Name every line it flags — a customer with no VAT number is a statement that cannot be filed.',
|
|
495
|
+
'5. Say what is due or refundable, and what would have to be corrected before filing.',
|
|
496
|
+
'',
|
|
497
|
+
'This prepares figures. It files nothing, and it changes nothing in the books.',
|
|
498
|
+
].join('\n'),
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
],
|
|
502
|
+
}));
|
|
503
|
+
// ------------------------------------------------------------------ modules
|
|
504
|
+
//
|
|
505
|
+
// The socle's tools are written out above because they are the socle. A
|
|
506
|
+
// module's are declared as data and registered here, so adding a module to
|
|
507
|
+
// this server is adding a toolset to `tools/modules.ts` and nothing else —
|
|
508
|
+
// the same shape the registry table takes in the database.
|
|
509
|
+
for (const toolset of toolsetsFor(options.modules ?? [])) {
|
|
510
|
+
for (const tool of toolset.tools) {
|
|
511
|
+
server.registerTool(`${toolset.prefix}_${tool.verb}`, {
|
|
512
|
+
title: tool.title,
|
|
513
|
+
description: tool.description,
|
|
514
|
+
inputSchema: tool.input.shape,
|
|
515
|
+
annotations: { readOnlyHint: tool.readOnly, openWorldHint: false },
|
|
516
|
+
}, async (args) => guard(() => tool.run(backend, args)));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return server;
|
|
520
|
+
}
|
|
521
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/sql.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The direct-Postgres backend.
|
|
3
|
+
*
|
|
4
|
+
* For a self-hosted installation where PostgREST is not in front of the
|
|
5
|
+
* database, and for the tests, which run the real schema in Postgres compiled
|
|
6
|
+
* to WebAssembly. It is the second route, not the privileged one: every call
|
|
7
|
+
* runs inside a transaction that sets `request.jwt.claims` and switches to
|
|
8
|
+
* the `authenticated` role, so row level security binds exactly as it does
|
|
9
|
+
* over the API. A connection that could bypass the policies would make this
|
|
10
|
+
* server a way round them, which is the one thing it must never be.
|
|
11
|
+
*
|
|
12
|
+
* The driver is behind `SqlClient` — thirty lines with nothing to decide — so
|
|
13
|
+
* the tests plug PGlite in and never load a network driver.
|
|
14
|
+
*/
|
|
15
|
+
import { type Backend } from './backend.js';
|
|
16
|
+
/** A Postgres connection, reduced to what this server needs. */
|
|
17
|
+
export interface SqlClient {
|
|
18
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
19
|
+
exec(sql: string): Promise<void>;
|
|
20
|
+
transaction<T>(fn: (tx: SqlClient) => Promise<T>): Promise<T>;
|
|
21
|
+
close(): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export interface SqlBackendOptions {
|
|
24
|
+
/**
|
|
25
|
+
* The user this server acts for. Required: without it there is no
|
|
26
|
+
* `auth.uid()`, every policy fails closed, and the useful-looking
|
|
27
|
+
* alternative — running as the owner — is the one that must not exist.
|
|
28
|
+
*/
|
|
29
|
+
userId: string;
|
|
30
|
+
/** Extra JWT claims, if an installation reads more than `sub` and `role`. */
|
|
31
|
+
claims?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
export declare function sqlBackend(db: SqlClient, options: SqlBackendOptions): Backend;
|
|
34
|
+
/** Opens a connection with the `postgres` driver. */
|
|
35
|
+
export declare function connect(connectionString: string): Promise<SqlClient>;
|
|
36
|
+
//# sourceMappingURL=sql.d.ts.map
|