Connect an AI client with a read-only key to inspect a company's QuickBooks records. Start with a question such as "Which invoices for Harbor Parts still have a balance?" The server lets the agent choose an end user, find the operation and read its input schema before making the call. If QuickBooks cannot answer, the result includes the request ID and actions for the person who can resolve the problem.
- Covers all 438 operations of API 1.0.0 through five compact tools, so it does not fill the agent's context.
- Writes carry an idempotency key and are never retried blindly. Read-only keys are enforced by the API itself.
- Runs over stdio with Node.js 20 or later on Windows, macOS and Linux, with no runtime dependencies.
The current version is 0.8.0. MCP guide · Documentation · Changelog · Status
Both expose the same tools and call the same API with your secret key:
| Hosted server | This package | |
|---|---|---|
| Address | https://mcp.desktopaccountingapi.com/ (Streamable HTTP) |
npx -y @desktopaccountingapi/quickbooks-desktop-mcp (stdio) |
| Install | Nothing | Node.js 20 or later |
| Secret key | Authorization: Bearer sk_... header |
DAAPI_SECRET_KEY environment variable |
| Use it when | Your client supports remote servers with a header | Your client runs only local servers, or you prefer a local process |
- Create a secret key in the dashboard under API keys. Use a separate key per person or tool, so you can revoke one without affecting the rest. For tools that should only look things up, choose Read-only (see Read-only access). Test projects issue
sk_test_...keys, production projectssk_live_...keys. - Connect at least one end user's QuickBooks Desktop company file. The Web Connector must be running on the connected Windows computer. QuickBooks can stay closed if the Admin granted access when QuickBooks is not running; otherwise leave the connected company file open. See How the Web Connector opens QuickBooks.
Replace sk_live_... below with your key. Keep it in your client's configuration only, never in shared documents, chat or a repository.
Create a read-only secret key in the dashboard and use it in the setup below. The API enforces it for every client: a read-only key can call GET operations, query-only passthrough and typed batches containing only reads. Any attempt to change data returns 403 API_KEY_READ_ONLY before anything reaches QuickBooks. The server recognizes a read-only key and hides write tools from the agent on its own. Add --read-only (or DAAPI_MCP_READ_ONLY=true) to hide them for a full-access key too; the read-only key is what guarantees writes cannot happen.
Confirm that write operations are absent from the tool list. A direct write with this key is refused by the API with API_KEY_READ_ONLY.
Ask the agent: "List my QuickBooks Desktop end users and show the 5 most recent invoices for the first one." If it returns real data from the company file, you are set up. The key is checked when the agent first requests data, so a "connected" indicator alone does not prove the key works.
For remote MCP clients, configure https://mcp.desktopaccountingapi.com/ and its Authorization: Bearer sk_live_... header. The hosted server needs no local process.
claude mcp add --transport http quickbooks-desktop https://mcp.desktopaccountingapi.com/ --header "Authorization: Bearer sk_live_..."Include --scope user to register this server for your user account across projects.
Cursor, VS Code and Codex HTTP configurations are in the MCP guide.
The package runs as a local process with DAAPI_SECRET_KEY.
Open Settings > Developer > Edit Config (claude_desktop_config.json) and add:
{
"mcpServers": {
"quickbooks-desktop": {
"command": "npx",
"args": ["-y", "@desktopaccountingapi/[email protected]"],
"env": { "DAAPI_SECRET_KEY": "sk_live_..." }
}
}
}Keep your existing server definitions. Insert a new quickbooks-desktop property under mcpServers, using the object shown above, then restart Claude Desktop to load the updated configuration. Drop @0.8.0 from the package name to always run the latest version.
claude mcp add quickbooks-desktop --env DAAPI_SECRET_KEY=sk_live_... -- npx -y @desktopaccountingapi/quickbooks-desktop-mcpIn ~/.cursor/mcp.json, or .cursor/mcp.json inside a project:
{
"mcpServers": {
"quickbooks-desktop": {
"command": "npx",
"args": ["-y", "@desktopaccountingapi/quickbooks-desktop-mcp"],
"env": { "DAAPI_SECRET_KEY": "sk_live_..." }
}
}
}Open the Command Palette and select MCP: Open User Configuration. For a project-specific setup, put the server definition in that project's .vscode/mcp.json. VS Code expects the definitions under servers.
{
"inputs": [{ "type": "promptString", "id": "daapi-key", "description": "Desktop Accounting API secret key", "password": true }],
"servers": {
"quickbooks-desktop": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@desktopaccountingapi/quickbooks-desktop-mcp"],
"env": { "DAAPI_SECRET_KEY": "${input:daapi-key}" }
}
}
}VS Code asks for the key once and stores it securely, so it never sits in the file.
Run npx -y @desktopaccountingapi/quickbooks-desktop-mcp with DAAPI_SECRET_KEY set in the process environment.
| Flag | Environment | Meaning |
|---|---|---|
DAAPI_SECRET_KEY |
Secret key (sk_live_... or sk_test_...). Required. |
|
--read-only |
DAAPI_MCP_READ_ONLY=true |
Hide and refuse operations that change data. |
--resources invoices,customers |
DAAPI_MCP_RESOURCES |
Also expose one tool per operation for these resources (all for every operation). |
--end-user-id eu_... |
DAAPI_END_USER_ID |
Default end user (company file) for QuickBooks operations. A tool call's end_user_id overrides it. |
--base-url <url> |
DAAPI_BASE_URL |
API origin. Default https://api.desktopaccountingapi.com. |
--version |
Print the version. | |
--help |
Print the options. |
We recommend a read-only secret key for AI tools. The API rejects every write made with it (403 API_KEY_READ_ONLY), whatever the client does, and the server detects such a key and hides write operations without --read-only. QuickBooks data in tool results is wrapped in <untrusted-data> with a note telling the model not to follow instructions found inside it.
| Tool | What it does |
|---|---|
list_end_users |
Your end users (one QuickBooks company file each), with connection status and QuickBooks company name. |
list_api_endpoints |
Searches the operations by resource, name, words or report type, for example "open invoices" or "profit and loss", and names the matching report types. |
get_api_endpoint_schema |
One operation's description and the JSON Schema of its arguments. |
invoke_api_endpoint |
Calls an operation and returns its JSON result. fields (dot paths such as ["id", "refNumber"]) trims each record. |
search_docs |
Searches the documentation, including the error codes. |
With --resources, each operation of those resources also becomes its own tool, such as qbd_invoices_list and qbd_invoices_create.
- By default the agent can read and write. The server instructs agents to describe each write and get your confirmation first.
- Every write carries an
Idempotency-Key, and the result shows it. Within the key's seven-day retention period, a completed or uncertain call is not sent again with the same key. After expiry, verify the earlier outcome before retrying old work. - Nothing is retried automatically. When a write's outcome is unknown, the result tells the agent not to resend it and how to check the request instead.
- Errors include the
userFacingMessageandfixesfrom the error catalog, so the agent can tell you what to do. - Every call appears in the dashboard's request log, like any other API call.
- Tool annotations come from the API contract (
x-daapi-effect,x-daapi-idempotent): deletes, voids, merges, passthrough, a company file identity reset and a secret rotation aredestructiveHint: true; creates, updates, custom field values and cleared status are not. Your MCP client decides how to use the hints; keep approval enabled for write tools.idempotentHintis true for reads and for writes that only set a state (disabling or enabling a connection, canceling a queued request, a transaction's cleared status).
- Confirm. List-record deletes, merges and custom field definition deletes need
confirm: true; transaction deletes and voids do not. For a delete it is a query argument at the top level ofargs; for a merge it is a field ofbody. Without it the server refuses the call before sending anything (and the API answers400 INVALID_PARAMETER). Boolean query arguments go out astrueorfalse; the strings"true"and"false"are accepted too. Ask the user before you set it. - What a list delete returns. QuickBooks Desktop can accept a delete of a list record (a customer, an item, a class) and keep the record, inactive and readable by its ID. The result says which:
deleted: trueonly when QuickBooks no longer returns the record; otherwisedeleted: falsewithdeactivatedandisActive. - Custom field values. The
*_set_custom_fieldoperations takebody.operation:updatewrites a value (use it for public fields, whether or not the record has one),addgives a record its first value of a private field,deleteclears the value on that record and keeps the field. - Owner IDs.
ownerId"0"is a public custom field, the kind people see in QuickBooks. A GUID is a private field owned by an application. A public definition can be assigned only to customers, vendors, employees and items, and cannot be deleted through the API. A custom field definition is addressed bydefinitionNamein the path (its current name), so it never clashes with thenamefield of a body. - Required arguments. Required path and query arguments (for example
definitionName,confirm,ownerIdon a definition delete) are checked before the call, and a missing one returns an error naming it.
handleMcpRequest(request, options) serves Streamable HTTP from any runtime with web-standard Request and Response, such as Cloudflare Workers, Deno or Bun:
import { buildCatalog, handleMcpRequest } from "@desktopaccountingapi/quickbooks-desktop-mcp";
// The tool catalog comes from the API's OpenAPI document, published with the documentation.
const spec = await (await fetch("https://www.desktopaccountingapi.com/docs/openapi.json")).json();
const catalog = buildCatalog(spec);
export default {
fetch: (request: Request): Promise<Response> =>
handleMcpRequest(request, { catalog, version: "1.0.0", apiBaseUrl: "https://api.desktopaccountingapi.com" }),
};Clients send their own secret key as Authorization: Bearer sk_...; the server passes it to the API unchanged. McpServer and Tools are exported for other transports.
- "No secret key reached the MCP server".
DAAPI_SECRET_KEY(or theAuthorizationheader for the hosted server) is missing or not passed through. - "The secret key ... is malformed". The key was cut off or mistyped. Copy it again from the dashboard.
API_KEY_INVALID. The key is unknown or was revoked. The message shows only the key's last four characters.- Requests fail with a QuickBooks error. QuickBooks must be open on the end user's computer and the Web Connector must be running. See troubleshooting.
- The package follows semantic versioning and is released together with the Node.js, Python, .NET and Java SDKs, with the same version number. Before 1.0, a minor version may contain breaking changes; they are marked Breaking in the CHANGELOG.
- It is generated from the Desktop Accounting API contract (sha256
149fc7b0599d...for this release) by the same pipeline as the SDKs. - Every release is listed in CHANGELOG.md and tagged
v<version>on GitHub.
- MCP guide, documentation and status page.
- Bugs and feature requests for this package: GitHub issues.
- Questions about your account, keys, billing or a connection: contact us. Never send your secret key.
- Security reports: use Report a vulnerability on this repository's Security tab.
mise install # pinned Node.js
mise run check # install, typecheck, build, tests with the official MCP client, README samples, smoke test, package contentsThis README is generated; mise run check parses its JSON configuration blocks and type-checks its TypeScript sample against the build.
MIT. See LICENSE.
QuickBooks is a registered trademark of Intuit Inc. Desktop Accounting API is an independent product and is not affiliated with, endorsed by, or approved by Intuit Inc.