bankmcp 0.1.2 → 0.1.3

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 CHANGED
@@ -187,7 +187,7 @@ service to others. This project does not change those terms.
187
187
  | `create_watch`, `list_watches`, `delete_watch`, `check_watches` | background rules with webhook notifications |
188
188
 
189
189
  **Prompts**: `connect-bank`, `monthly-summary`, `build-budget`,
190
- `subscription-audit`, `unusual-transactions`.
190
+ `savings-scan`, `subscription-audit`, `unusual-transactions`.
191
191
 
192
192
  **Watches** run on the server. Rules: balance below or above an amount, a
193
193
  single debit over an amount, an incoming or outgoing payment matching a name,
package/dist/lib/data.js CHANGED
@@ -17,10 +17,15 @@ export function simplifyTransaction(t) {
17
17
  }
18
18
  export function simplifyBalances(balances) {
19
19
  const byType = (types) => balances.find((b) => types.includes(b.balance_type));
20
- const booked = byType(["CLBD"]) ?? byType(["ITBD"]) ?? byType(["CLAV"]);
20
+ // Preference order: closing booked, interim booked, closing available, interim
21
+ // available, expected, then whatever the bank sent. Some banks (Revolut, for
22
+ // one) report a single ITAV balance and nothing else; an account must never
23
+ // vanish from a total because of the label its bank chose.
24
+ const booked = byType(["CLBD"]) ?? byType(["ITBD"]) ?? byType(["CLAV"]) ?? byType(["ITAV"]) ?? byType(["XPCD"]) ?? balances[0];
21
25
  const available = byType(["XPCD"]) ?? balances.find((b) => /avail/i.test(b.name ?? "") || /avail/i.test(b.balance_type));
22
26
  return {
23
27
  booked: booked ? round2(Number(booked.balance_amount.amount)) : undefined,
28
+ booked_type: booked?.balance_type,
24
29
  available: available && available !== booked ? round2(Number(available.balance_amount.amount)) : undefined,
25
30
  currency: (booked ?? balances[0])?.balance_amount.currency,
26
31
  reference_date: (booked ?? balances[0])?.reference_date,
package/dist/lib/mcp.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { registerTools } from "./tools.js";
3
3
  import { registerPrompts } from "./prompts.js";
4
- export const VERSION = "0.1.2";
4
+ export const VERSION = "0.1.3";
5
5
  export function createServer() {
6
6
  const server = new McpServer({ name: "bank", version: VERSION }, {
7
7
  instructions: [
@@ -23,6 +23,19 @@ export function registerPrompts(server) {
23
23
  3. When I say I am done, call consent_status and list_accounts. Summarise what got linked.
24
24
  4. Suggest a short label for each account based on its name and product, and offer to set them with set_account_label so I can refer to accounts by name.
25
25
 
26
+ ${accountsContext()}`));
27
+ server.registerPrompt("savings-scan", {
28
+ title: "Savings scan",
29
+ description: "For the vague 'how am I doing?' question. A 90-day scan that returns at most three findings ranked by money at stake and urgency: about to run short, a needless cost, or a regular payment that changed. Each with a concrete action. Not a monthly category review.",
30
+ }, () => text(`Give me a 90-day money-saving scan: prevent harm or leave me better off. At most three findings.
31
+
32
+ 1. Call list_accounts with include_balances, then get_transactions on each current account for the last 90 days (follow continuation keys). Skip loan and mortgage accounts for spending findings; note their booked balance only if cash is tight. Do not fetch any other window. If a range comes back empty, say the bank returned nothing.
33
+ 2. Work out each account's role from what flows through it: everyday account (salary in, cards and bills out), transfer or holding account (mostly moves between my own accounts), savings, or liability. Use the role so you do not misread things: a transfer account running low means "top up", not "short before payday". Do not lead with the role; offer set_account_label only as a follow-up. Do not invent accounts I have not linked; if a payee suggests one (a card bill, a rent payment), say so.
34
+ 3. Main currency is the one my income arrives in and my cards are paid from, not an empty travel wallet. Quote and rank in it. Do not invent exchange rates. If a charge was billed in another currency, keep the billed currency; show both only for a currency-fee finding.
35
+ 4. Scan for: (a) running short: project the next low point from the usual cadence of income and bills, and flag overdraft or failed-payment risk if the booked balance looks tight. (b) needless cost: duplicates (same name, same amount, days apart), recurring charges that look forgotten or are new, a merchant whose amount stepped up, avoidable currency or card fees. (c) changed without asking: a regular debit rose, a regular credit shrank or missed, a new regular payment appeared. For each: amount at stake per month or per year, urgency (cash-tight first), confidence (low when names are vague or the history is short).
36
+ 5. Output at most three findings, most expensive or most urgent first, and say in one line if you dropped others. Each finding: one sentence of fact, the amount, the confidence, then one concrete action (cancel, query this charge, top up before a date, connect the account a bill suggests). Give an estimated monthly or yearly saving when the finding is a cost; for running short, give a date instead. If nothing is worth doing, say so in one line and ask one useful question.
37
+ 6. Offer, not perform: subscription-audit for the full recurring table, unusual-transactions if I suspect something is wrong beyond these three, build-budget if I want a plan.
38
+
26
39
  ${accountsContext()}`));
27
40
  server.registerPrompt("monthly-summary", {
28
41
  title: "Monthly summary",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bankmcp",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "BankMCP™: self-hosted, read-only MCP server that lets any AI assistant (Claude, ChatGPT, Mistral, Cursor, or a local model) answer questions about your own bank accounts via open banking (Enable Banking, PSD2)",
5
5
  "license": "MIT",
6
6
  "type": "module",