Remote MCP server exposing BFlow to AI agents. Talks to the BFlow API over HTTPS as an ordinary OAuth2 client — no dependency on bflow's domain module, repositories, or database.
bflow-mcp demonstrates solid tool design with consistent naming (verb_noun pattern), comprehensive parameter schemas, and clear descriptions. All 10 tools follow action-verb conventions (list*, create*, update*, get*). Descriptions average ~120 chars, meeting the 10-1024 char baseline. Input schemas are well-typed with descriptions for all parameters. However, output schemas are not documented in the provided source, and error handling lacks recovery guidance. Write operations include confirmation patterns (confirmed=true), which is excellent for safety. Missing: explicit output schema documentation, error classification, and per-tool audit logging hints.
Creates a new budget covering all spending in one wallet (e.g. 'set a $200 monthly budget for my personal wallet'). Does not support per-category budgets yet. Requires confirmed=true to actually execute — call once to get a preview, show it to the user, then call again with confirmed=true.
Creates a new recurring expense or income schedule (e.g. a monthly subscription, a biweekly paycheck). BFlow generates the individual transactions from this automatically — use createTransaction instead for a one-off entry. Requires confirmed=true to actually execute — call once to get a preview, show it to the user, then call again with confirmed=true.
Creates a new expense or income entry for the current user (e.g. 'I bought a phone for $500' is an EXPENSE, 'I got paid my salary' is an INCOME). Does not handle recurring transactions. If retrying after an unclear result, pass the same idempotencyKey used before instead of calling again blind. Requires confirmed=true to actually execute — call once to get a preview, show it to the user, then call again with confirmed=true.
Gets a summary of the current user's spending for the current month, across all their wallets.
Lists the current user's budgets, across all their wallets.
Output schemas not documented. Tool descriptions state what is returned (e.g., 'Lists the wallets...') but do not specify the structure of returned objects, field names, or types. LLMs cannot plan downstream tool calls without knowing what fields to extract.
Error handling lacks recovery guidance. No tool description explains what to do if a call fails (e.g., 'If wallet not found, call listWallets() first'). Error responses are not categorized as retryable, user-fixable, or fatal.
List tools lack pagination parameters. listTransactions, listBudgets, listRecurring, and listCategories accept no limit, offset, or cursor parameters. Large result sets will blow context windows and degrade LLM reasoning.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 57 | <=2025-11-25 | v2 |
Lists the transaction categories available in BFlow, including each category's id, name, type (INCOME, EXPENSE or TRANSFER), icon and color. Use this to look up the categoryId needed by tools that create transactions or budgets.
Lists the current user's recurring transactions (scheduled expenses/incomes).
Lists the current user's transactions (expenses, incomes, transfers) across all their wallets.
Lists the wallets the current user owns or belongs to.
Updates an existing expense or income entry. This replaces the whole entry, so pass every field, not just the one that changed — read the transaction first if unsure of its current values, especially 'recurring' (passing recurring=false on a recurring transaction turns recurrence off). Requires confirmed=true to actually execute — call once to get a preview, show it to the user, then call again with confirmed=true.
Confirmation pattern (confirmed=true) is well-implemented for write operations, but no tool description explains the two-step flow or what the preview response contains. LLMs may not understand they must call twice.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint) are not declared in tool definitions. Spring AI supports these via @Tool annotation attributes, but no evidence they are used. This prevents clients from understanding tool safety properties.