MainBook Bank Statement Converter
Convierte extractos bancarios en PDF a Excel, CSV o JSON verificados, con validación de saldo.
Documentación
MainBook Bank Statement Converter
Un servidor MCP de finanzas enfocado en una sola tarea: convertir estados de cuenta bancarios en PDF a JSON, Excel o CSV verificados — no es un MCP de contabilidad general. Se ejecuta localmente después de un mainbook-mcp auth login, o a través del endpoint alojado de MainBook en https://mcp.mainbook.ai/mcp, donde tu cliente te permite iniciar sesión con tu cuenta de MainBook. Las claves API existentes de mb_live_ siguen funcionando para scripts y clientes más antiguos.
Señala a tu asistente un estado de cuenta y pide una hoja de cálculo. El PDF se envía a MainBook, que extrae cada transacción, normaliza las fechas a YYYY-MM-DD, mantiene el dinero como montos exactos, y vuelve a sumar el estado de cuenta para que opening balance + credits − debits tenga que coincidir con el saldo de cierre. Las filas que no encajan se marcan en lugar de pasarse por alto silenciosamente.
> Convert ~/Downloads/march-statement.pdf and save the Excel next to it.
mainbook - convert_bank_statement (MCP)
63 transactions · 4 pages · 4 credits
Totals reconciled against the statement
Saved to ~/Downloads/march-statement.xlsx
Done — 63 transactions. Opening 4,127.50 and closing 3,881.05 both match
the statement, and nothing was flagged.
Lo que no es
No se conecta a cuentas bancarias y no es una API de Open Banking ni de datos bancarios. Lee archivos de estados de cuenta que ya tienes. No se extrae nada y no se involucran credenciales bancarias.
Lo que necesitas
Una cuenta de MainBook y las carpetas que contienen tus estados de cuenta. La conversión es la única herramienta que gasta créditos de página. De las otras cuatro, get_balance y list_conversions solo leen, get_conversion puede escribir un archivo de resultado, y output_folder cambia una preferencia local; ninguna de ellas cambia nada en tu cuenta de MainBook.
Añádelo a tu cliente
Inicia sesión una vez desde una terminal:
uvx mainbook-mcp auth login
El comando abre MainBook en tu navegador, muestra el mismo código corto en ambos lugares, y espera tu aprobación. Almacena la credencial en el llavero del sistema operativo cuando el paquete opcional keyring está instalado y funcionando. De lo contrario, usa ~/.config/mainbook/credentials.json con permisos privados de directorio y archivo. Usa mainbook-mcp auth status para verificar la credencial activa en el servidor sin gastar créditos de página. mainbook-mcp auth logout revoca esa clave almacenada primero, luego elimina la copia local; si MainBook no se puede alcanzar, dice claramente que la clave puede seguir activa. Iniciar sesión de nuevo revoca la clave previamente almacenada antes de guardar su reemplazo. La respuesta del token del dispositivo no incluye un correo electrónico ni un ID de cuenta, por lo que el estado dice que la identidad de la cuenta no fue proporcionada en lugar de adivinar.
Luego añade una entrada a la configuración MCP de tu cliente. Este es el mismo bloque para Claude Desktop (Configuración → Desarrollador → Editar Config), Claude Code y Cursor; no se copia ninguna clave en él:
{
"mcpServers": {
"mainbook": {
"command": "uvx",
"args": ["mainbook-mcp", "~/Downloads", "~/Desktop", "~/Documents"]
}
}
}
Codex lee TOML, así que pon lo mismo en ~/.codex/config.toml:
[mcp_servers.mainbook]
command = "uvx"
args = ["mainbook-mcp", "~/Downloads", "~/Desktop", "~/Documents"]
uvx viene con uv; instálalo una vez con brew install uv o curl -LsSf https://astral.sh/uv/install.sh | sh. Descarga y ejecuta el paquete publicado, así que no hay nada que descargar manualmente ni nada que actualizar. Si prefieres no añadir uv, ejecuta pip install mainbook-mcp y usa "command": "mainbook-mcp" con los mismos argumentos — luego lo actualizas tú mismo con pip install -U mainbook-mcp.
Los argumentos de carpeta son los únicos lugares donde el servidor puede leer un estado de cuenta o escribir un resultado; cualquier cosa fuera de ellos es rechazada. MAINBOOK_ALLOWED_DIRS establece la misma lista a través del entorno en su lugar, separada por el os.pathsep de la plataforma (: en macOS/Linux, ; en Windows).
Clave API manual para scripts y CI
MAINBOOK_API_KEY tiene prioridad sobre cualquier inicio de sesión almacenado. Mantén el método manual para automatización donde no hay un navegador interactivo disponible. auth login advierte cuando esta variable seguirá anulando la credencial recién almacenada:
export MAINBOOK_API_KEY="mb_live_REPLACE_ME"
mainbook-mcp
Crea y revoca claves manuales en https://mainbook.ai/developer. Nunca las confirmes.
Claude Desktop, sin tocar un archivo de configuración
Claude Desktop también acepta un paquete de un solo archivo: Extensiones → Instalar Extensión… y elige mainbook.mcpb. Pide la clave API y las carpetas en un diálogo y gestiona su propio runtime de Python, así que no hay nada que instalar primero. El bloque de configuración anterior hace el mismo trabajo y es la mejor opción si ya mantienes otros servidores allí. Construye el paquete desde este directorio con:
npx --yes @anthropic-ai/mcpb@2.1.2 validate manifest.json
npx --yes @anthropic-ai/mcpb@2.1.2 pack . dist/mainbook.mcpb
Lo que expone
convert_bank_statement: crea un trabajo de crédito de página de pago, sube un PDF, inicia la conversión, consulta durante hasta 30-900 segundos, y devuelve el resultado revisado. El JSON permanece en línea. En modo stdio local, los bytes XLSX/CSV se escriben en disco y solo la ruta completa entra en el contexto del modelo.get_conversion: verifica un trabajo después de un tiempo de espera y devuelve JSON en línea o escribe XLSX/CSV en un destino local elegido.list_conversions: devuelve una página de cursor de trabajos de cuenta másnext_cursor.get_balance: devuelve créditos totales, reservados y disponibles, todos medidos en páginas PDF.output_folder: lee o cambia la carpeta de resultados local predeterminada.
El modo stdio local lista las cinco herramientas. El modo HTTP alojado lista exactamente las primeras cuatro; output_folder no se anuncia de forma remota porque el disco del servidor no pertenece al cliente.
No hay herramientas para comprar créditos, pagos, eliminar trabajos o cambiar datos de cuenta. Las herramientas que pueden crear una conversión, escribir un archivo de resultado local o cambiar la preferencia de salida están marcadas como no solo lectura. get_conversion es de solo lectura sobre HTTP alojado, donde no escribe ningún archivo, y no solo lectura sobre stdio local, donde puede escribir XLSX o CSV. Ninguna está marcada como destructiva porque los archivos de resultado existentes nunca se reemplazan.
Dónde van los archivos de resultado
Para clientes stdio locales (Claude Desktop, Claude Code, Cursor y Codex), los resultados XLSX y CSV se escriben en el primer destino disponible en este orden:
output_pathproporcionado aconvert_bank_statementoget_conversion(un nombre de archivo absoluto o una carpeta existente);- la carpeta recordada por
output_folder; - junto al PDF fuente, con el mismo nombre base y la extensión de resultado.
get_conversion no puede inferir la carpeta del PDF original. Sin output_path o una carpeta recordada válida devuelve un error claro en lugar de adivinar un destino. Cada respuesta de archivo exitosa contiene la ruta absoluta y explica qué regla la seleccionó. Los archivos existentes nunca se reemplazan: statement.xlsx es seguido por statement (2).xlsx, luego (3), y así sucesivamente.
Pide al cliente que llame a output_folder sin argumento para ver la configuración actual y cada carpeta permitida. Establécelo con un directorio absoluto permitido, o pasa next_to_source para restaurar el valor predeterminado. La preferencia es compartida por clientes locales en la misma máquina en ~/.mainbook/preferences.json. Una carpeta guardada que falta o ya no está permitida se ignora, y esa alternativa se indica en el resultado.
El JSON permanece en línea. También se escribe en un archivo .json solo cuando se proporciona un output_path explícito. En modo HTTP remoto, las rutas locales y output_folder no están disponibles, porque el disco del servidor no pertenece al cliente. XLSX/CSV vuelve como un enlace de descarga de un solo uso que caduca en diez minutos cuando iniciaste sesión a través de OAuth, y como una instrucción de descarga REST cuando te autenticaste con una clave mb_live_ heredada.
Requisitos e instalación manual
- Python 3.11 o más reciente
- Una cuenta de MainBook
Desde este directorio:
python3 -m venv .venv
.venv/bin/python -m pip install .
Para preferir el llavero del sistema operativo sobre la alternativa JSON privada, instala el extra opcional en cada entorno que ejecute el comando de inicio de sesión o el servidor local:
.venv/bin/python -m pip install '.[keyring]'
Usa una instalación normal, no pip install -e .. En este checkout, la instalación editable escribe un archivo .pth que el intérprete no recoge, así que python -m mainbook_mcp falla con "No module named mainbook_mcp" mientras el paquete parece instalado. Un archivo idéntico con otro nombre se honra, así que el contenido está bien y la causa sigue sin explicación — una instalación normal lo evita por completo.
Si usas el método manual para automatización, mantén los valores de mb_live_... en un entorno secreto o configuración de cliente. Nunca los confirmes.
Modo HTTP Streamable
MainBook ejecuta este servidor por ti en https://mcp.mainbook.ai/mcp, así que un cliente que hable MCP remoto no necesita nada instalado. Pega esa URL en claude.ai, Claude Desktop, ChatGPT o Cursor e inicia sesión con tu cuenta de MainBook cuando el cliente lo pida; no se copia ninguna clave en la configuración. Cursor toma un ID de cliente fijo en lugar de registrarse, así que dale este bloque:
{
"mcpServers": {
"mainbook": {
"url": "https://mcp.mainbook.ai/mcp",
"auth": {
"CLIENT_ID": "mainbook-cursor",
"scopes": ["mainbook:read", "mainbook:convert"]
}
}
}
}
Un cliente que no puede iniciar sesión aún puede enviar una clave heredada desde mainbook.ai/developer:
Authorization: Bearer mb_live_REPLACE_ME
Cualquiera de las dos credenciales se lee de cada solicitud, así que cada usuario de un cliente llega a su propia cuenta de MainBook y gasta sus propios créditos de página. initialize y tools/list responden sin credencial; cada llamada de herramienta requiere una. Las rutas de archivo locales y output_folder no existen sobre HTTP — pasa file_url en lugar de file_path, porque el disco del servidor no es tuyo. Los resultados XLSX o CSV vuelven como un enlace de descarga de un solo uso (diez minutos, uso único) para sesiones OAuth, o como una instrucción de descarga REST para una clave mb_live_ heredada.
También puedes ejecutar el mismo modo remoto tú mismo. Es HTTP Streamable sin estado con respuestas JSON:
mainbook-mcp --transport http --host 127.0.0.1 --port 8000
El endpoint MCP es entonces http://127.0.0.1:8000/mcp. Cada cliente debe enviar su propio encabezado:
Authorization: Bearer mb_live_REPLACE_ME
El encabezado se lee de cada solicitud de llamada de herramienta y nunca se almacena en estado global. El modo HTTP alojado no inspecciona MAINBOOK_API_KEY, el llavero del sistema operativo, ni el archivo de credenciales local. Para el modo remoto de Codex:
[mcp_servers.mainbook]
url = "https://mcp.mainbook.ai/mcp"
bearer_token_env_var = "MAINBOOK_API_KEY"
tool_timeout_sec = 920
default_tools_approval_mode = "writes"
Reemplaza la URL con tu propio host si lo despliegas tú mismo; un despliegue autoalojado aún necesita terminación HTTPS normal y controles de acceso.
OAuth en el servicio alojado
El inicio de sesión de cuenta está activo en https://mcp.mainbook.ai/mcp (desde 2026-08-20). El verificador permanece deshabilitado por defecto en este árbol fuente, así que un despliegue que ejecutes tú mismo tiene que habilitarlo deliberadamente. Donde esté habilitado, initialize y tools/list permanecen públicos, mientras que cada llamada de herramienta acepta una clave mb_live_ existente o un token de acceso RS256 de MainBook. Los tokens OAuth se verifican localmente solo contra la URL JWKS de MainBook configurada; nunca se reenvían a la API de Desarrollador. El servidor MCP envía una credencial X-MainBook-Service fresca de 60 segundos para cada solicitud REST interna en su lugar.
Los ámbitos de herramientas alojados están fijos en un mapa: convert_bank_statement requiere mainbook:convert; get_balance, get_conversion y list_conversions requieren mainbook:read. Los metadatos de recursos protegidos se publican en /.well-known/oauth-protected-resource/mcp solo mientras la bandera está habilitada.
Variables de entorno
MAINBOOK_API_KEY: opcional en stdio y tiene prioridad sobre un inicio de sesión almacenado; se ignora en modo HTTP, donde cada llamada de herramienta debe llevar su propio encabezado Bearer.MAINBOOK_API_BASE_URL: host REST, predeterminadohttps://api.mainbook.ai. El servidor añade/api/v1/developer.MAINBOOK_ALLOWED_DIRS: carpetas locales permitidas para lecturas de origen y escrituras de resultados, separadas por elos.pathsepde la plataforma (:en macOS/Linux y;en Windows). Los argumentos posicionales de directorio tienen prioridad. Si no se proporciona ninguno, los valores predeterminados son~/Downloads,~/Desktopy~/Documents.MAINBOOK_MCP_TRANSPORT:stdio(predeterminado) ohttp.MAINBOOK_MCP_HOST: host de enlace HTTP, predeterminado127.0.0.1.MAINBOOK_MCP_PORT: puerto de enlace HTTP, predeterminado8000.MAINBOOK_MCP_OAUTH_ENABLED: indicador de función del verificador OAuth alojado, predeterminadofalse. Con el indicador desactivado, los metadatos están ausentes y el manejo de Bearer alojado permanece en el comportamiento heredado demb_live_.MAINBOOK_MCP_OAUTH_ISSUER: emisor de confianza exacto, predeterminadohttps://api.mainbook.ai.MAINBOOK_MCP_OAUTH_JWKS_URL: URL JWKS de confianza, predeterminadohttps://api.mainbook.ai/.well-known/jwks.json. Las URLs de encabezado de token se ignoran.MAINBOOK_MCP_OAUTH_RESOURCE: audiencia/recurso exacto, predeterminadohttps://mcp.mainbook.ai/mcp.MAINBOOK_MCP_OAUTH_CLOCK_SKEW_SECONDS: margen de reloj NumericDate, predeterminado5.MAINBOOK_MCP_OAUTH_MAX_TOKEN_AGE_SECONDS: edad máxima aceptada desdeiat, predeterminado600.MAINBOOK_MCP_OAUTH_JWKS_CACHE_TTL_SECONDS: vida útil de caché JWKS, predeterminado300.MAINBOOK_MCP_OAUTH_JWKS_REFRESH_MIN_INTERVAL_SECONDS: intervalo mínimo entre intentos de actualización dekiddesconocido, predeterminado30.MCP_SERVICE_SIGNING_SECRETS: secretos de puerta de servicio separados por comas. MCP firma con el primero; Django puede aceptar valores actuales y anteriores durante la rotación. Requerido cuando OAuth está habilitado; nunca lo comprometas.
Seguridad de archivos y red
file_pathyfile_urlson mutuamente excluyentes.file_pathse acepta solo sobre stdio local; el modo HTTP lo rechaza antes de que se ejecute el cargador de archivos y requierefile_url.- El acceso local a
file_pathy las escrituras de archivos de resultados usan las mismas carpetas configuradas. Los directorios CLI posicionales tienen prioridad sobreMAINBOOK_ALLOWED_DIRS; el entorno tiene prioridad sobre los valores predeterminados~/Downloads,~/Desktopy~/Documents. Cada raíz se expande y resuelve, las raíces faltantes se ignoran y las raíces activas se imprimen en stderr cuando el servidor se inicia. Si no quedan raíces, el acceso local falla de manera segura mientras el servidor continúa ejecutándose. - Los padres de salida se resuelven antes de escribir y se verifican por identidad de directorio, por lo que un enlace simbólico no puede redirigir un resultado fuera de las carpetas permitidas. La creación de resultados es exclusiva y segura contra colisiones; los archivos existentes no se sobrescriben.
~/.mainbook/preferences.jsonse reemplaza atómicamente. El directorio.mainbooktiene modo0700y el archivo de preferencias tiene modo0600; las preferencias malformadas o ilegibles se ignoran de manera segura.- Las credenciales de terminal usan el llavero del sistema operativo cuando el paquete opcional es utilizable. El
~/.config/mainbook/credentials.jsonde respaldo se reemplaza atómicamente dentro de un directorio con modo0700y tiene modo0600; sus entradas de nivel superior están claveadas por URL base de API. - Las rutas locales se expanden y resuelven estrictamente antes de la verificación de la lista de permitidos, por lo que
..y los enlaces simbólicos no pueden hacer que un objetivo externo parezca estar dentro de una carpeta permitida. La ruta resuelta debe estar estrictamente debajo de una raíz, no igual a la raíz misma. - El archivo local se abre una vez. El servidor usa
fstaten ese descriptor para requerir un archivo regular y aplicar el límite de 50 MiB, luego realiza la lectura limitada a través del mismo descriptor. Esto cierra la ventana de reemplazo entre verificación y lectura, pero no elimina por completo la carrera entre resolver la ruta y abrirla; la ruta aún puede reemplazarse durante ese intervalo. - Un archivo local debe contener
%PDF-dentro de sus primeros 1024 bytes antes de invocarpypdf. Las extensiones de nombre de archivo no se usan para decidir si un archivo es un PDF. - Los archivos remotos deben usar HTTPS. No se siguen redirecciones.
- Las respuestas DNS se rechazan si alguna dirección es privada, de bucle local, de enlace local, de metadatos, reservada o no pública, tanto para IPv4 como para IPv6.
- Las descargas de URL se conectan a una IP numérica ya validada mientras conservan el nombre de host original para la verificación del certificado TLS y el encabezado HTTP
Host, cerrando las carreras de reenlace DNS. Content-Lengthy el recuento real de bytes transmitidos están limitados de forma independiente a 50 MiB.- Los PDFs se analizan localmente con
pypdfy se limitan a 500 páginas. - Los encabezados de carga pre-firmados de MainBook se reenvían sin cambios; la clave Bearer de MainBook nunca se envía al almacenamiento.
Comprobaciones de desarrollo
.venv/bin/python -m pip install '.[dev]'
.venv/bin/pytest
.venv/bin/pytest --cov=mainbook_mcp --cov-report=term-missing --cov-report=annotate:cov_annotate
.venv/bin/ruff check .
Todas las pruebas REST usan mocks o un stub local. Ninguna prueba requiere o acepta una clave API real de MainBook.