expense-tracker-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| DATABASE_URL | Yes | PostgreSQL connection string (Neon). Use the pooled connection. The server strips libpq query parameters such as sslmode, and TLS is requested in code instead. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| extensions | {
"io.modelcontextprotocol/ui": {}
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| whoamiA | Report which user the server sees, and whether expenses are scoped. Worth having permanently rather than as a one-off diagnostic: "why can't I see my expenses?" is answered by this tool in one call, and the answer is almost always that the request arrived unauthenticated and landed in the shared local bucket. |
| list_categoriesA | List every valid category and its subcategories. Call this before logging an expense if you are unsure which category a purchase belongs to. Categories are a fixed taxonomy; anything outside it is rejected. |
| add_expenseA | Record a single expense. Pass the user's local date -- the server does not infer 'today', because its clock is UTC and would log the wrong day either side of midnight. |
| list_expensesA | List individual expenses, newest first. All filters are optional; with none set this returns the most recent
expenses. Use |
| delete_expenseA | Delete one expense, by id. Use |
| summarizeA | Total spending over a date range, broken down by category. Summing happens in Postgres over NUMERIC values, so the total is exact. Prefer this over listing every row and adding them up. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| categories | The full category taxonomy: every category and its subcategories. Deliberately duplicates the `list_categories` tool. Resources are the correct MCP primitive for read-only reference data, but a client only reads one when a *user* attaches it -- models are handed tools, not resources. Testing against Claude showed exactly that: it reported the taxonomy as unavailable and proposed writing a junk row to discover the valid values from the rejection. The tool is what the model can actually reach; this stays for clients that browse resources directly. |
TDQS
Scored across 6 tools
Each tool maps to a distinct action (auth check, category lookup, add, list, delete, summarize), and the list_expenses vs summarize distinction is explicitly drawn as rows versus totals. whoami is a bit of an outlier but clearly scoped to diagnosing visibility. Only minor overlap exists between listing and summarizing expense data.
Most tools follow a clear lower_snake_case verb_noun pattern (list_categories, add_expense, list_expenses, delete_expense). summarize and whoami break the noun-object pattern but are still readable and not confusingly styled. The pluralization of expenses is slightly inconsistent (list_expenses vs delete_expense) but harmless.
Six tools is a well-scoped size for an expense tracker: one diagnostic, one taxonomy lookup, and core expense operations. Each tool earns its place without redundancy or bloat. This is in the ideal 3–15 tool range.
The core lifecycle is covered: add, list, delete, summarize, plus category validation and auth scoping. The only notable gap is an update/edit operation, but users can delete and re-add an incorrect expense. Overall agents can accomplish expense tracking without dead ends.