freeagent-mcp-remote
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., "@freeagent-mcp-remotewhich bank transactions from March are still unexplained?"
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.
freeagent-mcp-remote
This "connector" was built to give Claude access to my FreeAgent data. At this point it is an internal tool, however I tried to write clearly and for the general public in case it would be useful for others. If you need help to set up, adapt, or if you'd like a similar tool for your business, ask a question.
Inspired by samaxbytez/freeagent-mcp Although initially I thought I'd be developing on top of it I decided to start from scratch using [https://gofastmcp.com] and Python.
WIP — "work in progress". A term used by developers, used throughout this readme to mark functionality that is not yet available. Equivalent to "coming soon".
What's available
Status | |
A FreeAgent command-line tool — read your accounting data from a terminal | Works now |
A Claude connector — ask Claude questions about your books | WIP |
They share the same setup, so following the steps below gets you the working half today.
How it works
This project is a small server that sits between FreeAgent and Claude (or another AI provider) and acts as a translator. Once it's connected, you can ask Claude things like "which bank transactions from March are still unexplained?" and Claude can go and look.
The technical name for this kind of translator is an MCP server — MCP being a shared standard for connecting AI assistants to outside tools. In Claude, these show up as connectors. You don't need to know anything more than that to use it.
Additional reading:
What is MCP? explains it in plain terms (think "a USB-C port for AI").
Get started with custom connectors.
Setup
Needed for both the command-line tool and (later) the connector. Written assuming you can follow a terminal, but haven't necessarily built a Python service before.
1. Get FreeAgent credentials
Before connecting to FreeAgent you need to register an "app". That gives you two strings — a client ID and a client secret — which together identify this server to FreeAgent. This way one "app" can be installed on different FreeAgent organisations, and for example if an "app" is found to be malicious FreeAgent can uninstall it from all the organisations at once. Unfortunately this registration is required even if you only want to connect to your own account.
Go to the FreeAgent Developer Dashboard and sign in.
Create an app.
Set the OAuth redirect URI to
http://localhost:8723/callback. This is where FreeAgent sends your browser back to after you approve access, so it has to match exactly — a trailing slash will break it.That address is the one the command-line tool uses, because the browser comes back to your own machine. The connector, once it's deployed, is reached at a public web address instead, and so needs its own redirect URI registered —
<the container's URL>/auth/callback. Nothing to do about that now; the deployment runbook covers it at the point where it matters. It's only worth knowing so that seeing two different addresses later doesn't look like one of them is a mistake.Duplicate
.env.exampleinto.envif you haven't already. That file is not checked into git, thanks to.gitignore. Copy the OAuth identifier and secret into it asFREEAGENT_CLIENT_IDandFREEAGENT_CLIENT_SECRET.
2. Install
The only thing you need installed first is uv, a tool that manages Python projects. It fetches the right version of Python for you, so you don't need Python installed already and don't need to know anything about virtual environments.
On a Mac, with Homebrew:
brew install uv
uv --version # check it workedOther platforms, and other ways to install it, are covered in uv's installation guide.
Then:
git clone <this-repo> && cd freeagent-mcp-remote
uv sync # creates .venv, installs everything, fetches Python 3.14
cp .env.example .env # then add the credentials from the step aboveuv sync takes a minute the first time and is near-instant afterwards.
uv run <command> runs things inside that environment, which is why every command below
starts with it.
3. Authorise
uv run scripts/fa_auth.pyA browser opens, you approve access, and it writes a token back to .env. FreeAgent's
access tokens last an hour, but a refresh token is saved alongside and used automatically,
so this is genuinely a one-time step.
Sandbox. FreeAgent offers a free sandbox at signup.sandbox.freeagent.com — a throwaway company you can safely write to. It needs its own signup and its own app registration; sandbox credentials don't work against production. Point at it by setting
FREEAGENT_API_BASE_URL=https://api.sandbox.freeagent.com/v2, and the login endpoints follow automatically so the two can't get crossed. Worth doing before anything that writes; not worth it for reading, since a sandbox has none of your actual data.
Using the command-line tool
This works today. It reads any part of your FreeAgent account from the terminal, handling the login for you.
FreeAgent's data is organised into "endpoints" — /company, /invoices,
/bank_accounts and so on. The FreeAgent API docs list
them all. You ask for one like this:
uv run fastmcp call scripts/freeagent_api_caller.py request path=/companySome things to try
All of these are read-only and safe.
# Your company profile: year end dates, VAT registration, company type
uv run fastmcp call scripts/freeagent_api_caller.py request path=/company
# Bank accounts, including how many transactions are still unexplained
uv run fastmcp call scripts/freeagent_api_caller.py request path=/bank_accounts
# Trial balance — every nominal account and its total
uv run fastmcp call scripts/freeagent_api_caller.py request \
path=/accounting/trial_balance/summary
# One contact, to see what fields a contact has
uv run fastmcp call scripts/freeagent_api_caller.py request \
--input-json '{"path": "/contacts", "params": {"per_page": "1"}}'
# Click around in a browser instead
uv run fastmcp dev inspector scripts/freeagent_api_caller.pySimple arguments go as key=value. Nested ones — params and body — need
--input-json, which can carry the whole call.
Keeping the output manageable
A list endpoint can return thousands of records. Two ways to trim it, and they combine:
per_page=1limits how many records come back. Usually what you want — one real record shows you the actual formats values come in.shape_only=truefield names and types, no values. Useful for learning API shape during development.
uv run fastmcp call scripts/freeagent_api_caller.py request path=/invoices shape_only=trueOther options
Argument | What it does |
| Which endpoint to call. The only required one. |
|
|
| Query options, e.g. |
| Adds the true record count and paging links to the result. |
| Required before anything that changes data. |
Changing data (POST, PUT, DELETE) needs confirm_write=true. That's deliberate
friction — these are your real accounting records. Use the sandbox for those.
[WIP] The Claude connector
Not ready yet. When it is, you'll be able to add this to Claude as a connector and ask questions in plain language rather than calling endpoints yourself:
Work through unexplained bank transactions and suggest how to categorise them
Pull up the profit & loss, balance sheet or trial balance for a period
Look at journal entries, or post corrections
Prepare figures for VAT returns and corporation tax
Review payroll and PAYE figures
Think through the salary-versus-dividends split using your actual profit
Track time, tasks and projects
The difference from the command-line tool is that the connector exposes each of these as a separate, narrow capability rather than one general "call anything" command — for reasons under Safety below.
For developers
Everyday commands
uv run pytest # run the tests
uv run pytest --lf # just the ones that failed last time
uv run ruff format . # auto-format the code
uv run ruff check . # find likely mistakes and style problems
uv run mypy # check the types line upmypy is the one worth not skipping: it's set to strict, so it catches a whole class of
"this could be nothing here" bugs before they ever run.
Checks on commit
A git hook runs all four automatically every time you commit. Enable it once:
git config core.hooksPath .githooksThe whole suite takes about two seconds. If something fails, the commit stops and you get the output.
To commit anyway, use git's built-in bypass:
git commit --no-verify -m "..."The hook also refuses outright to commit .env, which holds a live FreeAgent secret and
access token.
Working on the connector
# What tools does the server expose, and what do their inputs look like?
uv run fastmcp inspect src/server.py:create_server
# Click through it in a browser
uv run fastmcp dev inspector src/server.py:create_serverNote the :create_server at the end — these commands need the file and the name of the
function inside it that builds the server, not just the filename.
FreeAgent's documentation has gaps, contradictions and at least two copy-paste errors,
so the connector's tools are designed against real API responses rather than against the
docs. That's what the command-line tool above is for. scripts/freeagent_api_caller.py is local
only and must never be deployed; there's a test that fails if it ever reaches the deployed
server.
Learning
Caches
Three directories appear once you've run the tools. All are generated, gitignored, and never inputs to the program — deleting any of them costs nothing but a slower next run.
.mypy_cache/— what mypy learned about each file's types, so re-checking an unchanged file is a cache read rather than a fresh analysis. The one that matters most: without it, every run re-analyses all your dependencies' type information..pytest_cache/— which tests failed last time. This is what powerspytest --lf(last-failed) and--ff(failed-first), so you can iterate on just the broken tests..ruff_cache/— per-file lint results. Ruff is fast enough that you'd barely notice this one missing.
If anything ever behaves strangely, rm -rf .mypy_cache .pytest_cache .ruff_cache is a
safe reset.
If you get stuck
I built this for my own company's books, and wrote it up properly in case it's useful to someone else.
If you're trying to set up something like this and it isn't going well, I do this kind of work professionally and I'm happy to talk.
If you've found a bug or something here is wrong, an issue is welcome.
This 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.
Related MCP Connectors
Hosted MCP server for Mini Accountant: invoices, expenses, customers, analytics, tax estimates.
Hosted Amazon Seller Central and Amazon Ads MCP server for Claude, ChatGPT, Cursor, and agents.
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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/kivistudio/freeagent-connector'
If you have feedback or need assistance with the MCP directory API, please join our Discord server