expense-tracker-mcp
expense-tracker-mcp
Un servidor MCP remoto para llevar un seguimiento de gastos personales, respaldado por Postgres, diseñado para ser manejado por dos clientes diferentes: Claude como conector y un agente LangGraph personalizado.
Registra un gasto diciendo "gasté 450 en comestibles hoy", y luego pregunta "¿cuánto gasté en comida este mes?" — y obtén la misma respuesta de cualquiera de los dos clientes, porque el estado vive en una base de datos en lugar de en una sesión de chat.
Claude (connector) ─┐
├─► expense-tracker-mcp ─► Neon Postgres
LangGraph agent ────┘ (FastMCP)Estado
Fase | ||
1 | Base del servidor — herramientas tipadas, Postgres, validación de categorías | funciona localmente |
2 | Cliente LangGraph — terminal, | no iniciada |
3 | Interfaz Streamlit sobre el agente funcional | no iniciada |
4 | OAuth 2.1, consultas limitadas al usuario autenticado | no iniciada |
La fase 1 está verificada de extremo a extremo contra una base de datos Neon real. El despliegue es el siguiente paso.
Related MCP server: expense-tracker-mcp-server
Herramientas
Herramienta | Propósito |
| La taxonomía válida, para que el modelo pueda consultarla en lugar de adivinar. |
| Registra un gasto. Valida la categoría antes de escribir. |
| Filas individuales, las más recientes primero. Filtros opcionales por rango de fechas y categoría. |
| Totales en un rango de fechas, agrupados por categoría — o por subcategoría cuando filtras a una categoría. |
La taxonomía también se publica como recurso, expenses://categories. Esa duplicación es deliberada, y probar con Claude es lo que la puso ahí: los recursos son la primitiva MCP correcta para datos de referencia de solo lectura, pero un cliente solo lee uno cuando un usuario lo adjunta — a los modelos se les dan herramientas, no recursos. Al preguntar "¿qué categorías puedo usar?", Claude informó que la taxonomía no estaba disponible y ofreció escribir una fila basura para poder leer los valores válidos del error de rechazo. La herramienta es lo que el modelo realmente puede alcanzar; el recurso permanece para clientes que navegan recursos directamente.
Las categorías son una taxonomía fija de dos niveles definida en categories.json — 20 categorías, cada una con subcategorías. Cualquier cosa fuera de ella se rechaza con los valores válidos incluidos en el error, para que el modelo pueda corregirse en un solo viaje de ida y vuelta.
Ejecutarlo localmente
Requisitos previos: Python 3.10+, uv y una cuenta de Neon (el nivel gratuito es suficiente).
git clone https://github.com/<your-username>/expense-tracker-mcp
cd expense-tracker-mcp
uv syncConfigura la base de datos. Copia el archivo de ejemplo y completa tu cadena de conexión de Neon:
cp .env.example .env # PowerShell: Copy-Item .env.example .envDos cosas importantes sobre esa cadena:
Usa la conexión agrupada — el host contiene
-pooler.Elimina la cadena de consulta
?sslmode=require&channel_binding=require. asyncpg no acepta los parámetros de consulta de libpq y lanzaráinvalid dsn: invalid connection option "sslmode". TLS se solicita explícitamente en el código en su lugar. (El servidor también elimina estos de forma defensiva, por lo que una cadena pegada sin procesar aún funciona).
Crea la tabla. Ejecuta schema.sql una vez, en el Editor SQL de Neon o en cualquier cliente de Postgres. Cada declaración es idempotente.
Inicia el servidor:
uv run python main.py # http://127.0.0.1:8000/mcpO explóralo interactivamente con el Inspector MCP (necesita Node):
uv run fastmcp dev inspector main.pyUna solicitud GET del navegador a /mcp devuelve 406 Not Acceptable. Eso es correcto, no un fallo — MCP requiere POST con
Accept: application/json, text/event-stream.
Despliegue
Construido para Prefect Horizon (anteriormente FastMCP Cloud). Apúntalo a este repositorio con el punto de entrada main.py:mcp y establece DATABASE_URL en las variables de entorno. Los servidores desplegados obtienen una URL *.fastmcp.app, que se puede añadir directamente a Claude como conector.
Ten en cuenta que deliberadamente no hay archivo .python-version. Horizon compila con UV_PROJECT_ENVIRONMENT=/usr/local, un prefijo de Python del sistema en lugar de un virtualenv; una fijación de versión hace que uv lo rechace, descargue un CPython gestionado y falle al intentar recrear un directorio que no es venv. El requisito requires-python = ">=3.10" en pyproject.toml es suficiente.
Decisiones de diseño
El dinero es NUMERIC(12,2), nunca un flotante. El punto flotante binario no puede representar 0.1 exactamente, por lo que sumar cantidades flotantes acumula error y los totales se desvían por céntimos. Las cantidades son Decimal en Python, NUMERIC en Postgres y cruzan el cable como cadenas — los números JSON son dobles IEEE-754, por lo que serializar como flotante reintroduciría la desviación en el último paso.
450.55 + 120.45 devuelve exactamente 571.00.
El grupo de conexiones se crea de forma diferida, nunca en la importación. Conectar en el momento de la importación convierte un problema transitorio de base de datos en un despliegue fallido; un grupo diferido lo convierte en una llamada de herramienta fallida que el llamador puede reintentar. La creación del esquema es igualmente un script separado de una sola vez, no algo que el servidor haga al arrancar.
Cada parámetro está anotado. FastMCP construye el esquema JSON que el modelo ve a partir de las sugerencias de tipo, por lo que date: date llega al modelo como
{"type": "string", "format": "date"} y amount lleva
exclusiveMinimum: 0. Los parámetros sin tipo degradan notablemente la precisión de la llamada a herramientas — y la entrada inválida se rechaza mediante la validación del esquema antes de que el cuerpo de la herramienta se ejecute.
Cada herramienta devuelve un dict, tanto en éxito como en fallo, con una clave ok. Una herramienta que devuelve una lista en éxito y un dict en error obliga a cada llamador a verificar el tipo antes de usar el resultado.
user_id existe desde el primer día, con un valor predeterminado y actualmente sin uso; la fase 4 limita cada consulta por él. Añadir una columna NOT NULL a una tabla poblada más tarde es una migración — añadirla ahora es gratis. Deliberadamente no es un parámetro de herramienta: si el modelo pudiera elegir el user_id, cualquier cliente podría leer los gastos de cualquiera solo con preguntar.
El registro va a stderr. Sobre el transporte stdio, stdout es el canal JSON-RPC, y un print() suelto corrompe el flujo del protocolo.
Aún no implementado
Limitaciones honestas en lugar de descuidos:
Sin herramientas de edición o eliminación. Corregir un gasto mal registrado significa ir directamente a la base de datos. Diferido hasta que demuestre ser molesto en la práctica.
Sin columna de moneda. Se asume que cada cantidad está en una sola moneda.
Sin autenticación. Cada gasto se escribe como
user_id = 'default', por lo que el servidor desplegado es de un solo inquilino hasta la fase 4.
Estructura
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_URLConstruido con
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