Connect Wave to Claude: Sync Customers, Products, and Sales Taxes
A definitive engineering guide to connecting Wave to Claude via an MCP server. Automate invoices, sync products, and bypass GraphQL accounting API complexities.
If your finance team needs to connect Wave to Claude to automate accounting workflows, reconcile ledgers, and manage sales tax compliance, you need a Model Context Protocol (MCP) server. This infrastructure layer translates the model's intent into executable API requests. You can spend weeks building and hosting this infrastructure internally, or you can use a managed platform like Truto to instantly deploy a secure, compliant MCP endpoint. If your team uses ChatGPT, check out our guide on connecting Wave to ChatGPT or explore our broader architectural framework on connecting Wave to AI Agents.
Granting a Large Language Model (LLM) autonomous access to an accounting platform is not a trivial task. Wave houses highly sensitive business data. Building a custom integration means you are responsible for maintaining complex authentication lifecycles, mapping intricate financial schemas to LLM tool definitions, and preventing hallucinations from corrupting your general ledger.
This guide outlines exactly how to bypass the boilerplate. We will cover how to use Truto to generate a secure, managed Wave MCP server, connect it directly to Claude, and execute sophisticated financial automation using natural language.
The Engineering Reality of the Wave API
A custom MCP server is essentially a self-hosted API proxy. While Anthropic's MCP provides a standardized format for models to discover and execute tools via JSON-RPC 2.0, the reality of implementing it against Wave's specific architecture introduces immediate friction.
Wave does not expose a standard REST API. It relies heavily on a GraphQL architecture. If you decide to build a custom MCP server for Wave, you must navigate several unique engineering hurdles:
GraphQL Mutations and Field-Level Error Handling
Wave utilizes GraphQL mutations for all write operations (e.g., accountCreate, invoicePatch). When an API relies on GraphQL, an HTTP 200 OK response does not guarantee the operation was successful. Domain-level validation failures are frequently returned inside the response payload as an inputErrors [] array. If you pass raw GraphQL responses to Claude, the model will often misinterpret an HTTP 200 status as a success, failing to realize the invoice was rejected due to an invalid currency code. Truto's proxy layer normalizes these responses, mapping them to standard REST-like tool definitions so Claude can explicitly read and react to inputErrors [] without parsing complex GraphQL error nodes.
The Classic vs Beta Accounting Split
Wave is in the middle of a data model transition. If you are interacting with money transactions, the API explicitly distinguishes between legacy systems and the newer architecture. For example, the moneyTransactionCreate mutation requires a boolean flag indicating isClassicAccounting is false. Exposing this architectural nuance directly to an LLM almost guarantees hallucinations. Truto encapsulates these operational requirements within documented JSON schemas, guiding Claude to provide the correct flags based on the target account's state.
Pagination Inconsistencies
Wave utilizes offset pagination (page and pageSize) for certain heavily populated endpoints like businesses and invoices, while returning unpaginated, flat arrays for static directories like countries and currencies. If you expose raw offset parameters to Claude, the model will frequently attempt to paginate unpaginated endpoints or lose its place in paginated lists. Truto normalizes the paginated endpoints using a standard limit and next_cursor schema. The tool description explicitly instructs the model to pass the cursor back unchanged, effectively preventing pagination hallucinations.
Rate Limits and 429 Handling
Wave enforces API rate limits to protect its infrastructure. Truto does not retry, throttle, or apply backoff on rate limit errors. When Wave returns an HTTP 429, Truto passes that error directly back to the caller. However, Truto normalizes the upstream rate limit information into standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). The system orchestrating Claude is entirely responsible for implementing retry and exponential backoff logic based on these standardized headers.
Instead of building a GraphQL translation layer from scratch, handling token lifecycles, and managing error parsing, you can use Truto to dynamically generate a managed MCP server. Truto converts Wave's GraphQL schema into a clean array of MCP-compatible tools.
How to Generate a Wave MCP Server
Truto creates MCP servers dynamically based on your integrated accounts. A server is backed by a cryptographic token that maps to a specific tenant's authenticated Wave instance.
You can generate the MCP server using either the Truto UI or the API.
Method 1: Generating via the Truto UI
If you prefer a visual interface, you can generate a server in less than a minute:
- Log in to your Truto dashboard.
- Navigate to the Integrated Accounts section and select your connected Wave account.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Select your desired configuration. You can assign a human-readable name, restrict operations to
readorwritemethods, filter tools by tags, and set an expiration date. - Click Create and copy the generated MCP Server URL (e.g.,
https://api.truto.one/mcp/a1b2c3d4...).
Method 2: Generating via the API
For platform engineers building scalable SaaS features, MCP servers should be generated programmatically. This allows you to spin up temporary, scoped access for your AI agents dynamically.
Make a POST request to /integrated-account/:id/mcp. You must authenticate this request using your Truto API token.
curl -X POST https://api.truto.one/integrated-account/YOUR_ACCOUNT_ID/mcp \
-H "Authorization: Bearer YOUR_TRUTO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Wave Financial Automation Server",
"config": {
"methods": ["read", "write", "custom"]
}
}'The Truto API will evaluate the Wave integration, ensure it has documented tools available, provision the secure token infrastructure, and return the server details.
{
"id": "mcp_xyz789",
"name": "Wave Financial Automation Server",
"config": {
"methods": ["read", "write", "custom"]
},
"expires_at": null,
"url": "https://api.truto.one/mcp/a1b2c3d4e5f6..."
}Keep this url safe. It contains the hashed token required to authenticate the JSON-RPC connection.
Connecting the Wave MCP Server to Claude
Once you have the Truto MCP URL, connecting it to Claude requires zero additional code. Anthropic supports Server-Sent Events (SSE) connections for MCP servers natively.
Method 1: Connecting via the Claude UI
If you are using Claude Desktop or an enterprise workspace that supports UI configuration:
- Open Claude and navigate to Settings.
- Locate the Integrations or Developer / Custom Connectors tab (depending on your specific Claude tier).
- Click Add MCP Server.
- Paste the Truto MCP URL (
https://api.truto.one/mcp/...) into the input field and save.
Claude will immediately ping the server, invoke the tools/list JSON-RPC method, and load the available Wave operations into its context.
Method 2: Connecting via the Config File
If you are running Claude Desktop locally for development, you can map the remote SSE endpoint using a local proxy command in your configuration file.
Open your claude_desktop_config.json file (typically located at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS or %APPDATA%\Claude\claude_desktop_config.json on Windows).
Add the Truto URL using the standard @modelcontextprotocol/server-sse package via npx:
{
"mcpServers": {
"wave_financial": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sse",
"https://api.truto.one/mcp/a1b2c3d4e5f6..."
]
}
}
}Restart Claude Desktop. The model will automatically discover the tools and you can begin prompting it.
Hero Tools for Wave
Truto exposes dozens of endpoints across the Wave ecosystem. Here are the highest-leverage operations your agent can use to orchestrate financial workflows.
list_all_wave_businesses
Description: Wave requires a businessId for almost every major operation (creating customers, issuing invoices, recording transactions). This tool returns all businesses associated with the authenticated user, providing the foundational ID required for subsequent calls.
Usage note: The response is paginated via limit and next_cursor. The response includes the business's default currency and timezone.
"Claude, check my Wave account and list all the businesses I have access to. Give me the business ID and default currency for the one named 'Acme Corp'."
create_a_wave_customer
Description: Creates a new customer record via the customerCreate GraphQL mutation. This is a prerequisite for generating estimates and invoices.
Usage note: Requires the businessId and a customer name. The API returns an inputErrors [] array if the operation fails validation at the field level.
"Claude, create a new customer in my primary Wave business. The company name is 'Stark Industries'. Make sure to check the response for any input errors."
create_a_wave_product
Description: Adds a product or service item to the business catalog via the productCreate mutation.
Usage note: Requires businessId, name, and unitPrice. You can optionally provide default sales tax IDs to automatically apply taxes when this product is invoiced.
"Claude, add a new product to my Wave account called 'Enterprise Consulting SLA'. Set the unit price to 5000 and ensure it is linked to my primary business ID."
create_a_wave_invoice
Description: Drafts a new invoice mapping a business to a customer via the invoiceCreate mutation.
Usage note: Requires both the businessId and customerId. The initial call drafts the invoice. You must use subsequent update tools to add line items.
"Claude, draft a new invoice for 'Stark Industries'. Use the business ID you found earlier. Let me know what the generated invoice ID is so we can add line items."
wave_invoices_send
Description: Dispatches a drafted or approved invoice to the customer via email.
Usage note: The business must have emailSendEnabled set to true. Requires the invoiceId and an array of destination email addresses (to). You can customize the subject line and message body.
"Claude, take invoice INV-1002 and send it to tony@stark.com. Include a custom message thanking them for their business and attach the PDF."
create_a_wave_money_transaction
Description: Records a financial transaction in the general ledger via the moneyTransactionCreate mutation.
Usage note: This is part of the BETA API and requires the account to have isClassicAccounting set to false. You must provide the businessId, date, description, and the detailed lineItems array.
"Claude, log a new money transaction for an office supply expense. The amount is $45.50. Ensure you format the line items correctly for the new transaction API."
To view the complete schema definitions and the full list of supported Wave endpoints, visit the Truto Wave integration reference.
Workflows in Action
Access to individual tools is useful, but the real power of connecting Claude to Wave via MCP is the ability to orchestrate complex, multi-step workflows autonomously.
Scenario 1: Quote-to-Cash Automation
Sales teams close deals in an external CRM, but the finance team needs the customer created and invoiced in Wave. Instead of manual data entry, you can instruct Claude to handle the entire lifecycle.
"Claude, I just closed a deal with 'Globex Corporation'. They need to be billed for our 'Annual Software License' at $12,000. Please create the customer in Wave, ensure the product exists in our catalog, generate the invoice, and email it to hank@globex.com."
Execution Sequence:
list_all_wave_businesses: Claude fetches the context to locate the correctbusinessId.create_a_wave_customer: Claude creates the "Globex Corporation" record and extracts the newcustomerId.create_a_wave_product: Claude adds the "Annual Software License" to the product catalog at the specified unit price.create_a_wave_invoice: Claude initializes the invoice connecting the business and customer.update_a_wave_invoice_by_id: Claude patches the drafted invoice, attaching the product as a line item.wave_invoices_approve: Claude marks the invoice as approved.wave_invoices_send: Claude executes the send mutation, emailing the final PDF to the provided address.
Result: The user receives a conversational confirmation that the customer was onboarded and the $12,000 invoice has been dispatched, complete with the Wave invoice reference number.
Scenario 2: Payment Reconciliation
When manual payments are received outside of standard gateways (like wire transfers or mailed checks), they must be reconciled against open invoices.
"Claude, we just received a wire transfer for $2,500 from Wayne Enterprises. Find their open invoice and record a manual payment against it for today's date."
Execution Sequence:
list_all_wave_businesses: Retrieves the context ID.list_all_wave_customers: (Assuming a custom tool list or search mechanism) Claude locates the customer ID for "Wayne Enterprises".list_all_wave_invoices: Claude queries the open invoices for that customer to find the one matching the $2,500 amount.create_a_wave_invoice_payment: Claude records the payment against the specificinvoiceId, supplying the amount, the payment date, and setting the method to 'Wire Transfer'.wave_invoices_send_payment_receipt: Claude optionally triggers the receipt email to the client.
Result: The invoice status in Wave updates to "Paid" and the general ledger reflects the deposited cash, all without a human opening the Wave dashboard.
Security and Access Control
Giving an LLM access to your company's accounting software requires stringent security. Truto provides several mechanisms to lock down your MCP servers at the configuration level, maintaining SOC-2 and GDPR compliant data processing:
- Method Filtering: You can enforce immutability by setting
methods: ["read"]during server generation. This guarantees Claude can only read data (like fetching a list of businesses or viewing a specific invoice) and is physically blocked from executing write operations likecreate,update, ordelete. - Tag Filtering: Limit the surface area of the LLM by passing specific tags. For example, you could restrict an agent to only have access to tools tagged with
inventoryorcustomers, completely hiding payroll and general ledger operations. - Require API Token Authentication: By default, the cryptographically secure MCP URL is sufficient to connect. For environments requiring defense-in-depth, setting
require_api_token_auth: trueforces the client to also pass a valid Truto API token in theAuthorizationheader. - Ephemeral Servers: Set an
expires_attimestamp when creating the server. Truto will automatically destroy the token and terminate access at the specified time, which is ideal for temporary agent run-times or contractor access.
Orchestrating Financial Data Safely
Building integrations for accounting systems is notoriously difficult. The schemas are highly nested, validation rules are strict, and GraphQL error structures often confuse natural language models. Hand-coding an MCP server to translate LLM intent into valid Wave API requests is a massive drain on engineering resources.
By utilizing a managed platform, you eliminate the integration maintenance burden. Truto handles the schema normalization, token management, and protocol formatting out of the box, allowing your AI agents to securely query ledgers, draft estimates, and orchestrate billing cycles immediately.
FAQ
- How does Truto handle Wave API rate limits during Claude tool calls?
- Truto does not retry, throttle, or apply backoff on rate limit errors. If Wave returns an HTTP 429 Too Many Requests, Truto passes that error directly to the caller. Truto normalizes the upstream rate limit information into standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). The client orchestrating Claude is responsible for implementing retry and exponential backoff logic.
- Does Claude need to understand GraphQL to interact with Wave through Truto?
- No. Truto abstracts Wave's GraphQL mutations and queries into standard REST-like MCP tools. Claude only needs to pass JSON arguments based on the tool's JSON Schema. Truto handles the translation layer.
- Can I restrict Claude from creating or deleting financial records in Wave?
- Yes. When generating the MCP server, you can apply method filtering. By setting the methods array to ["read"], Claude will only have access to "get" and "list" operations, completely blocking write operations like creating invoices or deleting accounts.