@him0/freee-mcp 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,15 +6,15 @@ MCP サーバー(API 呼び出し機能)と skill(API リファレンス
6
6
 
7
7
  [![npm version](https://badge.fury.io/js/@him0%2Ffreee-mcp.svg)](https://www.npmjs.com/package/@him0/freee-mcp)
8
8
 
9
- > **Note**: このプロジェクトは開発中であり、予期せぬ不具合が発生する可能性があります。問題を発見された場合は [Issue](https://github.com/him0/freee-mcp/issues) として報告していただけると幸いです。プルリクエストも歓迎しています。
9
+ > Note: このプロジェクトは開発中であり、予期せぬ不具合が発生する可能性があります。問題を発見された場合は [Issue](https://github.com/him0/freee-mcp/issues) として報告していただけると幸いです。プルリクエストも歓迎しています。
10
10
 
11
11
  ## 特徴
12
12
 
13
- - **MCP サーバー**: freee API を Claude Desktop / Claude Code から直接呼び出し
14
- - **Claude Plugin**: 詳細な API リファレンスドキュメント付きスキルを提供
15
- - **複数 API 対応**: 会計・人事労務・請求書・工数管理・販売の5つの freee API をサポート
16
- - **OAuth 2.0 + PKCE**: セキュアな認証フロー、トークン自動更新
17
- - **複数事業所対応**: 事業所の動的切り替えが可能
13
+ - MCP サーバー: freee API を Claude Desktop / Claude Code から直接呼び出し
14
+ - Claude Plugin: 詳細な API リファレンスドキュメント付きスキルを提供
15
+ - 複数 API 対応: 会計・人事労務・請求書・工数管理・販売の5つの freee API をサポート
16
+ - OAuth 2.0 + PKCE: セキュアな認証フロー、トークン自動更新
17
+ - 複数事業所対応: 事業所の動的切り替えが可能
18
18
 
19
19
  ## クイックスタート
20
20
 
@@ -22,8 +22,8 @@ MCP サーバー(API 呼び出し機能)と skill(API リファレンス
22
22
 
23
23
  [freee アプリストア](https://app.secure.freee.co.jp/developers) で新しいアプリを作成:
24
24
 
25
- - **コールバックURL**: `http://127.0.0.1:54321/callback`
26
- - **Client ID****Client Secret** を取得
25
+ - コールバックURL: `http://127.0.0.1:54321/callback`
26
+ - Client ID と Client Secret を取得
27
27
  - 必要な権限にチェック
28
28
 
29
29
  ### 2. セットアップ
@@ -55,7 +55,7 @@ npx @him0/freee-mcp configure
55
55
  }
56
56
  ```
57
57
 
58
- > **⚠️ 環境変数での設定について**
58
+ > ⚠️ 環境変数での設定について
59
59
  > 環境変数(`FREEE_CLIENT_ID`、`FREEE_CLIENT_SECRET` など)を使った設定は非推奨です。
60
60
  > 代わりに `npx @him0/freee-mcp configure` を実行して設定ファイルに移行してください。
61
61
  > 環境変数設定は将来のバージョンで削除される予定です。
@@ -85,9 +85,9 @@ Claude との会話中に API の使い方を質問すると、これらのリ
85
85
 
86
86
  請求書や経費精算など、同じ形式のデータを繰り返し作成する場合は、以前に作成したデータを参照することで効率的に作業できます:
87
87
 
88
- - **請求書作成**: 過去の請求書を取得して、取引先・品目・税区分などを参考にする
89
- - **経費精算**: 過去の申請を参照して、勘定科目や部門の指定を正確に行う
90
- - **取引登録**: 類似の取引を参考にして、入力ミスを防ぐ
88
+ - 請求書作成: 過去の請求書を取得して、取引先・品目・税区分などを参考にする
89
+ - 経費精算: 過去の申請を参照して、勘定科目や部門の指定を正確に行う
90
+ - 取引登録: 類似の取引を参考にして、入力ミスを防ぐ
91
91
 
92
92
  ```
93
93
  例: 「先月の○○社への請求書を参考に、今月分を作成して」
@@ -97,14 +97,15 @@ Claude との会話中に API の使い方を質問すると、これらのリ
97
97
 
98
98
  ### 管理ツール
99
99
 
100
- | ツール | 説明 |
101
- | ---------------------- | -------------------------- |
102
- | `freee_authenticate` | OAuth 認証を実行 |
103
- | `freee_auth_status` | 認証状態を確認 |
104
- | `freee_set_company` | 事業所を切り替え |
105
- | `freee_list_companies` | 事業所一覧を取得 |
106
- | `freee_help` | 使い方ガイド |
107
- | `freee_status` | 現在の状態と推奨アクション |
100
+ | ツール | 説明 |
101
+ | -------------------------- | ------------------ |
102
+ | `freee_authenticate` | OAuth 認証を実行 |
103
+ | `freee_auth_status` | 認証状態を確認 |
104
+ | `freee_clear_auth` | 認証情報をクリア |
105
+ | `freee_set_current_company`| 事業所を切り替え |
106
+ | `freee_get_current_company`| 現在の事業所を表示 |
107
+ | `freee_list_companies` | 事業所一覧を取得 |
108
+ | `freee_current_user` | 現在のユーザー情報 |
108
109
 
109
110
  ### API ツール
110
111
 
@@ -121,6 +122,14 @@ HTTPメソッドごとのシンプルなツール構成:
121
122
 
122
123
  パスは OpenAPI スキーマに対して自動検証されます。
123
124
 
125
+ ### company_id の取り扱い
126
+
127
+ リクエスト(パラメータまたはボディ)に `company_id` を含める場合、現在の事業所と一致している必要があります。不一致の場合はエラーになります。
128
+
129
+ - 事業所の確認: `freee_get_current_company`
130
+ - 事業所の切り替え: `freee_set_company`
131
+ - company_id を含まない API(例: `/api/1/companies`)はそのまま実行可能
132
+
124
133
  ## 開発者向け
125
134
 
126
135
  ```bash
@@ -150,6 +159,12 @@ TypeScript / Model Context Protocol SDK / OAuth 2.0 + PKCE / Zod / esbuild
150
159
 
151
160
  ISC
152
161
 
162
+ ## コミュニティ
163
+
164
+ 質問や情報交換は Discord サーバーで行っています。お気軽にご参加ください。
165
+
166
+ - [Discord サーバー](https://discord.gg/fPA75nHp)
167
+
153
168
  ## 関連リンク
154
169
 
155
170
  - [freee API ドキュメント](https://developer.freee.co.jp/docs)
package/bin/cli.js CHANGED
@@ -1,27 +1,29 @@
1
1
  #! /usr/bin/env node
2
2
 
3
- var Fe=Object.defineProperty;var z=(t,e)=>()=>(t&&(e=t(t=0)),e);var fe=(t,e)=>{for(var n in e)Fe(t,n,{get:e[n],enumerable:!0})};import de from"path";import Oe from"os";function A(){return process.env.XDG_CONFIG_HOME?de.join(process.env.XDG_CONFIG_HOME,ge):de.join(Oe.homedir(),".config",ge)}var ge,T,M,N,b=z(()=>{"use strict";ge="freee-mcp";T=54321,M=300*1e3,N=384});var he={};fe(he,{getCompanyInfo:()=>x,getCompanyList:()=>Ne,getCurrentCompanyId:()=>E,getDownloadDir:()=>Y,loadFullConfig:()=>m,saveFullConfig:()=>_,setCurrentCompany:()=>W,setDownloadDir:()=>He});import G from"fs/promises";import me from"path";import Le from"os";function K(){return me.join(A(),"config.json")}async function Ue(){let t=me.dirname(K());await G.mkdir(t,{recursive:!0})}function je(t){return t!=null&&typeof t=="object"&&"defaultCompanyId"in t&&"currentCompanyId"in t&&"companies"in t&&!("clientId"in t)}function Me(t){return console.error("\u{1F4E6} \u53E4\u3044\u8A2D\u5B9A\u5F62\u5F0F\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002\u65B0\u3057\u3044\u5F62\u5F0F\u306B\u79FB\u884C\u3057\u307E\u3059..."),{clientId:void 0,clientSecret:void 0,callbackPort:void 0,defaultCompanyId:t.defaultCompanyId,currentCompanyId:t.currentCompanyId,companies:t.companies}}async function m(){let t=K();try{let e=await G.readFile(t,"utf8"),n=JSON.parse(e);if(je(n)){let r=Me(n);return await _(r),r}return n}catch(e){if(e.code==="ENOENT"){let n=process.env.FREEE_DEFAULT_COMPANY_ID||"0",r={clientId:void 0,clientSecret:void 0,callbackPort:void 0,defaultCompanyId:n,currentCompanyId:n,companies:{[n]:{id:n,name:"Default Company",description:"Company from environment variable",addedAt:Date.now(),lastUsed:Date.now()}}};return await _(r),r}throw e}}async function _(t){await Ue();let e=K();await G.writeFile(e,JSON.stringify(t,null,2),{mode:N})}async function E(){return(await m()).currentCompanyId}async function W(t,e,n){let r=await m();r.companies[t]?(e||n)&&(e&&(r.companies[t].name=e),n&&(r.companies[t].description=n)):r.companies[t]={id:t,name:e||`Company ${t}`,description:n||void 0,addedAt:Date.now()},r.companies[t].lastUsed=Date.now(),r.currentCompanyId=t,await _(r)}async function Ne(){let t=await m();return Object.values(t.companies).sort((e,n)=>(n.lastUsed||0)-(e.lastUsed||0))}async function x(t){return(await m()).companies[t]||null}async function Y(){return(await m()).downloadDir||Le.tmpdir()}async function He(t){let e=await m();e.downloadDir=t,await _(e)}var P=z(()=>{"use strict";b()});var ye={};fe(ye,{config:()=>l,getConfig:()=>Je,loadConfig:()=>X});function Be(){return!!(process.env.FREEE_CLIENT_ID||process.env.FREEE_CLIENT_SECRET)}async function X(){if(w)return w;let t=await m(),e,n,r;if(Be())console.error("Warning: \u74B0\u5883\u5909\u6570\u3067\u306E\u8A8D\u8A3C\u60C5\u5831\u8A2D\u5B9A\u306F\u975E\u63A8\u5968\u3067\u3059\u3002"),console.error(" `freee-mcp configure` \u3092\u5B9F\u884C\u3057\u3066\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306B\u79FB\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"),console.error(` \u74B0\u5883\u5909\u6570\u8A2D\u5B9A\u306F\u5C06\u6765\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3067\u524A\u9664\u3055\u308C\u308B\u4E88\u5B9A\u3067\u3059\u3002
4
- `),e=process.env.FREEE_CLIENT_ID||"",n=process.env.FREEE_CLIENT_SECRET||"",r=process.env.FREEE_CALLBACK_PORT?parseInt(process.env.FREEE_CALLBACK_PORT,10):T;else{if(!t.clientId||!t.clientSecret)throw new Error("\u8A8D\u8A3C\u60C5\u5831\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\n`freee-mcp configure` \u3092\u5B9F\u884C\u3057\u3066\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3057\u3066\u304F\u3060\u3055\u3044\u3002");e=t.clientId,n=t.clientSecret,r=t.callbackPort||T}let o=process.env.FREEE_DEFAULT_COMPANY_ID||"0";return process.env.FREEE_DEFAULT_COMPANY_ID&&(console.error("Warning: FREEE_DEFAULT_COMPANY_ID \u74B0\u5883\u5909\u6570\u306F\u975E\u63A8\u5968\u3067\u3059\u3002"),console.error(" \u4E8B\u696D\u6240ID\u306F `freee_set_company` \u30C4\u30FC\u30EB\u3067\u52D5\u7684\u306B\u5909\u66F4\u3067\u304D\u307E\u3059\u3002\n")),w={freee:{clientId:e,clientSecret:n,companyId:o,apiUrl:"https://api.freee.co.jp"},oauth:{callbackPort:r,redirectUri:`http://127.0.0.1:${r}/callback`,authorizationEndpoint:"https://accounts.secure.freee.co.jp/public_api/authorize",tokenEndpoint:"https://accounts.secure.freee.co.jp/public_api/token",scope:"read write"},server:{name:"freee",version:"1.0.0"},auth:{timeoutMs:M}},w}function Je(){if(!w)throw new Error("Config not loaded. Call loadConfig() first.");return w}var w,l,h=z(()=>{"use strict";P();b();w=null;l=new Proxy({},{get(t,e){if(!w)throw new Error("Config not loaded. Call loadConfig() first in async context.");return w[e]}})});h();import{McpServer as st}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as ct}from"@modelcontextprotocol/sdk/server/stdio.js";h();import Ke from"http";import{URL as We}from"url";import Ye from"net";h();import ke from"crypto";h();b();import C from"fs/promises";import I from"path";async function y(t){return t.json().catch(()=>({}))}function Q(){return I.join(A(),"tokens.json")}async function H(t){let e=Q(),n=I.dirname(e);try{console.error(`[info] Creating directory: ${n}`),await C.mkdir(n,{recursive:!0}),console.error(`[info] Writing tokens to: ${e}`),await C.writeFile(e,JSON.stringify(t,null,2),{mode:N}),console.error("[info] Tokens saved successfully")}catch(r){throw console.error("[error] Failed to save tokens:",r),r}}async function Z(){let t=Q();try{let e=await C.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await qe();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function Ve(t){return Date.now()<t.expires_at}async function qe(){let t=A();try{let n=(await C.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));if(n.length>0){let r=I.join(t,n[0]),o=await C.readFile(r,"utf8"),i=JSON.parse(o);return await H(i),await Promise.all(n.map(a=>C.unlink(I.join(t,a)).catch(s=>{console.error(`[warn] Failed to clean up legacy token file ${a}:`,s)}))),console.error("[info] Migrated legacy company-specific tokens to user-based tokens"),i}}catch(e){console.error("[warn] Error during legacy token migration attempt:",e)}return null}async function ze(t){let e=await fetch(l.oauth.tokenEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:t,client_id:l.freee.clientId,client_secret:l.freee.clientSecret})});if(!e.ok){let o=await y(e);throw new Error(`Token refresh failed: ${e.status} ${JSON.stringify(o)}`)}let n=await e.json(),r={access_token:n.access_token,refresh_token:n.refresh_token||t,expires_at:Date.now()+n.expires_in*1e3,token_type:n.token_type||"Bearer",scope:n.scope||l.oauth.scope};return await H(r),r}async function Ce(){let t=Q();try{await C.unlink(t),console.error("[info] Tokens cleared successfully")}catch(e){if(e.code==="ENOENT"){console.error("[info] No tokens to clear (file does not exist)");return}throw console.error("[error] Failed to clear tokens:",e),e}await Ge()}async function Ge(){let t=A();try{let n=(await C.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));await Promise.all(n.map(r=>C.unlink(I.join(t,r)).catch(o=>{console.error(`[warn] Failed to clear legacy token file ${r}:`,o)}))),n.length>0&&console.error("[info] Cleared legacy company-specific token files")}catch(e){console.error("[warn] Error during legacy token cleanup:",e)}}async function we(){let t=await Z();if(!t)return null;if(Ve(t))return t.access_token;try{return(await ze(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function _e(){let t=ke.randomBytes(32).toString("base64url"),e=ke.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function B(t,e,n){let r=new URLSearchParams({response_type:"code",client_id:l.freee.clientId,redirect_uri:n,scope:l.oauth.scope,state:e,code_challenge:t,code_challenge_method:"S256"});return`${l.oauth.authorizationEndpoint}?${r.toString()}`}async function J(t,e,n){let r=await fetch(l.oauth.tokenEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:l.freee.clientId,client_secret:l.freee.clientSecret,code:t,redirect_uri:n,code_verifier:e})});if(!r.ok){let a=await y(r);throw new Error(`Token exchange failed: ${r.status} ${JSON.stringify(a)}`)}let o=await r.json(),i={access_token:o.access_token,refresh_token:o.refresh_token,expires_at:Date.now()+o.expires_in*1e3,token_type:o.token_type||"Bearer",scope:o.scope||l.oauth.scope};return await H(i),i}var ee=class{pendingAuthentications=new Map;cliAuthHandlers=new Map;registerAuthentication(e,n){console.error(`Registering authentication request with state: ${e.substring(0,10)}...`),console.error(`Code verifier: ${n.substring(0,10)}...`);let r=setTimeout(()=>{this.pendingAuthentications.delete(e),console.error(`Authentication timeout for state: ${e.substring(0,10)}...`)},l.auth.timeoutMs);this.pendingAuthentications.set(e,{codeVerifier:n,resolve:o=>{console.error("Authentication completed successfully!")},reject:o=>{console.error("Authentication failed:",o)},timeout:r}),console.error(`Registration complete. Total pending: ${this.pendingAuthentications.size}`)}getPendingAuthentication(e){return this.pendingAuthentications.get(e)}removePendingAuthentication(e){let n=this.pendingAuthentications.get(e);n&&(clearTimeout(n.timeout),this.pendingAuthentications.delete(e))}clearAllPending(){for(let[e,n]of this.pendingAuthentications)clearTimeout(n.timeout),n.reject(new Error("Server shutdown"));this.pendingAuthentications.clear()}get pendingCount(){return this.pendingAuthentications.size}registerCliAuthHandler(e,n){this.cliAuthHandlers.set(e,n)}getCliAuthHandler(e){return this.cliAuthHandlers.get(e)}removeCliAuthHandler(e){this.cliAuthHandlers.delete(e)}},te=class{server=null;port=null;authManager;constructor(e){this.authManager=e}getRedirectUri(){if(this.port===null)throw new Error("Callback server not started. Call start() first.");return`http://127.0.0.1:${this.port}/callback`}getPort(){return this.port}isRunning(){return this.server!==null}async start(){if(this.server)return;let e=l.oauth.callbackPort,n=await this.findAvailablePort(e);return this.port=n,n!==e&&console.error(`Warning: Port ${e} is in use. Using fallback port ${n} for OAuth callback server.`),new Promise((r,o)=>{this.server=Ke.createServer((i,a)=>{console.error(`Callback request: ${i.method} ${i.url}`);let s=new We(i.url,`http://127.0.0.1:${n}`);s.pathname==="/callback"?this.handleCallback(s,a):s.pathname==="/"?(a.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),a.end("<h1>freee MCP OAuth Server</h1><p>\u30B3\u30FC\u30EB\u30D0\u30C3\u30AF\u30B5\u30FC\u30D0\u30FC\u304C\u7A3C\u50CD\u4E2D\u3067\u3059\u3002</p>")):(a.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),a.end("<h1>404 Not Found</h1><p>\u3053\u306E\u30D1\u30B9\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002</p>"))}),this.server.on("error",i=>{console.error("Callback server error:",i),o(i)}),this.server.listen(n,"127.0.0.1",()=>{console.error(`OAuth callback server listening on http://127.0.0.1:${n}`),r()})})}stop(){this.server&&(this.authManager.clearAllPending(),this.server.close(()=>{console.error("OAuth callback server stopped")}),this.server=null,this.port=null)}async checkPortAvailable(e){return new Promise(n=>{let r=Ye.createServer();r.listen(e,"127.0.0.1",()=>{r.close(()=>{n(!0)})}),r.on("error",()=>{n(!1)})})}async findAvailablePort(e,n=50){for(let r=e;r<e+n;r++)if(await this.checkPortAvailable(r))return r;throw new Error(`No available port found after checking ${n} ports starting from ${e}`)}handleCallback(e,n){let r=e.searchParams.get("code"),o=e.searchParams.get("state"),i=e.searchParams.get("error"),a=e.searchParams.get("error_description");console.error(`Callback received - URL: ${e.toString()}`),console.error("Callback parameters:",{code:r?`${r.substring(0,10)}...`:null,state:o?`${o.substring(0,10)}...`:null,error:i,errorDescription:a}),console.error(`Pending authentications count: ${this.authManager.pendingCount}`);let s=o?this.authManager.getCliAuthHandler(o):void 0;if(i){let u=a||i;if(console.error(`OAuth error: ${i} - ${a}`),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end(`<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${u}</p>`),s)s.reject(new Error(`OAuth error: ${i} - ${a}`));else if(o){let k=this.authManager.getPendingAuthentication(o);k&&(clearTimeout(k.timeout),k.reject(new Error(`OAuth error: ${i} - ${a}`)),this.authManager.removePendingAuthentication(o))}return}if(!r||!o){console.error("Missing code or state"),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u8A8D\u8A3C\u30B3\u30FC\u30C9\u307E\u305F\u306F\u72B6\u614B\u30D1\u30E9\u30E1\u30FC\u30BF\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059\u3002</p>");return}if(s){console.error("Valid CLI callback received"),n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u5B8C\u4E86</h1><p>\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\u3002\u3053\u306E\u30DA\u30FC\u30B8\u3092\u9589\u3058\u3066\u30BF\u30FC\u30DF\u30CA\u30EB\u306B\u623B\u3063\u3066\u304F\u3060\u3055\u3044\u3002</p>"),s.resolve(r);return}let p=this.authManager.getPendingAuthentication(o);if(!p){console.error(`Unknown state: ${o}`),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u4E0D\u660E\u306A\u8A8D\u8A3C\u72B6\u614B\u3067\u3059\u3002\u8A8D\u8A3C\u3092\u518D\u958B\u3057\u3066\u304F\u3060\u3055\u3044\u3002</p>");return}console.error("Valid callback received, exchanging code for tokens..."),n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u5B8C\u4E86</h1><p>\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\u3002\u3053\u306E\u30DA\u30FC\u30B8\u3092\u9589\u3058\u3066\u304F\u3060\u3055\u3044\u3002</p>"),this.authManager.removePendingAuthentication(o),J(r,p.codeVerifier,this.getRedirectUri()).then(u=>{console.error("Token exchange successful!"),p.resolve(u)}).catch(u=>{console.error("Token exchange failed:",u),p.reject(u)})}},ne=new ee,re=new te(ne);function S(){return re.getRedirectUri()}async function V(){return re.start()}function Ee(t,e){ne.registerAuthentication(t,e)}function $(){re.stop()}function Ae(){return ne}h();import tt from"crypto";import{z as oe}from"zod";h();P();import Xe from"fs/promises";import Qe from"path";function Ze(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function et(t){let e={"application/pdf":".pdf","image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp","text/csv":".csv"};for(let[n,r]of Object.entries(e))if(t.includes(n))return r;return t.includes("image/"),".bin"}async function R(t,e,n,r,o){let i=o||l.freee.apiUrl,a=await E(),s=await we();if(!s)throw new Error(`\u8A8D\u8A3C\u304C\u5FC5\u8981\u3067\u3059\u3002freee_authenticate \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u8A8D\u8A3C\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
5
- \u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${a}
6
- \u307E\u305F\u306F\u3001FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let p=i.endsWith("/")?i:i+"/",u=e.startsWith("/")?e.slice(1):e,k=new URL(u,p);n&&Object.entries(n).forEach(([f,g])=>{g!==void 0&&k.searchParams.append(f,String(g))}),k.searchParams.append("company_id",String(a));let d=await fetch(k.toString(),{method:t,headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:r?JSON.stringify(typeof r=="string"?JSON.parse(r):r):void 0});if(d.status===401||d.status===403){let f=await y(d);throw new Error(`\u8A8D\u8A3C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002freee_authenticate \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u518D\u8A8D\u8A3C\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
7
- \u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${a}
8
- \u30A8\u30E9\u30FC\u8A73\u7D30: ${d.status} ${JSON.stringify(f)}
3
+ var Ke=Object.defineProperty;var ee=(t,e)=>()=>(t&&(e=t(t=0)),e);var ke=(t,e)=>{for(var n in e)Ke(t,n,{get:e[n],enumerable:!0})};import Ee from"path";import We from"os";function k(){return process.env.XDG_CONFIG_HOME?Ee.join(process.env.XDG_CONFIG_HOME,Ae):Ee.join(We.homedir(),".config",Ae)}var Ae,x,N,H,B,b=ee(()=>{"use strict";Ae="freee-mcp";x=54321,N=300*1e3,H=384,B="https://api.freee.co.jp"});var ve={};ke(ve,{getCompanyInfo:()=>S,getCurrentCompanyId:()=>w,getDownloadDir:()=>oe,loadFullConfig:()=>C,saveFullConfig:()=>E,setCurrentCompany:()=>re});import te from"fs/promises";import Pe from"path";import Xe from"os";function ne(){return Pe.join(k(),"config.json")}async function Qe(){let t=Pe.dirname(ne());await te.mkdir(t,{recursive:!0})}function Ye(t){return t!=null&&typeof t=="object"&&"defaultCompanyId"in t&&"currentCompanyId"in t&&"companies"in t&&!("clientId"in t)}function Ze(t){return console.error("\u{1F4E6} \u53E4\u3044\u8A2D\u5B9A\u5F62\u5F0F\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002\u65B0\u3057\u3044\u5F62\u5F0F\u306B\u79FB\u884C\u3057\u307E\u3059..."),{clientId:void 0,clientSecret:void 0,callbackPort:void 0,defaultCompanyId:t.defaultCompanyId,currentCompanyId:t.currentCompanyId,companies:t.companies}}async function C(){let t=ne();try{let e=await te.readFile(t,"utf8"),n=JSON.parse(e);if(Ye(n)){let r=Ze(n);return await E(r),r}return n}catch(e){if(e.code==="ENOENT"){let n={clientId:void 0,clientSecret:void 0,callbackPort:void 0,defaultCompanyId:"0",currentCompanyId:"0",companies:{}};return await E(n),n}throw e}}async function E(t){await Qe();let e=ne();await te.writeFile(e,JSON.stringify(t,null,2),{mode:H})}async function w(){return(await C()).currentCompanyId}async function re(t,e,n){let r=await C();r.companies[t]?(e||n)&&(e&&(r.companies[t].name=e),n&&(r.companies[t].description=n)):r.companies[t]={id:t,name:e||`Company ${t}`,description:n||void 0,addedAt:Date.now()},r.companies[t].lastUsed=Date.now(),r.currentCompanyId=t,await E(r)}async function S(t){return(await C()).companies[t]||null}async function oe(){return(await C()).downloadDir||Xe.tmpdir()}var A=ee(()=>{"use strict";b()});var Te={};ke(Te,{config:()=>l,loadConfig:()=>ie});function et(){return!!(process.env.FREEE_CLIENT_ID||process.env.FREEE_CLIENT_SECRET)}async function ie(){if(P)return P;let t=await C(),e,n,r;if(et())console.error("Warning: \u74B0\u5883\u5909\u6570\u3067\u306E\u8A8D\u8A3C\u60C5\u5831\u8A2D\u5B9A\u306F\u975E\u63A8\u5968\u3067\u3059\u3002"),console.error(" `freee-mcp configure` \u3092\u5B9F\u884C\u3057\u3066\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306B\u79FB\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"),console.error(` \u74B0\u5883\u5909\u6570\u8A2D\u5B9A\u306F\u5C06\u6765\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3067\u524A\u9664\u3055\u308C\u308B\u4E88\u5B9A\u3067\u3059\u3002
4
+ `),e=process.env.FREEE_CLIENT_ID||"",n=process.env.FREEE_CLIENT_SECRET||"",r=process.env.FREEE_CALLBACK_PORT?parseInt(process.env.FREEE_CALLBACK_PORT,10):x;else{if(!t.clientId||!t.clientSecret)throw new Error("\u8A8D\u8A3C\u60C5\u5831\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\n`freee-mcp configure` \u3092\u5B9F\u884C\u3057\u3066\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3057\u3066\u304F\u3060\u3055\u3044\u3002");e=t.clientId,n=t.clientSecret,r=t.callbackPort||x}return P={freee:{clientId:e,clientSecret:n,companyId:"0",apiUrl:B},oauth:{callbackPort:r,redirectUri:`http://127.0.0.1:${r}/callback`,authorizationEndpoint:"https://accounts.secure.freee.co.jp/public_api/authorize",tokenEndpoint:"https://accounts.secure.freee.co.jp/public_api/token",scope:"read write"},server:{name:"freee",version:"1.0.0"},auth:{timeoutMs:N}},P}var P,l,y=ee(()=>{"use strict";A();b();P=null;l=new Proxy({},{get(t,e){if(!P)throw new Error("Config not loaded. Call loadConfig() first in async context.");return P[e]}})});y();import{McpServer as wt}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as _t}from"@modelcontextprotocol/sdk/server/stdio.js";y();import it from"http";import{URL as at}from"url";import st from"net";y();import Se from"crypto";y();b();import h from"fs/promises";import I from"path";async function m(t){return t.json().catch(()=>({}))}function ae(){return I.join(k(),"tokens.json")}async function J(t){let e=ae(),n=I.dirname(e);try{console.error(`[info] Creating directory: ${n}`),await h.mkdir(n,{recursive:!0}),console.error(`[info] Writing tokens to: ${e}`),await h.writeFile(e,JSON.stringify(t,null,2),{mode:H}),console.error("[info] Tokens saved successfully")}catch(r){throw console.error("[error] Failed to save tokens:",r),r}}async function se(){let t=ae();try{let e=await h.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await nt();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function tt(t){return Date.now()<t.expires_at}async function nt(){let t=k();try{let n=(await h.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));if(n.length>0){let r=I.join(t,n[0]),o=await h.readFile(r,"utf8"),a=JSON.parse(o);return await J(a),await Promise.all(n.map(i=>h.unlink(I.join(t,i)).catch(c=>{console.error(`[warn] Failed to clean up legacy token file ${i}:`,c)}))),console.error("[info] Migrated legacy company-specific tokens to user-based tokens"),a}}catch(e){console.error("[warn] Error during legacy token migration attempt:",e)}return null}async function rt(t){let e=await fetch(l.oauth.tokenEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:t,client_id:l.freee.clientId,client_secret:l.freee.clientSecret})});if(!e.ok){let o=await m(e);throw new Error(`Token refresh failed: ${e.status} ${JSON.stringify(o)}`)}let n=await e.json(),r={access_token:n.access_token,refresh_token:n.refresh_token||t,expires_at:Date.now()+n.expires_in*1e3,token_type:n.token_type||"Bearer",scope:n.scope||l.oauth.scope};return await J(r),r}async function xe(){let t=ae();try{await h.unlink(t),console.error("[info] Tokens cleared successfully")}catch(e){if(e.code==="ENOENT"){console.error("[info] No tokens to clear (file does not exist)");return}throw console.error("[error] Failed to clear tokens:",e),e}await ot()}async function ot(){let t=k();try{let n=(await h.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));await Promise.all(n.map(r=>h.unlink(I.join(t,r)).catch(o=>{console.error(`[warn] Failed to clear legacy token file ${r}:`,o)}))),n.length>0&&console.error("[info] Cleared legacy company-specific token files")}catch(e){console.error("[warn] Error during legacy token cleanup:",e)}}async function be(){let t=await se();if(!t)return null;if(tt(t))return t.access_token;try{return(await rt(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function Ie(){let t=Se.randomBytes(32).toString("base64url"),e=Se.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function V(t,e,n){let r=new URLSearchParams({response_type:"code",client_id:l.freee.clientId,redirect_uri:n,scope:l.oauth.scope,state:e,code_challenge:t,code_challenge_method:"S256"});return`${l.oauth.authorizationEndpoint}?${r.toString()}`}async function q(t,e,n){let r=await fetch(l.oauth.tokenEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:l.freee.clientId,client_secret:l.freee.clientSecret,code:t,redirect_uri:n,code_verifier:e})});if(!r.ok){let i=await m(r);throw new Error(`Token exchange failed: ${r.status} ${JSON.stringify(i)}`)}let o=await r.json(),a={access_token:o.access_token,refresh_token:o.refresh_token,expires_at:Date.now()+o.expires_in*1e3,token_type:o.token_type||"Bearer",scope:o.scope||l.oauth.scope};return await J(a),a}var ce=class{pendingAuthentications=new Map;cliAuthHandlers=new Map;registerAuthentication(e,n){console.error(`Registering authentication request with state: ${e.substring(0,10)}...`),console.error(`Code verifier: ${n.substring(0,10)}...`);let r=setTimeout(()=>{this.pendingAuthentications.delete(e),console.error(`Authentication timeout for state: ${e.substring(0,10)}...`)},l.auth.timeoutMs);this.pendingAuthentications.set(e,{codeVerifier:n,resolve:o=>{console.error("Authentication completed successfully!")},reject:o=>{console.error("Authentication failed:",o)},timeout:r}),console.error(`Registration complete. Total pending: ${this.pendingAuthentications.size}`)}getPendingAuthentication(e){return this.pendingAuthentications.get(e)}removePendingAuthentication(e){let n=this.pendingAuthentications.get(e);n&&(clearTimeout(n.timeout),this.pendingAuthentications.delete(e))}clearAllPending(){for(let[e,n]of this.pendingAuthentications)clearTimeout(n.timeout),n.reject(new Error("Server shutdown"));this.pendingAuthentications.clear()}get pendingCount(){return this.pendingAuthentications.size}registerCliAuthHandler(e,n){this.cliAuthHandlers.set(e,n)}getCliAuthHandler(e){return this.cliAuthHandlers.get(e)}removeCliAuthHandler(e){this.cliAuthHandlers.delete(e)}},le=class{server=null;port=null;authManager;constructor(e){this.authManager=e}getRedirectUri(){if(this.port===null)throw new Error("Callback server not started. Call start() first.");return`http://127.0.0.1:${this.port}/callback`}getPort(){return this.port}isRunning(){return this.server!==null}async start(){if(this.server)return;let e=l.oauth.callbackPort,n=await this.findAvailablePort(e);return this.port=n,n!==e&&console.error(`Warning: Port ${e} is in use. Using fallback port ${n} for OAuth callback server.`),new Promise((r,o)=>{this.server=it.createServer((a,i)=>{console.error(`Callback request: ${a.method} ${a.url}`);let c=new at(a.url,`http://127.0.0.1:${n}`);c.pathname==="/callback"?this.handleCallback(c,i):c.pathname==="/"?(i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end("<h1>freee MCP OAuth Server</h1><p>\u30B3\u30FC\u30EB\u30D0\u30C3\u30AF\u30B5\u30FC\u30D0\u30FC\u304C\u7A3C\u50CD\u4E2D\u3067\u3059\u3002</p>")):(i.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),i.end("<h1>404 Not Found</h1><p>\u3053\u306E\u30D1\u30B9\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002</p>"))}),this.server.on("error",a=>{console.error("Callback server error:",a),o(a)}),this.server.listen(n,"127.0.0.1",()=>{console.error(`OAuth callback server listening on http://127.0.0.1:${n}`),r()})})}stop(){this.server&&(this.authManager.clearAllPending(),this.server.close(()=>{console.error("OAuth callback server stopped")}),this.server=null,this.port=null)}async checkPortAvailable(e){return new Promise(n=>{let r=st.createServer();r.listen(e,"127.0.0.1",()=>{r.close(()=>{n(!0)})}),r.on("error",()=>{n(!1)})})}async findAvailablePort(e,n=50){for(let r=e;r<e+n;r++)if(await this.checkPortAvailable(r))return r;throw new Error(`No available port found after checking ${n} ports starting from ${e}`)}handleCallback(e,n){let r=e.searchParams.get("code"),o=e.searchParams.get("state"),a=e.searchParams.get("error"),i=e.searchParams.get("error_description");console.error(`Callback received - URL: ${e.toString()}`),console.error("Callback parameters:",{code:r?`${r.substring(0,10)}...`:null,state:o?`${o.substring(0,10)}...`:null,error:a,errorDescription:i}),console.error(`Pending authentications count: ${this.authManager.pendingCount}`);let c=o?this.authManager.getCliAuthHandler(o):void 0;if(a){let f=i||a;if(console.error(`OAuth error: ${a} - ${i}`),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end(`<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${f}</p>`),c)c.reject(new Error(`OAuth error: ${a} - ${i}`));else if(o){let _=this.authManager.getPendingAuthentication(o);_&&(clearTimeout(_.timeout),_.reject(new Error(`OAuth error: ${a} - ${i}`)),this.authManager.removePendingAuthentication(o))}return}if(!r||!o){console.error("Missing code or state"),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u8A8D\u8A3C\u30B3\u30FC\u30C9\u307E\u305F\u306F\u72B6\u614B\u30D1\u30E9\u30E1\u30FC\u30BF\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059\u3002</p>");return}if(c){console.error("Valid CLI callback received"),n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u5B8C\u4E86</h1><p>\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\u3002\u3053\u306E\u30DA\u30FC\u30B8\u3092\u9589\u3058\u3066\u30BF\u30FC\u30DF\u30CA\u30EB\u306B\u623B\u3063\u3066\u304F\u3060\u3055\u3044\u3002</p>"),c.resolve(r);return}let p=this.authManager.getPendingAuthentication(o);if(!p){console.error(`Unknown state: ${o}`),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u4E0D\u660E\u306A\u8A8D\u8A3C\u72B6\u614B\u3067\u3059\u3002\u8A8D\u8A3C\u3092\u518D\u958B\u3057\u3066\u304F\u3060\u3055\u3044\u3002</p>");return}console.error("Valid callback received, exchanging code for tokens..."),n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u5B8C\u4E86</h1><p>\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\u3002\u3053\u306E\u30DA\u30FC\u30B8\u3092\u9589\u3058\u3066\u304F\u3060\u3055\u3044\u3002</p>"),this.authManager.removePendingAuthentication(o),q(r,p.codeVerifier,this.getRedirectUri()).then(f=>{console.error("Token exchange successful!"),p.resolve(f)}).catch(f=>{console.error("Token exchange failed:",f),p.reject(f)})}},pe=new ce,fe=new le(pe);function $(){return fe.getRedirectUri()}async function z(){return fe.start()}function $e(t,e){pe.registerAuthentication(t,e)}function R(){fe.stop()}function Re(){return pe}y();import ut from"crypto";import{z as ue}from"zod";y();A();import ct from"fs/promises";import lt from"path";function pt(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function ft(t){let e={"application/pdf":".pdf","image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp","text/csv":".csv"};for(let[n,r]of Object.entries(e))if(t.includes(n))return r;return t.includes("image/"),".bin"}async function F(t,e,n,r,o){let a=o||l.freee.apiUrl,i=await w(),c=await be();if(!c)throw new Error(`\u8A8D\u8A3C\u304C\u5FC5\u8981\u3067\u3059\u3002freee_authenticate \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u8A8D\u8A3C\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
5
+ \u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${i}
6
+ \u307E\u305F\u306F\u3001FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let p=a.endsWith("/")?a:a+"/",f=e.startsWith("/")?e.slice(1):e,_=new URL(f,p);n&&Object.entries(n).forEach(([u,g])=>{g!==void 0&&_.searchParams.append(u,String(g))});let Q=n?.company_id;if(Q!==void 0&&String(Q)!==String(i))throw new Error(`company_id \u306E\u4E0D\u6574\u5408: \u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id (${Q}) \u3068\u73FE\u5728\u306E\u4E8B\u696D\u6240 (${i}) \u304C\u7570\u306A\u308A\u307E\u3059\u3002
7
+ freee_set_company \u3067\u4E8B\u696D\u6240\u3092\u5207\u308A\u66FF\u3048\u308B\u304B\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id \u3092\u4FEE\u6B63\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let Y=r?.company_id;if(Y!==void 0&&String(Y)!==String(i))throw new Error(`company_id \u306E\u4E0D\u6574\u5408: \u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3\u306E company_id (${Y}) \u3068\u73FE\u5728\u306E\u4E8B\u696D\u6240 (${i}) \u304C\u7570\u306A\u308A\u307E\u3059\u3002
8
+ freee_set_company \u3067\u4E8B\u696D\u6240\u3092\u5207\u308A\u66FF\u3048\u308B\u304B\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id \u3092\u4FEE\u6B63\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let d=await fetch(_.toString(),{method:t,headers:{Authorization:`Bearer ${c}`,"Content-Type":"application/json"},body:r?JSON.stringify(typeof r=="string"?JSON.parse(r):r):void 0});if(d.status===401||d.status===403){let u=await m(d);throw new Error(`\u8A8D\u8A3C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002freee_authenticate \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u518D\u8A8D\u8A3C\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
9
+ \u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${i}
10
+ \u30A8\u30E9\u30FC\u8A73\u7D30: ${d.status} ${JSON.stringify(u)}
9
11
 
10
12
  \u78BA\u8A8D\u4E8B\u9805:
11
13
  1. FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B
12
14
  2. freee\u5074\u3067\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u8A2D\u5B9A\u304C\u6B63\u3057\u3044\u304B\uFF08\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8URI\u7B49\uFF09
13
15
  3. \u30C8\u30FC\u30AF\u30F3\u306E\u6709\u52B9\u671F\u9650\u304C\u5207\u308C\u3066\u3044\u306A\u3044\u304B
14
- 4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(!d.ok){let f=await y(d),g=`API request failed: ${d.status}`;if(f&&f.errors&&Array.isArray(f.errors)){let j=[];for(let v of f.errors)v.messages&&Array.isArray(v.messages)&&j.push(...v.messages);j.length>0&&(g+=`
16
+ 4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(!d.ok){let u=await m(d),g=`API request failed: ${d.status}`;if(u&&u.errors&&Array.isArray(u.errors)){let U=[];for(let T of u.errors)T.messages&&Array.isArray(T.messages)&&U.push(...T.messages);U.length>0&&(g+=`
15
17
 
16
18
  \u30A8\u30E9\u30FC\u8A73\u7D30:
17
- ${j.join(`
19
+ ${U.join(`
18
20
  `)}`,d.status===400&&(g+=`
19
21
 
20
22
  \u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,g+=`
21
23
  \u65E2\u5B58\u306E\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3057\u3066\u6B63\u3057\u3044\u69CB\u9020\u3092\u78BA\u8A8D\u3059\u308B\u3053\u3068\u3092\u304A\u52E7\u3081\u3057\u307E\u3059\u3002`,g+=`
22
- \u4F8B: get_items, get_partners, get_account_items \u306A\u3069\u3067\u65E2\u5B58\u30C7\u30FC\u30BF\u306E\u69CB\u9020\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`))}throw f?.errors||(g+=`
24
+ \u4F8B: get_items, get_partners, get_account_items \u306A\u3069\u3067\u65E2\u5B58\u30C7\u30FC\u30BF\u306E\u69CB\u9020\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`))}throw u?.errors||(g+=`
23
25
 
24
- \u8A73\u7D30: ${JSON.stringify(f)}`),new Error(g)}let q=d.headers.get("content-type")||"";if(Ze(q)){let f=await Y(),g=et(q),v=`freee_download_${Date.now()}${g}`,pe=Qe.join(f,v),ue=await d.arrayBuffer();return await Xe.writeFile(pe,Buffer.from(ue)),{type:"binary",filePath:pe,mimeType:q,size:ue.byteLength}}return d.json()}P();function Pe(t){t.tool("freee_current_user","\u73FE\u5728\u306E\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u3092\u53D6\u5F97\u3002\u8A73\u7D30\u30AC\u30A4\u30C9\u306Ffreee-mcp skill\u3092\u53C2\u7167\u3002",{},async()=>{try{let e=await E(),n=await x(e);if(!e)return{content:[{type:"text",text:"\u4F1A\u793EID\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002freee_set_company \u3067\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}]};let r=await R("GET","/api/1/users/me");return{content:[{type:"text",text:`\u73FE\u5728\u306E\u30E6\u30FC\u30B6\u30FC\u60C5\u5831:
26
+ \u8A73\u7D30: ${JSON.stringify(u)}`),new Error(g)}let Z=d.headers.get("content-type")||"";if(pt(Z)){let u=await oe(),g=ft(Z),T=`freee_download_${Date.now()}${g}`,we=lt.join(u,T),_e=await d.arrayBuffer();return await ct.writeFile(we,Buffer.from(_e)),{type:"binary",filePath:we,mimeType:Z,size:_e.byteLength}}return d.json()}A();function Fe(t){t.tool("freee_current_user","\u73FE\u5728\u306E\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u3092\u53D6\u5F97\u3002\u8A73\u7D30\u30AC\u30A4\u30C9\u306Ffreee-mcp skill\u3092\u53C2\u7167\u3002",{},async()=>{try{let e=await w(),n=await S(e);if(!e)return{content:[{type:"text",text:"\u4F1A\u793EID\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002freee_set_current_company \u3067\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}]};let r=await F("GET","/api/1/users/me");return{content:[{type:"text",text:`\u73FE\u5728\u306E\u30E6\u30FC\u30B6\u30FC\u60C5\u5831:
25
27
  \u4F1A\u793EID: ${e}
26
28
  \u4F1A\u793E\u540D: ${n?.name||"Unknown"}
27
29
  \u30E6\u30FC\u30B6\u30FC\u8A73\u7D30:
@@ -29,51 +31,50 @@ ${JSON.stringify(r,null,2)}`}]}}catch(e){return{content:[{type:"text",text:`\u30
29
31
  OAuth\u8A8D\u8A3C\u3092\u884C\u3046\u306B\u306F\u3001freee developers\u3067\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u4F5C\u6210\u3057\u3001
30
32
  \u30AF\u30E9\u30A4\u30A2\u30F3\u30C8ID\u3092\u74B0\u5883\u5909\u6570\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`}]};if(!l.freee.clientSecret)return{content:[{type:"text",text:`FREEE_CLIENT_SECRET\u74B0\u5883\u5909\u6570\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002
31
33
  OAuth\u8A8D\u8A3C\u3092\u884C\u3046\u306B\u306F\u3001freee developers\u3067\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u4F5C\u6210\u3057\u3001
32
- \u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u30B7\u30FC\u30AF\u30EC\u30C3\u30C8\u3092\u74B0\u5883\u5909\u6570\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`}]};let{codeVerifier:e,codeChallenge:n}=_e(),r=tt.randomBytes(16).toString("hex"),o=B(n,r,S());return Ee(r,e),console.error(`Authentication URL: ${o}`),{content:[{type:"text",text:`\u8A8D\u8A3CURL: ${o}
34
+ \u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u30B7\u30FC\u30AF\u30EC\u30C3\u30C8\u3092\u74B0\u5883\u5909\u6570\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`}]};let{codeVerifier:e,codeChallenge:n}=Ie(),r=ut.randomBytes(16).toString("hex"),o=V(n,r,$());return $e(r,e),console.error(`Authentication URL: ${o}`),{content:[{type:"text",text:`\u8A8D\u8A3CURL: ${o}
33
35
 
34
- \u30D6\u30E9\u30A6\u30B6\u3067\u958B\u3044\u3066\u8A8D\u8A3C\u3057\u3066\u304F\u3060\u3055\u3044\u30025\u5206\u3067\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3059\u3002`}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u958B\u59CB\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_auth_status","\u8A8D\u8A3C\u72B6\u614B\u3092\u78BA\u8A8D\u3002",{},async()=>{try{let e=await Z();if(!e)return{content:[{type:"text",text:"\u672A\u8A8D\u8A3C\u3002freee_authenticate \u3067\u8A8D\u8A3C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}]};let n=Date.now()<e.expires_at,r=new Date(e.expires_at).toLocaleString();return{content:[{type:"text",text:`\u8A8D\u8A3C\u72B6\u614B: ${n?"\u6709\u52B9":"\u671F\u9650\u5207\u308C"}
36
+ \u30D6\u30E9\u30A6\u30B6\u3067\u958B\u3044\u3066\u8A8D\u8A3C\u3057\u3066\u304F\u3060\u3055\u3044\u30025\u5206\u3067\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3059\u3002`}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u958B\u59CB\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_auth_status","\u8A8D\u8A3C\u72B6\u614B\u3092\u78BA\u8A8D\u3002",{},async()=>{try{let e=await se();if(!e)return{content:[{type:"text",text:"\u672A\u8A8D\u8A3C\u3002freee_authenticate \u3067\u8A8D\u8A3C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}]};let n=Date.now()<e.expires_at,r=new Date(e.expires_at).toLocaleString();return{content:[{type:"text",text:`\u8A8D\u8A3C\u72B6\u614B: ${n?"\u6709\u52B9":"\u671F\u9650\u5207\u308C"}
35
37
  \u6709\u52B9\u671F\u9650: ${r}`+(n?"":`
36
- \u6B21\u56DEAPI\u4F7F\u7528\u6642\u306B\u81EA\u52D5\u66F4\u65B0\u3055\u308C\u307E\u3059\u3002`)}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u72B6\u614B\u306E\u78BA\u8A8D\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_clear_auth","\u8A8D\u8A3C\u60C5\u5831\u3092\u30AF\u30EA\u30A2\u3002",{},async()=>{try{return await Ce(),{content:[{type:"text",text:"\u8A8D\u8A3C\u60C5\u5831\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F\u3002\u518D\u8A8D\u8A3C\u3059\u308B\u306B\u306F freee_authenticate \u3092\u4F7F\u7528\u3002"}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u60C5\u5831\u306E\u30AF\u30EA\u30A2\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_set_company","\u4E8B\u696D\u6240\u3092\u8A2D\u5B9A\u30FB\u5207\u308A\u66FF\u3048\u3002",{company_id:oe.string().describe("\u4E8B\u696D\u6240ID"),name:oe.string().optional().describe("\u4E8B\u696D\u6240\u540D"),description:oe.string().optional().describe("\u8AAC\u660E")},async e=>{try{let{company_id:n,name:r,description:o}=e;return await W(n,r,o),{content:[{type:"text",text:`\u4E8B\u696D\u6240\u3092\u8A2D\u5B9A: ${(await x(n))?.name||n}`}]}}catch(n){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u306E\u8A2D\u5B9A\u306B\u5931\u6557: ${n instanceof Error?n.message:String(n)}`}]}}}),t.tool("freee_get_current_company","\u73FE\u5728\u306E\u4E8B\u696D\u6240\u60C5\u5831\u3092\u8868\u793A\u3002",{},async()=>{try{let e=await E(),n=await x(e);return n?{content:[{type:"text",text:`\u4E8B\u696D\u6240: ${n.name} (ID: ${n.id})`}]}:{content:[{type:"text",text:`\u4E8B\u696D\u6240ID: ${e} (\u8A73\u7D30\u60C5\u5831\u306A\u3057)`}]}}catch(e){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_list_companies","\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u8868\u793A\u3002",{},async()=>{try{let e=await R("GET","/api/1/companies"),n=await E();return e?.companies?.length?{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7:
37
- ${e.companies.map(o=>{let i=o.id===parseInt(n)?" *":"";return`${o.name} (${o.id})${i}`}).join(`
38
- `)}`}]}:{content:[{type:"text",text:"\u4E8B\u696D\u6240\u60C5\u5831\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002"}]}}catch(e){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7\u306E\u53D6\u5F97\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}})}import{z as c}from"zod";import Te from"node:fs";import F from"node:path";import{fileURLToPath as nt}from"node:url";var ie=F.dirname(nt(import.meta.url));function rt(){let t=[F.resolve(ie,"./openapi/minimal"),F.resolve(ie,"../dist/openapi/minimal"),F.resolve(ie,"../../openapi/minimal")];for(let e of t)if(Te.existsSync(e))return e;throw new Error(`Could not find minimal schema directory. Searched paths:
38
+ \u6B21\u56DEAPI\u4F7F\u7528\u6642\u306B\u81EA\u52D5\u66F4\u65B0\u3055\u308C\u307E\u3059\u3002`)}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u72B6\u614B\u306E\u78BA\u8A8D\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_clear_auth","\u8A8D\u8A3C\u60C5\u5831\u3092\u30AF\u30EA\u30A2\u3002",{},async()=>{try{return await xe(),{content:[{type:"text",text:"\u8A8D\u8A3C\u60C5\u5831\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F\u3002\u518D\u8A8D\u8A3C\u3059\u308B\u306B\u306F freee_authenticate \u3092\u4F7F\u7528\u3002"}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u60C5\u5831\u306E\u30AF\u30EA\u30A2\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_set_current_company","\u4E8B\u696D\u6240\u3092\u8A2D\u5B9A\u30FB\u5207\u308A\u66FF\u3048\u3002",{company_id:ue.string().describe("\u4E8B\u696D\u6240ID"),name:ue.string().optional().describe("\u4E8B\u696D\u6240\u540D"),description:ue.string().optional().describe("\u8AAC\u660E")},async e=>{try{let{company_id:n,name:r,description:o}=e;return await re(n,r,o),{content:[{type:"text",text:`\u4E8B\u696D\u6240\u3092\u8A2D\u5B9A: ${(await S(n))?.name||n}`}]}}catch(n){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u306E\u8A2D\u5B9A\u306B\u5931\u6557: ${n instanceof Error?n.message:String(n)}`}]}}}),t.tool("freee_get_current_company","\u73FE\u5728\u306E\u4E8B\u696D\u6240\u60C5\u5831\u3092\u8868\u793A\u3002",{},async()=>{try{let e=await w(),n=await S(e);return n?{content:[{type:"text",text:`\u4E8B\u696D\u6240: ${n.name} (ID: ${n.id})`}]}:{content:[{type:"text",text:`\u4E8B\u696D\u6240ID: ${e} (\u8A73\u7D30\u60C5\u5831\u306A\u3057)`}]}}catch(e){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_list_companies","\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u8868\u793A\u3002",{},async()=>{try{let e=await F("GET","/api/1/companies"),n=await w();return e?.companies?.length?{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7:
39
+ ${e.companies.map(o=>{let a=o.id===parseInt(n)?" *":"";return`${o.name} (${o.id})${a}`}).join(`
40
+ `)}`}]}:{content:[{type:"text",text:"\u4E8B\u696D\u6240\u60C5\u5831\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002"}]}}catch(e){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7\u306E\u53D6\u5F97\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}})}import{z as s}from"zod";import Oe from"node:fs";import M from"node:path";import{fileURLToPath as dt}from"node:url";var de=M.dirname(dt(import.meta.url));function gt(){let t=[M.resolve(de,"./openapi/minimal"),M.resolve(de,"../dist/openapi/minimal"),M.resolve(de,"../../openapi/minimal")];for(let e of t)if(Oe.existsSync(e))return e;throw new Error(`Could not find minimal schema directory. Searched paths:
39
41
  ${t.join(`
40
- `)}`)}var ot=rt();function D(t){let e=F.join(ot,t),n=Te.readFileSync(e,"utf-8");return JSON.parse(n)}var ae=null;function se(){return ae===null&&(ae={accounting:{schema:D("accounting.json"),baseUrl:"https://api.freee.co.jp",prefix:"accounting",name:"freee\u4F1A\u8A08 API"},hr:{schema:D("hr.json"),baseUrl:"https://api.freee.co.jp/hr",prefix:"hr",name:"freee\u4EBA\u4E8B\u52B4\u52D9 API"},invoice:{schema:D("invoice.json"),baseUrl:"https://api.freee.co.jp/iv",prefix:"invoice",name:"freee\u8ACB\u6C42\u66F8 API"},pm:{schema:D("pm.json"),baseUrl:"https://api.freee.co.jp/pm",prefix:"pm",name:"freee\u5DE5\u6570\u7BA1\u7406 API"},sm:{schema:D("sm.json"),baseUrl:"https://api.freee.co.jp/sm",prefix:"sm",name:"freee\u8CA9\u58F2 API"}}),ae}var ce=new Proxy({},{get(t,e){return se()[e]},ownKeys(){return Object.keys(se())},getOwnPropertyDescriptor(t,e){let n=se();if(e in n)return{enumerable:!0,configurable:!0,value:n[e]}}});function ve(t,e,n,r){let o=r.schema.paths;if(e in o){let i=o[e];if(t in i)return{isValid:!0,message:"Valid path and method",operation:i[t],actualPath:e,apiType:n,baseUrl:r.baseUrl}}for(let i of Object.keys(o)){let a=i.replace(/\{[^}]+\}/g,"[^/]+");if(new RegExp(`^${a}$`).test(e)){let p=o[i];if(t in p)return{isValid:!0,message:"Valid path and method",operation:p[t],actualPath:e,apiType:n,baseUrl:r.baseUrl}}}return null}function be(t,e,n){let r=t.toLowerCase();if(n!==void 0){let o=ce[n],i=ve(r,e,n,o);return i||{isValid:!1,message:`Path '${e}' not found in ${o.name} schema. Please check the path format or use freee_api_list_paths to see available endpoints.`}}for(let[o,i]of Object.entries(ce)){let a=ve(r,e,o,i);if(a)return a}return{isValid:!1,message:`Path '${e}' not found in any freee API schema. Please check the path format or use freee_api_list_paths to see available endpoints.`}}function xe(){let t=[];for(let[,e]of Object.entries(ce)){let n=e.schema.paths,r=[];Object.entries(n).forEach(([o,i])=>{let a=Object.keys(i).filter(s=>["get","post","put","delete","patch"].includes(s)).map(s=>s.toUpperCase());a.length>0&&r.push(` ${a.join("|")} ${o}`)}),r.length>0&&t.push(`
42
+ `)}`)}var mt=gt();function ht(t){let e=M.join(mt,t),n=Oe.readFileSync(e,"utf-8");return JSON.parse(n)}var G={accounting:{schemaFile:"accounting.json",baseUrl:"https://api.freee.co.jp",prefix:"accounting",name:"freee\u4F1A\u8A08 API"},hr:{schemaFile:"hr.json",baseUrl:"https://api.freee.co.jp/hr",prefix:"hr",name:"freee\u4EBA\u4E8B\u52B4\u52D9 API"},invoice:{schemaFile:"invoice.json",baseUrl:"https://api.freee.co.jp/iv",prefix:"invoice",name:"freee\u8ACB\u6C42\u66F8 API"},pm:{schemaFile:"pm.json",baseUrl:"https://api.freee.co.jp/pm",prefix:"pm",name:"freee\u5DE5\u6570\u7BA1\u7406 API"},sm:{schemaFile:"sm.json",baseUrl:"https://api.freee.co.jp/sm",prefix:"sm",name:"freee\u8CA9\u58F2 API"}},ge={};function Me(t){if(!ge[t]){let e=G[t];ge[t]={schema:ht(e.schemaFile),baseUrl:e.baseUrl,prefix:e.prefix,name:e.name}}return ge[t]}var me=new Proxy({},{get(t,e){if(e in G)return Me(e)},ownKeys(){return Object.keys(G)},getOwnPropertyDescriptor(t,e){if(e in G)return{enumerable:!0,configurable:!0,value:Me(e)}}});function De(t,e,n,r){let o=r.schema.paths;if(e in o){let a=o[e];if(t in a)return{isValid:!0,message:"Valid path and method",operation:a[t],actualPath:e,apiType:n,baseUrl:r.baseUrl}}for(let a of Object.keys(o)){let i=a.replace(/\{[^}]+\}/g,"[^/]+");if(new RegExp(`^${i}$`).test(e)){let p=o[a];if(t in p)return{isValid:!0,message:"Valid path and method",operation:p[t],actualPath:e,apiType:n,baseUrl:r.baseUrl}}}return null}function je(t,e,n){let r=t.toLowerCase();if(n!==void 0){let o=me[n],a=De(r,e,n,o);return a||{isValid:!1,message:`Path '${e}' not found in ${o.name} schema. Please check the path format or use freee_api_list_paths to see available endpoints.`}}for(let[o,a]of Object.entries(me)){let i=De(r,e,o,a);if(i)return i}return{isValid:!1,message:`Path '${e}' not found in any freee API schema. Please check the path format or use freee_api_list_paths to see available endpoints.`}}function Le(){let t=[];for(let[,e]of Object.entries(me)){let n=e.schema.paths,r=[];Object.entries(n).forEach(([o,a])=>{let i=Object.keys(a).filter(c=>["get","post","put","delete","patch"].includes(c)).map(c=>c.toUpperCase());i.length>0&&r.push(` ${i.join("|")} ${o}`)}),r.length>0&&t.push(`
41
43
  ## ${e.name} (${e.baseUrl})
42
44
  ${r.sort().join(`
43
45
  `)}`)}return t.join(`
44
- `)}function it(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="binary"}function at(t){let e=(t.size/1024).toFixed(2);return`\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u307E\u3057\u305F
46
+ `)}function yt(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="binary"}function Ct(t){let e=(t.size/1024).toFixed(2);return`\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u307E\u3057\u305F
45
47
 
46
48
  \u4FDD\u5B58\u5834\u6240: ${t.filePath}
47
49
  MIME\u30BF\u30A4\u30D7: ${t.mimeType}
48
- \u30B5\u30A4\u30BA: ${e} KB`}var O="service: accounting/hr/invoice/pm/sm",L=c.enum(["accounting","hr","invoice","pm","sm"]).describe("\u5BFE\u8C61\u306Efreee\u30B5\u30FC\u30D3\u30B9");function U(t){return async e=>{try{let{service:n,path:r,query:o,body:i}=e,a=be(t,r,n);if(!a.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${a.message}
50
+ \u30B5\u30A4\u30BA: ${e} KB`}var D="service: accounting/hr/invoice/pm/sm",O=s.enum(["accounting","hr","invoice","pm","sm"]).describe("\u5BFE\u8C61\u306Efreee\u30B5\u30FC\u30D3\u30B9");function j(t){return async e=>{try{let{service:n,path:r,query:o,body:a}=e,i=je(t,r,n);if(!i.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${i.message}
49
51
 
50
- \u5229\u7528\u53EF\u80FD\u306A\u30D1\u30B9\u3092\u78BA\u8A8D\u3059\u308B\u306B\u306F freee_api_list_paths \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002`}]};let s=await R(t,a.actualPath,o,i,a.baseUrl);return it(s)?{content:[{type:"text",text:at(s)}]}:{content:[{type:"text",text:JSON.stringify(s,null,2)}]}}catch(n){return{content:[{type:"text",text:`API\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC: ${n instanceof Error?n.message:String(n)}`}]}}}}function Ie(t){t.tool("freee_api_get",`freee API GET\u3002${O}`,{service:L,path:c.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),query:c.record(c.string(),c.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},U("GET")),t.tool("freee_api_post",`freee API POST\u3002${O}`,{service:L,path:c.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),body:c.record(c.string(),c.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.record(c.string(),c.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},U("POST")),t.tool("freee_api_put",`freee API PUT\u3002${O}`,{service:L,path:c.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123, /invoices/123)"),body:c.record(c.string(),c.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.record(c.string(),c.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},U("PUT")),t.tool("freee_api_delete",`freee API DELETE\u3002${O}`,{service:L,path:c.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),query:c.record(c.string(),c.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},U("DELETE")),t.tool("freee_api_patch",`freee API PATCH\u3002${O}`,{service:L,path:c.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),body:c.record(c.string(),c.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.record(c.string(),c.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},U("PATCH")),t.tool("freee_api_list_paths","freee API \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u4E00\u89A7\u3002\u8A73\u7D30\u306A\u30AC\u30A4\u30C9\u306Ffreee-mcp skill\u3092\u53C2\u7167\u3002",{},async()=>({content:[{type:"text",text:`# freee API \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u4E00\u89A7${xe()}
52
+ \u5229\u7528\u53EF\u80FD\u306A\u30D1\u30B9\u3092\u78BA\u8A8D\u3059\u308B\u306B\u306F freee_api_list_paths \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002`}]};let c=await F(t,i.actualPath,o,a,i.baseUrl);return yt(c)?{content:[{type:"text",text:Ct(c)}]}:{content:[{type:"text",text:JSON.stringify(c,null,2)}]}}catch(n){return{content:[{type:"text",text:`API\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC: ${n instanceof Error?n.message:String(n)}`}]}}}}function Ue(t){t.tool("freee_api_get",`freee API GET\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("GET")),t.tool("freee_api_post",`freee API POST\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),body:s.record(s.string(),s.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("POST")),t.tool("freee_api_put",`freee API PUT\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123, /invoices/123)"),body:s.record(s.string(),s.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("PUT")),t.tool("freee_api_delete",`freee API DELETE\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("DELETE")),t.tool("freee_api_patch",`freee API PATCH\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),body:s.record(s.string(),s.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("PATCH")),t.tool("freee_api_list_paths","freee API \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u4E00\u89A7\u3002\u8A73\u7D30\u306A\u30AC\u30A4\u30C9\u306Ffreee-mcp skill\u3092\u53C2\u7167\u3002",{},async()=>({content:[{type:"text",text:`# freee API \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u4E00\u89A7${Le()}
51
53
 
52
54
  \u4F7F\u7528\u4F8B:
53
55
  freee_api_get { "service": "accounting", "path": "/api/1/deals", "query": { "limit": 10 } }
54
56
  freee_api_get { "service": "invoice", "path": "/invoices" }
55
- freee_api_post { "service": "accounting", "path": "/api/1/deals", "body": { "issue_date": "2024-01-01", ... } }`}]}))}async function Se(){let t=await X(),e=new st({name:t.server.name,version:t.server.version});Pe(e),Ie(e);try{await V(),console.error(`OAuth callback server started on http://127.0.0.1:${t.oauth.callbackPort}`)}catch(r){console.error("Failed to start callback server:",r),console.error("OAuth authentication will fall back to manual mode")}let n=new ct;await e.connect(n),console.error("Freee MCP Server running on stdio"),process.on("SIGINT",()=>{$(),process.exit(0)}),process.on("SIGTERM",()=>{$(),process.exit(0)})}import $e from"prompts";import*as Re from"node:os";import le from"node:crypto";import lt from"open";h();P();b();async function pt(t){let e=await fetch(`${l.freee.apiUrl}/api/1/companies`,{headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!e.ok){let r=await y(e);throw new Error(`\u4E8B\u696D\u6240\u4E00\u89A7\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${e.status} ${JSON.stringify(r)}`)}return(await e.json()).companies||[]}async function ut(){let t=await Promise.resolve().then(()=>(P(),he)).then(a=>a.loadFullConfig()),e=!!(t.clientId&&t.clientSecret);e&&(console.log("\u65E2\u5B58\u306E\u8A2D\u5B9A\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002"),console.log(` \u5909\u66F4\u3057\u306A\u3044\u9805\u76EE\u306F\u305D\u306E\u307E\u307E Enter \u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002
57
+ freee_api_post { "service": "accounting", "path": "/api/1/deals", "body": { "issue_date": "2024-01-01", ... } }`}]}))}async function Ne(){let t=await ie(),e=new wt({name:t.server.name,version:t.server.version});Fe(e),Ue(e);try{await z(),console.error(`OAuth callback server started on http://127.0.0.1:${t.oauth.callbackPort}`)}catch(r){console.error("Failed to start callback server:",r),console.error("OAuth authentication will fall back to manual mode")}let n=new _t;await e.connect(n),console.error("Freee MCP Server running on stdio"),process.on("SIGINT",()=>{R(),process.exit(0)}),process.on("SIGTERM",()=>{R(),process.exit(0)})}import X from"prompts";import Ce from"node:crypto";import Et from"open";A();import K from"node:fs/promises";import v from"node:path";import L from"node:os";var W="freee-mcp",kt={command:"npx",args:["@him0/freee-mcp"]};function he(t){let e=L.platform();if(t==="claude-code")return v.join(L.homedir(),".claude.json");if(e==="darwin")return v.join(L.homedir(),"Library","Application Support","Claude","claude_desktop_config.json");if(e==="win32"){let n=process.env.APPDATA||v.join(L.homedir(),"AppData","Roaming");return v.join(n,"Claude","claude_desktop_config.json")}else return v.join(L.homedir(),".config","Claude","claude_desktop_config.json")}function He(t){return t==="claude-code"?"Claude Code":"Claude Desktop"}async function ye(t){try{let e=await K.readFile(t,"utf-8");return JSON.parse(e)}catch{return null}}async function Be(t,e){let n=v.dirname(t);await K.mkdir(n,{recursive:!0}),await K.writeFile(t,JSON.stringify(e,null,2)+`
58
+ `,"utf-8")}async function Je(t){let e=he(t);try{await K.access(e);let n=await ye(e);return{path:e,exists:!0,hasFreeeConfig:n?.mcpServers?.[W]!==void 0}}catch{return{path:e,exists:!1,hasFreeeConfig:!1}}}async function Ve(t){let e=he(t),n=await ye(e);n||(n={}),n.mcpServers||(n.mcpServers={}),n.mcpServers[W]={...kt},await Be(e,n)}async function qe(t){let e=he(t),n=await ye(e);n?.mcpServers?.[W]&&(delete n.mcpServers[W],Object.keys(n.mcpServers).length===0&&delete n.mcpServers,await Be(e,n))}b();async function At(t){let e=await fetch(`${B}/api/1/companies`,{headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!e.ok){let r=await m(e);throw new Error(`\u4E8B\u696D\u6240\u4E00\u89A7\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${e.status} ${JSON.stringify(r)}`)}return(await e.json()).companies||[]}async function Pt(){let t=await Promise.resolve().then(()=>(A(),ve)).then(i=>i.loadFullConfig()),e=!!(t.clientId&&t.clientSecret);e&&(console.log("\u65E2\u5B58\u306E\u8A2D\u5B9A\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002"),console.log(` \u5909\u66F4\u3057\u306A\u3044\u9805\u76EE\u306F\u305D\u306E\u307E\u307E Enter \u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002
56
59
  `)),console.log(`\u30B9\u30C6\u30C3\u30D7 1/3: OAuth\u8A8D\u8A3C\u60C5\u5831\u306E\u5165\u529B
57
- `);let n=await $e([{type:"text",name:"clientId",message:"FREEE_CLIENT_ID:",initial:t.clientId||void 0,validate:a=>a.trim()?!0:"CLIENT_ID \u306F\u5FC5\u9808\u3067\u3059"},{type:"password",name:"clientSecret",message:e?"FREEE_CLIENT_SECRET (\u5909\u66F4\u3057\u306A\u3044\u5834\u5408\u306F\u7A7A\u6B04):":"FREEE_CLIENT_SECRET:",validate:a=>e&&!a.trim()||a.trim()?!0:"CLIENT_SECRET \u306F\u5FC5\u9808\u3067\u3059"},{type:"text",name:"callbackPort",message:"FREEE_CALLBACK_PORT:",initial:String(t.callbackPort||T)}]);if(!n.clientId)throw new Error("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002");let r=n.clientId.trim(),o=n.clientSecret.trim()||t.clientSecret,i=parseInt(n.callbackPort.trim(),10);if(!o)throw new Error("CLIENT_SECRET \u306F\u5FC5\u9808\u3067\u3059\u3002");return process.env.FREEE_CLIENT_ID=r,process.env.FREEE_CLIENT_SECRET=o,process.env.FREEE_CALLBACK_PORT=String(i),console.log(`
60
+ `);let n=await X([{type:"text",name:"clientId",message:"FREEE_CLIENT_ID:",initial:t.clientId||void 0,validate:i=>i.trim()?!0:"CLIENT_ID \u306F\u5FC5\u9808\u3067\u3059"},{type:"password",name:"clientSecret",message:e?"FREEE_CLIENT_SECRET (\u5909\u66F4\u3057\u306A\u3044\u5834\u5408\u306F\u7A7A\u6B04):":"FREEE_CLIENT_SECRET:",validate:i=>e&&!i.trim()||i.trim()?!0:"CLIENT_SECRET \u306F\u5FC5\u9808\u3067\u3059"},{type:"text",name:"callbackPort",message:"FREEE_CALLBACK_PORT:",initial:String(t.callbackPort||x)}]);if(!n.clientId)throw new Error("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002");let r=n.clientId.trim(),o=n.clientSecret.trim()||t.clientSecret,a=parseInt(n.callbackPort.trim(),10);if(!o)throw new Error("CLIENT_SECRET \u306F\u5FC5\u9808\u3067\u3059\u3002");return process.env.FREEE_CLIENT_ID=r,process.env.FREEE_CLIENT_SECRET=o,process.env.FREEE_CALLBACK_PORT=String(a),console.log(`
58
61
  \u8A8D\u8A3C\u60C5\u5831\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002
59
- `),{clientId:r,clientSecret:o,callbackPort:i}}async function ft(){console.log(`\u30B9\u30C6\u30C3\u30D7 2/3: OAuth\u8A8D\u8A3C
60
- `),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(h(),ye)).then(a=>a.loadConfig()),await V();let t=le.randomBytes(32).toString("base64url"),e=le.createHash("sha256").update(t).digest("base64url"),n=le.randomBytes(16).toString("base64url"),r=B(e,n,S());console.log(`
62
+ `),{clientId:r,clientSecret:o,callbackPort:a}}async function vt(){console.log(`\u30B9\u30C6\u30C3\u30D7 2/3: OAuth\u8A8D\u8A3C
63
+ `),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(y(),Te)).then(i=>i.loadConfig()),await z();let t=Ce.randomBytes(32).toString("base64url"),e=Ce.createHash("sha256").update(t).digest("base64url"),n=Ce.randomBytes(16).toString("base64url"),r=V(e,n,$());console.log(`
61
64
  \u8A8D\u8A3CURL: ${r}
62
- `),await lt(r),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u3092\u5B8C\u4E86\u3057\u3066\u304F\u3060\u3055\u3044..."),console.log(`\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3059\u308B\u3068\u81EA\u52D5\u7684\u306B\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u306B\u9032\u307F\u307E\u3059\u3002
63
- `);let o=Ae(),i=new Promise((a,s)=>{let p=setTimeout(()=>{s(new Error("\u8A8D\u8A3C\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\uFF085\u5206\uFF09"))},M);o.registerCliAuthHandler(n,{resolve:u=>{clearTimeout(p),a(u)},reject:u=>{clearTimeout(p),s(u)},codeVerifier:t})});try{let a=await i;console.log("\u8A8D\u8A3C\u30B3\u30FC\u30C9\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002"),console.log("\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u4E2D...");let s=await J(a,t,S());return console.log(`\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002
64
- `),{accessToken:s.access_token,refreshToken:s.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function dt(t){console.log(`\u30B9\u30C6\u30C3\u30D7 3/3: \u30C7\u30D5\u30A9\u30EB\u30C8\u4E8B\u696D\u6240\u306E\u9078\u629E
65
- `),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await pt(t);if(e.length===0)throw new Error("\u5229\u7528\u53EF\u80FD\u306A\u4E8B\u696D\u6240\u304C\u3042\u308A\u307E\u305B\u3093\u3002");let n=await $e({type:"select",name:"companyId",message:"\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u4E8B\u696D\u6240\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044:",choices:e.map(o=>({title:`${o.display_name||o.name} (ID: ${o.id}) - ${o.role}`,value:o.id}))});if(!n.companyId)throw new Error("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002");let r=e.find(o=>o.id===n.companyId);if(!r)throw new Error(`\u9078\u629E\u3057\u305F\u4E8B\u696D\u6240\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ID ${n.companyId}`);return console.log(`
65
+ `),await Et(r),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u3092\u5B8C\u4E86\u3057\u3066\u304F\u3060\u3055\u3044..."),console.log(`\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3059\u308B\u3068\u81EA\u52D5\u7684\u306B\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u306B\u9032\u307F\u307E\u3059\u3002
66
+ `);let o=Re(),a=new Promise((i,c)=>{let p=setTimeout(()=>{c(new Error("\u8A8D\u8A3C\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\uFF085\u5206\uFF09"))},N);o.registerCliAuthHandler(n,{resolve:f=>{clearTimeout(p),i(f)},reject:f=>{clearTimeout(p),c(f)},codeVerifier:t})});try{let i=await a;console.log("\u8A8D\u8A3C\u30B3\u30FC\u30C9\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002"),console.log("\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u4E2D...");let c=await q(i,t,$());return console.log(`\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002
67
+ `),{accessToken:c.access_token,refreshToken:c.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function Tt(t){console.log(`\u30B9\u30C6\u30C3\u30D7 3/3: \u30C7\u30D5\u30A9\u30EB\u30C8\u4E8B\u696D\u6240\u306E\u9078\u629E
68
+ `),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await At(t);if(e.length===0)throw new Error("\u5229\u7528\u53EF\u80FD\u306A\u4E8B\u696D\u6240\u304C\u3042\u308A\u307E\u305B\u3093\u3002");let n=await X({type:"select",name:"companyId",message:"\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u4E8B\u696D\u6240\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044:",choices:e.map(o=>({title:`${o.display_name||o.name} (ID: ${o.id}) - ${o.role}`,value:o.id}))});if(!n.companyId)throw new Error("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002");let r=e.find(o=>o.id===n.companyId);if(!r)throw new Error(`\u9078\u629E\u3057\u305F\u4E8B\u696D\u6240\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ID ${n.companyId}`);return console.log(`
66
69
  ${r.display_name||r.name} \u3092\u9078\u629E\u3057\u307E\u3057\u305F\u3002
67
- `),{selected:{id:r.id,name:r.name,displayName:r.display_name||r.name,role:r.role},all:e}}async function gt(t,e,n){let r={clientId:t.clientId,clientSecret:t.clientSecret,callbackPort:t.callbackPort,defaultCompanyId:String(e.id),currentCompanyId:String(e.id),companies:{}};n.forEach(s=>{r.companies[String(s.id)]={id:String(s.id),name:s.display_name||s.name,description:`Role: ${s.role}`,addedAt:Date.now(),lastUsed:s.id===e.id?Date.now():void 0}}),await _(r),console.log(`\u8A2D\u5B9A\u60C5\u5831\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F\u3002
68
- `),console.log(`=== MCP\u8A2D\u5B9A ===
69
- `),console.log(`\u4EE5\u4E0B\u306E\u8A2D\u5B9A\u3092Claude desktop\u306E\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306B\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044:
70
- `);let o=Re.platform(),i="";o==="darwin"?i="~/Library/Application Support/Claude/claude_desktop_config.json":o==="win32"?i="%APPDATA%\\Claude\\claude_desktop_config.json":i="~/.config/Claude/claude_desktop_config.json",console.log(`\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u5834\u6240: ${i}
71
- `),console.log(JSON.stringify({mcpServers:{"freee-mcp":{command:"npx",args:["@him0/freee-mcp","client"]}}},null,2)),console.log(`
72
- \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5B8C\u4E86!
73
- `),console.log("\u8A8D\u8A3C\u60C5\u5831\u306F ~/.config/freee-mcp/config.json \u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002"),console.log("\u30C8\u30FC\u30AF\u30F3\u306F ~/.config/freee-mcp/tokens.json \u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002"),console.log(`Claude desktop\u3092\u518D\u8D77\u52D5\u3059\u308B\u3068\u3001freee-mcp\u304C\u5229\u7528\u53EF\u80FD\u306B\u306A\u308A\u307E\u3059\u3002
74
- `)}async function De(){console.log(`
70
+ `),{selected:{id:r.id,name:r.name,displayName:r.display_name||r.name,role:r.role},all:e}}async function xt(t,e,n){let r={clientId:t.clientId,clientSecret:t.clientSecret,callbackPort:t.callbackPort,defaultCompanyId:String(e.id),currentCompanyId:String(e.id),companies:{}};n.forEach(o=>{r.companies[String(o.id)]={id:String(o.id),name:o.display_name||o.name,description:`Role: ${o.role}`,addedAt:Date.now(),lastUsed:o.id===e.id?Date.now():void 0}}),await E(r),console.log(`\u8A2D\u5B9A\u60C5\u5831\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F\u3002
71
+ `),console.log("\u8A8D\u8A3C\u60C5\u5831\u306F ~/.config/freee-mcp/config.json \u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002"),console.log(`\u30C8\u30FC\u30AF\u30F3\u306F ~/.config/freee-mcp/tokens.json \u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002
72
+ `)}async function ze(t){let e=He(t),n=await Je(t);if(n.hasFreeeConfig){let{action:r}=await X({type:"select",name:"action",message:`${e} \u306B freee-mcp \u304C\u8A2D\u5B9A\u6E08\u307F\u3067\u3059\u3002\u3069\u3046\u3057\u307E\u3059\u304B?`,choices:[{title:"\u305D\u306E\u307E\u307E (\u5909\u66F4\u306A\u3057)",value:"keep"},{title:"\u524A\u9664\u3059\u308B",value:"remove"}],initial:0});r==="remove"?(await qe(t),console.log(` \u2713 ${e} \u304B\u3089 freee-mcp \u3092\u524A\u9664\u3057\u307E\u3057\u305F\u3002`)):console.log(` - ${e} \u306E\u8A2D\u5B9A\u306F\u5909\u66F4\u3057\u307E\u305B\u3093\u3002`)}else{let{shouldAdd:r}=await X({type:"confirm",name:"shouldAdd",message:`${e} \u306B freee-mcp \u3092\u8FFD\u52A0\u3057\u307E\u3059\u304B?`,initial:!0});r?(await Ve(t),console.log(` \u2713 ${e} \u306B freee-mcp \u3092\u8FFD\u52A0\u3057\u307E\u3057\u305F\u3002`),console.log(` \u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB: ${n.path}`)):console.log(` - ${e} \u3078\u306E\u8FFD\u52A0\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F\u3002`)}}async function bt(){console.log(`=== MCP\u8A2D\u5B9A ===
73
+ `),console.log(`Claude Code / Claude Desktop \u306B freee-mcp \u3092\u8A2D\u5B9A\u3067\u304D\u307E\u3059\u3002
74
+ `),await ze("claude-code"),console.log(""),await ze("claude-desktop"),console.log(""),console.log("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5B8C\u4E86!"),console.log(`\u5909\u66F4\u3092\u53CD\u6620\u3059\u308B\u306B\u306F\u3001Claude Code / Claude Desktop \u3092\u518D\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\u3002
75
+ `)}async function Ge(){console.log(`
75
76
  === freee-mcp Configuration Setup ===
76
77
  `),console.log("\u3053\u306E\u30A6\u30A3\u30B6\u30FC\u30C9\u3067\u306F\u3001freee-mcp\u306E\u8A2D\u5B9A\u3068\u8A8D\u8A3C\u3092\u5BFE\u8A71\u5F0F\u3067\u884C\u3044\u307E\u3059\u3002"),console.log(`freee OAuth\u8A8D\u8A3C\u60C5\u5831\u304C\u5FC5\u8981\u3067\u3059\u3002
77
- `);try{let t=await ut(),e=await ft(),{selected:n,all:r}=await dt(e.accessToken);await gt(t,n,r)}catch(t){t instanceof Error?console.error(`
78
+ `);try{let t=await Pt(),e=await vt(),{selected:n,all:r}=await Tt(e.accessToken);await xt(t,n,r),await bt()}catch(t){t instanceof Error?console.error(`
78
79
  Error: ${t.message}`):console.error(`
79
- \u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:`,t),process.exit(1)}finally{$()}}var mt=async()=>{let e=process.argv.slice(2)[0];if(e==="configure"){await De();return}e&&e!=="client"&&(console.error(`Unknown subcommand: ${e}`),console.error("Usage: freee-mcp [configure]"),console.error(" configure - Interactive configuration setup"),process.exit(1)),console.error("Starting freee MCP server"),await Se()};mt().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
80
+ \u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:`,t),process.exit(1)}finally{R()}}var St=async()=>{let e=process.argv.slice(2)[0];if(e==="configure"){await Ge();return}e&&e!=="client"&&(console.error(`Unknown subcommand: ${e}`),console.error("Usage: freee-mcp [configure]"),console.error(" configure - Interactive configuration setup"),process.exit(1)),console.error("Starting freee MCP server"),await Ne()};St().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
@@ -26,29 +26,9 @@ export declare class AuthenticationManager {
26
26
  getCliAuthHandler(state: string): CliAuthHandler | undefined;
27
27
  removeCliAuthHandler(state: string): void;
28
28
  }
29
- /**
30
- * CallbackServer - manages the OAuth callback HTTP server
31
- * Encapsulates server state that was previously global
32
- */
33
- export declare class CallbackServer {
34
- private server;
35
- private port;
36
- private authManager;
37
- constructor(authManager: AuthenticationManager);
38
- getRedirectUri(): string;
39
- getPort(): number | null;
40
- isRunning(): boolean;
41
- start(): Promise<void>;
42
- stop(): void;
43
- private checkPortAvailable;
44
- private findAvailablePort;
45
- private handleCallback;
46
- }
47
29
  export declare function getActualRedirectUri(): string;
48
- export declare function getActualCallbackPort(): number | null;
49
30
  export declare function startCallbackServer(): Promise<void>;
50
31
  export declare function registerAuthenticationRequest(state: string, codeVerifier: string): void;
51
32
  export declare function stopCallbackServer(): void;
52
33
  export declare function getDefaultAuthManager(): AuthenticationManager;
53
- export declare function getDefaultCallbackServer(): CallbackServer;
54
34
  export {};
@@ -14,11 +14,6 @@ export interface FullConfig {
14
14
  companies: Record<string, CompanyConfig>;
15
15
  downloadDir?: string;
16
16
  }
17
- export interface LegacyCompaniesConfig {
18
- defaultCompanyId: string;
19
- currentCompanyId: string;
20
- companies: Record<string, CompanyConfig>;
21
- }
22
17
  /**
23
18
  * Load full config from file
24
19
  */
@@ -35,10 +30,6 @@ export declare function getCurrentCompanyId(): Promise<string>;
35
30
  * Set current company
36
31
  */
37
32
  export declare function setCurrentCompany(companyId: string, name?: string, description?: string): Promise<void>;
38
- /**
39
- * Get list of all companies
40
- */
41
- export declare function getCompanyList(): Promise<CompanyConfig[]>;
42
33
  /**
43
34
  * Get company info by ID
44
35
  */
@@ -48,7 +39,3 @@ export declare function getCompanyInfo(companyId: string): Promise<CompanyConfig
48
39
  * Returns configured directory or system temp directory as default
49
40
  */
50
41
  export declare function getDownloadDir(): Promise<string>;
51
- /**
52
- * Set download directory for binary files
53
- */
54
- export declare function setDownloadDir(dir: string): Promise<void>;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * MCP configuration management for Claude Code and Claude Desktop
3
+ *
4
+ * Handles reading, adding, and removing freee-mcp configuration
5
+ * from Claude Code (~/.claude.json) and Claude Desktop config files.
6
+ */
7
+ export type McpTarget = 'claude-code' | 'claude-desktop';
8
+ export type McpConfigStatus = {
9
+ path: string;
10
+ exists: boolean;
11
+ hasFreeeConfig: boolean;
12
+ };
13
+ /**
14
+ * Get the MCP configuration file path for the specified target.
15
+ */
16
+ export declare function getMcpConfigPath(target: McpTarget): string;
17
+ /**
18
+ * Get display name for the target.
19
+ */
20
+ export declare function getTargetDisplayName(target: McpTarget): string;
21
+ /**
22
+ * Check the current MCP configuration status for the specified target.
23
+ */
24
+ export declare function checkMcpConfigStatus(target: McpTarget): Promise<McpConfigStatus>;
25
+ /**
26
+ * Add freee-mcp configuration to the specified target.
27
+ * Preserves existing configuration while adding/updating the freee-mcp entry.
28
+ */
29
+ export declare function addFreeeMcpConfig(target: McpTarget): Promise<void>;
30
+ /**
31
+ * Remove freee-mcp configuration from the specified target.
32
+ * Preserves other MCP server configurations.
33
+ */
34
+ export declare function removeFreeeMcpConfig(target: McpTarget): Promise<void>;
@@ -0,0 +1 @@
1
+ export {};
package/dist/config.d.ts CHANGED
@@ -25,11 +25,6 @@ export interface Config {
25
25
  * Priority: environment variables > config file > error
26
26
  */
27
27
  export declare function loadConfig(): Promise<Config>;
28
- /**
29
- * Get config synchronously (must call loadConfig first)
30
- * For backward compatibility with existing code
31
- */
32
- export declare function getConfig(): Config;
33
28
  /**
34
29
  * Legacy export for backward compatibility
35
30
  * @deprecated Use loadConfig() or getConfig() instead
@@ -27,3 +27,7 @@ export declare const AUTH_TIMEOUT_MS: number;
27
27
  * File permission for sensitive configuration files (owner read/write only)
28
28
  */
29
29
  export declare const CONFIG_FILE_PERMISSION = 384;
30
+ /**
31
+ * Base URL for freee API
32
+ */
33
+ export declare const FREEE_API_URL = "https://api.freee.co.jp";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * E2E tests for the configure CLI command
3
+ * Tests the complete configuration flow without affecting the actual machine settings
4
+ */
5
+ export {};
@@ -115,17 +115,6 @@ export declare const mockUnauthorizedResponse: {
115
115
  error: string;
116
116
  error_description: string;
117
117
  };
118
- export declare const mockForbiddenResponse: {
119
- error: string;
120
- error_description: string;
121
- };
122
- export declare const mockBadRequestResponse: {
123
- status_code: number;
124
- errors: {
125
- type: string;
126
- messages: string[];
127
- }[];
128
- };
129
118
  export declare const mockNotFoundResponse: {
130
119
  status_code: number;
131
120
  errors: {
@@ -133,13 +122,6 @@ export declare const mockNotFoundResponse: {
133
122
  messages: string[];
134
123
  }[];
135
124
  };
136
- export declare const mockServerErrorResponse: {
137
- status_code: number;
138
- errors: {
139
- type: string;
140
- messages: string[];
141
- }[];
142
- };
143
125
  export declare const mockTokenResponse: {
144
126
  access_token: string;
145
127
  refresh_token: string;
@@ -148,11 +130,3 @@ export declare const mockTokenResponse: {
148
130
  scope: string;
149
131
  created_at: number;
150
132
  };
151
- export declare const mockRefreshedTokenResponse: {
152
- access_token: string;
153
- refresh_token: string;
154
- token_type: string;
155
- expires_in: number;
156
- scope: string;
157
- created_at: number;
158
- };
@@ -23,10 +23,6 @@ interface MockResponse {
23
23
  text: () => Promise<string>;
24
24
  }
25
25
  type MockFetchFn = MockInstance<(url: string, options?: RequestInit) => Promise<MockResponse>>;
26
- /**
27
- * Creates a mock fetch function that responds based on URL patterns
28
- */
29
- export declare function createMockFetch(config?: MockApiConfig): MockFetchFn;
30
26
  /**
31
27
  * Sets up global fetch mock for E2E testing
32
28
  */
@@ -35,27 +31,4 @@ export declare function setupMockApi(config?: MockApiConfig): MockFetchFn;
35
31
  * Clears the global fetch mock
36
32
  */
37
33
  export declare function clearMockApi(): void;
38
- interface MockScenarioResponse {
39
- status: number;
40
- body: unknown;
41
- }
42
- /**
43
- * Creates mock responses for specific test scenarios
44
- */
45
- export declare const mockScenarios: {
46
- /** Successful API call */
47
- success: (body: unknown) => MockScenarioResponse;
48
- /** Created response (201) */
49
- created: (body: unknown) => MockScenarioResponse;
50
- /** No content response (204) */
51
- noContent: () => MockScenarioResponse;
52
- /** Bad request (400) */
53
- badRequest: (messages?: string[]) => MockScenarioResponse;
54
- /** Unauthorized (401) */
55
- unauthorized: () => MockScenarioResponse;
56
- /** Not found (404) */
57
- notFound: () => MockScenarioResponse;
58
- /** Server error (500) */
59
- serverError: () => MockScenarioResponse;
60
- };
61
34
  export {};