wave-mcp-server
Summary: An unofficial MCP server that lets an MCP client read and write Wave invoicing data for one pinned business, with irreversible actions behind a preview-then-confirm step.
Read business details (
wave_get_business), customers, invoices, products, sales taxes and chart-of-accounts entries — with filters (name/email, status, customer, currency, date range, invoice number) and pagination.Inspect invoices in full: line items, taxes, payments, totals, amount due, PDF and customer-view URLs.
Create/update customers and create products/services (price, income account, default taxes).
Create and edit draft invoices only (line items, taxes, dates, currency, exchange rate, memo, PO number); updates refuse non-drafts.
Gated actions (first call returns a preview + fingerprint, acts only on a repeated call with
confirm: trueand that fingerprint, refusing if the invoice changed): approve a draft invoice, email an invoice to given recipients, mark an invoice sent, record an already-received payment against an approved invoice.Not possible: deleting anything, editing payments, estimates or expenses; no tool accepts a business id — everything is scoped to
WAVE_BUSINESS_ID, and the server only talks to Wave's public GraphQL API.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@wave-mcp-serverlist my recent invoices"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
wave-mcp-server
An MCP server that lets Claude (or any MCP client) work with Wave invoicing for one business: look up customers and invoices, create customers and draft invoices, and approve, send and record payments behind a preview-then-confirm step.
Unofficial. This project is not affiliated with, endorsed by or supported by Wave Financial. It uses Wave's public GraphQL API with a token you create yourself.
Requirements
Node.js 22 or later
A Wave account and a Full Access Token from the Wave developer portal
Related MCP server: Wave MCP Server
Setup
Create a test business in Wave (Wave recommends this as a sandbox) and add a customer, a product and a sales tax to it. Point the server at it until you trust the setup.
Create an application and token: in the Wave developer portal go to Manage Applications, create an application, then Create token. The token can see every business in your Wave account; treat it like a password.
Find your business id:
WAVE_ACCESS_TOKEN=your-token npx -y @sdnly/wave-mcp-server --list-businessesRegister with Claude Code:
claude mcp add wave \ -e WAVE_ACCESS_TOKEN=your-token \ -e WAVE_BUSINESS_ID=your-business-id \ -- npx -y @sdnly/wave-mcp-serverFor Claude Desktop or another client, add the same command and environment variables to its MCP config:
{ "mcpServers": { "wave": { "command": "npx", "args": ["-y", "@sdnly/wave-mcp-server"], "env": { "WAVE_ACCESS_TOKEN": "your-token", "WAVE_BUSINESS_ID": "your-business-id" } } } }Ask Claude to run
wave_get_businessto confirm the connection.
To switch from the test business to the real one, change WAVE_BUSINESS_ID and restart your
client.
Running from a clone
If you would rather not use npx, or want to keep the token out of your client's config:
git clone https://github.com/yoyodyne7/wave-mcp-server.git && cd wave-mcp-server
npm install && npm run build
cp .env.example .env && chmod 600 .env # paste the token and business id into .env
node dist/index.js --list-businesses
claude mcp add wave -- node "$(pwd)/dist/index.js"The server reads .env from the folder above dist/. If a value is set both there and in the
environment with different contents, it refuses to start rather than guess which one you meant.
Tools
Kind | Tools |
Read |
|
Write |
|
Gated |
|
Gated tools return a preview and a fingerprint on the first call and do nothing. They act only
when called again with confirm: true and that fingerprint, and refuse if the invoice changed
in between.
There are no delete tools. Deletions, payment edits, estimates and expenses stay in Wave.
Security and privacy
Read this before pointing the server at real books.
The token is a master key. A Wave Full Access Token can read and change every business in your Wave account, not just the one in
WAVE_BUSINESS_ID, and it lasts for years. The one-business limit is enforced by this server, not by Wave; anything else that gets hold of the token has no such limit. Where the token lives:With
claude mcp add -eor a Desktop config, it is stored in plain text in that client's config file (for Claude Code,~/.claude.json).With a clone, it is in
.env. Keep that filechmod 600and out of git.
Either way, any program running as your user can read it. If your computer is lost or compromised, revoke the token in the Wave developer portal (Manage Applications) first.
Your Wave data goes to your AI provider. Everything a tool returns (customer names, emails, addresses, invoice amounts) becomes part of the conversation and is sent to whichever model your client uses. Check that this fits your privacy obligations to your own customers.
Your approval is the safety net. Text the assistant reads elsewhere in a session (an email, a web page, a document) can try to instruct it to create, approve or send invoices. Keep every write and gated tool on "ask every time", and read the preview before approving a gated call. The preview step proves a preview was requested, not that you read it. If you allow-list tools to cut down prompts, allow-list only the eight read tools, never
mcp__wave__*as a whole.Pin the version.
npx -y @sdnly/wave-mcp-serverruns the newest published release. For books you care about, pin one you have reviewed, e.g.npx -y @sdnly/wave-mcp-server@0.1.1, or run from a clone.The server talks only to Wave's API (
https://gql.waveapps.com/graphql/public) over HTTPS. It sends no telemetry and writes nothing to disk, and it strips the token from error messages.
Usage notes
The server acts only on
WAVE_BUSINESS_ID. No tool accepts a business id.Writes are never retried. If a write times out, check the invoice in Wave before retrying.
Tax on invoice lines: omit
sales_tax_idsto use the product's default taxes; pass[]for no tax (zero-rated or export clients).On "Wave rejected the access token", create a new token and update your configuration.
Status
Tested against a Wave test business. wave_send_invoice (Wave emails the invoice to the
customer) has not yet been verified against a live send; treat it as experimental and try it
on a test business first.
Development
npm test # unit and contract tests (no network)
npm run build # compile to dist/Wave's schema is unversioned. If a tool starts returning "Wave rejected the request shape",
compare the query in src/queries/ with the API Reference in the developer portal.
License
MIT. See LICENSE. Provided as is, without warranty: you are responsible for what it does in your Wave account.
Available Tools
17 toolswave_approve_invoiceApprove Wave invoiceADestructive
Approve a DRAFT invoice, which posts it to the books and makes it sendable. It does not email anyone. This is a two-step tool: the first call (confirm omitted) returns a preview and a fingerprint and changes nothing. Show the preview to the user. Only after they agree, call again with confirm: true and the fingerprint.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No | Leave false to get a preview (nothing happens). Set true only after the user has seen the preview and agreed, and pass the preview's fingerprint. | |
| invoice_id | Yes | Invoice ID exactly as returned by Wave (an opaque string) | |
| fingerprint | No | The fingerprint returned by the preview call; required with confirm: true |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| invoice | No | |
| message | Yes | |
| preview | No | |
| fingerprint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing the real side effect (posts the invoice to the books), the explicit non-behavior (does not email), and the safety contract that the preview call changes nothing and must be confirmed via fingerprint. This is exactly the mutating-operation context an agent needs when destructiveHint=true and idempotentHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the verb and effect in the first sentence, then layers the non-effect, the two-step mechanics, and the user-agreement gate. Every sentence earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, non-idempotent mutation with an output schema and full param coverage, the description supplies the prerequisite (draft state), the workflow, the human-in-the-loop gate, and the fingerprint handoff. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents confirm, invoice_id, and fingerprint thoroughly. The description reinforces how confirm and fingerprint interlock with the preview step but adds little syntax beyond the schema, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Approve) and resource (a DRAFT invoice) and enumerates the concrete effect: posts to the books and makes it sendable. The clause 'It does not email anyone' carves out a clear boundary against the send-family siblings, so an agent can distinguish it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use guidance for the internal two-step flow: first call without confirm yields a preview, and the second call with confirm: true is only appropriate after the user agrees. It implies but never names the alternative send tools, so it falls just short of the when/when-not/alternatives bar for a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_create_customerCreate Wave customerA
Create a customer in the pinned Wave business. Check wave_list_customers first to avoid duplicates. Set currency for clients billed in a currency other than the business default (e.g. USD for US clients).
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Customer or company name | |
| No | Email of the main contact; invoices are sent here | ||
| phone | No | ||
| address | No | ||
| currency | No | Default currency for this customer's invoices | |
| last_name | No | Last name of the main contact | |
| first_name | No | First name of the main contact | |
| internal_notes | No | Notes visible only inside Wave |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| Yes | ||
| phone | Yes | |
| address | Yes | |
| overdue | Yes | |
| currency | Yes | |
| last_name | Yes | |
| first_name | Yes | |
| is_archived | Yes | |
| outstanding | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safe-write profile (readOnly=false, destructive=false, idempotent=false, openWorld=true), so the bar is lower. The description still adds real context beyond them: the write targets the pinned business, duplicate creation is a live risk, and currency overrides business defaults. It does not say what happens if a duplicate is actually submitted, which is the remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero filler, front-loaded with the action and scope before the operational caveats. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, and the description covers the two operational hazards an agent would realistically hit (duplicates, currency). Adequate for an 8-param create tool with nested address objects and one required field.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so the schema carries most parameter meaning already. The description enriches only `currency` (use it for clients billed outside the business default, e.g. USD for US clients); email, phone, address, first_name/last_name and internal_notes are left entirely to the schema. Above-baseline but narrow.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Create a customer') and scopes it to the pinned Wave business, which distinguishes it from wave_update_customer, wave_get_customer, and wave_list_customers. An agent can select it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete pre-call guidance: check wave_list_customers first to avoid duplicates, and set currency when the client is billed in a non-default currency. Names the sibling to consult, but does not state when NOT to use this tool (e.g. prefer wave_update_customer for existing records).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_create_invoiceCreate draft Wave invoiceA
Create a DRAFT invoice. Nothing is sent and nothing is posted to the books until wave_approve_invoice and wave_send_invoice. Needs a customer id (wave_list_customers) and at least one line item with a product id (wave_list_products). Tax per line: omit sales_tax_ids to use the product's defaults, or pass [] for no tax (zero-rated US/export clients).
| Name | Required | Description | Default |
|---|---|---|---|
| memo | No | Notes shown on the invoice | |
| items | Yes | Line items; at least one | |
| title | No | ||
| footer | No | ||
| currency | No | Invoice currency (default: business currency) | |
| due_date | No | Due date (default: business payment terms) | |
| po_number | No | ||
| customer_id | Yes | Customer ID exactly as returned by Wave (an opaque string) | |
| invoice_date | No | Issue date (default: today) | |
| exchange_rate | No | Rate from the invoice currency to the business currency; set it for foreign-currency invoices | |
| invoice_number | No | Default: Wave assigns the next number |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| memo | Yes | |
| items | Yes | |
| title | Yes | |
| total | Yes | |
| footer | Yes | |
| status | Yes | |
| pdf_url | Yes | |
| currency | Yes | |
| due_date | Yes | |
| payments | Yes | |
| view_url | Yes | |
| po_number | Yes | |
| tax_total | Yes | |
| amount_due | Yes | |
| amount_paid | Yes | |
| customer_id | Yes | |
| modified_at | Yes | |
| invoice_date | Yes | |
| customer_name | Yes | |
| exchange_rate | Yes | |
| customer_email | Yes | |
| invoice_number | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only establish that this is a non-read-only, non-destructive, non-idempotent, open-world write. The description adds real behavioral context beyond that: the record is created in DRAFT state and neither sent nor posted to the books until approve/send. It does not mention auth/permission requirements or what happens on duplicate invoice numbers, so it stops short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, front-loaded with the draft-state constraint, then prerequisites, then the riskiest parameter semantics. No filler and nothing repeated for its own sake.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter, 2-required creation tool with an output schema available, the description covers everything an agent needs to call it correctly: what it creates, the required inputs, where to get the ids, and the one parameter whose default behavior is easy to get wrong. Return values are left to the output schema, as intended.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema coverage at 73%, the schema already documents most parameters, and the tax rule (omit sales_tax_ids for product defaults, pass [] for zero-rated) is largely restated from the schema. The description still adds value by tying the id parameters to their source tools (wave_list_customers, wave_list_products, wave_list_sales_taxes) and by surfacing the tax trap prominently rather than burying it in a nested schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (create a DRAFT invoice) and immediately bounds the scope: 'Nothing is sent and nothing is posted to the books.' This cleanly distinguishes it from the sibling wave_approve_invoice and wave_send_invoice, which it names.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit preconditions ('Needs a customer id... and at least one line item with a product id') and routes the agent to the lookup siblings wave_list_customers and wave_list_products. The draft/approve/send sequencing makes the boundary between this tool and its alternatives unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_create_productCreate Wave product or serviceA
Create a product/service that can be used on invoice line items. Check wave_list_products first. income_account_id must be an account of subtype INCOME, DISCOUNTS or OTHER_INCOME.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| unit_price | Yes | Default price per unit as a decimal string, e.g. "5000.00" | |
| description | No | ||
| income_account_id | No | Income account ID exactly as returned by Wave (an opaque string) | |
| default_sales_tax_ids | No | Taxes applied by default on invoices |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| unit_price | Yes | |
| description | Yes | |
| income_account_id | Yes | |
| default_sales_taxes | Yes | |
| income_account_name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-readonly, open-world, non-idempotent creation operation. The description adds the critical constraint that income_account_id must be an INCOME, DISCOUNTS, or OTHER_INCOME account, which is valuable validation context beyond the schema. It does not cover permissions, side effects, or error conditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, each earning its place: purpose, pre-check, and a critical parameter constraint. Front-loaded and waste-free.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the mutation annotations, an output schema, and 60% schema coverage, the description equips an agent to call the tool correctly. It could mention the pre-check's purpose more explicitly or note that unit_price format is schema-documented, but it is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 60%, so the description compensates by clarifying the subtype constraint on income_account_id, which the schema only calls an 'opaque string'. This is meaningful added semantics, though it could say more about default_sales_tax_ids and name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Create) and resource (product/service usable on invoice line items), which distinguishes it from siblings like wave_create_invoice and wave_create_customer. The purpose is immediately clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs to check wave_list_products first, which is a concrete usage guideline. However, it does not state when not to create or describe alternative approaches, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_get_businessGet Wave businessARead-onlyIdempotent
Show the Wave business this server is pinned to: name, default currency, timezone and whether Wave email sending is enabled. Use it to check the connection before other tools. All wave_* tools act on this one business only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| currency | Yes | |
| timezone | Yes | |
| is_personal | Yes | |
| email_send_enabled | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds genuinely useful scope context that annotations cannot express: this tool reads a single pinned business and every other wave_* tool acts on that same business, which shapes how an agent should interpret results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with zero filler, front-loading the resource and its returned fields before the usage and scope notes. Every sentence carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value structure need not be re-explained, and the description still summarizes the salient fields. Combined with the explicit scope constraint and pre-flight usage hint, nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters and the schema is empty, so there is nothing to misinterpret; no parameter documentation is required. Baseline for a 0-param tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Show the Wave business this server is pinned to') and enumerates exactly what it returns: name, default currency, timezone, and email-sending status. It also differentiates itself from every sibling by declaring that all wave_* tools operate on this one business.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use it to check the connection before other tools' gives an explicit when-to-use and effectively positions it as the entry point for the wave_* family. There is no when-not guidance or named alternative, but for a zero-param introspection tool the routing intent is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_get_customerGet Wave customerARead-onlyIdempotent
Get one customer by id, including address, default currency and outstanding/overdue amounts.
| Name | Required | Description | Default |
|---|---|---|---|
| customer_id | Yes | Customer ID exactly as returned by Wave (an opaque string) |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| Yes | ||
| phone | Yes | |
| address | Yes | |
| overdue | Yes | |
| currency | Yes | |
| last_name | Yes | |
| first_name | Yes | |
| is_archived | Yes | |
| outstanding | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is fully covered structurally. The description's contribution is the payload summary (address, default currency, outstanding/overdue amounts), which does hint that this is a read with computed financials rather than a raw record fetch. It adds little beyond annotations plus the output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence with zero filler; the resource and the identifying parameter lead, and the payload detail trails. Nothing to trim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and rich annotations, the description need not spell out return values or safety behavior, and the single parameter is fully documented in the schema. The only real gap is behavior on a missing/invalid customer id, which is minor for a read-only lookup.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter is described as 'an opaque string exactly as returned by Wave'. The description's 'by id' only restates that; it adds no format, sourcing, or error semantics beyond the schema. Baseline 3 for a fully documented single-parameter schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Get one customer by id') that distinguishes a single-record fetch from the sibling wave_list_customers by using 'one'. It also names the salient payload fields (address, currency, outstanding/overdue), so an agent knows the shape of what it gets without opening the schema. It does not explicitly name the list sibling as an alternative, which keeps it out of 5 territory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'by id' — the tool applies when a customer ID is already known — but there is no explicit statement of when to prefer this over wave_list_customers or the wave_update_customer/get_invoice siblings, and no mention of what happens for an unknown ID. Adequate but inferential.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_get_invoiceGet Wave invoiceARead-onlyIdempotent
Get one invoice with line items, taxes, payments, totals, amount due and the PDF and customer-view URLs.
| Name | Required | Description | Default |
|---|---|---|---|
| invoice_id | Yes | Invoice ID exactly as returned by Wave (an opaque string) |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| memo | Yes | |
| items | Yes | |
| title | Yes | |
| total | Yes | |
| footer | Yes | |
| status | Yes | |
| pdf_url | Yes | |
| currency | Yes | |
| due_date | Yes | |
| payments | Yes | |
| view_url | Yes | |
| po_number | Yes | |
| tax_total | Yes | |
| amount_due | Yes | |
| amount_paid | Yes | |
| customer_id | Yes | |
| modified_at | Yes | |
| invoice_date | Yes | |
| customer_name | Yes | |
| exchange_rate | Yes | |
| customer_email | Yes | |
| invoice_number | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is fully covered. The description adds the list of returned artifacts (payment history, URLs), which is modest added context, but says nothing about failure behavior for an unknown ID or about access scope. Adequate against the lower bar set by annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. However, it spends its length enumerating return fields that the existing output schema already documents, which is slightly redundant rather than wasteful enough to drop below 4.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values, and with 100% schema coverage on the single required parameter, the call mechanics are clear. It falls short of 5 only because it omits error/not-found behavior and any access-scope caveats.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the sole parameter is documented as an opaque string returned by Wave, so the schema already carries the semantics. The description adds no parameter-level detail beyond what the schema provides, making the baseline 3 correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('Get one invoice') and enumerates the returned contents (line items, taxes, payments, totals, amount due, PDF and customer-view URLs), which distinguishes it cleanly from the sibling wave_list_invoices. An agent can tell this is single-invoice retrieval without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no prerequisites, and no mention of alternatives such as wave_list_invoices for browsing or wave_update_invoice for modification. The description only states what is returned, leaving tool selection to inference from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_list_accountsList Wave accountsARead-onlyIdempotent
List chart-of-accounts entries (unarchived). Filter by types and/or subtypes. For the deposit account in wave_record_payment use subtypes ["CASH_AND_BANK"]. For a product's income account use subtypes ["INCOME"].
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 1-based page number (default 1) | |
| types | No | ||
| subtypes | No | ||
| page_size | No | Items per page (default 25, max 100) |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| items | Yes | |
| has_more | Yes | |
| page_size | Yes | |
| total_count | Yes | |
| total_pages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already disclose read-only, idempotent, non-destructive, open-world behavior, so the bar is lower. The description still adds real behavioral value by revealing that archived accounts are silently excluded via the 'unarchived' qualifier — a scope constraint the annotations do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the resource and scope, then filter mechanics, then practical examples. No filler and every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering the safety profile and an output schema covering return shape, the description only needs to cover purpose and filtering, which it does well. Only minor gaps remain: no hint about pagination relevance or the allowed 'types' vocabulary.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% (only page and page_size are documented), so the description must compensate for types/subtypes. It does so by explaining the filter semantics and giving concrete subtype values (CASH_AND_BANK, INCOME), though it never explains the ASSET/EQUITY/EXPENSE/INCOME/LIABILITY type enum or the subtype naming pattern.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and resource (chart-of-accounts entries) with a scope qualifier (unarchived). This clearly distinguishes it from its siblings (customers, products, invoices, payments), which it also references by name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete usage context by prescribing exact subtypes for two workflows (deposit account in wave_record_payment, income account for products), which tells the agent when and how to apply this tool. It stops short of stating when to use an alternative tool or when filtering is unnecessary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_list_customersList Wave customersARead-onlyIdempotent
List customers of the pinned Wave business, sorted by name. Filter by exact email, or by name (case-insensitive contains; searches up to 500 customers and sets scan_truncated if there are more). Returns id, contact details, default currency and outstanding/overdue amounts. Use the id with wave_create_invoice or wave_list_invoices.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Part of the customer name, e.g. "acme" | |
| page | No | 1-based page number (default 1) | |
| No | Exact email address to match | ||
| page_size | No | Items per page (default 25, max 100) |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| items | Yes | |
| has_more | Yes | |
| page_size | Yes | |
| total_count | Yes | |
| total_pages | Yes | |
| scan_truncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safe, idempotent read profile, and the description goes beyond them by disclosing the case-insensitive 'contains' semantics, the 500-customer scan ceiling, and the scan_truncated signal. It also names the returned fields, which is useful though partly redundant with the output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: purpose, filter semantics, and downstream usage. The most decision-relevant facts (name ordering, filter behavior) are front-loaded with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-shape explanation is optional, yet the description summarizes the key fields. With annotations covering safety and the schema covering paging, nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so email/page/page_size are already documented; the description adds the exact-vs-contains nuance and the scan limit for `name`. It says nothing about paging parameters, but the schema carries that load, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('List customers'), scopes it ('of the pinned Wave business, sorted by name'), and enumerates the filter dimensions. It is clearly distinguishable from wave_get_customer (single fetch) and wave_create_customer by its list semantics and paging.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides concrete routing guidance for the result ('Use the id with wave_create_invoice or wave_list_invoices') and explains how each filter behaves. It stops short of explicitly contrasting when to prefer this over wave_get_customer or the other list_* tools, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_list_invoicesList Wave invoicesARead-onlyIdempotent
List invoices of the pinned Wave business, newest invoice date first. Filter by status, customer, currency, invoice date range or invoice number (contains match). Returns summaries; use wave_get_invoice for line items and payments. For accounts receivable, list status OVERDUE or UNPAID.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 1-based page number (default 1) | |
| status | No | SAVED means approved but not yet sent | |
| currency | No | ||
| page_size | No | Items per page (default 25, max 100) | |
| customer_id | No | Customer ID exactly as returned by Wave (an opaque string) | |
| invoice_number | No | Contains match: "12" also finds 112 and 120 | |
| invoice_date_end | No | Invoices dated on or before this date | |
| invoice_date_start | No | Invoices dated on or after this date |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| items | Yes | |
| has_more | Yes | |
| page_size | Yes | |
| total_count | Yes | |
| total_pages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and open-world, so safety is covered. The description adds genuinely new behavior: the result ordering, the fact that only summaries come back rather than full invoice detail, and that scope is the pinned business. It does not mention pagination limits or default page size, which are left to the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four compact sentences with zero filler: scope and ordering first, then filters, then return shape and the sibling pointer, then the AR tip. Every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-field detail is not required, and annotations cover the safety profile. The description adds the return-shape summary and the get-invoice routing, leaving nothing essential missing for a filtered list operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 88%, so the schema already documents formats, defaults, and the invoice_number contains-match rule. The description restates the filter set (status, customer, currency, date range, invoice number) and adds the OVERDUE/UNPAID pairing, which is closer to usage guidance than parameter semantics. Baseline 3 is appropriate since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (list invoices) plus scope (the pinned Wave business) and a defined ordering (newest invoice date first). It explicitly distinguishes itself from the sibling wave_get_invoice, so an agent can choose between them without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing ("use wave_get_invoice for line items and payments") and a concrete when-to-use case ("For accounts receivable, list status OVERDUE or UNPAID"). Both the alternative and the selecting condition are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_list_productsList Wave products and servicesARead-onlyIdempotent
List the products/services the business sells (unarchived), sorted by name. Each invoice line item needs a product id from here. Shows unit price, income account and default sales taxes.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 1-based page number (default 1) | |
| page_size | No | Items per page (default 25, max 100) |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| items | Yes | |
| has_more | Yes | |
| page_size | Yes | |
| total_count | Yes | |
| total_pages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds real behavioral context beyond that: only unarchived products are returned, results are name-sorted, and each record surfaces unit price, income account, and default sales taxes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with what the tool returns, followed by the motivating use case and the fields exposed. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value detail is not needed here. For a simple read-only list tool with two well-documented params, the description covers scope, ordering, use case, and notable fields — nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both pagination parameters are fully documented in the schema (defaults, min, max). The description adds no pagination or ordering-parameter guidance, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the products/services the business sells') plus an explicit scope qualifier ('unarchived') and ordering ('sorted by name'). This clearly separates it from siblings like wave_list_customers, wave_list_invoices, and wave_create_product.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete use case: 'Each invoice line item needs a product id from here,' telling the agent when to reach for this tool during invoice creation. It does not explicitly name alternative tools or when-not to use it, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_list_sales_taxesList Wave sales taxesARead-onlyIdempotent
List the business's sales taxes (e.g. HST) with ids and current rates. Use the ids in wave_create_invoice line items (sales_tax_ids).
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 1-based page number (default 1) | |
| page_size | No | Items per page (default 25, max 100) |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| items | Yes | |
| has_more | Yes | |
| page_size | Yes | |
| total_count | Yes | |
| total_pages | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is fully covered. The description adds only that results carry ids and current rates — useful but thin, and the output schema already exists to describe return shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the resource and returned fields front-loaded and the actionable integration hint appended. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple paginated read tool with full annotation coverage, a 100%-documented 2-param schema and an output schema, the description supplies everything the agent still needs: what is listed and where the ids are consumed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: both `page` and `page_size` carry defaults, bounds and descriptions in the schema. The description adds no parameter-level meaning, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (the business's sales taxes) plus the returned content (ids and current rates). No sibling tool covers sales taxes, so an agent can uniquely identify this tool from the sibling list without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to use the returned ids in wave_create_invoice line items (`sales_tax_ids`), which tells the agent the downstream context for calling this tool. There is no when-not guidance or named alternative, but none is needed since no sibling overlaps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_mark_invoice_sentMark Wave invoice as sentADestructive
Record that an approved invoice was sent outside Wave (e.g. from your own email). Wave emails no one. This is a two-step tool: the first call (confirm omitted) returns a preview and a fingerprint and changes nothing. Show the preview to the user. Only after they agree, call again with confirm: true and the fingerprint.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No | Leave false to get a preview (nothing happens). Set true only after the user has seen the preview and agreed, and pass the preview's fingerprint. | |
| invoice_id | Yes | Invoice ID exactly as returned by Wave (an opaque string) | |
| fingerprint | No | The fingerprint returned by the preview call; required with confirm: true | |
| send_method | No | How it was sent (default MARKED_SENT) | MARKED_SENT |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| invoice | No | |
| message | Yes | |
| preview | No | |
| fingerprint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the mutation flags (readOnlyHint=false, destructiveHint=true, idempotentHint=false), and the description goes well beyond them: it discloses that Wave sends no email, that the first call 'changes nothing' and only returns a preview plus fingerprint, and that the confirmation call requires the fingerprint. That is exactly the safety-relevant context an agent needs before mutating.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the purpose, then the constraint, then the operational sequence. Every sentence carries distinct information with no repetition of the title or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, non-idempotent mutation with an output schema and full annotation coverage, the description supplies the workflow and safety narrative. It does not spell out the resulting invoice state after confirmation, but that is a minor gap given the output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3. The description adds meaning the schema does not: confirm is not just a boolean but the second half of a preview-then-confirm handshake, and fingerprint is only valid when paired with confirm: true. send_method remains schema-only, which is acceptable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Record that an approved invoice was sent outside Wave') and immediately scopes it against the sibling wave_send_invoice with 'Wave emails no one.' An agent can distinguish this bookkeeping tool from the actual-sending tool without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly gives the condition for use ('an approved invoice was sent outside Wave (e.g. from your own email)') and lays out the two-step call sequence in order. It stops short of naming wave_send_invoice as the alternative for actually emailing, relying on the implicit contrast instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_record_paymentRecord payment on Wave invoiceADestructive
Record a payment the business has ALREADY received against an approved invoice. This changes the books; it does not move money. amount is in the invoice's currency and may not exceed the amount due. payment_account_id is the account the money landed in: wave_list_accounts with subtypes ["CASH_AND_BANK"]. This is a two-step tool: the first call (confirm omitted) returns a preview and a fingerprint and changes nothing. Show the preview to the user. Only after they agree, call again with confirm: true and the fingerprint.
| Name | Required | Description | Default |
|---|---|---|---|
| memo | No | Internal note on the payment | |
| amount | Yes | Amount received, in the invoice currency, e.g. "1130.00" | |
| confirm | No | Leave false to get a preview (nothing happens). Set true only after the user has seen the preview and agreed, and pass the preview's fingerprint. | |
| invoice_id | Yes | Invoice ID exactly as returned by Wave (an opaque string) | |
| fingerprint | No | The fingerprint returned by the preview call; required with confirm: true | |
| payment_date | Yes | Date the payment was actually received (YYYY-MM-DD) | |
| exchange_rate | No | Rate from the invoice currency to the deposit account's currency. Omit when they match. REQUIRED when they differ (e.g. a USD invoice paid into a CAD account); never guess it, ask the user. | |
| payment_method | Yes | How it was paid; e-transfers are BANK_TRANSFER | |
| payment_account_id | Yes | Deposit account ID exactly as returned by Wave (an opaque string) |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| invoice | No | |
| message | Yes | |
| preview | No | |
| fingerprint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=false, and the description adds substantial context beyond them: the pass is book-only with no fund movement, the amount may not exceed the amount due, the first call changes nothing and returns a preview/fingerprint, and the second call requires explicit user approval. That is exactly the mutation-safety detail annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the one-line purpose, then the safety distinction, then parameter constraints, then the two-step protocol. Every clause carries operational weight; nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, non-idempotent 9-parameter mutation with an output schema, the description covers the prerequisites, the confirmation workflow, and the currency/account constraints an agent must get right. Return-value explanation is correctly left to the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes further: it constrains amount to the invoice currency and caps it at the amount due, explains that payment_account_id is the deposit account and how to find one, and narrates the confirm/fingerprint pairing. It does not restate, only adds.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb and resource — recording an already-received payment against an approved invoice — and immediately scopes it with 'this changes the books; it does not move money,' which separates it from any money-transfer sibling. An agent can identify the tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Specifies the triggering condition (payment ALREADY received, invoice must be approved), the two-step invocation protocol (preview first, confirm + fingerprint only after user agreement), and names a concrete alternative for the dependent lookup (wave_list_accounts with subtypes ["CASH_AND_BANK"]). Nothing about when or how to call it is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_send_invoiceEmail Wave invoice to clientADestructive
Have Wave EMAIL an approved invoice to the given addresses. This reaches a real client and cannot be unsent. The preview shows recipients, subject, totals and tax, and whether a recipient matches the customer's email on file. This is a two-step tool: the first call (confirm omitted) returns a preview and a fingerprint and changes nothing. Show the preview to the user. Only after they agree, call again with confirm: true and the fingerprint.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Recipient email addresses | |
| confirm | No | Leave false to get a preview (nothing happens). Set true only after the user has seen the preview and agreed, and pass the preview's fingerprint. | |
| message | No | Email body text (default: Wave's standard message) | |
| subject | No | Email subject (default: Wave's standard subject) | |
| cc_myself | No | Send a copy to the Wave account owner (default false) | |
| attach_pdf | No | Attach the invoice PDF (default true) | |
| invoice_id | Yes | Invoice ID exactly as returned by Wave (an opaque string) | |
| fingerprint | No | The fingerprint returned by the preview call; required with confirm: true |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| invoice | No | |
| message | Yes | |
| preview | No | |
| fingerprint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive/openWorld/non-idempotent, and the description adds the consequences in plain terms: it reaches a real client and cannot be unsent, and it enumerates what the preview surfaces (recipients, subject, totals, tax, customer-email match).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The irreversibility warning is front-loaded, followed by preview contents and then the two-step mechanics. Every sentence carries distinct, actionable information with no repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value documentation is not needed, and the description supplies the operational context (preview contents, fingerprint handshake, confirmation gate) that makes a destructive, irreversible email tool safe to invoke.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by tying confirm and fingerprint together into a two-step safety gate and explaining what the preview returns before confirmation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Have Wave EMAIL an approved invoice to the given addresses'), and the scope ('approved invoice') separates it from siblings like wave_mark_invoice_sent or wave_create_invoice.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Lays out an explicit when/when-not protocol: first call with confirm omitted returns a preview and changes nothing, show it to the user, and only then call again with confirm: true plus the fingerprint. The agent knows exactly which call to make at which point.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_update_customerUpdate Wave customerB
Change fields on an existing customer. Only the fields you pass are changed.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| No | Email of the main contact; invoices are sent here | ||
| phone | No | ||
| address | No | ||
| currency | No | Default currency for this customer's invoices | |
| last_name | No | Last name of the main contact | |
| first_name | No | First name of the main contact | |
| customer_id | Yes | Customer ID exactly as returned by Wave (an opaque string) | |
| internal_notes | No | Notes visible only inside Wave |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| Yes | ||
| phone | Yes | |
| address | Yes | |
| overdue | Yes | |
| currency | Yes | |
| last_name | Yes | |
| first_name | Yes | |
| is_archived | Yes | |
| outstanding | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, and openWorldHint=true, so safety and idempotency are covered. The description adds useful partial-update semantics: 'Only the fields you pass are changed.' It does not describe auth needs, error behavior, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with purpose and immediately followed by the key partial-update behavior. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. For a 9-parameter nested update tool, the description supplies the essential contract—update an existing customer and change only passed fields—while annotations cover safety. Missing only secondary details like auth requirements or error behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67%, so many parameters are documented in the schema. The description clarifies that only passed fields are updated, which reinforces optionality, but it adds no individual parameter meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Change fields on an existing customer.' The word 'existing' distinguishes this from wave_create_customer, though no sibling tools are named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies use for existing customers but gives no explicit when-to-use guidance, no comparison to wave_create_customer or wave_get_customer, and no prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wave_update_invoiceUpdate draft Wave invoiceA
Change a DRAFT invoice. Only the fields you pass are changed, except items, which replaces ALL line items. Refuses invoices that are no longer drafts.
| Name | Required | Description | Default |
|---|---|---|---|
| memo | No | Notes shown on the invoice | |
| items | No | Replaces all existing line items | |
| title | No | ||
| footer | No | ||
| currency | No | Invoice currency (default: business currency) | |
| due_date | No | Due date (default: business payment terms) | |
| po_number | No | ||
| invoice_id | Yes | Invoice ID exactly as returned by Wave (an opaque string) | |
| customer_id | No | Customer ID exactly as returned by Wave (an opaque string) | |
| invoice_date | No | Issue date (default: today) | |
| exchange_rate | No | Rate from the invoice currency to the business currency; set it for foreign-currency invoices |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| memo | Yes | |
| items | Yes | |
| title | Yes | |
| total | Yes | |
| footer | Yes | |
| status | Yes | |
| pdf_url | Yes | |
| currency | Yes | |
| due_date | Yes | |
| payments | Yes | |
| view_url | Yes | |
| po_number | Yes | |
| tax_total | Yes | |
| amount_due | Yes | |
| amount_paid | Yes | |
| customer_id | Yes | |
| modified_at | Yes | |
| invoice_date | Yes | |
| customer_name | Yes | |
| exchange_rate | Yes | |
| customer_email | Yes | |
| invoice_number | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false), so the bar is lower, yet the description still adds the important PATCH-style semantics (only passed fields change) and the notable exception that `items` replaces ALL line items, plus the draft-only refusal. It does not mention permissions/auth or currency side effects, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with zero filler, and the merge-vs-replace rule is front-loaded right after the draft-only constraint. Every clause carries operational meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and the mutation's core behavior and precondition are covered. Missing only auth/permission expectations and what the caller should do when the draft-only guard rejects the call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 73%, so the schema already documents most parameters (including the items replacement note, currency default, and exchange_rate guidance). The description adds the update-merge semantics usefully but names no parameters beyond `items`, so the baseline 3 for schema-driven documentation applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Change) and resource (DRAFT invoice) with an explicit scope restriction. It is immediately distinguishable from wave_create_invoice, wave_approve_invoice, and wave_send_invoice without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear precondition (only draft invoices; refuses non-drafts), which is the key gating condition for this tool. It stops short of routing the agent to a specific alternative for non-draft invoices (e.g., revert/approve flows) or pointing at wave_get_invoice for reads, so it is clear but not fully exclusionary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
17 tool updates
v0.1.0- First observed
wave_approve_invoice - First observed
wave_create_customer - First observed
wave_create_invoice - First observed
wave_create_product - First observed
wave_get_business - First observed
wave_get_customer - First observed
wave_get_invoice - First observed
wave_list_accounts - First observed
wave_list_customers - First observed
wave_list_invoices - First observed
wave_list_products - First observed
wave_list_sales_taxes - First observed
wave_mark_invoice_sent - First observed
wave_record_payment - First observed
wave_send_invoice - First observed
wave_update_customer - First observed
wave_update_invoice
TDQS
Scored across 17 tools
Each tool targets a distinct resource+action, and the descriptions carefully delineate the tricky invoice lifecycle tools (create vs approve vs send vs mark_sent) with explicit sequencing notes. An agent can reliably select the right tool for each step.
Every tool follows a strict wave_verb_noun snake_case pattern (wave_list_customers, wave_create_invoice, wave_record_payment), with no deviations in casing or verb style across the set.
17 tools is on the higher side but each covers a genuine entity/action across the customers, products, invoices, taxes, accounts and payments domain. It is well-scoped for a full invoicing lifecycle with only minor redundancy.
The invoice lifecycle is fully covered (create, update, approve, send, record payment), plus customers, products, taxes and accounts. Minor gaps exist: no customer delete/archive and no product update/get, but core workflows have no dead ends.
Maintenance
Related MCP Connectors
Read Invoiced customers, invoices, payments, subscriptions; create customers, draft invoices, notes.
Free hosted MCP for invoices, estimates, clients, items and PDFs. OAuth authorization required.
Manage Apollo invoices and customers with entity-scoped OAuth and optional read/write access.
Create and manage invoices and customers on Jupiter Invoice (MCP, API-key auth).
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceComprehensive MCP server for Wave Accounting, providing 45+ tools across invoicing, customers, products, transactions, bills, estimates, taxes, and financial reporting, plus 17 pre-built UI workflows.5-
- AlicenseAqualityDmaintenanceEnables Wave invoicing operations including listing invoices, retrieving details, and generating branded PDFs directly from AI assistants.512 npmISC
- AlicenseNot gradedqualityDmaintenanceProvides 54 tools across 10 categories for Wave Accounting, enabling invoicing, customer management, products, transactions, bills, estimates, taxes, businesses, and financial reporting through Wave's GraphQL API.9 npm1ISC
- FlicenseBqualityDmaintenanceA complete MCP server for Wave Accounting, providing comprehensive access to invoicing, customers, products, transactions, bills, estimates, taxes, and financial reporting.54-