freee を CLI から操作するツールと Agent Skill を作り、トークン効率を75%改善した
こんにちは、@yamitzkyです。
freee が公式に公開している MCP サーバーと Agent Skill freee/freee-mcp を fork して、freee CLIと、それを使う Agent Skill という構成に再構築したものを公開しました。
念の為記載しますが、あくまで非公式なフォークです。
使い方
freee CLI 単独でも、エージェントスキル経由でも使えます。
たとえば稟議申請一覧を取得する場合、
npx @yamitzky/freee accounting get approval_requests
# または
npm install -g @yamitzky/freee
freee accounting get approval_requests
Agent Skill 経由で、Claudeなどから取得する場合は、
npx skills add yamitzky/freee-cli
claude
# freeeの最新の稟議一覧を取得して
Why not freee MCP?
freee からは、公式の MCP(Model Context Protocol)サーバーと、それに対応する Agent Skill が公開されています。会計・人事労務・請求書・工数管理・販売の 5 つの API に対応しており、Claude などから freee の操作ができるようになっています。このような取り組みをオフィシャルに公開している点が非常に素晴らしいと思います。
ただ、以下3つの観点で、現状の MCP + Agent Skills というオフィシャルな設計に課題を感じています。いずれも、個別個別に見れば解決策はあるかもしれませんが...
トークン効率が悪い可能性
MCP サーバーは、ツール定義(ツール名・パラメータスキーマ)をエージェントのコンテキストに公開します。ツール定義だけでかなりのトークンを消費します。さらに、API レスポンスは JSON がそのままエージェントに返るため、大量のフィールドを含む freee API のレスポンスはコンテキストウィンドウを圧迫します。
権限設定の柔軟さの不足
Claude Code では、外部ツールの実行を permission wildcards で制御できます。たとえば以下の設定のように、特定パターンのコマンドだけを許可できます。
{
"permissions": {
"allow": [
"Bash(find:*)"
]
}
}
しかし現状の freee-mcp の場合、以下の7つのツールにまとめられています。
| ツール名 | HTTPメソッド | 必須パラメータ | オプションパラメータ | 説明 |
|---|---|---|---|---|
| freee_api_get | GET | service, path | query | データ取得 |
| freee_api_post | POST | service, path, body | query | データ作成 |
| freee_api_put | PUT | service, path, body | query | データ更新 |
| freee_api_delete | DELETE | service, path | query | データ削除 |
| freee_api_patch | PATCH | service, path, body | query | データ部分更新 |
| freee_api_list_paths | - | なし | なし | エンドポイント一覧表示 |
| freee_file_upload | POST | file_path | description, partner_name, issue_date, amount, qualified_invoice, document_type | ファイルボックスにアップロード |
そのため、「経費精算はAIが自動でやっていいけど、支払い依頼はダメ」といったような権限指定ができないのではと思います
ツールとしてのポータビリティ不足
MCP は、Claude Code のような AI が使うには使いやすい仕組みです。
ですが、シェルスクリプトから使いたい、AI 以外で自動化・定期タスクにしたい、といったモチベーションがある場合には使いづらい仕組みで、結局 API を直接扱う必要が出てきてしまいます。認証の仕組みの理解も必要になってしまいます。
CLI + Agent Skill という選択肢
おそらくは似たような課題感だと思いますが、最近では CLI + スキルという構成で作られたAgent Skills が出てきています。
例えば Notion からは元々 MCP が公開されていましたが、記事執筆の5日前に makenotion/skills が公開されました。これは ntn という CLI と、87行程度の SKILL.md という構成です。
記事執筆の17日前に公開された、Google Workspace の公式 CLI googleworkspace/cli も(こちらは細かく SKILL.md が別れていますが) 似たような構成です。
今回作った、yamitzky/freee-cli も似たような構成になっています。
- Skill(SKILL.md): CLI の使い方を51行の SKILL.md で記述。エージェントのコンテキストに最小限の情報だけを注入する
- CLI(
freeeコマンド): 実際の API 呼び出しは CLI 経由で行う。--help,--specで API 仕様をオンデマンドで取得できる
この設計の肝は、API スキーマ全体をエージェントのコンテキストに載せないことです。必要な情報は CLI の自己文書化コマンドでその都度取得する。これにより初期コンテキストが軽くなり、トークン消費を大幅に削減できます。
実装のポイント
コマンド体系と権限制御
コマンド体系を freee <service> <method> <path> に設計しました。これは ntn CLI と gogcli を参考にしました。
freee accounting get deals # 取引一覧を取得
freee accounting post deals key=val # 取引を作成
freee hr get employees # 従業員一覧を取得
service は accounting, hr, invoice, pm, sm の 5 つに対応しています。
この設計により、Claude Code の permission wildcards で細かい制御が可能になります:
freee accounting get:* → 会計の参照系を自動許可
freee accounting post:* → 会計の作成系は都度確認
freee hr:* → 人事労務系はすべて都度確認
コンパクト出力
MCP では API レスポンスの JSON がそのままエージェントに渡されますが、CLI ではコンパクトなテーブル形式(TSV)に変換して出力します。
# MCP(JSON そのまま)
{"deals": [{"id": 1, "company_id": 12345, "issue_date": "2025-01-15", "type": "income", "ref_number": "", "status": "settled", ...(数十フィールド)}, ...]}
# CLI(テーブル出力)
id issue_date type amount partner
1 2025-01-15 income 100000 株式会社A
2 2025-01-20 expense 50000 株式会社B
これにより、同じ情報を得るのに消費するトークン数が減ることが期待できます。必要に応じて --json フラグで生の JSON を取得することもできます。
セルフドキュメント
CLI 自身が API ドキュメントを持っているため、エージェントは必要に応じて仕様を確認できます。
freee accounting ls # エンドポイント一覧
freee accounting ls deals # キーワードで絞り込み
freee accounting get deals --help # コンパクトな CLI のヘルプ
freee accounting get deals --spec # 生の OpenAPI フラグメント
エージェントは最初にすべての API 仕様を読み込む必要はなく、必要なエンドポイントの仕様だけをその都度取得できます。
例えば ls コマンドでは、以下のように絞り込んだコマンド一覧が出力されます。
❯ freee accounting ls deal
RESOURCE OPERATIONS
deals get(取引(収入・支出)取得) | post(取引(収入・支出)の作成)
deals/{id} get(取引(収入・支出)の取得) | put(取引(収入・支出)の更新) | delete(取引(収入・支出)の削除)
deals/{id}/payments post(取引(収入・支出)の支払行の作成)
deals/{id}/payments/{payment_id} put(取引(収入・支出)の支払行の更新) | delete(取引(収入・支出)の支払行の削除)
deals/{id}/renews post(取引(収入・支出)の+更新の作成)
deals/{id}/renews/{renew_id} put(取引(収入・支出)の+更新の更新) | delete(取引(収入・支出)の+更新の削除)
--help をつけると OpenAPI の定義を元にして、以下のように出力されます。元となった OpenAPI にはレスポンスのスキーマもありますが、AI にはいらないのではという判断から削っています。
❯ freee accounting get deals --help
freee accounting get deals
取引(収入・支出)一覧の取得
使い方:
freee accounting get deals
freee accounting get deals partner_id==... account_item_id==...
パラメータ:
company_id 事業所ID(デフォルト: 現在の事業所)
partner_id 取引先IDで絞込
account_item_id 勘定科目IDで絞込
partner_code 取引先コードで絞込
status 決済状況で絞込 (未決済: unsettled, 完了: settled)
type 収支区分 (収入: income, 支出: expense)
start_issue_date 発生日で絞込:開始日(yyyy-mm-dd)
end_issue_date 発生日で絞込:終了日(yyyy-mm-dd)
start_due_date 支払期日で絞込:開始日(yyyy-mm-dd)
end_due_date 支払期日で絞込:終了日(yyyy-mm-dd)
start_renew_date +更新日で絞込:開始日(yyyy-mm-dd)
end_renew_date +更新日で絞込:終了日(yyyy-mm-dd)
offset 取得レコードのオフセット (デフォルト: 0)
limit 取得レコードの件数 (デフォルト: 20, 最大: 100)
accruals 取引の債権債務行の表示(without: 表示しない(デフォルト), with: 表示する)
トークン消費の比較
同じ操作「(会社のメールアドレス)が2026年3月に提出した支払い依頼一覧を出して」という指示、MCP 版と CLI 版で実行し、Claude Code のセッショントークン消費を比較しました。
| MCP 版 | CLI 版 | |
|---|---|---|
| トークン消費 | 38,137 | 27,500 |
| 削減率 | - | -27.9% |
約 28% のトークン削減が確認できました。「1+1は?」と聞くだけでも23,930 tokensは消費されるので(必ず消費されるトークン数)、そこと比較すると、75%ほどのトークン削減になっています。
とはいえ、より現実的/実践的なシナリオ(〜で稟議申請して、など)で検証できているわけではありません。
なぜ差が出るのか
MCP 版のツール呼び出し(6ステップ)は、
- Skill ロード
-
freee_get_current_company(MCP ツール)で事業所取得 - references ディレクトリを検索
-
accounting-payment-requests.mdを80行読み込み -
freee_api_getで users 取得 → JSON 全量(約20フィールド x 34人) -
freee_api_getで payment_requests 取得 → JSON 全量(約20フィールド x 6件)
CLI 版のツール呼び出し(4ステップ)は、
- Skill ロード
-
freee accounting docs payment_requests→ コンパクトなパラメータ一覧 -
freee accounting get users→ テーブル出力(6フィールド x 10件 + 残件数) -
freee accounting get payment_requests ...→ テーブル出力(6フィールド x 6件)
でした。主な差分のポイントとしては、
- references ファイルの読み込みが不要(CLI の
docsコマンドで代替) - company_id の自動注入により
freee_get_current_companyが不要 - レスポンスがコンパクトテーブル形式(トップレベルのスカラーフィールドのみ、デフォルト10件)
- MCP のツール定義スキーマがコンテキストに載らない
などが上げられます。SKILL.md 内での指示の違いなどもあるため、必ずしもアーキテクチャの差分(MCP+Skill→CLI+Skill)とは言えないことに注意してください。あくまで簡易的な検証をしているに過ぎないです。
ライセンスについて
今回作ったリポジトリに関しては、
freee K.K. による freee/freee-mcp のコードが含まれており、当該コードは Apache License 2.0 に基づいて提供されています。法令上許容される限りにおいて、私がこのフォークに加えた独自の変更および追加部分については、著作権が発生するとは考えておらず、CC0 1.0 に基づき、著作権その他の関連する権利を放棄します。
という記載をしています。
これは「freee-mcpおよびAPI仕様書の貢献がソースコードの大部分を占めており、それをCLI化した程度の私の変更については、私は著作権があるとも考えていないし、それを主張もしない」ということです。API利用規約に従って正しく使ってください。
現状と今後の展望
今のところは、稟議一覧の取得や、稟議申請など、一部のユースケースしか検証していません。そもそも、私が業務で使っていない freee 会計以外はテストしてすらいないです。
とはいえ、あまり長期的にメンテしたいと考えてはいません。非公式なツールであるということは、利用者にとってもリスクがあると感じることでしょう。
今回作った CLI+Agent Skills 構成が合理的なものであれば、freee-mcp 本体で対応してくれたらいいな...
Discussion