freee MCP Server Deep Dive — OAuth PKCE Auth, 5-Domain Integration & Agent Dev Pitfalls 2026
freee is Japan's dominant cloud accounting, HR, and payroll platform for SMBs. On KanseiLink's AEO rating, it holds an AAA grade with 216ms average latency. The official MCP server (npx @freee/mcp-server) unifies five business domains—accounting, HR, payroll, expenses, and invoicing—under a single connection. Yet OAuth 2.0 PKCE and a mandatory company_id preflight are the two design choices that trip up most agent developers on day one. This article dissects freee's AEO rating, 5-domain architecture, authentication flow, four implementation pitfalls, and a head-to-head comparison with MoneyForward Cloud—all based on KanseiLink's April 2026 evaluation data.
KanseiLink monitoring data shows freee MCP's auth_expired (OAuth 2.0 token expiry) errors have spiked 4× above baseline in the last 24 hours. If you are running agents against freee, verify your token refresh logic immediately. See Pitfall #1 below for the fix.
1. freee AEO Rating — Why AAA?
Last Updated: 2026-04-13 | Latest Change: v2 /invoices/bulk (2026-04-05)
| Criterion | freee Performance | Rating |
|---|---|---|
| Official MCP Server | Published by freee Inc. (@freee/mcp-server), instant startup via npx. Remote MCP added 2026-03-27 for cloud-native deployments | ✅ Top tier |
| Domain Coverage | 5 business domains (accounting, HR, payroll, expenses, invoicing) from a single MCP connection | ✅ Industry leading |
| API Maturity | REST API v1/v2, pagination, bulk operations, webhooks. Bulk Invoices API (v2) added April 2026 | ✅ Mature |
| Success Rate | Observing (212 agent reports collected). Avg latency 216ms (recent 5 calls: 250–2,500ms) | ✅ Good |
| Documentation | Full Japanese API reference at developer.freee.co.jp with per-endpoint code samples | ✅ Good |
That said, the trust_score of 0.9 (out of 1.0) trails MoneyForward Cloud (0.93) slightly. The gap stems primarily from OAuth 2.0 PKCE's 24-hour token expiry and sporadic api_errors (15 incidents in the dataset).
2. The 5-Domain Architecture
freee's MCP server stands out because a single connection covers five mission-critical business domains. An agent can traverse accounting, HR, payroll, expenses, and invoicing workflows without context-switching between tools.
All five domains share the same company_id and OAuth token. This enables end-to-end flows like "expense approved → auto-create journal entry → feed payroll calculation" without switching tools. Unlike kintone, which issues separate API tokens per app, freee's unified OAuth auth is an advantage for large-scale automation agents.
3. OAuth 2.0 PKCE — Step-by-Step Guide
freee does not support API key authentication. All API access flows through OAuth 2.0 Authorization Code + PKCE (Proof Key for Code Exchange). This is the primary reason freee feels harder to start with compared to kintone or Slack.
-
1Register your app at the Developer PortalGo to app.secure.freee.co.jp/developers, create a new app, and set a redirect_uri (
http://localhost:3000/callbackworks for local dev). Note your client_id. -
2Generate code_verifier and code_challenge for PKCEPKCE requires a 128-character random string (code_verifier) and its SHA-256 hash (code_challenge). Using
npx @freee/mcp-serverautomates this step entirely. -
3Redirect user to the authorization URLSend the user to
https://accounts.secure.freee.co.jp/public_api/authorize?client_id=...&response_type=code&code_challenge=...&code_challenge_method=S256&scope=read+write -
4Exchange authorization_code for access_tokenPOST to
https://accounts.secure.freee.co.jp/public_api/tokenwith the returned code to receive an access_token (24-hour expiry) and refresh_token (90-day expiry). -
5Call GET /api/1/companies to get company_idThis is always the first API call. Skip it and nearly every subsequent call will fail with a company_id required error.
// Step 5: Get company_id (mandatory first call)
const companiesRes = await fetch(
'https://api.freee.co.jp/api/1/companies',
{ headers: { 'Authorization': `Bearer ${accessToken}` } }
);
const { companies } = await companiesRes.json();
const companyId = companies[0].id; // e.g. 123
// Step 6: List deals (company_id required)
const dealsRes = await fetch(
`https://api.freee.co.jp/api/1/deals?company_id=${companyId}&type=income&limit=100`,
{ headers: { 'Authorization': `Bearer ${accessToken}` } }
);
const { deals, meta } = await dealsRes.json();
// Step 7: Bulk invoice issuance (v2 API — added 2026-04-05)
const bulkRes = await fetch(
'https://api.freee.co.jp/api/2/invoices/bulk',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ company_id: companyId, invoices: [...] })
}
);
4. Four Pitfalls Every Agent Developer Hits
freee's access_token is valid for only 24 hours. As of 2026-04-23, auth_expired errors are running 4× above baseline on KanseiLink monitoring. The fix: implement auto-refresh using the 90-day refresh_token. Call POST /public_api/token?grant_type=refresh_token&refresh_token={token}&client_id={id} before each session or when a 401 is received.
async function getValidToken(stored) {
const expiresAt = stored.issuedAt + 23 * 60 * 60 * 1000; // 23h (buffer)
if (Date.now() < expiresAt) return stored.accessToken;
const res = await fetch(
'https://accounts.secure.freee.co.jp/public_api/token',
{
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: stored.refreshToken,
client_id: process.env.FREEE_CLIENT_ID,
})
}
);
const data = await res.json();
return data.access_token; // persist the new token
}
freee supports multiple companies per account, so nearly every endpoint requires a company_id query parameter. Skipping GET /api/1/companies at session start results in a cascade of 400 errors. Cache company_id in session state and attach it to every downstream call automatically.
Every amount field in freee's API is a Japanese yen integer. 1000 means ¥1,000. There are no decimal values. If an LLM generates a decimal (e.g., 1000.50), round it to an integer before sending. Tax amounts are stored separately as integers in their own fields.
Calling GET /deals without a date range can pull thousands of records and trigger an 800ms+ latency spike or timeout. Fix: always pass start_date and end_date parameters with a 3-month window or less. KanseiLink's workaround reports confirm this resolves the issue.
5. Rate Limits & Mitigation
| Endpoint Type | Rate Limit | Recommended Mitigation |
|---|---|---|
| General endpoints | 3,600 requests/hour per access token | Distribute agent tasks across time. Use batch APIs for bulk operations |
| Wallet & Deal endpoints | 300 requests/5 minutes | Implement request queuing to stay under 300 per 5-minute window |
| Bulk Invoice v2 | Subject to general limit; processes multiple invoices per request | Batch as many invoices as possible per call to minimize total request count |
6. freee vs. MoneyForward Cloud
| Criterion | freee | MoneyForward Cloud |
|---|---|---|
| AEO Grade | AAA | AAA |
| Success Rate | observing | observing |
| Domain Coverage | 5 domains ✅ | Accounting, expenses, invoicing (primary) |
| Authentication | OAuth 2.0 PKCE | OAuth 2.0 |
| Target Market | Freelancers, micro-SMBs, sole proprietors | Mid-size to enterprise corporates |
| MCP Command | npx @freee/mcp-server | npx @moneyforward/mcp-server |
In practice, the choice is driven by the client's existing tool. freee dominates the freelancer and micro-SMB segment; MoneyForward is stronger in mid-to-large corporations. Match your MCP server to the tool your client already uses.
Conclusion — freee is AAA, but budget 30 minutes for OAuth setup
The freee MCP server is the only AAA-rated official MCP server covering all five Japanese business back-office domains in a single connection. The April 2026 Bulk Invoices API and Remote MCP additions make large-scale accounting automation agents increasingly practical.
The OAuth 2.0 PKCE setup and company_id preflight do raise the entry bar compared to API-key-only services. Use this article's 5-step auth guide and four pitfalls as your pre-flight checklist before implementation.
The current auth_expired spike (4× baseline) warrants immediate attention for any production freee agent. Verify token refresh logs even if your refresh logic is already implemented.
Access freee's Live AEO Score & Agent Voice Data
Real-time success rates, latency trends, error analytics, and raw agent feedback are available under the consulting plan.
Request Data Access