# freshbooks-mcp [Health: Active]

**Category:** 💰 Finance & Fintech  
**Repository:** https://github.com/chrischall/freshbooks-mcp  
**GitHub Stars:** 0  
**npm Downloads (last month):** 2001  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/freshbooks-mcp

## Description
FreshBooks invoicing for Claude — invoices, clients, estimates, and payments

## Tools
Capabilities this server exposes over MCP:

- **freshbooks_auth_url** — Get the FreshBooks consent URL to authorize this connection. Open it, approve, and you'll land on the redirect URL — pass that whole URL to freshbooks_auth_exchange (its state parameter binds the approval to this server; valid 15 minutes, single-use). Read-only; contacts nothing.
- **freshbooks_auth_exchange** — Complete FreshBooks authorization. Local sessions save the credentials privately and return only status; hosted sessions return the refresh token to the host's credential-capture flow. Pass the whole redirect URL: its state must match a consent URL freshbooks_auth_url issued, so a bare code is refused. The code is SINGLE-USE — if this fails, authorize again rather than retrying it.
- **freshbooks_get_identity** — Resolve the authenticated FreshBooks user and their identifiers: accountId (alphanumeric, used by accounting and payments endpoints), businessId (integer, used by projects and time tracking) and businessUuid. The three are not interchangeable — using the wrong one returns a 404 rather than a useful error. When the identity belongs to several businesses, `businesses` lists them all; unless FRESHBOOKS_BUSINESS_ID picks one, writes are refused.
- **freshbooks_healthcheck** — Resolves the credential the way real tools do, then makes one authenticated request to api.freshbooks.com. Reports which source supplied the credential, whether api.freshbooks.com accepted it, the round-trip time, and a plain-English hint distinguishing 'no credential' from 'credential rejected' from 'a api.freshbooks.com-side problem'. Read-only; never returns the credential itself. Call this when a real tool fails and you want to know which hop broke.
- **freshbooks_list_invoices** — List invoices for the authenticated FreshBooks account. Supports pagination and raw FreshBooks filter params. Returns items plus page/pages/total.
- **freshbooks_get_invoice** — Get a single invoice by its numeric FreshBooks id.
- **freshbooks_list_clients** — List clients for the authenticated FreshBooks account. Supports pagination and raw FreshBooks filter params. Returns items plus page/pages/total.
- **freshbooks_get_client** — Get a single client by its numeric FreshBooks id.
- **freshbooks_list_estimates** — List estimates for the authenticated FreshBooks account. Supports pagination and raw FreshBooks filter params. Returns items plus page/pages/total.
- **freshbooks_get_estimate** — Get a single estimate by its numeric FreshBooks id.
- **freshbooks_list_payments** — List payments for the authenticated FreshBooks account. Supports pagination and raw FreshBooks filter params. Returns items plus page/pages/total.
- **freshbooks_get_payment** — Get a single payment by its numeric FreshBooks id.
- **freshbooks_list_items** — List items for the authenticated FreshBooks account. Supports pagination and raw FreshBooks filter params. Returns items plus page/pages/total.
- **freshbooks_get_item** — Get a single item by its numeric FreshBooks id.
- **freshbooks_create_client** — Create a client (customer) in FreshBooks. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).
- **freshbooks_create_invoice** — Create an invoice for a client. Created invoices start as drafts. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).
- **freshbooks_update_invoice** — Update an existing invoice. Only the supplied fields are sent. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE). Note that changing an invoice out of draft can email it to the client. email_recipients in fields must be addresses on the invoice's client record unless allow_non_client_recipients is set, which is only for addresses the user named themselves.
- **freshbooks_record_payment** — Record a payment against an invoice. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).
- **freshbooks_accept_estimate** — Accept an estimate on behalf of the account, by sending FreshBooks' action_accept on the estimate (PUT estimates/estimates/{id} with {"estimate": {"action_accept": true}}). Acceptance is not reversible through the API — there is no un-accept action. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE). Idempotent: an estimate already accepted or invoiced is returned unchanged with changed: false and no write is sent. Returns the re-fetched estimate.
- **freshbooks_decline_estimate** — NOT SUPPORTED by the FreshBooks API — this tool always fails, and never sends a request. FreshBooks models no declined state for estimates: the status set is draft / sent / viewed / replied / accepted / invoiced, there is no action_deny or action_decline counterpart to action_accept in FreshBooks' own API collection, and there is no estimate.decline webhook event. The tool exists so this answers with the reason instead of a plausible-looking write that changes nothing. Call it to get the alternatives.
- **freshbooks_update_estimate** — Update an existing estimate. Only the supplied fields are sent; anything omitted is left alone. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE). Supplying lines REPLACES the whole line set — include each existing line's lineid to keep it. Returns the re-fetched estimate.
- **freshbooks_send_estimate** — Email an estimate to the client, by sending FreshBooks' action_email on the estimate (PUT estimates/estimates/{id} with {"estimate": {"action_email": true, …}}). This puts mail in a client's inbox. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE). Omitting email_recipients lets FreshBooks use the client's own address. email_recipients must be addresses on the estimate's client record unless allow_non_client_recipients is set, which is only for addresses the user named themselves. Returns the re-fetched estimate.
- **freshbooks_list_expenses** — List expenses for the account, newest-first by default. Supports pagination and raw FreshBooks filters (e.g. {"search[categoryid]": 5}). If the response reports a total with no rows, the count includes records this identity cannot read — that is reported in the `note` field rather than looking like an empty account.
- **freshbooks_get_expense** — Get a single expense by its numeric id.
- **freshbooks_list_expense_categories** — List expense categories, which supply the categoryid used when creating an expense.
- **freshbooks_create_expense** — Record an expense. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).
- **freshbooks_list_projects** — List projects for the business. Uses businessId (not accountId) and works even when the business has no accounting account.
- **freshbooks_get_project** — Get a single project by its numeric id.
- **freshbooks_create_project** — Create a project. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).
- **freshbooks_list_time_entries** — List tracked time entries for the business. The response envelope also carries total_logged and total_unbilled alongside the rows.
- **freshbooks_create_time_entry** — Log a time entry. Duration is in SECONDS. Asks the user to confirm first: a confirmation prompt where the client supports one; otherwise the first call returns a preview and a confirmToken and makes no network call, and only a repeat call with that token proceeds (see MCP_CONFIRM_MODE).
- **freshbooks_list_services** — List services (the billable work types available to projects and time entries).
- **freshbooks_list_records** — List any FreshBooks accounting resource by name — the generic reader covering the long tail (taxes, credit notes, invoice profiles, tasks, staff, gateways, bills, bill vendors, bill payments, other income, expense categories) alongside the ones with dedicated tools. Returns items plus page/pages/total. Some resources are gated by plan or account role and will report that rather than returning rows.
- **freshbooks_get_record** — Get a single record from any FreshBooks accounting resource by name and id. Ids are numeric on every resource mapped here; the schema also accepts a string so an id carried around as text still works.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "freshbooks-mcp": {
    "command": "npx",
    "args": ["-y","@chrischall/freshbooks-mcp"],
    "env": {
      "FRESHBOOKS_CLIENT_ID": "",
      "FRESHBOOKS_CLIENT_SECRET": ""
    }
  }
}
```

**Requires environment variables:** `FRESHBOOKS_CLIENT_ID`, `FRESHBOOKS_CLIENT_SECRET` — the values above are empty placeholders; fill in real credentials before running (see the repository for what each one is for).

## Documentation

## What freshbooks-mcp does

The freshbooks-mcp MCP server connects an MCP-compatible agent to FreshBooks. It provides tools for resolving account and business identifiers, completing OAuth authorization, checking credential health, and working with accounting data.

Read operations cover invoices, clients, estimates, payments, catalogue items, expenses, expense categories, projects, time entries, and billable services. A generic records interface extends access to taxes, credit notes, invoice profiles, tasks, staff, gateways, bills, bill vendors, bill payments, and other income.

The server also supports selected writes: creating clients, invoices, expenses, projects, and time entries; updating invoices and estimates; recording payments; accepting or emailing estimates; and handling related FreshBooks actions. Write tools require confirmation. The estimate-decline tool does not perform a decline because FreshBooks does not provide that operation; it returns alternatives instead.

## How it works

freshbooks-mcp uses FreshBooks OAuth2. There is no API key or personal access token flow. The server can generate a consent URL and exchange an authorization code or pasted redirect URL for a refresh token. It can also resolve the FreshBooks account and business identifiers needed by some operations and distinguish missing credentials, rejected credentials, and an unavailable FreshBooks service through its health check.

For local sessions, rotated refresh tokens are saved in the configured token store with restrictive file permissions. FreshBooks replaces the refresh token after each refresh, so the latest stored value takes precedence over an older environment value. A single token store should not be shared by separate tools.

Confirmation behavior depends on the client. Clients with prompt support can show the intended write directly. Other clients receive a preview and a single-use confirmation token before any network write occurs. Tokens can expire, cannot be reused, and become invalid if the arguments change.

## Setup and configuration

Install the package globally with npm, then register an application in the FreshBooks developer area. The redirect URI must use HTTPS and cannot include a query string; `https://localhost` is an example supported by the project.

Set `FRESHBOOKS_CLIENT_ID` and `FRESHBOOKS_CLIENT_SECRET`, start the server, call `freshbooks_auth_url`, authorize in a browser, and pass the resulting URL to `freshbooks_auth_exchange`. Local sessions save the token in `FRESHBOOKS_TOKEN_STORE`. `FRESHBOOKS_REFRESH_TOKEN` can be used for an existing environment-based setup, while `FRESHBOOKS_REDIRECT_URI` and `FRESHBOOKS_TOKEN_STORE` customize the defaults.

If the FreshBooks user belongs to multiple businesses, set `FRESHBOOKS_BUSINESS_ID`. Some invoice and expense writes also need `FRESHBOOKS_ACCOUNT_ID` when FreshBooks does not return an account identifier for the selected business. Hosted deployments use `MCP_DATA_DIR` to identify their environment and return the refresh token to the host's secret-management flow.

Confirmation behavior can be adjusted with `MCP_CONFIRM_MODE`, `MCP_CONFIRM_ELICITATION`, `MCP_CONFIRM_TTL_SECONDS`, and `MCP_CONFIRM_SECRET`.

## Tools and capabilities

- Resolve FreshBooks identity and verify OAuth reachability.
- Browse and fetch invoices, clients, estimates, payments, items, expenses, projects, and related records.
- Create clients, invoices, expenses, projects, and time entries after confirmation.
- Update invoices and estimates, record payments, accept estimates, and email estimates.
- List time entries with logged and unbilled totals.
- Access less common accounting resources through generic record tools.

## Limitations and notes

The freshbooks-mcp MCP server cannot decline estimates because FreshBooks has no decline API operation. Estimate acceptance is an action rather than a writable status field and is idempotent; a previously accepted or invoiced estimate does not trigger another write.

Refresh tokens rotate on every refresh and the old token becomes invalid immediately. Losing the token store requires repeating authorization. After local reauthorization, restart local MCP processes that use the store. Changing the app credentials or redirect URI can also require a new sign-in.

When FreshBooks omits the account ID for a selected business, invoice and expense writes are refused until both business and account identifiers are supplied. Projects and time entries can still work in that situation.

_Full upstream README: https://allmcps.com/mcp/freshbooks-mcp/readme_

