@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/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server as a library.
|
|
3
|
+
*
|
|
4
|
+
* Exported so the tests can call every tool handler directly against a real
|
|
5
|
+
* Postgres — the same functions the protocol calls — and so another host can
|
|
6
|
+
* mount this server on a transport of its own instead of shelling out to
|
|
7
|
+
* `npx`.
|
|
8
|
+
*/
|
|
9
|
+
export { EkwoMcpError, explain, socleCode, type Backend, type Filter, type Order, type Row, type SelectQuery, } from './backend.js';
|
|
10
|
+
export { ENV, isServiceRoleKey, openBackend, readConfig, type Config } from './config.js';
|
|
11
|
+
export { amountIn, decimal, money, moneyFields, type Decimal } from '@ekwo-ai/core';
|
|
12
|
+
export { connect, sqlBackend, type SqlBackendOptions, type SqlClient } from './sql.js';
|
|
13
|
+
export { postgrestBackend, type PostgrestBackendOptions } from './postgrest.js';
|
|
14
|
+
export { SERVER_NAME, SERVER_VERSION, buildServer, type ServerOptions } from './server.js';
|
|
15
|
+
export { SCHEMA_MIN, assertSchemaSupported, installedSchemaVersion } from './schema.js';
|
|
16
|
+
export * as readTools from './tools/read.js';
|
|
17
|
+
export * as writeTools from './tools/write.js';
|
|
18
|
+
export { MODULE_TOOLSETS, installedModules, toolsetsFor, type ModuleTool, type ModuleToolset, } from './tools/modules.js';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,YAAY,EACZ,OAAO,EACP,SAAS,EACT,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The server as a library.
|
|
3
|
+
*
|
|
4
|
+
* Exported so the tests can call every tool handler directly against a real
|
|
5
|
+
* Postgres — the same functions the protocol calls — and so another host can
|
|
6
|
+
* mount this server on a transport of its own instead of shelling out to
|
|
7
|
+
* `npx`.
|
|
8
|
+
*/
|
|
9
|
+
export { EkwoMcpError, explain, socleCode, } from './backend.js';
|
|
10
|
+
export { ENV, isServiceRoleKey, openBackend, readConfig } from './config.js';
|
|
11
|
+
export { amountIn, decimal, money, moneyFields } from '@ekwo-ai/core';
|
|
12
|
+
export { connect, sqlBackend } from './sql.js';
|
|
13
|
+
export { postgrestBackend } from './postgrest.js';
|
|
14
|
+
export { SERVER_NAME, SERVER_VERSION, buildServer } from './server.js';
|
|
15
|
+
export { SCHEMA_MIN, assertSchemaSupported, installedSchemaVersion } from './schema.js';
|
|
16
|
+
export * as readTools from './tools/read.js';
|
|
17
|
+
export * as writeTools from './tools/write.js';
|
|
18
|
+
export { MODULE_TOOLSETS, installedModules, toolsetsFor, } from './tools/modules.js';
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,YAAY,EACZ,OAAO,EACP,SAAS,GAMV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAgB,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,UAAU,EAA0C,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAgC,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,GAGZ,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The recommended backend: PostgREST, with the user's own session.
|
|
3
|
+
*
|
|
4
|
+
* Supabase already turns the schema into a REST API with an OpenAPI
|
|
5
|
+
* description, and row level security decides what each request may see. So
|
|
6
|
+
* this server holds no privileges of its own: it signs in as the person using
|
|
7
|
+
* it — or is handed their access token — and everything it can do afterwards
|
|
8
|
+
* is what that person can do. There is no service_role path here, on purpose.
|
|
9
|
+
* A server that could read every company would turn "an AI keeps my books"
|
|
10
|
+
* into "an AI holds the keys to everybody's books".
|
|
11
|
+
*
|
|
12
|
+
* `@supabase/supabase-js` does two things this package deliberately does not
|
|
13
|
+
* hand-write: the password grant with its token refresh, and the query string
|
|
14
|
+
* PostgREST expects. Both are the part that cannot be tested here — no test
|
|
15
|
+
* talks to a Supabase project — and a library that is known to work is worth
|
|
16
|
+
* more than code of ours that is merely untested.
|
|
17
|
+
*/
|
|
18
|
+
import { type Backend } from './backend.js';
|
|
19
|
+
export interface PostgrestBackendOptions {
|
|
20
|
+
supabaseUrl: string;
|
|
21
|
+
anonKey: string;
|
|
22
|
+
/** A session already in hand. Otherwise sign in with the two below. */
|
|
23
|
+
accessToken?: string | undefined;
|
|
24
|
+
email?: string | undefined;
|
|
25
|
+
password?: string | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Signs in, or takes the token it was given, and returns the backend.
|
|
29
|
+
*
|
|
30
|
+
* With an email and a password the client keeps the session in memory and
|
|
31
|
+
* refreshes it on its own; nothing is written to disk, so a long-running
|
|
32
|
+
* server outlives the first hour without a credential cache existing.
|
|
33
|
+
*/
|
|
34
|
+
export declare function postgrestBackend(options: PostgrestBackendOptions): Promise<Backend>;
|
|
35
|
+
//# sourceMappingURL=postgrest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgrest.d.ts","sourceRoot":"","sources":["../src/postgrest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAIL,KAAK,OAAO,EAIb,MAAM,cAAc,CAAC;AAuDtB,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CAkHzF"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The recommended backend: PostgREST, with the user's own session.
|
|
3
|
+
*
|
|
4
|
+
* Supabase already turns the schema into a REST API with an OpenAPI
|
|
5
|
+
* description, and row level security decides what each request may see. So
|
|
6
|
+
* this server holds no privileges of its own: it signs in as the person using
|
|
7
|
+
* it — or is handed their access token — and everything it can do afterwards
|
|
8
|
+
* is what that person can do. There is no service_role path here, on purpose.
|
|
9
|
+
* A server that could read every company would turn "an AI keeps my books"
|
|
10
|
+
* into "an AI holds the keys to everybody's books".
|
|
11
|
+
*
|
|
12
|
+
* `@supabase/supabase-js` does two things this package deliberately does not
|
|
13
|
+
* hand-write: the password grant with its token refresh, and the query string
|
|
14
|
+
* PostgREST expects. Both are the part that cannot be tested here — no test
|
|
15
|
+
* talks to a Supabase project — and a library that is known to work is worth
|
|
16
|
+
* more than code of ours that is merely untested.
|
|
17
|
+
*/
|
|
18
|
+
import { createClient } from '@supabase/supabase-js';
|
|
19
|
+
import { EkwoMcpError, explain, identifier, } from './backend.js';
|
|
20
|
+
function applyFilters(builder, filters) {
|
|
21
|
+
let out = builder;
|
|
22
|
+
for (const filter of filters ?? []) {
|
|
23
|
+
const column = identifier(filter.column);
|
|
24
|
+
switch (filter.op) {
|
|
25
|
+
case 'is':
|
|
26
|
+
out = out.is(column, null);
|
|
27
|
+
break;
|
|
28
|
+
case 'in':
|
|
29
|
+
out = out.in(column, filter.value);
|
|
30
|
+
break;
|
|
31
|
+
case 'ilike':
|
|
32
|
+
out = out.ilike(column, filter.value);
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
out = out[filter.op](column, filter.value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
/** Unwraps a PostgREST answer, letting the schema's own message through. */
|
|
41
|
+
function unwrap(answer, what) {
|
|
42
|
+
if (answer.error !== null) {
|
|
43
|
+
const { message, details, hint } = answer.error;
|
|
44
|
+
// `details` is where Postgres puts the rest of a raise; keep it.
|
|
45
|
+
const full = [message, details, hint].filter((part) => typeof part === 'string' && part.length > 0).join(' — ');
|
|
46
|
+
throw explain(full.length > 0 ? full : `${what} failed`);
|
|
47
|
+
}
|
|
48
|
+
if (answer.data === null) {
|
|
49
|
+
throw new EkwoMcpError(`${what}: nothing came back`);
|
|
50
|
+
}
|
|
51
|
+
return answer.data;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Signs in, or takes the token it was given, and returns the backend.
|
|
55
|
+
*
|
|
56
|
+
* With an email and a password the client keeps the session in memory and
|
|
57
|
+
* refreshes it on its own; nothing is written to disk, so a long-running
|
|
58
|
+
* server outlives the first hour without a credential cache existing.
|
|
59
|
+
*/
|
|
60
|
+
export async function postgrestBackend(options) {
|
|
61
|
+
const headers = {};
|
|
62
|
+
if (options.accessToken !== undefined && options.accessToken.length > 0) {
|
|
63
|
+
headers['Authorization'] = `Bearer ${options.accessToken}`;
|
|
64
|
+
}
|
|
65
|
+
const client = createClient(options.supabaseUrl, options.anonKey, {
|
|
66
|
+
auth: {
|
|
67
|
+
persistSession: false,
|
|
68
|
+
autoRefreshToken: options.accessToken === undefined,
|
|
69
|
+
detectSessionInUrl: false,
|
|
70
|
+
},
|
|
71
|
+
global: { headers },
|
|
72
|
+
});
|
|
73
|
+
let actingAs;
|
|
74
|
+
if (options.accessToken === undefined || options.accessToken.length === 0) {
|
|
75
|
+
if (options.email === undefined || options.password === undefined) {
|
|
76
|
+
throw new EkwoMcpError('no_credentials: set EKWO_EMAIL and EKWO_PASSWORD, or EKWO_ACCESS_TOKEN');
|
|
77
|
+
}
|
|
78
|
+
const { data, error } = await client.auth.signInWithPassword({
|
|
79
|
+
email: options.email,
|
|
80
|
+
password: options.password,
|
|
81
|
+
});
|
|
82
|
+
if (error !== null) {
|
|
83
|
+
throw new EkwoMcpError(`sign_in_failed: ${error.message}`);
|
|
84
|
+
}
|
|
85
|
+
actingAs = data.user?.id;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const { data } = await client.auth.getUser(options.accessToken);
|
|
89
|
+
actingAs = data.user?.id;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The client, pointed at one schema.
|
|
93
|
+
*
|
|
94
|
+
* PostgREST serves a schema other than `public` through the `Accept-Profile`
|
|
95
|
+
* and `Content-Profile` headers, which `supabase-js` sets for you through
|
|
96
|
+
* `.schema()`. It answers 406 for a schema the project does not expose, and
|
|
97
|
+
* no migration can expose one — `ekwo module enable` prints the line to add.
|
|
98
|
+
*/
|
|
99
|
+
const on = (schema) => schema === undefined ? client : client.schema(identifier(schema));
|
|
100
|
+
return {
|
|
101
|
+
mode: 'postgrest',
|
|
102
|
+
actingAs,
|
|
103
|
+
async rpc(fn, args = {}, schema) {
|
|
104
|
+
const answer = (await on(schema).rpc(identifier(fn), args));
|
|
105
|
+
const data = unwrap(answer, fn);
|
|
106
|
+
// A function returning one composite row comes back as an object, a
|
|
107
|
+
// set-returning one as an array. Tools see an array either way.
|
|
108
|
+
return (Array.isArray(data) ? data : [data]);
|
|
109
|
+
},
|
|
110
|
+
async rpcVoid(fn, args = {}, schema) {
|
|
111
|
+
const answer = (await on(schema).rpc(identifier(fn), args));
|
|
112
|
+
if (answer.error !== null) {
|
|
113
|
+
throw explain(answer.error.message);
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
async select(query) {
|
|
117
|
+
let builder = on(query.schema).from(identifier(query.table)).select(query.columns.join(','));
|
|
118
|
+
builder = applyFilters(builder, query.where);
|
|
119
|
+
for (const order of query.order ?? []) {
|
|
120
|
+
builder = builder.order(identifier(order.column), { ascending: order.ascending !== false });
|
|
121
|
+
}
|
|
122
|
+
if (query.limit !== undefined)
|
|
123
|
+
builder = builder.limit(query.limit);
|
|
124
|
+
return unwrap((await builder), `select from ${query.table}`);
|
|
125
|
+
},
|
|
126
|
+
async insert(table, rows, returning = ['*'], schema) {
|
|
127
|
+
const answer = (await on(schema)
|
|
128
|
+
.from(identifier(table))
|
|
129
|
+
.insert(rows)
|
|
130
|
+
.select(returning.join(',')));
|
|
131
|
+
return unwrap(answer, `insert into ${table}`);
|
|
132
|
+
},
|
|
133
|
+
async update(table, patch, where, returning = ['*'], schema) {
|
|
134
|
+
let builder = on(schema).from(identifier(table)).update(patch);
|
|
135
|
+
builder = applyFilters(builder, where);
|
|
136
|
+
const answer = (await builder.select(returning.join(',')));
|
|
137
|
+
return unwrap(answer, `update ${table}`);
|
|
138
|
+
},
|
|
139
|
+
async remove(table, where, schema) {
|
|
140
|
+
let builder = on(schema).from(identifier(table)).delete();
|
|
141
|
+
builder = applyFilters(builder, where);
|
|
142
|
+
const answer = (await builder);
|
|
143
|
+
if (answer.error !== null)
|
|
144
|
+
throw explain(answer.error.message);
|
|
145
|
+
},
|
|
146
|
+
async close() {
|
|
147
|
+
// Stops the refresh timer; there is no socket to give back.
|
|
148
|
+
await client.auth.stopAutoRefresh();
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=postgrest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgrest.js","sourceRoot":"","sources":["../src/postgrest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one rounding rule of Ekwo: **half up, on the absolute value, at the
|
|
3
|
+
* currency's decimals**.
|
|
4
|
+
*
|
|
5
|
+
* Three packages used to answer this differently — `Math.round((v + EPSILON) *
|
|
6
|
+
* 100) / 100`, `Math.round(v * 100) / 100` and `Number.prototype.toFixed(2)` —
|
|
7
|
+
* and the three disagreed on the two cases that matter: a negative half, where
|
|
8
|
+
* `Math.round` goes towards positive infinity and turns -0.005 into -0.00, and
|
|
9
|
+
* a value a binary float cannot hold, where 2.675 becomes 2.67 because
|
|
10
|
+
* `2.675 * 100` is really 267.49999999999994. A credit note is a sale with the
|
|
11
|
+
* sign flipped; a rule that treats the two differently puts a cent between an
|
|
12
|
+
* invoice and its credit note, and the cent is found by the person filing the
|
|
13
|
+
* return.
|
|
14
|
+
*
|
|
15
|
+
* Half up on the absolute value is what an invoice, a VAT return and a set of
|
|
16
|
+
* annual accounts are written with, and it is symmetric by construction: the
|
|
17
|
+
* rounding of -x is the rounding of x with the sign put back.
|
|
18
|
+
*
|
|
19
|
+
* The file is deliberately identical in every package that holds a copy. A
|
|
20
|
+
* format brick may not import the core or another brick, so the rule is
|
|
21
|
+
* duplicated rather than shared — and `tests/rounding.test.ts` reads the
|
|
22
|
+
* copies and refuses one that has drifted. See `docs/decisions.md`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function roundCurrency(value: number, decimals?: number): number;
|
|
25
|
+
//# sourceMappingURL=rounding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rounding.d.ts","sourceRoot":"","sources":["../src/rounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAUjE"}
|
package/dist/rounding.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one rounding rule of Ekwo: **half up, on the absolute value, at the
|
|
3
|
+
* currency's decimals**.
|
|
4
|
+
*
|
|
5
|
+
* Three packages used to answer this differently — `Math.round((v + EPSILON) *
|
|
6
|
+
* 100) / 100`, `Math.round(v * 100) / 100` and `Number.prototype.toFixed(2)` —
|
|
7
|
+
* and the three disagreed on the two cases that matter: a negative half, where
|
|
8
|
+
* `Math.round` goes towards positive infinity and turns -0.005 into -0.00, and
|
|
9
|
+
* a value a binary float cannot hold, where 2.675 becomes 2.67 because
|
|
10
|
+
* `2.675 * 100` is really 267.49999999999994. A credit note is a sale with the
|
|
11
|
+
* sign flipped; a rule that treats the two differently puts a cent between an
|
|
12
|
+
* invoice and its credit note, and the cent is found by the person filing the
|
|
13
|
+
* return.
|
|
14
|
+
*
|
|
15
|
+
* Half up on the absolute value is what an invoice, a VAT return and a set of
|
|
16
|
+
* annual accounts are written with, and it is symmetric by construction: the
|
|
17
|
+
* rounding of -x is the rounding of x with the sign put back.
|
|
18
|
+
*
|
|
19
|
+
* The file is deliberately identical in every package that holds a copy. A
|
|
20
|
+
* format brick may not import the core or another brick, so the rule is
|
|
21
|
+
* duplicated rather than shared — and `tests/rounding.test.ts` reads the
|
|
22
|
+
* copies and refuses one that has drifted. See `docs/decisions.md`.
|
|
23
|
+
*/
|
|
24
|
+
export function roundCurrency(value, decimals = 2) {
|
|
25
|
+
const factor = 10 ** decimals;
|
|
26
|
+
const scaled = Math.abs(value) * factor;
|
|
27
|
+
// The nudge is proportional to the number, which is what makes it work at
|
|
28
|
+
// 1.005 and at 1000000.005 alike, and far too small to move a value that is
|
|
29
|
+
// not already within a bit of the halfway point.
|
|
30
|
+
const rounded = Math.round(scaled + Number.EPSILON * scaled);
|
|
31
|
+
// `-0` is a value of its own in JavaScript and it prints as "-0.00".
|
|
32
|
+
// Adding zero turns it back into `0`.
|
|
33
|
+
return (value < 0 ? -rounded : rounded) / factor + 0;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=rounding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rounding.js","sourceRoot":"","sources":["../src/rounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,QAAQ,GAAG,CAAC;IACvD,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;IACxC,0EAA0E;IAC1E,4EAA4E;IAC5E,iDAAiD;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;IAC7D,qEAAqE;IACrE,sCAAsC;IACtC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;AACvD,CAAC"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What this server needs of the database it is pointed at.
|
|
3
|
+
*
|
|
4
|
+
* An MCP client is installed by whoever wants an assistant, and the database
|
|
5
|
+
* it reaches was installed by whoever runs the books — two decisions, two
|
|
6
|
+
* dates. So the server asks the schema its version before it answers anything,
|
|
7
|
+
* and refuses one it is too new for, by name. The alternative is what an
|
|
8
|
+
* assistant does with a missing column: it improvises, and the improvisation
|
|
9
|
+
* is an accounting entry.
|
|
10
|
+
*
|
|
11
|
+
* Declared in `package.json` under `ekwo.schemaMin`, as a country pack
|
|
12
|
+
* declares it in its manifest, and repeated here as a constant so a bundle
|
|
13
|
+
* that never reads a manifest still carries it.
|
|
14
|
+
*/
|
|
15
|
+
import { type Backend } from './backend.js';
|
|
16
|
+
/** The oldest schema this server speaks to. */
|
|
17
|
+
export declare const SCHEMA_MIN = "0.4.0";
|
|
18
|
+
/** The version the migrations of that database define. */
|
|
19
|
+
export declare function installedSchemaVersion(backend: Backend): Promise<string | undefined>;
|
|
20
|
+
/**
|
|
21
|
+
* Refuses a database older than this server, and says which way to fix it.
|
|
22
|
+
*
|
|
23
|
+
* A database that cannot answer at all is refused too: `ekwo_schema_version()`
|
|
24
|
+
* has existed since the first migration, so a silence means the schema is not
|
|
25
|
+
* installed rather than that it is old.
|
|
26
|
+
*/
|
|
27
|
+
export declare function assertSchemaSupported(backend: Backend): Promise<string>;
|
|
28
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAE1D,+CAA+C;AAC/C,eAAO,MAAM,UAAU,UAAU,CAAC;AAElC,0DAA0D;AAC1D,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAU1F;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB7E"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What this server needs of the database it is pointed at.
|
|
3
|
+
*
|
|
4
|
+
* An MCP client is installed by whoever wants an assistant, and the database
|
|
5
|
+
* it reaches was installed by whoever runs the books — two decisions, two
|
|
6
|
+
* dates. So the server asks the schema its version before it answers anything,
|
|
7
|
+
* and refuses one it is too new for, by name. The alternative is what an
|
|
8
|
+
* assistant does with a missing column: it improvises, and the improvisation
|
|
9
|
+
* is an accounting entry.
|
|
10
|
+
*
|
|
11
|
+
* Declared in `package.json` under `ekwo.schemaMin`, as a country pack
|
|
12
|
+
* declares it in its manifest, and repeated here as a constant so a bundle
|
|
13
|
+
* that never reads a manifest still carries it.
|
|
14
|
+
*/
|
|
15
|
+
import { schemaIsAtLeast } from '@ekwo-ai/core';
|
|
16
|
+
import { EkwoMcpError } from './backend.js';
|
|
17
|
+
/** The oldest schema this server speaks to. */
|
|
18
|
+
export const SCHEMA_MIN = '0.4.0';
|
|
19
|
+
/** The version the migrations of that database define. */
|
|
20
|
+
export async function installedSchemaVersion(backend) {
|
|
21
|
+
try {
|
|
22
|
+
const rows = await backend.rpc('ekwo_schema_version');
|
|
23
|
+
const version = rows[0];
|
|
24
|
+
return typeof version === 'string' ? version : undefined;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// A database that has no such function is not an Ekwo database at this
|
|
28
|
+
// version — which is exactly what the caller is about to say.
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Refuses a database older than this server, and says which way to fix it.
|
|
34
|
+
*
|
|
35
|
+
* A database that cannot answer at all is refused too: `ekwo_schema_version()`
|
|
36
|
+
* has existed since the first migration, so a silence means the schema is not
|
|
37
|
+
* installed rather than that it is old.
|
|
38
|
+
*/
|
|
39
|
+
export async function assertSchemaSupported(backend) {
|
|
40
|
+
const installed = await installedSchemaVersion(backend);
|
|
41
|
+
if (installed === undefined) {
|
|
42
|
+
throw new EkwoMcpError(`schema_not_found: this database does not answer ekwo_schema_version(), so it does not carry the Ekwo schema. Run \`npx ekwo init\` against it first.`);
|
|
43
|
+
}
|
|
44
|
+
if (!schemaIsAtLeast(installed, SCHEMA_MIN)) {
|
|
45
|
+
throw new EkwoMcpError(`schema_too_old: this database is at ${installed} and @ekwo-ai/mcp needs ${SCHEMA_MIN} or newer. Run \`npx ekwo migrate\` against it, then start this server again.`, {
|
|
46
|
+
hint: 'Upgrading the database is the fix, never pinning this server: the schema moves forward only, and an older client would be reading rows that no longer mean what it thinks.',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return installed;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAgB,MAAM,cAAc,CAAC;AAE1D,+CAA+C;AAC/C,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC;AAElC,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAgB;IAC3D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAS,qBAAqB,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,8DAA8D;QAC9D,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAgB;IAC1D,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,YAAY,CACpB,sJAAsJ,CACvJ,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,YAAY,CACpB,uCAAuC,SAAS,2BAA2B,UAAU,+EAA+E,EACpK;YACE,IAAI,EAAE,4KAA4K;SACnL,CACF,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
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 } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
11
|
+
import { type Backend } from './backend.js';
|
|
12
|
+
export declare const SERVER_NAME = "@ekwo-ai/mcp";
|
|
13
|
+
/**
|
|
14
|
+
* What this server tells a client it is, in the MCP handshake.
|
|
15
|
+
*
|
|
16
|
+
* Repeated here rather than read from `package.json`, for the reason
|
|
17
|
+
* `SCHEMA_MIN` is: a bundle that never ships a manifest still has to carry it.
|
|
18
|
+
* `tests/mcp/surface.test.ts` keeps the two equal, so a release that bumps one
|
|
19
|
+
* and forgets the other fails the build.
|
|
20
|
+
*/
|
|
21
|
+
export declare const SERVER_VERSION = "0.4.0";
|
|
22
|
+
export interface ServerOptions {
|
|
23
|
+
/**
|
|
24
|
+
* The modules this installation carries, from `public.modules`. Their tools
|
|
25
|
+
* are registered under the module's own prefix — `assets_list`,
|
|
26
|
+
* `budgets_variance` — and a module that is not installed is not offered,
|
|
27
|
+
* because a tool a model cannot use is worse than a tool it cannot see.
|
|
28
|
+
* `bin.ts` asks the database; a test passes the list it wants.
|
|
29
|
+
*/
|
|
30
|
+
modules?: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
export declare function buildServer(backend: Backend, options?: ServerOptions): McpServer;
|
|
33
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAGtF,OAAO,EAAgB,KAAK,OAAO,EAAY,MAAM,cAAc,CAAC;AAMpE,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAC1C;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,UAAU,CAAC;AA+BtC,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,aAAkB,GAAG,SAAS,CAozBpF"}
|