@bank-mcp/server 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 +564 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +79 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +6 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +96 -0
- package/dist/init.js.map +1 -0
- package/dist/providers/base.d.ts +22 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +9 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/enable-banking/auth.d.ts +9 -0
- package/dist/providers/enable-banking/auth.d.ts.map +1 -0
- package/dist/providers/enable-banking/auth.js +30 -0
- package/dist/providers/enable-banking/auth.js.map +1 -0
- package/dist/providers/enable-banking/index.d.ts +12 -0
- package/dist/providers/enable-banking/index.d.ts.map +1 -0
- package/dist/providers/enable-banking/index.js +171 -0
- package/dist/providers/enable-banking/index.js.map +1 -0
- package/dist/providers/mock/index.d.ts +18 -0
- package/dist/providers/mock/index.d.ts.map +1 -0
- package/dist/providers/mock/index.js +151 -0
- package/dist/providers/mock/index.js.map +1 -0
- package/dist/providers/plaid/index.d.ts +12 -0
- package/dist/providers/plaid/index.d.ts.map +1 -0
- package/dist/providers/plaid/index.js +213 -0
- package/dist/providers/plaid/index.js.map +1 -0
- package/dist/providers/registry.d.ts +4 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +26 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/teller/index.d.ts +12 -0
- package/dist/providers/teller/index.d.ts.map +1 -0
- package/dist/providers/teller/index.js +215 -0
- package/dist/providers/teller/index.js.map +1 -0
- package/dist/providers/tink/index.d.ts +12 -0
- package/dist/providers/tink/index.d.ts.map +1 -0
- package/dist/providers/tink/index.js +169 -0
- package/dist/providers/tink/index.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +90 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/get-balance.d.ts +8 -0
- package/dist/tools/get-balance.d.ts.map +1 -0
- package/dist/tools/get-balance.js +39 -0
- package/dist/tools/get-balance.js.map +1 -0
- package/dist/tools/list-accounts.d.ts +7 -0
- package/dist/tools/list-accounts.d.ts.map +1 -0
- package/dist/tools/list-accounts.js +33 -0
- package/dist/tools/list-accounts.js.map +1 -0
- package/dist/tools/list-transactions.d.ts +17 -0
- package/dist/tools/list-transactions.d.ts.map +1 -0
- package/dist/tools/list-transactions.js +104 -0
- package/dist/tools/list-transactions.js.map +1 -0
- package/dist/tools/search-transactions.d.ts +10 -0
- package/dist/tools/search-transactions.d.ts.map +1 -0
- package/dist/tools/search-transactions.js +27 -0
- package/dist/tools/search-transactions.js.map +1 -0
- package/dist/tools/spending-summary.d.ts +25 -0
- package/dist/tools/spending-summary.d.ts.map +1 -0
- package/dist/tools/spending-summary.js +65 -0
- package/dist/tools/spending-summary.js.map +1 -0
- package/dist/types.d.ts +65 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cache.d.ts +19 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +33 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/http.d.ts +12 -0
- package/dist/utils/http.d.ts.map +1 -0
- package/dist/utils/http.js +34 -0
- package/dist/utils/http.js.map +1 -0
- package/dist/utils/zod-to-json.d.ts +9 -0
- package/dist/utils/zod-to-json.d.ts.map +1 -0
- package/dist/utils/zod-to-json.js +62 -0
- package/dist/utils/zod-to-json.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { listTransactions } from "./list-transactions.js";
|
|
3
|
+
export const spendingSummarySchema = z.object({
|
|
4
|
+
connectionId: z.string().optional(),
|
|
5
|
+
dateFrom: z.string().optional(),
|
|
6
|
+
dateTo: z.string().optional(),
|
|
7
|
+
groupBy: z
|
|
8
|
+
.enum(["merchant", "category"])
|
|
9
|
+
.optional()
|
|
10
|
+
.describe('Group expenses by "merchant" (default) or "category".'),
|
|
11
|
+
limit: z
|
|
12
|
+
.number()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Max groups to return (default 20, sorted by total spent)."),
|
|
15
|
+
});
|
|
16
|
+
export async function spendingSummary(args) {
|
|
17
|
+
const transactions = await listTransactions({
|
|
18
|
+
connectionId: args.connectionId,
|
|
19
|
+
dateFrom: args.dateFrom,
|
|
20
|
+
dateTo: args.dateTo,
|
|
21
|
+
type: "debit",
|
|
22
|
+
});
|
|
23
|
+
const groupBy = args.groupBy || "merchant";
|
|
24
|
+
const limit = args.limit || 20;
|
|
25
|
+
// Group expenses
|
|
26
|
+
const groups = new Map();
|
|
27
|
+
for (const tx of transactions) {
|
|
28
|
+
const key = groupBy === "merchant"
|
|
29
|
+
? tx.merchantName || tx.description || "Unknown"
|
|
30
|
+
: tx.category || "uncategorized";
|
|
31
|
+
const existing = groups.get(key) || { total: 0, count: 0, currency: tx.currency };
|
|
32
|
+
existing.total += Math.abs(tx.amount);
|
|
33
|
+
existing.count += 1;
|
|
34
|
+
groups.set(key, existing);
|
|
35
|
+
}
|
|
36
|
+
// Sort by total spent descending
|
|
37
|
+
const sorted = [...groups.entries()]
|
|
38
|
+
.map(([name, data]) => ({
|
|
39
|
+
name,
|
|
40
|
+
totalSpent: Math.round(data.total * 100) / 100,
|
|
41
|
+
transactionCount: data.count,
|
|
42
|
+
currency: data.currency,
|
|
43
|
+
}))
|
|
44
|
+
.sort((a, b) => b.totalSpent - a.totalSpent)
|
|
45
|
+
.slice(0, limit);
|
|
46
|
+
const totalSpent = Math.round(transactions.reduce((sum, t) => sum + Math.abs(t.amount), 0) * 100) / 100;
|
|
47
|
+
const currency = transactions[0]?.currency || "PLN";
|
|
48
|
+
const dateFrom = args.dateFrom || defaultDateFrom(90);
|
|
49
|
+
const dateTo = args.dateTo || today();
|
|
50
|
+
return {
|
|
51
|
+
groups: sorted,
|
|
52
|
+
totalSpent,
|
|
53
|
+
currency,
|
|
54
|
+
period: `${dateFrom} to ${dateTo}`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function defaultDateFrom(days) {
|
|
58
|
+
const d = new Date();
|
|
59
|
+
d.setDate(d.getDate() - days);
|
|
60
|
+
return d.toISOString().slice(0, 10);
|
|
61
|
+
}
|
|
62
|
+
function today() {
|
|
63
|
+
return new Date().toISOString().slice(0, 10);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=spending-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spending-summary.js","sourceRoot":"","sources":["../../src/tools/spending-summary.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalized banking types — all providers map to these.
|
|
3
|
+
*/
|
|
4
|
+
export interface BankAccount {
|
|
5
|
+
uid: string;
|
|
6
|
+
iban: string;
|
|
7
|
+
name: string;
|
|
8
|
+
currency: string;
|
|
9
|
+
connectionId: string;
|
|
10
|
+
}
|
|
11
|
+
export interface Transaction {
|
|
12
|
+
id: string;
|
|
13
|
+
accountId: string;
|
|
14
|
+
date: string;
|
|
15
|
+
amount: number;
|
|
16
|
+
currency: string;
|
|
17
|
+
description: string;
|
|
18
|
+
merchantName?: string;
|
|
19
|
+
category?: string;
|
|
20
|
+
type: "debit" | "credit";
|
|
21
|
+
reference?: string;
|
|
22
|
+
rawData?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
export interface Balance {
|
|
25
|
+
accountId: string;
|
|
26
|
+
amount: number;
|
|
27
|
+
currency: string;
|
|
28
|
+
type: string;
|
|
29
|
+
}
|
|
30
|
+
export interface TransactionFilter {
|
|
31
|
+
dateFrom?: string;
|
|
32
|
+
dateTo?: string;
|
|
33
|
+
amountMin?: number;
|
|
34
|
+
amountMax?: number;
|
|
35
|
+
type?: "debit" | "credit";
|
|
36
|
+
limit?: number;
|
|
37
|
+
}
|
|
38
|
+
export interface ConfigField {
|
|
39
|
+
name: string;
|
|
40
|
+
label: string;
|
|
41
|
+
type: "string" | "path" | "select";
|
|
42
|
+
required: boolean;
|
|
43
|
+
secret?: boolean;
|
|
44
|
+
options?: string[];
|
|
45
|
+
default?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface ConnectionConfig {
|
|
48
|
+
id: string;
|
|
49
|
+
provider: string;
|
|
50
|
+
label: string;
|
|
51
|
+
config: Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
export interface AppConfig {
|
|
54
|
+
version: number;
|
|
55
|
+
connections: ConnectionConfig[];
|
|
56
|
+
defaults: {
|
|
57
|
+
transactionDays: number;
|
|
58
|
+
currency: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export declare const EXPENSE_CATEGORIES: readonly ["housing", "transportation", "food", "utilities", "insurance", "healthcare", "entertainment", "other"];
|
|
62
|
+
export declare const INCOME_CATEGORIES: readonly ["salary", "freelance", "investments", "rental", "other"];
|
|
63
|
+
export type ExpenseCategory = (typeof EXPENSE_CATEGORIES)[number];
|
|
64
|
+
export type IncomeCategory = (typeof INCOME_CATEGORIES)[number];
|
|
65
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,QAAQ,EAAE;QACR,eAAe,EAAE,MAAM,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,eAAO,MAAM,kBAAkB,kHASrB,CAAC;AAEX,eAAO,MAAM,iBAAiB,oEAMpB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalized banking types — all providers map to these.
|
|
3
|
+
*/
|
|
4
|
+
export const EXPENSE_CATEGORIES = [
|
|
5
|
+
"housing",
|
|
6
|
+
"transportation",
|
|
7
|
+
"food",
|
|
8
|
+
"utilities",
|
|
9
|
+
"insurance",
|
|
10
|
+
"healthcare",
|
|
11
|
+
"entertainment",
|
|
12
|
+
"other",
|
|
13
|
+
];
|
|
14
|
+
export const INCOME_CATEGORIES = [
|
|
15
|
+
"salary",
|
|
16
|
+
"freelance",
|
|
17
|
+
"investments",
|
|
18
|
+
"rental",
|
|
19
|
+
"other",
|
|
20
|
+
];
|
|
21
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkEH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,SAAS;IACT,gBAAgB;IAChB,MAAM;IACN,WAAW;IACX,WAAW;IACX,YAAY;IACZ,eAAe;IACf,OAAO;CACC,CAAC;AAEX,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,QAAQ;IACR,WAAW;IACX,aAAa;IACb,QAAQ;IACR,OAAO;CACC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple in-memory TTL cache.
|
|
3
|
+
*
|
|
4
|
+
* Dies with the process — no disk persistence.
|
|
5
|
+
* TTLs: balances 5min, transactions 15min, accounts 1hr.
|
|
6
|
+
*/
|
|
7
|
+
export declare class Cache {
|
|
8
|
+
private store;
|
|
9
|
+
get<T>(key: string): T | undefined;
|
|
10
|
+
set<T>(key: string, value: T, ttlMs: number): void;
|
|
11
|
+
clear(): void;
|
|
12
|
+
}
|
|
13
|
+
export declare const cache: Cache;
|
|
14
|
+
export declare const TTL: {
|
|
15
|
+
readonly ACCOUNTS: number;
|
|
16
|
+
readonly TRANSACTIONS: number;
|
|
17
|
+
readonly BALANCES: number;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAA0C;IAEvD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAUlC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIlD,KAAK,IAAI,IAAI;CAGd;AAGD,eAAO,MAAM,KAAK,OAAc,CAAC;AAEjC,eAAO,MAAM,GAAG;;;;CAIN,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple in-memory TTL cache.
|
|
3
|
+
*
|
|
4
|
+
* Dies with the process — no disk persistence.
|
|
5
|
+
* TTLs: balances 5min, transactions 15min, accounts 1hr.
|
|
6
|
+
*/
|
|
7
|
+
export class Cache {
|
|
8
|
+
store = new Map();
|
|
9
|
+
get(key) {
|
|
10
|
+
const entry = this.store.get(key);
|
|
11
|
+
if (!entry)
|
|
12
|
+
return undefined;
|
|
13
|
+
if (Date.now() > entry.expiresAt) {
|
|
14
|
+
this.store.delete(key);
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
return entry.value;
|
|
18
|
+
}
|
|
19
|
+
set(key, value, ttlMs) {
|
|
20
|
+
this.store.set(key, { value, expiresAt: Date.now() + ttlMs });
|
|
21
|
+
}
|
|
22
|
+
clear() {
|
|
23
|
+
this.store.clear();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Singleton + TTL constants
|
|
27
|
+
export const cache = new Cache();
|
|
28
|
+
export const TTL = {
|
|
29
|
+
ACCOUNTS: 60 * 60 * 1000, // 1 hour
|
|
30
|
+
TRANSACTIONS: 15 * 60 * 1000, // 15 minutes
|
|
31
|
+
BALANCES: 5 * 60 * 1000, // 5 minutes
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,OAAO,KAAK;IACR,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;IAEvD,GAAG,CAAI,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,KAAK,CAAC,KAAU,CAAC;IAC1B,CAAC;IAED,GAAG,CAAI,GAAW,EAAE,KAAQ,EAAE,KAAa;QACzC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF;AAED,4BAA4B;AAC5B,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;AAEjC,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,SAAS;IACnC,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IAC3C,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;CAC7B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal fetch wrapper with timeout and retry for banking APIs.
|
|
3
|
+
*/
|
|
4
|
+
export interface FetchOptions {
|
|
5
|
+
method?: string;
|
|
6
|
+
headers?: Record<string, string>;
|
|
7
|
+
body?: string;
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
retries?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function httpFetch(url: string, opts?: FetchOptions): Promise<unknown>;
|
|
12
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/utils/http.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,OAAO,CAAC,CAqClB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal fetch wrapper with timeout and retry for banking APIs.
|
|
3
|
+
*/
|
|
4
|
+
export async function httpFetch(url, opts = {}) {
|
|
5
|
+
const { method = "GET", headers, body, timeoutMs = 30000, retries = 1 } = opts;
|
|
6
|
+
let lastError;
|
|
7
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
8
|
+
const controller = new AbortController();
|
|
9
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
10
|
+
try {
|
|
11
|
+
const res = await fetch(url, {
|
|
12
|
+
method,
|
|
13
|
+
headers,
|
|
14
|
+
body,
|
|
15
|
+
signal: controller.signal,
|
|
16
|
+
});
|
|
17
|
+
clearTimeout(timer);
|
|
18
|
+
if (!res.ok) {
|
|
19
|
+
const text = await res.text().catch(() => "");
|
|
20
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}: ${text.slice(0, 200)}`);
|
|
21
|
+
}
|
|
22
|
+
return await res.json();
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
27
|
+
// Don't retry on 4xx (client errors)
|
|
28
|
+
if (lastError.message.includes("HTTP 4"))
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
throw lastError;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/utils/http.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,OAAqB,EAAE;IAEvB,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,KAAK,EAAE,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;IAE/E,IAAI,SAA4B,CAAC;IAEjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACnD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;QAE9D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,MAAM;gBACN,OAAO;gBACP,IAAI;gBACJ,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,KAAK,CAAC,CAAC;YAEpB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC9C,MAAM,IAAI,KAAK,CACb,QAAQ,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAC9D,CAAC;YACJ,CAAC;YAED,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAEhE,qCAAqC;YACrC,IAAI,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,MAAM;QAClD,CAAC;IACH,CAAC;IAED,MAAM,SAAU,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ZodObject, ZodRawShape } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal Zod → JSON Schema converter for MCP tool inputSchema.
|
|
4
|
+
*
|
|
5
|
+
* Handles the subset we actually use: objects with string, number,
|
|
6
|
+
* enum, and optional fields. No need for a full library.
|
|
7
|
+
*/
|
|
8
|
+
export declare function zodToJsonSchema(schema: ZodObject<ZodRawShape>): Record<string, unknown>;
|
|
9
|
+
//# sourceMappingURL=zod-to-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-to-json.d.ts","sourceRoot":"","sources":["../../src/utils/zod-to-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAc,MAAM,KAAK,CAAC;AAE9D;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuBzB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Zod → JSON Schema converter for MCP tool inputSchema.
|
|
3
|
+
*
|
|
4
|
+
* Handles the subset we actually use: objects with string, number,
|
|
5
|
+
* enum, and optional fields. No need for a full library.
|
|
6
|
+
*/
|
|
7
|
+
export function zodToJsonSchema(schema) {
|
|
8
|
+
const shape = schema.shape;
|
|
9
|
+
const properties = {};
|
|
10
|
+
const required = [];
|
|
11
|
+
for (const [key, fieldDef] of Object.entries(shape)) {
|
|
12
|
+
const field = fieldDef;
|
|
13
|
+
const prop = zodFieldToJson(field);
|
|
14
|
+
properties[key] = prop;
|
|
15
|
+
if (!field.isOptional()) {
|
|
16
|
+
required.push(key);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const result = {
|
|
20
|
+
type: "object",
|
|
21
|
+
properties,
|
|
22
|
+
};
|
|
23
|
+
if (required.length > 0) {
|
|
24
|
+
result.required = required;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
function zodFieldToJson(field) {
|
|
29
|
+
const def = field._def;
|
|
30
|
+
// Unwrap optional
|
|
31
|
+
if (def.typeName === "ZodOptional") {
|
|
32
|
+
return zodFieldToJson(def.innerType);
|
|
33
|
+
}
|
|
34
|
+
// Unwrap default
|
|
35
|
+
if (def.typeName === "ZodDefault") {
|
|
36
|
+
return zodFieldToJson(def.innerType);
|
|
37
|
+
}
|
|
38
|
+
const result = {};
|
|
39
|
+
// Extract description
|
|
40
|
+
if (def.description) {
|
|
41
|
+
result.description = def.description;
|
|
42
|
+
}
|
|
43
|
+
switch (def.typeName) {
|
|
44
|
+
case "ZodString":
|
|
45
|
+
result.type = "string";
|
|
46
|
+
break;
|
|
47
|
+
case "ZodNumber":
|
|
48
|
+
result.type = "number";
|
|
49
|
+
break;
|
|
50
|
+
case "ZodBoolean":
|
|
51
|
+
result.type = "boolean";
|
|
52
|
+
break;
|
|
53
|
+
case "ZodEnum":
|
|
54
|
+
result.type = "string";
|
|
55
|
+
result.enum = def.values;
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
result.type = "string";
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=zod-to-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-to-json.js","sourceRoot":"","sources":["../../src/utils/zod-to-json.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,MAA8B;IAE9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,MAAM,UAAU,GAA4C,EAAE,CAAC;IAC/D,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,QAAsB,CAAC;QACrC,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACnC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QAEvB,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAA4B;QACtC,IAAI,EAAE,QAAQ;QACd,UAAU;KACX,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,KAAiB;IACvC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC;IAEvB,kBAAkB;IAClB,IAAI,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QACnC,OAAO,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,iBAAiB;IACjB,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAClC,OAAO,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,sBAAsB;IACtB,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;IACvC,CAAC;IAED,QAAQ,GAAG,CAAC,QAAQ,EAAE,CAAC;QACrB,KAAK,WAAW;YACd,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;YACvB,MAAM;QACR,KAAK,WAAW;YACd,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;YACvB,MAAM;QACR,KAAK,YAAY;YACf,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC;YACxB,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;YACvB,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC;YACzB,MAAM;QACR;YACE,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bank-mcp/server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Banking data MCP server — give your AI assistant read-only access to bank accounts via pluggable providers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"bank-mcp": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
16
|
+
"lint": "eslint src/ tests/",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"banking",
|
|
22
|
+
"psd2",
|
|
23
|
+
"enable-banking",
|
|
24
|
+
"ai",
|
|
25
|
+
"llm",
|
|
26
|
+
"claude"
|
|
27
|
+
],
|
|
28
|
+
"author": "Luke",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/elcukro/bank-mcp.git"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/elcukro/bank-mcp/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/elcukro/bank-mcp#readme",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.25.0",
|
|
40
|
+
"jsonwebtoken": "^9.0.0",
|
|
41
|
+
"zod": "^4.3.6"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/jsonwebtoken": "^9.0.0",
|
|
45
|
+
"@types/node": "^22.0.0",
|
|
46
|
+
"eslint": "^9.0.0",
|
|
47
|
+
"typescript": "^5.7.0",
|
|
48
|
+
"vitest": "^3.0.0"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=18.0.0"
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"dist",
|
|
55
|
+
"README.md",
|
|
56
|
+
"LICENSE"
|
|
57
|
+
]
|
|
58
|
+
}
|