LedgerLink MCP
by bpmj-martin
README.md
# LedgerLink MCP
An MCP server that connects AI assistants to QuickBooks Online. Manage invoices, customers, expenses, and reports through natural conversation.
> "Show me all unpaid invoices" · "Create an invoice for Acme Corp for $5,000" · "What's my P&L for last quarter?"
## What It Does
LedgerLink MCP gives AI assistants (Claude Desktop, Cursor, etc.) direct access to your QuickBooks Online data through the [Model Context Protocol](https://modelcontextprotocol.io). Instead of clicking through the QuickBooks UI, you talk to your AI assistant in plain English.
**32 tools** across 10 QuickBooks entities:
| Category | Tools |
|----------|-------|
| **Invoices** | List, get, create, send, void |
| **Customers** | List, get, create, update |
| **Bills** | List, get, create |
| **Payments** | List, record |
| **Expenses** | List, get, create |
| **Reports** | Profit & Loss, Balance Sheet, Cash Flow, AR Aging, AP Aging |
| **Accounts** | List, get, create (Chart of Accounts) |
| **Vendors** | List, get, create |
| **Items** | List, get, create (Products & Services) |
| **Company** | Get company info |
## Quick Start
### 1. Get QuickBooks Credentials
1. Create a free account at [developer.intuit.com](https://developer.intuit.com)
2. Create an app → choose "QuickBooks Online and Payments"
3. Note your **Client ID** and **Client Secret**
4. Add `http://localhost:3847/callback` as a Redirect URI (under Settings)
### 2. Authenticate
```bash
# Clone and install
git clone https://github.com/YOUR_USERNAME/ledgerlink-mcp.git
cd ledgerlink-mcp
npm install
# Authenticate with QuickBooks (opens browser)
QB_CLIENT_ID=your_id QB_CLIENT_SECRET=your_secret npx tsx bin/cli.ts auth
```
A browser window opens → log in to QuickBooks → authorize → tokens are saved to `~/.ledgerlink/tokens.json`.
### 3. Add to Claude Desktop
Edit your Claude Desktop config:
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"ledgerlink": {
"command": "npx",
"args": ["tsx", "/path/to/ledgerlink-mcp/src/index.ts"],
"env": {
"QB_CLIENT_ID": "your_client_id",
"QB_CLIENT_SECRET": "your_client_secret",
"QB_ENVIRONMENT": "sandbox"
}
}
}
}
```
Restart Claude Desktop. You'll see the tools icon — start talking to your books.
### 4. Try It
- "Show me all unpaid invoices"
- "Who owes me the most money?"
- "What's my profit and loss for 2024?"
- "Create an invoice for customer ID 1 for $500 consulting"
- "List all bills due this week"
## How It Works
```
You: "Show me unpaid invoices"
↓
Claude Desktop → LedgerLink MCP (stdio) → QuickBooks API
↓
Claude: "You have 4 unpaid invoices totaling $3,200..."
```
LedgerLink runs as a local process. Claude Desktop spawns it, communicates over stdio (stdin/stdout), and your QuickBooks data never leaves your machine.
## Configuration
### Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| `QB_CLIENT_ID` | Yes | From Intuit developer portal |
| `QB_CLIENT_SECRET` | Yes | From Intuit developer portal |
| `QB_REDIRECT_URI` | No | Default: `http://localhost:3847/callback` |
| `QB_ENVIRONMENT` | No | `sandbox` (default) or `production` |
### Token Storage
Tokens are stored in `~/.ledgerlink/tokens.json` with owner-only permissions (chmod 600). Access tokens auto-refresh when expired (1-hour lifetime, 100-day refresh token).
## Tool Reference
### Invoices
- **`list_invoices`** — Filter by status (Unpaid/Paid/Overdue), customer, date range
- **`get_invoice`** — Full invoice details by ID
- **`create_invoice`** — Create with customer, line items, due date, memo
- **`send_invoice`** — Email an invoice to the customer
- **`void_invoice`** — Void an invoice (cannot be undone)
### Customers
- **`list_customers`** — Search by name, filter active/inactive
- **`get_customer`** — Full customer details by ID
- **`create_customer`** — Create with name, email, phone, address
- **`update_customer`** — Update existing customer fields
### Bills (Accounts Payable)
- **`list_bills`** — Filter by status, vendor, due date
- **`get_bill`** — Full bill details by ID
- **`create_bill`** — Create with vendor, line items, due date
### Payments
- **`list_payments`** — Filter by date range, customer
- **`record_payment`** — Record payment, optionally applied to an invoice
### Expenses
- **`list_expenses`** — Filter by date range, vendor
- **`get_expense`** — Full expense details by ID
- **`create_expense`** — Create with account, payment type, line items
### Reports
- **`get_profit_and_loss`** — P&L for a date range, optionally by month/week
- **`get_balance_sheet`** — Balance sheet as of a date
- **`get_cash_flow`** — Cash flow statement for a date range
- **`get_aging_receivables`** — Who owes you, grouped by aging bucket
- **`get_aging_payables`** — What you owe, grouped by aging bucket
### Chart of Accounts
- **`list_accounts`** — Filter by type (Bank, Expense, Income, etc.)
- **`get_account`** — Full account details by ID
- **`create_account`** — Create new account with type and sub-type
### Vendors
- **`list_vendors`** — Search by name, filter active/inactive
- **`get_vendor`** — Full vendor details by ID
- **`create_vendor`** — Create with name, email, phone
### Items (Products & Services)
- **`list_items`** — Search by name, filter by type (Service/Inventory)
- **`get_item`** — Full item details by ID
- **`create_item`** — Create with name, type, price, income account
### Company
- **`get_company_info`** — Company name, address, fiscal year, currency
## Development
```bash
# Install dependencies
npm install
# Run in development mode
QB_CLIENT_ID=xxx QB_CLIENT_SECRET=xxx npx tsx src/index.ts
# Test with MCP Inspector
QB_CLIENT_ID=xxx QB_CLIENT_SECRET=xxx npx @modelcontextprotocol/inspector npx tsx src/index.ts
# Type check
npx tsc --noEmit
# Build for distribution
npm run build
# Run tests
npm test
```
## Architecture
```
src/
├── index.ts # Entry point — wires everything together
├── auth/
│ ├── oauth.ts # OAuth 2.0 flow (local callback server)
│ └── token-store.ts # Token persistence (~/.ledgerlink/)
├── quickbooks/
│ ├── client.ts # HTTP client (auth, retry, rate limiting)
│ ├── types.ts # TypeScript types for QB entities
│ ├── invoices.ts # Invoice API operations
│ ├── customers.ts # Customer API operations
│ └── ... # (10 entity modules total)
├── tools/
│ ├── invoice-tools.ts # MCP tool registrations for invoices
│ ├── customer-tools.ts # MCP tool registrations for customers
│ └── ... # (10 tool modules total)
├── resources/
│ └── index.ts # MCP read-only resources
└── utils/
├── rate-limiter.ts # Sliding window (450 req/min)
├── query-builder.ts # QB query builder with sanitization
└── formatters.ts # Report response formatting
```
## Security
- Tokens stored with chmod 600 (owner-only read/write)
- Client credentials passed via environment variables, never committed
- Query builder sanitizes all user input to prevent QB query injection
- All QuickBooks data stays local — no external servers, no telemetry
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues