@him0/freee-mcp 0.6.0 → 0.6.2

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.
Files changed (40) hide show
  1. package/bin/cli.js +59 -45
  2. package/package.json +5 -24
  3. package/README.md +0 -171
  4. package/dist/.keep +0 -0
  5. package/dist/api/client.d.ts +0 -10
  6. package/dist/api/client.test.d.ts +0 -1
  7. package/dist/auth/oauth.d.ts +0 -7
  8. package/dist/auth/oauth.test.d.ts +0 -1
  9. package/dist/auth/server.d.ts +0 -34
  10. package/dist/auth/tokens.d.ts +0 -13
  11. package/dist/auth/tokens.test.d.ts +0 -1
  12. package/dist/cli.d.ts +0 -1
  13. package/dist/config/companies.d.ts +0 -41
  14. package/dist/config/mcp-config.d.ts +0 -34
  15. package/dist/config/mcp-config.test.d.ts +0 -1
  16. package/dist/config.d.ts +0 -32
  17. package/dist/config.test.d.ts +0 -1
  18. package/dist/constants.d.ts +0 -33
  19. package/dist/e2e/auth-flow.e2e.test.d.ts +0 -5
  20. package/dist/e2e/client-mode.e2e.test.d.ts +0 -5
  21. package/dist/e2e/configure.e2e.test.d.ts +0 -5
  22. package/dist/e2e/fixtures/api-responses.d.ts +0 -132
  23. package/dist/e2e/mock-api.d.ts +0 -34
  24. package/dist/index.cjs +0 -78
  25. package/dist/index.d.ts +0 -1
  26. package/dist/index.esm.js +0 -78
  27. package/dist/index.test.d.ts +0 -1
  28. package/dist/mcp/handlers.d.ts +0 -1
  29. package/dist/mcp/handlers.test.d.ts +0 -1
  30. package/dist/mcp/tools.d.ts +0 -2
  31. package/dist/mcp/tools.test.d.ts +0 -1
  32. package/dist/openapi/client-mode.d.ts +0 -5
  33. package/dist/openapi/minimal-types.d.ts +0 -27
  34. package/dist/openapi/schema-loader.d.ts +0 -28
  35. package/dist/openapi/schema-loader.test.d.ts +0 -1
  36. package/dist/openapi/schema.d.ts +0 -5
  37. package/dist/openapi/schema.test.d.ts +0 -1
  38. package/dist/test-utils/setup.d.ts +0 -5
  39. package/dist/test-utils/temp-dir.d.ts +0 -32
  40. package/dist/utils/error.d.ts +0 -8
package/bin/cli.js CHANGED
@@ -1,80 +1,94 @@
1
1
  #! /usr/bin/env node
2
2
 
3
- var Ke=Object.defineProperty;var ee=(t,e)=>()=>(t&&(e=t(t=0)),e);var ke=(t,e)=>{for(var n in e)Ke(t,n,{get:e[n],enumerable:!0})};import Ee from"path";import We from"os";function k(){return process.env.XDG_CONFIG_HOME?Ee.join(process.env.XDG_CONFIG_HOME,Ae):Ee.join(We.homedir(),".config",Ae)}var Ae,x,N,H,B,b=ee(()=>{"use strict";Ae="freee-mcp";x=54321,N=300*1e3,H=384,B="https://api.freee.co.jp"});var ve={};ke(ve,{getCompanyInfo:()=>S,getCurrentCompanyId:()=>w,getDownloadDir:()=>oe,loadFullConfig:()=>C,saveFullConfig:()=>E,setCurrentCompany:()=>re});import te from"fs/promises";import Pe from"path";import Xe from"os";function ne(){return Pe.join(k(),"config.json")}async function Qe(){let t=Pe.dirname(ne());await te.mkdir(t,{recursive:!0})}function Ye(t){return t!=null&&typeof t=="object"&&"defaultCompanyId"in t&&"currentCompanyId"in t&&"companies"in t&&!("clientId"in t)}function Ze(t){return console.error("\u{1F4E6} \u53E4\u3044\u8A2D\u5B9A\u5F62\u5F0F\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002\u65B0\u3057\u3044\u5F62\u5F0F\u306B\u79FB\u884C\u3057\u307E\u3059..."),{clientId:void 0,clientSecret:void 0,callbackPort:void 0,defaultCompanyId:t.defaultCompanyId,currentCompanyId:t.currentCompanyId,companies:t.companies}}async function C(){let t=ne();try{let e=await te.readFile(t,"utf8"),n=JSON.parse(e);if(Ye(n)){let r=Ze(n);return await E(r),r}return n}catch(e){if(e.code==="ENOENT"){let n={clientId:void 0,clientSecret:void 0,callbackPort:void 0,defaultCompanyId:"0",currentCompanyId:"0",companies:{}};return await E(n),n}throw e}}async function E(t){await Qe();let e=ne();await te.writeFile(e,JSON.stringify(t,null,2),{mode:H})}async function w(){return(await C()).currentCompanyId}async function re(t,e,n){let r=await C();r.companies[t]?(e||n)&&(e&&(r.companies[t].name=e),n&&(r.companies[t].description=n)):r.companies[t]={id:t,name:e||`Company ${t}`,description:n||void 0,addedAt:Date.now()},r.companies[t].lastUsed=Date.now(),r.currentCompanyId=t,await E(r)}async function S(t){return(await C()).companies[t]||null}async function oe(){return(await C()).downloadDir||Xe.tmpdir()}var A=ee(()=>{"use strict";b()});var Te={};ke(Te,{config:()=>l,loadConfig:()=>ie});function et(){return!!(process.env.FREEE_CLIENT_ID||process.env.FREEE_CLIENT_SECRET)}async function ie(){if(P)return P;let t=await C(),e,n,r;if(et())console.error("Warning: \u74B0\u5883\u5909\u6570\u3067\u306E\u8A8D\u8A3C\u60C5\u5831\u8A2D\u5B9A\u306F\u975E\u63A8\u5968\u3067\u3059\u3002"),console.error(" `freee-mcp configure` \u3092\u5B9F\u884C\u3057\u3066\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306B\u79FB\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"),console.error(` \u74B0\u5883\u5909\u6570\u8A2D\u5B9A\u306F\u5C06\u6765\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3067\u524A\u9664\u3055\u308C\u308B\u4E88\u5B9A\u3067\u3059\u3002
4
- `),e=process.env.FREEE_CLIENT_ID||"",n=process.env.FREEE_CLIENT_SECRET||"",r=process.env.FREEE_CALLBACK_PORT?parseInt(process.env.FREEE_CALLBACK_PORT,10):x;else{if(!t.clientId||!t.clientSecret)throw new Error("\u8A8D\u8A3C\u60C5\u5831\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\n`freee-mcp configure` \u3092\u5B9F\u884C\u3057\u3066\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3057\u3066\u304F\u3060\u3055\u3044\u3002");e=t.clientId,n=t.clientSecret,r=t.callbackPort||x}return P={freee:{clientId:e,clientSecret:n,companyId:"0",apiUrl:B},oauth:{callbackPort:r,redirectUri:`http://127.0.0.1:${r}/callback`,authorizationEndpoint:"https://accounts.secure.freee.co.jp/public_api/authorize",tokenEndpoint:"https://accounts.secure.freee.co.jp/public_api/token",scope:"read write"},server:{name:"freee",version:"1.0.0"},auth:{timeoutMs:N}},P}var P,l,y=ee(()=>{"use strict";A();b();P=null;l=new Proxy({},{get(t,e){if(!P)throw new Error("Config not loaded. Call loadConfig() first in async context.");return P[e]}})});y();import{McpServer as wt}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as _t}from"@modelcontextprotocol/sdk/server/stdio.js";y();import it from"http";import{URL as at}from"url";import st from"net";y();import Se from"crypto";y();b();import h from"fs/promises";import I from"path";async function m(t){return t.json().catch(()=>({}))}function ae(){return I.join(k(),"tokens.json")}async function J(t){let e=ae(),n=I.dirname(e);try{console.error(`[info] Creating directory: ${n}`),await h.mkdir(n,{recursive:!0}),console.error(`[info] Writing tokens to: ${e}`),await h.writeFile(e,JSON.stringify(t,null,2),{mode:H}),console.error("[info] Tokens saved successfully")}catch(r){throw console.error("[error] Failed to save tokens:",r),r}}async function se(){let t=ae();try{let e=await h.readFile(t,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT"){let n=await nt();return n||null}throw console.error("[error] Failed to load tokens:",e),e}}function tt(t){return Date.now()<t.expires_at}async function nt(){let t=k();try{let n=(await h.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));if(n.length>0){let r=I.join(t,n[0]),o=await h.readFile(r,"utf8"),a=JSON.parse(o);return await J(a),await Promise.all(n.map(i=>h.unlink(I.join(t,i)).catch(c=>{console.error(`[warn] Failed to clean up legacy token file ${i}:`,c)}))),console.error("[info] Migrated legacy company-specific tokens to user-based tokens"),a}}catch(e){console.error("[warn] Error during legacy token migration attempt:",e)}return null}async function rt(t){let e=await fetch(l.oauth.tokenEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:t,client_id:l.freee.clientId,client_secret:l.freee.clientSecret})});if(!e.ok){let o=await m(e);throw new Error(`Token refresh failed: ${e.status} ${JSON.stringify(o)}`)}let n=await e.json(),r={access_token:n.access_token,refresh_token:n.refresh_token||t,expires_at:Date.now()+n.expires_in*1e3,token_type:n.token_type||"Bearer",scope:n.scope||l.oauth.scope};return await J(r),r}async function xe(){let t=ae();try{await h.unlink(t),console.error("[info] Tokens cleared successfully")}catch(e){if(e.code==="ENOENT"){console.error("[info] No tokens to clear (file does not exist)");return}throw console.error("[error] Failed to clear tokens:",e),e}await ot()}async function ot(){let t=k();try{let n=(await h.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"));await Promise.all(n.map(r=>h.unlink(I.join(t,r)).catch(o=>{console.error(`[warn] Failed to clear legacy token file ${r}:`,o)}))),n.length>0&&console.error("[info] Cleared legacy company-specific token files")}catch(e){console.error("[warn] Error during legacy token cleanup:",e)}}async function be(){let t=await se();if(!t)return null;if(tt(t))return t.access_token;try{return(await rt(t.refresh_token)).access_token}catch(e){return console.error("[warn] Failed to refresh token:",e),null}}function Ie(){let t=Se.randomBytes(32).toString("base64url"),e=Se.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function V(t,e,n){let r=new URLSearchParams({response_type:"code",client_id:l.freee.clientId,redirect_uri:n,scope:l.oauth.scope,state:e,code_challenge:t,code_challenge_method:"S256"});return`${l.oauth.authorizationEndpoint}?${r.toString()}`}async function q(t,e,n){let r=await fetch(l.oauth.tokenEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:l.freee.clientId,client_secret:l.freee.clientSecret,code:t,redirect_uri:n,code_verifier:e})});if(!r.ok){let i=await m(r);throw new Error(`Token exchange failed: ${r.status} ${JSON.stringify(i)}`)}let o=await r.json(),a={access_token:o.access_token,refresh_token:o.refresh_token,expires_at:Date.now()+o.expires_in*1e3,token_type:o.token_type||"Bearer",scope:o.scope||l.oauth.scope};return await J(a),a}var ce=class{pendingAuthentications=new Map;cliAuthHandlers=new Map;registerAuthentication(e,n){console.error(`Registering authentication request with state: ${e.substring(0,10)}...`),console.error(`Code verifier: ${n.substring(0,10)}...`);let r=setTimeout(()=>{this.pendingAuthentications.delete(e),console.error(`Authentication timeout for state: ${e.substring(0,10)}...`)},l.auth.timeoutMs);this.pendingAuthentications.set(e,{codeVerifier:n,resolve:o=>{console.error("Authentication completed successfully!")},reject:o=>{console.error("Authentication failed:",o)},timeout:r}),console.error(`Registration complete. Total pending: ${this.pendingAuthentications.size}`)}getPendingAuthentication(e){return this.pendingAuthentications.get(e)}removePendingAuthentication(e){let n=this.pendingAuthentications.get(e);n&&(clearTimeout(n.timeout),this.pendingAuthentications.delete(e))}clearAllPending(){for(let[e,n]of this.pendingAuthentications)clearTimeout(n.timeout),n.reject(new Error("Server shutdown"));this.pendingAuthentications.clear()}get pendingCount(){return this.pendingAuthentications.size}registerCliAuthHandler(e,n){this.cliAuthHandlers.set(e,n)}getCliAuthHandler(e){return this.cliAuthHandlers.get(e)}removeCliAuthHandler(e){this.cliAuthHandlers.delete(e)}},le=class{server=null;port=null;authManager;constructor(e){this.authManager=e}getRedirectUri(){if(this.port===null)throw new Error("Callback server not started. Call start() first.");return`http://127.0.0.1:${this.port}/callback`}getPort(){return this.port}isRunning(){return this.server!==null}async start(){if(this.server)return;let e=l.oauth.callbackPort,n=await this.findAvailablePort(e);return this.port=n,n!==e&&console.error(`Warning: Port ${e} is in use. Using fallback port ${n} for OAuth callback server.`),new Promise((r,o)=>{this.server=it.createServer((a,i)=>{console.error(`Callback request: ${a.method} ${a.url}`);let c=new at(a.url,`http://127.0.0.1:${n}`);c.pathname==="/callback"?this.handleCallback(c,i):c.pathname==="/"?(i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end("<h1>freee MCP OAuth Server</h1><p>\u30B3\u30FC\u30EB\u30D0\u30C3\u30AF\u30B5\u30FC\u30D0\u30FC\u304C\u7A3C\u50CD\u4E2D\u3067\u3059\u3002</p>")):(i.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),i.end("<h1>404 Not Found</h1><p>\u3053\u306E\u30D1\u30B9\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002</p>"))}),this.server.on("error",a=>{console.error("Callback server error:",a),o(a)}),this.server.listen(n,"127.0.0.1",()=>{console.error(`OAuth callback server listening on http://127.0.0.1:${n}`),r()})})}stop(){this.server&&(this.authManager.clearAllPending(),this.server.close(()=>{console.error("OAuth callback server stopped")}),this.server=null,this.port=null)}async checkPortAvailable(e){return new Promise(n=>{let r=st.createServer();r.listen(e,"127.0.0.1",()=>{r.close(()=>{n(!0)})}),r.on("error",()=>{n(!1)})})}async findAvailablePort(e,n=50){for(let r=e;r<e+n;r++)if(await this.checkPortAvailable(r))return r;throw new Error(`No available port found after checking ${n} ports starting from ${e}`)}handleCallback(e,n){let r=e.searchParams.get("code"),o=e.searchParams.get("state"),a=e.searchParams.get("error"),i=e.searchParams.get("error_description");console.error(`Callback received - URL: ${e.toString()}`),console.error("Callback parameters:",{code:r?`${r.substring(0,10)}...`:null,state:o?`${o.substring(0,10)}...`:null,error:a,errorDescription:i}),console.error(`Pending authentications count: ${this.authManager.pendingCount}`);let c=o?this.authManager.getCliAuthHandler(o):void 0;if(a){let f=i||a;if(console.error(`OAuth error: ${a} - ${i}`),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end(`<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${f}</p>`),c)c.reject(new Error(`OAuth error: ${a} - ${i}`));else if(o){let _=this.authManager.getPendingAuthentication(o);_&&(clearTimeout(_.timeout),_.reject(new Error(`OAuth error: ${a} - ${i}`)),this.authManager.removePendingAuthentication(o))}return}if(!r||!o){console.error("Missing code or state"),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u8A8D\u8A3C\u30B3\u30FC\u30C9\u307E\u305F\u306F\u72B6\u614B\u30D1\u30E9\u30E1\u30FC\u30BF\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059\u3002</p>");return}if(c){console.error("Valid CLI callback received"),n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u5B8C\u4E86</h1><p>\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\u3002\u3053\u306E\u30DA\u30FC\u30B8\u3092\u9589\u3058\u3066\u30BF\u30FC\u30DF\u30CA\u30EB\u306B\u623B\u3063\u3066\u304F\u3060\u3055\u3044\u3002</p>"),c.resolve(r);return}let p=this.authManager.getPendingAuthentication(o);if(!p){console.error(`Unknown state: ${o}`),n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u30A8\u30E9\u30FC</h1><p>\u4E0D\u660E\u306A\u8A8D\u8A3C\u72B6\u614B\u3067\u3059\u3002\u8A8D\u8A3C\u3092\u518D\u958B\u3057\u3066\u304F\u3060\u3055\u3044\u3002</p>");return}console.error("Valid callback received, exchanging code for tokens..."),n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>\u8A8D\u8A3C\u5B8C\u4E86</h1><p>\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\u3002\u3053\u306E\u30DA\u30FC\u30B8\u3092\u9589\u3058\u3066\u304F\u3060\u3055\u3044\u3002</p>"),this.authManager.removePendingAuthentication(o),q(r,p.codeVerifier,this.getRedirectUri()).then(f=>{console.error("Token exchange successful!"),p.resolve(f)}).catch(f=>{console.error("Token exchange failed:",f),p.reject(f)})}},pe=new ce,fe=new le(pe);function $(){return fe.getRedirectUri()}async function z(){return fe.start()}function $e(t,e){pe.registerAuthentication(t,e)}function R(){fe.stop()}function Re(){return pe}y();import ut from"crypto";import{z as ue}from"zod";y();A();import ct from"fs/promises";import lt from"path";function pt(t){return["application/pdf","application/octet-stream","image/"].some(n=>t.includes(n))}function ft(t){let e={"application/pdf":".pdf","image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp","text/csv":".csv"};for(let[n,r]of Object.entries(e))if(t.includes(n))return r;return t.includes("image/"),".bin"}async function F(t,e,n,r,o){let a=o||l.freee.apiUrl,i=await w(),c=await be();if(!c)throw new Error(`\u8A8D\u8A3C\u304C\u5FC5\u8981\u3067\u3059\u3002freee_authenticate \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u8A8D\u8A3C\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
3
+ var At=Object.defineProperty;var le=(t,e)=>()=>(t&&(e=t(t=0)),e);var $e=(t,e)=>{for(var r in e)At(t,r,{get:e[r],enumerable:!0})};import Me from"path";import Tt from"os";function A(){return process.env.XDG_CONFIG_HOME?Me.join(process.env.XDG_CONFIG_HOME,Fe):Me.join(Tt.homedir(),".config",Fe)}var Fe,j,R,W,X,Pt,Oe,w=le(()=>{"use strict";Fe="freee-mcp";j=54321,R=300*1e3,W=384,X="https://api.freee.co.jp",Pt="0.6.2",Oe=`freee-mcp/${Pt} (MCP Server; +https://github.com/him0/freee-mcp)`});var Ue={};$e(Ue,{CompanyConfigSchema:()=>je,FullConfigSchema:()=>Ne,getCompanyInfo:()=>N,getCurrentCompanyId:()=>b,getDownloadDir:()=>me,loadFullConfig:()=>v,saveFullConfig:()=>$,setCurrentCompany:()=>fe});import pe from"fs/promises";import De from"path";import St from"os";import{z as d}from"zod";function ue(){return De.join(A(),"config.json")}async function vt(){let t=De.dirname(ue());await pe.mkdir(t,{recursive:!0})}function bt(t){return t!=null&&typeof t=="object"&&"defaultCompanyId"in t&&"currentCompanyId"in t&&"companies"in t&&!("clientId"in t)}function It(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 v(){let t=ue();try{let e=await pe.readFile(t,"utf8"),r=JSON.parse(e);if(bt(r)){let o=It(r);return await $(o),o}let n=Ne.safeParse(r);if(!n.success)throw new Error(`Invalid config file: ${n.error.message}`);return n.data}catch(e){if(e.code==="ENOENT"){let r={clientId:void 0,clientSecret:void 0,callbackPort:void 0,defaultCompanyId:"0",currentCompanyId:"0",companies:{}};return await $(r),r}throw e}}async function $(t){await vt();let e=ue();await pe.writeFile(e,JSON.stringify(t,null,2),{mode:W})}async function b(){return(await v()).currentCompanyId}async function fe(t,e,r){let n=await v();n.companies[t]?(e||r)&&(e&&(n.companies[t].name=e),r&&(n.companies[t].description=r)):n.companies[t]={id:t,name:e||`Company ${t}`,description:r||void 0,addedAt:Date.now()},n.companies[t].lastUsed=Date.now(),n.currentCompanyId=t,await $(n)}async function N(t){return(await v()).companies[t]||null}async function me(){return(await v()).downloadDir||St.tmpdir()}var je,Ne,M=le(()=>{"use strict";w();je=d.object({id:d.string(),name:d.string().optional(),description:d.string().optional(),addedAt:d.number(),lastUsed:d.number().optional()}),Ne=d.object({clientId:d.string().optional(),clientSecret:d.string().optional(),callbackPort:d.number().optional(),defaultCompanyId:d.string(),currentCompanyId:d.string(),companies:d.record(d.string(),je),downloadDir:d.string().optional()})});var Le={};$e(Le,{getConfig:()=>h,loadConfig:()=>de});function xt(){return!!(process.env.FREEE_CLIENT_ID||process.env.FREEE_CLIENT_SECRET)}async function de(){if(F)return F;let t=await v(),e,r,n;if(xt())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||"",r=process.env.FREEE_CLIENT_SECRET||"",n=process.env.FREEE_CALLBACK_PORT?parseInt(process.env.FREEE_CALLBACK_PORT,10):j;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,r=t.clientSecret,n=t.callbackPort||j}return F={freee:{clientId:e,clientSecret:r,companyId:"0",apiUrl:X},oauth:{callbackPort:n,redirectUri:`http://127.0.0.1:${n}/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:R}},F}function h(){if(!F)throw new Error("Config not loaded. Call loadConfig() first in async context.");return F}var F,T=le(()=>{"use strict";M();w();F=null});T();import{McpServer as Kt}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Wt}from"@modelcontextprotocol/sdk/server/stdio.js";T();import Lt from"crypto";import{z as P}from"zod";T();T();w();import Z from"fs/promises";import Ve from"path";import{z as C}from"zod";async function _(t){try{return{success:!0,data:await t.json()}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}function l(t){return{content:[{type:"text",text:t}]}}function k(t){return t instanceof Error?t.message:String(t)}function Q(t,e){return{access_token:t.access_token,refresh_token:t.refresh_token||e.refreshToken||"",expires_at:Date.now()+t.expires_in*1e3,token_type:t.token_type||"Bearer",scope:t.scope||e.scope}}w();import Y from"fs/promises";import ge from"path";async function Je(){let t=A();try{return(await Y.readdir(t)).filter(r=>r.startsWith("tokens-")&&r.endsWith(".json"))}catch{return[]}}async function Be(t){let e=A();try{let r=await Je();if(r.length>0){let n=ge.join(e,r[0]),o=await Y.readFile(n,"utf8"),a=JSON.parse(o),i=he.safeParse(a);if(!i.success)return console.error("[error] Invalid legacy token file:",i.error.message),null;let s=i.data;return await t(s),await Promise.all(r.map(p=>Y.unlink(ge.join(e,p)).catch(u=>{console.error(`[warn] Failed to clean up legacy token file ${p}:`,u)}))),console.error("[info] Migrated legacy company-specific tokens to user-based tokens"),s}}catch(r){console.error("[warn] Error during legacy token migration attempt:",r)}return null}async function He(){let t=A();try{let e=await Je();await Promise.all(e.map(r=>Y.unlink(ge.join(t,r)).catch(n=>{console.error(`[warn] Failed to clear legacy token file ${r}:`,n)}))),e.length>0&&console.error("[info] Cleared legacy company-specific token files")}catch(e){console.error("[warn] Error during legacy token cleanup:",e)}}var he=C.object({access_token:C.string(),refresh_token:C.string(),expires_at:C.number(),token_type:C.string(),scope:C.string()}),ye=C.object({access_token:C.string(),refresh_token:C.string().optional(),expires_in:C.number(),token_type:C.string().optional(),scope:C.string().optional()});function Ce(){return Ve.join(A(),"tokens.json")}async function ee(t){let e=Ce(),r=Ve.dirname(e);try{console.error(`[info] Creating directory: ${r}`),await Z.mkdir(r,{recursive:!0}),console.error(`[info] Writing tokens to: ${e}`),await Z.writeFile(e,JSON.stringify(t,null,2),{mode:W}),console.error("[info] Tokens saved successfully")}catch(n){throw console.error("[error] Failed to save tokens:",n),n}}async function we(){let t=Ce();try{let e=await Z.readFile(t,"utf8"),r=JSON.parse(e),n=he.safeParse(r);return n.success?n.data:(console.error("[error] Invalid token file:",n.error.message),null)}catch(e){if(e.code==="ENOENT"){let r=await Be(ee);return r||null}throw console.error("[error] Failed to load tokens:",e),e}}function Rt(t){return Date.now()<t.expires_at}async function $t(t){let e=h(),r=await fetch(e.oauth.tokenEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:t,client_id:e.freee.clientId,client_secret:e.freee.clientSecret})});if(!r.ok){let i=await _(r),s=i.success?JSON.stringify(i.data):`(JSON parse failed: ${i.error})`;throw new Error(`Token refresh failed: ${r.status} ${s}`)}let n=await r.json(),o=ye.safeParse(n);if(!o.success)throw new Error(`Invalid token response format: ${o.error.message}`);let a=Q(o.data,{refreshToken:t,scope:e.oauth.scope});return await ee(a),a}async function ze(){let t=Ce();try{await Z.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 He()}async function qe(){let t=await we();return t?Rt(t)?t.access_token:(await $t(t.refresh_token)).access_token:null}M();w();import Mt from"fs/promises";import Ft from"path";function Ge(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="binary"}function Ot(t){return["application/pdf","application/octet-stream","image/"].some(r=>t.includes(r))}function Dt(t){let e={"application/pdf":".pdf","image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp","text/csv":".csv"};for(let[r,n]of Object.entries(e))if(t.includes(r))return n;return t.includes("image/"),".bin"}async function U(t,e,r,n,o){let a=o||h().freee.apiUrl,i=await b(),s=await qe();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: ${i}
6
- \u307E\u305F\u306F\u3001FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let p=a.endsWith("/")?a:a+"/",f=e.startsWith("/")?e.slice(1):e,_=new URL(f,p);n&&Object.entries(n).forEach(([u,g])=>{g!==void 0&&_.searchParams.append(u,String(g))});let Q=n?.company_id;if(Q!==void 0&&String(Q)!==String(i))throw new Error(`company_id \u306E\u4E0D\u6574\u5408: \u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id (${Q}) \u3068\u73FE\u5728\u306E\u4E8B\u696D\u6240 (${i}) \u304C\u7570\u306A\u308A\u307E\u3059\u3002
7
- freee_set_company \u3067\u4E8B\u696D\u6240\u3092\u5207\u308A\u66FF\u3048\u308B\u304B\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id \u3092\u4FEE\u6B63\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let Y=r?.company_id;if(Y!==void 0&&String(Y)!==String(i))throw new Error(`company_id \u306E\u4E0D\u6574\u5408: \u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3\u306E company_id (${Y}) \u3068\u73FE\u5728\u306E\u4E8B\u696D\u6240 (${i}) \u304C\u7570\u306A\u308A\u307E\u3059\u3002
8
- freee_set_company \u3067\u4E8B\u696D\u6240\u3092\u5207\u308A\u66FF\u3048\u308B\u304B\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id \u3092\u4FEE\u6B63\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let d=await fetch(_.toString(),{method:t,headers:{Authorization:`Bearer ${c}`,"Content-Type":"application/json"},body:r?JSON.stringify(typeof r=="string"?JSON.parse(r):r):void 0});if(d.status===401||d.status===403){let u=await m(d);throw new Error(`\u8A8D\u8A3C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002freee_authenticate \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u518D\u8A8D\u8A3C\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
6
+ \u307E\u305F\u306F\u3001FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let p=a.endsWith("/")?a:a+"/",u=e.startsWith("/")?e.slice(1):e,x=new URL(u,p);r&&Object.entries(r).forEach(([m,f])=>{f!==void 0&&x.searchParams.append(m,String(f))});let se=r?.company_id;if(se!==void 0&&String(se)!==String(i))throw new Error(`company_id \u306E\u4E0D\u6574\u5408: \u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id (${se}) \u3068\u73FE\u5728\u306E\u4E8B\u696D\u6240 (${i}) \u304C\u7570\u306A\u308A\u307E\u3059\u3002
7
+ freee_set_company \u3067\u4E8B\u696D\u6240\u3092\u5207\u308A\u66FF\u3048\u308B\u304B\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id \u3092\u4FEE\u6B63\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let ce=n?.company_id;if(ce!==void 0&&String(ce)!==String(i))throw new Error(`company_id \u306E\u4E0D\u6574\u5408: \u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3\u306E company_id (${ce}) \u3068\u73FE\u5728\u306E\u4E8B\u696D\u6240 (${i}) \u304C\u7570\u306A\u308A\u307E\u3059\u3002
8
+ freee_set_company \u3067\u4E8B\u696D\u6240\u3092\u5207\u308A\u66FF\u3048\u308B\u304B\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u306E company_id \u3092\u4FEE\u6B63\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);let y=await fetch(x.toString(),{method:t,headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json","User-Agent":Oe},body:n?JSON.stringify(typeof n=="string"?JSON.parse(n):n):void 0});if(y.status===401){let m=await _(y),f=m.success?JSON.stringify(m.data):`(JSON parse failed: ${m.error})`;throw new Error(`\u8A8D\u8A3C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002freee_authenticate \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u518D\u8A8D\u8A3C\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
9
9
  \u73FE\u5728\u306E\u4E8B\u696D\u6240ID: ${i}
10
- \u30A8\u30E9\u30FC\u8A73\u7D30: ${d.status} ${JSON.stringify(u)}
10
+ \u30A8\u30E9\u30FC\u8A73\u7D30: ${y.status} ${f}
11
11
 
12
12
  \u78BA\u8A8D\u4E8B\u9805:
13
13
  1. FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B
14
14
  2. freee\u5074\u3067\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u8A2D\u5B9A\u304C\u6B63\u3057\u3044\u304B\uFF08\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8URI\u7B49\uFF09
15
15
  3. \u30C8\u30FC\u30AF\u30F3\u306E\u6709\u52B9\u671F\u9650\u304C\u5207\u308C\u3066\u3044\u306A\u3044\u304B
16
- 4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(!d.ok){let u=await m(d),g=`API request failed: ${d.status}`;if(u&&u.errors&&Array.isArray(u.errors)){let U=[];for(let T of u.errors)T.messages&&Array.isArray(T.messages)&&U.push(...T.messages);U.length>0&&(g+=`
16
+ 4. \u4E8B\u696D\u6240ID\u304C\u6B63\u3057\u3044\u304B\uFF08freee_get_current_company \u3067\u78BA\u8A8D\uFF09`)}if(y.status===403){let m=await _(y),f=m.success?JSON.stringify(m.data):`(JSON parse failed: ${m.error})`;throw new Error(`\u30A2\u30AF\u30BB\u30B9\u62D2\u5426 (403): ${f}
17
+ \u4E8B\u696D\u6240ID: ${i}
18
+
19
+ \u30EC\u30FC\u30C8\u30EA\u30DF\u30C3\u30C8\u306E\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u6570\u5206\u5F85\u3063\u3066\u304B\u3089\u518D\u8A66\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002
20
+ \u305D\u308C\u3067\u3082\u89E3\u6C7A\u3057\u306A\u3044\u5834\u5408\u306F\u3001\u30A2\u30D7\u30EA\u306E\u6A29\u9650\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u304B\u3001freee_authenticate \u3067\u518D\u8A8D\u8A3C\u3057\u3066\u304F\u3060\u3055\u3044\u3002`)}if(!y.ok){let m=await _(y),f=`API request failed: ${y.status}`;if(m.success){let S=m.data;if(S&&S.errors&&Array.isArray(S.errors)){let D=[];for(let E of S.errors)E&&typeof E=="object"&&"messages"in E&&Array.isArray(E.messages)&&D.push(...E.messages);D.length>0&&(f+=`
17
21
 
18
22
  \u30A8\u30E9\u30FC\u8A73\u7D30:
19
- ${U.join(`
20
- `)}`,d.status===400&&(g+=`
23
+ ${D.join(`
24
+ `)}`,y.status===400&&(f+=`
25
+
26
+ \u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,f+=`
27
+ \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`,f+=`
28
+ \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`))}S?.errors||(f+=`
29
+
30
+ \u8A73\u7D30: ${JSON.stringify(S)}`)}else f+=`
21
31
 
22
- \u30D2\u30F3\u30C8: \u4E0D\u6B63\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002`,g+=`
23
- \u65E2\u5B58\u306E\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3057\u3066\u6B63\u3057\u3044\u69CB\u9020\u3092\u78BA\u8A8D\u3059\u308B\u3053\u3068\u3092\u304A\u52E7\u3081\u3057\u307E\u3059\u3002`,g+=`
24
- \u4F8B: get_items, get_partners, get_account_items \u306A\u3069\u3067\u65E2\u5B58\u30C7\u30FC\u30BF\u306E\u69CB\u9020\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`))}throw u?.errors||(g+=`
32
+ \u8A73\u7D30: (JSON parse failed: ${m.error})`;throw new Error(f)}let K=y.headers.get("content-type")||"";if(Ot(K)){let m=await me(),f=Dt(K),D=`freee_download_${Date.now()}${f}`,E=Ft.join(m,D),Re=await y.arrayBuffer();return await Mt.writeFile(E,Buffer.from(Re)),{type:"binary",filePath:E,mimeType:K,size:Re.byteLength}}let xe=await y.text();try{return JSON.parse(xe)}catch{throw new Error(`Failed to parse API response as JSON. Status: ${y.status}, Content-Type: ${K}, Body preview: ${xe.slice(0,200)}`)}}T();import Ke from"crypto";function We(){let t=Ke.randomBytes(32).toString("base64url"),e=Ke.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}function te(t,e,r){let n=h(),o=new URLSearchParams({response_type:"code",client_id:n.freee.clientId,redirect_uri:r,scope:n.oauth.scope,state:e,code_challenge:t,code_challenge_method:"S256"});return`${n.oauth.authorizationEndpoint}?${o.toString()}`}async function re(t,e,r){let n=h(),o=await fetch(n.oauth.tokenEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:n.freee.clientId,client_secret:n.freee.clientSecret,code:t,redirect_uri:r,code_verifier:e})});if(!o.ok){let p=await _(o),u=p.success?JSON.stringify(p.data):`(JSON parse failed: ${p.error})`;throw new Error(`Token exchange failed: ${o.status} ${u}`)}let a=await o.json(),i=ye.safeParse(a);if(!i.success)throw new Error(`Invalid token response format: ${i.error.message}`);let s=Q(i.data,{scope:n.oauth.scope});return await ee(s),s}T();import jt from"http";import{URL as Nt}from"url";import Ut from"net";var _e=class{pendingAuthentications=new Map;cliAuthHandlers=new Map;registerAuthentication(e,r){console.error(`Registering authentication request with state: ${e.substring(0,10)}...`),console.error(`Code verifier: ${r.substring(0,10)}...`);let n=setTimeout(()=>{this.pendingAuthentications.delete(e),console.error(`Authentication timeout for state: ${e.substring(0,10)}...`)},h().auth.timeoutMs);this.pendingAuthentications.set(e,{codeVerifier:r,resolve:o=>{console.error("Authentication completed successfully!")},reject:o=>{console.error("Authentication failed:",o)},timeout:n}),console.error(`Registration complete. Total pending: ${this.pendingAuthentications.size}`)}getPendingAuthentication(e){return this.pendingAuthentications.get(e)}removePendingAuthentication(e){let r=this.pendingAuthentications.get(e);r&&(clearTimeout(r.timeout),this.pendingAuthentications.delete(e))}clearAllPending(){for(let[e,r]of this.pendingAuthentications)clearTimeout(r.timeout),r.reject(new Error("Server shutdown"));this.pendingAuthentications.clear()}get pendingCount(){return this.pendingAuthentications.size}registerCliAuthHandler(e,r){this.cliAuthHandlers.set(e,r)}getCliAuthHandler(e){return this.cliAuthHandlers.get(e)}removeCliAuthHandler(e){this.cliAuthHandlers.delete(e)}},ke=class{server=null;port=null;authManager;autoStopTimeout=null;constructor(e){this.authManager=e}clearAutoStopTimeout(){this.autoStopTimeout&&(clearTimeout(this.autoStopTimeout),this.autoStopTimeout=null)}scheduleAutoStop(e){this.clearAutoStopTimeout(),this.autoStopTimeout=setTimeout(()=>{console.error("OAuth callback server auto-stopping after timeout"),this.stop()},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){console.error("OAuth callback server is already running. If authentication is not working, try restarting the MCP server.");return}let e=h().oauth.callbackPort;if(!await this.checkPortAvailable(e)){let n=`http://127.0.0.1:${e}/callback`;throw new Error(`\u30DD\u30FC\u30C8 ${e} \u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002
25
33
 
26
- \u8A73\u7D30: ${JSON.stringify(u)}`),new Error(g)}let Z=d.headers.get("content-type")||"";if(pt(Z)){let u=await oe(),g=ft(Z),T=`freee_download_${Date.now()}${g}`,we=lt.join(u,T),_e=await d.arrayBuffer();return await ct.writeFile(we,Buffer.from(_e)),{type:"binary",filePath:we,mimeType:Z,size:_e.byteLength}}return d.json()}A();function Fe(t){t.tool("freee_current_user","\u73FE\u5728\u306E\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u3092\u53D6\u5F97\u3002\u8A73\u7D30\u30AC\u30A4\u30C9\u306Ffreee-mcp skill\u3092\u53C2\u7167\u3002",{},async()=>{try{let e=await w(),n=await S(e);if(!e)return{content:[{type:"text",text:"\u4F1A\u793EID\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002freee_set_current_company \u3067\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}]};let r=await F("GET","/api/1/users/me");return{content:[{type:"text",text:`\u73FE\u5728\u306E\u30E6\u30FC\u30B6\u30FC\u60C5\u5831:
34
+ freee \u30A2\u30D7\u30EA\u306B\u30B3\u30FC\u30EB\u30D0\u30C3\u30AFURL (${n}) \u3092\u767B\u9332\u3057\u3066\u3044\u308B\u5834\u5408\u3001\u30DD\u30FC\u30C8\u3092\u5909\u66F4\u3059\u308B\u3068\u8A8D\u8A3C\u304C\u5931\u6557\u3057\u307E\u3059\u3002
35
+
36
+ \u89E3\u6C7A\u65B9\u6CD5:
37
+ 1. \u30DD\u30FC\u30C8 ${e} \u3092\u4F7F\u7528\u3057\u3066\u3044\u308B\u30D7\u30ED\u30BB\u30B9\u3092\u7D42\u4E86\u3059\u308B
38
+ (\u4F8B: lsof -i :${e} \u3067\u30D7\u30ED\u30BB\u30B9\u3092\u78BA\u8A8D)
39
+ 2. \u307E\u305F\u306F\u3001\u8A2D\u5B9A\u3067\u30DD\u30FC\u30C8\u3092\u5909\u66F4\u3057\u3001freee \u30A2\u30D7\u30EA\u306E\u30B3\u30FC\u30EB\u30D0\u30C3\u30AFURL\u3082\u66F4\u65B0\u3059\u308B
40
+ (freee-mcp configure \u3092\u5B9F\u884C\u3057\u3066\u518D\u8A2D\u5B9A)`)}return this.port=e,new Promise((n,o)=>{this.server=jt.createServer((a,i)=>{console.error(`Callback request: ${a.method} ${a.url}`);let s=new Nt(a.url,`http://127.0.0.1:${e}`);s.pathname==="/callback"?this.handleCallback(s,i):s.pathname==="/"?(i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end("<h1>freee MCP OAuth Server</h1><p>\u30B3\u30FC\u30EB\u30D0\u30C3\u30AF\u30B5\u30FC\u30D0\u30FC\u304C\u7A3C\u50CD\u4E2D\u3067\u3059\u3002</p>")):(i.writeHead(404,{"Content-Type":"text/html; charset=utf-8"}),i.end("<h1>404 Not Found</h1><p>\u3053\u306E\u30D1\u30B9\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002</p>"))}),this.server.on("error",a=>{let i=a instanceof Error?a.message:String(a);console.error(`OAuth callback server failed to start: ${i}`),this.server=null,this.port=null,o(new Error(`Failed to start OAuth callback server: ${i}`))}),this.server.listen(e,"127.0.0.1",()=>{console.error(`OAuth callback server listening on http://127.0.0.1:${e}`),n()})})}stop(){this.clearAutoStopTimeout(),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(r=>{let n=Ut.createServer();n.listen(e,"127.0.0.1",()=>{n.close(()=>{r(!0)})}),n.on("error",()=>{r(!1)})})}handleCallback(e,r){let n=e.searchParams.get("code"),o=e.searchParams.get("state"),a=e.searchParams.get("error"),i=e.searchParams.get("error_description");console.error(`Callback received - URL: ${e.toString()}`),console.error("Callback parameters:",{code:n?`${n.substring(0,10)}...`:null,state:o?`${o.substring(0,10)}...`:null,error:a,errorDescription:i}),console.error(`Pending authentications count: ${this.authManager.pendingCount}`);let s=o?this.authManager.getCliAuthHandler(o):void 0;if(a){let u=i||a;if(console.error(`OAuth error: ${a} - ${i}`),r.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),r.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: ${a} - ${i}`));else if(o){let x=this.authManager.getPendingAuthentication(o);x&&(clearTimeout(x.timeout),x.reject(new Error(`OAuth error: ${a} - ${i}`)),this.authManager.removePendingAuthentication(o))}return}if(!n||!o){console.error("Missing code or state"),r.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),r.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"),r.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),r.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(n);return}let p=this.authManager.getPendingAuthentication(o);if(!p){console.error(`Unknown state: ${o}`),r.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),r.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..."),r.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),r.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),re(n,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)})}},Ee=new _e,L=new ke(Ee);function J(){return L.getRedirectUri()}async function Xe(){return L.start()}async function Qe(t){await L.start(),L.scheduleAutoStop(t)}function Ye(t,e){Ee.registerAuthentication(t,e)}function Ze(){L.stop()}function et(){return Ee}M();w();function tt(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 b(),r=await N(e);if(!e)return l("\u4F1A\u793EID\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002freee_set_current_company \u3067\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");let n=await U("GET","/api/1/users/me");return l(`\u73FE\u5728\u306E\u30E6\u30FC\u30B6\u30FC\u60C5\u5831:
27
41
  \u4F1A\u793EID: ${e}
28
- \u4F1A\u793E\u540D: ${n?.name||"Unknown"}
42
+ \u4F1A\u793E\u540D: ${r?.name||"Unknown"}
29
43
  \u30E6\u30FC\u30B6\u30FC\u8A73\u7D30:
30
- ${JSON.stringify(r,null,2)}`}]}}catch(e){return{content:[{type:"text",text:`\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_authenticate","OAuth\u8A8D\u8A3C\u3092\u958B\u59CB\u3002\u521D\u56DE\u306E\u307F\u5FC5\u8981\u3002",{},async()=>{try{if(!l.freee.clientId)return{content:[{type:"text",text:`FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002
44
+ ${JSON.stringify(n,null,2)}`)}catch(e){return l(`\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557: ${k(e)}`)}}),t.tool("freee_authenticate","OAuth\u8A8D\u8A3C\u3092\u958B\u59CB\u3002\u521D\u56DE\u306E\u307F\u5FC5\u8981\u3002",{},async()=>{try{if(!h().freee.clientId)return l(`FREEE_CLIENT_ID\u74B0\u5883\u5909\u6570\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002
31
45
  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\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
46
+ \u30AF\u30E9\u30A4\u30A2\u30F3\u30C8ID\u3092\u74B0\u5883\u5909\u6570\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);if(!h().freee.clientSecret)return l(`FREEE_CLIENT_SECRET\u74B0\u5883\u5909\u6570\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002
33
47
  OAuth\u8A8D\u8A3C\u3092\u884C\u3046\u306B\u306F\u3001freee developers\u3067\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u4F5C\u6210\u3057\u3001
34
- \u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u30B7\u30FC\u30AF\u30EC\u30C3\u30C8\u3092\u74B0\u5883\u5909\u6570\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`}]};let{codeVerifier:e,codeChallenge:n}=Ie(),r=ut.randomBytes(16).toString("hex"),o=V(n,r,$());return $e(r,e),console.error(`Authentication URL: ${o}`),{content:[{type:"text",text:`\u8A8D\u8A3CURL: ${o}
48
+ \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`);await Qe(R);let{codeVerifier:e,codeChallenge:r}=We(),n=Lt.randomBytes(16).toString("hex"),o=te(r,n,J());return Ye(n,e),console.error(`Authentication URL: ${o}`),l(`\u8A8D\u8A3CURL: ${o}
35
49
 
36
- \u30D6\u30E9\u30A6\u30B6\u3067\u958B\u3044\u3066\u8A8D\u8A3C\u3057\u3066\u304F\u3060\u3055\u3044\u30025\u5206\u3067\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3059\u3002`}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u958B\u59CB\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_auth_status","\u8A8D\u8A3C\u72B6\u614B\u3092\u78BA\u8A8D\u3002",{},async()=>{try{let e=await se();if(!e)return{content:[{type:"text",text:"\u672A\u8A8D\u8A3C\u3002freee_authenticate \u3067\u8A8D\u8A3C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}]};let n=Date.now()<e.expires_at,r=new Date(e.expires_at).toLocaleString();return{content:[{type:"text",text:`\u8A8D\u8A3C\u72B6\u614B: ${n?"\u6709\u52B9":"\u671F\u9650\u5207\u308C"}
37
- \u6709\u52B9\u671F\u9650: ${r}`+(n?"":`
38
- \u6B21\u56DEAPI\u4F7F\u7528\u6642\u306B\u81EA\u52D5\u66F4\u65B0\u3055\u308C\u307E\u3059\u3002`)}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u72B6\u614B\u306E\u78BA\u8A8D\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_clear_auth","\u8A8D\u8A3C\u60C5\u5831\u3092\u30AF\u30EA\u30A2\u3002",{},async()=>{try{return await xe(),{content:[{type:"text",text:"\u8A8D\u8A3C\u60C5\u5831\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F\u3002\u518D\u8A8D\u8A3C\u3059\u308B\u306B\u306F freee_authenticate \u3092\u4F7F\u7528\u3002"}]}}catch(e){return{content:[{type:"text",text:`\u8A8D\u8A3C\u60C5\u5831\u306E\u30AF\u30EA\u30A2\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_set_current_company","\u4E8B\u696D\u6240\u3092\u8A2D\u5B9A\u30FB\u5207\u308A\u66FF\u3048\u3002",{company_id:ue.string().describe("\u4E8B\u696D\u6240ID"),name:ue.string().optional().describe("\u4E8B\u696D\u6240\u540D"),description:ue.string().optional().describe("\u8AAC\u660E")},async e=>{try{let{company_id:n,name:r,description:o}=e;return await re(n,r,o),{content:[{type:"text",text:`\u4E8B\u696D\u6240\u3092\u8A2D\u5B9A: ${(await S(n))?.name||n}`}]}}catch(n){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u306E\u8A2D\u5B9A\u306B\u5931\u6557: ${n instanceof Error?n.message:String(n)}`}]}}}),t.tool("freee_get_current_company","\u73FE\u5728\u306E\u4E8B\u696D\u6240\u60C5\u5831\u3092\u8868\u793A\u3002",{},async()=>{try{let e=await w(),n=await S(e);return n?{content:[{type:"text",text:`\u4E8B\u696D\u6240: ${n.name} (ID: ${n.id})`}]}:{content:[{type:"text",text:`\u4E8B\u696D\u6240ID: ${e} (\u8A73\u7D30\u60C5\u5831\u306A\u3057)`}]}}catch(e){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}}),t.tool("freee_list_companies","\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u8868\u793A\u3002",{},async()=>{try{let e=await F("GET","/api/1/companies"),n=await w();return e?.companies?.length?{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7:
39
- ${e.companies.map(o=>{let a=o.id===parseInt(n)?" *":"";return`${o.name} (${o.id})${a}`}).join(`
40
- `)}`}]}:{content:[{type:"text",text:"\u4E8B\u696D\u6240\u60C5\u5831\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002"}]}}catch(e){return{content:[{type:"text",text:`\u4E8B\u696D\u6240\u4E00\u89A7\u306E\u53D6\u5F97\u306B\u5931\u6557: ${e instanceof Error?e.message:String(e)}`}]}}})}import{z as s}from"zod";import Oe from"node:fs";import M from"node:path";import{fileURLToPath as dt}from"node:url";var de=M.dirname(dt(import.meta.url));function gt(){let t=[M.resolve(de,"./openapi/minimal"),M.resolve(de,"../dist/openapi/minimal"),M.resolve(de,"../../openapi/minimal")];for(let e of t)if(Oe.existsSync(e))return e;throw new Error(`Could not find minimal schema directory. Searched paths:
50
+ \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 l(`\u8A8D\u8A3C\u958B\u59CB\u306B\u5931\u6557: ${k(e)}`)}}),t.tool("freee_auth_status","\u8A8D\u8A3C\u72B6\u614B\u3092\u78BA\u8A8D\u3002",{},async()=>{try{let e=await we();if(!e)return l("\u672A\u8A8D\u8A3C\u3002freee_authenticate \u3067\u8A8D\u8A3C\u3057\u3066\u304F\u3060\u3055\u3044\u3002");let r=Date.now()<e.expires_at,n=new Date(e.expires_at).toLocaleString();return l(`\u8A8D\u8A3C\u72B6\u614B: ${r?"\u6709\u52B9":"\u671F\u9650\u5207\u308C"}
51
+ \u6709\u52B9\u671F\u9650: ${n}`+(r?"":`
52
+ \u6B21\u56DEAPI\u4F7F\u7528\u6642\u306B\u81EA\u52D5\u66F4\u65B0\u3055\u308C\u307E\u3059\u3002`))}catch(e){return l(`\u8A8D\u8A3C\u72B6\u614B\u306E\u78BA\u8A8D\u306B\u5931\u6557: ${k(e)}`)}}),t.tool("freee_clear_auth","\u8A8D\u8A3C\u60C5\u5831\u3092\u30AF\u30EA\u30A2\u3002",{},async()=>{try{return await ze(),l("\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 l(`\u8A8D\u8A3C\u60C5\u5831\u306E\u30AF\u30EA\u30A2\u306B\u5931\u6557: ${k(e)}`)}}),t.tool("freee_set_current_company","\u4E8B\u696D\u6240\u3092\u8A2D\u5B9A\u30FB\u5207\u308A\u66FF\u3048\u3002",{company_id:P.string().describe("\u4E8B\u696D\u6240ID"),name:P.string().optional().describe("\u4E8B\u696D\u6240\u540D"),description:P.string().optional().describe("\u8AAC\u660E")},async e=>{try{let{company_id:r,name:n,description:o}=e;await fe(r,n,o);let a=await N(r);return l(`\u4E8B\u696D\u6240\u3092\u8A2D\u5B9A: ${a?.name||r}`)}catch(r){return l(`\u4E8B\u696D\u6240\u306E\u8A2D\u5B9A\u306B\u5931\u6557: ${k(r)}`)}}),t.tool("freee_get_current_company","\u73FE\u5728\u306E\u4E8B\u696D\u6240\u60C5\u5831\u3092\u8868\u793A\u3002",{},async()=>{try{let e=await b(),r=await N(e);return r?l(`\u4E8B\u696D\u6240: ${r.name} (ID: ${r.id})`):l(`\u4E8B\u696D\u6240ID: ${e} (\u8A73\u7D30\u60C5\u5831\u306A\u3057)`)}catch(e){return l(`\u4E8B\u696D\u6240\u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557: ${k(e)}`)}}),t.tool("freee_list_companies","\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u8868\u793A\u3002",{},async()=>{try{let e=P.object({companies:P.array(P.object({id:P.number(),name:P.string()})).optional()}),r=await U("GET","/api/1/companies"),n=e.safeParse(r);if(!n.success)return{content:[{type:"text",text:`API\u30EC\u30B9\u30DD\u30F3\u30B9\u306E\u5F62\u5F0F\u304C\u4E0D\u6B63\u3067\u3059: ${n.error.message}`}]};let o=n.data,a=await b();if(!o?.companies?.length)return l("\u4E8B\u696D\u6240\u60C5\u5831\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002");let i=o.companies.map(s=>{let p=s.id===parseInt(a)?" *":"";return`${s.name} (${s.id})${p}`}).join(`
53
+ `);return l(`\u4E8B\u696D\u6240\u4E00\u89A7:
54
+ ${i}`)}catch(e){return l(`\u4E8B\u696D\u6240\u4E00\u89A7\u306E\u53D6\u5F97\u306B\u5931\u6557: ${k(e)}`)}})}import{z as c}from"zod";import it from"node:fs";import H from"node:path";import{fileURLToPath as Ht}from"node:url";import{z as g}from"zod";var Jt=g.object({name:g.string(),in:g.enum(["path","query"]),required:g.boolean().optional(),description:g.string().optional(),type:g.string()}),B=g.object({summary:g.string().optional(),description:g.string().optional(),parameters:g.array(Jt).optional(),hasJsonBody:g.boolean().optional()}),Bt=g.object({get:B.optional(),post:B.optional(),put:B.optional(),delete:B.optional(),patch:B.optional()}),rt=g.object({paths:g.record(g.string(),Bt)});var Ae=H.dirname(Ht(import.meta.url));function Vt(){let t=[H.resolve(Ae,"./openapi/minimal"),H.resolve(Ae,"../dist/openapi/minimal"),H.resolve(Ae,"../../openapi/minimal")];for(let e of t)if(it.existsSync(e))return e;throw new Error(`Could not find minimal schema directory. Searched paths:
41
55
  ${t.join(`
42
- `)}`)}var mt=gt();function ht(t){let e=M.join(mt,t),n=Oe.readFileSync(e,"utf-8");return JSON.parse(n)}var G={accounting:{schemaFile:"accounting.json",baseUrl:"https://api.freee.co.jp",prefix:"accounting",name:"freee\u4F1A\u8A08 API"},hr:{schemaFile:"hr.json",baseUrl:"https://api.freee.co.jp/hr",prefix:"hr",name:"freee\u4EBA\u4E8B\u52B4\u52D9 API"},invoice:{schemaFile:"invoice.json",baseUrl:"https://api.freee.co.jp/iv",prefix:"invoice",name:"freee\u8ACB\u6C42\u66F8 API"},pm:{schemaFile:"pm.json",baseUrl:"https://api.freee.co.jp/pm",prefix:"pm",name:"freee\u5DE5\u6570\u7BA1\u7406 API"},sm:{schemaFile:"sm.json",baseUrl:"https://api.freee.co.jp/sm",prefix:"sm",name:"freee\u8CA9\u58F2 API"}},ge={};function Me(t){if(!ge[t]){let e=G[t];ge[t]={schema:ht(e.schemaFile),baseUrl:e.baseUrl,prefix:e.prefix,name:e.name}}return ge[t]}var me=new Proxy({},{get(t,e){if(e in G)return Me(e)},ownKeys(){return Object.keys(G)},getOwnPropertyDescriptor(t,e){if(e in G)return{enumerable:!0,configurable:!0,value:Me(e)}}});function De(t,e,n,r){let o=r.schema.paths;if(e in o){let a=o[e];if(t in a)return{isValid:!0,message:"Valid path and method",operation:a[t],actualPath:e,apiType:n,baseUrl:r.baseUrl}}for(let a of Object.keys(o)){let i=a.replace(/\{[^}]+\}/g,"[^/]+");if(new RegExp(`^${i}$`).test(e)){let p=o[a];if(t in p)return{isValid:!0,message:"Valid path and method",operation:p[t],actualPath:e,apiType:n,baseUrl:r.baseUrl}}}return null}function je(t,e,n){let r=t.toLowerCase();if(n!==void 0){let o=me[n],a=De(r,e,n,o);return a||{isValid:!1,message:`Path '${e}' not found in ${o.name} schema. Please check the path format or use freee_api_list_paths to see available endpoints.`}}for(let[o,a]of Object.entries(me)){let i=De(r,e,o,a);if(i)return i}return{isValid:!1,message:`Path '${e}' not found in any freee API schema. Please check the path format or use freee_api_list_paths to see available endpoints.`}}function Le(){let t=[];for(let[,e]of Object.entries(me)){let n=e.schema.paths,r=[];Object.entries(n).forEach(([o,a])=>{let i=Object.keys(a).filter(c=>["get","post","put","delete","patch"].includes(c)).map(c=>c.toUpperCase());i.length>0&&r.push(` ${i.join("|")} ${o}`)}),r.length>0&&t.push(`
56
+ `)}`)}var zt=Vt();function qt(t){let e=H.join(zt,t),r=it.readFileSync(e,"utf-8"),n=JSON.parse(r),o=rt.safeParse(n);if(!o.success)throw new Error(`Invalid schema file ${t}: ${o.error.message}`);return o.data}var ne={accounting:{schemaFile:"accounting.json",baseUrl:"https://api.freee.co.jp",prefix:"accounting",name:"freee\u4F1A\u8A08 API"},hr:{schemaFile:"hr.json",baseUrl:"https://api.freee.co.jp/hr",prefix:"hr",name:"freee\u4EBA\u4E8B\u52B4\u52D9 API"},invoice:{schemaFile:"invoice.json",baseUrl:"https://api.freee.co.jp/iv",prefix:"invoice",name:"freee\u8ACB\u6C42\u66F8 API"},pm:{schemaFile:"pm.json",baseUrl:"https://api.freee.co.jp/pm",prefix:"pm",name:"freee\u5DE5\u6570\u7BA1\u7406 API"},sm:{schemaFile:"sm.json",baseUrl:"https://api.freee.co.jp/sm",prefix:"sm",name:"freee\u8CA9\u58F2 API"}},Te={};function nt(t){if(!Te[t]){let e=ne[t];Te[t]={schema:qt(e.schemaFile),baseUrl:e.baseUrl,prefix:e.prefix,name:e.name}}return Te[t]}var Pe=new Proxy({},{get(t,e){if(e in ne)return nt(e)},ownKeys(){return Object.keys(ne)},getOwnPropertyDescriptor(t,e){if(e in ne)return{enumerable:!0,configurable:!0,value:nt(e)}}});function ot(t,e,r,n){let o=n.schema.paths;if(e in o){let a=o[e];if(t in a)return{isValid:!0,message:"Valid path and method",operation:a[t],actualPath:e,apiType:r,baseUrl:n.baseUrl}}for(let a of Object.keys(o)){let i=a.replace(/\{[^}]+\}/g,"[^/]+");if(new RegExp(`^${i}$`).test(e)){let p=o[a];if(t in p)return{isValid:!0,message:"Valid path and method",operation:p[t],actualPath:e,apiType:r,baseUrl:n.baseUrl}}}return null}function at(t,e,r){let n=t.toLowerCase();if(r!==void 0){let o=Pe[r],a=ot(n,e,r,o);return a||{isValid:!1,message:`Path '${e}' not found in ${o.name} schema. Please check the path format or use freee_api_list_paths to see available endpoints.`}}for(let[o,a]of Object.entries(Pe)){let i=ot(n,e,o,a);if(i)return i}return{isValid:!1,message:`Path '${e}' not found in any freee API schema. Please check the path format or use freee_api_list_paths to see available endpoints.`}}function st(){let t=[];for(let[,e]of Object.entries(Pe)){let r=e.schema.paths,n=[];Object.entries(r).forEach(([o,a])=>{let i=Object.keys(a).filter(s=>["get","post","put","delete","patch"].includes(s)).map(s=>s.toUpperCase());i.length>0&&n.push(` ${i.join("|")} ${o}`)}),n.length>0&&t.push(`
43
57
  ## ${e.name} (${e.baseUrl})
44
- ${r.sort().join(`
58
+ ${n.sort().join(`
45
59
  `)}`)}return t.join(`
46
- `)}function yt(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="binary"}function Ct(t){let e=(t.size/1024).toFixed(2);return`\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u307E\u3057\u305F
60
+ `)}function Gt(t){let e=(t.size/1024).toFixed(2);return`\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u307E\u3057\u305F
47
61
 
48
62
  \u4FDD\u5B58\u5834\u6240: ${t.filePath}
49
63
  MIME\u30BF\u30A4\u30D7: ${t.mimeType}
50
- \u30B5\u30A4\u30BA: ${e} KB`}var D="service: accounting/hr/invoice/pm/sm",O=s.enum(["accounting","hr","invoice","pm","sm"]).describe("\u5BFE\u8C61\u306Efreee\u30B5\u30FC\u30D3\u30B9");function j(t){return async e=>{try{let{service:n,path:r,query:o,body:a}=e,i=je(t,r,n);if(!i.isValid)return{content:[{type:"text",text:`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${i.message}
64
+ \u30B5\u30A4\u30BA: ${e} KB`}var V="service: accounting/hr/invoice/pm/sm",z=c.enum(["accounting","hr","invoice","pm","sm"]).describe("\u5BFE\u8C61\u306Efreee\u30B5\u30FC\u30D3\u30B9");function q(t){return async e=>{try{let{service:r,path:n,query:o,body:a}=e,i=at(t,n,r);if(!i.isValid)return l(`\u30D1\u30B9\u691C\u8A3C\u30A8\u30E9\u30FC: ${i.message}
51
65
 
52
- \u5229\u7528\u53EF\u80FD\u306A\u30D1\u30B9\u3092\u78BA\u8A8D\u3059\u308B\u306B\u306F freee_api_list_paths \u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002`}]};let c=await F(t,i.actualPath,o,a,i.baseUrl);return yt(c)?{content:[{type:"text",text:Ct(c)}]}:{content:[{type:"text",text:JSON.stringify(c,null,2)}]}}catch(n){return{content:[{type:"text",text:`API\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC: ${n instanceof Error?n.message:String(n)}`}]}}}}function Ue(t){t.tool("freee_api_get",`freee API GET\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("GET")),t.tool("freee_api_post",`freee API POST\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals, /invoices)"),body:s.record(s.string(),s.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("POST")),t.tool("freee_api_put",`freee API PUT\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123, /invoices/123)"),body:s.record(s.string(),s.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("PUT")),t.tool("freee_api_delete",`freee API DELETE\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("DELETE")),t.tool("freee_api_patch",`freee API PATCH\u3002${D}`,{service:O,path:s.string().describe("API\u30D1\u30B9 (\u4F8B: /api/1/deals/123)"),body:s.record(s.string(),s.unknown()).describe("\u30EA\u30AF\u30A8\u30B9\u30C8\u30DC\u30C7\u30A3"),query:s.record(s.string(),s.unknown()).optional().describe("\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF (\u30AA\u30D7\u30B7\u30E7\u30F3)")},j("PATCH")),t.tool("freee_api_list_paths","freee API \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u4E00\u89A7\u3002\u8A73\u7D30\u306A\u30AC\u30A4\u30C9\u306Ffreee-mcp skill\u3092\u53C2\u7167\u3002",{},async()=>({content:[{type:"text",text:`# freee API \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u4E00\u89A7${Le()}
66
+ \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 U(t,i.actualPath,o,a,i.baseUrl);return Ge(s)?l(Gt(s)):l(JSON.stringify(s,null,2))}catch(r){return l(`API\u30EA\u30AF\u30A8\u30B9\u30C8\u30A8\u30E9\u30FC: ${k(r)}`)}}}function ct(t){t.tool("freee_api_get",`freee API GET\u3002${V}`,{service:z,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)")},q("GET")),t.tool("freee_api_post",`freee API POST\u3002${V}`,{service:z,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)")},q("POST")),t.tool("freee_api_put",`freee API PUT\u3002${V}`,{service:z,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)")},q("PUT")),t.tool("freee_api_delete",`freee API DELETE\u3002${V}`,{service:z,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)")},q("DELETE")),t.tool("freee_api_patch",`freee API PATCH\u3002${V}`,{service:z,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)")},q("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()=>{let e=st();return l(`# freee API \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u4E00\u89A7${e}
53
67
 
54
68
  \u4F7F\u7528\u4F8B:
55
69
  freee_api_get { "service": "accounting", "path": "/api/1/deals", "query": { "limit": 10 } }
56
70
  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 Ne(){let t=await ie(),e=new wt({name:t.server.name,version:t.server.version});Fe(e),Ue(e);try{await z(),console.error(`OAuth callback server started on http://127.0.0.1:${t.oauth.callbackPort}`)}catch(r){console.error("Failed to start callback server:",r),console.error("OAuth authentication will fall back to manual mode")}let n=new _t;await e.connect(n),console.error("Freee MCP Server running on stdio"),process.on("SIGINT",()=>{R(),process.exit(0)}),process.on("SIGTERM",()=>{R(),process.exit(0)})}import X from"prompts";import Ce from"node:crypto";import Et from"open";A();import K from"node:fs/promises";import v from"node:path";import L from"node:os";var W="freee-mcp",kt={command:"npx",args:["@him0/freee-mcp"]};function he(t){let e=L.platform();if(t==="claude-code")return v.join(L.homedir(),".claude.json");if(e==="darwin")return v.join(L.homedir(),"Library","Application Support","Claude","claude_desktop_config.json");if(e==="win32"){let n=process.env.APPDATA||v.join(L.homedir(),"AppData","Roaming");return v.join(n,"Claude","claude_desktop_config.json")}else return v.join(L.homedir(),".config","Claude","claude_desktop_config.json")}function He(t){return t==="claude-code"?"Claude Code":"Claude Desktop"}async function ye(t){try{let e=await K.readFile(t,"utf-8");return JSON.parse(e)}catch{return null}}async function Be(t,e){let n=v.dirname(t);await K.mkdir(n,{recursive:!0}),await K.writeFile(t,JSON.stringify(e,null,2)+`
58
- `,"utf-8")}async function Je(t){let e=he(t);try{await K.access(e);let n=await ye(e);return{path:e,exists:!0,hasFreeeConfig:n?.mcpServers?.[W]!==void 0}}catch{return{path:e,exists:!1,hasFreeeConfig:!1}}}async function Ve(t){let e=he(t),n=await ye(e);n||(n={}),n.mcpServers||(n.mcpServers={}),n.mcpServers[W]={...kt},await Be(e,n)}async function qe(t){let e=he(t),n=await ye(e);n?.mcpServers?.[W]&&(delete n.mcpServers[W],Object.keys(n.mcpServers).length===0&&delete n.mcpServers,await Be(e,n))}b();async function At(t){let e=await fetch(`${B}/api/1/companies`,{headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!e.ok){let r=await m(e);throw new Error(`\u4E8B\u696D\u6240\u4E00\u89A7\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${e.status} ${JSON.stringify(r)}`)}return(await e.json()).companies||[]}async function Pt(){let t=await Promise.resolve().then(()=>(A(),ve)).then(i=>i.loadFullConfig()),e=!!(t.clientId&&t.clientSecret);e&&(console.log("\u65E2\u5B58\u306E\u8A2D\u5B9A\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002"),console.log(` \u5909\u66F4\u3057\u306A\u3044\u9805\u76EE\u306F\u305D\u306E\u307E\u307E Enter \u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002
71
+ freee_api_post { "service": "accounting", "path": "/api/1/deals", "body": { "issue_date": "2024-01-01", ... } }`)})}async function lt(){let t=await de(),e=new Kt({name:t.server.name,version:t.server.version});tt(e),ct(e);let r=new Wt;await e.connect(r),console.error("Freee MCP Server running on stdio")}import ae from"prompts";import oe from"node:fs/promises";import O from"node:path";import G from"node:os";var ie="freee-mcp",Xt={command:"npx",args:["@him0/freee-mcp"]};function Se(t){let e=G.platform();if(t==="claude-code")return O.join(G.homedir(),".claude.json");if(e==="darwin")return O.join(G.homedir(),"Library","Application Support","Claude","claude_desktop_config.json");if(e==="win32"){let r=process.env.APPDATA||O.join(G.homedir(),"AppData","Roaming");return O.join(r,"Claude","claude_desktop_config.json")}else return O.join(G.homedir(),".config","Claude","claude_desktop_config.json")}function pt(t){return t==="claude-code"?"Claude Code":"Claude Desktop"}async function ve(t){try{let e=await oe.readFile(t,"utf-8");return JSON.parse(e)}catch{return null}}async function ut(t,e){let r=O.dirname(t);await oe.mkdir(r,{recursive:!0}),await oe.writeFile(t,JSON.stringify(e,null,2)+`
72
+ `,"utf-8")}async function ft(t){let e=Se(t);try{await oe.access(e);let r=await ve(e);return{path:e,exists:!0,hasFreeeConfig:r?.mcpServers?.[ie]!==void 0}}catch{return{path:e,exists:!1,hasFreeeConfig:!1}}}async function mt(t){let e=Se(t),r=await ve(e);r||(r={}),r.mcpServers||(r.mcpServers={}),r.mcpServers[ie]={...Xt},await ut(e,r)}async function dt(t){let e=Se(t),r=await ve(e);r?.mcpServers?.[ie]&&(delete r.mcpServers[ie],Object.keys(r.mcpServers).length===0&&delete r.mcpServers,await ut(e,r))}w();w();import{z as I}from"zod";var Qt=I.object({id:I.number(),name:I.string(),display_name:I.string(),role:I.string()}),gt=I.object({companies:I.array(Qt).optional()});async function ht(t){let e=await fetch(`${X}/api/1/companies`,{headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"}});if(!e.ok){let o=await _(e),a=o.success?JSON.stringify(o.data):`(JSON parse failed: ${o.error})`;throw new Error(`\u4E8B\u696D\u6240\u4E00\u89A7\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${e.status} ${a}`)}let r=await e.json(),n=gt.safeParse(r);if(!n.success)throw new Error(`Invalid companies response format: ${n.error.message}`);return n.data.companies||[]}async function Ct(){let t=await Promise.resolve().then(()=>(M(),Ue)).then(i=>i.loadFullConfig()),e=!!(t.clientId&&t.clientSecret);e&&(console.log("\u65E2\u5B58\u306E\u8A2D\u5B9A\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002"),console.log(` \u5909\u66F4\u3057\u306A\u3044\u9805\u76EE\u306F\u305D\u306E\u307E\u307E Enter \u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002
59
73
  `)),console.log(`\u30B9\u30C6\u30C3\u30D7 1/3: OAuth\u8A8D\u8A3C\u60C5\u5831\u306E\u5165\u529B
60
- `);let n=await X([{type:"text",name:"clientId",message:"FREEE_CLIENT_ID:",initial:t.clientId||void 0,validate:i=>i.trim()?!0:"CLIENT_ID \u306F\u5FC5\u9808\u3067\u3059"},{type:"password",name:"clientSecret",message:e?"FREEE_CLIENT_SECRET (\u5909\u66F4\u3057\u306A\u3044\u5834\u5408\u306F\u7A7A\u6B04):":"FREEE_CLIENT_SECRET:",validate:i=>e&&!i.trim()||i.trim()?!0:"CLIENT_SECRET \u306F\u5FC5\u9808\u3067\u3059"},{type:"text",name:"callbackPort",message:"FREEE_CALLBACK_PORT:",initial:String(t.callbackPort||x)}]);if(!n.clientId)throw new Error("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002");let r=n.clientId.trim(),o=n.clientSecret.trim()||t.clientSecret,a=parseInt(n.callbackPort.trim(),10);if(!o)throw new Error("CLIENT_SECRET \u306F\u5FC5\u9808\u3067\u3059\u3002");return process.env.FREEE_CLIENT_ID=r,process.env.FREEE_CLIENT_SECRET=o,process.env.FREEE_CALLBACK_PORT=String(a),console.log(`
74
+ `);let r=await ae([{type:"text",name:"clientId",message:"FREEE_CLIENT_ID:",initial:t.clientId||void 0,validate:i=>i.trim()?!0:"CLIENT_ID \u306F\u5FC5\u9808\u3067\u3059"},{type:"password",name:"clientSecret",message:e?"FREEE_CLIENT_SECRET (\u5909\u66F4\u3057\u306A\u3044\u5834\u5408\u306F\u7A7A\u6B04):":"FREEE_CLIENT_SECRET:",validate:i=>e&&!i.trim()||i.trim()?!0:"CLIENT_SECRET \u306F\u5FC5\u9808\u3067\u3059"},{type:"text",name:"callbackPort",message:"FREEE_CALLBACK_PORT:",initial:String(t.callbackPort||j)}]);if(!r.clientId)throw new Error("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002");let n=r.clientId.trim(),o=r.clientSecret.trim()||t.clientSecret,a=parseInt(r.callbackPort.trim(),10);if(!o)throw new Error("CLIENT_SECRET \u306F\u5FC5\u9808\u3067\u3059\u3002");return process.env.FREEE_CLIENT_ID=n,process.env.FREEE_CLIENT_SECRET=o,process.env.FREEE_CALLBACK_PORT=String(a),console.log(`
61
75
  \u8A8D\u8A3C\u60C5\u5831\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002
62
- `),{clientId:r,clientSecret:o,callbackPort:a}}async function vt(){console.log(`\u30B9\u30C6\u30C3\u30D7 2/3: OAuth\u8A8D\u8A3C
63
- `),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(y(),Te)).then(i=>i.loadConfig()),await z();let t=Ce.randomBytes(32).toString("base64url"),e=Ce.createHash("sha256").update(t).digest("base64url"),n=Ce.randomBytes(16).toString("base64url"),r=V(e,n,$());console.log(`
64
- \u8A8D\u8A3CURL: ${r}
65
- `),await Et(r),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u3092\u5B8C\u4E86\u3057\u3066\u304F\u3060\u3055\u3044..."),console.log(`\u8A8D\u8A3C\u304C\u5B8C\u4E86\u3059\u308B\u3068\u81EA\u52D5\u7684\u306B\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u306B\u9032\u307F\u307E\u3059\u3002
66
- `);let o=Re(),a=new Promise((i,c)=>{let p=setTimeout(()=>{c(new Error("\u8A8D\u8A3C\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\uFF085\u5206\uFF09"))},N);o.registerCliAuthHandler(n,{resolve:f=>{clearTimeout(p),i(f)},reject:f=>{clearTimeout(p),c(f)},codeVerifier:t})});try{let i=await a;console.log("\u8A8D\u8A3C\u30B3\u30FC\u30C9\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002"),console.log("\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u4E2D...");let c=await q(i,t,$());return console.log(`\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002
67
- `),{accessToken:c.access_token,refreshToken:c.refresh_token}}finally{o.removeCliAuthHandler(n)}}async function Tt(t){console.log(`\u30B9\u30C6\u30C3\u30D7 3/3: \u30C7\u30D5\u30A9\u30EB\u30C8\u4E8B\u696D\u6240\u306E\u9078\u629E
68
- `),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await At(t);if(e.length===0)throw new Error("\u5229\u7528\u53EF\u80FD\u306A\u4E8B\u696D\u6240\u304C\u3042\u308A\u307E\u305B\u3093\u3002");let n=await X({type:"select",name:"companyId",message:"\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u4E8B\u696D\u6240\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044:",choices:e.map(o=>({title:`${o.display_name||o.name} (ID: ${o.id}) - ${o.role}`,value:o.id}))});if(!n.companyId)throw new Error("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002");let r=e.find(o=>o.id===n.companyId);if(!r)throw new Error(`\u9078\u629E\u3057\u305F\u4E8B\u696D\u6240\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ID ${n.companyId}`);return console.log(`
69
- ${r.display_name||r.name} \u3092\u9078\u629E\u3057\u307E\u3057\u305F\u3002
70
- `),{selected:{id:r.id,name:r.name,displayName:r.display_name||r.name,role:r.role},all:e}}async function xt(t,e,n){let r={clientId:t.clientId,clientSecret:t.clientSecret,callbackPort:t.callbackPort,defaultCompanyId:String(e.id),currentCompanyId:String(e.id),companies:{}};n.forEach(o=>{r.companies[String(o.id)]={id:String(o.id),name:o.display_name||o.name,description:`Role: ${o.role}`,addedAt:Date.now(),lastUsed:o.id===e.id?Date.now():void 0}}),await E(r),console.log(`\u8A2D\u5B9A\u60C5\u5831\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F\u3002
71
- `),console.log("\u8A8D\u8A3C\u60C5\u5831\u306F ~/.config/freee-mcp/config.json \u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002"),console.log(`\u30C8\u30FC\u30AF\u30F3\u306F ~/.config/freee-mcp/tokens.json \u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F\u3002
72
- `)}async function ze(t){let e=He(t),n=await Je(t);if(n.hasFreeeConfig){let{action:r}=await X({type:"select",name:"action",message:`${e} \u306B freee-mcp \u304C\u8A2D\u5B9A\u6E08\u307F\u3067\u3059\u3002\u3069\u3046\u3057\u307E\u3059\u304B?`,choices:[{title:"\u305D\u306E\u307E\u307E (\u5909\u66F4\u306A\u3057)",value:"keep"},{title:"\u524A\u9664\u3059\u308B",value:"remove"}],initial:0});r==="remove"?(await qe(t),console.log(` \u2713 ${e} \u304B\u3089 freee-mcp \u3092\u524A\u9664\u3057\u307E\u3057\u305F\u3002`)):console.log(` - ${e} \u306E\u8A2D\u5B9A\u306F\u5909\u66F4\u3057\u307E\u305B\u3093\u3002`)}else{let{shouldAdd:r}=await X({type:"confirm",name:"shouldAdd",message:`${e} \u306B freee-mcp \u3092\u8FFD\u52A0\u3057\u307E\u3059\u304B?`,initial:!0});r?(await Ve(t),console.log(` \u2713 ${e} \u306B freee-mcp \u3092\u8FFD\u52A0\u3057\u307E\u3057\u305F\u3002`),console.log(` \u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB: ${n.path}`)):console.log(` - ${e} \u3078\u306E\u8FFD\u52A0\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F\u3002`)}}async function bt(){console.log(`=== MCP\u8A2D\u5B9A ===
76
+ `),{clientId:n,clientSecret:o,callbackPort:a}}async function wt(t){console.log(`\u30B9\u30C6\u30C3\u30D7 3/3: \u30C7\u30D5\u30A9\u30EB\u30C8\u4E8B\u696D\u6240\u306E\u9078\u629E
77
+ `),console.log("\u4E8B\u696D\u6240\u4E00\u89A7\u3092\u53D6\u5F97\u4E2D...");let e=await ht(t);if(e.length===0)throw new Error("\u5229\u7528\u53EF\u80FD\u306A\u4E8B\u696D\u6240\u304C\u3042\u308A\u307E\u305B\u3093\u3002");let r=await ae({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(!r.companyId)throw new Error("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002");let n=e.find(o=>o.id===r.companyId);if(!n)throw new Error(`\u9078\u629E\u3057\u305F\u4E8B\u696D\u6240\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ID ${r.companyId}`);return console.log(`
78
+ ${n.display_name||n.name} \u3092\u9078\u629E\u3057\u307E\u3057\u305F\u3002
79
+ `),{selected:{id:n.id,name:n.name,displayName:n.display_name||n.name,role:n.role},all:e}}async function yt(t){let e=pt(t),r=await ft(t);if(r.hasFreeeConfig){let{action:n}=await ae({type:"select",name:"action",message:`${e} \u306B freee-mcp \u304C\u8A2D\u5B9A\u6E08\u307F\u3067\u3059\u3002\u3069\u3046\u3057\u307E\u3059\u304B?`,choices:[{title:"\u305D\u306E\u307E\u307E (\u5909\u66F4\u306A\u3057)",value:"keep"},{title:"\u524A\u9664\u3059\u308B",value:"remove"}],initial:0});n==="remove"?(await dt(t),console.log(` \u2713 ${e} \u304B\u3089 freee-mcp \u3092\u524A\u9664\u3057\u307E\u3057\u305F\u3002`)):console.log(` - ${e} \u306E\u8A2D\u5B9A\u306F\u5909\u66F4\u3057\u307E\u305B\u3093\u3002`)}else{let{shouldAdd:n}=await ae({type:"confirm",name:"shouldAdd",message:`${e} \u306B freee-mcp \u3092\u8FFD\u52A0\u3057\u307E\u3059\u304B?`,initial:!0});n?(await mt(t),console.log(` \u2713 ${e} \u306B freee-mcp \u3092\u8FFD\u52A0\u3057\u307E\u3057\u305F\u3002`),console.log(` \u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB: ${r.path}`)):console.log(` - ${e} \u3078\u306E\u8FFD\u52A0\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F\u3002`)}}async function _t(){console.log(`=== MCP\u8A2D\u5B9A ===
73
80
  `),console.log(`Claude Code / Claude Desktop \u306B freee-mcp \u3092\u8A2D\u5B9A\u3067\u304D\u307E\u3059\u3002
74
- `),await ze("claude-code"),console.log(""),await ze("claude-desktop"),console.log(""),console.log("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5B8C\u4E86!"),console.log(`\u5909\u66F4\u3092\u53CD\u6620\u3059\u308B\u306B\u306F\u3001Claude Code / Claude Desktop \u3092\u518D\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\u3002
75
- `)}async function Ge(){console.log(`
81
+ `),await yt("claude-code"),console.log(""),await yt("claude-desktop"),console.log(""),console.log("\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5B8C\u4E86!"),console.log(`\u5909\u66F4\u3092\u53CD\u6620\u3059\u308B\u306B\u306F\u3001Claude Code / Claude Desktop \u3092\u518D\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\u3002
82
+ `)}import be from"node:crypto";import Yt from"open";w();async function kt(){console.log(`\u30B9\u30C6\u30C3\u30D7 2/3: OAuth\u8A8D\u8A3C
83
+ `),console.log("\u30D6\u30E9\u30A6\u30B6\u3067\u8A8D\u8A3C\u30DA\u30FC\u30B8\u3092\u958B\u304D\u307E\u3059..."),await Promise.resolve().then(()=>(T(),Le)).then(i=>i.loadConfig()),await Xe();let t=be.randomBytes(32).toString("base64url"),e=be.createHash("sha256").update(t).digest("base64url"),r=be.randomBytes(16).toString("base64url"),n=te(e,r,J());console.log(`
84
+ \u8A8D\u8A3CURL: ${n}
85
+ `),await Yt(n),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
86
+ `);let o=et(),a=new Promise((i,s)=>{let p=setTimeout(()=>{s(new Error("\u8A8D\u8A3C\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\uFF085\u5206\uFF09"))},R);o.registerCliAuthHandler(r,{resolve:u=>{clearTimeout(p),i(u)},reject:u=>{clearTimeout(p),s(u)},codeVerifier:t})});try{let i=await a;console.log("\u8A8D\u8A3C\u30B3\u30FC\u30C9\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\u3002"),console.log("\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u4E2D...");let s=await re(i,t,J());return console.log(`\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002
87
+ `),{accessToken:s.access_token,refreshToken:s.refresh_token}}finally{o.removeCliAuthHandler(r)}}M();async function Et(t,e,r){let n={clientId:t.clientId,clientSecret:t.clientSecret,callbackPort:t.callbackPort,defaultCompanyId:String(e.id),currentCompanyId:String(e.id),companies:{}};r.forEach(o=>{n.companies[String(o.id)]={id:String(o.id),name:o.display_name||o.name,description:`Role: ${o.role}`,addedAt:Date.now(),lastUsed:o.id===e.id?Date.now():void 0}}),await $(n),console.log(`\u8A2D\u5B9A\u60C5\u5831\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F\u3002
88
+ `),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
89
+ `)}async function Ie(){console.log(`
76
90
  === freee-mcp Configuration Setup ===
77
91
  `),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
78
- `);try{let t=await Pt(),e=await vt(),{selected:n,all:r}=await Tt(e.accessToken);await xt(t,n,r),await bt()}catch(t){t instanceof Error?console.error(`
92
+ `);try{let t=await Ct(),e=await kt(),{selected:r,all:n}=await wt(e.accessToken);await Et(t,r,n),await _t()}catch(t){t instanceof Error?console.error(`
79
93
  Error: ${t.message}`):console.error(`
80
- \u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:`,t),process.exit(1)}finally{R()}}var St=async()=>{let e=process.argv.slice(2)[0];if(e==="configure"){await Ge();return}e&&e!=="client"&&(console.error(`Unknown subcommand: ${e}`),console.error("Usage: freee-mcp [configure]"),console.error(" configure - Interactive configuration setup"),process.exit(1)),console.error("Starting freee MCP server"),await Ne()};St().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
94
+ \u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:`,t),process.exit(1)}finally{Ze()}}var Zt=async()=>{let e=process.argv.slice(2)[0];if(e==="configure"){await Ie();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 lt()};Zt().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@him0/freee-mcp",
4
- "version": "0.6.0",
5
- "main": "dist/index.js",
4
+ "version": "0.6.2",
6
5
  "bin": {
7
6
  "freee-mcp": "./bin/cli.js"
8
7
  },
@@ -10,24 +9,10 @@
10
9
  "license": "ISC",
11
10
  "description": "Model Context Protocol (MCP) server for freee API integration",
12
11
  "devDependencies": {
13
- "@changesets/cli": "^2.29.8",
14
12
  "@modelcontextprotocol/inspector": "^0.17.2",
15
- "@types/crypto-js": "^4.2.2",
16
- "@types/node": "^24.10.1",
17
- "@types/prompts": "^2.4.9",
18
- "@typescript-eslint/eslint-plugin": "^8.48.1",
19
- "@typescript-eslint/parser": "^8.48.1",
20
13
  "@vitest/coverage-v8": "^3.2.4",
21
14
  "@vitest/ui": "^3.2.4",
22
- "esbuild": "^0.25.12",
23
- "eslint": "^9.39.1",
24
- "eslint-config-prettier": "^10.1.8",
25
- "jsdom": "^26.1.0",
26
15
  "knip": "^5.78.0",
27
- "prettier": "^3.7.4",
28
- "tsx": "^4.21.0",
29
- "typescript": "^5.9.3",
30
- "vitest": "^3.2.4",
31
16
  "yaml": "^2.8.2"
32
17
  },
33
18
  "dependencies": {
@@ -46,7 +31,8 @@
46
31
  ],
47
32
  "repository": {
48
33
  "type": "git",
49
- "url": "https://github.com/him0/freee-mcp.git"
34
+ "url": "https://github.com/him0/freee-mcp.git",
35
+ "directory": "packages/freee-mcp"
50
36
  },
51
37
  "files": [
52
38
  "dist/",
@@ -54,9 +40,7 @@
54
40
  "README.md"
55
41
  ],
56
42
  "scripts": {
57
- "build": "pnpm run build:types && pnpm run build:esbuild",
58
- "build:esbuild": "tsx build.ts",
59
- "build:types": "tsc --declaration --emitDeclarationOnly --declarationDir './dist'",
43
+ "build": "tsx build.ts",
60
44
  "start": "tsx src/index.ts",
61
45
  "dev": "tsx watch src/index.ts",
62
46
  "typecheck": "tsc --noEmit",
@@ -70,9 +54,6 @@
70
54
  "test:coverage": "vitest run --coverage",
71
55
  "test:ui": "vitest --ui",
72
56
  "generate:references": "tsx scripts/generate-references.ts",
73
- "fetch:schemas": "tsx scripts/fetch-schemas.ts",
74
- "changeset": "changeset",
75
- "version": "changeset version",
76
- "release": "pnpm build && changeset publish"
57
+ "fetch:schemas": "tsx scripts/fetch-schemas.ts"
77
58
  }
78
59
  }
package/README.md DELETED
@@ -1,171 +0,0 @@
1
- # @him0/freee-mcp
2
-
3
- freee API を Claude から使えるようにする MCP サーバー & Claude Plugin です。
4
-
5
- MCP サーバー(API 呼び出し機能)と skill(API リファレンス)を組み合わせて利用することを想定しています。
6
-
7
- [![npm version](https://badge.fury.io/js/@him0%2Ffreee-mcp.svg)](https://www.npmjs.com/package/@him0/freee-mcp)
8
-
9
- > Note: このプロジェクトは開発中であり、予期せぬ不具合が発生する可能性があります。問題を発見された場合は [Issue](https://github.com/him0/freee-mcp/issues) として報告していただけると幸いです。プルリクエストも歓迎しています。
10
-
11
- ## 特徴
12
-
13
- - MCP サーバー: freee API を Claude Desktop / Claude Code から直接呼び出し
14
- - Claude Plugin: 詳細な API リファレンスドキュメント付きスキルを提供
15
- - 複数 API 対応: 会計・人事労務・請求書・工数管理・販売の5つの freee API をサポート
16
- - OAuth 2.0 + PKCE: セキュアな認証フロー、トークン自動更新
17
- - 複数事業所対応: 事業所の動的切り替えが可能
18
-
19
- ## クイックスタート
20
-
21
- ### 1. freee アプリケーションの登録
22
-
23
- [freee アプリストア](https://app.secure.freee.co.jp/developers) で新しいアプリを作成:
24
-
25
- - コールバックURL: `http://127.0.0.1:54321/callback`
26
- - Client ID と Client Secret を取得
27
- - 必要な権限にチェック
28
-
29
- ### 2. セットアップ
30
-
31
- ```bash
32
- npx @him0/freee-mcp configure
33
- ```
34
-
35
- 対話式ウィザードが認証情報の設定、OAuth認証、事業所選択を行います。
36
-
37
- ### 3. Claude Desktop に追加
38
-
39
- `configure` が出力する設定を Claude Desktop の設定ファイルに追加:
40
-
41
- | OS | 設定ファイルパス |
42
- | ------- | ----------------------------------------------------------------- |
43
- | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
44
- | Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
45
- | Linux | `~/.config/Claude/claude_desktop_config.json` |
46
-
47
- ```json
48
- {
49
- "mcpServers": {
50
- "freee": {
51
- "command": "npx",
52
- "args": ["@him0/freee-mcp"]
53
- }
54
- }
55
- }
56
- ```
57
-
58
- > ⚠️ 環境変数での設定について
59
- > 環境変数(`FREEE_CLIENT_ID`、`FREEE_CLIENT_SECRET` など)を使った設定は非推奨です。
60
- > 代わりに `npx @him0/freee-mcp configure` を実行して設定ファイルに移行してください。
61
- > 環境変数設定は将来のバージョンで削除される予定です。
62
-
63
- ## Claude Plugin として使う
64
-
65
- Claude Code でプラグインとしてインストールすると、API リファレンス付きのスキルが利用できます:
66
-
67
- ```bash
68
- claude plugin marketplace add him0/freee-mcp
69
- claude plugin install freee-api
70
- ```
71
-
72
- ### 含まれるリファレンス
73
-
74
- | API | 内容 | ファイル数 |
75
- | -------- | -------------------------------------------- | ---------- |
76
- | 会計 | 取引、勘定科目、取引先、請求書、経費申請など | 31 |
77
- | 人事労務 | 従業員、勤怠、給与明細、年末調整など | 27 |
78
- | 請求書 | 請求書、見積書、納品書 | 3 |
79
- | 工数管理 | ユーザー情報 | 1 |
80
- | 販売 | 案件、受注 | 2 |
81
-
82
- Claude との会話中に API の使い方を質問すると、これらのリファレンスを参照して正確な情報を提供します。
83
-
84
- ### データ作成のベストプラクティス
85
-
86
- 請求書や経費精算など、同じ形式のデータを繰り返し作成する場合は、以前に作成したデータを参照することで効率的に作業できます:
87
-
88
- - 請求書作成: 過去の請求書を取得して、取引先・品目・税区分などを参考にする
89
- - 経費精算: 過去の申請を参照して、勘定科目や部門の指定を正確に行う
90
- - 取引登録: 類似の取引を参考にして、入力ミスを防ぐ
91
-
92
- ```
93
- 例: 「先月の○○社への請求書を参考に、今月分を作成して」
94
- ```
95
-
96
- ## 利用可能なツール
97
-
98
- ### 管理ツール
99
-
100
- | ツール | 説明 |
101
- | -------------------------- | ------------------ |
102
- | `freee_authenticate` | OAuth 認証を実行 |
103
- | `freee_auth_status` | 認証状態を確認 |
104
- | `freee_clear_auth` | 認証情報をクリア |
105
- | `freee_set_current_company`| 事業所を切り替え |
106
- | `freee_get_current_company`| 現在の事業所を表示 |
107
- | `freee_list_companies` | 事業所一覧を取得 |
108
- | `freee_current_user` | 現在のユーザー情報 |
109
-
110
- ### API ツール
111
-
112
- HTTPメソッドごとのシンプルなツール構成:
113
-
114
- | ツール | 説明 | 例 |
115
- | ---------------------- | ------------------ | ------------------ |
116
- | `freee_api_get` | データ取得 | `/api/1/deals` |
117
- | `freee_api_post` | 新規作成 | `/api/1/deals` |
118
- | `freee_api_put` | 更新 | `/api/1/deals/123` |
119
- | `freee_api_delete` | 削除 | `/api/1/deals/123` |
120
- | `freee_api_patch` | 部分更新 | `/api/1/deals/123` |
121
- | `freee_api_list_paths` | エンドポイント一覧 | - |
122
-
123
- パスは OpenAPI スキーマに対して自動検証されます。
124
-
125
- ### company_id の取り扱い
126
-
127
- リクエスト(パラメータまたはボディ)に `company_id` を含める場合、現在の事業所と一致している必要があります。不一致の場合はエラーになります。
128
-
129
- - 事業所の確認: `freee_get_current_company`
130
- - 事業所の切り替え: `freee_set_company`
131
- - company_id を含まない API(例: `/api/1/companies`)はそのまま実行可能
132
-
133
- ## 開発者向け
134
-
135
- ```bash
136
- git clone https://github.com/him0/freee-mcp.git
137
- cd freee-mcp
138
- pnpm install
139
-
140
- pnpm dev # 開発サーバー(ウォッチモード)
141
- pnpm build # ビルド
142
- pnpm typecheck # 型チェック
143
- pnpm lint # リント
144
- pnpm test:run # テスト
145
-
146
- # API リファレンスの再生成
147
- pnpm generate:references
148
- ```
149
-
150
- ### 技術スタック
151
-
152
- TypeScript / Model Context Protocol SDK / OAuth 2.0 + PKCE / Zod / esbuild
153
-
154
- ### アーキテクチャ詳細
155
-
156
- プロジェクトのアーキテクチャ、内部構造、開発ガイドラインについては [CLAUDE.md](./CLAUDE.md) を参照してください。
157
-
158
- ## ライセンス
159
-
160
- ISC
161
-
162
- ## コミュニティ
163
-
164
- 質問や情報交換は Discord サーバーで行っています。お気軽にご参加ください。
165
-
166
- - [Discord サーバー](https://discord.gg/fPA75nHp)
167
-
168
- ## 関連リンク
169
-
170
- - [freee API ドキュメント](https://developer.freee.co.jp/docs)
171
- - [Model Context Protocol](https://modelcontextprotocol.io)
package/dist/.keep DELETED
File without changes
@@ -1,10 +0,0 @@
1
- /**
2
- * Response type for binary file downloads
3
- */
4
- export interface BinaryFileResponse {
5
- type: 'binary';
6
- filePath: string;
7
- mimeType: string;
8
- size: number;
9
- }
10
- export declare function makeApiRequest(method: string, apiPath: string, params?: Record<string, unknown>, body?: Record<string, unknown>, baseUrl?: string): Promise<unknown | BinaryFileResponse>;
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- import { TokenData } from './tokens.js';
2
- export declare function generatePKCE(): {
3
- codeVerifier: string;
4
- codeChallenge: string;
5
- };
6
- export declare function buildAuthUrl(codeChallenge: string, state: string, redirectUri: string): string;
7
- export declare function exchangeCodeForTokens(code: string, codeVerifier: string, redirectUri: string): Promise<TokenData>;
@@ -1 +0,0 @@
1
- export {};