mcpField
F
freshbooks-mcp

freshbooks-mcp

ローカル
github.com/chrischall金融データ02 日前に更新

freshbooks-mcp について

Claude から FreshBooks の会計データを参照・操作するための MCP サーバーです。請求書や顧客、経費、作業時間を扱い、書き込みには確認を求め、ローカルの OAuth トークンを非公開で保存します。

主な機能

  1. 01請求書、顧客、見積もり、支払いの参照
  2. 02会計レコードの作成と更新
  3. 03経費とプロジェクト作業時間の記録
  4. 04書き込み前の確認
  5. 05更新される OAuth トークンのローカル保存

活用シーン

  1. 01請求書や支払いの詳細確認
  2. 02承認後の請求書作成
  3. 03経費やプロジェクト作業時間の記録

MCP 対応

FreshBooks のデータと操作を、MCP クライアント向けの型付きツールとして公開します。書き込みツールは、クライアントの対応状況に応じて確認プロンプトまたはプレビューとトークンを使います。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"chrischall-freshbooks": {
"command": "npx",
"args": [
"-y",
"@chrischall/freshbooks-mcp"
],
"env": {
"FRESHBOOKS_CLIENT_ID": "<FRESHBOOKS_CLIENT_ID>",
"FRESHBOOKS_CLIENT_SECRET": "<FRESHBOOKS_CLIENT_SECRET>",
"FRESHBOOKS_REFRESH_TOKEN": "<FRESHBOOKS_REFRESH_TOKEN>",
"FRESHBOOKS_REDIRECT_URI": "<FRESHBOOKS_REDIRECT_URI>",
"FRESHBOOKS_TOKEN_STORE": "<FRESHBOOKS_TOKEN_STORE>",
"FRESHBOOKS_BUSINESS_ID": "<FRESHBOOKS_BUSINESS_ID>",
"FRESHBOOKS_ACCOUNT_ID": "<FRESHBOOKS_ACCOUNT_ID>",
"FRESHBOOKS_REQUEST_TIMEOUT_MS": "<FRESHBOOKS_REQUEST_TIMEOUT_MS>"
}
}
}
}
起動コマンドnpx -y @chrischall/freshbooks-mcp
設定が必要な環境変数
FRESHBOOKS_CLIENT_IDOAuth client ID from my.freshbooks.com/#/developer
FRESHBOOKS_CLIENT_SECRETシークレットOAuth client secret
FRESHBOOKS_REFRESH_TOKENシークレットOptional for local sign-in, which saves tokens privately. Required for hosted or legacy environment-token setup.
FRESHBOOKS_REDIRECT_URIRegistered redirect URI; required on refresh calls too (default https://localhost)
FRESHBOOKS_TOKEN_STOREシークレットPath for the rotating-refresh-token store (default ~/.freshbooks-mcp/session.json)
FRESHBOOKS_BUSINESS_IDThe integer businessId to work in when the authenticated identity belongs to several businesses. Without it, reads use the first business FreshBooks lists and writes are refused rather than landing in the wrong books.
FRESHBOOKS_ACCOUNT_IDOverrides the account id normally resolved from /auth/api/v1/users/me. Set it explicitly when the authenticated identity belongs to no business membership and resolution fails, or, together with FRESHBOOKS_BUSINESS_ID, when FreshBooks reports no account_id for the chosen business (accounting writes are refused until the pairing is confirmed this way).
FRESHBOOKS_REQUEST_TIMEOUT_MSPer-request deadline for API calls, in milliseconds (default 30000)

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npm@chrischall/freshbooks-mcp1.2.2

ツール

34

掲載時のツール一覧 · 2 週間前に更新

このツールにパラメーターはありません。

詳細

freshbooks-mcp

FreshBooks 向け MCP サーバーです。請求書、クライアント、見積もり、支払いを型付きツールとして Claude に公開します。

このプロジェクトは AI(Claude Code)が開発し、保守しています。ご自身の判断でご利用ください。

インストール

npm install -g @chrischall/freshbooks-mcp

セットアップ

FreshBooks は OAuth2 のみに対応しています。API キーや個人用アクセストークンはないため、ブラウザーで一度だけ認可する必要があります。

  1. https://my.freshbooks.com/#/developer でアプリを登録します。リダイレクト URI はクエリ文字列のない HTTPSである必要があります。https://localhost が使用でき、名前解決の必要はありません。
  2. クライアント IDとクライアントシークレットを控えます。
  3. 一度だけ認可を完了します。
    • サーバー自体から(スクリプトなし): FRESHBOOKS_CLIENT_ID と FRESHBOOKS_CLIENT_SECRET を設定してサーバーを起動し、freshbooks_auth_url を呼び出します。返された URL を開いて認可したら、移動先の URL 全体を freshbooks_auth_exchange に渡します。その state は、サーバーが発行した同意 URL と一致する必要があります(有効期間は 15 分で、1 回のみ使用可能です)。そのため、コードだけの場合や、他の人の認可によるリダイレクト URL は、コードが使用される前に拒否されます。ローカルセッションではトークンが FRESHBOOKS_TOKEN_STORE に直接保存され、成功メッセージのみが返されます。そのメッセージが表示されたら、ローカル MCP サーバーを再起動してください。トークンをチャットや設定にコピーする必要はありません。再起動後も同じアプリの認証情報と保存先を使用してください。
    • ホスト型接続: mcp-host の authFlow は引き続き交換レスポンスからリフレッシュトークンを取得し、シークレットストアを通じて提供します。MCP_DATA_DIR はこのホスト環境を識別します。ローカルのコーディングエージェント接続では設定しないでください。ホストモードでは意図的にトークンが返されます。発行済みの state は MCP_DATA_DIR の下にダイジェストとして保存されるため、利用者が認可している間に子プロセスが再起動してもログインを完了できます。**登録のフローでは、利用者に freshbooks_auth_url が返す authorize_url を表示する必要があります。**この URL には一度だけ使用できる state が含まれており、交換処理では state のないリダイレクトは拒否されます。ステップの説明に静的な同意リンクを記載しても state がないため、それを経由する新しいログインや再設定はすべて失敗します。freshbooks_auth_url ステップの authorize_url を引き継ぎ、プロンプトを表示するステップでステップリンク(link: {from: 'authorize_url', hosts: ['auth.freshbooks.com']}、mcp-host 2.30.0 以降)を使って表示してください。そのプロンプトでは、コードだけでなくリダイレクト URL 全体を入力してもらう必要があります。state チェックを含むリリースがホストの固定バージョンに到達する前に、この変更を行ってください。既存の接続では引き続きトークンを更新できます。影響するのは新しいログインと再設定のみです。
    • 従来の手動セットアップ: skills/freshbooks-curl のスクリプトはトークンを表示します。必ずプライベートなターミナルで実行し、エージェントが内容を取得するターミナルでは実行しないでください。
  4. 設定します。
FRESHBOOKS_CLIENT_ID=...
FRESHBOOKS_CLIENT_SECRET=...
FRESHBOOKS_REFRESH_TOKEN=...       # optional locally; if set during reauth, keep it set
FRESHBOOKS_REDIRECT_URI=https://localhost   # optional; must match what you registered
FRESHBOOKS_TOKEN_STORE=~/.freshbooks-mcp/session.json   # optional
FRESHBOOKS_BUSINESS_ID=...         # optional; required for writes if you belong to several businesses
FRESHBOOKS_ACCOUNT_ID=...          # optional; with FRESHBOOKS_BUSINESS_ID, confirms its accountId when FreshBooks omits it
FRESHBOOKS_REQUEST_TIMEOUT_MS=30000  # optional; per-request deadline for API calls

Claude Desktop では、どちらも拡張機能の設定にある任意項目です。選択したビジネスについて FreshBooks から account_id が返されない場合、両方の ID を手動で設定するまで、請求書と経費の書き込みは拒否されます(プロジェクトとタイムエントリーは引き続き利用できます)。

⚠️ リフレッシュトークンはローテーションされます

FreshBooks は、リフレッシュのたびに新しいリフレッシュトークンを発行し、古いトークンをただちに無効化します。このサーバーは、リフレッシュが完了したとみなされる前に、ローテーションのたびに FRESHBOOKS_TOKEN_STORE(モード 0600)へ保存します。また、環境変数の値より保存済みのトークンを優先します。保存済みのトークンのほうが新しいためです。

ログインフローでは、保留中の同意 state ダイジェストを記録する小さなファイルも書き込みます(モード 0600、エントリーの有効期限は15分)。ローカルではトークンストアと同じ場所にあり、<FRESHBOOKS_TOKEN_STORE>.oauth-state.json(デフォルトでは ~/.freshbooks-mcp/session.json.oauth-state.json)です。ホスト環境では $MCP_DATA_DIR/freshbooks-oauth-state.json です。このファイルは、ログインが最後まで完了しなくても、最初の freshbooks_auth_url 呼び出し時に作成されます。トークンは含まれません。

知っておくべき点が2つあります。

  • 2つのツールを同じストアに向けないでください。 MCP サーバーと freshbooks-curl スキルは、意図的に別々の状態ファイルを使用します。共有すると、互いのトークンを消費し、両方がロックアウトされます。
  • ストアを失った場合は、ブートストラップをやり直してください。 使用済みのリフレッシュトークンは復元できません。

環境トークンを使わずにローカルでサインインすると、プライベートストアはアプリのクライアント ID、シークレット、リダイレクト URI に紐づきます。これらを変更するには、新たにサインインする必要があります。既存の環境トークン設定では、引き続き保存済みのローテーション済みトークンが優先されます。FRESHBOOKS_REFRESH_TOKEN を新しい値に変更すると、新しいトークンチェーンが開始されます。FRESHBOOKS_REFRESH_TOKEN を設定した状態でローカル認可をやり直す場合は、同じ値を設定したままにしてください。保存されるログインはその値に紐づきます。この変数を削除するには、まず設定を解除してからローカルで再度サインインし、ストアをアプリに紐づけてください。ローカルでの認可コード交換と保存には、リフレッシュと同じロックを使用します。リフレッシュによる書き込みはロックを保持している間に限られるため、ロックを解放した後に新しいログインを上書きすることはありません。 再認可後は、そのストアを使うすべてのローカルサーバーを再起動してください。

ツール

ツール用途
freshbooks_get_identityaccountId / businessId / businessUuid を特定します
freshbooks_auth_urlこの接続を認証するための同意 URL を取得します
freshbooks_auth_exchange認証を完了します。ローカルセッションにトークンを非公開で保存するか、ホスト型認証フローにリフレッシュトークンを返します
freshbooks_healthcheckOAuth 認証情報と FreshBooks への接続を確認します。「認証情報なし」「拒否」「FreshBooks の停止」を区別します
freshbooks_list_invoices / freshbooks_get_invoice請求書を閲覧・取得します
freshbooks_list_clients / freshbooks_get_clientクライアントを閲覧・取得します
freshbooks_list_estimates / freshbooks_get_estimate見積もりを閲覧・取得します
freshbooks_list_payments / freshbooks_get_payment支払いを閲覧・取得します
freshbooks_list_items / freshbooks_get_itemカタログ項目を閲覧・取得します
freshbooks_create_clientクライアントを作成します — 確認が必要です
freshbooks_create_invoice請求書を作成します — 確認が必要です
freshbooks_update_invoice請求書を更新します — 確認が必要です
freshbooks_record_payment請求書に対する支払いを記録します — 確認が必要です
freshbooks_accept_estimate見積もりを承認します(action_accept)— 確認が必要です。冪等です
freshbooks_update_estimate見積もりの明細、メモ、条件、表示内容を更新します — 確認が必要です
freshbooks_send_estimate見積もりをクライアントにメールで送信します(action_email)— 確認が必要です
freshbooks_decline_estimate常に失敗します。FreshBooks には見積もりを辞退する機能がありません。代替案を提示します
freshbooks_list_expenses / freshbooks_get_expense経費を閲覧・取得します
freshbooks_list_expense_categories新しい経費の categoryid に使用するカテゴリを取得します
freshbooks_create_expense経費を記録します — 確認が必要です
freshbooks_list_projects / freshbooks_get_projectプロジェクト(businessId をキーとして使用)
freshbooks_create_projectプロジェクトを作成します — 確認が必要です
freshbooks_list_time_entries記録済み時間。total_logged / total_unbilled を含みます
freshbooks_create_time_entry秒単位で時間を記録します — 確認が必要です
freshbooks_list_servicesプロジェクトや時間記録に対する請求可能な作業種別
freshbooks_list_records / freshbooks_get_record会計関連の幅広いデータ(税金、クレジットノート、請求書プロファイル、タスク、スタッフ、決済ゲートウェイ、請求書、請求書の仕入先、請求書の支払い、その他の収入)にアクセスする汎用ツール

確認が必要とは、書き込みを行う前にツールが確認を求めることを意味します。確認プロンプトを表示できるクライアント(Claude Code)では、送信される内容を正確に示す確認プロンプトが表示されます。それ以外(claude.ai、Claude Desktop)では、最初の呼び出しではネットワークリクエストを行わず、送信されるメソッド、パス、本文のプレビューと、1 回限りの confirmToken を返します。このトークンと同じ引数を指定して再度呼び出した場合にのみ、書き込みが実行されます。プレビュー後に引数が変更された場合(DRAFT_CHANGED)、すでに使用済みの場合(TOKEN_REUSED)、または有効期限が切れた場合、トークンは拒否されます。

確認
変数デフォルト
MCP_CONFIRM_MODEask-user確認プロンプトを表示できないクライアント(claude.ai、Claude Desktop)で、書き込みをどう扱うかを指定します。ask-user:2段階で処理します。最初の呼び出しでは何も実行せず、プレビューとトークンを返します。その後、モデルはチャットでユーザーの承認を得てから、トークンを付けて再度呼び出す必要があります。auto:同じく2段階で処理しますが、モデルはプレビューを自ら確認した後、トークンを使用できます。refuse:そのようなクライアントでは書き込みを拒否します。プロンプトを表示できるクライアント(Claude Code)には、MCP_CONFIRM_ELICITATION=off でない限り、常に実際のプロンプトが表示されます。認識されない値は refuse として扱われます。
MCP_CONFIRM_ELICITATIONonoff にすると確認プロンプトは表示されず、すべてのクライアントに MCP_CONFIRM_MODE の動作が適用されます。プロンプトを表示できると宣言しながら実際には表示しないクライアント(書き込みがハングする opencode 2.0.x)に設定してください。それ以外の値は on として扱われ、stderr に警告が出力されます。
MCP_CONFIRM_TTL_SECONDS600トークンの有効期間です。
MCP_CONFIRM_SECRETプロセスごとにランダム署名キーです。トークンをサーバーの再起動後も有効にする必要がある場合にのみ設定してください。
見積もりへの書き込み

承認は見積もりに対するアクションであり、ステータスフィールドではありません。status(int)、display_status、ui_status は計算値で読み取り専用です。また、意図的に互いに異なる値になります(閲覧済みの見積もりでは status: 3、display_status: "viewed"、ui_status: "open" となります)。承認するには、{"estimate": {"action_accept": true}} を指定して PUT estimates/estimates/{id} を実行します。この形式の由来については、docs/FRESHBOOKS-API.md を参照してください。

  • 承認は冪等です。 すでに承認済み(または請求書発行済み)の見積もりは changed: false とともに返され、書き込みは送信されません。API では承認を取り消せないため、再度呼び出しても承認処理を再実行してはなりません。
  • 却下する方法はありません。 FreshBooks の見積もりステータスは、下書き/送信済み/閲覧済み/返信済み/承認済み/請求書発行済みです。却下状態も、action_deny も、estimate.decline webhook もありません。freshbooks_decline_estimate は、何も変更しない書き込みをエージェントがでっち上げないよう、却下できないことを伝えて代替手段を示すためだけに存在します。
  • すべての書き込みは、再取得した見積もりと before/after の状態、および changed/changedFields を返します。 成功は 200 から推測するのではなく、レコードと照合して検証されます。changed はステータスフィールドに加え、書き込みで実際に設定されたフィールドも対象とするため、ステータスに変化がなくても、メモの編集が成功すれば changed: true になります。freshbooks_send_estimate ではレコードの状態のみを示します。送信済みの見積もりをメールで再送しても状態は変わらず、changed: false の場合に再試行すると、クライアントに同じ内容をもう一度送ることになります。

書き込みにはオーナーまたは管理者の会計アカウントが必要です

FreshBooks では、ビジネスでのロールと、会計アカウントでのロールは別々に管理されています。会計アカウントを持たないビジネス(account_id: null)を所有しながら、実際に表示できるアカウントではクライアントにすぎない場合があります。この場合、読み取りは成功しますが、OAuth トークンにすべての :write スコープが含まれていても、すべての書き込みが 403 Permission Denied を返します。

freshbooks_get_identity は accountRole と businessRole を報告するため、この状況を事前に確認できます。accountRole が client の場合、そのアカウントでは請求関連の書き込みツールは機能しません。これはアカウント権限の問題であり、設定の問題ではありません。

API が誤解を招く形で報告する2つのこと
  • total は、読み取れない場合があるレコードも数えます。 経費の取得では total: 16 と報告されましたが、返された行は0件でした。このような場合、リスト結果には note が付加されるため、アカウントが空なのではなく、権限の境界があると分かります。
  • プロジェクトと時間追跡は accountId ではなく businessId をキーとしており、フラットな page/pages/total ではなく meta ブロックを使ってページネーションします。 これらは、会計アカウントがまったくないビジネスでも利用できます。

3種類の識別子

FreshBooks では互換性のない3種類の ID が発行されます。誤った ID を使うと、レコードが見つからないように見える 404 がそのまま返されます。

識別子使用先
accountId(英数字)/accounting/account/…、/payments/account/…
businessId(整数)/projects/business/…、/timetracking/business/…
businessUuid(UUID)/accounting/businesses/…

まず freshbooks_get_identity を呼び出してください。4種類の異なるエラー形式を含む API の詳しい説明は、docs/FRESHBOOKS-API.md にあります。

サーバーを使わないシェルアクセス

skills/freshbooks-curl では、OAuth の初期設定やローテーションに安全なトークン処理を含め、curl + jq を使ってシェルから同じ API を利用する方法を説明しています。

開発

npm install
npm run build
npm test

ライセンス

MIT

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。