expense-tracker-mcp
expense-tracker-mcp
一个远程 MCP 服务器,用于跟踪个人支出,以 Postgres 为后端,设计为由两种不同的客户端驱动:Claude 作为连接器,以及一个自定义的 LangGraph 代理。
说一句“今天在杂货上花了 450”,然后问“我这个月在食物上花了多少?”——无论从哪个客户端,都能得到相同的答案,因为状态存在于数据库中,而不是聊天会话中。
Claude (connector) ─┐
├─► expense-tracker-mcp ─► Neon Postgres
LangGraph agent ────┘ (FastMCP)状态
阶段 | ||
1 | 服务器基础——类型化工具、Postgres、类别验证 | 本地可用 |
2 | LangGraph 客户端——终端、 | 未开始 |
3 | 基于可用代理的 Streamlit 前端 | 未开始 |
4 | OAuth 2.1、按已认证用户范围限定查询 | 未开始 |
阶段 1 已针对真实的 Neon 数据库进行了端到端验证。下一步是部署。
Related MCP server: expense-tracker-mcp-server
工具
工具 | 用途 |
| 有效的分类体系,使模型可以查询而不是猜测。 |
| 记录一笔支出。写入前验证类别。 |
| 各行记录,最新的在前。可选的日期范围和类别筛选。 |
| 按日期范围统计总额,按类别分组——或者当筛选到单个类别时按子类别分组。 |
该分类体系也作为资源 expenses://categories 发布。这种重复是有意为之,而针对 Claude 的测试正是产生这一设计的原因:资源是只读参考数据的 正确 MCP 原语,但客户端只有在用户附加资源时才会读取——模型拿到的是工具,而不是资源。当被问到“我可以使用哪些类别?”时,Claude 报告分类体系不可用,并主动提出写入一条胡乱的行,以便从拒绝错误中读取有效值。工具才是模型实际能够触达的东西;资源则保留给直接浏览资源的客户端。
类别是在 categories.json 中定义的固定两级分类体系——20 个类别,每个类别都有子类别。任何超出该体系的内容都会被拒绝,错误信息中包含有效值,因此模型可以在一次往返中自行纠正。
本地运行
先决条件: Python 3.10+、uv 以及一个 Neon 账户(免费套餐就足够了)。
git clone https://github.com/<your-username>/expense-tracker-mcp
cd expense-tracker-mcp
uv sync配置数据库。 复制示例文件并填写你的 Neon 连接字符串:
cp .env.example .env # PowerShell: Copy-Item .env.example .env关于该字符串,有两件事很重要:
使用池化连接——主机名包含
-pooler。去掉
?sslmode=require&channel_binding=require查询字符串。 asyncpg 不接受 libpq 的查询参数,会抛出invalid dsn: invalid connection option "sslmode"。而是在代码中显式请求 TLS。(服务器也会防御性地剥离这些参数,因此直接粘贴原始字符串仍然可以工作。)
创建表。 在 Neon SQL Editor 或任何 Postgres 客户端中运行一次 schema.sql。每条语句都是幂等的。
启动服务器:
uv run python main.py # http://127.0.0.1:8000/mcp或者使用 MCP Inspector 以交互方式探索(需要 Node):
uv run fastmcp dev inspector main.py在浏览器中对 /mcp 执行 GET 会返回 406 Not Acceptable。这是正确的,不是失败——MCP 要求使用 POST,并带有 Accept: application/json, text/event-stream。
部署
为 Prefect Horizon(原 FastMCP Cloud)构建。将其指向此仓库,入口点为 main.py:mcp,并在环境变量中设置 DATABASE_URL。部署后的服务器会获得一个 *.fastmcp.app URL,可以直接作为连接器添加到 Claude。
请注意,这里故意没有 .python-version 文件。Horizon 使用 UV_PROJECT_ENVIRONMENT=/usr/local 构建,这是系统 Python 前缀,而不是虚拟环境;版本固定会使 uv 拒绝它、下载托管的 CPython,并在尝试重建非 venv 目录时失败。pyproject.toml 中 requires-python = ">=3.10" 的下限就足够了。
设计决策
金额使用 NUMERIC(12,2),绝不使用浮点数。 二进制浮点数无法精确表示 0.1,因此对浮点金额求和会累积误差,总额会以分为单位漂移。金额在 Python 中是 Decimal,在 Postgres 中是 NUMERIC,并在网络上以字符串传输——JSON 数字是 IEEE-754 双精度浮点数,因此如果序列化为浮点数,会在最后一步重新引入漂移。450.55 + 120.45 精确地返回 571.00。
连接池是惰性创建的,绝不会在导入时创建。 在导入时连接会把暂时的数据库问题变成一次失败的部署;惰性连接池则会把它变成一次可重试的失败工具调用。Schema 创建同样是一个独立的一次性脚本,而不是服务器在启动时做的事情。
每个参数都有类型注解。 FastMCP 从类型提示构建模型看到的 JSON schema,因此 date: date 以 {"type": "string", "format": "date"} 的形式到达模型,amount 带有 exclusiveMinimum: 0。无类型的参数会显著降低工具调用的准确性——而且无效输入会在工具体运行之前就被 schema 验证拒绝。
每个工具都返回一个 dict,无论成功还是失败,并带有 ok 键。如果一个工具成功时返回 list、出错时返回 dict,就会迫使每个调用者在使用结果之前进行类型检查。
user_id 从第一天起就存在,具有默认值且当前未使用;阶段 4 将按它来限定每个查询的范围。事后向一个有数据的表添加 NOT NULL 列需要迁移——现在添加则毫无代价。它故意不作为工具参数:如果模型可以选择 user_id,任何客户端都可以仅凭询问就读取任何人的支出记录。
日志输出到 stderr。 在 stdio 传输上,stdout 就是 JSON-RPC 通道,任何多余的 print() 都会破坏协议流。
尚未实现
如实说明限制,而非遗漏:
没有编辑或删除工具。 纠正一条记错的支出意味着直接操作数据库。推迟到在实践中确实令人困扰时再实现。
没有货币列。 所有金额都假定使用同一种货币。
没有身份验证。 每笔支出都以
user_id = 'default'写入,因此在阶段 4 之前,部署的服务器是单租户的。
目录结构
main.py the server: three tools, one resource
schema.sql one-time table + index creation
categories.json the category taxonomy, single source of truth
.env.example documents DATABASE_URL技术栈
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenancePersonal expense tracker MCP server that enables tracking expenses, income, budgets, and savings goals through natural language.10MIT
- FlicenseBqualityDmaintenanceMCP server for tracking personal expenses using FastMCP and SQLite, enabling adding, listing, updating, deleting expenses and summarizing by category via natural language tools.51
- FlicenseNot gradedqualityDmaintenanceA local MCP server for tracking personal expenses using SQLite, enabling users to add, list, and summarize expenses via natural language.
- FlicenseNot gradedqualityCmaintenanceMCP server for tracking expenses with local SQLite storage. Provides tools to add, list, and summarize expenses by category.
Related MCP Connectors
Hosted MCP server for Mini Accountant: invoices, expenses, customers, analytics, tax estimates.
MCP server for managing Prisma Postgres.
GibsonAI MCP server: manage your databases with natural language
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mhopareprathmesh5-creator/expense-tracker-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server