freshbooks-mcp-server
Click on "Install 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., "@freshbooks-mcp-servershow my overdue 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.
FreshBooks MCP Server
An MCP (Model Context Protocol) server for the FreshBooks API. Connect Claude to your FreshBooks account to read invoices, clients, expenses, projects, services, and more, and to manage payments and time entries.
Supports two modes:
stdio — for Claude Desktop and MCP Inspector (no server needed)
HTTP + SSE — for claude.ai custom connectors (requires a public HTTPS URL)
Tools
Tool | Description |
| Get the authenticated user's profile and account/business IDs |
| List all team members in the business with their identity_id, name, email, and role |
| Get a team member by their identity_id |
| List clients with optional search and filters |
| Get a client by ID |
| List invoices filtered by client, status, or date range |
| Get an invoice by ID including line items |
| List expenses filtered by client, project, or date range |
| Get an expense by ID |
| List payments filtered by invoice or date range |
| Get a payment by ID |
| List projects filtered by client or active status |
| Get a project by ID |
| List time entries filtered by project, client, or date range |
| Get a time entry by ID |
| Log a time entry against a project; automatically associates the project's client and accepts an optional |
| Update a time entry |
| Delete a time entry |
| List items (products/services) |
| Get an item by ID |
| List all services defined for the business |
| Get a service by ID |
| Get the global billing rate for a service |
| List per-project billing rate overrides for all services on a project (undocumented endpoint) |
Related MCP server: @him0/freee-mcp
Prerequisites
Node.js v20.6 or later
A FreshBooks account
A FreshBooks app (free) — create one at my.freshbooks.com/#/developer
Setup
git clone https://github.com/bitovi/freshbooks-mcp-server
cd freshbooks-mcp-server
npm install
npm run build
cp .env.example .envEdit .env and set your FreshBooks app credentials:
FRESHBOOKS_CLIENT_ID=your_client_id
FRESHBOOKS_CLIENT_SECRET=your_client_secretClaude Desktop (stdio)
This is the simplest way to use the server. Claude Desktop communicates with it directly over stdio — no HTTP server or public URL required.
1. Get a FreshBooks refresh token
Start the HTTP server to complete the OAuth flow once:
npm run dev:httpIn a separate terminal, print the auth URL:
npm run auth-urlOpen the printed URL in your browser and log in with FreshBooks. Your refresh_token and session_token are displayed in the browser. FreshBooks tokens are also saved to ~/.freshbooks-mcp/sessions.json.
Copy the refresh_token value and add it to .env:
FRESHBOOKS_REFRESH_TOKEN=your_refresh_tokenThe server exchanges this for an access token on startup and handles renewal automatically — you only need to do this once unless you revoke the app's access in FreshBooks.
2. Add to Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"freshbooks": {
"command": "/path/to/node",
"args": ["/path/to/freshbooks-mcp-server/dist/index.js"],
"env": {
"MODE": "stdio"
}
}
}
}Replace /path/to/node with the full path to your Node.js binary (which node) and /path/to/freshbooks-mcp-server with the absolute path to this repo.
nvm users: Claude Desktop doesn't inherit your shell environment. Use the full path to your node binary, e.g.
/Users/you/.nvm/versions/node/v22.8.0/bin/node.
Restart Claude Desktop. The FreshBooks tools will appear in the hammer menu in the chat input.
claude.ai Custom Connector (HTTP + SSE)
Claude.ai custom connectors require a public HTTPS URL. You can test the connector with ngrok or by a deploy to AWS.
Testing locally
1. Start the server
npm run dev:http2. Trust the self-signed certificate
Open https://localhost:3443 in your browser. Click Advanced → Proceed to localhost to accept the self-signed cert. You only need to do this once per browser session — otherwise the OAuth redirect will be blocked.
3. Add the callback URI to your FreshBooks app
In your FreshBooks developer console, add:
https://localhost:3443/oauth/callback4. Get the auth URL
npm run auth-urlOpen the printed URL in your browser, log in with FreshBooks, and you'll see your session token displayed on the page.
5. Test the SSE endpoint
curl -sk https://localhost:3443/sse -H "Authorization: Bearer <session_token>"Setting up ngrok
If you want to test in claude.ai locally with a real certificate, use ngrok:
# Add to .env:
HTTPS=false
SERVER_URL=https://your-subdomain.ngrok-free.appnpm run dev:http # Terminal 1
ngrok http 3000 # Terminal 2Add https://your-subdomain.ngrok-free.app/oauth/callback to your FreshBooks app, then run npm run auth-url.
Adding to claude.ai
Go to Settings → Integrations → Add Integration and enter your SSE URL:
https://your-subdomain.ngrok-free.app/sse # ngrok
https://freshbooks-mcp.yourdomain.com/sse # productionClaude will prompt you to log in with FreshBooks. After authenticating, the tools are available in your conversations.
Deploying to AWS (EC2 + nginx)
The recommended setup is an EC2 instance running nginx as a reverse proxy, with Let's Encrypt for a free TLS certificate. Sessions are stored on disk so they survive restarts.
Architecture
claude.ai → ALB (or Elastic IP) → nginx (HTTPS/443) → Node.js (HTTP/3000)You can skip the ALB and use nginx + Let's Encrypt directly on EC2 if you don't need auto-scaling.
1. Launch an EC2 instance
AMI: Amazon Linux 2023 (or Ubuntu 22.04)
Instance type: t3.micro (free tier) or t3.small
Security group inbound rules:
SSH (22) — your IP only
HTTP (80) — anywhere (needed for Let's Encrypt verification)
HTTPS (443) — anywhere
Attach an Elastic IP so your DNS record stays stable across reboots
2. Point a domain at the instance
In Route 53 (or any DNS provider), create an A record pointing your domain to the Elastic IP:
freshbooks-mcp.yourdomain.com → <Elastic IP>3. Install Node.js 22 and nginx
# Amazon Linux 2023
sudo dnf install -y nginx git
curl -fsSL https://rpm.nodesource.com/setup_22.x | sudo bash -
sudo dnf install -y nodejs
# Ubuntu 22.04
sudo apt update && sudo apt install -y nginx git
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash -
sudo apt install -y nodejsInstall PM2 globally:
sudo npm install -g pm24. Deploy the app
git clone https://github.com/bitovi/freshbooks-mcp-server /srv/freshbooks-mcp
cd /srv/freshbooks-mcp
npm install
npm run build
mkdir -p logs
cp .env.example .env
nano .env # fill in credentials (see Environment variables below)Minimum .env for production:
FRESHBOOKS_CLIENT_ID=your_client_id
FRESHBOOKS_CLIENT_SECRET=your_client_secret
MODE=http
HTTPS=false
SERVER_URL=https://freshbooks-mcp.yourdomain.comPORT defaults to 3000 when HTTPS=false, so no need to set it explicitly.
5. Configure nginx
Create /etc/nginx/conf.d/freshbooks-mcp.conf:
server {
listen 80;
server_name freshbooks-mcp.yourdomain.com;
# Let's Encrypt challenge + redirect everything else to HTTPS
location /.well-known/acme-challenge/ { root /var/www/certbot; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl;
server_name freshbooks-mcp.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/freshbooks-mcp.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/freshbooks-mcp.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Required for SSE — disable buffering so events stream immediately
proxy_buffering off;
proxy_cache off;
proxy_set_header Connection '';
# Keep SSE connections open for up to 24 hours
proxy_read_timeout 86400s;
chunked_transfer_encoding on;
}
}Test and reload:
sudo nginx -t && sudo systemctl reload nginx6. Get a TLS certificate
sudo dnf install -y python3-certbot-nginx # Amazon Linux 2023
# or: sudo apt install -y certbot python3-certbot-nginx # Ubuntu
sudo certbot --nginx -d freshbooks-mcp.yourdomain.comCertbot auto-configures nginx and sets up auto-renewal via a systemd timer.
7. Start the server with PM2
cd /srv/freshbooks-mcp
pm2 start ecosystem.config.cjs
pm2 save # persist across reboots
pm2 startup # follow the printed command to enable on bootUseful commands:
pm2 logs freshbooks-mcp # tail logs
pm2 reload freshbooks-mcp # zero-downtime restart after code changes
pm2 status # check process health8. Update FreshBooks and claude.ai
In your FreshBooks developer console, add the production redirect URI:
https://freshbooks-mcp.yourdomain.com/oauth/callbackIn claude.ai → Settings → Integrations → Add Integration, enter:
https://freshbooks-mcp.yourdomain.com/sseClaude will walk you through the FreshBooks OAuth flow. After that, all tools are live.
Updating the server
cd /srv/freshbooks-mcp
git pull
npm install
npm run build
pm2 reload freshbooks-mcpNotes
Sessions are stored in
~/.freshbooks-mcp/sessions.jsonon the EC2 instance. Since EC2 has a persistent filesystem, sessions survive restarts and deploys.ALB: If you later add an Application Load Balancer, set its idle timeout to 3600 seconds (default 60 will drop long-lived SSE connections). nginx's
proxy_read_timeouthandles this when going direct.Logs go to
./logs/in the project directory and are managed by PM2.
Environment variables
Variable | Required | Description |
| Yes | Your FreshBooks app's client ID |
| Yes | Your FreshBooks app's client secret |
| For stdio | A valid FreshBooks access token |
| Optional | Refresh token — used to auto-renew the access token |
| No |
|
| No | Listen port. Defaults to |
| For HTTP mode | Public base URL. Defaults to |
| No |
|
| No | Path for persisted sessions (default: |
| No | Override the FreshBooks API base URL (default: |
Project structure
src/
index.ts Entry point — picks stdio or HTTP based on MODE
load-env.ts Minimal .env loader (no dotenv dependency)
config.ts Config from environment variables
mcp-server.ts Creates the McpServer and registers all tools
http-server.ts Express server with SSE transport and OAuth2 proxy
stdio-server.ts Stdio transport with token resolution
freshbooks/
client.ts FreshBooks API client
types.ts TypeScript types for API responses
tools/
users.ts get_current_user, list_team_members, get_team_member
clients.ts Client tools
invoices.ts Invoice tools
expenses.ts Expense tools
payments.ts Payment tools
projects.ts Project tools
time-entries.ts Time entry tools
items.ts Item tools
services.ts Service tools
scripts/
auth-url.ts Prints the FreshBooks OAuth URL for local testingThis server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bitovi/freshbooks-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server