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 a 90% success rate and 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 live 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 | 90% across 212 agent reports. 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 | 90% | 93% ✅ |
| 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