cata-centavo 0.1.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/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/bin/cata-centavo.js +226 -0
- package/dist/bin/cata-centavo.js.map +1 -0
- package/dist/cli/dispatch.js +67 -0
- package/dist/cli/dispatch.js.map +1 -0
- package/dist/cli/doctor.js +178 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.js +125 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/progress.js +85 -0
- package/dist/cli/progress.js.map +1 -0
- package/dist/cli/sync.js +26 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/config.js +119 -0
- package/dist/config.js.map +1 -0
- package/dist/core/account.js +12 -0
- package/dist/core/account.js.map +1 -0
- package/dist/core/accounts.js +91 -0
- package/dist/core/accounts.js.map +1 -0
- package/dist/core/aggregate.js +83 -0
- package/dist/core/aggregate.js.map +1 -0
- package/dist/core/balance.js +68 -0
- package/dist/core/balance.js.map +1 -0
- package/dist/core/bill-rows.js +132 -0
- package/dist/core/bill-rows.js.map +1 -0
- package/dist/core/bill.js +103 -0
- package/dist/core/bill.js.map +1 -0
- package/dist/core/category-source.js +26 -0
- package/dist/core/category-source.js.map +1 -0
- package/dist/core/category.js +72 -0
- package/dist/core/category.js.map +1 -0
- package/dist/core/consent.js +19 -0
- package/dist/core/consent.js.map +1 -0
- package/dist/core/contracts.js +9 -0
- package/dist/core/contracts.js.map +1 -0
- package/dist/core/counterparty.js +69 -0
- package/dist/core/counterparty.js.map +1 -0
- package/dist/core/date.js +25 -0
- package/dist/core/date.js.map +1 -0
- package/dist/core/description.js +58 -0
- package/dist/core/description.js.map +1 -0
- package/dist/core/diagnose.js +32 -0
- package/dist/core/diagnose.js.map +1 -0
- package/dist/core/mcc.js +124 -0
- package/dist/core/mcc.js.map +1 -0
- package/dist/core/refresh.js +142 -0
- package/dist/core/refresh.js.map +1 -0
- package/dist/core/self-transfer.js +22 -0
- package/dist/core/self-transfer.js.map +1 -0
- package/dist/core/taxonomy-tree.js +148 -0
- package/dist/core/taxonomy-tree.js.map +1 -0
- package/dist/core/taxonomy.js +70 -0
- package/dist/core/taxonomy.js.map +1 -0
- package/dist/core/transaction.js +2 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/transactions.js +46 -0
- package/dist/core/transactions.js.map +1 -0
- package/dist/logging.js +93 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp/cursor.js +64 -0
- package/dist/mcp/cursor.js.map +1 -0
- package/dist/mcp/format.js +38 -0
- package/dist/mcp/format.js.map +1 -0
- package/dist/mcp/server.js +50 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/source.js +2 -0
- package/dist/mcp/source.js.map +1 -0
- package/dist/mcp/tools/accounts.js +144 -0
- package/dist/mcp/tools/accounts.js.map +1 -0
- package/dist/mcp/tools/balance.js +96 -0
- package/dist/mcp/tools/balance.js.map +1 -0
- package/dist/mcp/tools/bill-summary-format.js +161 -0
- package/dist/mcp/tools/bill-summary-format.js.map +1 -0
- package/dist/mcp/tools/bill-summary.js +105 -0
- package/dist/mcp/tools/bill-summary.js.map +1 -0
- package/dist/mcp/tools/bills.js +144 -0
- package/dist/mcp/tools/bills.js.map +1 -0
- package/dist/mcp/tools/closing-days.js +90 -0
- package/dist/mcp/tools/closing-days.js.map +1 -0
- package/dist/mcp/tools/list-transactions.js +122 -0
- package/dist/mcp/tools/list-transactions.js.map +1 -0
- package/dist/mcp/tools/result.js +12 -0
- package/dist/mcp/tools/result.js.map +1 -0
- package/dist/mcp/tools/set-category.js +74 -0
- package/dist/mcp/tools/set-category.js.map +1 -0
- package/dist/mcp/tools/sources.js +73 -0
- package/dist/mcp/tools/sources.js.map +1 -0
- package/dist/mcp/tools/transaction-details.js +146 -0
- package/dist/mcp/tools/transaction-details.js.map +1 -0
- package/dist/mcp/tools/transaction-input.js +51 -0
- package/dist/mcp/tools/transaction-input.js.map +1 -0
- package/dist/mcp/tools/transactions.js +186 -0
- package/dist/mcp/tools/transactions.js.map +1 -0
- package/dist/pluggy/client.js +123 -0
- package/dist/pluggy/client.js.map +1 -0
- package/dist/pluggy/errors.js +152 -0
- package/dist/pluggy/errors.js.map +1 -0
- package/dist/pluggy/mapper.js +155 -0
- package/dist/pluggy/mapper.js.map +1 -0
- package/dist/pluggy/money.js +53 -0
- package/dist/pluggy/money.js.map +1 -0
- package/dist/pluggy/transaction-mapper.js +124 -0
- package/dist/pluggy/transaction-mapper.js.map +1 -0
- package/dist/pluggy/transport.js +170 -0
- package/dist/pluggy/transport.js.map +1 -0
- package/dist/pluggy/wire.js +207 -0
- package/dist/pluggy/wire.js.map +1 -0
- package/dist/storage/categories.js +101 -0
- package/dist/storage/categories.js.map +1 -0
- package/dist/storage/category-sql.js +37 -0
- package/dist/storage/category-sql.js.map +1 -0
- package/dist/storage/closing-days.js +27 -0
- package/dist/storage/closing-days.js.map +1 -0
- package/dist/storage/db.js +162 -0
- package/dist/storage/db.js.map +1 -0
- package/dist/storage/diagnostics.js +57 -0
- package/dist/storage/diagnostics.js.map +1 -0
- package/dist/storage/harvest.js +87 -0
- package/dist/storage/harvest.js.map +1 -0
- package/dist/storage/migrations.js +125 -0
- package/dist/storage/migrations.js.map +1 -0
- package/dist/storage/transaction-row.js +74 -0
- package/dist/storage/transaction-row.js.map +1 -0
- package/dist/storage/transactions.js +213 -0
- package/dist/storage/transactions.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-transactions.js","sourceRoot":"","sources":["../../../src/mcp/tools/list-transactions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { prune } from "../format.js";
|
|
2
|
+
export function finishToolError(log, startedAt, message, fields) {
|
|
3
|
+
log.info({ durationMs: Date.now() - startedAt, outcome: "tool-error", ...fields }, "Tool finished with an error");
|
|
4
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
5
|
+
}
|
|
6
|
+
export function configurationProblems(problems) {
|
|
7
|
+
return `Configuration problems:\n${problems.join("\n")}`;
|
|
8
|
+
}
|
|
9
|
+
export function textResult(payload) {
|
|
10
|
+
return { content: [{ type: "text", text: JSON.stringify(prune(payload)) }] };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../../src/mcp/tools/result.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAarC,MAAM,UAAU,eAAe,CAC7B,GAAW,EACX,SAAiB,EACjB,OAAe,EACf,MAAyC;IAEzC,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,EAAE,6BAA6B,CAAC,CAAC;IAElH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAA2B;IAC/D,OAAO,4BAA4B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { isCategoryId } from "../../core/category.js";
|
|
3
|
+
import { isDocument } from "../../core/counterparty.js";
|
|
4
|
+
import { configurationProblems, finishToolError, textResult } from "./result.js";
|
|
5
|
+
export const SET_CATEGORY_DESCRIPTION = `Corrects the category of specific transactions.
|
|
6
|
+
|
|
7
|
+
Use this tool when:
|
|
8
|
+
- The user tells you a transaction is in the wrong category.
|
|
9
|
+
- You listed uncategorized transactions with categories: ["none"] and the user said what they are.
|
|
10
|
+
|
|
11
|
+
Returns: How many transactions were corrected, and any ids that are not in the local cache.`;
|
|
12
|
+
export const SET_COUNTERPARTY_CATEGORY_DESCRIPTION = `Assigns a category to everyone a CPF or CNPJ identifies, backwards and forwards.
|
|
13
|
+
|
|
14
|
+
Use this tool when:
|
|
15
|
+
- The user tells you what a merchant is, rather than what one transaction is.
|
|
16
|
+
- The same counterparty keeps landing in the wrong category.
|
|
17
|
+
|
|
18
|
+
Returns: The document, the category, and how many cached transactions now resolve through it. That count is the blast radius — read it back to the user when it is larger than they expected.`;
|
|
19
|
+
const categoryInput = z.string().refine(isCategoryId, "must be a known category id");
|
|
20
|
+
export const setCategorySchema = z.object({
|
|
21
|
+
transactionIds: z.array(z.string().min(1)).min(1).max(100),
|
|
22
|
+
category: categoryInput,
|
|
23
|
+
});
|
|
24
|
+
export const setCounterpartyCategorySchema = z.object({
|
|
25
|
+
document: z.string().min(1),
|
|
26
|
+
category: categoryInput,
|
|
27
|
+
});
|
|
28
|
+
export function registerSetCategory(server, deps) {
|
|
29
|
+
server.registerTool("setCategory", { description: SET_CATEGORY_DESCRIPTION, inputSchema: setCategorySchema }, async (input) => handleSetCategory(deps, input));
|
|
30
|
+
}
|
|
31
|
+
export function registerSetCounterpartyCategory(server, deps) {
|
|
32
|
+
server.registerTool("setCounterpartyCategory", { description: SET_COUNTERPARTY_CATEGORY_DESCRIPTION, inputSchema: setCounterpartyCategorySchema }, async (input) => handleSetCounterpartyCategory(deps, input));
|
|
33
|
+
}
|
|
34
|
+
export async function handleSetCategory(deps, rawInput) {
|
|
35
|
+
const startedAt = Date.now();
|
|
36
|
+
if (!deps.source.ok) {
|
|
37
|
+
return finishToolError(deps.log, startedAt, configurationProblems(deps.source.problems), { tool: "setCategory" });
|
|
38
|
+
}
|
|
39
|
+
const parsed = setCategorySchema.safeParse(rawInput);
|
|
40
|
+
if (!parsed.success) {
|
|
41
|
+
return finishToolError(deps.log, startedAt, parsed.error.message, { tool: "setCategory" });
|
|
42
|
+
}
|
|
43
|
+
const writer = deps.writer ?? deps.source.writer;
|
|
44
|
+
if (!writer) {
|
|
45
|
+
return finishToolError(deps.log, startedAt, "Storage is read-only", { tool: "setCategory" });
|
|
46
|
+
}
|
|
47
|
+
const result = writer.setCategory(parsed.data.transactionIds, parsed.data.category);
|
|
48
|
+
return textResult(result);
|
|
49
|
+
}
|
|
50
|
+
export async function handleSetCounterpartyCategory(deps, rawInput) {
|
|
51
|
+
const startedAt = Date.now();
|
|
52
|
+
if (!deps.source.ok) {
|
|
53
|
+
return finishToolError(deps.log, startedAt, configurationProblems(deps.source.problems), { tool: "setCounterpartyCategory" });
|
|
54
|
+
}
|
|
55
|
+
const parsed = setCounterpartyCategorySchema.safeParse(rawInput);
|
|
56
|
+
if (!parsed.success) {
|
|
57
|
+
return finishToolError(deps.log, startedAt, parsed.error.message, { tool: "setCounterpartyCategory" });
|
|
58
|
+
}
|
|
59
|
+
const cleanDoc = parsed.data.document.replace(/\D/g, "");
|
|
60
|
+
if (!isDocument(cleanDoc)) {
|
|
61
|
+
return finishToolError(deps.log, startedAt, "document must be an 11-digit CPF or 14-digit CNPJ", { tool: "setCounterpartyCategory" });
|
|
62
|
+
}
|
|
63
|
+
const writer = deps.writer ?? deps.source.writer;
|
|
64
|
+
if (!writer) {
|
|
65
|
+
return finishToolError(deps.log, startedAt, "Storage is read-only", { tool: "setCounterpartyCategory" });
|
|
66
|
+
}
|
|
67
|
+
const result = writer.setCounterpartyCategory(cleanDoc, parsed.data.category);
|
|
68
|
+
return textResult({
|
|
69
|
+
document: cleanDoc,
|
|
70
|
+
category: parsed.data.category,
|
|
71
|
+
affected: result.affected,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=set-category.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-category.js","sourceRoot":"","sources":["../../../src/mcp/tools/set-category.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,UAAU,EAAiB,MAAM,aAAa,CAAC;AAEhG,MAAM,CAAC,MAAM,wBAAwB,GAAG;;;;;;4FAMoD,CAAC;AAE7F,MAAM,CAAC,MAAM,qCAAqC,GAAG;;;;;;8LAMyI,CAAC;AAE/L,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,6BAA6B,CAAC,CAAC;AAErF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAC1D,QAAQ,EAAE,aAAa;CACxB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,QAAQ,EAAE,aAAa;CACxB,CAAC,CAAC;AAEH,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,IAAc;IACnE,MAAM,CAAC,YAAY,CACjB,aAAa,EACb,EAAE,WAAW,EAAE,wBAAwB,EAAE,WAAW,EAAE,iBAAiB,EAAE,EACzE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAChD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,MAAiB,EAAE,IAAc;IAC/E,MAAM,CAAC,YAAY,CACjB,yBAAyB,EACzB,EAAE,WAAW,EAAE,qCAAqC,EAAE,WAAW,EAAE,6BAA6B,EAAE,EAClG,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,6BAA6B,CAAC,IAAI,EAAE,KAAK,CAAC,CAC5D,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAc,EAAE,QAAiB;IAEvE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACpB,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IACpH,CAAC;IAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IACjD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,sBAAsB,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpF,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,IAAc,EAAE,QAAiB;IACnF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACpB,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC;IAChI,CAAC;IAED,MAAM,MAAM,GAAG,6BAA6B,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC;IACzG,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,mDAAmD,EAAE,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC;IACxI,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IACjD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,sBAAsB,EAAE,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC;IAC3G,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,uBAAuB,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9E,OAAO,UAAU,CAAC;QAChB,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ;QAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { diagnose } from "../../core/diagnose.js";
|
|
4
|
+
import { configurationProblems, finishToolError, textResult } from "./result.js";
|
|
5
|
+
export const LIST_SOURCES_DESCRIPTION = `Lists every configured bank connection with its sync status and consent state.
|
|
6
|
+
|
|
7
|
+
Use this tool when:
|
|
8
|
+
- You want to diagnose why an account or transaction tool came back empty or unavailable.
|
|
9
|
+
- The user asks which banks are connected, or whether a connection needs attention.
|
|
10
|
+
|
|
11
|
+
Returns: Per connection, its institution, sync status, warnings, what the bank is waiting on, and consent state (active, revoked, expired or unknown). This lists what is configured, not what exists in your Pluggy account — a bank linked outside this configuration is invisible to it.`;
|
|
12
|
+
/** Registers the diagnostic tool over every configured connection. */
|
|
13
|
+
export function registerListSources(server, deps) {
|
|
14
|
+
server.registerTool("listSources", { description: LIST_SOURCES_DESCRIPTION }, async () => handleListSources(deps));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Reports every configured connection's status and consent.
|
|
18
|
+
*
|
|
19
|
+
* Never returns `isError` because of connection state: a broken connection
|
|
20
|
+
* *is* the diagnosis this tool exists to give, and erroring at the moment
|
|
21
|
+
* everything is rotten would hide it. Only missing configuration errors.
|
|
22
|
+
*/
|
|
23
|
+
export async function handleListSources(deps) {
|
|
24
|
+
const startedAt = Date.now();
|
|
25
|
+
const log = deps.log.child({ tool: "listSources", callId: randomUUID() });
|
|
26
|
+
log.info({}, "listSources started");
|
|
27
|
+
if (!deps.source.ok) {
|
|
28
|
+
return finishToolError(log, startedAt, configurationProblems(deps.source.problems), { problems: deps.source.problems.length });
|
|
29
|
+
}
|
|
30
|
+
const diagnoses = await diagnose(deps.source.bank, deps.source.connections, deps.source.toFailure, deps.clock);
|
|
31
|
+
const response = { sources: diagnoses.map(formatDiagnosis) };
|
|
32
|
+
log.info({ durationMs: Date.now() - startedAt, outcome: "ok", sources: diagnoses.length }, "listSources finished");
|
|
33
|
+
return textResult(response);
|
|
34
|
+
}
|
|
35
|
+
function formatDiagnosis(diagnosis) {
|
|
36
|
+
return {
|
|
37
|
+
id: diagnosis.id,
|
|
38
|
+
...formatConnectionFields(diagnosis),
|
|
39
|
+
failure: diagnosis.failure,
|
|
40
|
+
consent: formatConsent(diagnosis),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function formatConnectionFields(diagnosis) {
|
|
44
|
+
const { connection } = diagnosis;
|
|
45
|
+
if (connection === null) {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
institution: connection.institution,
|
|
50
|
+
status: connection.status,
|
|
51
|
+
executionStatus: connection.executionStatus,
|
|
52
|
+
lastUpdatedAt: connection.lastUpdatedAt?.toISOString() ?? null,
|
|
53
|
+
warnings: connection.warnings,
|
|
54
|
+
parameter: connection.parameter,
|
|
55
|
+
failedLogins: connection.failedLogins,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function formatConsent(diagnosis) {
|
|
59
|
+
const { consent } = diagnosis;
|
|
60
|
+
return {
|
|
61
|
+
state: diagnosis.state,
|
|
62
|
+
expiresAt: isoOrNull(consent?.expiresAt),
|
|
63
|
+
revokedAt: isoOrNull(consent?.revokedAt),
|
|
64
|
+
products: consent?.products ?? null,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function isoOrNull(date) {
|
|
68
|
+
if (date === null || date === undefined) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return date.toISOString();
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.js","sourceRoot":"","sources":["../../../src/mcp/tools/sources.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { toDecimal } from "../format.js";
|
|
4
|
+
import { configurationProblems, finishToolError, textResult } from "./result.js";
|
|
5
|
+
const getTransactionDetailsInput = z.object({
|
|
6
|
+
ids: z.array(z.string().min(1)).min(1).max(20),
|
|
7
|
+
}).superRefine((input, context) => {
|
|
8
|
+
if (new Set(input.ids).size !== input.ids.length) {
|
|
9
|
+
context.addIssue({ code: "custom", path: ["ids"], message: "must not contain duplicates" });
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
export const GET_TRANSACTION_DETAILS_DESCRIPTION = `Returns full details for a bounded set of transaction ids.
|
|
13
|
+
|
|
14
|
+
Use this tool when:
|
|
15
|
+
- You need the counterparty, payment, instalment or card metadata behind a transaction.
|
|
16
|
+
- An aggregate sample id or a listed row identifies the transaction to inspect.
|
|
17
|
+
|
|
18
|
+
Returns: Our transaction fields with money as decimal strings. The request is capped at 20 ids, and unknown ids are reported as an error.`;
|
|
19
|
+
export function registerGetTransactionDetails(server, deps) {
|
|
20
|
+
server.registerTool("getTransactionDetails", { description: GET_TRANSACTION_DETAILS_DESCRIPTION, inputSchema: getTransactionDetailsInput }, async (input) => handleGetTransactionDetails(deps, input));
|
|
21
|
+
}
|
|
22
|
+
export async function handleGetTransactionDetails(deps, input) {
|
|
23
|
+
const startedAt = Date.now();
|
|
24
|
+
const parsed = getTransactionDetailsInput.safeParse(input);
|
|
25
|
+
if (!parsed.success) {
|
|
26
|
+
return finishToolError(deps.log, startedAt, validationMessage(parsed.error), { outcome: "invalid-input" });
|
|
27
|
+
}
|
|
28
|
+
const log = deps.log.child({ tool: "getTransactionDetails" });
|
|
29
|
+
log.info({}, "getTransactionDetails started");
|
|
30
|
+
if (!deps.source.ok) {
|
|
31
|
+
return finishToolError(log, startedAt, configurationProblems(deps.source.problems), { problems: deps.source.problems.length });
|
|
32
|
+
}
|
|
33
|
+
if (deps.reader === null) {
|
|
34
|
+
return finishToolError(log, startedAt, "Transaction reader is unavailable.", { outcome: "reader-unavailable" });
|
|
35
|
+
}
|
|
36
|
+
return executeDetails({ source: deps.source, input: parsed.data, startedAt, log, reader: deps.reader });
|
|
37
|
+
}
|
|
38
|
+
async function executeDetails(options) {
|
|
39
|
+
const { source, input, startedAt, log, reader } = options;
|
|
40
|
+
try {
|
|
41
|
+
const loaded = await reader.load(source.connections);
|
|
42
|
+
const unavailable = unavailableConnections(loaded.unavailable);
|
|
43
|
+
if (unavailable !== null) {
|
|
44
|
+
return finishToolError(log, startedAt, unavailable.message, unavailable.fields);
|
|
45
|
+
}
|
|
46
|
+
const rows = reader.byIds(input.ids);
|
|
47
|
+
const missing = input.ids.filter((id) => !rows.some((row) => row.id === id));
|
|
48
|
+
if (missing.length > 0) {
|
|
49
|
+
return finishToolError(log, startedAt, `Unknown transaction id(s): ${missing.join(", ")}.`, { missing });
|
|
50
|
+
}
|
|
51
|
+
const byId = new Map(rows.map((row) => [row.id, row]));
|
|
52
|
+
const transactions = input.ids.map((id) => formatDetail(rowForId(byId, id)));
|
|
53
|
+
log.info({ durationMs: Date.now() - startedAt, outcome: "ok", rows: transactions.length }, "getTransactionDetails finished");
|
|
54
|
+
return textResult({ transactions });
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
return finishToolError(log, startedAt, `Cannot read transaction details: ${messageOf(error)}`, { outcome: "failure" });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function unavailableConnections(unavailable) {
|
|
61
|
+
if (unavailable.length === 0) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const connections = unavailable.map(({ connectionId }) => connectionId).join(", ");
|
|
65
|
+
return {
|
|
66
|
+
message: `Cannot read transaction details because these connections are unavailable: ${connections}.`,
|
|
67
|
+
fields: { unavailable: unavailable.length },
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function rowForId(rows, id) {
|
|
71
|
+
const row = rows.get(id);
|
|
72
|
+
if (row === undefined) {
|
|
73
|
+
throw new Error(`transaction ${id} disappeared during detail lookup`);
|
|
74
|
+
}
|
|
75
|
+
return row;
|
|
76
|
+
}
|
|
77
|
+
function formatDetail(row) {
|
|
78
|
+
return {
|
|
79
|
+
id: row.id,
|
|
80
|
+
accountId: row.accountId,
|
|
81
|
+
accountType: row.accountType,
|
|
82
|
+
accountSubtype: row.accountSubtype,
|
|
83
|
+
date: row.localDate,
|
|
84
|
+
occurredAt: row.occurredAt,
|
|
85
|
+
description: row.description,
|
|
86
|
+
descriptionNorm: row.descriptionNorm,
|
|
87
|
+
amount: toDecimal(row.amountCents),
|
|
88
|
+
currency: row.currency,
|
|
89
|
+
original: formatOriginal(row),
|
|
90
|
+
category: row.category,
|
|
91
|
+
categorySrc: row.categorySrc,
|
|
92
|
+
categoryId: row.categoryId,
|
|
93
|
+
counterparty: formatCounterparty(row),
|
|
94
|
+
paymentMethod: row.paymentMethod,
|
|
95
|
+
instalment: formatInstalment(row),
|
|
96
|
+
purchaseDate: row.purchaseDate,
|
|
97
|
+
mcc: row.mcc,
|
|
98
|
+
billId: row.billId,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function formatOriginal(row) {
|
|
102
|
+
if (row.originalAmountCents === null || row.originalCurrency === null) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
return { amount: toDecimal(row.originalAmountCents), currency: row.originalCurrency };
|
|
106
|
+
}
|
|
107
|
+
function formatCounterparty(row) {
|
|
108
|
+
if (row.document === null && row.counterpartyName === null) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const details = {};
|
|
112
|
+
if (row.document !== null) {
|
|
113
|
+
details.document = row.document;
|
|
114
|
+
}
|
|
115
|
+
if (row.counterpartyName !== null) {
|
|
116
|
+
details.name = row.counterpartyName;
|
|
117
|
+
}
|
|
118
|
+
return details;
|
|
119
|
+
}
|
|
120
|
+
function formatInstalment(row) {
|
|
121
|
+
if (row.instalmentNumber === null && row.instalmentTotal === null) {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
const details = {};
|
|
125
|
+
if (row.instalmentNumber !== null) {
|
|
126
|
+
details.number = row.instalmentNumber;
|
|
127
|
+
}
|
|
128
|
+
if (row.instalmentTotal !== null) {
|
|
129
|
+
details.total = row.instalmentTotal;
|
|
130
|
+
}
|
|
131
|
+
return details;
|
|
132
|
+
}
|
|
133
|
+
function validationMessage(error) {
|
|
134
|
+
const issue = error.issues[0];
|
|
135
|
+
if (issue === undefined) {
|
|
136
|
+
return "Invalid transaction ids.";
|
|
137
|
+
}
|
|
138
|
+
return `Invalid transaction ids: ${issue.path.join(".") || "input"} ${issue.message}.`;
|
|
139
|
+
}
|
|
140
|
+
function messageOf(error) {
|
|
141
|
+
if (error instanceof Error) {
|
|
142
|
+
return error.message;
|
|
143
|
+
}
|
|
144
|
+
return String(error);
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=transaction-details.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-details.js","sourceRoot":"","sources":["../../../src/mcp/tools/transaction-details.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { isCategoryFilterValue } from "../../core/category.js";
|
|
3
|
+
const dateInput = z.string().regex(/^\d{4}-\d{2}-\d{2}$/u, "must be YYYY-MM-DD");
|
|
4
|
+
const categoryInput = z.string().refine(isCategoryFilterValue, 'must be a known category id, or "none" for uncategorized');
|
|
5
|
+
export const listTransactionsInput = z.object({
|
|
6
|
+
startDate: dateInput,
|
|
7
|
+
endDate: dateInput,
|
|
8
|
+
categories: z.array(categoryInput).optional(),
|
|
9
|
+
minAmountCents: z.number().int().optional(),
|
|
10
|
+
maxAmountCents: z.number().int().optional(),
|
|
11
|
+
accountType: z.enum(["BANK", "CREDIT", "INVESTMENT", "LOAN"]).optional(),
|
|
12
|
+
accountSubtype: z.string().min(1).optional(),
|
|
13
|
+
limit: z.number().int().min(1).max(100),
|
|
14
|
+
cursor: z.string().optional(),
|
|
15
|
+
}).superRefine(validateRange);
|
|
16
|
+
export function validateRange(input, context) {
|
|
17
|
+
if (input.endDate < input.startDate) {
|
|
18
|
+
context.addIssue({ code: "custom", path: ["endDate"], message: "must not be before startDate" });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function validationMessage(error) {
|
|
22
|
+
const issue = error.issues[0];
|
|
23
|
+
if (issue === undefined) {
|
|
24
|
+
return "Invalid transaction filters.";
|
|
25
|
+
}
|
|
26
|
+
return `Invalid transaction filters: ${issue.path.join(".") || "input"} ${issue.message}.`;
|
|
27
|
+
}
|
|
28
|
+
export function toTransactionFilter(input, accounts) {
|
|
29
|
+
let filter = {
|
|
30
|
+
accountIds: accounts.map((account) => account.id),
|
|
31
|
+
from: input.startDate,
|
|
32
|
+
to: input.endDate,
|
|
33
|
+
};
|
|
34
|
+
if (input.categories !== undefined) {
|
|
35
|
+
filter = { ...filter, categories: input.categories };
|
|
36
|
+
}
|
|
37
|
+
if (input.minAmountCents !== undefined) {
|
|
38
|
+
filter = { ...filter, minAmountCents: input.minAmountCents };
|
|
39
|
+
}
|
|
40
|
+
if (input.maxAmountCents !== undefined) {
|
|
41
|
+
filter = { ...filter, maxAmountCents: input.maxAmountCents };
|
|
42
|
+
}
|
|
43
|
+
if (input.accountType !== undefined) {
|
|
44
|
+
filter = { ...filter, accountType: input.accountType };
|
|
45
|
+
}
|
|
46
|
+
if (input.accountSubtype !== undefined) {
|
|
47
|
+
filter = { ...filter, accountSubtype: input.accountSubtype };
|
|
48
|
+
}
|
|
49
|
+
return filter;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=transaction-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-input.js","sourceRoot":"","sources":["../../../src/mcp/tools/transaction-input.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { aggregate } from "../../core/aggregate.js";
|
|
4
|
+
import { categoryById, isCategoryFilterValue } from "../../core/category.js";
|
|
5
|
+
import { todayIn } from "../../core/date.js";
|
|
6
|
+
import { toDecimal } from "../format.js";
|
|
7
|
+
import { configurationProblems, finishToolError, textResult } from "./result.js";
|
|
8
|
+
export { handleListTransactions, registerListTransactions, LIST_TRANSACTIONS_DESCRIPTION } from "./list-transactions.js";
|
|
9
|
+
export const GET_TRANSACTIONS_DESCRIPTION = `Totals spending and income over a date range, grouped by category.
|
|
10
|
+
|
|
11
|
+
Use this tool when:
|
|
12
|
+
- You need to know how much was spent in a period, overall or in one category.
|
|
13
|
+
- You need to compare categories or periods against each other.
|
|
14
|
+
- You need transaction ids to look at individual rows afterwards.
|
|
15
|
+
- You need to know how much is still uncategorized, by passing \`categories: ["none"]\`.
|
|
16
|
+
|
|
17
|
+
Returns: \`spent\` and \`received\` as positive amounts, and one group per category with a signed total, a count and up to ten sample ids. Transfers between the user's own accounts and credit card bill payments are listed as groups but excluded from \`spent\` and \`received\`, because moving money between your own accounts is not spending. Instalments dated in the future are reported separately as \`upcoming\`. \`dataThrough\` states the most recent date each connection has actually supplied, which can trail its last sync by weeks.`;
|
|
18
|
+
const dateInput = z.string().regex(/^\d{4}-\d{2}-\d{2}$/u, "must be YYYY-MM-DD");
|
|
19
|
+
const categoryInput = z.string().refine(isCategoryFilterValue, 'must be a known category id, or "none" for uncategorized');
|
|
20
|
+
const getTransactionsInput = z.object({
|
|
21
|
+
startDate: dateInput,
|
|
22
|
+
endDate: dateInput,
|
|
23
|
+
categories: z.array(categoryInput).optional(),
|
|
24
|
+
minAmountCents: z.number().int().optional(),
|
|
25
|
+
maxAmountCents: z.number().int().optional(),
|
|
26
|
+
accountType: z.enum(["BANK", "CREDIT", "INVESTMENT", "LOAN"]).optional(),
|
|
27
|
+
accountSubtype: z.string().min(1).optional(),
|
|
28
|
+
}).superRefine(validateRange);
|
|
29
|
+
export function registerGetTransactions(server, deps) {
|
|
30
|
+
server.registerTool("getTransactions", { description: GET_TRANSACTIONS_DESCRIPTION, inputSchema: getTransactionsInput }, async (input) => handleGetTransactions(deps, input));
|
|
31
|
+
}
|
|
32
|
+
export async function handleGetTransactions(deps, input) {
|
|
33
|
+
const startedAt = Date.now();
|
|
34
|
+
const parsed = getTransactionsInput.safeParse(input);
|
|
35
|
+
if (!parsed.success) {
|
|
36
|
+
return finishToolError(deps.log, startedAt, validationMessage(parsed.error), { outcome: "invalid-input" });
|
|
37
|
+
}
|
|
38
|
+
const log = deps.log.child({ tool: "getTransactions" });
|
|
39
|
+
log.info({}, "getTransactions started");
|
|
40
|
+
if (!deps.source.ok) {
|
|
41
|
+
return finishToolError(log, startedAt, configurationProblems(deps.source.problems), { problems: deps.source.problems.length });
|
|
42
|
+
}
|
|
43
|
+
if (deps.reader === null) {
|
|
44
|
+
return finishToolError(log, startedAt, "Transaction reader is unavailable.", { outcome: "reader-unavailable" });
|
|
45
|
+
}
|
|
46
|
+
return executeGetTransactions({ deps, input: parsed.data, startedAt, log, reader: deps.reader });
|
|
47
|
+
}
|
|
48
|
+
function validateRange(input, context) {
|
|
49
|
+
if (input.endDate < input.startDate) {
|
|
50
|
+
context.addIssue({ code: "custom", path: ["endDate"], message: "must not be before startDate" });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function executeGetTransactions(options) {
|
|
54
|
+
const { deps, input, startedAt, log, reader } = options;
|
|
55
|
+
if (!deps.source.ok) {
|
|
56
|
+
return finishToolError(log, startedAt, configurationProblems(deps.source.problems), { problems: deps.source.problems.length });
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const loaded = await reader.load(deps.source.connections);
|
|
60
|
+
const unavailable = unavailableRefusal(loaded.unavailable);
|
|
61
|
+
if (unavailable !== null) {
|
|
62
|
+
return finishToolError(log, startedAt, unavailable.message, unavailable.fields);
|
|
63
|
+
}
|
|
64
|
+
const currency = oneCurrency(loaded.accounts);
|
|
65
|
+
if (currency === null) {
|
|
66
|
+
return currencyError(log, startedAt, loaded.accounts);
|
|
67
|
+
}
|
|
68
|
+
const aggregateResult = readAggregate({ source: deps.source, reader, input, accounts: loaded.accounts, clock: deps.clock });
|
|
69
|
+
const response = formatResponse({ result: aggregateResult.result, input, currency, accounts: loaded.accounts, reader, today: aggregateResult.today });
|
|
70
|
+
log.info({ durationMs: Date.now() - startedAt, outcome: "ok", rows: aggregateResult.rows }, "getTransactions finished");
|
|
71
|
+
return textResult(response);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return finishToolError(log, startedAt, `Cannot read transactions: ${messageOf(error)}`, { outcome: "failure" });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function validationMessage(error) {
|
|
78
|
+
const issue = error.issues[0];
|
|
79
|
+
if (issue === undefined) {
|
|
80
|
+
return "Invalid transaction filters.";
|
|
81
|
+
}
|
|
82
|
+
return `Invalid transaction filters: ${issue.path.join(".") || "input"} ${issue.message}.`;
|
|
83
|
+
}
|
|
84
|
+
function toFilter(input, accounts) {
|
|
85
|
+
let filter = {
|
|
86
|
+
accountIds: accounts.map((account) => account.id),
|
|
87
|
+
from: input.startDate,
|
|
88
|
+
to: input.endDate,
|
|
89
|
+
};
|
|
90
|
+
if (input.categories !== undefined) {
|
|
91
|
+
filter = { ...filter, categories: input.categories };
|
|
92
|
+
}
|
|
93
|
+
if (input.minAmountCents !== undefined) {
|
|
94
|
+
filter = { ...filter, minAmountCents: input.minAmountCents };
|
|
95
|
+
}
|
|
96
|
+
if (input.maxAmountCents !== undefined) {
|
|
97
|
+
filter = { ...filter, maxAmountCents: input.maxAmountCents };
|
|
98
|
+
}
|
|
99
|
+
if (input.accountType !== undefined) {
|
|
100
|
+
filter = { ...filter, accountType: input.accountType };
|
|
101
|
+
}
|
|
102
|
+
if (input.accountSubtype !== undefined) {
|
|
103
|
+
filter = { ...filter, accountSubtype: input.accountSubtype };
|
|
104
|
+
}
|
|
105
|
+
return filter;
|
|
106
|
+
}
|
|
107
|
+
function oneCurrency(accounts) {
|
|
108
|
+
const currencies = currenciesIn(accounts);
|
|
109
|
+
if (currencies.length !== 1) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const currency = currencies[0];
|
|
113
|
+
if (currency === undefined) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return currency;
|
|
117
|
+
}
|
|
118
|
+
function currenciesIn(accounts) {
|
|
119
|
+
return [...new Set(accounts.map((account) => account.currency))].sort();
|
|
120
|
+
}
|
|
121
|
+
function currencyError(log, startedAt, accounts) {
|
|
122
|
+
const currencies = currenciesIn(accounts);
|
|
123
|
+
return finishToolError(log, startedAt, `Cannot consolidate transactions across currencies: ${currencies.join(", ")}.`, { currencies });
|
|
124
|
+
}
|
|
125
|
+
function unavailableRefusal(unavailable) {
|
|
126
|
+
if (unavailable.length === 0) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
message: `Cannot read transactions because ${unavailable
|
|
131
|
+
.map(({ connectionId, kind, message }) => `${connectionId} (${kind}): ${message}`)
|
|
132
|
+
.join("; ")}`,
|
|
133
|
+
fields: { unavailable: unavailable.length },
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function readAggregate(options) {
|
|
137
|
+
const filter = toFilter(options.input, options.accounts);
|
|
138
|
+
const rows = options.reader.query(filter);
|
|
139
|
+
const today = todayIn(options.clock);
|
|
140
|
+
return { result: aggregate(rows, today), rows: rows.length, today };
|
|
141
|
+
}
|
|
142
|
+
function formatResponse(options) {
|
|
143
|
+
const { result, input, currency, accounts, reader, today } = options;
|
|
144
|
+
let upcomingField;
|
|
145
|
+
if (result.upcoming.count === 0) {
|
|
146
|
+
upcomingField = {};
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
upcomingField = { upcoming: { total: toDecimal(result.upcoming.totalCents), count: result.upcoming.count } };
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
from: input.startDate,
|
|
153
|
+
to: input.endDate,
|
|
154
|
+
currency,
|
|
155
|
+
spent: toDecimal(result.spentCents),
|
|
156
|
+
received: toDecimal(result.receivedCents),
|
|
157
|
+
groups: result.groups.map(formatGroup),
|
|
158
|
+
...upcomingField,
|
|
159
|
+
accountsCovered: accounts.length,
|
|
160
|
+
dataThrough: [...reader.dataThrough(accounts.map((account) => account.id), today)].map(([connectionId, through]) => ({ connectionId, through })),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function messageOf(error) {
|
|
164
|
+
if (error instanceof Error) {
|
|
165
|
+
return error.message;
|
|
166
|
+
}
|
|
167
|
+
return String(error);
|
|
168
|
+
}
|
|
169
|
+
function formatGroup(group) {
|
|
170
|
+
let label = "Uncategorized";
|
|
171
|
+
if (group.categoryId !== null) {
|
|
172
|
+
const category = categoryById(group.categoryId);
|
|
173
|
+
if (category === undefined) {
|
|
174
|
+
throw new Error(`category ${group.categoryId} is not in the display taxonomy`);
|
|
175
|
+
}
|
|
176
|
+
label = category.pt;
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
category: group.categoryId,
|
|
180
|
+
label,
|
|
181
|
+
total: toDecimal(group.totalCents),
|
|
182
|
+
count: group.count,
|
|
183
|
+
sampleIds: group.sampleIds,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=transactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactions.js","sourceRoot":"","sources":["../../../src/mcp/tools/transactions.ts"],"names":[],"mappings":"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"}
|