WF

wavingcatapps/freeagent-mcp-vercel

Developer tools
10 stars 4 forks Quality 76 Trend 38MIT

A Model Context Protocol (MCP) server for the FreeAgent accounting API. Enables LLMs to manage contacts, invoices, estimates, bills, expenses, timeslips, projects, tasks, bank accounts, and more.

Overview

A Model Context Protocol (MCP) server for the FreeAgent accounting API. Enables LLMs to manage contacts, invoices, estimates, bills, expenses, timeslips, projects, tasks, bank accounts, and more. By my own admission, most of this project is vibe coded. - : contacts, invoices (incl. transitions, email, duplicate, direct debit), estimates, bills, recurring invoices, price list items, expenses, timeslips, projects, tasks, bank accounts/feeds/statements (JSON lines), credit notes + reconciliations, notes, attachments (metadata), journals, capital assets, accounting reports (P&L, balance sheet, trial balance, cashflow, ledger), VAT/corp tax/income tax/final accounts, payroll, properties/stock/hire purchases, CIS, sales tax periods, account locks, categories, company info, and users - : reconcile_bank_transaction, log_expense, and invoice_from_timeslips collapse multi-call sequences into single tool calls and resolve human-friendly hints (names, codes, references) to FreeAgent URLs...

README

FreeAgent MCP Server

A Model Context Protocol (MCP) server for the FreeAgent accounting API. Enables LLMs to manage contacts, invoices, estimates, bills, expenses, timeslips, projects, tasks, bank accounts, and more.

By my own admission, most of this project is vibe coded.

Features

  • Broad FreeAgent coverage: contacts, invoices (incl. transitions, email, duplicate, direct debit), estimates, bills, recurring invoices, price list items, expenses, timeslips, projects, tasks, bank accounts/feeds/statements (JSON lines), credit notes + reconciliations, notes, attachments (metadata), journals, capital assets, accounting reports (P&L, balance sheet, trial balance, cashflow, ledger), VAT/corp tax/income tax/final accounts, payroll, properties/stock/hire purchases, CIS, sales tax periods, account locks, categories, company info, and users
  • Intent-bundle tools: reconcile_bank_transaction, log_expense, and invoice_from_timeslips collapse multi-call sequences into single tool calls and resolve human-friendly hints (names, codes, references) to FreeAgent URLs server-side
  • Tool-search mode (FREEAGENT_TOOL_SEARCH=true): optional — collapses the catalog behind freeagent_search_tools / freeagent_call_tool for a smaller tools/list. Default is the full catalog (including on Vercel)
  • MCP elicitation: create_invoice falls back to a form elicitation when contact is omitted (on clients that support it)
  • Two deployment modes: local (stdio) or cloud (Vercel serverless via Streamable HTTP)
  • OAuth 2.0: stateless JWT-based auth for serverless, or direct token for local use
  • Tool annotations: readOnlyHint, destructiveHint, idempotentHint, openWorldHint on every tool
  • Zod validation: strict input schemas with .describe() on all fields
  • Dual response formats: Markdown (human-readable) or JSON (structured)
  • Pagination: proper header parsing with x-total-count and Link headers
  • Rate limit handling: clear error messages with retry-after guidance
  • Sandbox support: test safely against FreeAgent’s sandbox environment

Deployment Options

Local (stdio) - for Claude Desktop

  1. Install and build:

    bun install
    bun run build
    
  2. Set environment variables:

    export FREEAGENT_ACCESS_TOKEN="your_access_token"
    export FREEAGENT_USE_SANDBOX="true"  # optional
    
    # optional: refresh the access token automatically when it expires
    export FREEAGENT_REFRESH_TOKEN="your_refresh_token"
    export FREEAGENT_CLIENT_ID="your_client_id"
    export FREEAGENT_CLIENT_SECRET="your_client_secret"
    export FREEAGENT_TOKEN_CACHE="$HOME/.config/freeagent-mcp/tokens.json"  # optional, this is the default
    

    With the refresh variables set, a 401 triggers a token refresh and one retry. The newest tokens are saved to the cache file (mode 600) and used on the next start, so you only need to repeat the OAuth flow if the refresh token itself is revoked.

  3. Add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):

    {
      "mcpServers": {
        "freeagent": {
          "command": "node",
          "args": ["/path/to/freeagent-mcp-server/dist/index.js"],
          "env": {
            "FREEAGENT_ACCESS_TOKEN": "your_token",
            "FREEAGENT_USE_SANDBOX": "true"
          }
        }
      }
    }
    

Vercel (Streamable HTTP) - for cloud access

One-click deploy (clones this repo into your Git account and prompts for env vars):

After deploy, register https://YOUR_PROJECT.vercel.app/oauth/callback on your FreeAgent OAuth app (see OAUTH_SETUP.md). Full walkthrough: VERCEL_DEPLOYMENT.md.

Key points:

  • Uses StreamableHTTPServerTransport in stateless mode (no sessions) with enableJsonResponse: true (avoids empty SSE bodies on Vercel)
  • OAuth 2.0 with PKCE via JWT-encoded tokens (no database needed)
  • Handles POST (JSON-RPC tool calls); GET/DELETE return 405 in this serverless/stateless deploy (no durable SSE sessions)
  • Set PRODUCTION_URL (or rely on VERCEL_PROJECT_PRODUCTION_URL) for stable production OAuth callback URLs. Preview OAuth uses the request host (or VERCEL_URL) so short per-deploy hosts match FreeAgent * wildcards.

Required env vars: FREEAGENT_CLIENT_ID, FREEAGENT_CLIENT_SECRET, JWT_SECRET (stable secret required on Vercel so OAuth JWTs verify across serverless instances)

Tool-Search Mode (optional)

By default the server registers every catalog tool directly (~165 definitions in tools/list), including on Vercel. That path is reliable again after the tools/list schema fixes.

If you want a smaller tools/list (e.g. many MCP servers competing for context), opt in:

export FREEAGENT_TOOL_SEARCH=true   # only freeagent_search_tools + freeagent_call_tool

Unset it (or anything other than true/1) to keep the full catalog.

Tool Purpose
freeagent_search_tools Search the catalog and return JSONSchema for matching tools. Query forms: select:name1,name2 for direct lookup, +required optional for scored search with required keywords, or plain keywords for a ranked search.
freeagent_call_tool Invoke any catalog tool by name with validated arguments ({ name, arguments }). Pair with search_tools to discover schemas on demand.

This mirrors the deferred-loading pattern used by Claude Code’s internal ToolSearch.

Available Tools

See TOOLS.md for per-tool parameters and examples. Summary:

Contacts

Tool Description Read-only
freeagent_list_contacts List contacts with pagination and sorting Yes
freeagent_get_contact Get contact details by ID Yes
freeagent_create_contact Create a new contact No

Invoices

Tool Description Read-only
freeagent_list_invoices List invoices with status/contact/project filters Yes
freeagent_get_invoice Get invoice details (renders computed discount amount) Yes
freeagent_create_invoice Create a draft invoice (supports discount_percent; elicits contact if omitted) No
freeagent_transition_invoice mark_as_sent / mark_as_cancelled / mark_as_draft / mark_as_scheduled / convert_to_credit_note No
freeagent_invoice_from_timeslips Intent bundle: draft an invoice from a contact’s unbilled timeslips No

Estimates

Tool Description Read-only
freeagent_list_estimates List estimates with status/contact/project filters Yes
freeagent_get_estimate Get estimate details (renders computed discount amount) Yes
freeagent_create_estimate Draft an estimate (supports discount_percent) No
freeagent_transition_estimate mark_as_sent / mark_as_approved / mark_as_rejected / mark_as_cancelled / mark_as_draft / convert_to_invoice No

Bills

Tool Description Read-only
freeagent_list_bills List supplier bills with filters Yes
freeagent_get_bill Get bill details Yes
freeagent_create_bill Record a supplier bill No

Recurring Invoices

Tool Description Read-only
freeagent_list_recurring_invoices List recurring invoice templates Yes
freeagent_get_recurring_invoice Get template details Yes

Price List Items

Tool Description Read-only
freeagent_list_price_list_items List catalog items Yes
freeagent_get_price_list_item Get catalog item details Yes
freeagent_create_price_list_item Add a catalog item No

Expenses

Tool Description Read-only
freeagent_list_expenses List expenses with date/view filters Yes
freeagent_get_expense Get expense details (inc. mileage info) Yes
freeagent_create_expense Create expense or mileage claim (with attachments) No
freeagent_update_expense Update an existing expense No
freeagent_log_expense Intent bundle: log a regular expense with a positive amount + kind enum No

Timeslips

Tool Description Read-only
freeagent_list_timeslips List time entries with filters Yes
freeagent_get_timeslip Get timeslip details Yes
freeagent_create_timeslip Create a time entry No
freeagent_update_timeslip Update a timeslip (incl. billed_on_invoice) No

Bank Accounts & Transactions

Tool Description Read-only
freeagent_list_bank_accounts List all bank accounts Yes
freeagent_get_bank_account Get bank account details Yes
freeagent_list_bank_transactions List transactions for an account Yes
freeagent_get_bank_transaction Get bank transaction details Yes
freeagent_list_bank_transaction_explanations List transaction explanations Yes
freeagent_get_bank_transaction_explanation Get explanation details Yes
freeagent_create_bank_transaction_explanation Explain/categorize a bank transaction No
freeagent_update_bank_transaction_explanation Update a transaction explanation No
freeagent_reconcile_bank_transaction Intent bundle: explain a transaction with a category name / invoice ref / bill ref No

Projects & Tasks

Tool Description Read-only
freeagent_list_projects List projects with status/contact filters Yes
freeagent_get_project Get project details Yes
freeagent_create_project Create a new project No
freeagent_list_tasks List tasks with project/status filters Yes
freeagent_get_task Get task details Yes
freeagent_create_task Create a task within a project No

Categories, Company & Users

Tool Description Read-only
freeagent_list_categories List accounting categories Yes
freeagent_get_category Get category by nominal code Yes
freeagent_get_company Get company information Yes
freeagent_list_users List all users Yes

Intentional omissions

  • Timeslip timers — start/stop timer endpoints are not exposed (poor MCP fit).
  • Binary PDF download tools — invoice/estimate/credit-note PDF bytes are not returned (no efficient agentic binary channel yet).
  • File-based bank statement upload — use freeagent_upload_bank_statement with JSON lines instead. Nested base64 attachments on expenses/explanations remain supported.
  • Accountancy Practice API — practice/client endpoints are out of scope for this company-facing server.

Development

Prerequisites

  • Bun (used for package management and running scripts)
  • Node.js 24.x

Setup

bun install

Scripts

Command Description
bun run build Compile TypeScript
bun run dev Watch mode (auto-recompile)
bun run start Run the compiled server
bun run lint Run ESLint
bun run test Run tests
bun run test:watch Run tests in watch mode
bun run test:coverage Run tests with coverage

Project Structure

freeagent-mcp-server/
├── src/
│   ├── index.ts                       # Stdio server entry point
│   ├── constants.ts                   # Configuration constants & shared utilities
│   ├── types.ts                       # TypeScript type definitions
│   ├── schemas/
│   │   ├── index.ts                   # Zod validation schemas for all tools
│   │   ├── projects.ts                # Project-specific schemas
│   │   └── schemas.test.ts            # Schema validation tests
│   ├── services/
│   │   ├── api-client.ts              # FreeAgent API client (Axios)
│   │   ├── api-client.test.ts         # API client tests
│   │   ├── formatter.ts               # Response formatting utilities (incl. discount amount helper)
│   │   ├── formatter.test.ts          # Formatter tests
│   │   ├── resolvers.ts               # Shared resolvers (category / user / contact / bill hints → URLs)
│   │   ├── oauth-jwt.ts               # JWT-based OAuth provider (Vercel)
│   │   └── freeagent-auth.ts          # Token validation
│   └── tools/
│       ├── register.ts                # Shared tool definitions, registration, ToolContext (elicitation)
│       ├── contacts.ts                # Contact CRUD
│       ├── invoices.ts                # Invoice management (incl. elicitation fallback)
│       ├── transition-invoice.ts      # Invoice lifecycle transitions
│       ├── invoice-from-timeslips.ts  # Intent bundle: draft an invoice from unbilled time
│       ├── estimates.ts               # Estimates + transition_estimate
│       ├── bills.ts                   # Supplier bills
│       ├── recurring-invoices.ts      # Recurring invoice templates (read-only)
│       ├── price-list-items.ts        # Catalog items
│       ├── expenses.ts                # Expense & mileage tracking
│       ├── log-expense.ts             # Intent bundle: positive-amount expense logging
│       ├── timeslips.ts               # Time tracking (incl. update_timeslip)
│       ├── bank-accounts.ts           # Bank accounts & transactions
│       ├── bank-transactions.ts       # Transaction explanations
│       ├── reconcile.ts               # Intent bundle: reconcile a transaction in one call
│       ├── projects.ts                # Project management
│       ├── tasks.ts                   # Task management
│       ├── categories.ts              # Accounting categories
│       └── company.ts                 # Company info & users
├── api/
│   └── index.ts              # Vercel serverless entry point
├── .github/
│   └── workflows/
│       └── ci.yml            # GitHub Actions CI (lint, test, build)
├── eslint.config.js          # ESLint flat config
├── vitest.config.ts          # Vitest configuration
├── vercel.json               # Vercel deployment config
├── package.json
└── tsconfig.json

CI

GitHub Actions runs on every push to main and on pull requests:

  • Lint: ESLint with TypeScript rules
  • Test: Vitest unit tests (no external API calls)
  • Build: TypeScript compilation check

Rate Limiting

Environment Limit
Production 15 requests / 60 seconds
Sandbox 5 requests / 60 seconds

The server returns clear error messages with retry-after timing when rate limited.

Error Handling

All tool handlers return structured errors via { isError: true, content: [...] } (never thrown exceptions). Error messages are designed for LLM consumption with actionable guidance:

Status Meaning
401 Token expired - refresh OAuth token
403 Insufficient permissions
404 Resource not found or deleted
422 Validation error with field-level details
429 Rate limited - retry after N seconds

Security

  • Access tokens are never logged or committed
  • JWT tokens use HS256 signing with configurable secret
  • PKCE is used for the OAuth authorization flow
  • Strict Zod schemas reject unexpected input fields
  • Bearer auth middleware protects all MCP endpoints

License

MIT

View the full README on GitHub

Install

This server does not publish a one-line install command.

Open the repository installation guide New to MCP? Start with the mcpskill.org guide →

Configuration

{ "mcpServers": { "freeagent": { "command": "node", "args": ["/path/to/freeagent-mcp-server/dist/index.js"], "env": { "FREEAGENT_ACCESS_TOKEN": "your_token", "FREEAGENT_USE_SANDBOX": "true" } } } }