@him0/freee-mcp 0.4.0 → 0.5.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 +12 -22
- package/bin/cli.js +31 -35
- package/dist/config.d.ts +0 -8
- package/dist/index.cjs +31 -35
- package/dist/index.esm.js +31 -35
- package/package.json +1 -1
- package/dist/e2e/api-mode.e2e.test.d.ts +0 -5
- package/dist/openapi/converter.d.ts +0 -2
- package/dist/openapi/converter.test.d.ts +0 -1
package/README.md
CHANGED
|
@@ -49,12 +49,17 @@ npx @him0/freee-mcp configure
|
|
|
49
49
|
"mcpServers": {
|
|
50
50
|
"freee": {
|
|
51
51
|
"command": "npx",
|
|
52
|
-
"args": ["@him0/freee-mcp"
|
|
52
|
+
"args": ["@him0/freee-mcp"]
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
> **⚠️ 環境変数での設定について**
|
|
59
|
+
> 環境変数(`FREEE_CLIENT_ID`、`FREEE_CLIENT_SECRET` など)を使った設定は非推奨です。
|
|
60
|
+
> 代わりに `npx @him0/freee-mcp configure` を実行して設定ファイルに移行してください。
|
|
61
|
+
> 環境変数設定は将来のバージョンで削除される予定です。
|
|
62
|
+
|
|
58
63
|
## Claude Plugin として使う
|
|
59
64
|
|
|
60
65
|
Claude Code でプラグインとしてインストールすると、API リファレンス付きのスキルが利用できます:
|
|
@@ -88,25 +93,6 @@ Claude との会話中に API の使い方を質問すると、これらのリ
|
|
|
88
93
|
例: 「先月の○○社への請求書を参考に、今月分を作成して」
|
|
89
94
|
```
|
|
90
95
|
|
|
91
|
-
## 起動モード
|
|
92
|
-
|
|
93
|
-
freee-mcp は2つのモードで起動できます:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
# クライアントモード(推奨):HTTPメソッド別の6ツール
|
|
97
|
-
npx @him0/freee-mcp client
|
|
98
|
-
|
|
99
|
-
# APIモード:エンドポイントごとの個別ツール(数百個)
|
|
100
|
-
npx @him0/freee-mcp api
|
|
101
|
-
# または
|
|
102
|
-
npx @him0/freee-mcp
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
| モード | ツール数 | 特徴 | 推奨 |
|
|
106
|
-
| ------ | -------- | ---- | ---- |
|
|
107
|
-
| client | 6個 | コンテキスト使用量が少ない、任意のパスを指定可能 | ✅ |
|
|
108
|
-
| api | 数百個 | エンドポイントごとに専用ツール、コンテキスト消費大 | ❌ |
|
|
109
|
-
|
|
110
96
|
## 利用可能なツール
|
|
111
97
|
|
|
112
98
|
### 管理ツール
|
|
@@ -120,7 +106,7 @@ npx @him0/freee-mcp
|
|
|
120
106
|
| `freee_help` | 使い方ガイド |
|
|
121
107
|
| `freee_status` | 現在の状態と推奨アクション |
|
|
122
108
|
|
|
123
|
-
### API
|
|
109
|
+
### API ツール
|
|
124
110
|
|
|
125
111
|
HTTPメソッドごとのシンプルなツール構成:
|
|
126
112
|
|
|
@@ -144,7 +130,7 @@ pnpm install
|
|
|
144
130
|
|
|
145
131
|
pnpm dev # 開発サーバー(ウォッチモード)
|
|
146
132
|
pnpm build # ビルド
|
|
147
|
-
pnpm
|
|
133
|
+
pnpm typecheck # 型チェック
|
|
148
134
|
pnpm lint # リント
|
|
149
135
|
pnpm test:run # テスト
|
|
150
136
|
|
|
@@ -156,6 +142,10 @@ pnpm generate:references
|
|
|
156
142
|
|
|
157
143
|
TypeScript / Model Context Protocol SDK / OAuth 2.0 + PKCE / Zod / esbuild
|
|
158
144
|
|
|
145
|
+
### アーキテクチャ詳細
|
|
146
|
+
|
|
147
|
+
プロジェクトのアーキテクチャ、内部構造、開発ガイドラインについては [CLAUDE.md](./CLAUDE.md) を参照してください。
|
|
148
|
+
|
|
159
149
|
## ライセンス
|
|
160
150
|
|
|
161
151
|
ISC
|
package/bin/cli.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
2
|
|
|
3
|
-
var
|
|
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):$;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||$}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")),P={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:V}},P}function nt(){if(!P)throw new Error("Config not loaded. Call loadConfig() first.");return P}function G(t){Te=t}function ae(){return Te}var Te,P,l,C=ee(()=>{"use strict";I();F();Te=!1,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]}})});C();import{McpServer as Et}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as At}from"@modelcontextprotocol/sdk/server/stdio.js";C();import st from"http";import{URL as ct}from"url";import lt from"net";C();import Se from"crypto";C();F();import k from"fs/promises";import O from"path";async function _(t){return t.json().catch(()=>({}))}function se(){return O.join(x(),"tokens.json")}async function K(t){let e=se(),n=O.dirname(e);try{console.error(`[info] Creating directory: ${n}`),await k.mkdir(n,{recursive:!0}),console.error(`[info] Writing tokens to: ${e}`),await k.writeFile(e,JSON.stringify(t,null,2),{mode:q}),console.error("[info] Tokens saved successfully")}catch(r){throw console.error("[error] Failed to save tokens:",r),r}}async function ce(){let t=se();try{let e=await k.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await ot();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function rt(t){return Date.now()<t.expires_at}async function ot(){let t=x();try{let n=(await k.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));if(n.length>0){let r=O.join(t,n[0]),o=await k.readFile(r,"utf8"),i=JSON.parse(o);return await K(i),await Promise.all(n.map(a=>k.unlink(O.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 it(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 _(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 K(r),r}async function xe(){let t=se();try{await k.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 at()}async function at(){let t=x();try{let n=(await k.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));await Promise.all(n.map(r=>k.unlink(O.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 Ie(){let t=await ce();if(!t)return null;if(rt(t))return t.access_token;try{return(await it(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function Re(){let t=Se.randomBytes(32).toString("base64url"),e=Se.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function W(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 Z(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 _(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 K(i),i}var le=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)}},pe=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=st.createServer((i,a)=>{console.error(`Callback request: ${i.method} ${i.url}`);let s=new ct(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=lt.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 p=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: ${p}</p>`),s)s.reject(new Error(`OAuth error: ${i} - ${a}`));else if(o){let d=this.authManager.getPendingAuthentication(o);d&&(clearTimeout(d.timeout),d.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 m=this.authManager.getPendingAuthentication(o);if(!m){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),Z(r,m.codeVerifier,this.getRedirectUri()).then(p=>{console.error("Token exchange successful!"),m.resolve(p)}).catch(p=>{console.error("Token exchange failed:",p),m.reject(p)})}},ue=new le,fe=new pe(ue);function M(){return fe.getRedirectUri()}async function Y(){return fe.start()}function $e(t,e){ue.registerAuthentication(t,e)}function U(){fe.stop()}function Fe(){return ue}C();import dt from"crypto";import{z as me}from"zod";C();I();import pt from"fs/promises";import ut from"path";function ft(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function mt(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 v(t,e,n,r,o){let i=o||l.freee.apiUrl,a=await T(),s=await Ie();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
|
|
3
|
+
var Re=Object.defineProperty;var q=(t,e)=>()=>(t&&(e=t(t=0)),e);var ue=(t,e)=>{for(var n in e)Re(t,n,{get:e[n],enumerable:!0})};import fe from"path";import De from"os";function E(){return process.env.XDG_CONFIG_HOME?fe.join(process.env.XDG_CONFIG_HOME,ge):fe.join(De.homedir(),".config",ge)}var ge,v,j,M,b=q(()=>{"use strict";ge="freee-mcp";v=54321,j=300*1e3,M=384});var me={};ue(me,{getCompanyInfo:()=>x,getCompanyList:()=>je,getCurrentCompanyId:()=>A,getDownloadDir:()=>W,loadFullConfig:()=>m,saveFullConfig:()=>_,setCurrentCompany:()=>K,setDownloadDir:()=>Me});import z from"fs/promises";import de from"path";import Fe from"os";function G(){return de.join(E(),"config.json")}async function Oe(){let t=de.dirname(G());await z.mkdir(t,{recursive:!0})}function Le(t){return t!=null&&typeof t=="object"&&"defaultCompanyId"in t&&"currentCompanyId"in t&&"companies"in t&&!("clientId"in t)}function Ue(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=G();try{let e=await z.readFile(t,"utf8"),n=JSON.parse(e);if(Le(n)){let r=Ue(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 Oe();let e=G();await z.writeFile(e,JSON.stringify(t,null,2),{mode:M})}async function A(){return(await m()).currentCompanyId}async function K(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 je(){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 W(){return(await m()).downloadDir||Fe.tmpdir()}async function Me(t){let e=await m();e.downloadDir=t,await _(e)}var P=q(()=>{"use strict";b()});var he={};ue(he,{config:()=>l,getConfig:()=>He,loadConfig:()=>Y});function Ne(){return!!(process.env.FREEE_CLIENT_ID||process.env.FREEE_CLIENT_SECRET)}async function Y(){if(w)return w;let t=await m(),e,n,r;if(Ne())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):v;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||v}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:j}},w}function He(){if(!w)throw new Error("Config not loaded. Call loadConfig() first.");return w}var w,l,h=q(()=>{"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 at}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as st}from"@modelcontextprotocol/sdk/server/stdio.js";h();import ze from"http";import{URL as Ge}from"url";import Ke from"net";h();import we from"crypto";h();b();import C from"fs/promises";import I from"path";async function y(t){return t.json().catch(()=>({}))}function X(){return I.join(E(),"tokens.json")}async function N(t){let e=X(),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:M}),console.error("[info] Tokens saved successfully")}catch(r){throw console.error("[error] Failed to save tokens:",r),r}}async function Q(){let t=X();try{let e=await C.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await Je();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function Be(t){return Date.now()<t.expires_at}async function Je(){let t=E();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 N(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 Ve(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 N(r),r}async function ye(){let t=X();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 qe()}async function qe(){let t=E();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 Ce(){let t=await Q();if(!t)return null;if(Be(t))return t.access_token;try{return(await Ve(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function ke(){let t=we.randomBytes(32).toString("base64url"),e=we.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function H(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 B(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 N(i),i}var Z=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)}},ee=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=ze.createServer((i,a)=>{console.error(`Callback request: ${i.method} ${i.url}`);let s=new Ge(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=Ke.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),B(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)})}},te=new Z,ne=new ee(te);function S(){return ne.getRedirectUri()}async function J(){return ne.start()}function _e(t,e){te.registerAuthentication(t,e)}function $(){ne.stop()}function Ae(){return te}h();import Ze from"crypto";import{z as re}from"zod";h();P();import We from"fs/promises";import Ye from"path";function Xe(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function Qe(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 A(),s=await Ce();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
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
|
|
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,d])=>{d!==void 0&&k.searchParams.append(f,String(d))}),k.searchParams.append("company_id",String(a));let g=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(g.status===401||g.status===403){let f=await y(g);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
7
|
\u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${a}
|
|
8
|
-
\u30A8\u30E9\u30FC\u8A73\u7D30: ${
|
|
8
|
+
\u30A8\u30E9\u30FC\u8A73\u7D30: ${g.status} ${JSON.stringify(f)}
|
|
9
9
|
|
|
10
10
|
\u78BA\u8A8D\u4E8B\u9805:
|
|
11
11
|
1. FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B
|
|
12
12
|
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
13
|
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(!
|
|
14
|
+
4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(!g.ok){let f=await y(g),d=`API request failed: ${g.status}`;if(f&&f.errors&&Array.isArray(f.errors)){let U=[];for(let T of f.errors)T.messages&&Array.isArray(T.messages)&&U.push(...T.messages);U.length>0&&(d+=`
|
|
15
15
|
|
|
16
16
|
\u30A8\u30E9\u30FC\u8A73\u7D30:
|
|
17
|
-
${
|
|
18
|
-
`)}`,
|
|
17
|
+
${U.join(`
|
|
18
|
+
`)}`,g.status===400&&(d+=`
|
|
19
19
|
|
|
20
|
-
\u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,
|
|
21
|
-
\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`,
|
|
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||(
|
|
20
|
+
\u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,d+=`
|
|
21
|
+
\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`,d+=`
|
|
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||(d+=`
|
|
23
23
|
|
|
24
|
-
\u8A73\u7D30: ${JSON.stringify(f)}`),new Error(
|
|
24
|
+
\u8A73\u7D30: ${JSON.stringify(f)}`),new Error(d)}let V=g.headers.get("content-type")||"";if(Xe(V)){let f=await W(),d=Qe(V),T=`freee_download_${Date.now()}${d}`,le=Ye.join(f,T),pe=await g.arrayBuffer();return await We.writeFile(le,Buffer.from(pe)),{type:"binary",filePath:le,mimeType:V,size:pe.byteLength}}return g.json()}P();function Ee(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 A(),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:
|
|
25
25
|
\u4F1A\u793EID: ${e}
|
|
26
26
|
\u4F1A\u793E\u540D: ${n?.name||"Unknown"}
|
|
27
27
|
\u30E6\u30FC\u30B6\u30FC\u8A73\u7D30:
|
|
@@ -29,53 +29,49 @@ ${JSON.stringify(r,null,2)}`}]}}catch(e){return{content:[{type:"text",text:`\u30
|
|
|
29
29
|
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
30
|
\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
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
|
|
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}=
|
|
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}=ke(),r=Ze.randomBytes(16).toString("hex"),o=H(n,r,S());return _e(r,e),console.error(`Authentication URL: ${o}`),{content:[{type:"text",text:`\u8A8D\u8A3CURL: ${o}
|
|
33
33
|
|
|
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
|
|
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 Q();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
35
|
\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
|
|
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 ye(),{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:re.string().describe("\u4E8B\u696D\u6240ID"),name:re.string().optional().describe("\u4E8B\u696D\u6240\u540D"),description:re.string().optional().describe("\u8AAC\u660E")},async e=>{try{let{company_id:n,name:r,description:o}=e;return await K(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 A(),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 A();return e?.companies?.length?{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7:
|
|
37
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
|
|
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 et from"node:fs";import se from"node:path";import{fileURLToPath as tt}from"node:url";var nt=se.dirname(tt(import.meta.url)),rt=se.resolve(nt,"../../openapi/minimal");function D(t){let e=se.join(rt,t),n=et.readFileSync(e,"utf-8");return JSON.parse(n)}var oe=null;function ie(){return oe===null&&(oe={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"}}),oe}var ae=new Proxy({},{get(t,e){return ie()[e]},ownKeys(){return Object.keys(ie())},getOwnPropertyDescriptor(t,e){let n=ie();if(e in n)return{enumerable:!0,configurable:!0,value:n[e]}}});function Pe(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 Te(t,e,n){let r=t.toLowerCase();if(n!==void 0){let o=ae[n],i=Pe(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(ae)){let a=Pe(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 ve(){let t=[];for(let[,e]of Object.entries(ae)){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(`
|
|
39
39
|
## ${e.name} (${e.baseUrl})
|
|
40
40
|
${r.sort().join(`
|
|
41
41
|
`)}`)}return t.join(`
|
|
42
|
-
`)}function
|
|
42
|
+
`)}function ot(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="binary"}function it(t){let e=(t.size/1024).toFixed(2);return`\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u307E\u3057\u305F
|
|
43
43
|
|
|
44
44
|
\u4FDD\u5B58\u5834\u6240: ${t.filePath}
|
|
45
45
|
MIME\u30BF\u30A4\u30D7: ${t.mimeType}
|
|
46
|
-
\u30B5\u30A4\u30BA: ${e} KB`}
|
|
46
|
+
\u30B5\u30A4\u30BA: ${e} KB`}var F="service: accounting/hr/invoice/pm/sm",O=c.enum(["accounting","hr","invoice","pm","sm"]).describe("\u5BFE\u8C61\u306Efreee\u30B5\u30FC\u30D3\u30B9");function L(t){return async e=>{try{let{service:n,path:r,query:o,body:i}=e,a=Te(t,r,n);if(!a.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${a.message}
|
|
47
47
|
|
|
48
|
-
\
|
|
49
|
-
MIME\u30BF\u30A4\u30D7: ${t.mimeType}
|
|
50
|
-
\u30B5\u30A4\u30BA: ${e} KB`}var B="service: accounting/hr/invoice/pm/sm",H=c.enum(["accounting","hr","invoice","pm","sm"]).describe("\u5BFE\u8C61\u306Efreee\u30B5\u30FC\u30D3\u30B9");function z(t){return async e=>{try{let{service:n,path:r,query:o,body:i}=e,a=Ue(t,r,n);if(!a.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${a.message}
|
|
51
|
-
|
|
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 s=await v(t,a.actualPath,o,i,a.baseUrl);return kt(s)?{content:[{type:"text",text:Pt(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 Be(t){t.tool("freee_api_get",`freee API GET\u3002${B}`,{service:H,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)")},z("GET")),t.tool("freee_api_post",`freee API POST\u3002${B}`,{service:H,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)")},z("POST")),t.tool("freee_api_put",`freee API PUT\u3002${B}`,{service:H,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)")},z("PUT")),t.tool("freee_api_delete",`freee API DELETE\u3002${B}`,{service:H,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)")},z("DELETE")),t.tool("freee_api_patch",`freee API PATCH\u3002${B}`,{service:H,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)")},z("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${Ne()}
|
|
48
|
+
\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 ot(s)?{content:[{type:"text",text:it(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 be(t){t.tool("freee_api_get",`freee API GET\u3002${F}`,{service:O,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)")},L("GET")),t.tool("freee_api_post",`freee API POST\u3002${F}`,{service:O,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)")},L("POST")),t.tool("freee_api_put",`freee API PUT\u3002${F}`,{service:O,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)")},L("PUT")),t.tool("freee_api_delete",`freee API DELETE\u3002${F}`,{service:O,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)")},L("DELETE")),t.tool("freee_api_patch",`freee API PATCH\u3002${F}`,{service:O,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)")},L("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${ve()}
|
|
53
49
|
|
|
54
50
|
\u4F7F\u7528\u4F8B:
|
|
55
51
|
freee_api_get { "service": "accounting", "path": "/api/1/deals", "query": { "limit": 10 } }
|
|
56
52
|
freee_api_get { "service": "invoice", "path": "/invoices" }
|
|
57
|
-
freee_api_post { "service": "accounting", "path": "/api/1/deals", "body": { "issue_date": "2024-01-01", ... } }`}]}))}async function
|
|
53
|
+
freee_api_post { "service": "accounting", "path": "/api/1/deals", "body": { "issue_date": "2024-01-01", ... } }`}]}))}async function xe(){let t=await Y(),e=new at({name:t.server.name,version:t.server.version});Ee(e),be(e);try{await J(),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 st;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 Ie from"prompts";import*as Se from"node:os";import ce from"node:crypto";import ct from"open";h();P();b();async function lt(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 pt(){let t=await Promise.resolve().then(()=>(P(),me)).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
|
|
58
54
|
`)),console.log(`\u30B9\u30C6\u30C3\u30D7 1/3: OAuth\u8A8D\u8A3C\u60C5\u5831\u306E\u5165\u529B
|
|
59
|
-
`);let n=await
|
|
55
|
+
`);let n=await Ie([{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||v)}]);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
56
|
\u8A8D\u8A3C\u60C5\u5831\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002
|
|
61
|
-
`),{clientId:r,clientSecret:o,callbackPort:i}}async function
|
|
62
|
-
`),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(
|
|
57
|
+
`),{clientId:r,clientSecret:o,callbackPort:i}}async function ut(){console.log(`\u30B9\u30C6\u30C3\u30D7 2/3: OAuth\u8A8D\u8A3C
|
|
58
|
+
`),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(h(),he)).then(a=>a.loadConfig()),await J();let t=ce.randomBytes(32).toString("base64url"),e=ce.createHash("sha256").update(t).digest("base64url"),n=ce.randomBytes(16).toString("base64url"),r=H(e,n,S());console.log(`
|
|
63
59
|
\u8A8D\u8A3CURL: ${r}
|
|
64
|
-
`),await
|
|
65
|
-
`);let o=
|
|
66
|
-
`),{accessToken:s.access_token,refreshToken:s.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function
|
|
67
|
-
`),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await
|
|
60
|
+
`),await ct(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
|
|
61
|
+
`);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"))},j);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 B(a,t,S());return console.log(`\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002
|
|
62
|
+
`),{accessToken:s.access_token,refreshToken:s.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function ft(t){console.log(`\u30B9\u30C6\u30C3\u30D7 3/3: \u30C7\u30D5\u30A9\u30EB\u30C8\u4E8B\u696D\u6240\u306E\u9078\u629E
|
|
63
|
+
`),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await lt(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 Ie({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(`
|
|
68
64
|
${r.display_name||r.name} \u3092\u9078\u629E\u3057\u307E\u3057\u305F\u3002
|
|
69
|
-
`),{selected:{id:r.id,name:r.name,displayName:r.display_name||r.name,role:r.role},all:e}}async function
|
|
65
|
+
`),{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
|
|
70
66
|
`),console.log(`=== MCP\u8A2D\u5B9A ===
|
|
71
67
|
`),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:
|
|
72
|
-
`);let o=
|
|
68
|
+
`);let o=Se.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}
|
|
73
69
|
`),console.log(JSON.stringify({mcpServers:{"freee-mcp":{command:"npx",args:["@him0/freee-mcp","client"]}}},null,2)),console.log(`
|
|
74
70
|
\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5B8C\u4E86!
|
|
75
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"),console.log(`Claude desktop\u3092\u518D\u8D77\u52D5\u3059\u308B\u3068\u3001freee-mcp\u304C\u5229\u7528\u53EF\u80FD\u306B\u306A\u308A\u307E\u3059\u3002
|
|
76
|
-
`)}async function
|
|
72
|
+
`)}async function $e(){console.log(`
|
|
77
73
|
=== freee-mcp Configuration Setup ===
|
|
78
74
|
`),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
|
|
79
|
-
`);try{let t=await
|
|
75
|
+
`);try{let t=await pt(),e=await ut(),{selected:n,all:r}=await ft(e.accessToken);await gt(t,n,r)}catch(t){t instanceof Error?console.error(`
|
|
80
76
|
Error: ${t.message}`):console.error(`
|
|
81
|
-
\u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:`,t),process.exit(1)}finally{
|
|
77
|
+
\u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:`,t),process.exit(1)}finally{$()}}var dt=async()=>{let e=process.argv.slice(2)[0];if(e==="configure"){await $e();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 xe()};dt().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
|
package/dist/config.d.ts
CHANGED
|
@@ -35,11 +35,3 @@ export declare function getConfig(): Config;
|
|
|
35
35
|
* @deprecated Use loadConfig() or getConfig() instead
|
|
36
36
|
*/
|
|
37
37
|
export declare const config: Config;
|
|
38
|
-
/**
|
|
39
|
-
* Sets the API mode (client or individual tools)
|
|
40
|
-
*/
|
|
41
|
-
export declare function setMode(useClient: boolean): void;
|
|
42
|
-
/**
|
|
43
|
-
* Get current mode (client or individual tools)
|
|
44
|
-
*/
|
|
45
|
-
export declare function getMode(): boolean;
|
package/dist/index.cjs
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`),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):O;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||O}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")),E={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:q}},E}function _t(){if(!E)throw new Error("Config not loaded. Call loadConfig() first.");return E}function W(t){$e=t}function de(){return $e}var $e,E,l,w=se(()=>{"use strict";S();M();$e=!1,E=null;l=new Proxy({},{get(t,e){if(!E)throw new Error("Config not loaded. Call loadConfig() first in async context.");return E[e]}})});var tt=require("@modelcontextprotocol/sdk/server/mcp.js"),nt=require("@modelcontextprotocol/sdk/server/stdio.js");w();var Ue=u(require("http"),1),Ne=require("url"),Le=u(require("net"),1);w();var ye=u(require("crypto"),1);w();var _=u(require("fs/promises"),1),R=u(require("path"),1);w();M();async function P(t){return t.json().catch(()=>({}))}function ge(){return R.default.join(I(),"tokens.json")}async function Z(t){let e=ge(),n=R.default.dirname(e);try{console.error(`[info] Creating directory: ${n}`),await _.default.mkdir(n,{recursive:!0}),console.error(`[info] Writing tokens to: ${e}`),await _.default.writeFile(e,JSON.stringify(t,null,2),{mode:G}),console.error("[info] Tokens saved successfully")}catch(r){throw console.error("[error] Failed to save tokens:",r),r}}async function he(){let t=ge();try{let e=await _.default.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await Pt();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function kt(t){return Date.now()<t.expires_at}async function Pt(){let t=I();try{let n=(await _.default.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));if(n.length>0){let r=R.default.join(t,n[0]),o=await _.default.readFile(r,"utf8"),i=JSON.parse(o);return await Z(i),await Promise.all(n.map(a=>_.default.unlink(R.default.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 Et(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 P(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 Z(r),r}async function De(){let t=ge();try{await _.default.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 At()}async function At(){let t=I();try{let n=(await _.default.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));await Promise.all(n.map(r=>_.default.unlink(R.default.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 Oe(){let t=await he();if(!t)return null;if(kt(t))return t.access_token;try{return(await Et(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function Me(){let t=ye.default.randomBytes(32).toString("base64url"),e=ye.default.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function Y(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 X(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 P(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 Z(i),i}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)}},we=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=Ue.default.createServer((i,a)=>{console.error(`Callback request: ${i.method} ${i.url}`);let s=new Ne.URL(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=Le.default.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 p=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: ${p}</p>`),s)s.reject(new Error(`OAuth error: ${i} - ${a}`));else if(o){let g=this.authManager.getPendingAuthentication(o);g&&(clearTimeout(g.timeout),g.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 d=this.authManager.getPendingAuthentication(o);if(!d){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),X(r,d.codeVerifier,this.getRedirectUri()).then(p=>{console.error("Token exchange successful!"),d.resolve(p)}).catch(p=>{console.error("Token exchange failed:",p),d.reject(p)})}},_e=new Ce,ke=new we(_e);function N(){return ke.getRedirectUri()}async function Q(){return ke.start()}function je(t,e){_e.registerAuthentication(t,e)}function L(){ke.stop()}function Be(){return _e}var Je=u(require("crypto"),1),ee=require("zod");w();w();S();var He=u(require("fs/promises"),1),ze=u(require("path"),1);function bt(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function Tt(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 x(t,e,n,r,o){let i=o||l.freee.apiUrl,a=await v(),s=await Oe();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
|
|
1
|
+
"use strict";var Ge=Object.create;var Y=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var We=Object.getOwnPropertyNames;var Ye=Object.getPrototypeOf,Xe=Object.prototype.hasOwnProperty;var X=(t,e)=>()=>(t&&(e=t(t=0)),e);var ye=(t,e)=>{for(var n in e)Y(t,n,{get:e[n],enumerable:!0})},Qe=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of We(e))!Xe.call(t,o)&&o!==n&&Y(t,o,{get:()=>e[o],enumerable:!(r=Ke(e,o))||r.enumerable});return t};var p=(t,e,n)=>(n=t!=null?Ge(Ye(t)):{},Qe(e||!t||!t.__esModule?Y(n,"default",{value:t,enumerable:!0}):n,t));function P(){return process.env.XDG_CONFIG_HOME?Q.default.join(process.env.XDG_CONFIG_HOME,Ce):Q.default.join(we.default.homedir(),".config",Ce)}var Q,we,Ce,x,M,N,I=X(()=>{"use strict";Q=p(require("path"),1),we=p(require("os"),1),Ce="freee-mcp";x=54321,M=300*1e3,N=384});var _e={};ye(_e,{getCompanyInfo:()=>S,getCompanyList:()=>nt,getCurrentCompanyId:()=>E,getDownloadDir:()=>ne,loadFullConfig:()=>y,saveFullConfig:()=>A,setCurrentCompany:()=>te,setDownloadDir:()=>rt});function ee(){return Z.default.join(P(),"config.json")}async function Ze(){let t=Z.default.dirname(ee());await H.default.mkdir(t,{recursive:!0})}function et(t){return t!=null&&typeof t=="object"&&"defaultCompanyId"in t&&"currentCompanyId"in t&&"companies"in t&&!("clientId"in t)}function tt(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 y(){let t=ee();try{let e=await H.default.readFile(t,"utf8"),n=JSON.parse(e);if(et(n)){let r=tt(n);return await A(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 A(r),r}throw e}}async function A(t){await Ze();let e=ee();await H.default.writeFile(e,JSON.stringify(t,null,2),{mode:N})}async function E(){return(await y()).currentCompanyId}async function te(t,e,n){let r=await y();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 A(r)}async function nt(){let t=await y();return Object.values(t.companies).sort((e,n)=>(n.lastUsed||0)-(e.lastUsed||0))}async function S(t){return(await y()).companies[t]||null}async function ne(){return(await y()).downloadDir||ke.default.tmpdir()}async function rt(t){let e=await y();e.downloadDir=t,await A(e)}var H,Z,ke,T=X(()=>{"use strict";H=p(require("fs/promises"),1),Z=p(require("path"),1),ke=p(require("os"),1);I()});var Ae={};ye(Ae,{config:()=>l,getConfig:()=>it,loadConfig:()=>re});function ot(){return!!(process.env.FREEE_CLIENT_ID||process.env.FREEE_CLIENT_SECRET)}async function re(){if(k)return k;let t=await y(),e,n,r;if(ot())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
|
|
2
|
+
`),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}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")),k={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}},k}function it(){if(!k)throw new Error("Config not loaded. Call loadConfig() first.");return k}var k,l,C=X(()=>{"use strict";T();I();k=null;l=new Proxy({},{get(t,e){if(!k)throw new Error("Config not loaded. Call loadConfig() first in async context.");return k[e]}})});var He=require("@modelcontextprotocol/sdk/server/mcp.js"),Be=require("@modelcontextprotocol/sdk/server/stdio.js");C();var ve=p(require("http"),1),be=require("url"),xe=p(require("net"),1);C();var ae=p(require("crypto"),1);C();var h=p(require("fs/promises"),1),v=p(require("path"),1);C();I();async function w(t){return t.json().catch(()=>({}))}function oe(){return v.default.join(P(),"tokens.json")}async function B(t){let e=oe(),n=v.default.dirname(e);try{console.error(`[info] Creating directory: ${n}`),await h.default.mkdir(n,{recursive:!0}),console.error(`[info] Writing tokens to: ${e}`),await h.default.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 ie(){let t=oe();try{let e=await h.default.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await st();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function at(t){return Date.now()<t.expires_at}async function st(){let t=P();try{let n=(await h.default.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));if(n.length>0){let r=v.default.join(t,n[0]),o=await h.default.readFile(r,"utf8"),i=JSON.parse(o);return await B(i),await Promise.all(n.map(a=>h.default.unlink(v.default.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 ct(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 w(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 B(r),r}async function Ee(){let t=oe();try{await h.default.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 lt()}async function lt(){let t=P();try{let n=(await h.default.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));await Promise.all(n.map(r=>h.default.unlink(v.default.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 Pe(){let t=await ie();if(!t)return null;if(at(t))return t.access_token;try{return(await ct(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function Te(){let t=ae.default.randomBytes(32).toString("base64url"),e=ae.default.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function J(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 V(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 w(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 B(i),i}var se=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)}},ce=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=ve.default.createServer((i,a)=>{console.error(`Callback request: ${i.method} ${i.url}`);let s=new be.URL(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=xe.default.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 f=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: ${f}</p>`),s)s.reject(new Error(`OAuth error: ${i} - ${a}`));else if(o){let _=this.authManager.getPendingAuthentication(o);_&&(clearTimeout(_.timeout),_.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 u=this.authManager.getPendingAuthentication(o);if(!u){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),V(r,u.codeVerifier,this.getRedirectUri()).then(f=>{console.error("Token exchange successful!"),u.resolve(f)}).catch(f=>{console.error("Token exchange failed:",f),u.reject(f)})}},le=new se,pe=new ce(le);function $(){return pe.getRedirectUri()}async function q(){return pe.start()}function Ie(t,e){le.registerAuthentication(t,e)}function R(){pe.stop()}function Se(){return le}var De=p(require("crypto"),1),z=require("zod");C();C();T();var $e=p(require("fs/promises"),1),Re=p(require("path"),1);function pt(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function ut(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 D(t,e,n,r,o){let i=o||l.freee.apiUrl,a=await E(),s=await Pe();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
|
|
3
3
|
\u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${a}
|
|
4
|
-
\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
|
|
4
|
+
\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 u=i.endsWith("/")?i:i+"/",f=e.startsWith("/")?e.slice(1):e,_=new URL(f,u);n&&Object.entries(n).forEach(([g,m])=>{m!==void 0&&_.searchParams.append(g,String(m))}),_.searchParams.append("company_id",String(a));let d=await fetch(_.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 g=await w(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
|
|
5
5
|
\u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${a}
|
|
6
|
-
\u30A8\u30E9\u30FC\u8A73\u7D30: ${
|
|
6
|
+
\u30A8\u30E9\u30FC\u8A73\u7D30: ${d.status} ${JSON.stringify(g)}
|
|
7
7
|
|
|
8
8
|
\u78BA\u8A8D\u4E8B\u9805:
|
|
9
9
|
1. FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B
|
|
10
10
|
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
|
|
11
11
|
3. \u30C8\u30FC\u30AF\u30F3\u306E\u6709\u52B9\u671F\u9650\u304C\u5207\u308C\u3066\u3044\u306A\u3044\u304B
|
|
12
|
-
4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(!
|
|
12
|
+
4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(!d.ok){let g=await w(d),m=`API request failed: ${d.status}`;if(g&&g.errors&&Array.isArray(g.errors)){let j=[];for(let b of g.errors)b.messages&&Array.isArray(b.messages)&&j.push(...b.messages);j.length>0&&(m+=`
|
|
13
13
|
|
|
14
14
|
\u30A8\u30E9\u30FC\u8A73\u7D30:
|
|
15
|
-
${
|
|
16
|
-
`)}`,
|
|
15
|
+
${j.join(`
|
|
16
|
+
`)}`,d.status===400&&(m+=`
|
|
17
17
|
|
|
18
|
-
\u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,
|
|
19
|
-
\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`,
|
|
20
|
-
\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
|
|
18
|
+
\u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,m+=`
|
|
19
|
+
\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`,m+=`
|
|
20
|
+
\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 g?.errors||(m+=`
|
|
21
21
|
|
|
22
|
-
\u8A73\u7D30: ${JSON.stringify(
|
|
22
|
+
\u8A73\u7D30: ${JSON.stringify(g)}`),new Error(m)}let W=d.headers.get("content-type")||"";if(pt(W)){let g=await ne(),m=ut(W),b=`freee_download_${Date.now()}${m}`,me=Re.default.join(g,b),he=await d.arrayBuffer();return await $e.default.writeFile(me,Buffer.from(he)),{type:"binary",filePath:me,mimeType:W,size:he.byteLength}}return d.json()}T();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 E(),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_company \u3067\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}]};let r=await D("GET","/api/1/users/me");return{content:[{type:"text",text:`\u73FE\u5728\u306E\u30E6\u30FC\u30B6\u30FC\u60C5\u5831:
|
|
23
23
|
\u4F1A\u793EID: ${e}
|
|
24
24
|
\u4F1A\u793E\u540D: ${n?.name||"Unknown"}
|
|
25
25
|
\u30E6\u30FC\u30B6\u30FC\u8A73\u7D30:
|
|
@@ -27,53 +27,49 @@ ${JSON.stringify(r,null,2)}`}]}}catch(e){return{content:[{type:"text",text:`\u30
|
|
|
27
27
|
OAuth\u8A8D\u8A3C\u3092\u884C\u3046\u306B\u306F\u3001freee developers\u3067\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u4F5C\u6210\u3057\u3001
|
|
28
28
|
\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
|
|
29
29
|
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
|
-
\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}=
|
|
30
|
+
\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}=Te(),r=De.default.randomBytes(16).toString("hex"),o=J(n,r,$());return Ie(r,e),console.error(`Authentication URL: ${o}`),{content:[{type:"text",text:`\u8A8D\u8A3CURL: ${o}
|
|
31
31
|
|
|
32
|
-
\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
|
|
32
|
+
\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 ie();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"}
|
|
33
33
|
\u6709\u52B9\u671F\u9650: ${r}`+(n?"":`
|
|
34
|
-
\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
|
|
34
|
+
\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 Ee(),{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:z.z.string().describe("\u4E8B\u696D\u6240ID"),name:z.z.string().optional().describe("\u4E8B\u696D\u6240\u540D"),description:z.z.string().optional().describe("\u8AAC\u660E")},async e=>{try{let{company_id:n,name:r,description:o}=e;return await te(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 E(),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 D("GET","/api/1/companies"),n=await E();return e?.companies?.length?{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7:
|
|
35
35
|
${e.companies.map(o=>{let i=o.id===parseInt(n)?" *":"";return`${o.name} (${o.id})${i}`}).join(`
|
|
36
|
-
`)}`}]}:{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)}`}]}}})}var
|
|
36
|
+
`)}`}]}:{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)}`}]}}})}var c=require("zod");var Le=p(require("node:fs"),1),G=p(require("node:path"),1),Ue=require("node:url"),dt={},ft=G.default.dirname((0,Ue.fileURLToPath)(dt.url)),gt=G.default.resolve(ft,"../../openapi/minimal");function F(t){let e=G.default.join(gt,t),n=Le.default.readFileSync(e,"utf-8");return JSON.parse(n)}var ue=null;function fe(){return ue===null&&(ue={accounting:{schema:F("accounting.json"),baseUrl:"https://api.freee.co.jp",prefix:"accounting",name:"freee\u4F1A\u8A08 API"},hr:{schema:F("hr.json"),baseUrl:"https://api.freee.co.jp/hr",prefix:"hr",name:"freee\u4EBA\u4E8B\u52B4\u52D9 API"},invoice:{schema:F("invoice.json"),baseUrl:"https://api.freee.co.jp/iv",prefix:"invoice",name:"freee\u8ACB\u6C42\u66F8 API"},pm:{schema:F("pm.json"),baseUrl:"https://api.freee.co.jp/pm",prefix:"pm",name:"freee\u5DE5\u6570\u7BA1\u7406 API"},sm:{schema:F("sm.json"),baseUrl:"https://api.freee.co.jp/sm",prefix:"sm",name:"freee\u8CA9\u58F2 API"}}),ue}var ge=new Proxy({},{get(t,e){return fe()[e]},ownKeys(){return Object.keys(fe())},getOwnPropertyDescriptor(t,e){let n=fe();if(e in n)return{enumerable:!0,configurable:!0,value:n[e]}}});function Oe(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 u=o[i];if(t in u)return{isValid:!0,message:"Valid path and method",operation:u[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=ge[n],i=Oe(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(ge)){let a=Oe(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 Me(){let t=[];for(let[,e]of Object.entries(ge)){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(`
|
|
37
37
|
## ${e.name} (${e.baseUrl})
|
|
38
38
|
${r.sort().join(`
|
|
39
39
|
`)}`)}return t.join(`
|
|
40
|
-
`)}function
|
|
40
|
+
`)}function mt(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="binary"}function ht(t){let e=(t.size/1024).toFixed(2);return`\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u307E\u3057\u305F
|
|
41
41
|
|
|
42
42
|
\u4FDD\u5B58\u5834\u6240: ${t.filePath}
|
|
43
43
|
MIME\u30BF\u30A4\u30D7: ${t.mimeType}
|
|
44
|
-
\u30B5\u30A4\u30BA: ${e} KB`}
|
|
44
|
+
\u30B5\u30A4\u30BA: ${e} KB`}var O="service: accounting/hr/invoice/pm/sm",L=c.z.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=je(t,r,n);if(!a.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${a.message}
|
|
45
45
|
|
|
46
|
-
\
|
|
47
|
-
MIME\u30BF\u30A4\u30D7: ${t.mimeType}
|
|
48
|
-
\u30B5\u30A4\u30BA: ${e} KB`}var H="service: accounting/hr/invoice/pm/sm",z=c.z.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:i}=e,a=Ze(t,r,n);if(!a.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${a.message}
|
|
49
|
-
|
|
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 x(t,a.actualPath,o,i,a.baseUrl);return $t(s)?{content:[{type:"text",text:Ft(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 et(t){t.tool("freee_api_get",`freee API GET\u3002${H}`,{service:z,path:c.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),query:c.z.record(c.z.string(),c.z.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${H}`,{service:z,path:c.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),body:c.z.record(c.z.string(),c.z.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.z.record(c.z.string(),c.z.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${H}`,{service:z,path:c.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123, /invoices/123)"),body:c.z.record(c.z.string(),c.z.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.z.record(c.z.string(),c.z.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${H}`,{service:z,path:c.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),query:c.z.record(c.z.string(),c.z.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${H}`,{service:z,path:c.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),body:c.z.record(c.z.string(),c.z.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.z.record(c.z.string(),c.z.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${Ye()}
|
|
46
|
+
\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 D(t,a.actualPath,o,i,a.baseUrl);return mt(s)?{content:[{type:"text",text:ht(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 Ne(t){t.tool("freee_api_get",`freee API GET\u3002${O}`,{service:L,path:c.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),query:c.z.record(c.z.string(),c.z.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.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),body:c.z.record(c.z.string(),c.z.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.z.record(c.z.string(),c.z.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.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123, /invoices/123)"),body:c.z.record(c.z.string(),c.z.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.z.record(c.z.string(),c.z.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.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),query:c.z.record(c.z.string(),c.z.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.z.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),body:c.z.record(c.z.string(),c.z.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:c.z.record(c.z.string(),c.z.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${Me()}
|
|
51
47
|
|
|
52
48
|
\u4F7F\u7528\u4F8B:
|
|
53
49
|
freee_api_get { "service": "accounting", "path": "/api/1/deals", "query": { "limit": 10 } }
|
|
54
50
|
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
|
|
51
|
+
freee_api_post { "service": "accounting", "path": "/api/1/deals", "body": { "issue_date": "2024-01-01", ... } }`}]}))}async function Je(){let t=await re(),e=new He.McpServer({name:t.server.name,version:t.server.version});Fe(e),Ne(e);try{await q(),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 Be.StdioServerTransport;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)})}var de=p(require("prompts"),1),Ve=p(require("node:os"),1),K=p(require("node:crypto"),1),qe=p(require("open"),1);C();T();I();async function yt(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 w(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 Ct(){let t=await Promise.resolve().then(()=>(T(),_e)).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
|
|
56
52
|
`)),console.log(`\u30B9\u30C6\u30C3\u30D7 1/3: OAuth\u8A8D\u8A3C\u60C5\u5831\u306E\u5165\u529B
|
|
57
|
-
`);let n=await(0,
|
|
53
|
+
`);let n=await(0,de.default)([{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||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,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(`
|
|
58
54
|
\u8A8D\u8A3C\u60C5\u5831\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002
|
|
59
|
-
`),{clientId:r,clientSecret:o,callbackPort:i}}async function
|
|
60
|
-
`),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(
|
|
55
|
+
`),{clientId:r,clientSecret:o,callbackPort:i}}async function wt(){console.log(`\u30B9\u30C6\u30C3\u30D7 2/3: OAuth\u8A8D\u8A3C
|
|
56
|
+
`),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(C(),Ae)).then(a=>a.loadConfig()),await q();let t=K.default.randomBytes(32).toString("base64url"),e=K.default.createHash("sha256").update(t).digest("base64url"),n=K.default.randomBytes(16).toString("base64url"),r=J(e,n,$());console.log(`
|
|
61
57
|
\u8A8D\u8A3CURL: ${r}
|
|
62
|
-
`),await(0,
|
|
63
|
-
`);let o=
|
|
64
|
-
`),{accessToken:s.access_token,refreshToken:s.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function
|
|
65
|
-
`),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await
|
|
58
|
+
`),await(0,qe.default)(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
|
|
59
|
+
`);let o=Se(),i=new Promise((a,s)=>{let u=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:f=>{clearTimeout(u),a(f)},reject:f=>{clearTimeout(u),s(f)},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 V(a,t,$());return console.log(`\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002
|
|
60
|
+
`),{accessToken:s.access_token,refreshToken:s.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function kt(t){console.log(`\u30B9\u30C6\u30C3\u30D7 3/3: \u30C7\u30D5\u30A9\u30EB\u30C8\u4E8B\u696D\u6240\u306E\u9078\u629E
|
|
61
|
+
`),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await yt(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(0,de.default)({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
62
|
${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
|
|
63
|
+
`),{selected:{id:r.id,name:r.name,displayName:r.display_name||r.name,role:r.role},all:e}}async function _t(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 A(r),console.log(`\u8A2D\u5B9A\u60C5\u5831\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F\u3002
|
|
68
64
|
`),console.log(`=== MCP\u8A2D\u5B9A ===
|
|
69
65
|
`),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=
|
|
66
|
+
`);let o=Ve.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
67
|
`),console.log(JSON.stringify({mcpServers:{"freee-mcp":{command:"npx",args:["@him0/freee-mcp","client"]}}},null,2)),console.log(`
|
|
72
68
|
\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5B8C\u4E86!
|
|
73
69
|
`),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
|
|
70
|
+
`)}async function ze(){console.log(`
|
|
75
71
|
=== freee-mcp Configuration Setup ===
|
|
76
72
|
`),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
|
|
73
|
+
`);try{let t=await Ct(),e=await wt(),{selected:n,all:r}=await kt(e.accessToken);await _t(t,n,r)}catch(t){t instanceof Error?console.error(`
|
|
78
74
|
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{
|
|
75
|
+
\u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:`,t),process.exit(1)}finally{R()}}var At=async()=>{let e=process.argv.slice(2)[0];if(e==="configure"){await ze();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 Je()};At().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
|
package/dist/index.esm.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
var
|
|
2
|
-
`),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):$;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||$}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")),P={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:V}},P}function nt(){if(!P)throw new Error("Config not loaded. Call loadConfig() first.");return P}function G(t){Te=t}function ae(){return Te}var Te,P,l,C=ee(()=>{"use strict";I();F();Te=!1,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]}})});C();import{McpServer as Et}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as At}from"@modelcontextprotocol/sdk/server/stdio.js";C();import st from"http";import{URL as ct}from"url";import lt from"net";C();import Se from"crypto";C();F();import k from"fs/promises";import O from"path";async function _(t){return t.json().catch(()=>({}))}function se(){return O.join(x(),"tokens.json")}async function K(t){let e=se(),n=O.dirname(e);try{console.error(`[info] Creating directory: ${n}`),await k.mkdir(n,{recursive:!0}),console.error(`[info] Writing tokens to: ${e}`),await k.writeFile(e,JSON.stringify(t,null,2),{mode:q}),console.error("[info] Tokens saved successfully")}catch(r){throw console.error("[error] Failed to save tokens:",r),r}}async function ce(){let t=se();try{let e=await k.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await ot();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function rt(t){return Date.now()<t.expires_at}async function ot(){let t=x();try{let n=(await k.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));if(n.length>0){let r=O.join(t,n[0]),o=await k.readFile(r,"utf8"),i=JSON.parse(o);return await K(i),await Promise.all(n.map(a=>k.unlink(O.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 it(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 _(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 K(r),r}async function xe(){let t=se();try{await k.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 at()}async function at(){let t=x();try{let n=(await k.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));await Promise.all(n.map(r=>k.unlink(O.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 Ie(){let t=await ce();if(!t)return null;if(rt(t))return t.access_token;try{return(await it(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function Re(){let t=Se.randomBytes(32).toString("base64url"),e=Se.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function W(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 Z(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 _(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 K(i),i}var le=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)}},pe=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=st.createServer((i,a)=>{console.error(`Callback request: ${i.method} ${i.url}`);let s=new ct(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=lt.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 p=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: ${p}</p>`),s)s.reject(new Error(`OAuth error: ${i} - ${a}`));else if(o){let d=this.authManager.getPendingAuthentication(o);d&&(clearTimeout(d.timeout),d.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 m=this.authManager.getPendingAuthentication(o);if(!m){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),Z(r,m.codeVerifier,this.getRedirectUri()).then(p=>{console.error("Token exchange successful!"),m.resolve(p)}).catch(p=>{console.error("Token exchange failed:",p),m.reject(p)})}},ue=new le,fe=new pe(ue);function M(){return fe.getRedirectUri()}async function Y(){return fe.start()}function $e(t,e){ue.registerAuthentication(t,e)}function U(){fe.stop()}function Fe(){return ue}C();import dt from"crypto";import{z as me}from"zod";C();I();import pt from"fs/promises";import ut from"path";function ft(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function mt(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 v(t,e,n,r,o){let i=o||l.freee.apiUrl,a=await T(),s=await Ie();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
|
|
1
|
+
var Re=Object.defineProperty;var q=(t,e)=>()=>(t&&(e=t(t=0)),e);var ue=(t,e)=>{for(var n in e)Re(t,n,{get:e[n],enumerable:!0})};import fe from"path";import De from"os";function E(){return process.env.XDG_CONFIG_HOME?fe.join(process.env.XDG_CONFIG_HOME,ge):fe.join(De.homedir(),".config",ge)}var ge,v,j,M,b=q(()=>{"use strict";ge="freee-mcp";v=54321,j=300*1e3,M=384});var me={};ue(me,{getCompanyInfo:()=>x,getCompanyList:()=>je,getCurrentCompanyId:()=>A,getDownloadDir:()=>W,loadFullConfig:()=>m,saveFullConfig:()=>_,setCurrentCompany:()=>K,setDownloadDir:()=>Me});import z from"fs/promises";import de from"path";import Fe from"os";function G(){return de.join(E(),"config.json")}async function Oe(){let t=de.dirname(G());await z.mkdir(t,{recursive:!0})}function Le(t){return t!=null&&typeof t=="object"&&"defaultCompanyId"in t&&"currentCompanyId"in t&&"companies"in t&&!("clientId"in t)}function Ue(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=G();try{let e=await z.readFile(t,"utf8"),n=JSON.parse(e);if(Le(n)){let r=Ue(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 Oe();let e=G();await z.writeFile(e,JSON.stringify(t,null,2),{mode:M})}async function A(){return(await m()).currentCompanyId}async function K(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 je(){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 W(){return(await m()).downloadDir||Fe.tmpdir()}async function Me(t){let e=await m();e.downloadDir=t,await _(e)}var P=q(()=>{"use strict";b()});var he={};ue(he,{config:()=>l,getConfig:()=>He,loadConfig:()=>Y});function Ne(){return!!(process.env.FREEE_CLIENT_ID||process.env.FREEE_CLIENT_SECRET)}async function Y(){if(w)return w;let t=await m(),e,n,r;if(Ne())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
|
|
2
|
+
`),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):v;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||v}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:j}},w}function He(){if(!w)throw new Error("Config not loaded. Call loadConfig() first.");return w}var w,l,h=q(()=>{"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 at}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as st}from"@modelcontextprotocol/sdk/server/stdio.js";h();import ze from"http";import{URL as Ge}from"url";import Ke from"net";h();import we from"crypto";h();b();import C from"fs/promises";import I from"path";async function y(t){return t.json().catch(()=>({}))}function X(){return I.join(E(),"tokens.json")}async function N(t){let e=X(),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:M}),console.error("[info] Tokens saved successfully")}catch(r){throw console.error("[error] Failed to save tokens:",r),r}}async function Q(){let t=X();try{let e=await C.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await Je();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function Be(t){return Date.now()<t.expires_at}async function Je(){let t=E();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 N(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 Ve(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 N(r),r}async function ye(){let t=X();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 qe()}async function qe(){let t=E();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 Ce(){let t=await Q();if(!t)return null;if(Be(t))return t.access_token;try{return(await Ve(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function ke(){let t=we.randomBytes(32).toString("base64url"),e=we.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function H(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 B(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 N(i),i}var Z=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)}},ee=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=ze.createServer((i,a)=>{console.error(`Callback request: ${i.method} ${i.url}`);let s=new Ge(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=Ke.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),B(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)})}},te=new Z,ne=new ee(te);function S(){return ne.getRedirectUri()}async function J(){return ne.start()}function _e(t,e){te.registerAuthentication(t,e)}function $(){ne.stop()}function Ae(){return te}h();import Ze from"crypto";import{z as re}from"zod";h();P();import We from"fs/promises";import Ye from"path";function Xe(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function Qe(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 A(),s=await Ce();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
|
|
3
3
|
\u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${a}
|
|
4
|
-
\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
|
|
4
|
+
\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,d])=>{d!==void 0&&k.searchParams.append(f,String(d))}),k.searchParams.append("company_id",String(a));let g=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(g.status===401||g.status===403){let f=await y(g);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
|
|
5
5
|
\u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${a}
|
|
6
|
-
\u30A8\u30E9\u30FC\u8A73\u7D30: ${
|
|
6
|
+
\u30A8\u30E9\u30FC\u8A73\u7D30: ${g.status} ${JSON.stringify(f)}
|
|
7
7
|
|
|
8
8
|
\u78BA\u8A8D\u4E8B\u9805:
|
|
9
9
|
1. FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B
|
|
10
10
|
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
|
|
11
11
|
3. \u30C8\u30FC\u30AF\u30F3\u306E\u6709\u52B9\u671F\u9650\u304C\u5207\u308C\u3066\u3044\u306A\u3044\u304B
|
|
12
|
-
4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(!
|
|
12
|
+
4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(!g.ok){let f=await y(g),d=`API request failed: ${g.status}`;if(f&&f.errors&&Array.isArray(f.errors)){let U=[];for(let T of f.errors)T.messages&&Array.isArray(T.messages)&&U.push(...T.messages);U.length>0&&(d+=`
|
|
13
13
|
|
|
14
14
|
\u30A8\u30E9\u30FC\u8A73\u7D30:
|
|
15
|
-
${
|
|
16
|
-
`)}`,
|
|
15
|
+
${U.join(`
|
|
16
|
+
`)}`,g.status===400&&(d+=`
|
|
17
17
|
|
|
18
|
-
\u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,
|
|
19
|
-
\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`,
|
|
20
|
-
\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||(
|
|
18
|
+
\u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,d+=`
|
|
19
|
+
\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`,d+=`
|
|
20
|
+
\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||(d+=`
|
|
21
21
|
|
|
22
|
-
\u8A73\u7D30: ${JSON.stringify(f)}`),new Error(
|
|
22
|
+
\u8A73\u7D30: ${JSON.stringify(f)}`),new Error(d)}let V=g.headers.get("content-type")||"";if(Xe(V)){let f=await W(),d=Qe(V),T=`freee_download_${Date.now()}${d}`,le=Ye.join(f,T),pe=await g.arrayBuffer();return await We.writeFile(le,Buffer.from(pe)),{type:"binary",filePath:le,mimeType:V,size:pe.byteLength}}return g.json()}P();function Ee(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 A(),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:
|
|
23
23
|
\u4F1A\u793EID: ${e}
|
|
24
24
|
\u4F1A\u793E\u540D: ${n?.name||"Unknown"}
|
|
25
25
|
\u30E6\u30FC\u30B6\u30FC\u8A73\u7D30:
|
|
@@ -27,53 +27,49 @@ ${JSON.stringify(r,null,2)}`}]}}catch(e){return{content:[{type:"text",text:`\u30
|
|
|
27
27
|
OAuth\u8A8D\u8A3C\u3092\u884C\u3046\u306B\u306F\u3001freee developers\u3067\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u4F5C\u6210\u3057\u3001
|
|
28
28
|
\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
|
|
29
29
|
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
|
-
\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}=
|
|
30
|
+
\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}=ke(),r=Ze.randomBytes(16).toString("hex"),o=H(n,r,S());return _e(r,e),console.error(`Authentication URL: ${o}`),{content:[{type:"text",text:`\u8A8D\u8A3CURL: ${o}
|
|
31
31
|
|
|
32
|
-
\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
|
|
32
|
+
\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 Q();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"}
|
|
33
33
|
\u6709\u52B9\u671F\u9650: ${r}`+(n?"":`
|
|
34
|
-
\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
|
|
34
|
+
\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 ye(),{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:re.string().describe("\u4E8B\u696D\u6240ID"),name:re.string().optional().describe("\u4E8B\u696D\u6240\u540D"),description:re.string().optional().describe("\u8AAC\u660E")},async e=>{try{let{company_id:n,name:r,description:o}=e;return await K(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 A(),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 A();return e?.companies?.length?{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7:
|
|
35
35
|
${e.companies.map(o=>{let i=o.id===parseInt(n)?" *":"";return`${o.name} (${o.id})${i}`}).join(`
|
|
36
|
-
`)}`}]}:{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
|
|
36
|
+
`)}`}]}:{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 et from"node:fs";import se from"node:path";import{fileURLToPath as tt}from"node:url";var nt=se.dirname(tt(import.meta.url)),rt=se.resolve(nt,"../../openapi/minimal");function D(t){let e=se.join(rt,t),n=et.readFileSync(e,"utf-8");return JSON.parse(n)}var oe=null;function ie(){return oe===null&&(oe={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"}}),oe}var ae=new Proxy({},{get(t,e){return ie()[e]},ownKeys(){return Object.keys(ie())},getOwnPropertyDescriptor(t,e){let n=ie();if(e in n)return{enumerable:!0,configurable:!0,value:n[e]}}});function Pe(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 Te(t,e,n){let r=t.toLowerCase();if(n!==void 0){let o=ae[n],i=Pe(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(ae)){let a=Pe(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 ve(){let t=[];for(let[,e]of Object.entries(ae)){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(`
|
|
37
37
|
## ${e.name} (${e.baseUrl})
|
|
38
38
|
${r.sort().join(`
|
|
39
39
|
`)}`)}return t.join(`
|
|
40
|
-
`)}function
|
|
40
|
+
`)}function ot(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="binary"}function it(t){let e=(t.size/1024).toFixed(2);return`\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u307E\u3057\u305F
|
|
41
41
|
|
|
42
42
|
\u4FDD\u5B58\u5834\u6240: ${t.filePath}
|
|
43
43
|
MIME\u30BF\u30A4\u30D7: ${t.mimeType}
|
|
44
|
-
\u30B5\u30A4\u30BA: ${e} KB`}
|
|
44
|
+
\u30B5\u30A4\u30BA: ${e} KB`}var F="service: accounting/hr/invoice/pm/sm",O=c.enum(["accounting","hr","invoice","pm","sm"]).describe("\u5BFE\u8C61\u306Efreee\u30B5\u30FC\u30D3\u30B9");function L(t){return async e=>{try{let{service:n,path:r,query:o,body:i}=e,a=Te(t,r,n);if(!a.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${a.message}
|
|
45
45
|
|
|
46
|
-
\
|
|
47
|
-
MIME\u30BF\u30A4\u30D7: ${t.mimeType}
|
|
48
|
-
\u30B5\u30A4\u30BA: ${e} KB`}var B="service: accounting/hr/invoice/pm/sm",H=c.enum(["accounting","hr","invoice","pm","sm"]).describe("\u5BFE\u8C61\u306Efreee\u30B5\u30FC\u30D3\u30B9");function z(t){return async e=>{try{let{service:n,path:r,query:o,body:i}=e,a=Ue(t,r,n);if(!a.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${a.message}
|
|
49
|
-
|
|
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 v(t,a.actualPath,o,i,a.baseUrl);return kt(s)?{content:[{type:"text",text:Pt(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 Be(t){t.tool("freee_api_get",`freee API GET\u3002${B}`,{service:H,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)")},z("GET")),t.tool("freee_api_post",`freee API POST\u3002${B}`,{service:H,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)")},z("POST")),t.tool("freee_api_put",`freee API PUT\u3002${B}`,{service:H,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)")},z("PUT")),t.tool("freee_api_delete",`freee API DELETE\u3002${B}`,{service:H,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)")},z("DELETE")),t.tool("freee_api_patch",`freee API PATCH\u3002${B}`,{service:H,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)")},z("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${Ne()}
|
|
46
|
+
\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 ot(s)?{content:[{type:"text",text:it(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 be(t){t.tool("freee_api_get",`freee API GET\u3002${F}`,{service:O,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)")},L("GET")),t.tool("freee_api_post",`freee API POST\u3002${F}`,{service:O,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)")},L("POST")),t.tool("freee_api_put",`freee API PUT\u3002${F}`,{service:O,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)")},L("PUT")),t.tool("freee_api_delete",`freee API DELETE\u3002${F}`,{service:O,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)")},L("DELETE")),t.tool("freee_api_patch",`freee API PATCH\u3002${F}`,{service:O,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)")},L("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${ve()}
|
|
51
47
|
|
|
52
48
|
\u4F7F\u7528\u4F8B:
|
|
53
49
|
freee_api_get { "service": "accounting", "path": "/api/1/deals", "query": { "limit": 10 } }
|
|
54
50
|
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
|
|
51
|
+
freee_api_post { "service": "accounting", "path": "/api/1/deals", "body": { "issue_date": "2024-01-01", ... } }`}]}))}async function xe(){let t=await Y(),e=new at({name:t.server.name,version:t.server.version});Ee(e),be(e);try{await J(),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 st;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 Ie from"prompts";import*as Se from"node:os";import ce from"node:crypto";import ct from"open";h();P();b();async function lt(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 pt(){let t=await Promise.resolve().then(()=>(P(),me)).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
|
|
56
52
|
`)),console.log(`\u30B9\u30C6\u30C3\u30D7 1/3: OAuth\u8A8D\u8A3C\u60C5\u5831\u306E\u5165\u529B
|
|
57
|
-
`);let n=await
|
|
53
|
+
`);let n=await Ie([{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||v)}]);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(`
|
|
58
54
|
\u8A8D\u8A3C\u60C5\u5831\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002
|
|
59
|
-
`),{clientId:r,clientSecret:o,callbackPort:i}}async function
|
|
60
|
-
`),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(
|
|
55
|
+
`),{clientId:r,clientSecret:o,callbackPort:i}}async function ut(){console.log(`\u30B9\u30C6\u30C3\u30D7 2/3: OAuth\u8A8D\u8A3C
|
|
56
|
+
`),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(h(),he)).then(a=>a.loadConfig()),await J();let t=ce.randomBytes(32).toString("base64url"),e=ce.createHash("sha256").update(t).digest("base64url"),n=ce.randomBytes(16).toString("base64url"),r=H(e,n,S());console.log(`
|
|
61
57
|
\u8A8D\u8A3CURL: ${r}
|
|
62
|
-
`),await
|
|
63
|
-
`);let o=
|
|
64
|
-
`),{accessToken:s.access_token,refreshToken:s.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function
|
|
65
|
-
`),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await
|
|
58
|
+
`),await ct(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
|
|
59
|
+
`);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"))},j);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 B(a,t,S());return console.log(`\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002
|
|
60
|
+
`),{accessToken:s.access_token,refreshToken:s.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function ft(t){console.log(`\u30B9\u30C6\u30C3\u30D7 3/3: \u30C7\u30D5\u30A9\u30EB\u30C8\u4E8B\u696D\u6240\u306E\u9078\u629E
|
|
61
|
+
`),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await lt(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 Ie({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
62
|
${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
|
|
63
|
+
`),{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
64
|
`),console.log(`=== MCP\u8A2D\u5B9A ===
|
|
69
65
|
`),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=
|
|
66
|
+
`);let o=Se.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
67
|
`),console.log(JSON.stringify({mcpServers:{"freee-mcp":{command:"npx",args:["@him0/freee-mcp","client"]}}},null,2)),console.log(`
|
|
72
68
|
\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5B8C\u4E86!
|
|
73
69
|
`),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
|
|
70
|
+
`)}async function $e(){console.log(`
|
|
75
71
|
=== freee-mcp Configuration Setup ===
|
|
76
72
|
`),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
|
|
73
|
+
`);try{let t=await pt(),e=await ut(),{selected:n,all:r}=await ft(e.accessToken);await gt(t,n,r)}catch(t){t instanceof Error?console.error(`
|
|
78
74
|
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{
|
|
75
|
+
\u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:`,t),process.exit(1)}finally{$()}}var dt=async()=>{let e=process.argv.slice(2)[0];if(e==="configure"){await $e();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 xe()};dt().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|