monobank-mcp-server
Version:
MCP server for Monobank API integration
90 lines (89 loc) • 4.04 kB
JavaScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { CurrencyRatesResponseSchema, StatementItemSchema } from "./schemas.js";
import { createSuccessResponse, fetchWithErrorHandling, parseJsonResponse, formatErrorAsToolResponse, validateStatementDates, formatStatementItems, } from "./helpers.js";
import { initializeConfig, getConfig } from "./config.js";
const server = new McpServer({
name: "monobank-mcp-server",
version: "1.0.0",
capabilities: {
tools: {},
},
});
server.tool("get_currency_rates", "Get a basic list of currency rates from Monobank. The information can be refreshed once per 5 minutes, otherwise an error will be thrown.", {}, async () => {
try {
const { baseUrl } = getConfig();
const response = await fetchWithErrorHandling(`${baseUrl}/bank/currency`);
const result = await parseJsonResponse(response);
const currencyRates = CurrencyRatesResponseSchema.parse(result);
return createSuccessResponse(currencyRates);
}
catch (error) {
return formatErrorAsToolResponse(error, "get currency rates");
}
});
server.tool("get_client_info", "Get information about a client and a list of their accounts and jars. The tool can be called not more than 1 time per 60 seconds, otherwise an error will be thrown.", {}, async () => {
try {
const { baseUrl, monobankApiToken } = getConfig();
const response = await fetchWithErrorHandling(`${baseUrl}/personal/client-info`, {
headers: {
"X-Token": monobankApiToken,
},
});
const clientInfo = await parseJsonResponse(response);
return createSuccessResponse(clientInfo);
}
catch (error) {
return formatErrorAsToolResponse(error, "get client info");
}
});
server.tool("get_statement", "Get Monobank statement for the time from {from} to {to} time in seconds in Unix time format. The maximum time for which it is posssible to obtain a statement is 31 days + 1 hour (2682000 seconds). The statement can be retrieved not more than once per 60 seconds, otherwise an error will be thrown.", {
input: z.object({
account: z
.string()
.nonempty()
.describe("A unique indentificator of the Monobank account or a jar from the Statement list. If not provided, then a defaukt account is used, which is equal to '0'."),
from: z
.string()
.nonempty()
.describe("A date in ISO 8601 YYYY-MM-DD format."),
to: z
.string()
.optional()
.describe("A date in ISO 8601 YYYY-MM-DD format."),
}),
}, async ({ input }) => {
try {
const { account, from, to } = input;
const dateValidation = validateStatementDates(from, to);
if ("content" in dateValidation) {
return dateValidation;
}
const { fromInSeconds, toInSeconds } = dateValidation;
const { baseUrl, monobankApiToken } = getConfig();
const response = await fetchWithErrorHandling(`${baseUrl}/personal/statement/${account}/${fromInSeconds}/${toInSeconds}`, {
headers: {
"X-Token": monobankApiToken,
},
});
const data = await parseJsonResponse(response);
const statement = z.array(StatementItemSchema).parse(data);
const formattedStatement = formatStatementItems(statement);
return createSuccessResponse(formattedStatement);
}
catch (error) {
return formatErrorAsToolResponse(error, "fetch statement");
}
});
async function main() {
initializeConfig();
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Monobank MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});