@codespar/mcp-open-finance 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/dist/index.js +268 -0
- package/package.json +30 -0
- package/src/index.ts +271 -0
- package/tsconfig.json +13 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Server for Open Finance Brasil — open banking standard.
|
|
4
|
+
*
|
|
5
|
+
* Tools:
|
|
6
|
+
* - list_accounts: List customer accounts
|
|
7
|
+
* - get_account_balance: Get account balance
|
|
8
|
+
* - list_transactions: List account transactions
|
|
9
|
+
* - get_consent: Get consent details
|
|
10
|
+
* - create_consent: Create a new consent request
|
|
11
|
+
* - list_credit_cards: List credit card accounts
|
|
12
|
+
* - get_credit_card_transactions: Get credit card transactions
|
|
13
|
+
* - list_investments: List investment products
|
|
14
|
+
*
|
|
15
|
+
* Environment:
|
|
16
|
+
* OPEN_FINANCE_BASE_URL — Institution API base URL
|
|
17
|
+
* OPEN_FINANCE_CLIENT_ID — OAuth2 client ID
|
|
18
|
+
* OPEN_FINANCE_CLIENT_SECRET — OAuth2 client secret
|
|
19
|
+
*/
|
|
20
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
21
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
22
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
23
|
+
const BASE_URL = process.env.OPEN_FINANCE_BASE_URL || "";
|
|
24
|
+
const CLIENT_ID = process.env.OPEN_FINANCE_CLIENT_ID || "";
|
|
25
|
+
const CLIENT_SECRET = process.env.OPEN_FINANCE_CLIENT_SECRET || "";
|
|
26
|
+
let accessToken = "";
|
|
27
|
+
let tokenExpiry = 0;
|
|
28
|
+
async function getAccessToken() {
|
|
29
|
+
if (accessToken && Date.now() < tokenExpiry)
|
|
30
|
+
return accessToken;
|
|
31
|
+
const res = await fetch(`${BASE_URL}/auth/token`, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
34
|
+
body: new URLSearchParams({
|
|
35
|
+
grant_type: "client_credentials",
|
|
36
|
+
client_id: CLIENT_ID,
|
|
37
|
+
client_secret: CLIENT_SECRET,
|
|
38
|
+
scope: "openid accounts credit-cards-accounts resources consents investments",
|
|
39
|
+
}),
|
|
40
|
+
});
|
|
41
|
+
if (!res.ok) {
|
|
42
|
+
const err = await res.text();
|
|
43
|
+
throw new Error(`Open Finance OAuth ${res.status}: ${err}`);
|
|
44
|
+
}
|
|
45
|
+
const data = await res.json();
|
|
46
|
+
accessToken = data.access_token;
|
|
47
|
+
tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;
|
|
48
|
+
return accessToken;
|
|
49
|
+
}
|
|
50
|
+
async function openFinanceRequest(method, path, body) {
|
|
51
|
+
const token = await getAccessToken();
|
|
52
|
+
const res = await fetch(`${BASE_URL}${path}`, {
|
|
53
|
+
method,
|
|
54
|
+
headers: {
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
"Authorization": `Bearer ${token}`,
|
|
57
|
+
},
|
|
58
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
59
|
+
});
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
const err = await res.text();
|
|
62
|
+
throw new Error(`Open Finance API ${res.status}: ${err}`);
|
|
63
|
+
}
|
|
64
|
+
return res.json();
|
|
65
|
+
}
|
|
66
|
+
const server = new Server({ name: "mcp-open-finance", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
67
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
68
|
+
tools: [
|
|
69
|
+
{
|
|
70
|
+
name: "list_accounts",
|
|
71
|
+
description: "List customer bank accounts via Open Finance",
|
|
72
|
+
inputSchema: {
|
|
73
|
+
type: "object",
|
|
74
|
+
properties: {
|
|
75
|
+
consentId: { type: "string", description: "Consent ID (required for data access)" },
|
|
76
|
+
page: { type: "number", description: "Page number" },
|
|
77
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
78
|
+
},
|
|
79
|
+
required: ["consentId"],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "get_account_balance",
|
|
84
|
+
description: "Get account balance via Open Finance",
|
|
85
|
+
inputSchema: {
|
|
86
|
+
type: "object",
|
|
87
|
+
properties: {
|
|
88
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
89
|
+
accountId: { type: "string", description: "Account ID" },
|
|
90
|
+
},
|
|
91
|
+
required: ["consentId", "accountId"],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "list_transactions",
|
|
96
|
+
description: "List account transactions via Open Finance",
|
|
97
|
+
inputSchema: {
|
|
98
|
+
type: "object",
|
|
99
|
+
properties: {
|
|
100
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
101
|
+
accountId: { type: "string", description: "Account ID" },
|
|
102
|
+
fromDate: { type: "string", description: "Start date (YYYY-MM-DD)" },
|
|
103
|
+
toDate: { type: "string", description: "End date (YYYY-MM-DD)" },
|
|
104
|
+
page: { type: "number", description: "Page number" },
|
|
105
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
106
|
+
},
|
|
107
|
+
required: ["consentId", "accountId"],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "get_consent",
|
|
112
|
+
description: "Get consent details by ID",
|
|
113
|
+
inputSchema: {
|
|
114
|
+
type: "object",
|
|
115
|
+
properties: {
|
|
116
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
117
|
+
},
|
|
118
|
+
required: ["consentId"],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "create_consent",
|
|
123
|
+
description: "Create a new consent request for data access",
|
|
124
|
+
inputSchema: {
|
|
125
|
+
type: "object",
|
|
126
|
+
properties: {
|
|
127
|
+
permissions: {
|
|
128
|
+
type: "array",
|
|
129
|
+
description: "Requested permissions (e.g., ACCOUNTS_READ, ACCOUNTS_BALANCES_READ, ACCOUNTS_TRANSACTIONS_READ)",
|
|
130
|
+
items: { type: "string" },
|
|
131
|
+
},
|
|
132
|
+
expirationDateTime: { type: "string", description: "Consent expiration (ISO 8601)" },
|
|
133
|
+
transactionFromDateTime: { type: "string", description: "Transaction data start (ISO 8601)" },
|
|
134
|
+
transactionToDateTime: { type: "string", description: "Transaction data end (ISO 8601)" },
|
|
135
|
+
},
|
|
136
|
+
required: ["permissions", "expirationDateTime"],
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "list_credit_cards",
|
|
141
|
+
description: "List credit card accounts via Open Finance",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: "object",
|
|
144
|
+
properties: {
|
|
145
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
146
|
+
page: { type: "number", description: "Page number" },
|
|
147
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
148
|
+
},
|
|
149
|
+
required: ["consentId"],
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "get_credit_card_transactions",
|
|
154
|
+
description: "Get credit card transactions via Open Finance",
|
|
155
|
+
inputSchema: {
|
|
156
|
+
type: "object",
|
|
157
|
+
properties: {
|
|
158
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
159
|
+
creditCardAccountId: { type: "string", description: "Credit card account ID" },
|
|
160
|
+
fromDate: { type: "string", description: "Start date (YYYY-MM-DD)" },
|
|
161
|
+
toDate: { type: "string", description: "End date (YYYY-MM-DD)" },
|
|
162
|
+
page: { type: "number", description: "Page number" },
|
|
163
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
164
|
+
},
|
|
165
|
+
required: ["consentId", "creditCardAccountId"],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "list_investments",
|
|
170
|
+
description: "List investment products via Open Finance",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {
|
|
174
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
175
|
+
investmentType: { type: "string", enum: ["BANK_FIXED_INCOMES", "CREDIT_FIXED_INCOMES", "VARIABLE_INCOMES", "TREASURE_TITLES", "FUNDS"], description: "Investment type filter" },
|
|
176
|
+
page: { type: "number", description: "Page number" },
|
|
177
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
178
|
+
},
|
|
179
|
+
required: ["consentId"],
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
}));
|
|
184
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
185
|
+
const { name, arguments: args } = request.params;
|
|
186
|
+
try {
|
|
187
|
+
switch (name) {
|
|
188
|
+
case "list_accounts": {
|
|
189
|
+
const params = new URLSearchParams();
|
|
190
|
+
if (args?.page)
|
|
191
|
+
params.set("page", String(args.page));
|
|
192
|
+
if (args?.pageSize)
|
|
193
|
+
params.set("page-size", String(args.pageSize));
|
|
194
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/accounts/v2/accounts?${params}`), null, 2) }] };
|
|
195
|
+
}
|
|
196
|
+
case "get_account_balance":
|
|
197
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/accounts/v2/accounts/${args?.accountId}/balances`), null, 2) }] };
|
|
198
|
+
case "list_transactions": {
|
|
199
|
+
const params = new URLSearchParams();
|
|
200
|
+
if (args?.fromDate)
|
|
201
|
+
params.set("fromBookingDate", String(args.fromDate));
|
|
202
|
+
if (args?.toDate)
|
|
203
|
+
params.set("toBookingDate", String(args.toDate));
|
|
204
|
+
if (args?.page)
|
|
205
|
+
params.set("page", String(args.page));
|
|
206
|
+
if (args?.pageSize)
|
|
207
|
+
params.set("page-size", String(args.pageSize));
|
|
208
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/accounts/v2/accounts/${args?.accountId}/transactions?${params}`), null, 2) }] };
|
|
209
|
+
}
|
|
210
|
+
case "get_consent":
|
|
211
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/consents/v2/consents/${args?.consentId}`), null, 2) }] };
|
|
212
|
+
case "create_consent": {
|
|
213
|
+
const payload = {
|
|
214
|
+
data: {
|
|
215
|
+
permissions: args?.permissions,
|
|
216
|
+
expirationDateTime: args?.expirationDateTime,
|
|
217
|
+
transactionFromDateTime: args?.transactionFromDateTime,
|
|
218
|
+
transactionToDateTime: args?.transactionToDateTime,
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("POST", "/open-banking/consents/v2/consents", payload), null, 2) }] };
|
|
222
|
+
}
|
|
223
|
+
case "list_credit_cards": {
|
|
224
|
+
const params = new URLSearchParams();
|
|
225
|
+
if (args?.page)
|
|
226
|
+
params.set("page", String(args.page));
|
|
227
|
+
if (args?.pageSize)
|
|
228
|
+
params.set("page-size", String(args.pageSize));
|
|
229
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/credit-cards-accounts/v2/accounts?${params}`), null, 2) }] };
|
|
230
|
+
}
|
|
231
|
+
case "get_credit_card_transactions": {
|
|
232
|
+
const params = new URLSearchParams();
|
|
233
|
+
if (args?.fromDate)
|
|
234
|
+
params.set("fromTransactionDate", String(args.fromDate));
|
|
235
|
+
if (args?.toDate)
|
|
236
|
+
params.set("toTransactionDate", String(args.toDate));
|
|
237
|
+
if (args?.page)
|
|
238
|
+
params.set("page", String(args.page));
|
|
239
|
+
if (args?.pageSize)
|
|
240
|
+
params.set("page-size", String(args.pageSize));
|
|
241
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/credit-cards-accounts/v2/accounts/${args?.creditCardAccountId}/transactions?${params}`), null, 2) }] };
|
|
242
|
+
}
|
|
243
|
+
case "list_investments": {
|
|
244
|
+
const investmentType = args?.investmentType || "BANK_FIXED_INCOMES";
|
|
245
|
+
const params = new URLSearchParams();
|
|
246
|
+
if (args?.page)
|
|
247
|
+
params.set("page", String(args.page));
|
|
248
|
+
if (args?.pageSize)
|
|
249
|
+
params.set("page-size", String(args.pageSize));
|
|
250
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/investments/v1/${investmentType.toLowerCase().replace(/_/g, "-")}?${params}`), null, 2) }] };
|
|
251
|
+
}
|
|
252
|
+
default:
|
|
253
|
+
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
async function main() {
|
|
261
|
+
if (!BASE_URL || !CLIENT_ID || !CLIENT_SECRET) {
|
|
262
|
+
console.error("OPEN_FINANCE_BASE_URL, OPEN_FINANCE_CLIENT_ID, and OPEN_FINANCE_CLIENT_SECRET environment variables are required");
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
const transport = new StdioServerTransport();
|
|
266
|
+
await server.connect(transport);
|
|
267
|
+
}
|
|
268
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codespar/mcp-open-finance",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Open Finance Brasil — accounts, transactions, consents, investments",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp-open-finance": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^25.5.0",
|
|
19
|
+
"typescript": "^5.8.0"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"open-finance",
|
|
25
|
+
"banking",
|
|
26
|
+
"pix",
|
|
27
|
+
"accounts",
|
|
28
|
+
"brazil"
|
|
29
|
+
]
|
|
30
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MCP Server for Open Finance Brasil — open banking standard.
|
|
5
|
+
*
|
|
6
|
+
* Tools:
|
|
7
|
+
* - list_accounts: List customer accounts
|
|
8
|
+
* - get_account_balance: Get account balance
|
|
9
|
+
* - list_transactions: List account transactions
|
|
10
|
+
* - get_consent: Get consent details
|
|
11
|
+
* - create_consent: Create a new consent request
|
|
12
|
+
* - list_credit_cards: List credit card accounts
|
|
13
|
+
* - get_credit_card_transactions: Get credit card transactions
|
|
14
|
+
* - list_investments: List investment products
|
|
15
|
+
*
|
|
16
|
+
* Environment:
|
|
17
|
+
* OPEN_FINANCE_BASE_URL — Institution API base URL
|
|
18
|
+
* OPEN_FINANCE_CLIENT_ID — OAuth2 client ID
|
|
19
|
+
* OPEN_FINANCE_CLIENT_SECRET — OAuth2 client secret
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
23
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
24
|
+
import {
|
|
25
|
+
CallToolRequestSchema,
|
|
26
|
+
ListToolsRequestSchema,
|
|
27
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
28
|
+
|
|
29
|
+
const BASE_URL = process.env.OPEN_FINANCE_BASE_URL || "";
|
|
30
|
+
const CLIENT_ID = process.env.OPEN_FINANCE_CLIENT_ID || "";
|
|
31
|
+
const CLIENT_SECRET = process.env.OPEN_FINANCE_CLIENT_SECRET || "";
|
|
32
|
+
|
|
33
|
+
let accessToken = "";
|
|
34
|
+
let tokenExpiry = 0;
|
|
35
|
+
|
|
36
|
+
async function getAccessToken(): Promise<string> {
|
|
37
|
+
if (accessToken && Date.now() < tokenExpiry) return accessToken;
|
|
38
|
+
|
|
39
|
+
const res = await fetch(`${BASE_URL}/auth/token`, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
42
|
+
body: new URLSearchParams({
|
|
43
|
+
grant_type: "client_credentials",
|
|
44
|
+
client_id: CLIENT_ID,
|
|
45
|
+
client_secret: CLIENT_SECRET,
|
|
46
|
+
scope: "openid accounts credit-cards-accounts resources consents investments",
|
|
47
|
+
}),
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const err = await res.text();
|
|
51
|
+
throw new Error(`Open Finance OAuth ${res.status}: ${err}`);
|
|
52
|
+
}
|
|
53
|
+
const data = await res.json() as { access_token: string; expires_in: number };
|
|
54
|
+
accessToken = data.access_token;
|
|
55
|
+
tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;
|
|
56
|
+
return accessToken;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function openFinanceRequest(method: string, path: string, body?: unknown): Promise<unknown> {
|
|
60
|
+
const token = await getAccessToken();
|
|
61
|
+
const res = await fetch(`${BASE_URL}${path}`, {
|
|
62
|
+
method,
|
|
63
|
+
headers: {
|
|
64
|
+
"Content-Type": "application/json",
|
|
65
|
+
"Authorization": `Bearer ${token}`,
|
|
66
|
+
},
|
|
67
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
68
|
+
});
|
|
69
|
+
if (!res.ok) {
|
|
70
|
+
const err = await res.text();
|
|
71
|
+
throw new Error(`Open Finance API ${res.status}: ${err}`);
|
|
72
|
+
}
|
|
73
|
+
return res.json();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const server = new Server(
|
|
77
|
+
{ name: "mcp-open-finance", version: "0.1.0" },
|
|
78
|
+
{ capabilities: { tools: {} } }
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
82
|
+
tools: [
|
|
83
|
+
{
|
|
84
|
+
name: "list_accounts",
|
|
85
|
+
description: "List customer bank accounts via Open Finance",
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
consentId: { type: "string", description: "Consent ID (required for data access)" },
|
|
90
|
+
page: { type: "number", description: "Page number" },
|
|
91
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
92
|
+
},
|
|
93
|
+
required: ["consentId"],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "get_account_balance",
|
|
98
|
+
description: "Get account balance via Open Finance",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
103
|
+
accountId: { type: "string", description: "Account ID" },
|
|
104
|
+
},
|
|
105
|
+
required: ["consentId", "accountId"],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "list_transactions",
|
|
110
|
+
description: "List account transactions via Open Finance",
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: "object",
|
|
113
|
+
properties: {
|
|
114
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
115
|
+
accountId: { type: "string", description: "Account ID" },
|
|
116
|
+
fromDate: { type: "string", description: "Start date (YYYY-MM-DD)" },
|
|
117
|
+
toDate: { type: "string", description: "End date (YYYY-MM-DD)" },
|
|
118
|
+
page: { type: "number", description: "Page number" },
|
|
119
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
120
|
+
},
|
|
121
|
+
required: ["consentId", "accountId"],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "get_consent",
|
|
126
|
+
description: "Get consent details by ID",
|
|
127
|
+
inputSchema: {
|
|
128
|
+
type: "object",
|
|
129
|
+
properties: {
|
|
130
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
131
|
+
},
|
|
132
|
+
required: ["consentId"],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "create_consent",
|
|
137
|
+
description: "Create a new consent request for data access",
|
|
138
|
+
inputSchema: {
|
|
139
|
+
type: "object",
|
|
140
|
+
properties: {
|
|
141
|
+
permissions: {
|
|
142
|
+
type: "array",
|
|
143
|
+
description: "Requested permissions (e.g., ACCOUNTS_READ, ACCOUNTS_BALANCES_READ, ACCOUNTS_TRANSACTIONS_READ)",
|
|
144
|
+
items: { type: "string" },
|
|
145
|
+
},
|
|
146
|
+
expirationDateTime: { type: "string", description: "Consent expiration (ISO 8601)" },
|
|
147
|
+
transactionFromDateTime: { type: "string", description: "Transaction data start (ISO 8601)" },
|
|
148
|
+
transactionToDateTime: { type: "string", description: "Transaction data end (ISO 8601)" },
|
|
149
|
+
},
|
|
150
|
+
required: ["permissions", "expirationDateTime"],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "list_credit_cards",
|
|
155
|
+
description: "List credit card accounts via Open Finance",
|
|
156
|
+
inputSchema: {
|
|
157
|
+
type: "object",
|
|
158
|
+
properties: {
|
|
159
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
160
|
+
page: { type: "number", description: "Page number" },
|
|
161
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
162
|
+
},
|
|
163
|
+
required: ["consentId"],
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "get_credit_card_transactions",
|
|
168
|
+
description: "Get credit card transactions via Open Finance",
|
|
169
|
+
inputSchema: {
|
|
170
|
+
type: "object",
|
|
171
|
+
properties: {
|
|
172
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
173
|
+
creditCardAccountId: { type: "string", description: "Credit card account ID" },
|
|
174
|
+
fromDate: { type: "string", description: "Start date (YYYY-MM-DD)" },
|
|
175
|
+
toDate: { type: "string", description: "End date (YYYY-MM-DD)" },
|
|
176
|
+
page: { type: "number", description: "Page number" },
|
|
177
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
178
|
+
},
|
|
179
|
+
required: ["consentId", "creditCardAccountId"],
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "list_investments",
|
|
184
|
+
description: "List investment products via Open Finance",
|
|
185
|
+
inputSchema: {
|
|
186
|
+
type: "object",
|
|
187
|
+
properties: {
|
|
188
|
+
consentId: { type: "string", description: "Consent ID" },
|
|
189
|
+
investmentType: { type: "string", enum: ["BANK_FIXED_INCOMES", "CREDIT_FIXED_INCOMES", "VARIABLE_INCOMES", "TREASURE_TITLES", "FUNDS"], description: "Investment type filter" },
|
|
190
|
+
page: { type: "number", description: "Page number" },
|
|
191
|
+
pageSize: { type: "number", description: "Items per page" },
|
|
192
|
+
},
|
|
193
|
+
required: ["consentId"],
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
}));
|
|
198
|
+
|
|
199
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
200
|
+
const { name, arguments: args } = request.params;
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
switch (name) {
|
|
204
|
+
case "list_accounts": {
|
|
205
|
+
const params = new URLSearchParams();
|
|
206
|
+
if (args?.page) params.set("page", String(args.page));
|
|
207
|
+
if (args?.pageSize) params.set("page-size", String(args.pageSize));
|
|
208
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/accounts/v2/accounts?${params}`), null, 2) }] };
|
|
209
|
+
}
|
|
210
|
+
case "get_account_balance":
|
|
211
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/accounts/v2/accounts/${args?.accountId}/balances`), null, 2) }] };
|
|
212
|
+
case "list_transactions": {
|
|
213
|
+
const params = new URLSearchParams();
|
|
214
|
+
if (args?.fromDate) params.set("fromBookingDate", String(args.fromDate));
|
|
215
|
+
if (args?.toDate) params.set("toBookingDate", String(args.toDate));
|
|
216
|
+
if (args?.page) params.set("page", String(args.page));
|
|
217
|
+
if (args?.pageSize) params.set("page-size", String(args.pageSize));
|
|
218
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/accounts/v2/accounts/${args?.accountId}/transactions?${params}`), null, 2) }] };
|
|
219
|
+
}
|
|
220
|
+
case "get_consent":
|
|
221
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/consents/v2/consents/${args?.consentId}`), null, 2) }] };
|
|
222
|
+
case "create_consent": {
|
|
223
|
+
const payload = {
|
|
224
|
+
data: {
|
|
225
|
+
permissions: args?.permissions,
|
|
226
|
+
expirationDateTime: args?.expirationDateTime,
|
|
227
|
+
transactionFromDateTime: args?.transactionFromDateTime,
|
|
228
|
+
transactionToDateTime: args?.transactionToDateTime,
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("POST", "/open-banking/consents/v2/consents", payload), null, 2) }] };
|
|
232
|
+
}
|
|
233
|
+
case "list_credit_cards": {
|
|
234
|
+
const params = new URLSearchParams();
|
|
235
|
+
if (args?.page) params.set("page", String(args.page));
|
|
236
|
+
if (args?.pageSize) params.set("page-size", String(args.pageSize));
|
|
237
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/credit-cards-accounts/v2/accounts?${params}`), null, 2) }] };
|
|
238
|
+
}
|
|
239
|
+
case "get_credit_card_transactions": {
|
|
240
|
+
const params = new URLSearchParams();
|
|
241
|
+
if (args?.fromDate) params.set("fromTransactionDate", String(args.fromDate));
|
|
242
|
+
if (args?.toDate) params.set("toTransactionDate", String(args.toDate));
|
|
243
|
+
if (args?.page) params.set("page", String(args.page));
|
|
244
|
+
if (args?.pageSize) params.set("page-size", String(args.pageSize));
|
|
245
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/credit-cards-accounts/v2/accounts/${args?.creditCardAccountId}/transactions?${params}`), null, 2) }] };
|
|
246
|
+
}
|
|
247
|
+
case "list_investments": {
|
|
248
|
+
const investmentType = args?.investmentType || "BANK_FIXED_INCOMES";
|
|
249
|
+
const params = new URLSearchParams();
|
|
250
|
+
if (args?.page) params.set("page", String(args.page));
|
|
251
|
+
if (args?.pageSize) params.set("page-size", String(args.pageSize));
|
|
252
|
+
return { content: [{ type: "text", text: JSON.stringify(await openFinanceRequest("GET", `/open-banking/investments/v1/${investmentType.toLowerCase().replace(/_/g, "-")}?${params}`), null, 2) }] };
|
|
253
|
+
}
|
|
254
|
+
default:
|
|
255
|
+
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
256
|
+
}
|
|
257
|
+
} catch (err) {
|
|
258
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
async function main() {
|
|
263
|
+
if (!BASE_URL || !CLIENT_ID || !CLIENT_SECRET) {
|
|
264
|
+
console.error("OPEN_FINANCE_BASE_URL, OPEN_FINANCE_CLIENT_ID, and OPEN_FINANCE_CLIENT_SECRET environment variables are required");
|
|
265
|
+
process.exit(1);
|
|
266
|
+
}
|
|
267
|
+
const transport = new StdioServerTransport();
|
|
268
|
+
await server.connect(transport);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
main().catch(console.error);
|
package/tsconfig.json
ADDED