Laravel QuickBooks MCP
Un paquete Composer de PHP/Laravel de primera parte que expone QuickBooks Online (QBO) como un servidor del Protocolo de Contexto de Modelo (MCP).
Documentación
Laravel QuickBooks MCP
Un paquete Composer de PHP/Laravel de primera parte que expone QuickBooks Online (QBO) como un servidor de Model Context Protocol (MCP). Los clientes de IA — Claude, Cursor, n8n y otros — se conectan a través de HTTP y realizan operaciones CRUD completas sobre entidades de QBO usando lenguaje natural.
Esta es la primera implementación de QuickBooks MCP en PHP/Laravel del ecosistema.
Características
- 50 herramientas MCP que cubren 11 entidades de QBO (clientes, proveedores, facturas, cuentas por pagar, presupuestos, compras, empleados, artículos, cuentas, asientos de diario y pagos de facturas)
- Transporte HTTP remoto — no es stdio local, por lo que funciona con cualquier cliente de IA alojado
- Multiinquilino — múltiples empresas de QBO por instalación de Laravel
- Resolución de nombre a ID — los agentes pasan nombres legibles por humanos; las búsquedas de ID ocurren automáticamente
- Flujo OAuth 2.0 completo — cualquier usuario de SaaS puede conectar su propia empresa de QBO
- Listo para producción desde el primer día (sandbox también compatible)
- Autenticación nativa de Laravel — funciona con Passport o Sanctum, sin suposiciones
Requisitos
| Requisito | Versión |
|---|---|
| PHP | >= 8.2 |
| Laravel | >= 11.x |
laravel/mcp | ^1.0 |
spinen/laravel-quickbooks-client | ^4.0 |
Tu aplicación anfitriona también debe tener:
- Una tabla
userscon una columnaid(Laravel estándar) - El trait
HasQuickBooksTokendespinen/laravel-quickbooks-clienten el modeloUser - Al menos un guard de autenticación configurado que resuelva
auth()->user()a partir de un token Bearer (Passport o Sanctum)
Instalación
1. Instalar vía Composer
composer require rajurayhan/laravel-quickbooks-mcp-server
2. Publicar los assets del paquete
# Publish config
php artisan vendor:publish --tag=quickbooks-mcp-config
# Publish migrations
php artisan vendor:publish --tag=quickbooks-mcp-migrations
# Publish routes stub
php artisan vendor:publish --tag=quickbooks-mcp-routes
# Or publish everything at once
php artisan vendor:publish --provider="Raju\QuickBooksMcp\QuickBooksMcpServiceProvider"
3. Ejecutar las migraciones
php artisan migrate
Esto crea una tabla: quickbooks_connections.
4. Configurar tu .env
# Intuit app credentials (from developer.intuit.com)
QUICKBOOKS_CLIENT_ID=your_intuit_app_client_id
QUICKBOOKS_CLIENT_SECRET=your_intuit_app_client_secret
QUICKBOOKS_REDIRECT_URI=https://yourdomain.com/quickbooks/callback
QUICKBOOKS_SCOPE=com.intuit.quickbooks.accounting
QUICKBOOKS_DATA_SOURCE=production # or: development (sandbox)
# MCP server settings
QBO_MCP_PATH=mcp/quickbooks
QBO_TOKEN_REFRESH_BUFFER=5
5. Registrar las rutas publicadas
Abre routes/quickbooks-mcp.php (publicado en la carpeta routes/ de tu aplicación) y regístralo en tu aplicación. Elige una de las siguientes opciones:
Opción A — en app/Providers/AppServiceProvider.php:
public function boot(): void
{
Route::middleware('web')
->group(base_path('routes/quickbooks-mcp.php'));
}
Opción B — al final de routes/web.php o routes/api.php:
require base_path('routes/quickbooks-mcp.php');
6. Configurar tu guard de autenticación
Dentro de routes/quickbooks-mcp.php, cambia auth:api para que coincida con el guard de token Bearer de tu aplicación:
// Change 'api' to 'sanctum' if your app uses Laravel Sanctum
Route::middleware([
'api',
'auth:api', // ← change this line if needed
ResolveQuickBooksRealm::class,
RefreshQuickBooksToken::class,
])->group(function () {
Mcp::server(QuickBooksServer::class)->at(config('quickbooks-mcp.path'));
});
7. Registrar tu URI de callback OAuth de Intuit
En la configuración de tu aplicación de desarrollador de Intuit, añade esta URI de redirección:
https://yourdomain.com/quickbooks/callback
Debe coincidir exactamente con la ruta /quickbooks/callback.
8. Añadir HasQuickBooksToken a tu modelo User
use Spinen\QuickBooks\HasQuickBooksToken;
class User extends Authenticatable
{
use HasQuickBooksToken;
// ...
}
Flujo OAuth
Una vez instalado, un usuario de SaaS conecta su empresa de QBO a través de tu aplicación:
1. User visits GET /quickbooks/connect
→ Redirected to Intuit consent screen
→ Grants access to their QBO company
→ Redirected back to GET /quickbooks/callback
2. Callback handler:
→ Exchanges auth code for tokens (stored by spinen in quickbooks_tokens)
→ Package records connection in quickbooks_connections (realm_id + company_name)
3. User authenticates your app with their existing Bearer token (Passport or Sanctum)
4. AI client is configured with:
MCP URL: https://yourdomain.com/mcp/quickbooks
Header: Authorization: Bearer <bearer-token>
5. Every MCP tool call thereafter:
→ Guard authenticates the Bearer token
→ ResolveQuickBooksRealm finds the user's active QBO connection
→ RefreshQuickBooksToken silently refreshes QBO tokens near expiry
→ Tool runs — zero extra params needed from the AI agent
Rutas de gestión de conexiones
| Método | Ruta | Descripción |
|---|---|---|
GET | /quickbooks/connect | Redirigir a la pantalla de consentimiento OAuth de Intuit |
GET | /quickbooks/callback | Gestionar el callback de OAuth y almacenar los tokens |
DELETE | /quickbooks/disconnect | Revocar los tokens de QBO y eliminar la conexión |
GET | /quickbooks/connections | Listar las conexiones activas de QBO del usuario |
Configuración
config/quickbooks-mcp.php:
| Clave | Predeterminado | Descripción |
|---|---|---|
path | mcp/quickbooks | Ruta URL donde se expone el servidor MCP |
multi_tenant | true | Resolver el realm desde el usuario autenticado |
search_limit | 20 | Límite de resultados predeterminado para las herramientas de búsqueda |
search_limit_max | 100 | Límite máximo de resultados para las herramientas de búsqueda |
environment | production | Entorno de QBO (production o development) |
redirect_uri | APP_URL/quickbooks/callback | URI de redirección de OAuth |
token_refresh_buffer_minutes | 5 | Minutos antes de la expiración para renovar de forma proactiva |
Herramientas disponibles
Cuenta (3 herramientas)
| Herramienta | Descripción |
|---|---|
create_account | Crear una nueva cuenta en el plan de cuentas |
search_accounts | Buscar cuentas por nombre o tipo |
update_account | Actualizar una cuenta existente |
Cuenta por pagar (5 herramientas)
| Herramienta | Descripción |
|---|---|
create_bill | Crear una nueva cuenta por pagar |
get_bill | Obtener una cuenta por pagar por ID |
search_bills | Buscar cuentas por pagar por proveedor, rango de fechas o estado de impago |
update_bill | Actualizar una cuenta por pagar existente |
delete_bill | Eliminar permanentemente una cuenta por pagar |
Pago de cuentas por pagar (5 herramientas)
| Herramienta | Descripción |
|---|---|
create_bill_payment | Pagar una o más cuentas por pagar abiertas |
get_bill_payment | Obtener un pago de cuenta por pagar por ID |
search_bill_payments | Buscar pagos de cuentas por pagar por proveedor o rango de fechas |
update_bill_payment | Actualizar un pago de cuenta por pagar existente |
delete_bill_payment | Eliminar permanentemente un pago de cuenta por pagar |
Cliente (5 herramientas)
| Herramienta | Descripción |
|---|---|
create_customer | Crear un nuevo cliente |
get_customer | Obtener un cliente por ID |
search_customers | Buscar clientes por nombre, correo electrónico o empresa |
update_customer | Actualizar un cliente existente |
delete_customer | Desactivar un cliente (borrado suave de QBO) |
Empleado (4 herramientas)
| Herramienta | Descripción |
|---|---|
create_employee | Crear un nuevo registro de empleado |
get_employee | Obtener un empleado por ID |
search_employees | Buscar empleados por nombre o correo electrónico |
update_employee | Actualizar un empleado existente |
Presupuesto (5 herramientas)
| Herramienta | Descripción |
|---|---|
create_estimate | Crear un nuevo presupuesto / cotización |
get_estimate | Obtener un presupuesto por ID |
search_estimates | Buscar presupuestos por cliente, estado o rango de fechas |
update_estimate | Actualizar o cambiar el estado de un presupuesto |
delete_estimate | Eliminar permanentemente un presupuesto |
Factura (4 herramientas)
| Herramienta | Descripción |
|---|---|
create_invoice | Crear una nueva factura |
read_invoice | Leer una factura completa con todas sus líneas de detalle |
search_invoices | Buscar facturas por cliente, rango de fechas o estado de pago |
update_invoice | Actualizar una factura existente |
Las facturas no se pueden eliminar permanentemente en QBO.
Artículo (4 herramientas)
| Herramienta | Descripción |
|---|---|
create_item | Crear un nuevo artículo de producto o servicio |
read_item | Leer un registro completo de artículo con precios y asignaciones de cuentas |
search_items | Buscar artículos por nombre o tipo |
update_item | Actualizar un artículo existente (establecer active: false para desactivar) |
Los artículos no se pueden eliminar permanentemente en QBO.
Asiento de diario (5 herramientas)
| Herramienta | Descripción |
|---|---|
create_journal_entry | Crear un asiento de diario (los débitos deben ser iguales a los créditos) |
get_journal_entry | Obtener un asiento de diario por ID |
search_journal_entries | Buscar asientos de diario por rango de fechas o número de documento |
update_journal_entry | Actualizar un asiento de diario existente |
delete_journal_entry | Eliminar permanentemente un asiento de diario |
Compra (5 herramientas)
| Herramienta | Descripción |
|---|---|
create_purchase | Crear una transacción de compra / gasto |
get_purchase | Obtener una compra por ID |
search_purchases | Buscar compras por tipo de pago o rango de fechas |
update_purchase | Actualizar una compra existente |
delete_purchase | Eliminar permanentemente una compra |
Proveedor (5 herramientas)
| Herramienta | Descripción |
|---|---|
create_vendor | Crear un nuevo proveedor |
get_vendor | Obtener un proveedor por ID |
search_vendors | Buscar proveedores por nombre, correo electrónico o empresa |
update_vendor | Actualizar un proveedor existente |
delete_vendor | Desactivar un proveedor (borrado suave de QBO) |
Resolución de nombres
Las herramientas que hacen referencia a entidades relacionadas (proveedor, cliente, cuenta, artículo) aceptan tanto un nombre como un ID numérico. El paquete resuelve los nombres a IDs automáticamente antes de llamar a la API de QBO.
# These are equivalent when calling create_bill:
vendor: "Office Depot"
vendor: "42"
Si no se encuentra un nombre, la herramienta devuelve un error descriptivo con una sugerencia para usar primero la herramienta de búsqueda correspondiente.
Comportamiento de eliminación
QBO tiene dos categorías de eliminación:
| Comportamiento | Entidades |
|---|---|
Borrado suave — establece Active = false | Cliente, Proveedor, Empleado, Artículo, Cuenta |
| Borrado duro — eliminado permanentemente | Bill, BillPayment, Estimate, JournalEntry, Purchase |
| No se puede eliminar | Invoice, Item (usar update_item con active: false) |
Arquitectura multiinquilino
Cada usuario autenticado tiene exactamente una conexión activa de QBO registrada en la tabla quickbooks_connections. El middleware ResolveQuickBooksRealm limita automáticamente cada llamada de herramienta a la empresa de QBO correcta — nunca se necesita un parámetro realm_id por parte del agente de IA.
Arquitectura del paquete
src/
├── QuickBooksMcpServiceProvider.php — registers service, publishes assets
├── Server/QuickBooksServer.php — MCP server, registers all 50 tools
├── Services/QuickBooksService.php — QBO API wrapper, name resolvers
├── Concerns/ResolvesEntityNames.php — trait for name-to-ID resolution
├── Http/
│ ├── Controllers/QuickBooksOAuthController.php
│ └── Middleware/
│ ├── ResolveQuickBooksRealm.php — scopes QBO service to user's company
│ └── RefreshQuickBooksToken.php — proactive token refresh
├── Models/QuickBooksConnection.php — tracks user ↔ QBO company links
├── Exceptions/
│ ├── QuickBooksAuthException.php
│ └── QuickBooksToolException.php
└── Tools/ — 50 tool classes across 11 entities
├── Account/, Bill/, BillPayment/, Customer/, Employee/
├── Estimate/, Invoice/, Item/, JournalEntry/
├── Purchase/, Vendor/
Licencia
MIT — consulta LICENSE para más detalles.
Autor
Raju Rayhan — github.com/rajurayhan