mcp-spendee
This MCP server lets clients inspect Spendee wallets, labels, categories, and transactions, and safely preview or create income/expense transactions with duplicate and foreign-currency controls.
Check local configuration and credential status via
spendee_statuswithout logging in or exposing secrets.List wallets with IDs, names, states, balances, and currencies.
List modern Spendee labels from Firestore.
List categories, optionally filtered by wallet and expense/income type.
List transactions, optionally filtered by wallet, with limit/offset.
Preview or create a transaction with positive amount;
transaction_typedetermines expense vs income sign.Attach existing labels and optionally use a foreign currency; preview resolves the exchange rate, and confirm pins it via
exchange_rate.Two-step creation: call with
confirm=falseto inspect the normalized payload, thenconfirm=truewith a uniquerequest_id.Prevent duplicates via request cache and Firestore content checks;
allow_duplicate=trueonly after explicit user confirmation for separate identical charges.Control wallet routing with
wallet_selection_reason(ordinary_defaultonly forОперационка,travel_ruleonly forОбщий,explicit_in_requestfor explicit choices).Accept legacy integer or Firestore UUID string IDs for categories and transactions.
Retry label attachment without duplicating the transaction if label writes fail after transaction creation.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-spendeeshow me my wallets"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-spendee
An unofficial Model Context Protocol (MCP) server for Spendee. It lets MCP clients inspect wallets, categories, and transactions, and create income or expense transactions.
Spendee does not publish a supported public API. This server uses afork of the archived third-party
spendee package and may stop working when Spendee changes its private API.
Test it with a non-critical wallet first.
Tools
spendee_status— check local configuration without logging in or exposing secrets.list_wallets— list Firestore wallet IDs, names, states, and currencies.list_labels— list modern Spendee labels stored in Firestore.list_categories— list and optionally filter categories.list_transactions— list and optionally filter transactions.create_transaction— preview or create an expense/income transaction, optionally with existing modern labels and an amount in a currency different from the selected wallet.
Creating a transaction is deliberately two-step. Call create_transaction once
with confirm=false to inspect the normalized payload, then repeat it with
confirm=true and a unique request_id. Reusing a request ID in the same
server process returns the cached result instead of creating a duplicate.
Every call must also state wallet_selection_reason: explicit_in_request,
travel_rule, or ordinary_default. The server accepts ordinary_default
only for the Операционка wallet and travel_rule only for Общий, so an
agent cannot silently route an ordinary unspecified expense to Общий.
Wallet and category IDs are legacy integers when Spendee still provides them;
newer resources use Firestore UUID strings. Both forms are accepted by
list_categories, list_transactions, and create_transaction.
Before a confirmed write, the server compares the complete normalized
transaction with current Firestore data: wallet, category, amount, type, note,
date and foreign-currency fields. An exact match returns status=existing
instead of creating another transaction, even when a retry uses a different
request_id or the server has restarted. If the retry adds labels, the server
applies them to the existing transaction.
When two source operations genuinely have identical fields, the caller can set
allow_duplicate=true only after the user explicitly confirms that both are
separate charges.
The forked spendee library owns both the modern Firestore transaction and
label writes. If label attachment fails after transaction creation, a
retry with the same request_id retries only the labels and does not create the
transaction twice.
For a foreign-currency transaction, pass the original positive amount and its
ISO currency. The preview resolves Spendee's current exchange rate and shows
both the wallet amount and the original amount. Repeat the confirmed call with
the preview's foreign_rate in exchange_rate; this pins the exact conversion
that was reviewed instead of silently fetching a newer rate.
Related MCP server: Expense Tracker MCP Server
Installation
Install uv, clone the repository, then run:
uv syncSet credentials in the MCP client environment. Do not commit a .env file:
SPENDEE_EMAIL=you@example.com
SPENDEE_PASSWORD=your-password
SPENDEE_TIMEZONE=Europe/Moscow
SPENDEE_GLOBAL_CURRENCY=EURSPENDEE_TIMEZONE and SPENDEE_GLOBAL_CURRENCY are optional. They default to
Europe/Moscow and EUR.
MCP client configuration
Use the absolute path to the cloned checkout:
{
"mcpServers": {
"spendee": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/mcp-spendee",
"run",
"mcp-spendee"
],
"env": {
"SPENDEE_EMAIL": "you@example.com",
"SPENDEE_PASSWORD": "your-password",
"SPENDEE_TIMEZONE": "Europe/Moscow",
"SPENDEE_GLOBAL_CURRENCY": "EUR"
}
}
}
}The server uses MCP over stdio. Logs and errors never write to the protocol's stdout stream.
Development
make install
make lint
make testSecurity
Credentials are read only from environment variables.
Status output never includes credentials.
Transaction amounts must be positive;
transaction_typedetermines the sign.Writes require both
confirm=trueand a non-emptyrequest_id.The request cache handles immediate retries, and the Firestore content check prevents exact duplicates across request IDs and server restarts.
License
MIT
Available Tools
6 toolscreate_transactionA
Preview or create a transaction.
Amount must always be positive. transaction_type controls whether Spendee receives a negative expense or positive income. currency defaults to the selected wallet's currency. For a different currency, preview without an exchange_rate first, then confirm with the returned foreign_rate as exchange_rate. First call with confirm=false; create only after checking the preview, then pass confirm=true and a unique request_id.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | ||
| amount | Yes | ||
| labels | No | ||
| confirm | No | ||
| currency | No | ||
| wallet_id | Yes | ||
| request_id | No | ||
| category_id | Yes | ||
| occurred_at | No | ||
| exchange_rate | No | ||
| transaction_type | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It reveals the two-step preview/confirm mechanic, the sign convention for expenses vs income, the currency defaulting behavior, the required exchange rate flow, and the need for a unique request_id. This is exceptionally transparent for a transaction creation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with the core purpose, and each sentence adds essential operational detail. It covers complex behavior in just four sentences without redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of an 11-parameter transaction creation tool with no annotations and zero schema descriptions, the description handles the critical workflow and non-obvious semantics well. It omits explanations for a few self-explanatory parameters, but the overall guidance is sufficient to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains the semantics of amount, transaction_type, currency, exchange_rate, confirm, and request_id, which are the non-obvious parameters. However, several parameters (wallet_id, category_id, note, labels, occurred_at) are left unexplained, leaving gaps that the schema does not fill.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description immediately states 'Preview or create a transaction' with a specific verb and resource, and clearly distinguishes the two-phase preview/confirm workflow. This makes the tool's purpose unambiguous and distinct from the sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit workflow guidance: first call with confirm=false, review the preview, then confirm with confirm=true and a unique request_id. It also explains how to handle different currencies and exchange rates. It does not explicitly mention when not to use the tool or list alternatives, but the guidance is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_categoriesA
List Spendee categories, optionally filtered by wallet and expense/income type.
| Name | Required | Description | Default |
|---|---|---|---|
| wallet_id | No | ||
| category_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must carry the behavioral transparency burden. 'List' implies a read-only operation, and the optional filters describe behavior, but the description does not explicitly state safety, authentication needs, or return behavior. It is adequate but not rich in behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that leads with the main action and adds filtering details concisely. Every word earns its place, with no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple tool with only two optional parameters and an existing output schema, the description sufficiently covers the purpose and filtering behavior. It does not explain edge cases like no filters or errors, but the schema defaults and the straightforward nature make this acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema description coverage is 0%, the description compensates by explaining both parameters as filters: 'wallet' maps to wallet_id and 'expense/income type' maps to category_type. It clarifies their optional nature and purpose, adding meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb+resource construction: 'List Spendee categories', and adds scope with optional filtering by wallet and expense/income type. This clearly distinguishes it from sibling tools like list_transactions or list_labels, establishing a unique purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool: when you need categories with optional wallet/type filtering. However, it does not explicitly state alternatives, prerequisites, or exclusion cases, leaving the usage context to inference rather than explicit guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_labelsA
List modern Spendee labels from Firestore.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the source (Firestore) and the action (list), implying a read-only operation, but does not explicitly state side effects, permissions, or other behavioral details. This is adequate for a simple list tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, front-loaded with the verb 'List', and contains no unnecessary words. It is highly concise and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists, the description need not explain return values. It specifies what is listed (modern Spendee labels) and the source (Firestore), which is complete for a list operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has 0 parameters, so schema coverage is 100% and the description does not need to explain them. The baseline of 4 applies here because there are no parameters to document.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it lists modern Spendee labels from Firestore, with a specific verb 'list' and resource 'labels'. This distinguishes it from sibling tools like list_wallets and list_categories.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives is provided. The usage is implied by the resource name (labels), but there is no mention of alternatives or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_transactionsA
List transactions, optionally filtered by wallet.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| wallet_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It accurately states the operation as listing transactions, which implies a read-only action. However, it does not disclose pagination behavior, filtering semantics, or any potential side effects, though the minimal nature of a list operation makes this acceptable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that is succinct and front-loaded with the primary action. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema, so return values are covered. However, the description lacks guidance on when to use this tool relative to alternatives and does not mention pagination or filter behavior. For a straightforward list operation, it is minimally viable but not comprehensive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It mentions the wallet filter (wallet_id) but does not explain the limit and offset parameters. The pagination controls are omitted, leaving the agent to infer their meaning from names alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists transactions and optionally filters by wallet. This distinguishes it from sibling tools like list_wallets and list_labels by specifying the resource type (transactions).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for listing transactions, with an optional wallet filter. It provides clear context but does not explicitly mention alternatives or when not to use, though sibling tools are sufficiently distinct.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_walletsA
List Spendee wallets with IDs, balances, and currencies.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description implies a read-only operation by saying 'List' and specifies the output fields, but it does not explicitly disclose safety guarantees or side effects. Since no annotations are provided, the description carries the full burden, and it falls short of mentioning auth requirements or non-mutating behavior explicitly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, focused sentence that directly states the tool's function and output. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no parameters and an output schema exists, the description sufficiently covers what the tool does. It is complete for an agent to select and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the input schema is empty. The description adds no parameter information, but there are none to explain; a baseline of 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists Spendee wallets, specifying the resource (wallets) and the information returned (IDs, balances, currencies). This distinguishes it from sibling tools that list other entities like labels or categories.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context that this tool is for listing wallets, which implies when to use it. However, it does not explicitly mention alternatives or exclusion criteria relative to sibling tools, so it lacks explicit when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
spendee_statusA
Check whether credentials and local Spendee settings are configured.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of behavioral disclosure. It only says 'Check whether credentials and local Spendee settings are configured' but does not disclose whether this is a read-only operation, makes network calls, or has side effects. The output format and safety behavior are not addressed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single clear sentence with no filler. It is appropriately sized for a status-check tool and the key information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with zero parameters and an output schema exists, so the description doesn't need to explain return values. However, the absence of usage guidance and behavioral transparency leaves some gaps, making it minimally complete rather than fully robust.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema provides complete coverage. The description does not need to explain parameter semantics, and the baseline of 4 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function with a specific verb ('Check') and resource ('credentials and local Spendee settings'). It distinguishes itself from sibling tools that list or create data, making it obvious this is a configuration/status check.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than explicitly stated. The description does not say when to use this tool versus alternatives, but the name 'status' and mention of configuration imply it is a preflight check. No exclusions or alternative tool references are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
create_transaction - First observed
list_categories - First observed
list_labels - First observed
list_transactions - First observed
list_wallets - First observed
spendee_status
TDQS
Scored across 6 tools
Each tool targets a distinct resource or action: status checks configuration, list_wallets/labels/categories/transactions each list a different entity, and create_transaction handles transaction creation. There is no overlap in purpose.
Most tools follow a verb_noun pattern (list_*, create_*), but 'spendee_status' deviates by using a noun without a verb. Still, the snake_case style and prefix are consistent, making it readable.
With 6 tools, the server is well-scoped for a Spendee integration, covering essential read operations, one write operation, and a status check. Each tool earns its place without bloat.
The core workflows of viewing wallets, labels, categories, and transactions, plus creating transactions, are covered. Missing update/delete operations are minor gaps that could be worked around, but for a finance-focused server they are not critical.
Maintenance
Related MCP Connectors
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
A MCP server for the Frankfurter API for currency exchange rates.
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA lightweight MCP server for tracking personal expenses, income, and budget summaries using SQLite.4Martin Birgmeier
- FlicenseBqualityDmaintenanceMCP server for managing and analyzing expenses. Provides tools to add, list, summarize expenses, and retrieve categories.3-
- AlicenseAqualityCmaintenanceAn unofficial MCP server that connects Despezzas financial data to MCP clients like ChatGPT, enabling listing accounts, cards, categories, searching transactions, and performing write operations with safety protections.35MIT
- FlicenseNot gradedqualityCmaintenanceMCP server for tracking expenses with local SQLite storage. Provides tools to add, list, and summarize expenses by category.-