Tool catalog
The full list of tools the Fealthy MCP server gives an agent — 70 of them, grouped by entity. Each one shows its name, a short description, whether a Read-level token is enough to call it, and an expandable list of its call parameters.
The full list of tools the Fealthy MCP server gives an agent — 70 of them, grouped by entity. Each one shows its name, a short description, whether a Read-level token is enough to call it, and an expandable list of its call parameters.
Creating and managing the user's accounts, plus the reference lists used to fill them in (colors, card presets, currencies, providers).
list_account_colorsReadList account colors
Global reference list of card colours, each naming the account types it is allowed on. Needed to fill create_account's and update_account's colorId.
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | optional | |
offset | integer | optional |
list_account_presetsReadList account presets
Global reference list of available card designs / bank products. Needed to fill create_account's and update_account's accountPresetUid.
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | optional | |
offset | integer | optional |
list_accountsReadList accounts
List the caller's own, non-deleted accounts with their current balance, initial balance, and bank-sync state. Accounts blocked by a plan limit are included like any other -- this tool never filters by plan. Supports filtering by currency, type, origin, provider and a case-insensitive name search.
| Name | Type | Required | Description |
|---|---|---|---|
currencyCode | string | optional | |
type | cash | credit_card | debit_card | banking | savings | investment | loan | manual | target | monobank_jar | privatbank_envelope | optional | |
origin | sync | manual | mixed | optional | |
providerUid | string | optional | |
search | string | optional | |
limit | integer | optional | |
offset | integer | optional |
list_currenciesReadList currencies
Global reference list of currencies Fealthy knows about, each with a flag for whether a new account can be created in it. Needed to fill create_account's currencyCode.
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | optional | |
offset | integer | optional |
list_providersReadList providers
Global reference list of banks and payment services. Needed to fill create_account's providerUid and to decode a providerUid elsewhere.
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | optional | |
offset | integer | optional |
get_accountReadGet an account
Reads one of the caller's own accounts by uid, including one blocked by a plan limit. A foreign or nonexistent uid returns not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
accountUid | string | required |
create_accountWriteCreate a manual account
Creates a new manual account the same way the Fealthy app does (never a bank-synced one -- Monobank and other sync connections happen inside the app). Same plan limit on account count as the app.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | |
type | debit_card | credit_card | banking | cash | manual | required | |
currencyCode | string | required | |
providerUid | string | optional | |
accountPresetUid | string | optional | |
colorId | string | optional | |
initialBalance | number | optional | |
excludeFromStatisticsByDefault | boolean | optional |
update_accountWriteUpdate an account
Renames an account, changes its statistics-exclusion flag, card colour, card design (only when not fully bank-synced), or type (only when it has no bank). Currency, initial balance, bank connection, card number and description can never be changed here.
| Name | Type | Required | Description |
|---|---|---|---|
accountUid | string | required | |
name | string | optional | |
excludeFromStatisticsByDefault | boolean | optional | |
colorId | string | optional | |
accountPresetUid | string | optional | |
type | debit_card | credit_card | banking | cash | manual | optional |
delete_accountWriteDelete an account
Deletes one of the caller's own accounts, including a bank-synced one (sync stops). WARNING: every transaction on this account is deleted with it. Refused when the account is linked to a savings target.
| Name | Type | Required | Description |
|---|---|---|---|
accountUid | string | required |
Transactions, transfers, currency exchange, and splitting a transaction into parts.
list_exchange_ratesReadList exchange rates
Global reference list of the current exchange rates the Fealthy app uses, for converting amounts between currencies. Optionally filter to one currency pair. An unreachable rates source is reported as an error, never a guessed rate.
| Name | Type | Required | Description |
|---|---|---|---|
baseCurrency | string | optional | |
targetCurrency | string | optional | |
limit | integer | optional | |
offset | integer | optional |
list_transactionsReadList transactions
Lists the caller's own transactions with filters, paged (limit up to 200, offset) and sorted by date or amount, plus the total count matching the filters. Initial-balance service records are never included. Filtering by a top-level categoryUid also matches its subcategories and any transaction whose category was only auto-detected, never manually set. NOT covered here (a known scope gap, tracked separately): free-text search over description/bank details, and hiding split "parent" transactions by default -- a parent and its parts (see get_transaction/create_split) are both included, so summing amounts over an unfiltered page double-counts a split transaction's total.
| Name | Type | Required | Description |
|---|---|---|---|
dateFrom | string | optional | |
dateTo | string | optional | |
accountUidIn | array of string | optional | |
categoryUidIn | array of string | optional | |
merchantUidIn | array of string | optional | |
labelUidIn | array of string | optional | |
direction | expense | income | optional | |
amountFrom | number | optional | |
amountTo | number | optional | |
sortBy | date | amount | optional | |
sortDirection | asc | desc | optional | |
limit | integer | optional | |
offset | integer | optional |
get_transactionReadGet a transaction
Reads one of the caller's own transactions by uid. If it has been split, its parts are included under "parts". A foreign or nonexistent uid returns not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
transactionUid | string | required |
create_exchangeWriteCreate a currency exchange between own accounts
Exchanges currency between two of the caller's own manual accounts with DIFFERENT currencies: creates a withdrawal of sentAmount on fromAccountUid and a deposit of receivedAmount on toAccountUid, linked exactly like the app's own "Обмін валют" action. Use create_transfer instead when the two accounts share the same currency. Counts as a single operation regardless of the two transactions it creates.
| Name | Type | Required | Description |
|---|---|---|---|
fromAccountUid | string | required | |
toAccountUid | string | required | |
sentAmount | number | required | |
receivedAmount | number | required | |
datetime | string | required | |
description | string | optional |
create_splitWriteSplit a transaction into parts
Splits one of the caller's own transactions into parts, each with its own required category and optional merchant/labels/description -- exactly like the app's own split action. The parts' amounts must sum to the transaction's own amount (0.01 tolerance) or nothing is created. Refused for a transaction that is already a split part, is already split, or belongs to a savings-target account. Counts as a single operation regardless of how many parts it creates.
| Name | Type | Required | Description |
|---|---|---|---|
transactionUid | string | required | |
parts | array of object { amount, categoryUid, merchantUid, labelsUids, description } | required |
create_transactionWriteCreate expense or income transactions
Creates 1 to 50 expenses or incomes in one call (e.g. every line of a receipt) -- each item succeeds or fails independently, so one bad item never cancels the rest. amount is in the account's own currency (negative = expense, positive = income); the transaction's currency is always the account's currency and cannot be chosen. categoryUid is required: manually created transactions (from the app or from an agent) are never auto-categorised, so pick the closest category yourself with list_categories. The server always generates each new transaction's uid. A fully bank-synced account cannot be written to manually.
| Name | Type | Required | Description |
|---|---|---|---|
items | array of object { accountUid, categoryUid, datetime, amount, originalAmount, originalCurrencyCode, merchantUid, labelsUids, description } | required |
create_transferWriteCreate a transfer between own accounts
Moves money between two of the caller's own manual accounts in the SAME currency: creates a withdrawal on fromAccountUid and a deposit on toAccountUid, linked as a transfer exactly like the app's own "Переказ" action. Use create_exchange instead when the two accounts have different currencies. Counts as a single operation regardless of the two transactions it creates.
| Name | Type | Required | Description |
|---|---|---|---|
fromAccountUid | string | required | |
toAccountUid | string | required | |
amount | number | required | |
datetime | string | required | |
description | string | optional |
update_splitWriteChange the parts of a split transaction
Replaces the full set of parts of one of the caller's already-split transactions in one call: pass the uid of an existing part to change it, omit uid to add a new part, and leave out a previously existing part's uid to remove it. The full new set of amounts must still sum to the transaction's own amount (0.01 tolerance).
| Name | Type | Required | Description |
|---|---|---|---|
transactionUid | string | required | |
parts | array of object { uid, amount, categoryUid, merchantUid, labelsUids, description } | required |
update_transactionWriteUpdate transactions
Changes 1 to 50 of the caller's own transactions in one call -- only the fields each item passes are changed; the rest keep their current value. labelsUids replaces the full label set (pass [] to clear it); merchantUid: null removes the merchant. Changing the date of a split transaction (a parent with parts) also moves its parts, as in the app. A fully bank-synced account only allows changing category, description, labels and merchant on its transactions -- amount, date and account can never change there. The amount of a split parent or one of its parts can never be changed here; use update_split instead.
| Name | Type | Required | Description |
|---|---|---|---|
items | array of object { transactionUid, datetime, amount, originalAmount, originalCurrencyCode, accountUid, categoryUid, merchantUid, labelsUids, description } | required |
delete_splitWriteCancel a split
Cancels the split of one of the caller's own transactions: its parts are removed and the transaction itself takes on the first part's category, exactly like the app's own "Скасувати поділ" action.
| Name | Type | Required | Description |
|---|---|---|---|
transactionUid | string | required |
delete_transactionWriteDelete transactions
Deletes 1 to 50 of the caller's own transactions in one call. Deleting a split transaction (a parent with parts) also deletes all of its parts, as in the app. A transaction on a fully bank-synced account cannot be deleted this way (cancelling a split via delete_split is the one exception). Deleting an already-deleted transaction is not an error.
| Name | Type | Required | Description |
|---|---|---|---|
items | array of object { transactionUid } | required |
Explicit links between transactions that already exist: a cancellation (a refund linked back to its original purchase) or a transfer (two already-recorded legs of one move, linked to each other).
list_transaction_relationsReadList transaction relations
Lists the caller's own transaction relations (refund-to-purchase cancellations and account-to-account transfers), paged. transactionUid filters to relations where that transaction appears on either side (a value the caller does not own returns an empty page, like every other xUidIn-style filter here). type filters to "cancellation" or "transfer". A handful of relations created before this mirror column existed are missing one of their two transaction uids on the underlying row -- those are silently excluded here rather than failing the whole list for one broken historical row.
| Name | Type | Required | Description |
|---|---|---|---|
transactionUid | string | optional | |
type | cancellation | transfer | optional | |
limit | integer | optional | |
offset | integer | optional |
get_transaction_relationReadGet a transaction relation
Reads one of the caller's own transaction relations by the relation's own uid (not either linked transaction's uid). A foreign, nonexistent, or historically broken (missing one of its two transaction uids) relation all return not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
relationUid | string | required |
create_transaction_relationWriteLink two transactions
Links two of the caller's own transactions as a "cancellation" (a refund/return cancelling out an earlier purchase) or a "transfer" (the two legs of a move between the caller's own accounts, each already recorded separately) -- the same as the app's own "Пов'язати транзакцію" action. One of the two must be an expense (negative amount) and the other an income (positive amount); direction (which uid becomes transactionUid vs targetTransactionUid) is aligned automatically to match the app, regardless of which order the caller passed them in. Calling this again for the same pair and type is safe and returns the existing relation rather than a duplicate; the same pair already linked as the OTHER type is a conflict -- delete_transaction_relation first. A part of a split transaction cannot be linked while its parent already has a relation, and a split transaction cannot be linked while one of its parts already has a relation. To record a refund for a purchase: first create_transaction for the new income, then link it here with type "cancellation". Creating a transfer from scratch (both transactions plus the link, in one call) is create_transfer, not this tool.
| Name | Type | Required | Description |
|---|---|---|---|
type | cancellation | transfer | required | |
transactionUid | string | required | |
targetTransactionUid | string | required |
delete_transaction_relationWriteUnlink two transactions
Removes one of the caller's own transaction relations by the relation's own uid -- the same as the app's own "Відв'язати" action. Neither linked transaction is changed or deleted. There is no update_ tool, matching the app: to change a relation's type, delete it and create a new one. A foreign, nonexistent, or already-deleted relation uid is not_found, never a silent no-op.
| Name | Type | Required | Description |
|---|---|---|---|
relationUid | string | required |
Subscriptions, recurring bills, and scheduled one-off payments.
list_transaction_schedulesReadList subscriptions, bills and planned payments
Lists the caller's own subscriptions, recurring bills and planned one-off payments, optionally filtered by type (subscription / bill / planned), source (manual / auto -- auto-detected), validity (approved / pending / rejected -- an auto-detected record awaiting a decision is pending), account (accountUid), category (categoryUid) or merchant (merchantUid). Paged (limit up to 200, offset). A rejected auto-detected record is never returned.
| Name | Type | Required | Description |
|---|---|---|---|
type | subscription | bill | planned | optional | |
source | manual | auto | optional | |
validity | approved | pending | rejected | optional | |
accountUid | string | optional | |
categoryUid | string | optional | |
merchantUid | string | optional | |
limit | integer | optional | |
offset | integer | optional |
get_transaction_scheduleReadGet a subscription, bill or planned payment
Reads one of the caller's own subscriptions, bills or planned payments by uid, with all its fields. A foreign or nonexistent uid returns not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
transactionScheduleUid | string | required |
create_transaction_scheduleWriteCreate a subscription, bill or planned payment
Creates a subscription, recurring bill or planned one-off payment exactly like the app's own forms. subscription/bill require frequency (daily/weekly/monthly/yearly), startDate and an optional interval (step, default 1) and endDate; planned requires datetime instead and accepts none of those. amount is always positive -- whether it becomes an expense or income is decided by categoryUid's own type, same as in the app. A date with no time (or exactly local midnight) is stored at 09:00 local time (end-of-day local for endDate) so the payment date never shifts across a daylight-saving change; an explicit time is kept as given. currencyCode defaults to the caller's own selected currency. The server always generates the new record's uid.
| Name | Type | Required | Description |
|---|---|---|---|
type | subscription | bill | planned | required | |
name | string | optional | |
description | string | optional | |
amount | number | required | |
currencyCode | string | optional | |
categoryUid | string | required | |
accountUid | string | optional | |
merchantUid | string | optional | |
labelsUids | array of string | optional | |
frequency | daily | weekly | monthly | yearly | optional | |
interval | integer | optional | |
startDate | string | optional | |
endDate | string | optional | |
datetime | string | optional | |
remindersEnabled | boolean | optional | |
reminderOffsetsSeconds | array of integer | optional |
update_transaction_scheduleWriteUpdate a subscription, bill or planned payment
Changes one of the caller's own records by uid -- a field not passed keeps its current value; type can never change. transactionsUids/labelsUids each replace the full set (to add one transaction, pass the existing ones plus the new one; [] clears them). excludeOccurrenceDate removes exactly one future occurrence (by its local calendar date) from a subscription/bill's recurrence -- pass it alone to "skip" that payment, or together with a full transactionsUids (old + new) to "confirm" it by linking the paying transaction. Changing the recurrence itself requires frequency AND startDate together (interval/endDate optional, same as create) -- it replaces the whole rule, including any previous excluded dates. validity (approved/rejected) is the ONLY field this tool accepts together on an auto-detected record that has not been decided yet, and the ONLY thing accepted at all: approving moves it out of "Виявлені" into the active list, rejecting removes it; a manual or already-decided record rejects any validity change. A foreign, nonexistent or already-rejected uid returns not_found.
| Name | Type | Required | Description |
|---|---|---|---|
transactionScheduleUid | string | required | |
name | string | null | optional | |
description | string | null | optional | |
amount | number | optional | |
currencyCode | string | optional | |
categoryUid | string | optional | |
accountUid | string | null | optional | |
merchantUid | string | null | optional | |
labelsUids | array of string | optional | |
transactionsUids | array of string | optional | |
frequency | daily | weekly | monthly | yearly | optional | |
interval | integer | optional | |
startDate | string | optional | |
endDate | string | null | optional | |
datetime | string | optional | |
excludeOccurrenceDate | string | optional | |
remindersEnabled | boolean | optional | |
reminderOffsetsSeconds | array of integer | optional | |
validity | approved | rejected | optional |
delete_transaction_scheduleWriteDelete a subscription, bill or planned payment
Deletes one of the caller's own records by uid, like the "Видалити" button in the app. An auto-detected record awaiting a decision (validity pending) must be approved or rejected first. A foreign, nonexistent or already-deleted uid returns not_found (deleting an already-deleted schedule is not idempotent).
| Name | Type | Required | Description |
|---|---|---|---|
transactionScheduleUid | string | required |
Rules that automatically categorize new transactions from bank sync and statement imports.
list_transaction_rulesReadList categorization rules
Lists the caller's own transaction categorization rules ("Правила" in Fealthy Settings), ordered by priority (index, ascending -- the first rule that matches a transaction wins; see create_transaction_rule's own description for how that interacts with Fealthy's built-in rules). Optional filters: enabled (true/false), categoryUid, merchantUid, labelsUids (matches a rule whose own labels include ANY of the given ones), and a case-insensitive substring search over the rule's name. A disabled rule is included with enabled: false; a deleted rule never is. Paged (limit up to 200, offset).
| Name | Type | Required | Description |
|---|---|---|---|
enabled | boolean | optional | |
categoryUid | string | optional | |
merchantUid | string | optional | |
labelsUids | array of string | optional | |
search | string | optional | |
limit | integer | optional | |
offset | integer | optional |
get_transaction_ruleReadGet a categorization rule
Reads one of the caller's own categorization rules by uid: its condition, actions (category/merchant/labels), validity period, priority (index) and enabled flag. A foreign or nonexistent uid returns not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
transactionRuleUid | string | required |
create_transaction_ruleWriteCreate a categorization rule
Creates a rule that automatically categorizes future transactions from bank sync and statement imports -- e.g. "everything with description containing 'Сільпо' -> category Продукти, label Дім" -- exactly like Settings -> Правила -> new rule. Requires a non-empty name, at least one condition (see the field list below), and at least one action: categoryUid, merchantUid, or a non-empty labelsUids. Text comparisons (Contains/StartsWith/EndsWith/Matches and their Not* variants) are case-sensitive. The rule always becomes LAST in priority (lowest priority); call list_transaction_rules first and check for a broader existing rule that would match the same transactions and pre-empt this one, since among the caller's own rules only the first match (by priority) applies -- if it has no category, Fealthy's built-in rules fill that in, but no other rule of the caller's is checked after it. This rule is applied automatically to new transactions from bank sync and statement imports; it never re-runs against transactions that already exist. condition fields: accountUidEq/Ne/In/Nin (only the caller's own accounts), amountEq/Ne/In/Nin/Gt/Gte/Lt/Lte, datetimeEq/Ne/Gt/Gte/Lt/Lte (ISO 8601), descriptionEq/Ne/In/Nin/Matches/NotMatches/StartsWith/NotStartsWith/EndsWith/NotEndsWith/Contains/NotContains, the same set for details, and and/or groups of nested conditions (each non-empty). categoryUid/merchantUid may reference either the caller's own or a shared (global) record; labelsUids only the caller's own. The server always generates the new rule's uid.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | |
condition | any | required | |
categoryUid | string | optional | |
merchantUid | string | optional | |
labelsUids | array of string | optional | |
startsAt | string | optional | |
endsAt | string | optional | |
enabled | boolean | optional |
update_transaction_ruleWriteUpdate a categorization rule
Changes one of the caller's own categorization rules: name, condition, actions (categoryUid/merchantUid/labelsUids), validity period, or enabled -- a field not passed keeps its current value. categoryUid/merchantUid: null removes that action (at least one action must remain among category/merchant/labels); labelsUids replaces the full label set (pass [] to clear it). The rule's priority (index) can never be changed here, same as in the app -- there is no reorder screen. A foreign, nonexistent, or already-deleted uid returns not_found... except a repeat call on the caller's OWN already-deleted rule, which returns success with status already_deleted rather than an error.
| Name | Type | Required | Description |
|---|---|---|---|
transactionRuleUid | string | required | |
name | string | optional | |
condition | any | optional | |
categoryUid | string | null | optional | |
merchantUid | string | null | optional | |
labelsUids | array of string | optional | |
startsAt | string | null | optional | |
endsAt | string | null | optional | |
enabled | boolean | optional |
delete_transaction_ruleWriteDelete a categorization rule
Deletes one of the caller's own categorization rules (soft delete, same as the app's delete action) -- it disappears from the list and stops affecting new transactions immediately. A foreign or nonexistent uid returns not_found. Calling this again on the caller's own already-deleted rule is not an error: it returns success with status already_deleted.
| Name | Type | Required | Description |
|---|---|---|---|
transactionRuleUid | string | required |
Custom and built-in categories, including hiding (archiving) a built-in category.
list_categoriesReadList categories
Lists the caller's categories -- system categories (with the caller's own renames/hides applied) plus their own custom ones -- as a two-level tree of top-level category + subcategories. Hidden (archived) categories are excluded unless includeArchived is set. Pass parentUid to instead list only the subcategories of one top-level category (an unknown, foreign, or non-top-level parentUid returns an empty list, not an error).
| Name | Type | Required | Description |
|---|---|---|---|
type | unknown | income | transfer | expense | optional | |
source | default | user | optional | |
includeArchived | boolean | optional | |
parentUid | string | optional | |
search | string | optional | |
limit | integer | optional | |
offset | integer | optional |
get_categoryReadGet a category
Reads one category the caller can see (system or own, top-level or subcategory) by uid, together with its subcategories if it is top-level. A foreign or nonexistent uid returns not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
categoryUid | string | required |
create_categoryWriteCreate a category
Creates a new custom category. Without parentUid this creates a top-level expense category (the only type the app's own creation flow offers) and automatically adds its "Інше" subcategory. With parentUid (an existing top-level category, system or own) this creates a subcategory that inherits the parent's type -- the way to create an income subcategory is to choose an income parent. If the chosen parent is currently hidden, it becomes visible again. The server always generates the new category's uid.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | |
icon | string | optional | |
parentUid | string | optional |
update_categoryWriteUpdate a category
Renames a category and/or changes its icon. An own (custom) category is changed directly. A system category is changed only for the caller, via a personal override -- other users and the shared record are unaffected, and its English name never changes. The "Інше" subcategory cannot be renamed or recoloured. Parent, type and mode can never be changed here.
| Name | Type | Required | Description |
|---|---|---|---|
categoryUid | string | required | |
name | string | optional | |
icon | string | optional |
delete_categoryWriteDelete a category
Deletes one of the caller's own (custom) categories or subcategories. A deleted subcategory's transactions move to that category's "Інше" subcategory; a deleted top-level category's transactions (only possible when its sole subcategory is "Інше") move to "Невідомо". A top-level category with other subcategories cannot be deleted until they are deleted first, and "Інше" cannot be deleted on its own. A system category is refused as global_read_only.
| Name | Type | Required | Description |
|---|---|---|---|
categoryUid | string | required |
archive_categoryWriteArchive (hide) a category
Hides a system category or subcategory for the caller only, the same as the eye toggle in Settings. Hiding a top-level category also hides all its subcategories; hiding the last visible subcategory also hides its parent. A top-level income category and any own (custom) category cannot be hidden -- own categories are deleted instead.
| Name | Type | Required | Description |
|---|---|---|---|
categoryUid | string | required |
unarchive_categoryWriteUnarchive (show) a category
Shows a hidden system category or subcategory again for the caller, the same as the eye toggle in Settings. Unhiding a top-level category also unhides all its subcategories; unhiding a subcategory also unhides its parent.
| Name | Type | Required | Description |
|---|---|---|---|
categoryUid | string | required |
Labels that can be attached to transactions.
list_labelsReadList labels
Lists the caller's own labels, matching the app's labels screen -- never the shared "Підписка" label or any other global one (read a global label with get_label instead, e.g. when it shows up on a transaction). Optional case-insensitive substring filter on name, and/or a uids filter to fetch a known set. Deleted labels are excluded.
| Name | Type | Required | Description |
|---|---|---|---|
search | string | optional | |
uids | array of string | optional | |
limit | integer | optional | |
offset | integer | optional |
get_labelReadGet a label
Reads one label by uid -- the caller's own, or a shared (global) label such as "Підписка" that can be seen (e.g. referenced on a transaction) but never changed or deleted. A deleted label, a foreign one, and a nonexistent uid all return not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
labelUid | string | required |
create_labelWriteCreate a label
Creates a new label the caller can attach to transactions, the same as the app's own "new label" action. Colour defaults to the app's own default (label-color-1) when omitted. Duplicate names are allowed, exactly like in the app -- call list_labels first if you want to reuse an existing one instead. The server always generates the new label's uid.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | |
colorId | label-color-1 | label-color-2 | label-color-3 | label-color-4 | label-color-5 | label-color-6 | label-color-7 | label-color-8 | optional |
update_labelWriteUpdate a label
Renames and/or recolours one of the caller's own labels. A shared (global) label such as "Підписка" is refused as global_read_only.
| Name | Type | Required | Description |
|---|---|---|---|
labelUid | string | required | |
name | string | optional | |
colorId | label-color-1 | label-color-2 | label-color-3 | label-color-4 | label-color-5 | label-color-6 | label-color-7 | label-color-8 | optional |
delete_labelWriteDelete a label
Deletes one of the caller's own labels. It is automatically removed from every transaction that had it -- transaction amounts and account balances are unaffected. This cannot be undone, so confirm with the user before calling it. A shared (global) label such as "Підписка" is refused as global_read_only.
| Name | Type | Required | Description |
|---|---|---|---|
labelUid | string | required |
The merchants and payees linked to transactions.
list_merchantsReadList merchants
Lists the merchants (businesses) the caller can see: the whole shared catalog (banks, shops, "АТБ", "Укрзалізниця", ...) plus the caller's own -- never another user's. Optional case-insensitive substring search across name/nameUk/nameEn, a typeIn filter ("user" = the caller's own, "commerce"/"charity" = catalog), and a uidIn filter for a known set. Call this with search before create_merchant to reuse an existing merchant instead of creating a duplicate.
| Name | Type | Required | Description |
|---|---|---|---|
search | string | optional | |
typeIn | array of commerce | charity | user | optional | |
uidIn | array of string | optional | |
limit | integer | optional | |
offset | integer | optional |
get_merchantReadGet a merchant
Reads one merchant (business) by uid -- the caller's own, or a shared catalog one. A foreign, deleted, or nonexistent uid all return not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
merchantUid | string | required |
create_merchantWriteCreate a merchant
Creates a new merchant (business) the caller can attach to transactions -- the same as the app's "Мої бізнеси" -> new business action. Call list_merchants with search first: an exact name match (case/whitespace/punctuation-insensitive) against the shared catalog or the caller's own merchants is refused with the existing merchant's uid and names instead of creating a duplicate. The server always generates the new merchant's uid.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | |
icon | string | optional |
update_merchantWriteUpdate a merchant
Renames and/or changes the emoji of one of the caller's own merchants -- exactly what the app's "Мої бізнеси" edit form allows. A field the caller does not pass keeps its current value; pass icon: null to explicitly remove the emoji. A shared (global) merchant is refused as global_read_only.
| Name | Type | Required | Description |
|---|---|---|---|
merchantUid | string | required | |
name | string | optional | |
icon | string | null | optional |
delete_merchantWriteDelete a merchant
Deletes one of the caller's own merchants, the same as the app's "Мої бізнеси" delete action. Every transaction, template, recurring schedule, budget and categorisation rule that referenced it keeps everything else -- only the merchant reference is cleared, and the transaction's category is unaffected. This cannot be undone, so confirm with the user before calling it. A shared (global) merchant is refused as global_read_only.
| Name | Type | Required | Description |
|---|---|---|---|
merchantUid | string | required |
Budgets and their spend status for the current period.
list_budgetsReadList budgets
Lists the caller's own budgets with their full configuration (limits and filters, not spend -- use get_budget_status for that), optionally filtered by name (substring, case-insensitive), currency, or a category the budget covers (categoryUid also matches a budget scoped to that category's top-level parent, since a parent-scoped budget covers all its subcategories). Paged (limit up to 200, offset).
| Name | Type | Required | Description |
|---|---|---|---|
search | string | optional | |
currencyCode | string | optional | |
categoryUid | string | optional | |
limit | integer | optional | |
offset | integer | optional |
get_budgetReadGet a budget
Reads one of the caller's own budgets by uid, with all its fields and filters. A foreign or nonexistent uid returns not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
budgetUid | string | required |
get_budget_statusReadGet budget spend status
For one or more of the caller's own budgets: the limit, how much has been spent in the CURRENT period, the remainder, the usage ratio (an overspent budget reports a value above 1 -- never clamped to 1) and the current period's own date bounds. Uses the exact same spend figure the 80%/100% budget notifications use, so this tool and a push notification never disagree. Pure read -- sends no notification and changes no notification state. A foreign or nonexistent budgetUid, or a budget whose saved period cannot be evaluated, is reported as a per-item error rather than failing the whole call.
| Name | Type | Required | Description |
|---|---|---|---|
budgetUids | array of string | required |
create_budgetWriteCreate a budget
Creates a budget: name, amount (> 0), an optional currency (defaults to the caller's own selected currency), one of the app's 8 periods (today, thisWeek, thisMonth, thisYear -- calendar; last7Days, last30Days, last90Days -- rolling; allTime), optional include/exclude filters by uid (category, label, account, merchant, transaction -- a top-level category also covers its subcategories), optional notifications (thresholds are 0.8 and/or 1, i.e. 80% and 100% -- the only two the app offers) and an optional icon. The server always generates the new budget's uid -- this tool does not accept one.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | |
amount | number | required | |
currencyCode | string | optional | |
period | today | thisWeek | thisMonth | thisYear | last7Days | last30Days | last90Days | allTime | required | |
icon | string | optional | |
notifications | object { enabled, thresholds } | optional | |
categoriesUids | array of string | optional | |
excludeCategoriesUids | array of string | optional | |
labelsUids | array of string | optional | |
excludeLabelsUids | array of string | optional | |
accountsUids | array of string | optional | |
excludeAccountsUids | array of string | optional | |
merchantsUids | array of string | optional | |
excludeMerchantsUids | array of string | optional | |
transactionsUids | array of string | optional | |
excludeTransactionsUids | array of string | optional |
update_budgetWriteUpdate a budget
Changes one of the caller's own budgets by uid -- a field that is not passed keeps its current value; passing [] for any of the *Uids filter fields clears just that filter. A foreign, nonexistent or already-deleted budget uid returns not_found.
| Name | Type | Required | Description |
|---|---|---|---|
budgetUid | string | required | |
name | string | optional | |
amount | number | optional | |
currencyCode | string | optional | |
period | today | thisWeek | thisMonth | thisYear | last7Days | last30Days | last90Days | allTime | optional | |
icon | string | null | optional | |
notifications | object { enabled, thresholds } | optional | |
categoriesUids | array of string | optional | |
excludeCategoriesUids | array of string | optional | |
labelsUids | array of string | optional | |
excludeLabelsUids | array of string | optional | |
accountsUids | array of string | optional | |
excludeAccountsUids | array of string | optional | |
merchantsUids | array of string | optional | |
excludeMerchantsUids | array of string | optional | |
transactionsUids | array of string | optional | |
excludeTransactionsUids | array of string | optional |
delete_budgetWriteDelete a budget
Deletes one of the caller's own budgets by uid. There is no archive tool -- the app only offers Edit and Delete for a budget. A foreign, nonexistent or already-deleted budget uid returns not_found (unlike transactions, deleting an already-deleted budget here is not idempotent).
| Name | Type | Required | Description |
|---|---|---|---|
budgetUid | string | required |
The user's debts and liabilities, including recording a repayment.
list_liabilitiesReadList liabilities
Lists the caller's own liabilities (debts, loans, credits), optionally filtered by status (active / paid_off / written_off), direction (owed_by_me / owed_to_me), type (debt / loan / credit) or currency. Paged (limit up to 200, offset). Deleted liabilities are never returned.
| Name | Type | Required | Description |
|---|---|---|---|
status | active | paid_off | written_off | optional | |
direction | owed_by_me | owed_to_me | optional | |
type | debt | loan | credit | optional | |
currencyCode | string | optional | |
limit | integer | optional | |
offset | integer | optional |
get_liabilityReadGet a liability
Reads one of the caller's own liabilities by uid, with all its fields, including relatedTransactionUids so the agent can show its repayment history. A foreign or nonexistent uid returns not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
liabilityUid | string | required |
create_liabilityWriteCreate a liability
Creates a debt/loan/credit exactly like the app's own "Додати борг" form: direction (owed_by_me -- the caller owes it; owed_to_me -- it is owed to the caller), amount (> 0), currencyCode and a counterparty name are required. type defaults to debt. Optional: dueDate, notes, relatedTransactionUids (money that already changed hands when the loan was made), and reminders (remindersEnabled + reminderOffsetsSeconds -- reminders require a dueDate, at most 5 offsets, each within 366 days). Status is always active and startDate is always today; the server always generates the new liability's uid.
| Name | Type | Required | Description |
|---|---|---|---|
direction | owed_by_me | owed_to_me | required | |
amount | number | required | |
currencyCode | string | required | |
counterparty | object { name, type } | required | |
type | debt | loan | credit | optional | |
dueDate | string | optional | |
notes | string | optional | |
relatedTransactionUids | array of string | optional | |
remindersEnabled | boolean | optional | |
reminderOffsetsSeconds | array of integer | optional |
create_liability_repaymentWriteRepay a liability
Records a repayment of one of the caller's own ACTIVE liabilities, like the app's own "Позначити як сплачений" action. Exactly one of two modes: (a) amount (in the liability's own currency) + accountUid -- creates an expense (owed_by_me) or income (owed_to_me) on that account, dated now, and links it; the account must be the caller's own, manual (not bank-synced), not a savings-target account, in the liability's own currency, and usable under the plan's account limit. (b) relatedTransactionUids -- links transactions the caller already created elsewhere (added to, never replacing, the liability's existing links); each must be the caller's own, have the correct sign for the direction (an expense for owed_by_me, an income for owed_to_me), and not already be linked to a different liability. Either way the repayment amount cannot exceed the liability's remaining balance, and fully repaying it moves its status to paid_off.
| Name | Type | Required | Description |
|---|---|---|---|
liabilityUid | string | required | |
amount | number | optional | |
accountUid | string | optional | |
relatedTransactionUids | array of string | optional |
update_liabilityWriteUpdate a liability
Changes one of the caller's own liabilities by uid -- a field that is not passed keeps its current value. relatedTransactionUids replaces the full set (an omitted key leaves existing links untouched; [] clears them). Status can only move active -> written_off ("Списати") or written_off -> active ("Відновити") -- any other transition, including a direct paid_off, is rejected. A foreign, nonexistent or already-deleted liability uid returns not_found.
| Name | Type | Required | Description |
|---|---|---|---|
liabilityUid | string | required | |
type | debt | loan | credit | optional | |
direction | owed_by_me | owed_to_me | optional | |
currencyCode | string | optional | |
amount | number | optional | |
status | active | paid_off | written_off | optional | |
counterparty | object { name, type } | optional | |
dueDate | string | null | optional | |
notes | string | null | optional | |
relatedTransactionUids | array of string | optional | |
remindersEnabled | boolean | optional | |
reminderOffsetsSeconds | array of integer | optional |
delete_liabilityWriteDelete a liability
Deletes one of the caller's own liabilities by uid, like the "Видалити" button in the app. Transactions linked to it are left untouched. A foreign, nonexistent or already-deleted liability uid returns not_found.
| Name | Type | Required | Description |
|---|---|---|---|
liabilityUid | string | required |
The user's financial goals.
list_targetsReadList financial targets
Lists the caller's own financial (savings) targets, each with how much has already been accumulated (currentAmount) and the completion percentage 0-100 (progress) -- computed exactly like the target card in the app: the sum of transaction amounts on the target's own account, initial balance excluded, never a value any tool can set directly. Topping up a Monobank jar or Privatbank envelope does NOT move this until the transfer is recorded in Fealthy; a target with no account always has 0/0. Filters: archived (true -- only completed targets, as in the app's Archive of goals; false -- only active ones; omitted -- both) and accountUid (the target bound to that account). Paged (limit up to 200, offset).
| Name | Type | Required | Description |
|---|---|---|---|
archived | boolean | optional | |
accountUid | string | optional | |
limit | integer | optional | |
offset | integer | optional |
get_targetReadGet a financial target
Reads one of the caller's own financial targets by uid, including currentAmount and progress. A foreign or nonexistent uid returns not_found identically.
| Name | Type | Required | Description |
|---|---|---|---|
targetUid | string | required |
create_targetWriteCreate a financial target
Creates a financial (savings) target exactly like the app's own goal-creation form: name (non-empty), currencyCode, targetAmount (> 0) and accountUid are all required. The account must be the caller's own, in the same currency, EMPTY (zero initial balance, no transactions, not bank-synced) and not already bound to another active (non-archived) target -- if none qualifies, create a fresh one first with an accounts tool, then create the target on it. icon defaults to "📌". Optional rules: endDate, paymentFrequency ({freq, interval} -- one of the app's own 4 presets: {freq:3,interval:1} daily, {freq:2,interval:1} every week, {freq:2,interval:2} every two weeks, {freq:1,interval:1} every month) and paymentAmount. The server always generates the new target's uid -- this tool does not accept one.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | |
currencyCode | string | required | |
targetAmount | number | required | |
accountUid | string | required | |
icon | string | optional | |
rules | object { endDate, paymentFrequency, paymentAmount } | optional |
update_targetWriteUpdate a financial target
Changes name, icon, targetAmount and/or rules of one of the caller's own financial targets by uid -- a field that is not passed keeps its current value. rules is REPLACED WHOLESALE when the key is passed: send the full new object, pass null (or {}) to clear every rule, or omit the key entirely to leave rules untouched -- exactly like the app's own goal-edit form, which always resubmits the full 3-field set. The account and currency can never be changed after creation, same as in the app: this tool does not accept accountUid, currencyCode or archived (use archive_target to complete a target instead). A foreign, nonexistent or already-deleted target uid returns not_found. If the target's own account still exists but has since fallen outside the caller's plan account limit, the update is refused with a plan-restriction error and nothing changes.
| Name | Type | Required | Description |
|---|---|---|---|
targetUid | string | required | |
name | string | optional | |
icon | string | optional | |
targetAmount | number | optional | |
rules | object | null | optional |
delete_targetWriteDelete a financial target
Deletes one of the caller's own financial targets by uid, but only an already-completed (archived) one -- exactly like the app, which only ever shows a Delete button once a target is archived. An active target is refused with a clear error naming archive_target as the required first step; nothing changes. The target's own account and its transactions are left untouched. A foreign or nonexistent uid returns not_found.
| Name | Type | Required | Description |
|---|---|---|---|
targetUid | string | required |
archive_targetWriteArchive (complete) a financial target
Completes one of the caller's own financial targets -- the app's own "Завершити ціль" / "Завершити достроково" action (there is no separate progress check here: the app allows completing early too). Irreversible: there is no tool to un-archive a target, matching the app. Calling this again on an already-archived target changes nothing and returns it as is. A foreign or nonexistent target uid returns not_found.
| Name | Type | Required | Description |
|---|---|---|---|
targetUid | string | required |
The profile and settings of the token's owner.
get_user_profileReadGet user profile
Reads the caller's own profile and settings: uid, name, selectedLanguage, selectedCurrencyCode, selectedTimezone. No parameters -- always the token owner's own data. selectedTimezone can be null when the user has never set one; when it is null, Fealthy treats "today" and any date range as Europe/Kyiv. There is no tool to change any of these -- the primary currency, language and timezone each have app-wide effects and are out of scope for MCP.
No parameters.