@flyle/ai-operator-mcp 0.0.0-stage → 0.6.1-develop.20261101093550.g442b937

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/LICENSE ADDED
@@ -0,0 +1,53 @@
1
+ Flyle AIオペレーター MCP サーバー 使用許諾条件
2
+
3
+ 本ソフトウェア(`@flyle/ai-operator-mcp`。以下「本ソフトウェア」)に関する著作権その他
4
+ の知的財産権は、株式会社Flyle(以下「当社」)に帰属します。本ソフトウェアは、以下の条件に同意
5
+ された場合に限りご使用いただけます。
6
+
7
+ 1. 使用許諾
8
+
9
+ 当社は、当社との間で Flyle AIオペレーター(以下「本サービス」)の利用契約を締結して
10
+ いるお客様に対し、当該契約の有効期間中、本サービスを利用する目的に限り、本ソフトウェアを
11
+ 使用する非独占的かつ譲渡不能の権利を許諾します。
12
+
13
+ 本ソフトウェアの実行に必要な範囲での複製(パッケージレジストリからの取得および実行環境への
14
+ キャッシュを含みます)は、本許諾に含まれます。
15
+
16
+ 2. 禁止事項
17
+
18
+ お客様は、前項に定める範囲を超えて本ソフトウェアを利用してはならず、特に次の行為を行っては
19
+ なりません。
20
+
21
+ (1) 第三者への再配布、貸与、販売、譲渡、公衆送信
22
+ (2) 改変、翻案、派生物の作成
23
+ (3) リバースエンジニアリング、逆コンパイル、逆アセンブル
24
+ (4) 著作権表示その他の権利に関する表示の削除または改変
25
+
26
+ 3. 無保証
27
+
28
+ 本ソフトウェアは現状有姿で提供されます。当社は、本ソフトウェアが特定の目的に適合すること、
29
+ および瑕疵がないことを保証しません。
30
+
31
+ 4. 責任の制限
32
+
33
+ 本ソフトウェアの使用または使用不能により生じた損害について、当社は責任を負いません。ただし、
34
+ 当社の故意または重過失による場合はこの限りではありません。
35
+
36
+ 5. 準拠法および関連規約
37
+
38
+ 本許諾は日本法に準拠します。本ソフトウェアの使用には、次の規約が併せて適用されます。
39
+
40
+ - 利用規約: https://flyle.io/jp/terms
41
+ - プライバシーポリシー: https://flyle.io/jp/privacy-policy
42
+ - セキュリティポリシー: https://flyle.io/jp/security-policy
43
+
44
+ 本許諾の定めと上記規約の定めとが矛盾する場合には、上記規約の定めが優先します。
45
+
46
+ ---
47
+
48
+ This software is proprietary and is NOT open source. It may be used only by customers
49
+ with an active Flyle AI Operator subscription, and solely for the purpose of using
50
+ that service. Redistribution, modification and reverse engineering are prohibited.
51
+ The Japanese text above is the governing version.
52
+
53
+ Copyright (c) 2026 Flyle, Inc. All rights reserved.
package/README.md CHANGED
@@ -1,3 +1,63 @@
1
- # Temporary Holding Version
1
+ # @flyle/ai-operator-mcp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Flyle AIオペレーターを Claude Code などの MCP クライアントから操作するための MCP サーバーです。ブラウザでご自身のアカウントにログインし、**ご自身のロールの権限の範囲で**エージェントの設定・検証などを行えます。
4
+
5
+ > [!NOTE]
6
+ > 試験的な提供です。現在は Flyle 社内メンバー(flyle.io ドメインのアカウント)に限定しています。仕様が変わる場合があります。
7
+
8
+ 詳しい使い方は、ご利用ガイドの「[公開 API で外部システムと連携する](https://guide.flyle.io/ja/flygate/public-api)」をご覧ください。
9
+
10
+ ## 必要なもの
11
+
12
+ - Node.js 22 以上
13
+ - テナント設定「外部ツールからのログイン接続」が許可されていること(「設定」>「テナント設定」)
14
+ - ご自身のロールに「外部ツール接続」の権限があること
15
+
16
+ ## はじめかた
17
+
18
+ 1. テナント専用の作業ディレクトリを用意します。1 つのディレクトリは 1 つのテナント専用になります。ホームディレクトリは使えません。
19
+
20
+ ```sh
21
+ mkdir acme-corp && cd acme-corp
22
+ ```
23
+
24
+ 2. そのディレクトリでログインします。ブラウザが開くので、同意画面で接続先のテナント・環境と操作できる範囲を確認して許可してください。
25
+
26
+ ```sh
27
+ npx @flyle/ai-operator-mcp@latest login --tenant <テナント名>
28
+ ```
29
+
30
+ 3. 同じディレクトリに `.mcp.json` を置き、Claude Code を起動します。
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "flyle-ai-operator": {
36
+ "command": "npx",
37
+ "args": ["-y", "@flyle/ai-operator-mcp@latest"]
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ Claude Code を起動したままログインした場合は、`/mcp` から MCP サーバーを再接続してください。
44
+
45
+ ## コマンド
46
+
47
+ 作業ディレクトリで実行します。
48
+
49
+ | コマンド | 内容 |
50
+ | --------------------------------------------------------------- | ---------------------------------------------------------------- |
51
+ | `npx @flyle/ai-operator-mcp@latest login --tenant <テナント名>` | ブラウザでログインします。2 回目以降は `--tenant` を省略できます |
52
+ | `npx @flyle/ai-operator-mcp@latest status` | ログイン中のテナント・環境と有効期限を表示します |
53
+ | `npx @flyle/ai-operator-mcp@latest logout` | ログアウトし、この作業ディレクトリの接続を切断します |
54
+
55
+ ログインは最後に使ってから 30 日間有効で、使うたびに延長されます。ただし、ログインしてから 90 日たつと、使い続けていても期限が切れるので `login` し直してください。ご自身の接続は管理画面の「設定」>「外部ツール接続」から確認・切断できます。
56
+
57
+ ## できること・できないこと
58
+
59
+ - エージェントの設定の取得・編集、ナレッジやファイルの取り込み、プレビューの準備、検証ケースの管理と検証の実行、改善提案の確認と反映・棄却などを行えます。
60
+ - 作業の前に Flyle AIオペレーターの考え方とご利用ガイドの記事を読み込みます(`get_product_guide`)。読み込むまで、公開 API を呼ぶツールは実行されません。
61
+ - 公開の実行・昇格・取消など、本番の応対に直接影響する操作は提供していません(公開状態の参照はできます)。
62
+ - ツールがダウンロードしたファイル(ナレッジ原本・音声など)は、作業ディレクトリの `.flyle-ai-operator-mcp/downloads` に保存されます。
63
+ - アップロードなどで読み込めるのは、作業ディレクトリの中のファイルだけです。
Binary file
package/main.js ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import{homedir as e,hostname as t,userInfo as n}from"node:os";import{serveStdio as r}from"@modelcontextprotocol/server/stdio";import{createHash as i,randomBytes as a,timingSafeEqual as o}from"node:crypto";import{chmod as s,link as c,mkdir as l,open as u,readFile as d,realpath as f,rename as p,rm as m,unlink as h,writeFile as g}from"node:fs/promises";import*as _ from"node:path";import{spawn as v}from"node:child_process";import{createServer as ee}from"node:http";import{parseArgs as te}from"node:util";import{constants as ne,readFileSync as re}from"node:fs";import{brotliDecompressSync as ie}from"node:zlib";import{McpServer as ae,fromJsonSchema as y}from"@modelcontextprotocol/server";var b=class extends Error{name=`InvalidArgumentsError`},x=class extends Error{name=`AuthError`;kind;constructor(e,t){super(t),this.kind=e}},oe=class extends Error{name=`ManifestLoadError`},S=class extends Error{name=`ApiError`;info;constructor(e){super(`${e.status} ${e.code??`http_error`}: ${e.message}`),this.info=e}},C=class extends Error{name=`TransportError`;kind;status;constructor(e,t,n=null){super(t),this.kind=e,this.status=n}},w=class extends Error{name=`TransferError`;kind;status;constructor(e,t,n=null){super(t),this.kind=e,this.status=n}},T=class extends Error{name=`LocalFileError`;kind;constructor(e,t){super(t),this.kind=e}},E=class extends Error{name=`InlineFileError`;kind;constructor(e,t){super(t),this.kind=e}},se=class extends Error{name=`OperationFailedError`;payload;constructor(e,t){super(e),this.payload=t}},D=class extends Error{name=`WorkspaceBindingError`;kind;constructor(e,t){super(t),this.kind=e}};const O=()=>{},ce=e=>e.operations.filter(e=>!e.responseContainsSecret);function k(e,t){return Object.hasOwn(e,t)}const le=(e,t)=>k(e,t),ue=e=>{let t=[];for(let n in e)le(e,n)&&t.push(n);return t},de=e=>{let t=[];for(let n in e)if(le(e,n)){let r=Reflect.get(e,n);t.push([n,r])}return t},fe=e=>{let t={};for(let[n,r]of e)Object.defineProperty(t,n,{configurable:!0,enumerable:!0,value:r,writable:!0});return t},A=e=>typeof e==`object`&&!!e&&!Array.isArray(e),pe={lang:void 0,message:void 0,abortEarly:void 0,abortPipeEarly:void 0};/* @__NO_SIDE_EFFECTS__ */
3
+ function me(e){return e?{lang:e?.lang??void 0,message:e?.message,abortEarly:e?.abortEarly??void 0,abortPipeEarly:e?.abortPipeEarly??void 0}:pe}/* @__NO_SIDE_EFFECTS__ */
4
+ function he(e){let t=typeof e;return t===`string`?`"${e}"`:t===`number`||t===`bigint`||t===`boolean`?`${e}`:t===`object`||t===`function`?(e&&Object.getPrototypeOf(e)?.constructor?.name)??`null`:t}function j(e,t,n,r,i){let a=i&&`input`in i?i.input:n.value,o=i?.expected??e.expects??null,s=i?.received??/* @__PURE__ */ he(a),c={kind:e.kind,type:e.type,input:a,expected:o,received:s,message:`Invalid ${t}: ${o?`Expected ${o} but r`:`R`}eceived ${s}`,requirement:e.requirement,path:i?.path,issues:i?.issues,lang:r.lang,abortEarly:r.abortEarly,abortPipeEarly:r.abortPipeEarly},l=e.kind===`schema`,u=i?.message??e.message??(e.reference,c.lang,void 0)??(l?(c.lang,void 0):null)??r.message??(c.lang,void 0);u!==void 0&&(c.message=typeof u==`function`?u(c):u),l&&(n.typed=!1),n.issues?n.issues.push(c):n.issues=[c]}/* @__NO_SIDE_EFFECTS__ */
5
+ function ge(e,t){return e===t||Number.isNaN(e)&&Number.isNaN(t)}/* @__NO_SIDE_EFFECTS__ */
6
+ function _e(e,t){return Object.prototype.hasOwnProperty.call(e,t)&&t!==`__proto__`&&t!==`prototype`&&t!==`constructor`}/* @__NO_SIDE_EFFECTS__ */
7
+ function ve(e,t){let n=[...new Set(e)];return n.length>1?`(${n.join(` ${t} `)})`:n[0]??`never`}function M(e){return e[`~standard`]={version:1,vendor:`valibot`,validate:t=>e[`~run`]({value:t},/* @__PURE__ */ me())},e}const ye=/^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])[T ](?:0\d|1\d|2[0-3])(?::[0-5]\d){2}(?:\.\d{1,9})?(?:Z| ?[+-](?:0\d|1\d|2[0-3])(?::?[0-5]\d)?)$/u;/* @__NO_SIDE_EFFECTS__ */
8
+ function be(e,t){return{kind:`validation`,type:`check`,reference:be,async:!1,expects:null,requirement:e,message:t,"~run"(e,t){return e.typed&&!this.requirement(e.value)&&j(this,`input`,e,t),e}}}/* @__NO_SIDE_EFFECTS__ */
9
+ function xe(e,t){let n=/* @__PURE__ */ he(e);return{kind:`validation`,type:`includes`,reference:xe,async:!1,expects:n,requirement:e,message:t,"~run"(e,t){return e.typed&&!e.value.includes(this.requirement)&&j(this,`content`,e,t,{received:`!${n}`}),e}}}/* @__NO_SIDE_EFFECTS__ */
10
+ function N(e){return{kind:`validation`,type:`iso_timestamp`,reference:N,async:!1,expects:null,requirement:ye,message:e,"~run"(e,t){return e.typed&&!this.requirement.test(e.value)&&j(this,`timestamp`,e,t),e}}}/* @__NO_SIDE_EFFECTS__ */
11
+ function Se(e){return{kind:`validation`,type:`non_empty`,reference:Se,async:!1,expects:`!0`,message:e,"~run"(e,t){return e.typed&&e.value.length===0&&j(this,`length`,e,t,{received:`0`}),e}}}/* @__NO_SIDE_EFFECTS__ */
12
+ function P(e,t){return{kind:`validation`,type:`regex`,reference:P,async:!1,expects:`${e}`,requirement:e,message:t,"~run"(e,t){return e.typed&&!this.requirement.test(e.value)&&j(this,`format`,e,t),e}}}/* @__NO_SIDE_EFFECTS__ */
13
+ function Ce(e){return{kind:`transformation`,type:`transform`,reference:Ce,async:!1,operation:e,"~run"(e){return e.value=this.operation(e.value),e}}}/* @__NO_SIDE_EFFECTS__ */
14
+ function we(e){return{kind:`validation`,type:`url`,reference:we,async:!1,expects:null,requirement(e){try{return URL.canParse?URL.canParse(e):(new URL(e),!0)}catch{return!1}},message:e,"~run"(e,t){return e.typed&&!this.requirement(e.value)&&j(this,`URL`,e,t),e}}}/* @__NO_SIDE_EFFECTS__ */
15
+ function Te(e,t,n){return typeof e.fallback==`function`?e.fallback(t,n):e.fallback}/* @__NO_SIDE_EFFECTS__ */
16
+ function Ee(e,t,n){return typeof e.default==`function`?e.default(t,n):e.default}/* @__NO_SIDE_EFFECTS__ */
17
+ function De(e,t){return M({kind:`schema`,type:`array`,reference:De,expects:`Array`,async:!1,item:e,message:t,"~run"(e,t){let n=e.value;if(Array.isArray(n)){e.typed=!0,e.value=[];for(let r=0;r<n.length;r++){let i=n[r],a=this.item[`~run`]({value:i},t);if(a.issues){let o={type:`array`,origin:`value`,input:n,key:r,value:i};for(let t of a.issues)t.path?t.path.unshift(o):t.path=[o],e.issues?.push(t);if(e.issues||=a.issues,t.abortEarly){e.typed=!1;break}}a.typed||(e.typed=!1),e.value.push(a.value)}}else j(this,`type`,e,t);return e}})}/* @__NO_SIDE_EFFECTS__ */
18
+ function Oe(e,t){return M({kind:`schema`,type:`literal`,reference:Oe,expects:/* @__PURE__ */ he(e),async:!1,literal:e,message:t,"~run"(e,t){return/* @__PURE__ */ ge(e.value,this.literal)?e.typed=!0:j(this,`type`,e,t),e}})}/* @__NO_SIDE_EFFECTS__ */
19
+ function ke(e,t){return M({kind:`schema`,type:`nullable`,reference:ke,expects:`(${e.expects} | null)`,async:!1,wrapped:e,default:t,"~run"(e,t){return e.value===null&&(this.default!==void 0&&(e.value=/* @__PURE__ */ Ee(this,e,t)),e.value===null)?(e.typed=!0,e):this.wrapped[`~run`](e,t)}})}/* @__NO_SIDE_EFFECTS__ */
20
+ function Ae(e){return M({kind:`schema`,type:`number`,reference:Ae,expects:`number`,async:!1,message:e,"~run"(e,t){return typeof e.value==`number`&&!isNaN(e.value)?e.typed=!0:j(this,`type`,e,t),e}})}/* @__NO_SIDE_EFFECTS__ */
21
+ function F(e,t){return M({kind:`schema`,type:`object`,reference:F,expects:`Object`,async:!1,entries:e,message:t,"~run"(e,t){let n=e.value;if(n&&typeof n==`object`){e.typed=!0,e.value={};for(let r in this.entries){let i=this.entries[r];if(r in n||(i.type===`exact_optional`||i.type===`optional`||i.type===`nullish`)&&i.default!==void 0){let a=r in n?n[r]:/* @__PURE__ */ Ee(i),o=i[`~run`]({value:a},t);if(o.issues){let i={type:`object`,origin:`value`,input:n,key:r,value:a};for(let t of o.issues)t.path?t.path.unshift(i):t.path=[i],e.issues?.push(t);if(e.issues||=o.issues,t.abortEarly){e.typed=!1;break}}o.typed||(e.typed=!1),e.value[r]=o.value}else if(i.fallback!==void 0)e.value[r]=/* @__PURE__ */ Te(i);else if(i.type!==`exact_optional`&&i.type!==`optional`&&i.type!==`nullish`&&(j(this,`key`,e,t,{input:void 0,expected:`"${r}"`,path:[{type:`object`,origin:`key`,input:n,key:r,value:n[r]}]}),t.abortEarly))break}}else j(this,`type`,e,t);return e}})}/* @__NO_SIDE_EFFECTS__ */
22
+ function je(e,t){return M({kind:`schema`,type:`optional`,reference:je,expects:`(${e.expects} | undefined)`,async:!1,wrapped:e,default:t,"~run"(e,t){return e.value===void 0&&(this.default!==void 0&&(e.value=/* @__PURE__ */ Ee(this,e,t)),e.value===void 0)?(e.typed=!0,e):this.wrapped[`~run`](e,t)}})}/* @__NO_SIDE_EFFECTS__ */
23
+ function Me(e,t,n){return M({kind:`schema`,type:`record`,reference:Me,expects:`Object`,async:!1,key:e,value:t,message:n,"~run"(e,t){let n=e.value;if(n&&typeof n==`object`){e.typed=!0,e.value={};for(let r in n)if(/* @__PURE__ */ _e(n,r)){let i=n[r],a=this.key[`~run`]({value:r},t);if(a.issues){let o={type:`object`,origin:`key`,input:n,key:r,value:i};for(let t of a.issues)t.path=[o],e.issues?.push(t);if(e.issues||=a.issues,t.abortEarly){e.typed=!1;break}}let o=this.value[`~run`]({value:i},t);if(o.issues){let a={type:`object`,origin:`value`,input:n,key:r,value:i};for(let t of o.issues)t.path?t.path.unshift(a):t.path=[a],e.issues?.push(t);if(e.issues||=o.issues,t.abortEarly){e.typed=!1;break}}(!a.typed||!o.typed)&&(e.typed=!1),a.typed&&(e.value[a.value]=o.value)}}else j(this,`type`,e,t);return e}})}/* @__NO_SIDE_EFFECTS__ */
24
+ function Ne(e,t){return M({kind:`schema`,type:`strict_object`,reference:Ne,expects:`Object`,async:!1,entries:e,message:t,"~run"(e,t){let n=e.value;if(n&&typeof n==`object`){e.typed=!0,e.value={};for(let r in this.entries){let i=this.entries[r];if(r in n||(i.type===`exact_optional`||i.type===`optional`||i.type===`nullish`)&&i.default!==void 0){let a=r in n?n[r]:/* @__PURE__ */ Ee(i),o=i[`~run`]({value:a},t);if(o.issues){let i={type:`object`,origin:`value`,input:n,key:r,value:a};for(let t of o.issues)t.path?t.path.unshift(i):t.path=[i],e.issues?.push(t);if(e.issues||=o.issues,t.abortEarly){e.typed=!1;break}}o.typed||(e.typed=!1),e.value[r]=o.value}else if(i.fallback!==void 0)e.value[r]=/* @__PURE__ */ Te(i);else if(i.type!==`exact_optional`&&i.type!==`optional`&&i.type!==`nullish`&&(j(this,`key`,e,t,{input:void 0,expected:`"${r}"`,path:[{type:`object`,origin:`key`,input:n,key:r,value:n[r]}]}),t.abortEarly))break}if(!e.issues||!t.abortEarly){for(let r in n)if(!Object.prototype.hasOwnProperty.call(this.entries,r)){j(this,`key`,e,t,{input:r,expected:`never`,path:[{type:`object`,origin:`key`,input:n,key:r,value:n[r]}]});break}}}else j(this,`type`,e,t);return e}})}/* @__NO_SIDE_EFFECTS__ */
25
+ function I(e){return M({kind:`schema`,type:`string`,reference:I,expects:`string`,async:!1,message:e,"~run"(e,t){return typeof e.value==`string`?e.typed=!0:j(this,`type`,e,t),e}})}/* @__NO_SIDE_EFFECTS__ */
26
+ function Pe(e){let t;if(e)for(let n of e)if(t)for(let e of n.issues)t.push(e);else t=n.issues;return t}/* @__NO_SIDE_EFFECTS__ */
27
+ function Fe(e,t){return M({kind:`schema`,type:`union`,reference:Fe,expects:/* @__PURE__ */ ve(e.map(e=>e.expects),`|`),async:!1,options:e,message:t,"~run"(e,t){let n,r,i;for(let a of this.options){let o=a[`~run`]({value:e.value},t);if(o.typed){if(o.issues)r?r.push(o):r=[o];else{n=o;break}}else i?i.push(o):i=[o]}if(n)return n;if(r){if(r.length===1)return r[0];j(this,`type`,e,t,{issues:/* @__PURE__ */ Pe(r)}),e.typed=!0}else if(i?.length===1)return i[0];else j(this,`type`,e,t,{issues:/* @__PURE__ */ Pe(i)});return e}})}/* @__NO_SIDE_EFFECTS__ */
28
+ function L(...e){return M({...e[0],pipe:e,"~run"(t,n){for(let r of e)if(r.kind!==`metadata`){if(t.issues&&(r.kind===`schema`||r.kind===`transformation`)){t.typed=!1;break}(!t.issues||!n.abortEarly&&!n.abortPipeEarly)&&(t=r[`~run`](t,n))}return t}})}/* @__NO_SIDE_EFFECTS__ */
29
+ function R(e,t,n){let r=e[`~run`]({value:t},/* @__PURE__ */ me(n));return{typed:r.typed,success:!r.issues,output:r.value,issues:r.issues}}const Ie=e=>{let t=e.length;for(;t>0&&e[t-1]===`/`;)--t;return e.slice(0,t)},Le=`0.6.1`,Re=/^flyle_ai_operator_ac_[0-9A-Za-z]{43}$/,ze=/^flyle_ai_operator_ut_[0-9A-Za-z]{43}$/,Be=/^flyle_ai_operator_rt_[0-9A-Za-z]{43}$/,Ve=/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/,He=/^[a-z0-9](-?[a-z0-9])*$/,Ue=6e5,We=536870912;var z=class extends Error{name=`ConfigError`},Ge=class extends Error{name=`GuideArticlesLoadError`};const Ke="ログインが必要です。作業ディレクトリで `npx @flyle/ai-operator-mcp@latest login` を実行してください";var qe=class extends Error{name=`InvalidGrantError`},B=class extends Error{name=`CliError`};const Je={allowInsecureHttp:`FLYLE_AI_OPERATOR_MCP_ALLOW_INSECURE_HTTP`},Ye=[`FLYLE_AI_CONTACT_CENTER_API_BASE_URL`,`FLYLE_AI_CONTACT_CENTER_TENANT_NAME`,`FLYLE_AI_CONTACT_CENTER_MCP_OUTPUT_DIR`,`FLYLE_AI_CONTACT_CENTER_MCP_FILE_ROOTS`,`FLYLE_AI_CONTACT_CENTER_MCP_STORAGE_HOSTS`,`FLYLE_AI_CONTACT_CENTER_MCP_ALLOW_INSECURE_HTTP`],Xe=[`.amazonaws.com`],Ze=/* @__PURE__ */ new Set([`localhost`,`127.0.0.1`,`[::1]`]),Qe=e=>Ze.has(e),$e=(e,t,n)=>{let r;try{r=new URL(e)}catch{throw new z(`${n} is not a valid URL`)}if(r.search!==``||r.hash!==``||r.username!==``||r.password!==``)throw new z(`${n} must not contain query, hash, or credentials`);let i=r.protocol===`http:`&&t&&Qe(r.hostname);if(r.protocol!==`https:`&&!i)throw new z(`${n} must use https (http is allowed only for localhost with ${Je.allowInsecureHttp}=1)`);let a=Ie(r.pathname);return new URL(`${r.origin}${a}`)},et=e=>e===`1`||e===`true`,tt=e=>e.length>=2&&e.length<=32&&He.test(e),nt=(e,t)=>{if(!tt(e))throw new z(`${t} is not a valid tenant name`);return e},rt=e=>{if(e.FLYLE_AI_CONTACT_CENTER_API_KEY!=null)throw new z("API キー方式は廃止されました。`npx @flyle/ai-operator-mcp@latest login` でログインしてください");let t=Ye.filter(t=>e[t]!=null);if(t.length!==0)throw new z(`${t.join(`, `)} は廃止しました。MCP の設定から削除してください。接続先(環境とテナント)は作業ディレクトリで \`npx @flyle/ai-operator-mcp@latest login --tenant <テナント名>\` を実行すると決まり、保存先と読込元は作業ディレクトリです。`)},it=e=>et(e[Je.allowInsecureHttp]),V=e=>e.host,at=(e,t,n)=>{let r=it(e);return{baseUrl:$e(n.apiBaseUrl,r,`作業ディレクトリの接続先`),tenantName:nt(n.tenantName,`作業ディレクトリのテナント`),outputDir:_.resolve(t,`.flyle-ai-operator-mcp/downloads`),fileRoots:[t],storageHostSuffixes:r?[...Xe,`s3.flyle.local`]:Xe,allowInsecureHttp:r}},ot=`flyle-ai-operator-mcp`,st=`credentials`,ct=()=>a(8).toString(`hex`),lt=/* @__PURE__ */ Ne({version:/* @__PURE__ */ Oe(1),apiBaseUrl:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ we()),tenantName:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ be(tt)),loginConnectionId:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ P(Ve)),accessToken:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ P(ze)),accessTokenExpiresAt:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ N()),refreshToken:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ P(Be)),refreshTokenExpiresAt:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ N())}),ut=({platform:e,env:t,homeDir:n})=>{let r=t.XDG_CONFIG_HOME;if(r!=null&&_.isAbsolute(r))return _.join(r,ot,st);let i=t.APPDATA;return e===`win32`&&i!=null&&_.isAbsolute(i)?_.join(i,ot,st):_.join(n,`.config`,ot,st)},dt=(e,t)=>_.join(e,`${t}.json`),ft=e=>e instanceof Error&&k(e,`code`)?e.code:null,pt=async e=>{let t;try{t=await d(e,`utf8`)}catch(e){if(ft(e)===`ENOENT`)return null;throw e}let n;try{n=JSON.parse(t)}catch{n=null}let r=/* @__PURE__ */ R(lt,n);if(!r.success)throw new x(`login_required`,`保存されたログイン情報(${e})を読めません。作業ディレクトリで \`npx @flyle/ai-operator-mcp@latest login\` を実行し直してください`);return r.output},mt=async e=>{await l(e,{recursive:!0,mode:448}),await s(e,448)},ht=async(e,t)=>{await mt(_.dirname(e));let n={version:1,...t},r=`${e}.${ct()}.tmp`;try{let t=await u(r,`wx`,384);try{await t.writeFile(`${JSON.stringify(n,null,2)}\n`)}finally{await t.close()}await p(r,e)}catch(e){throw await m(r,{force:!0}).catch(O),e}},gt=async e=>{await m(e,{force:!0})},_t=(e,t)=>({staleMs:6e4,acquireTimeoutMs:9e4,retryIntervalMs:100,now:e,sleep:t}),vt=async e=>{let t;try{t=await u(e,`r`)}catch(e){if(ft(e)===`ENOENT`)return null;throw e}try{let[e,n]=await Promise.all([t.readFile(`utf8`),t.stat()]);return{owner:e,mtimeMs:n.mtimeMs}}finally{await t.close()}},yt=async(e,t)=>{let n=`${e}.${ct()}.aside`;try{await p(e,n)}catch(e){if(ft(e)===`ENOENT`)return!1;throw e}return await d(n,`utf8`)===t?(await m(n,{force:!0}),!0):(await c(n,e).catch(e=>{if(ft(e)!==`EEXIST`)throw e}),await m(n,{force:!0}),!1)},bt=async(e,t)=>{let n=await vt(e);return n==null?!0:t.now()-n.mtimeMs<t.staleMs?!1:yt(e,n.owner)},xt=async(e,t)=>{let n=`${e}.${ct()}.tmp`,r=await u(n,`wx`,384);try{await r.writeFile(t)}finally{await r.close()}try{return await c(n,e),!0}catch(e){if(ft(e)===`EEXIST`)return!1;throw e}finally{await m(n,{force:!0})}},St=async(e,t,n)=>{await mt(_.dirname(e));let r=`${e}.lock`,i=ct(),a=t.now()+t.acquireTimeoutMs;for(;!await xt(r,i);)if(!await bt(r,t)){if(t.now()>=a)throw Error(`ログイン情報のロック(${r})を取得できませんでした。別の MCP プロセスが更新中です。しばらくしてから再実行してください`);await t.sleep(t.retryIntervalMs)}try{return await n()}finally{await yt(r,i).catch(O)}},H=e=>{if(e?.aborted)throw new C(`aborted`,`the API request was cancelled`)},Ct=(e,t,n)=>(H(t),t==null?n(e):new Promise((r,i)=>{let a=()=>{i(new C(`aborted`,`the API request was cancelled`))};t.addEventListener(`abort`,a,{once:!0}),n(e).then(()=>{t.removeEventListener(`abort`,a),r()},e=>{t.removeEventListener(`abort`,a),i(e instanceof Error?e:Error(String(e)))})})),wt=/\r\n|\n|\r/,Tt=()=>{let e=``,t=!1,n=``,r=[],i=null,a=()=>{if(r.length===0)return n=``,null;let e={event:n===``?`message`:n,data:r.join(`
30
+ `),id:i};return n=``,r=[],e},o=e=>{if(e===``)return a();if(e.startsWith(`:`))return null;let t=e.indexOf(`:`),o=t===-1?e:e.slice(0,t),s=t===-1?``:e.slice(t+1);return s.startsWith(` `)&&(s=s.slice(1)),o===`event`?n=s:o===`data`?r.push(s):o===`id`&&!s.includes(`\0`)&&(i=s),null};return{push:n=>{e+=n,t&&(t=!1,e.startsWith(`
31
+ `)&&(e=e.slice(1)));let r=[],i=e.search(wt);for(;i!==-1;){let n=e.slice(0,i);e[i]===`\r`&&i===e.length-1&&(t=!0);let a=e.startsWith(`\r
32
+ `,i)?2:1;e=e.slice(i+a);let s=o(n);s!=null&&r.push(s),i=e.search(wt)}return r},hasPendingIncomplete:()=>e!==``||r.length>0,flush:()=>(e=``,t=!1,n=``,r=[],[])}},Et=async(e,t)=>{if(t<=0)return`deadline`;let n=null,r=new Promise(e=>{n=setTimeout(e,t,`deadline`)});try{return await Promise.race([e.read(),r])}finally{n!=null&&clearTimeout(n)}},Dt=async(e,t)=>{let n=e.getReader(),r=new TextDecoder(`utf-8`),i=Tt(),a=[],o=0,s=async e=>(await n.cancel().catch(O),{events:a,truncated:!0,reason:e,discardedIncomplete:!1});for(;;){let e=await Et(n,t.deadlineAt-t.now());if(e===`deadline`)return await s(`deadline`);if(e.done){a.push(...i.push(r.decode()));let e=i.hasPendingIncomplete();return i.flush(),{events:a,truncated:!1,reason:`end`,discardedIncomplete:e}}if(o+=e.value.byteLength,o>t.maxBytes)return await s(`max_bytes`);if(a.push(...i.push(r.decode(e.value,{stream:!0}))),a.length>t.maxEvents)return a.length=t.maxEvents,await s(`max_events`)}},Ot=e=>{try{return JSON.parse(e)}catch{return e}},kt=`application/json`,At=`text/event-stream`,jt=`x-request-id`,Mt={headersTimeoutMs:6e4,maxJsonBytes:16777216,sseTotalMs:9e5,sseMaxEvents:1e4,sseMaxBytes:33554432,maxRetryAfterSeconds:30},Nt=(e,t)=>{if(e.origin!==t.origin)throw new C(`request_refused`,`refusing to send credentials outside the configured API origin`)},Pt=(e,t)=>{let n=`${Ie(e.pathname)}${t.path}`,r=new URL(n,e);if(r.pathname!==n)throw new C(`request_refused`,`refusing to send a request whose path was normalized`);for(let[e,n]of t.query)r.searchParams.append(e,n);return Nt(r,e),r},Ft=e=>{switch(e){case`json`:case`empty`:return kt;case`sse`:return At;case`binary`:return`*/*`;default:throw Error(`unknown response kind ${String(e)}`)}},It=async(e,t)=>{let n=Number(e.headers.get(`content-length`));if(Number.isFinite(n)&&n>t)throw await e.body?.cancel().catch(O),new C(`response_too_large`,`response exceeds ${t} bytes`,e.status);if(e.body==null)return/* @__PURE__ */ new Uint8Array;let r=e.body.getReader(),i=[],a=0;for(;;){let{done:n,value:o}=await r.read();if(n)break;if(a+=o.byteLength,a>t)throw await r.cancel().catch(O),new C(`response_too_large`,`response exceeds ${t} bytes`,e.status);i.push(o)}let o=new Uint8Array(a),s=0;for(let e of i)o.set(e,s),s+=e.byteLength;return o},Lt=e=>new TextDecoder(`utf-8`).decode(e),Rt=(e,t)=>(e.headers.get(`content-type`)??``).toLowerCase().startsWith(t),zt=e=>{if(e==null)return null;let t=Number(e);return Number.isInteger(t)&&t>=0?t:null},Bt=(e,t)=>{let n=e[t];return typeof n==`string`?n:null},Vt=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Ht=async(e,t)=>{let n=e.headers.get(jt),r=zt(e.headers.get(`retry-after`)),i;try{i=Lt(await It(e,t))}catch{i=``}if(Rt(e,kt))try{let t=JSON.parse(i),a=Vt(t)&&Vt(t.error)?t.error:null;if(a!=null)return new S({status:e.status,code:Bt(a,`code`),message:Bt(a,`message`)??e.statusText,detail:Bt(a,`detail`),requestId:Bt(a,`requestId`)??n,retryAfterSeconds:r})}catch{}return new S({status:e.status,code:null,message:i.slice(0,500)||e.statusText||`HTTP error`,detail:null,requestId:n,retryAfterSeconds:r})},Ut=e=>{if(e==null)return null;let t=/filename\*=UTF-8''([^;]+)/i.exec(e);if(t?.[1]!=null)try{return decodeURIComponent(t[1].trim())}catch{return null}return/filename="?([^";]+)"?/i.exec(e)?.[1]?.trim()??null},Wt=e=>e instanceof C?e:e instanceof Error&&e.name===`AbortError`?new C(`timeout`,`the API did not respond in time`):new C(`network`,e instanceof Error?e.message:`network failure`),Gt=(e,t=Mt)=>{let{config:n,auth:r,clientWorkspaceId:i,userAgent:a,fetch:o,now:s,sleep:c,logger:l}=e,u=async(e,r,{signal:c,canSend:l,metrics:u})=>{H(c);let d=Pt(n.baseUrl,e),f=new Headers({accept:Ft(e.responseKind)});a!=null&&f.set(`user-agent`,a),i!=null&&f.set(`x-flyle-client-workspace`,i),r!=null&&f.set(`authorization`,`Bearer ${r}`);let p;e.hasBody&&(p=JSON.stringify(e.body??{}),f.set(`content-type`,kt));let m=new AbortController,h=setTimeout(()=>m.abort(),t.headersTimeoutMs),g;try{if(l?.()===!1)throw new C(`aborted`,`the API request was cancelled before sending`);u!=null&&(u.attempts+=1,u.requestBytes+=p==null?0:new TextEncoder().encode(p).byteLength),g=await o(d,{method:e.method,headers:f,...p==null?{}:{body:p},redirect:`manual`,signal:c==null?m.signal:AbortSignal.any([m.signal,c])})}catch(e){throw clearTimeout(h),H(c),Wt(e)}let _=g.body;if(u!=null&&_!=null){let e=g,t=_.getReader(),n=new ReadableStream({async pull(e){try{let{done:n,value:r}=await t.read();if(n){t.releaseLock(),e.close();return}u.responseBytes+=r.byteLength,e.enqueue(r)}catch(n){t.releaseLock(),e.error(n)}},async cancel(e){try{await t.cancel(e)}finally{t.releaseLock()}}},{highWaterMark:0});g=new Response(n,{status:e.status,statusText:e.statusText,headers:e.headers})}if(g.type===`opaqueredirect`||g.status>=300&&g.status<400)throw clearTimeout(h),await g.body?.cancel().catch(O),new C(`redirect_not_followed`,`redirect responses are not followed`,g.status);if(!g.ok)try{throw await Ht(g,t.maxJsonBytes)}finally{clearTimeout(h)}let v=g.headers.get(jt);switch(e.responseKind){case`json`:try{if(!Rt(g,kt))throw await g.body?.cancel().catch(O),new C(`unexpected_content_type`,`expected an application/json response`,g.status);let e=Lt(await It(g,t.maxJsonBytes)),n;try{n=JSON.parse(e)}catch{throw new C(`invalid_json`,`the response body is not valid JSON`,g.status)}return{kind:`json`,status:g.status,requestId:v,body:n}}catch(e){throw H(c),Wt(e)}finally{clearTimeout(h)}case`empty`:return clearTimeout(h),await g.body?.cancel().catch(O),{kind:`empty`,status:g.status,requestId:v};case`sse`:{if(clearTimeout(h),!Rt(g,At))throw await g.body?.cancel().catch(O),new C(`unexpected_content_type`,`expected a text/event-stream response`,g.status);if(g.body==null)throw new C(`empty_body`,`the stream has no body`,g.status);let e=await Dt(g.body,{deadlineAt:s()+t.sseTotalMs,maxEvents:t.sseMaxEvents,maxBytes:t.sseMaxBytes,now:s});return H(c),{kind:`sse`,status:g.status,requestId:v,...e}}case`binary`:if(clearTimeout(h),g.body==null)throw new C(`empty_body`,`the download has no body`,g.status);return{kind:`binary`,status:g.status,requestId:v,contentType:g.headers.get(`content-type`),fileName:Ut(g.headers.get(`content-disposition`)),body:g.body};default:throw e.responseKind,Error(`unknown response kind ${String(e.responseKind)}`)}},d=async(e,n,r)=>{let{signal:i}=r,a=e.method===`GET`&&(e.responseKind===`json`||e.responseKind===`empty`);try{return await u(e,n,r)}catch(o){if(H(i),!a)throw o;if(o instanceof S&&o.info.status===429&&o.info.retryAfterSeconds!=null&&o.info.retryAfterSeconds<=t.maxRetryAfterSeconds)return l.warn(`rate limited; retrying once`,{path:e.path,retryAfterSeconds:o.info.retryAfterSeconds}),await Ct(o.info.retryAfterSeconds*1e3,i,c),await u(e,n,r);if(o instanceof C&&o.kind===`network`)return l.warn(`network failure; retrying once`,{path:e.path}),await u(e,n,r);throw o}};return{request:async(e,t,n,i)=>{H(t);let a={signal:t,canSend:n,metrics:i};if(r==null)return d(e,null,a);let o=await r.getAccessToken();try{return await d(e,o,a)}catch(n){if(!(n instanceof S)||n.info.status!==401)throw n;H(t);let i=await r.refreshAfterRejection(o);if(H(t),i===o)throw n;return l.warn(`access token rejected; retrying once with a refreshed token`,{path:e.path}),await d(e,i,a)}}}},Kt=`{tenantName}`,qt={...Mt,headersTimeoutMs:2e4},Jt=/* @__PURE__ */ F({authorizationUrlTemplate:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ xe(Kt))}),Yt=/* @__PURE__ */ F({accessToken:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ P(ze)),accessTokenExpiresAt:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ N()),refreshToken:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ P(Be)),refreshTokenExpiresAt:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ N()),tenantName:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ be(tt)),loginConnectionId:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ P(Ve))}),Xt=(e,t,n)=>{let r=/* @__PURE__ */ R(e,t);if(!r.success)throw new C(`invalid_json`,`the login connection response does not match the contract`,n);return r.output},Zt=async e=>{let t=await e.request({method:`GET`,path:`/v0/login-connections/metadata`,query:[],hasBody:!1,body:null,responseKind:`json`});if(t.kind!==`json`)throw new C(`unexpected_content_type`,`not JSON`);return Xt(Jt,t.body,t.status).authorizationUrlTemplate},Qt=async(e,t)=>{let n;try{n=await e.request({method:`POST`,path:`/v0/login-connections/token`,query:[],hasBody:!0,body:t,responseKind:`json`})}catch(e){throw e instanceof S&&e.info.code===`invalid_grant`?new qe(`the authorization code or refresh token is no longer valid`):e}if(n.kind!==`json`)throw new C(`unexpected_content_type`,`not JSON`);return Xt(Yt,n.body,n.status)},$t=(e,t,n)=>{if(e.apiBaseUrl!==t.href||e.tenantName!==n)throw new x(`credentials_mismatch`,`保存されたログイン(環境 ${V(new URL(e.apiBaseUrl))} / テナント ${e.tenantName})が、この作業ディレクトリの接続先(環境 ${V(t)} / テナント ${n})と一致しません。この作業ディレクトリで \`npx @flyle/ai-operator-mcp@latest login\` を実行し直してください`)},en=(e,t)=>({apiBaseUrl:t.href,tenantName:e.tenantName,loginConnectionId:e.loginConnectionId,accessToken:e.accessToken,accessTokenExpiresAt:e.accessTokenExpiresAt,refreshToken:e.refreshToken,refreshTokenExpiresAt:e.refreshTokenExpiresAt}),tn=e=>{let{credentialsFile:t,baseUrl:n,tenantName:r,tokenClient:i,now:a}=e,o=null,s=null,c=[],l=(...e)=>{c.push(...e),c.splice(0,Math.max(0,c.length-8))},u=async()=>{let e=await pt(t);if(e==null||Date.parse(e.refreshTokenExpiresAt)<=a())throw new x(`login_required`,Ke);return $t(e,n,r),e},d=e=>e-a()>6e4,f=async e=>{try{await ht(t,e)}catch{try{await ht(t,e)}catch{await gt(t)}}},p=a=>St(t,e.lock,async()=>{let e=await u();l(e.accessToken,e.refreshToken);let s=Date.parse(e.accessTokenExpiresAt);if(e.accessToken!==a&&d(s))return o={token:e.accessToken,expiresAt:s},e.accessToken;let c;try{c=await Qt(i,{grant_type:`refresh_token`,refresh_token:e.refreshToken})}catch(e){throw e instanceof qe?(await gt(t),new x(`login_required`,Ke)):e}if(l(c.accessToken,c.refreshToken),c.tenantName!==r)throw await gt(t),new x(`login_required`,`ログインの更新で、設定と違うテナント(${c.tenantName})の応答を受け取ったため、保存したログイン情報を破棄しました。${Ke}`);if(c.loginConnectionId!==e.loginConnectionId)throw await gt(t),new x(`login_required`,`ログインの更新で、保存したログインと違う接続の応答を受け取ったため、保存したログイン情報を破棄しました。${Ke}`);return o={token:c.accessToken,expiresAt:Date.parse(c.accessTokenExpiresAt)},await f(en(c,n)),c.accessToken}),m=e=>(s??=p(e).finally(()=>{s=null}),s);return{getAccessToken:()=>o!=null&&d(o.expiresAt)?Promise.resolve(o.token):m(o?.token??null),refreshAfterRejection:e=>o!=null&&o.token!==e?Promise.resolve(o.token):(o=null,m(e)),assertLoggedIn:async()=>{o??await u()},secrets:()=>c,whenIdle:async()=>{await Promise.allSettled(s==null?[]:[s])}}},nn=(e,t)=>e===`darwin`?[`open`,[t]]:e===`win32`?[`rundll32`,[`url.dll,FileProtocolHandler`,t]]:[`xdg-open`,[t]],rn=(e,t=process.platform)=>{let[n,r]=nn(t,e),i=v(n,r,{stdio:`ignore`,detached:!0,shell:!1});i.on(`error`,O),i.unref()},an=`flyle-ai-operator-mcp/${Le}`,on=(e,t=Mt)=>{let{workspaceId:n,...r}=e;return Gt({...r,clientWorkspaceId:n,userAgent:an},t)},sn=`.flyle-ai-operator-mcp`,cn=/* @__PURE__ */ F({tenantName:/* @__PURE__ */ I(),apiBaseUrl:/* @__PURE__ */ je(/* @__PURE__ */ ke(/* @__PURE__ */ I()),null)}),ln=e=>_.join(e,sn,`workspace.json`),un=e=>e instanceof Error&&k(e,`code`)&&e.code===`ENOENT`,dn=e=>e instanceof Error&&k(e,`code`)&&e.code===`EEXIST`,fn=async e=>{let t;try{t=await d(ln(e),`utf8`)}catch(e){if(un(e))return null;throw e}let n;try{n=JSON.parse(t)}catch{n=null}let r=/* @__PURE__ */ R(cn,n);if(!r.success)throw new D(`corrupted`,`${ln(e)} is not a valid workspace binding. Inspect it manually; the MCP server never overwrites it.`);return r.output},pn=async e=>(await fn(e))?.tenantName??null,mn=e=>` If you have never logged in successfully in this directory (e.g. you mistyped the tenant), delete ${_.join(e,sn)} and run login again (saved results in the default downloads folder are deleted too).`,hn=(e,t,n)=>new D(`tenant_mismatch`,`${e} is dedicated to tenant "${t}", not "${n}". Use a separate directory (and a separate Claude Code session) for each tenant.`+mn(e)),gn=(e,t,n)=>new D(`environment_mismatch`,`${e} is dedicated to the API ${new URL(t).host}, not ${new URL(n).host}. Use a separate directory for each environment.`+mn(e)),_n=e=>{let t=[],n=_.dirname(e);for(;n!==_.dirname(n);)t.push(n),n=_.dirname(n);return t.push(n),t},vn=async(e,t)=>{let n=await Promise.all(_n(e).map(async e=>({dir:e,tenant:await pn(e)})));for(let{dir:e,tenant:r}of n)if(r!=null&&r!==t)throw hn(e,r,t)},yn=(e,t)=>i(`sha256`).update(`${e.hostname}\0${e.username}\0${t}`).digest(`base64url`).slice(0,32),bn=(e,t)=>{let n={version:2,tenantName:e.tenantName,apiBaseUrl:e.apiBaseUrl,boundAt:t.toISOString()};return`${JSON.stringify(n,null,2)}\n`},xn=async(e,t,n)=>{let r=ln(e),i=`${r}.${a(8).toString(`hex`)}.tmp`;try{await g(i,bn(t,n),{flag:`wx`}),await p(i,r)}finally{await m(i,{force:!0})}},Sn=async(e,t,n,r)=>{await l(_.join(e,sn),{recursive:!0,mode:448});try{await g(ln(e),bn(t,n),{flag:`wx`});return}catch(e){if(!dn(e))throw e}let i=await fn(e);if(i?.tenantName!==t.tenantName)throw hn(e,i?.tenantName??`(unknown)`,t.tenantName);if(i.apiBaseUrl!==t.apiBaseUrl){if(i.apiBaseUrl==null&&r)await xn(e,t,n);else throw gn(e,i.apiBaseUrl??`(unknown)`,t.apiBaseUrl)}},Cn=async e=>{let t=await f(e.cwd);if(t===await f(e.homeDir).catch(()=>e.homeDir)||t===_.parse(t).root)throw new D(`shared_directory`,`${t} is shared by everything you do and cannot be dedicated to one tenant. Create a directory for this tenant (e.g. ~/flyle-cs/<tenant>) and start the session there.`);return t},wn=async(e,t)=>{let n=await Cn(e);return await vn(n,t.tenantName),await Sn(n,t,e.now(),!0),{...t,root:n,workspaceId:yn(e,n)}},Tn=async e=>{let t=await Cn(e),n=await fn(t);return n?.apiBaseUrl==null?null:(await vn(t,n.tenantName),{tenantName:n.tenantName,apiBaseUrl:n.apiBaseUrl,root:t,workspaceId:yn(e,t)})},En=async(e,t)=>{await Sn(e.root,e,t,!1)},Dn=(e,t,n)=>new D(`outside_workspace`,`${n} (${t}) must be inside the tenant workspace ${e}; a shared location could mix files between tenants.`),On=async(e,t)=>{if(!t.startsWith(`${e.root}${_.sep}`))throw Dn(e.root,t,`the file`);let n=[];for(let r=_.dirname(t);r!==e.root;r=_.dirname(r))n.push(r);let r=await Promise.all(n.map(async e=>({dir:e,tenant:await pn(e)})));for(let{dir:t,tenant:n}of r)if(n!=null&&n!==e.tenantName)throw hn(t,n,e.tenantName)},kn=(e,t,n)=>on({config:{baseUrl:t},auth:null,workspaceId:n,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger},qt),An=async e=>{let t=await Tn(e.workspaceEnv);if(t==null)return null;let n=dt(e.credentialsDir,t.workspaceId),r=await pt(n);return r==null?null:{workspace:t,file:n,stored:r,baseUrl:$e(r.apiBaseUrl,it(e.env),`${n} の apiBaseUrl`)}},jn=(e,t)=>{let n=tn({credentialsFile:t.file,baseUrl:t.baseUrl,tenantName:t.stored.tenantName,tokenClient:kn(e,t.baseUrl,t.workspace.workspaceId),now:e.now,lock:e.lock});return{auth:n,client:on({config:{baseUrl:t.baseUrl},auth:n,workspaceId:t.workspace.workspaceId,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger})}},Mn=(e,t)=>`/v0/tenants/${encodeURIComponent(e)}${t}`,Nn=e=>e instanceof B||e instanceof x||e instanceof z||e instanceof D?e.message:e instanceof S?`公開 API がエラーを返しました(${String(e.info.status)} ${e.info.code??`http_error`}): ${e.info.message}`:e instanceof C?`公開 API と通信できませんでした(${e.kind}): ${e.message}`:e instanceof Error?e.message:String(e),U=(e,t)=>{let n=e;for(let e of t)e.length!==0&&(n=n.split(e).join(`[redacted]`));return n},Pn=async(e,t)=>{let{client:n}=jn(e,t);try{await n.request({method:`DELETE`,path:Mn(t.stored.tenantName,`/current-login-connection`),query:[],hasBody:!1,body:null,responseKind:`empty`})}catch(e){if(!(e instanceof x&&e.kind===`login_required`||e instanceof S&&e.info.status===401))throw e}},Fn=async e=>{let t=await An(e);t==null?e.out(`この作業ディレクトリにはログイン情報がありません。`):(await Pn(e,t),await St(t.file,e.lock,()=>gt(t.file)),e.out(`ログアウトしました(環境 ${V(t.baseUrl)} / テナント ${t.stored.tenantName})。`))},In=`127.0.0.1`,Ln=`/callback`,Rn=e=>{try{let{values:t}=te({args:[...e],options:{tenant:{type:`string`},"api-base-url":{type:`string`}},strict:!0,allowPositionals:!1});return{tenant:t.tenant??null,apiBaseUrl:t[`api-base-url`]??null}}catch(e){throw new B(`${e instanceof Error?e.message:String(e)}\n使い方: login [--tenant <テナント名>] [--api-base-url <URL>]`)}},zn=(e,t,n)=>e==null?t?.apiBaseUrl==null?$e(`https://api.flygate.flyle.io`,n,`既定の接続先`):$e(t.apiBaseUrl,n,`作業ディレクトリの接続先`):$e(e,n,`--api-base-url`),Bn=(e,t)=>{if(e!=null)return nt(e,`--tenant`);if(t!=null)return t.tenantName;throw new B("テナントを決められません。`login --tenant <テナント名>` で指定してください(作業ディレクトリをそのテナント専用にします)。")},Vn=()=>a(32).toString(`base64url`),Hn=e=>i(`sha256`).update(e).digest(`base64url`),Un=(e,t)=>{let n=Buffer.from(e),r=Buffer.from(t);return n.length===r.length&&o(n,r)},Wn=(e,t,n)=>{let r;try{r=new URL(e.replaceAll(Kt,t))}catch{throw new B(`公開 API が返した同意画面の URL が不正です。`)}let i=r.protocol===`http:`&&n&&(Qe(r.hostname)||r.hostname.endsWith(`.localhost`));if(r.protocol!==`https:`&&!i)throw new B(`公開 API が返した同意画面の URL が https ではありません。`);return r},Gn=/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}\p{Co}]/gu,Kn=(e,t)=>{let n=``;for(let r of e){if(n.length+r.length>t)break;n+=r}return n},qn=(e,t)=>{let n=e=>e.replaceAll(Gn,``);return Kn(`${n(e)} / ${n(_.basename(t))}`,255)},Jn=/* @__PURE__ */ Fe([/* @__PURE__ */ F({error:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ P(/^[a-z_]{1,64}$/)),state:/* @__PURE__ */ I()}),/* @__PURE__ */ F({code:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ P(Re)),state:/* @__PURE__ */ I()})]),Yn={success:`ログインが完了しました。このタブは閉じてかまいません。`,denied:`ログインを中止しました。このタブは閉じてかまいません。`,failure:`ログインを完了できませんでした。このタブを閉じて、ターミナルの表示を確認してください。`,handled:`このログインは処理済みです。このタブは閉じてかまいません。`,unknown:`実行中のログインの応答として確認できませんでした。ログインを続ける場合は、ターミナルに表示された URL から同意画面を開き直してください。`,rejected:`この宛先への要求は受け付けていません。`},Xn=(e,t,n)=>{e.writeHead(t,{"content-type":`text/html; charset=utf-8`,"cache-control":`no-store`,"content-security-policy":`default-src 'none'`,"referrer-policy":`no-referrer`}),e.end(`<!doctype html><html lang="ja"><meta charset="utf-8"><title>Flyle AIオペレーター</title><p>${Yn[n]}</p></html>`)},Zn=e=>new Promise((t,n)=>{e.once(`error`,n),e.listen(0,In,()=>{let r=e.address();r==null||typeof r==`string`?n(new B(`ログイン用の待受ポートを開けませんでした。`)):t(r.port)})}),Qn=async(e,t,n)=>{let r=!1,i=0,a=null,o=Promise.withResolvers(),s=e=>{r=!0,o.reject(new B(e))},c=(e,t,r)=>{i+=1,Xn(e,400,t),n(r)},l=ee((t,n)=>{if(a==null||t.headers.host!==a){c(n,`rejected`,`ログイン用の待受に、想定外の宛先(Host ヘッダ)の要求が届いたため拒否しました。ログインは待ち続けています。`);return}let i=new URL(t.url??`/`,`http://${a}`);if(t.method!==`GET`||i.pathname!==Ln){n.writeHead(404).end();return}if(r){Xn(n,410,`handled`);return}let l=i.searchParams.get(`state`);if(l==null||!Un(l,e)){c(n,`unknown`,`このログインのものではない応答(state が一致しない、または無い)を受け取ったため無視しました。ブラウザで同意を続けてください。`);return}let u=/* @__PURE__ */ R(Jn,fe(i.searchParams));if(!u.success){Xn(n,400,`failure`),s(`同意画面からの応答の形式が正しくありません(認可コードがない、または形式が違います)。もう一度 login を実行してください。`);return}let d=u.output;if(k(d,`error`)){let e=d.error===`access_denied`;Xn(n,200,e?`denied`:`failure`),s(e?`ブラウザでログインが拒否されました。`:`同意画面がエラーを返しました(${d.error})。`);return}r=!0;let f=!1;o.resolve({code:d.code,finish:e=>{f||(f=!0,Xn(n,e===`success`?200:400,e))}})}),u=await Zn(l);a=`${In}:${String(u)}`;let d=setTimeout(()=>{if(r)return;let e=i===0?``:`(このログインのものではない要求を ${String(i)} 件受け取り、無視しました)`;s(`${String(Math.round(t/1e3/60))} 分以内にブラウザでの同意が完了しませんでした${e}。もう一度 login を実行してください。`)},t);return{port:u,received:o.promise,close:()=>new Promise(e=>{clearTimeout(d),l.closeAllConnections(),l.close(()=>e())})}},$n=`その接続は最長 30 日間有効なまま残る可能性があります。管理画面の「設定 → 外部ツール接続」から切断してください。`,er=async(e,t)=>{if(t!=null)try{await Pn(e,t)}catch(n){e.err(`以前のログイン(接続 ID ${t.stored.loginConnectionId})をサーバーで切断できませんでした(${Nn(n)})。${$n}`)}},tr=async e=>{try{return await An(e)}catch(t){if(!(t instanceof x&&t.kind===`login_required`)&&!(t instanceof z))throw t;return e.err(`以前のログイン情報を読めなかったため、新しいログインで上書きします(${Nn(t)})。以前の接続はサーバーで切断できていません。${$n}`),null}},nr=async(e,t,n,r)=>{let i=dt(e.credentialsDir,t.workspaceId);await St(i,e.lock,()=>ht(i,en(r,n)))},rr=e=>({getAccessToken:()=>Promise.resolve(e),refreshAfterRejection:()=>Promise.resolve(e),secrets:()=>[e]}),ir=async(e,t,n,r)=>{let i=on({config:{baseUrl:t},auth:rr(r.accessToken),workspaceId:n.workspaceId,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger});try{return await i.request({method:`DELETE`,path:Mn(r.tenantName,`/current-login-connection`),query:[],hasBody:!1,body:null,responseKind:`empty`}),!0}catch{return!1}},ar=async e=>{let t=Rn(e.argv),n=it(e.env),r=await fn(e.workspaceEnv.cwd),i=zn(t.apiBaseUrl,r,n),a=Bn(t.tenant,r),o=await wn(e.workspaceEnv,{tenantName:a,apiBaseUrl:i.href}),s=await tr(e),c=kn(e,i,o.workspaceId),l=Wn(await Zt(c),a,n),u=Vn(),d=Vn(),f=[u,d],p=await Qn(d,e.callbackTimeoutMs,e.err),m=null;try{let t=`http://${In}:${String(p.port)}${Ln}`;l.searchParams.set(`tenant_name`,a),l.searchParams.set(`code_challenge`,Hn(u)),l.searchParams.set(`code_challenge_method`,`S256`),l.searchParams.set(`redirect_uri`,t),l.searchParams.set(`state`,d),l.searchParams.set(`connection_name`,qn(e.workspaceEnv.hostname,o.root)),l.searchParams.set(`api_origin`,i.origin),e.err(`環境 ${V(i)} のテナント「${a}」にログインします。ブラウザで同意画面を開きます。\n開かない場合は、次の URL をブラウザで開いてください:\n${l.href}`),e.openBrowser(l.href),m=await p.received,f.push(m.code);let n;try{n=await Qt(c,{grant_type:`authorization_code`,code:m.code,code_verifier:u,redirect_uri:t})}catch(e){throw e instanceof qe?new B(`認可コードを交換できませんでした。もう一度 login を実行してください。`):e}if(f.push(n.accessToken,n.refreshToken),n.tenantName!==a){let t=await ir(e,i,o,n);throw new B(`ブラウザで同意したテナント(${n.tenantName})が、ログインしようとしたテナント(${a})と違います。ログイン情報は保存していません。`+(t?`そのテナントに作られた接続は切断しました。`:`テナント ${n.tenantName} の管理画面の「設定 → 外部ツール接続」から、作られた接続を切断してください。`))}await En(o,new Date(e.now())),await er(e,s),await nr(e,o,i,n),m.finish(`success`),e.out(`ログインしました(環境 ${V(i)} / テナント ${a} / 作業ディレクトリ ${o.root})。`)}catch(e){throw m?.finish(`failure`),new B(U(Nn(e),f))}finally{await p.close()}},or=/* @__PURE__ */ F({currentUser:/* @__PURE__ */ F({name:/* @__PURE__ */ ke(/* @__PURE__ */ I()),email:/* @__PURE__ */ ke(/* @__PURE__ */ I()),roles:/* @__PURE__ */ De(/* @__PURE__ */ F({roleName:/* @__PURE__ */ I()})),currentLoginConnection:/* @__PURE__ */ F({name:/* @__PURE__ */ I(),expiresAt:/* @__PURE__ */ L(/* @__PURE__ */ I(),/* @__PURE__ */ N())})})}),sr="ログインしていません。作業ディレクトリで `npx @flyle/ai-operator-mcp@latest login` を実行してください",cr=async e=>{let t=await An(e);if(t==null)throw new B(sr);e.out(`環境: ${V(t.baseUrl)}`),e.out(`テナント: ${t.stored.tenantName}`);let{client:n}=jn(e,t),r;try{r=await n.request({method:`GET`,path:Mn(t.stored.tenantName,`/current-user`),query:[],hasBody:!1,body:null,responseKind:`json`})}catch(e){throw e instanceof x&&e.kind===`login_required`?new B(`ログインの有効期限が切れています。${sr}`):e}let i=/* @__PURE__ */ R(or,r.kind===`json`?r.body:null);if(!i.success)throw new C(`invalid_json`,`the current user response does not match the contract`);let a=i.output.currentUser,o=a.email==null?``:` <${a.email}>`;e.out(`ユーザー: ${a.name??`(名前未設定)`}${o}`),e.out(`ロール: ${a.roles.map(e=>e.roleName).join(`, `)||`(なし)`}`),e.out(`接続名: ${a.currentLoginConnection.name}`),e.out(`ログインの有効期限: ${a.currentLoginConnection.expiresAt}(使うたびに延長。ログインから最長 90 日)`)},lr=async e=>{let t=await u(e,ne.O_RDONLY|ne.O_NONBLOCK|ne.O_NOFOLLOW);try{let e=await t.stat();if(!e.isFile())throw new T(`not_a_file`,`only regular files can be read`);return{handle:t,size:e.size}}catch(e){throw await t.close(),e}},ur=async(e,t)=>{let{handle:n,size:r}=await lr(e);try{if(r>t)throw new T(`too_large`,`the file exceeds ${String(t)} bytes`);let e=[],i=0;for(;;){let r=Buffer.allocUnsafe(Math.min(1048576,t-i+1)),{bytesRead:a}=await n.read(r,0,r.length,null);if(a===0)break;if(i+=a,i>t)throw new T(`too_large`,`the file exceeds ${String(t)} bytes`);e.push(r.subarray(0,a))}return Buffer.concat(e,i)}finally{await n.close()}},dr=(e,t)=>e===t||e.startsWith(`${t}${_.sep}`),fr=async(e,t,n,r)=>{let i=_.resolve(n,e),a;try{a=await f(i)}catch{throw new T(`not_found`,`file not found: ${e}`)}if(!(await Promise.all(t.map(e=>f(e).catch(()=>e)))).some(e=>dr(a,e)))throw new T(`outside_roots`,`the path is outside the configured file roots`);return await On(r,a),a},pr=/* @__PURE__ */ new Map([[`.md`,`text/markdown`],[`.markdown`,`text/markdown`],[`.txt`,`text/plain`],[`.csv`,`text/csv`],[`.json`,`application/json`],[`.html`,`text/html`],[`.htm`,`text/html`],[`.pdf`,`application/pdf`],[`.docx`,`application/vnd.openxmlformats-officedocument.wordprocessingml.document`],[`.xlsx`,`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`],[`.pptx`,`application/vnd.openxmlformats-officedocument.presentationml.presentation`],[`.png`,`image/png`],[`.jpg`,`image/jpeg`],[`.jpeg`,`image/jpeg`],[`.zip`,`application/zip`]]),mr=e=>pr.get(_.extname(e).toLowerCase())??`application/octet-stream`,hr=e=>new Promise((t,n)=>{let r=i(`sha256`);e.on(`data`,e=>r.update(e)).on(`error`,n).on(`end`,()=>t(r.digest()))}),gr=async(e,t,n,r)=>{let i=await fr(e,t,n,r),{handle:a,size:o}=await lr(i),s;try{s=await hr(a.createReadStream())}finally{await a.close()}let c=_.basename(i);return{path:i,fileName:c,sizeBytes:o,sha256Hex:s.toString(`hex`),sha256Base64:s.toString(`base64`),mimeType:mr(c)}},_r=(e,t=9e5,n=1e3)=>{let r=/* @__PURE__ */ new Map,i=()=>{let t=e();for(let[e,n]of r)n.expiresAt<=t&&r.delete(e)};return{get size(){return r.size},register:(a,o,s)=>{for(i();r.size>=n;){let e=r.keys().next();if(e.done)break;r.delete(e.value)}r.delete(a),r.set(a,{kind:o,headers:s,expiresAt:e()+t})},take:(t,n)=>{let i=r.get(t);if(i?.kind!==n)throw new w(`unknown_url`,`the URL was not returned by a recent API call for this kind of transfer`);if(r.delete(t),i.expiresAt<=e())throw new w(`expired_url`,`the signed URL has expired; call the API again to get a new one`);return i}}},vr=(e,t)=>{let n;try{n=new URL(e)}catch{throw new w(`not_allowed_host`,`the transfer URL is not a valid URL`)}let r=t.allowInsecureHttp&&Qe(n.hostname);if(n.protocol!==`https:`&&!(n.protocol===`http:`&&r))throw new w(`insecure_url`,`transfer URLs must use https`);if(n.username!==``||n.password!==``)throw new w(`not_allowed_host`,`transfer URLs must not contain credentials`);let i=n.hostname.toLowerCase();if(!(r||t.storageHostSuffixes.some(e=>e.startsWith(`.`)?i.endsWith(e):i===e)))throw new w(`not_allowed_host`,`the host ${i} is not an allowed storage host`);return n},yr=4096,br=async e=>{if(e.body==null)return``;let t=e.body.getReader(),n=[],r=0;try{for(;r<yr;){let{done:e,value:i}=await t.read();if(e)break;n.push(i),r+=i.byteLength}}catch{}finally{await t.cancel().catch(O)}return new TextDecoder(`utf-8`).decode(Buffer.concat(n)).slice(0,yr)},xr=e=>e instanceof w?e:e instanceof Error&&(e.name===`AbortError`||e.name===`TimeoutError`)?new w(`timeout`,`the storage did not respond in time`):new w(`network`,e instanceof Error?e.message:`network failure`),Sr=async e=>{if(ue(e.headers).some(e=>e.toLowerCase()===`authorization`))throw new w(`invalid_headers`,`transfer headers must not include authorization`);let t;try{t=await ur(e.filePath,e.maxBytes)}catch(e){throw e instanceof T&&(e.kind===`not_a_file`||e.kind===`too_large`)?new w(e.kind,e.kind===`not_a_file`?`only regular files can be uploaded`:e.message):e}let n;try{n=await e.fetch(e.url,{method:`PUT`,headers:e.headers,body:t,redirect:`manual`,signal:AbortSignal.timeout(e.timeoutMs)})}catch(e){throw xr(e)}if(n.status>=300&&n.status<400)throw await n.body?.cancel().catch(O),new w(`redirect_not_followed`,`redirect responses are not followed`,n.status);if(!n.ok)throw new w(`http_error`,`upload failed: ${(await br(n)).slice(0,300)}`,n.status);return await n.body?.cancel().catch(O),{status:n.status,etag:n.headers.get(`etag`),bytes:t.byteLength}},Cr=/[^A-Za-z0-9._-]/g,wr=(e,t)=>{let n=_.basename(e??``).replace(Cr,`_`).replace(/^_+/,``).slice(0,120);return n===``||/^\.+$/.test(n)?t:n},Tr=e=>`${(/* @__PURE__ */ new Date()).toISOString().replaceAll(/[:.]/g,`-`)}-${a(3).toString(`hex`)}-${e}`,Er=async(e,t)=>{if(t<=0)return`timeout`;let n=null,r=new Promise(e=>{n=setTimeout(e,t,`timeout`)});try{return await Promise.race([e.read(),r])}finally{n!=null&&clearTimeout(n)}},Dr=async(e,t)=>{await l(t.outputDir,{recursive:!0,mode:448});let n=_.join(t.outputDir,Tr(t.fileName)),r=await u(n,`wx`,384),a=i(`sha256`),o=e.getReader(),s=Date.now()+t.timeoutMs,c=0;try{for(;;){let e=await Er(o,s-Date.now());if(e===`timeout`)throw await o.cancel().catch(O),new w(`timeout`,`the download did not finish within ${t.timeoutMs} ms`);let{done:n,value:i}=e;if(n)break;if(c+=i.byteLength,c>t.maxBytes)throw await o.cancel().catch(O),new w(`too_large`,`the download exceeds ${t.maxBytes} bytes`);a.update(i),await r.write(i)}}catch(e){throw await r.close(),await h(n).catch(O),xr(e)}return await r.close(),{path:n,bytes:c,sha256Hex:a.digest(`hex`)}},Or=async e=>{let t;try{t=await e.fetch(e.url,{method:`GET`,redirect:`manual`,signal:AbortSignal.timeout(e.timeoutMs)})}catch(e){throw xr(e)}if(t.status>=300&&t.status<400)throw await t.body?.cancel().catch(O),new w(`redirect_not_followed`,`redirect responses are not followed`,t.status);if(!t.ok)throw new w(`http_error`,`download failed: ${(await br(t)).slice(0,300)}`,t.status);if(t.body==null)throw new w(`network`,`the download has no body`,t.status);return{...await Dr(t.body,{outputDir:e.outputDir,fileName:e.fileName,maxBytes:e.maxBytes,timeoutMs:e.timeoutMs}),status:t.status,contentType:t.headers.get(`content-type`)}},kr=(e,t,n,r)=>{let i={level:e,message:t,...n,time:(/* @__PURE__ */ new Date()).toISOString()};return U(JSON.stringify(i),r)},Ar=(e,t=e=>console.error(e))=>({info:(n,r)=>t(kr(`info`,n,r,e())),warn:(n,r)=>t(kr(`warn`,n,r,e())),error:(n,r)=>t(kr(`error`,n,r,e()))}),jr=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],Mr=[`json`,`empty`,`sse`,`binary`],Nr=[`upload`,`download`],Pr=[`read`,`draft`],Fr=[`wav-pcm16`,`base64`],Ir=[`pcm16le`,`base64`],W=e=>{throw new oe(e)},G=e=>e===null,K=e=>Array.isArray(e)&&e.every(e=>typeof e==`string`),Lr=e=>{if(!Array.isArray(e)||e.length===0)return!1;let t=0;for(let n of e){if(typeof n!=`number`||!Number.isInteger(n)||n<200||n>=300||n<=t)return!1;t=n}return!0},Rr=e=>typeof e==`string`&&jr.some(t=>t===e),zr=e=>typeof e==`string`&&Mr.some(t=>t===e),Br=e=>typeof e==`string`&&Nr.some(t=>t===e),Vr=e=>typeof e==`string`&&Pr.some(t=>t===e),Hr=(e,t)=>{if(G(e))return null;if(!A(e))return W(`${t}.transfer must be an object or null`);let{kind:n,urlPointer:r,headersPointer:i,namePointer:a}=e;return Br(n)?typeof r==`string`?!G(i)&&typeof i!=`string`?W(`${t}.transfer.headersPointer is invalid`):!G(a)&&typeof a!=`string`?W(`${t}.transfer.namePointer is invalid`):{kind:n,urlPointer:r,headersPointer:i,namePointer:a}:W(`${t}.transfer.urlPointer is invalid`):W(`${t}.transfer.kind is invalid`)},Ur=e=>typeof e==`string`&&Fr.some(t=>t===e),Wr=e=>typeof e==`string`&&Ir.some(t=>t===e),Gr=e=>typeof e==`number`&&Number.isInteger(e)&&e>0,Kr=(e,t)=>{if(G(e))return null;if(!A(e))return W(`${t} must be an object or null`);let{sampleRateHz:n,channels:r}=e;return Gr(n)?Gr(r)?{sampleRateHz:n,channels:r}:W(`${t}.channels is invalid`):W(`${t}.sampleRateHz is invalid`)},qr=(e,t)=>{if(!A(e))return W(`${t} must be an object`);let{pointer:n,format:r,maxBytes:i,pcm:a}=e;if(typeof n!=`string`||!n.startsWith(`/`))return W(`${t}.pointer is invalid`);if(!Ur(r))return W(`${t}.format is invalid`);if(!Gr(i))return W(`${t}.maxBytes is invalid`);let o=Kr(a,`${t}.pcm`);return r===`wav-pcm16`==(o!=null)?{pointer:n,format:r,maxBytes:i,pcm:o}:W(`${t}.pcm does not match the format`)},Jr=(e,t)=>{if(!A(e))return W(`${t} must be an object`);let{event:n,pointer:r,format:i,pcm:a,mediaType:o}=e;if(!G(n)&&typeof n!=`string`)return W(`${t}.event is invalid`);if(typeof r!=`string`||!r.startsWith(`/`))return W(`${t}.pointer is invalid`);if(!Wr(i))return W(`${t}.format is invalid`);if(!G(o)&&typeof o!=`string`)return W(`${t}.mediaType is invalid`);let s=Kr(a,`${t}.pcm`);return i===`pcm16le`==(s!=null)?i===`base64`==(o!=null)?{event:n,pointer:r,format:i,pcm:s,mediaType:o}:W(`${t}.mediaType does not match the format`):W(`${t}.pcm does not match the format`)},Yr=(e,t)=>{if(G(e))return null;if(!A(e))return W(`${t}.inlineFiles must be an object or null`);let{input:n,output:r}=e;return!Array.isArray(n)||!Array.isArray(r)?W(`${t}.inlineFiles is invalid`):n.length===0&&r.length===0?W(`${t}.inlineFiles must declare input or output`):{input:n.map((e,n)=>qr(e,`${t}.inlineFiles.input[${String(n)}]`)),output:r.map((e,n)=>Jr(e,`${t}.inlineFiles.output[${String(n)}]`))}},Xr=(e,t)=>{if(G(e))return null;if(!A(e))return W(`${t}.sseOutcome must be an object or null`);let{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}=e;return K(n)?typeof r==`string`?G(i)&&G(a)?K(o)?{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}:W(`${t}.sseOutcome.failureEvents is invalid`):typeof i!=`string`||!i.startsWith(`/`)?W(`${t}.sseOutcome.successPointer is invalid`):typeof a!=`string`&&typeof a!=`number`&&typeof a!=`boolean`?W(`${t}.sseOutcome.successValue is invalid`):K(o)?{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}:W(`${t}.sseOutcome.failureEvents is invalid`):W(`${t}.sseOutcome.terminalEvent is invalid`):W(`${t}.sseOutcome.requiredEvents is invalid`)},Zr=(e,t)=>{let n=`operations[${t}]`;if(!A(e))return W(`${n} must be an object`);let{operationId:r,method:i,pathTemplate:a,summary:o,label:s,description:c,permission:l,effect:u,responseContainsSecret:d,responseKind:f,successStatuses:p,pathParams:m,queryParams:h,bodyFields:g,wholeBodyField:_,inputSchema:v,transfer:ee,inlineFiles:te,sseOutcome:ne}=e;return typeof r!=`string`||r===``?W(`${n}.operationId is invalid`):Rr(i)?typeof a!=`string`||!a.startsWith(`/`)?W(`${n}.pathTemplate is invalid`):typeof o==`string`?!G(s)&&typeof s!=`string`?W(`${n}.label is invalid`):!G(c)&&typeof c!=`string`?W(`${n}.description is invalid`):!G(u)&&!Vr(u)?W(`${n}.effect is invalid`):typeof d==`boolean`?zr(f)?Lr(p)?K(m)?K(h)?!G(g)&&!K(g)?W(`${n}.bodyFields is invalid`):!G(_)&&typeof _!=`string`?W(`${n}.wholeBodyField is invalid`):g!=null&&_!=null?W(`${n} declares both bodyFields and wholeBodyField`):A(v)?{operationId:r,method:i,pathTemplate:a,summary:o,label:s,description:c,permission:l??null,effect:u,responseContainsSecret:d,responseKind:f,successStatuses:p,pathParams:m,queryParams:h,bodyFields:g,wholeBodyField:_,inputSchema:v,transfer:Hr(ee,n),inlineFiles:Yr(te,n),sseOutcome:Xr(ne,n)}:W(`${n}.inputSchema is invalid`):W(`${n}.queryParams is invalid`):W(`${n}.pathParams is invalid`):W(`${n}.successStatuses is invalid`):W(`${n}.responseKind is invalid`):W(`${n}.responseContainsSecret is invalid`):W(`${n}.summary is invalid`):W(`${n}.method is invalid`)},Qr=e=>{if(!A(e))return W(`manifest must be an object`);let t=e.source;if(!A(t)||typeof t.title!=`string`||typeof t.version!=`string`)return W(`manifest.source is invalid`);let n=e.operations;if(!Array.isArray(n))return W(`manifest.operations must be an array`);let r=n.map((e,t)=>Zr(e,t));return new Set(r.map(e=>e.operationId)).size===r.length?{source:{title:t.title,version:t.version},operations:r}:W(`manifest.operations has duplicate operationId`)},$r=(e,t)=>{let n;try{n=re(e)}catch{throw t(`${e.pathname} cannot be read`)}try{return JSON.parse((e.pathname.endsWith(`.br`)?ie(n):n).toString(`utf8`))}catch{throw t(`${e.pathname} is not valid JSON or brotli`)}},ei=new URL(`./manifest.json.br`,import.meta.url),ti=(e=ei)=>Qr($r(e,e=>new oe(`manifest at ${e}`))),ni=e=>`${e.product}/${e.slug}`,ri=e=>({articles:e,articleByReference:new Map(e.map(e=>[ni(e),e])),searchEntries:e.map(e=>({article:e,normalizedTitle:e.title.toLowerCase(),normalizedDescription:e.description.toLowerCase(),normalizedGroup:e.group.toLowerCase(),normalizedBody:e.body.toLowerCase()}))}),ii=(e,t)=>e.articleByReference.get(t)??null,ai=(e,t)=>{for(let n of t){let t=e.normalizedBody.indexOf(n);if(t===-1)continue;let{body:r}=e.article,i=Math.max(0,t-80),a=Math.min(r.length,t+n.length+80),o=i>0?`…`:``,s=a<r.length?`…`:``;return`${o}${r.slice(i,a).replaceAll(/\s+/g,` `).trim()}${s}`}return e.article.description},oi=(e,t,n)=>{let r=[...new Set(t.toLowerCase().split(/\s+/).filter(e=>e.length>0))];if(r.length===0)return[];let i=[];for(let t of e.searchEntries){let e=0,n=0;for(let i of r){let r=0;t.normalizedTitle.includes(i)&&(r+=10),t.normalizedDescription.includes(i)&&(r+=5),t.normalizedGroup.includes(i)&&(r+=3),t.normalizedBody.includes(i)&&(r+=1),r>0&&(e+=1,n+=r)}e>0&&i.push({entry:t,matchedKeywordCount:e,score:n})}return i.sort((e,t)=>t.matchedKeywordCount===e.matchedKeywordCount?t.score-e.score:t.matchedKeywordCount-e.matchedKeywordCount),i.slice(0,n).map(({entry:e})=>({article:ni(e.article),title:e.article.title,group:e.article.group,description:e.article.description,snippet:ai(e,r)}))},si=(e,t)=>{let n=e.replaceAll(/!\[[^\]]*\]\([^)]*\)/g,``),r=[];for(let e of n.split(/\r?\n/))(e.trim()!==``||r.at(-1)?.trim()!==``)&&r.push(e);return r.join(`
33
+ `).replaceAll(/\]\(([^)\s]+)\)/g,(e,n)=>{try{return`](${new URL(n,t).toString()})`}catch{return e}})},ci=(e,t)=>{let n=[],r=null,i=null;for(let a of e)a.product!==r&&(r=a.product,i=null,n.push(`## ${t[a.product]??a.product}`,``)),a.group!==i&&(i=a.group,n.push(`### ${a.group}`)),n.push(`- ${ni(a)}: ${a.title} — ${a.description}`);return n.join(`
34
+ `)},q=`get_product_guide`,J=`search_product_guide`,Y=`read_product_guide_article`,li=`ご利用ガイドの記事をキーワードで探します。空白区切りの複数キーワードは、より多く一致した記事を先に返します。記事の全文は ${Y} で読みます。`,ui=e=>`ご利用ガイドの記事を全文読みます。記事は ${e?`${q} の一覧や ${J} の結果`:`${J} の結果`}にある "flygate/knowledge" 形式で指定します。管理画面での操作手順・制約・用語の正はこの記事です。`,di={type:`object`,properties:{},additionalProperties:!1},fi={type:`object`,properties:{query:{type:`string`,minLength:1,description:`検索キーワード(例: "検証ケース 改善提案")。`},maxResults:{type:`integer`,minimum:1,maximum:20,description:`返す記事の最大数(既定 10)。`}},required:[`query`],additionalProperties:!1},pi={type:`object`,properties:{article:{type:`string`,minLength:1,description:`記事(例: "flygate/knowledge")。`}},required:[`article`],additionalProperties:!1},mi=`# Flyle AIオペレーターの全体像
35
+
36
+ Flyle AIオペレーターは、Web サイトのチャットや電話に寄せられるお問い合わせへ 24 時間自動で応答する AI の担当者(エージェント)を作り、運用する製品です。利用者はコンタクトセンターの導入・運用担当者で、エンジニアではありません。
37
+
38
+ ## 基本となる概念
39
+
40
+ - **エージェント**: 応答の単位です。業務フロー・ナレッジ・コネクター・フォーム・デザインをまとめて設定します。過去の応対履歴(CSV)と参考資料から、業務フローやナレッジを含む土台を自動生成できます(create-agent)。
41
+ - **業務フロー**: エージェントが応答を組み立てる流れです。問い合わせを最初に受けて用件ごとの業務フローへ振り分ける「メインフロー」と、用件ごとに応対する「サブフロー」で構成され、メインフローは「振り分けルール」で振り分け先のサブフローを決めます。各業務フローは「業務フロー指示」(何を根拠にどう応答するか)と「回答レビュー」(レビュー観点)を持ちます。ペルソナ・コミュニケーションスタイル・制限事項(応答してはいけない話題)は、すべての業務フローに共通する「共通設定」で決めます(common-settings、API では update_agent)。API では flows(メインフローは kind MAIN、サブフローは kind SUB、振り分けルールは routing-rules)として扱いますが、利用者には「ノード」「ルーティング」「ワーカー」ではなく画面の名前(業務フロー・メインフロー・サブフロー・振り分けルール)で伝えてください(business-flow)。
42
+ - **ナレッジ**: 回答の根拠となる資料や FAQ です。ナレッジベースにドキュメント(ファイル・Web ページ)を取り込み、検索用のデータに取り込んで(import)から使われます。「どう答えるか」は業務フロー、「何を根拠に答えるか」はナレッジで決まります(knowledge)。
43
+ - **類義語・音声辞書**: 表記ゆれを検索に反映する類義語と、電話で製品名や専門用語を正しく聞き取り・読み上げるための音声辞書です(synonym-dictionary / voice-dictionary)。
44
+ - **コネクター**: CRM や在庫システムなど外部システムとのやり取りを TypeScript の関数として登録したもので、エージェントが会話の中で呼び出します(connectors)。
45
+ - **フォーム**: 業務フローの開始時などに、訪問者に項目を入力してもらう仕組みです(form-options / business-flow)。
46
+ - **プレビューと検証**: 公開前に、プレビューチャット・音声で試し、想定する質問と期待する回答を「検証ケース」として登録してまとめて実行し、品質を確かめます。不合格のケースからは改善提案を作れます。エージェントの設定の変更はプレビューと検証に直ちに反映されますが、ナレッジベースやドキュメントを変えたときはプレビューの準備(preview build)が要ります。API の verification は画面の「検証」で、利用者には「評価」ではなく「検証を実行」「検証結果」「検証ケース」と伝えてください(preview-chat / verification-cases / verification-runs)。
47
+ - **公開と履歴**: 編集内容は下書きで、公開すると訪問者への応対に使われます。公開や下書き保存のたびにバージョンが残り、復元できます(history / embed-publish)。
48
+ - **チャネル**: 応対の経路です。管理画面の「チャネル」には、チャット(デザイン・埋め込みサイト)、音声、電話番号・SIP接続でつなぐ電話があります(design / audio-settings / embed-publish / phone-channel)。
49
+ - **オペレーターへの引き継ぎ**: AI が答えきれない会話をチームの担当者へ引き継ぐ設定と、担当者が会話に対応する「オペレーター対応」の画面です(operator-handoff / operator / team-management)。
50
+ - **結果の確認と改善**: ダッシュボードと会話履歴で状況を確かめ、ナレッジや業務フローを直し、検証してから再公開するサイクルを回します(dashboard / improve)。
51
+
52
+ ## この MCP サーバーでできること・できないこと
53
+
54
+ ツールで行えるのは、エージェント・業務フロー・ナレッジ・コネクター・フォーム・辞書の参照と下書きの編集、プレビューの準備と対話、検証ケースの管理と検証の実行、改善提案の確認と反映・棄却、公開状態・履歴の参照、チャネル設定の参照と一部の変更、会話履歴とダッシュボード(問い合わせ件数の推移)の参照です。すべてログインした利用者本人の権限で動きます。
55
+
56
+ 次の操作はツールにありません。ツールを組み合わせて代わりにやろうとせず、該当するご利用ガイドの記事を示して管理画面で操作するよう利用者に案内してください。
57
+
58
+ - 公開の実行・昇格・取り消し
59
+ - 埋め込みサイト(追加・再発行・失効・許可オリジンの変更)、コネクターの秘密情報の変更
60
+ - 電話番号・通話録音の設定・SIP接続の変更、エージェントの削除
61
+ - ロール・メンバー・チームの管理、テナント設定
62
+
63
+ ## 作業の進め方
64
+
65
+ 1. 依頼の内容に関係するご利用ガイドの記事を、下の一覧や ${J} で探し、${Y} で読みます。画面での概念・制約・用語を理解してから操作を選んでください。各ツールの説明にも、関係する記事を載せています。
66
+ 2. 対象のエージェントと現在の設定・検証ケースを一覧・取得系のツールで確かめます。
67
+ 3. 設定やデータを変える前に、何をどう変えるか(対象・変更前 → 変更後・影響)を利用者に示して同意を得ます。
68
+ 4. 変更後はプレビュー・検証で結果を確かめ、ケースごとの結果を利用者に報告します。
69
+
70
+ ## よくある依頼と使う記事
71
+
72
+ - 改善要望を反映したい: improve / verification-cases / verification-runs → 検証ケースの追加 → 変更前の検証 → 業務フローやナレッジの修正 → 全ケースの再検証
73
+ - ナレッジを足したい・直したい: knowledge → 取り込み → 検索用データへの取り込み完了 → プレビューの準備 → 検証
74
+ - 応答の流れを変えたい: business-flow → list_flows / get_flow → update_flow
75
+ - 口調や応答してはいけない話題を変えたい: common-settings → update_agent
76
+ - 外部システムと連携したい: connectors
77
+ - オペレーターへの引き継ぎを設定したい: operator-handoff / team-management
78
+ - 応対の状況を知りたい: dashboard / improve → get_agent_conversation_summary / list_conversations`,hi={agents:[`create-agent`,`business-flow`],"agent-generation-jobs":[`create-agent`],"agent-generation-upload-urls":[`create-agent`],"agents/generation-jobs":[`create-agent`],"agents/configuration":[`business-flow`],"agents/flows":[`business-flow`],"agents/subflow-common-rules":[`business-flow`],"agents/connectors":[`connectors`],"agents/forms":[`form-options`,`business-flow`],"agents/knowledge-bases":[`knowledge`],"agents/knowledge-import-job-summary":[`knowledge`],"agents/synonym-groups":[`synonym-dictionary`],"agents/voice-dictionary-terms":[`voice-dictionary`],"agents/preview-builds":[`preview-chat`,`knowledge`],"agents/preview-chat-messages":[`preview-chat`],"agents/preview-conversations":[`preview-chat`],"agents/preview-voice-messages":[`preview-chat`,`audio-settings`],"agents/preview-form-submissions":[`preview-chat`,`form-options`],"agents/verification-cases":[`preview-chat`],"agents/verification-case-imports":[`preview-chat`],"agents/verification-images":[`preview-chat`],"agents/verification-runs":[`preview-chat`],"agents/verification-run-case-results":[`preview-chat`],"agents/verification-case-result-histories":[`preview-chat`],"agents/improvement-attempts":[`preview-chat`,`improve`],"agents/improvement-attempt-summary":[`preview-chat`,`improve`],"improvement-proposals":[`preview-chat`,`improve`],"agents/versions":[`history`],"agents/latest-publish":[`history`,`embed-publish`],"agents/publishes":[`history`,`embed-publish`],"agents/publish-readiness":[`embed-publish`,`preview-chat`],"agents/chat-designs":[`design`],"agents/chat-embeddability":[`design`],"agents/voice-settings":[`audio-settings`],"agents/voice-samples":[`audio-settings`],"agents/embed-sites":[`embed-publish`,`manage-embed-sites`,`security-model`],"agents/operator-handoff-settings":[`operator-handoff`],"team-names":[`team-management`,`operator-handoff`],"agents/conversation-summary":[`dashboard`],conversations:[`improve`,`operator`],"usage-limit":[`usage-limit`],"current-user":[`role-management`],"call-recording-settings":[`phone-channel`],"phone-numbers":[`phone-channel`],"sip-connections":[`phone-channel`],"tenant-settings":[`tenant-settings`]},gi=e=>{let[t,n]=e.split(`/`).filter(e=>e!==``&&!e.startsWith(`{`)).slice(2);return t===`agents`&&n!=null?`${t}/${n}`:t??``},_i=e=>{let t=hi[gi(e)];if(t==null)return null;let n=t.map(e=>`flygate/${e}`).join(`, `);return`操作の前に読む記事(${Y}): ${n}`},vi=e=>{let t=null,n=()=>(t??=e.loadArticles(),t),r=null,i=()=>(r??=ri(n().articles),r),a=e.withOverview?`${q} の一覧か ${J}`:J;return{knowledge:i,overviewOutcome:()=>{let{articles:e,productLabels:t}=n();return{isError:!1,payload:{guide:`${mi}\n\n# ご利用ガイドの記事一覧\n\n${ci(e,t)}`}}},searchOutcome:(e,t)=>({isError:!1,payload:{results:oi(i(),e,t)}}),readArticleOutcome:e=>{let t=ii(i(),e);return t==null?{isError:!0,payload:{error:{kind:`guide_article_not_found`,message:`記事 "${e}" はありません。${a} で記事を探し、"flygate/knowledge" の形式で指定してください。`}}}:{isError:!1,payload:{article:ni(t),title:t.title,group:t.group,url:t.url,body:si(t.body,t.url)}}}}},yi=()=>({isError:!0,payload:{error:{kind:`product_guide_required`,message:`製品の考え方を確認する前の操作は実行しません。先に ${q} を呼び、依頼に関係する記事を ${Y} で読んでから、この操作をやり直してください。`}}}),bi=e=>typeof e==`string`?e:Array.isArray(e)&&e.every(e=>typeof e==`string`)?e.join(`, `):null,xi={"tenant-root":e=>`${e}(テナント全体に対して)`,"any-resource":e=>`${e}(いずれかのエージェントで保持)`,"per-resource":e=>`${e}(対象エージェントに対して)`,"per-resource-all":e=>`${e} のすべて(対象エージェントに対して)`,"per-resource-any":e=>`${e} のいずれか(対象エージェントに対して)`},Si=e=>k(xi,e),Ci=e=>{if(!A(e))return null;let t=e.gate;if(t===`none`)return`認証のみ(ロール不要)`;let n=bi(e.action??e.actions);return n==null||typeof t!=`string`?null:Si(t)?`必要な権限: ${xi[t](n)}`:`必要な権限: ${n}`},wi={read:null,draft:`下書きへの変更です。公開版(訪問者への配信)には publish まで反映されません。`},Ti=e=>e.effect==null?null:wi[e.effect],Ei=(e,t)=>{let n=[e.summary];e.description!=null&&n.push(``,e.description),n.push(``,`HTTP: ${e.method} ${e.pathTemplate}`);let r=Ci(e.permission);r!=null&&n.push(r);let i=Ti(e);i!=null&&n.push(``,i),e.responseKind===`sse`&&n.push(``,`ストリーミング応答を終端まで収集してから返します(数分かかることがあります)。`),e.responseKind===`binary`&&n.push(``,t.binaryResponse),e.transfer?.kind===`download`&&n.push(``,t.downloadTransfer),e.transfer?.kind===`upload`&&n.push(``,t.uploadTransfer),e.wholeBodyField!=null&&n.push(``,`リクエストボディは "${e.wholeBodyField}" 引数にそのまま渡します(判別共用体)。`);for(let r of e.inlineFiles?.input??[])n.push(``,t.inlineInput(r));if((e.inlineFiles?.output.length??0)>0&&n.push(``,t.inlineOutput),e.sseOutcome!=null){let t=[...e.sseOutcome.requiredEvents,e.sseOutcome.successPointer==null?e.sseOutcome.terminalEvent:`${e.sseOutcome.terminalEvent}{${e.sseOutcome.successPointer}=${JSON.stringify(e.sseOutcome.successValue)}}`];n.push(``,`成功判定: ${t.join(` と `)} が揃ったときだけ outcome=success。欠落・異常終了・打ち切りは isError で返し、自動再送しません。`)}return e.method!==`GET`&&n.push(``,`この操作は自動再送しません。タイムアウト時は状態を再取得して確認してください。`),n.join(`
79
+ `)},Di=e=>({readOnlyHint:e.method===`GET`,destructiveHint:e.method!==`GET`,idempotentHint:e.method===`GET`||e.method===`PUT`||e.method===`DELETE`,openWorldHint:!1}),Oi=new URL(`./guide-articles.json.br`,import.meta.url),ki=/* @__PURE__ */ Ne({productLabels:/* @__PURE__ */ Me(/* @__PURE__ */ I(),/* @__PURE__ */ I()),articles:/* @__PURE__ */ L(/* @__PURE__ */ De(/* @__PURE__ */ Ne({product:/* @__PURE__ */ I(),slug:/* @__PURE__ */ I(),title:/* @__PURE__ */ I(),description:/* @__PURE__ */ I(),group:/* @__PURE__ */ I(),order:/* @__PURE__ */ Ae(),body:/* @__PURE__ */ L(/* @__PURE__ */ De(/* @__PURE__ */ I()),/* @__PURE__ */ Ce(e=>e.join(`
80
+ `))),url:/* @__PURE__ */ I()})),/* @__PURE__ */ Se())}),Ai=(e=Oi)=>{let t=/* @__PURE__ */ R(ki,$r(e,e=>new Ge(`guide articles at ${e}`)));if(!t.success)throw new Ge(`guide articles at ${e.pathname} has an unexpected shape`);return t.output},{knowledge:ji,overviewOutcome:Mi,searchOutcome:Ni,readArticleOutcome:Pi}=vi({loadArticles:()=>Ai(),withOverview:!0}),Fi=e=>e.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`),Ii=e=>Array.isArray(e),Li=(e,t)=>{if(t===``)return[{value:e,wildcardIndices:[]}];let n=t.split(`/`).slice(1).map(e=>Fi(e)),r=[{value:e,wildcardIndices:[]}];for(let e of n){let t=[];for(let{value:n,wildcardIndices:i}of r)if(e===`*`){if(Ii(n))for(let[e,r]of n.entries())t.push({value:r,wildcardIndices:[...i,e]})}else if(Ii(n)){let r=Number(e);Number.isInteger(r)&&r>=0&&r<n.length&&t.push({value:n[r],wildcardIndices:i})}else A(n)&&k(n,e)&&t.push({value:n[e],wildcardIndices:i});r=t}return r},Ri=(e,t)=>Li(e,t).map(e=>e.value),zi=e=>{if(!A(e))return{};let t={};for(let[n,r]of de(e))typeof r==`string`&&(t[n]=r);return t},Bi=e=>e.join(`/`),Vi=(e,t,n)=>{let r=t==null?[]:Li(e,t),i=r[0]?.wildcardIndices.length??0,a=new Map(r.map(e=>[Bi(e.wildcardIndices),n(e.value)]));return e=>a.get(Bi(e.slice(0,i)))},Hi=(e,t)=>{if(t==null)return[];let n=Li(e,t.urlPointer).filter(e=>typeof e.value==`string`),r=Vi(e,t.headersPointer,zi),i=Vi(e,t.namePointer,e=>typeof e==`string`?e:null);return n.map(e=>({url:e.value,kind:t.kind,headers:r(e.wildcardIndices)??{},name:i(e.wildcardIndices)??null}))},Ui=(e,t)=>{let n=``,r=0,i=e.indexOf(`{`);for(;i!==-1;){let a=e.indexOf(`}`,i+1);if(a===-1)break;n+=a===i+1?e.slice(r,a+1):e.slice(r,i)+t(e.slice(i+1,a)),r=a+1,i=e.indexOf(`{`,r)}return n+e.slice(r)},Wi=(e,t)=>{if(typeof t==`string`)return t;if(typeof t==`number`||typeof t==`boolean`)return String(t);throw new b(`argument "${e}" must be a string, number, or boolean`)},Gi=/* @__PURE__ */ new Set([`.`,`..`,`%2e`,`.%2e`,`%2e.`,`%2e%2e`]),Ki=(e,t)=>{if(t===``||Gi.has(t.toLowerCase()))throw new b(`path parameter "${e}" must not be empty, "." or ".."`);return encodeURIComponent(t)},qi=(e,t,n)=>{if(k(n,`tenantName`))throw new b(`"tenantName" is fixed by the server configuration`);let r=Ui(t.pathTemplate,t=>{if(t===`tenantName`)return encodeURIComponent(e.tenantName);let r=n[t];if(r==null)throw new b(`path parameter "${t}" is required`);return Ki(t,Wi(t,r))}),i=[];for(let e of t.queryParams){let t=n[e];if(t!=null){if(Array.isArray(t))for(let n of t)i.push([e,Wi(e,n)]);else i.push([e,Wi(e,t)])}}let a=null,o=!1;if(t.wholeBodyField!=null){if(!k(n,t.wholeBodyField))throw new b(`argument "${t.wholeBodyField}" is required`);a=n[t.wholeBodyField],o=!0}else if(t.bodyFields!=null){let e={};for(let r of t.bodyFields)k(n,r)&&(e[r]=n[r]);a=e,o=!0}return{method:t.method,path:r,query:i,hasBody:o,body:a,responseKind:t.responseKind}},Ji=async(e,t)=>{try{return await e.preflight(),{isError:!1,payload:await t()}}catch(t){let n=e.secrets(),r=JSON.parse(U(JSON.stringify(e.errorPayload(t,n)),n));return e.onFailure(t,r),{isError:!0,payload:r}}},Yi=(e,t,n)=>{let r=t.findIndex(t=>t.event===e.terminalEvent),i=r===-1?null:t[r],a=r===-1?t:t.slice(0,r),o=i==null?null:Ot(i.data),s=new Set(a.map(e=>e.event)),c=e.failureEvents.find(e=>s.has(e));if(c!=null)return{outcome:`failed`,reason:`received failure event "${c}"`,terminal:o};if(i==null)return n.truncated?{outcome:`unknown`,reason:`the stream was cut off by the client limit (${n.reason??`unknown`})`,terminal:o}:{outcome:`unknown`,reason:`the stream ended without the terminal event "${e.terminalEvent}"`,terminal:o};let l=e.successPointer==null?null:Ri(o,e.successPointer)[0];if(e.successPointer!=null&&l!==e.successValue)return{outcome:`failed`,reason:`"${e.terminalEvent}" ended with ${e.successPointer}=${JSON.stringify(l)} (expected ${JSON.stringify(e.successValue)})`,terminal:o};let u=e.requiredEvents.filter(e=>!s.has(e));return u.length>0?{outcome:`failed`,reason:`required event(s) missing before "${e.terminalEvent}": ${u.join(`, `)}`,terminal:o}:{outcome:`success`,reason:null,terminal:o}},Xi=e=>({event:e.event,data:Ot(e.data),...e.id==null?{}:{id:e.id}}),Zi=(e,t)=>{if(e instanceof S)return{isError:!0,payload:{error:{kind:`api`,...e.info}}};if(e instanceof C)return{isError:!0,payload:{error:{kind:`transport`,failure:e.kind,status:e.status,message:e.message}}};if(e instanceof w)return{isError:!0,payload:{error:{kind:`transfer`,failure:e.kind,status:e.status,message:e.message}}};if(e instanceof b)return{isError:!0,payload:{error:{kind:`invalid_arguments`,message:e.message}}};if(e instanceof T)return{isError:!0,payload:{error:{kind:`local_file`,failure:e.kind,message:e.message}}};if(e instanceof E)return{isError:!0,payload:{error:{kind:`inline_file`,failure:e.kind,message:e.message}}};if(e instanceof D)return{isError:!0,payload:{error:{kind:`workspace`,failure:e.kind,message:e.message}}};if(e instanceof x)return{isError:!0,payload:{error:{kind:`auth`,failure:e.kind,message:e.message}}};if(e instanceof se)return{isError:!0,payload:e.payload};if(e instanceof Error)return{isError:!0,payload:{error:{kind:`unexpected`,message:U(e.message,t)}}};throw e},Qi=e=>e instanceof S?e.info.status:e instanceof C?e.status:null,$i=e=>e instanceof S?e.info.code:e instanceof Error?e.name:`unknown`,ea=(e,t,n)=>Ji({preflight:e.preflight,secrets:()=>e.auth.secrets(),errorPayload:(e,t)=>Zi(e,t).payload,onFailure:n=>{e.logger.warn(`tool call failed`,{operationId:t,status:Qi(n),code:$i(n)})}},n),ta=async(e,t,n,{hooks:r,signal:i,canSend:a})=>{let o={attempts:0,requestBytes:0,responseBytes:0},s=async()=>{H(i??void 0);let s=await r.prepareArguments(t,n);H(i??void 0);let c=qi(e.config,t,s),l=await e.client.request(c,i??void 0,a??void 0,o);switch(l.kind){case`json`:{let e=await r.processJson(t,l.body);return{status:l.status,requestId:l.requestId,body:e.body,...e.extra}}case`empty`:return{status:l.status,requestId:l.requestId};case`sse`:{let e=await r.processSse(t,l.events),n={status:l.status,requestId:l.requestId,events:e.events.map(e=>Xi(e)),truncated:l.truncated,stopReason:l.reason,discardedIncomplete:l.discardedIncomplete,...e.extra};if(t.sseOutcome==null)return n;let i=Yi(t.sseOutcome,l.events,{truncated:l.truncated,reason:l.reason}),a={...n,outcome:i.outcome,outcomeReason:i.reason,terminal:i.terminal};if(i.outcome!==`success`)throw new se(i.reason??`operation failed`,{...a,retryHint:`Not retried automatically. Check the affected resource or execution history before running this operation again.`});return a}case`binary`:return{status:l.status,requestId:l.requestId,...await r.processBinary(t,l)};default:throw Error(`unknown response kind`)}};return{...await ea(e,t.operationId,()=>s().catch(e=>{throw H(i??void 0),e})),metrics:o}},na=/^[A-Za-z0-9+/]*={0,2}$/,ra=e=>typeof e==`string`&&e.length%4==0&&na.test(e),ia=(e,t)=>{if(!ra(e))throw new E(`invalid_base64`,`"${t}" is not valid base64`);return e},aa=/* @__PURE__ */ new Map([[`audio/mpeg`,`.mp3`],[`audio/mp4`,`.m4a`],[`audio/ogg`,`.ogg`],[`audio/wav`,`.wav`],[`audio/webm`,`.webm`],[`image/png`,`.png`],[`image/jpeg`,`.jpg`],[`image/webp`,`.webp`],[`application/pdf`,`.pdf`]]),oa=e=>e.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`),sa=async(e,t,n)=>{let r=async(e,t,i)=>{let[a,...o]=t;if(a==null)return n(e,i);if(a===`*`){if(!Array.isArray(e))return e;let t=[];for(let[n,a]of e.entries())t.push(await r(a,o,`${i}/${String(n)}`));return t}if(Array.isArray(e)){let t=Number(a);if(!Number.isInteger(t)||t<0||t>=e.length)return e;let n=[...e];return n[t]=await r(e[t],o,`${i}/${a}`),n}return A(e)&&k(e,a)?{...e,[a]:await r(e[a],o,`${i}/${a}`)}:e};return r(e,t.split(`/`).slice(1).map(e=>oa(e)),``)},ca=(e,t)=>{let n=/* @__PURE__ */ new Set,r=[];for(let i of e.output){if(i.event==null)continue;n.add(i.event);let e=t.filter(e=>e.event===i.event).flatMap(e=>Ri(Ot(e.data),i.pointer));e.length>0&&r.push({output:i,chunks:e})}return{events:t.filter(e=>e.event==null||!n.has(e.event)),outputs:r}},la=(e,t)=>e.output.flatMap(e=>{if(e.event!=null)return[];let n=Ri(t,e.pointer);return n.length===0?[]:[{output:e,chunks:n}]}),ua=(e,t,n)=>String.fromCodePoint(...e.subarray(t,n)),da=e=>new DataView(e.buffer,e.byteOffset,e.byteLength),fa=e=>{if(e.length<12||ua(e,0,4)!==`RIFF`||ua(e,8,12)!==`WAVE`)throw new E(`not_wav`,`the file is not a RIFF/WAVE file`);let t=da(e),n=null,r=null,i=12;for(;i+8<=e.length;){let a=ua(e,i,i+4),o=t.getUint32(i+4,!0),s=i+8,c=s+o;if(c>e.length)throw new E(`not_wav`,`the "${a}" chunk claims more bytes than the file holds`);if(a===`fmt `){if(o<16)throw new E(`not_wav`,`the fmt chunk is truncated`);let e=t.getUint16(s,!0);if((e===65534&&o>=26?t.getUint16(s+24,!0):e)!==1)throw new E(`unsupported_format`,`unsupported WAV format code ${String(e)} (only PCM is accepted)`);n={channels:t.getUint16(s+2,!0),sampleRateHz:t.getUint32(s+4,!0),bitsPerSample:t.getUint16(s+14,!0)}}else a===`data`&&(r=e.subarray(s,c));i=c+o%2}if(n==null||r==null)throw new E(`not_wav`,`the WAV file lacks a fmt or data chunk`);if(n.channels===0||n.sampleRateHz===0)throw new E(`not_wav`,`the WAV file declares no channels or sample rate`);if(n.bitsPerSample!==16)throw new E(`unsupported_format`,`unsupported bit depth ${String(n.bitsPerSample)} (only 16-bit PCM is accepted)`);if(r.length===0)throw new E(`empty`,`the WAV file has no audio samples`);if(r.length%(2*n.channels)!=0)throw new E(`not_wav`,`the data chunk is not aligned to whole samples`);return{sampleRateHz:n.sampleRateHz,channels:n.channels,pcm:r}},pa=(e,t,n)=>{for(let r=0;r<n.length;r+=1)e[t+r]=n.codePointAt(r)??0},ma=(e,t)=>{let n=new Uint8Array(44+e.length),r=da(n),i=2*t.channels;return pa(n,0,`RIFF`),r.setUint32(4,36+e.length,!0),pa(n,8,`WAVE`),pa(n,12,`fmt `),r.setUint32(16,16,!0),r.setUint16(20,1,!0),r.setUint16(22,t.channels,!0),r.setUint32(24,t.sampleRateHz,!0),r.setUint32(28,t.sampleRateHz*i,!0),r.setUint16(32,i,!0),r.setUint16(34,16,!0),pa(n,36,`data`),r.setUint32(40,e.length,!0),n.set(e,44),n},ha=(e,t)=>Math.round(e/(2*t.channels*t.sampleRateHz)*1e3),ga=e=>Buffer.from(e.buffer,e.byteOffset,e.byteLength),_a=e=>{let t=fa(e);return{sampleRateHz:t.sampleRateHz,channels:t.channels,pcm:ga(t.pcm)}},va=(e,t)=>ga(ma(e,t)),ya=async(e,t,n,r)=>{let i=await fr(e,r.fileRoots,r.cwd,r.workspace);try{return await ur(i,t)}catch(e){throw e instanceof T&&e.kind===`too_large`?new E(`too_large`,`"${n}" exceeds ${String(t)} bytes`):e}},ba=async(e,t,n,r)=>{if(typeof t!=`string`||t===``)throw new E(`not_a_path`,`"${n}" must be a local file path`);let i=await ya(t,e.format===`wav-pcm16`?e.maxBytes+44:e.maxBytes,n,r);if(e.format===`base64`){if(i.length===0)throw new E(`empty`,`"${n}" points at an empty file`);return i.toString(`base64`)}let a=_a(i),o=e.pcm;if(o!=null&&(a.sampleRateHz!==o.sampleRateHz||a.channels!==o.channels))throw new E(`unsupported_format`,`"${n}" must be ${String(o.sampleRateHz)} Hz / ${String(o.channels)} channel PCM 16-bit WAV (got ${String(a.sampleRateHz)} Hz / ${String(a.channels)} channel)`);if(a.pcm.length>e.maxBytes)throw new E(`too_large`,`"${n}" holds ${String(a.pcm.length)} bytes of audio; at most ${String(e.maxBytes)} are accepted`);return{encoding:`pcm16le`,sampleRateHz:a.sampleRateHz,channels:a.channels,data:a.pcm.toString(`base64`)}},xa=async(e,t,n)=>{let r=t;for(let t of e.input)r=await sa(r,t.pointer,(e,r)=>ba(t,e,r,n));return A(r)?r:t},Sa=(e,t)=>Buffer.from(ia(e,t),`base64`),Ca=async(e,t,n)=>{let r=[],i=0;for(let[a,o]of t.entries()){let t=Sa(o,`${e.event??`body`}${e.pointer}[${String(a)}]`);if(e.format===`pcm16le`&&t.length%2!=0)throw new E(`unsupported_format`,`${e.event??`body`}${e.pointer} chunk ${String(a)} is not whole PCM 16-bit samples`);if(i+=t.length,i>n.maxBytes)throw new E(`too_large`,`inline output exceeds ${String(n.maxBytes)} bytes`);r.push(t)}let a=Buffer.concat(r),o=e.pcm,s=e.format===`pcm16le`&&o!=null,c=s?va(a,o):a,l=s?`audio/wav`:e.mediaType??`application/octet-stream`,u=s?`.wav`:aa.get(l)??`.bin`;return{...await Dr(new Blob([new Uint8Array(c)]).stream(),{outputDir:n.outputDir,fileName:wr(`${n.fileName}${u}`,`inline${u}`),maxBytes:n.maxBytes+44,timeoutMs:n.timeoutMs}),event:e.event,pointer:e.pointer,mediaType:l,chunks:t.length,durationMs:s?ha(a.length,o):null}},wa=async(e,t,n)=>{let r=ca(e,t),i=[];for(let{output:e,chunks:t}of r.outputs)i.push(await Ca(e,t,n));return{events:r.events,files:i}},Ta=async(e,t,n)=>{let r=t,i=[];for(let{output:a,chunks:o}of la(e,t)){let e=await Ca(a,o,n);i.push(e),r=await sa(r,a.pointer,()=>Promise.resolve(`[saved to ${e.path}]`))}return{body:r,files:i}},Ea={transferTimeoutMs:Ue,maxDownloadBytes:We,maxAutoDownloadsPerCall:20,maxInlineOutputBytes:33554432},Da=e=>({config:e.config,auth:e.auth,client:e.client,logger:e.logger,preflight:async()=>{await En(e.workspace,new Date(e.now())),await e.auth.assertLoggedIn()}}),Oa=async(e,t,n)=>ea(Da(e),t,n),ka=async(e,t,n,r)=>{let i=Hi(n,t.transfer);if(i.length===0)return{};let a=[],o=[],s=[],c=[];for(let n of i){let i;try{i=vr(n.url,e.config)}catch(e){c.push({url:n.url,reason:e instanceof Error?e.message:`rejected`});continue}if(n.kind===`upload`){e.registry.register(n.url,`upload`,n.headers),a.push(n.url);continue}if(o.length>=r.maxAutoDownloadsPerCall){e.registry.register(n.url,`download`,{});continue}let l=wr(n.name??i.pathname.split(`/`).at(-1)??null,`${t.operationId}.bin`),u;try{u=await Or({url:i,outputDir:e.config.outputDir,fileName:l,fetch:e.fetch,maxBytes:r.maxDownloadBytes,timeoutMs:r.transferTimeoutMs})}catch(r){if(!(r instanceof w))throw r;e.logger.warn(`automatic download failed`,{operationId:t.operationId,host:i.hostname,failure:r.kind}),e.registry.register(n.url,`download`,{}),s.push({url:n.url,failure:r.kind});continue}o.push({url:n.url,path:u.path,bytes:u.bytes,sha256Hex:u.sha256Hex,contentType:u.contentType})}return{...a.length===0?{}:{uploadUrls:a,uploadHint:`Call upload_file with one of these URLs and a local file path.`},...o.length===0?{}:{downloads:o},...s.length===0?{}:{failedDownloads:s,downloadHint:`The API response above is complete; only the automatic download failed. Retry it with download_file and the same URL.`},...c.length===0?{}:{rejectedTransferUrls:c}}},Aa=(e,t,n)=>({outputDir:e.config.outputDir,fileName:t.operationId,maxBytes:n.maxInlineOutputBytes,timeoutMs:n.transferTimeoutMs}),ja=e=>e.length===0?{}:{files:e},Ma=(e,t)=>({prepareArguments:async(t,n)=>t.inlineFiles==null?n:await xa(t.inlineFiles,n,{fileRoots:e.config.fileRoots,cwd:e.cwd,workspace:e.workspace}),processJson:async(n,r)=>{let i=await ka(e,n,r,t),a=n.inlineFiles==null?{body:r,files:[]}:await Ta(n.inlineFiles,r,Aa(e,n,t));return{body:a.body,extra:{...i,...ja(a.files)}}},processSse:async(n,r)=>{let i=n.inlineFiles==null?{events:r,files:[]}:await wa(n.inlineFiles,r,Aa(e,n,t));return{events:i.events,extra:ja(i.files)}},processBinary:async(n,r)=>({file:{...await Dr(r.body,{outputDir:e.config.outputDir,fileName:wr(r.fileName,`${n.operationId}.bin`),maxBytes:t.maxDownloadBytes,timeoutMs:t.transferTimeoutMs}),contentType:r.contentType,fileName:r.fileName}})}),Na=async(e,t,n,r=Ea)=>{let{isError:i,payload:a}=await ta(Da(e),t,n,{hooks:Ma(e,r),signal:null,canSend:null});return{isError:i,payload:a}},Pa=(e,t)=>`Flyle AIオペレーターの公開 API を呼ぶツール群です。
81
+ - 作業を始める前に必ず ${q} で製品の考え方とご利用ガイドの記事一覧を確認し、依頼に関係する記事を ${Y} で読んでください。公開 API の操作は ${q} を呼ぶまで実行されません。ツールに無い操作は代わりの手順を組み立てず、該当する記事を示して管理画面での操作を案内してください。
82
+ - 接続先テナントは「${e}」、環境(公開 API のホスト)は「${t}」です。テナント・環境・ログインはサーバー起動時に固定されており、ツール引数でテナントを指定することはできません。
83
+ - この作業ディレクトリは「${e}」専用です。別の顧客(テナント)の情報・ファイル・記憶をこのテナントへの書き込みに使わないでください。別テナントの作業は別ディレクトリの別セッションで行います。
84
+ - 各ツール結果の先頭の environment と tenantName は、その操作を実行した環境とテナントです。
85
+ - 顧客の環境を利用者の合意なしに変えないでください。まず読み取り系ツール(readOnlyHint)で調べ、どの設定・データをどう変えるか(対象、変更前 → 変更後、影響)と理由を示して、利用者の明示的な合意を得てから書き込み系ツールを呼びます。合意した範囲を超える変更が必要になったら、その都度改めて合意を得てください。プレビューでの対話・検証の実行など、設定やデータを変えない確認は合意なしで進めて構いません。利用者が合意を省いてよいと明示した場合は、その範囲に限って確認を省けます。
86
+ - ツールが「ログインが必要です」と返したら、利用者に作業ディレクトリで \`npx @flyle/ai-operator-mcp@latest login\` を実行してもらってください。
87
+ - 書き込み系ツールは自動再送しません。タイムアウトや transport エラーの後は、対象を再取得して状態を確認してください。
88
+ - 一覧は各ツールの入力スキーマと応答に従って取得してください。cursor / limit+offset / ページングなしの全件取得があります。
89
+ - 大きな JSON 結果は出力ディレクトリに全文を保存し、保存先と先頭部分を返します。全文は保存ファイルを参照してください。
90
+ - エージェントの新規作成や、業務フロー・フォーム・ナレッジの構成を変える依頼では、計画を示す前にご利用ガイドの記事 "flygate/design-agent"(エージェントの構成を設計する)と、使う機能の記事を読んでください。そのうえで、応対するチャネル(チャット・電話・両方)、問い合わせの分け方、回答の根拠の使い分け、応対を始める前に必ず聞く情報を決め、依頼から決まらないものは計画を示すときにまとめて確かめてください。機能の設定を提案するときは、記事に書かれた用途が今回の項目やデータに合うかを確かめてください。
91
+ - 利用者には管理画面の名前で話してください。API の flows は「業務フロー」(kind MAIN は「メインフロー」、kind SUB は「サブフロー」)、routing-rules は「振り分けルール」、エージェントの commonSettings は「共通設定」、verification は「検証」(検証ケース・検証を実行・検証結果)、connectors(connector)は「コネクター」です。「ノード」「ルーティング」「ワーカー」とは呼ばず、検証(verification)を「評価」と呼ばないでください(訪問者の評価・応対評価など、画面で「評価」と呼ぶものはそのまま「評価」です)。
92
+ - エージェントの応答や振り分けを変える依頼(改善要望に限らず、新しい問い合わせへの対応・指示文の追記・振り分けルールの変更なども含む)は、必ず検証ケースから始めます。ケースが無いと、あとで同じ問い合わせが壊れても気付けないためです。現在の設定・既存ケースの取得 → 追加するケース(問い合わせの例と期待する回答)と修正案を両方示して合意を得る → create_verification_case / import_verification_cases でケースを保存 → 変更前の検証 → 合意した修正 → プレビューの準備完了の確認 → 全ケースの再検証の順に進め、ケースを保存する前に設定を書き換えないでください。既存ケースで足りる場合は、どのケースで確かめるかを示してください。エージェントの設定(共通設定・業務フロー・振り分けルール・フォームなど)の変更は、プレビューと検証に直ちに反映されます。プレビューの準備(preview build)はナレッジの検索用データだけを作るため、設定だけを変えても previewAgentVersionsSerial は変わりません。プレビューの準備をやり直す必要があるのは、参照するナレッジベースやドキュメントを変えたときです。
93
+ - 改善提案は内容と get_improvement_proposal_plan を確認し、根拠のある actionIndexes だけを resolve_improvement_proposal で反映してください。検証の受付だけで合格と判断せず、get_verification_run と list_verification_run_case_results で完了・ケース別結果を確認してください。
94
+ - ファイルの取り込みは inspect_local_file → create_knowledge_upload_urls → upload_file → create_knowledge_import の順に進め、取り込みとドキュメントの処理完了を確認します。API の byteSize には sizeBytes、checksumSha256 には sha256Hex を渡します(sha256Base64 ではありません)。URL の発行と upload_file は同じ MCP 接続で行ってください。ダウンロード系はファイルパスを返します。`,Fa=e=>A(e)&&e.type===`object`&&A(e.properties),X=(e,t)=>{if(!Fa(e))throw Error(`${t}: input schema must be an object schema`);return e},Ia={binaryResponse:`ファイルを出力ディレクトリに保存し、パスと sha256 を返します。`,downloadTransfer:`応答に含まれる署名付き URL からその場でダウンロードし、ファイルパスを返します。`,uploadTransfer:`応答のアップロード URL は upload_file ツールで使えます(15 分・1 回限り)。`,inlineInput:e=>e.format===`wav-pcm16`&&e.pcm!=null?`"${e.pointer}" にはローカル WAV ファイルのパス(PCM 16bit / ${String(e.pcm.sampleRateHz)} Hz / ${String(e.pcm.channels)}ch、音声 ${String(e.maxBytes)} バイト以内)を渡します。base64 化はこのサーバーが行います。`:`"${e.pointer}" にはローカルファイルのパス(${String(e.maxBytes)} バイト以内)を渡します。base64 化はこのサーバーが行います。`,inlineOutput:`応答に埋め込まれた音声 / ファイルは出力ディレクトリに保存し、パスだけを返します(base64 は結果に含めません)。`},La=e=>{let t=_i(e.pathTemplate),n=Ei(e,Ia);return t==null?n:`${n}\n\n${t}`},Ra=e=>{let t=e.slice(0,4096),n=t.codePointAt(t.length-1)??0;return n>=55296&&n<=56319?t.slice(0,-1):t},za=e=>new ReadableStream({start(t){t.enqueue(e),t.close()}}),Ba=(e,t,n)=>({content:[{type:`text`,text:JSON.stringify({environment:e.environment,tenantName:e.tenantName})},{type:`text`,text:t}],isError:n}),Z=async(e,t)=>{let{secrets:n}=t,r=U(JSON.stringify(e.payload,null,2)??`null`,n);if(r.length<=1048576)return Ba(t,r,e.isError);let i=Buffer.from(U(JSON.stringify(e.payload)??`null`,n),`utf8`),a={totalChars:r.length,preview:Ra(r)};try{let n=await Dr(za(i),{outputDir:t.outputDir,fileName:t.fileName,maxBytes:t.maxFileBytes,timeoutMs:Ue});return Ba(t,JSON.stringify({file:{...n,format:`json`},...a},null,2),e.isError)}catch(e){let n=e instanceof w?e.kind:`unexpected`;return t.logger.warn(`tool result could not be saved`,{fileName:t.fileName,failure:n,bytes:i.byteLength}),Ba(t,JSON.stringify({error:{kind:`result_not_saved`,failure:n,message:`The full result was not saved; only the preview below is available. The operation may have completed; check its state before retrying.`},...a},null,2),!0)}},Q=(e,t)=>({environment:V(e.config.baseUrl),tenantName:e.config.tenantName,outputDir:e.config.outputDir,fileName:`${t}.result.json`,logger:e.logger,secrets:e.auth.secrets(),maxFileBytes:67108864}),Va=e=>A(e)?e:{},Ha=(e,t)=>{let n=e[t];if(typeof n!=`string`||n===``)throw new b(`argument "${t}" is required`);return n},Ua={inspectLocalFile:{type:`object`,properties:{path:{type:`string`,description:`ローカルファイルのパス(相対パスは作業ディレクトリ基準)。`}},required:[`path`],additionalProperties:!1},uploadFile:{type:`object`,properties:{url:{type:`string`,description:`直前の API 応答で返されたアップロード URL。`},path:{type:`string`,description:`アップロードするローカルファイルのパス。`}},required:[`url`,`path`],additionalProperties:!1},downloadFile:{type:`object`,properties:{url:{type:`string`,description:`直前の API 応答で返されたダウンロード URL。`},fileName:{type:`string`,description:`保存名(省略時は URL の末尾から決める)。`}},required:[`url`],additionalProperties:!1}},Wa=(e,t)=>{e.registerTool(`inspect_local_file`,{title:`ローカルファイルの検査`,description:`アップロード前にローカルファイルの名前・サイズ・sha256(hex / base64)・MIME を返します。API の byteSize には sizeBytes、checksumSha256 には sha256Hex を渡してください。読めるのは起動設定の根ディレクトリ配下だけです。`,inputSchema:y(X(Ua.inspectLocalFile,`inspect_local_file`)),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{let n=Va(e);return Z(await Oa(t,`inspect_local_file`,()=>gr(Ha(n,`path`),t.config.fileRoots,t.cwd,t.workspace)),Q(t,`inspect_local_file`))}),e.registerTool(`upload_file`,{title:`署名付き URL へアップロード`,description:`直前の API 応答で返されたアップロード URL へローカルファイルを PUT します。URL は応答由来のものだけを 15 分・1 回限りで受け付け、認証ヘッダは付けません。`,inputSchema:y(X(Ua.uploadFile,`upload_file`)),annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1}},async e=>{let n=Va(e);return Z(await Oa(t,`upload_file`,async()=>{let e=Ha(n,`url`),r=await fr(Ha(n,`path`),t.config.fileRoots,t.cwd,t.workspace),i=t.registry.take(e,`upload`);return await Sr({url:new URL(e),headers:i.headers,filePath:r,fetch:t.fetch,maxBytes:536870912,timeoutMs:Ue})}),Q(t,`upload_file`))}),e.registerTool(`download_file`,{title:`署名付き URL からダウンロード`,description:`直前の API 応答で返されたダウンロード URL からファイルを取得し、出力ディレクトリに保存してパスを返します。URL は応答由来のものだけを受け付けます。`,inputSchema:y(X(Ua.downloadFile,`download_file`)),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{let n=Va(e);return Z(await Oa(t,`download_file`,async()=>{let e=Ha(n,`url`);t.registry.take(e,`download`);let r=new URL(e),i=typeof n.fileName==`string`?n.fileName:null;return await Or({url:r,outputDir:t.config.outputDir,fileName:wr(i??r.pathname.split(`/`).at(-1)??null,`download.bin`),fetch:t.fetch,maxBytes:We,timeoutMs:Ue})}),Q(t,`download_file`))})},Ga={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},Ka=(e,t,n)=>{e.registerTool(q,{title:`製品の全体像とご利用ガイドの記事一覧`,description:`作業の最初に呼びます。Flyle AIオペレーターの考え方(エージェント・業務フロー・ナレッジ・検証・公開などの概念)、この MCP サーバーでできること・できないこと、よくある依頼の進め方と、ご利用ガイドの全記事の一覧を返します。これを呼ぶまで公開 API の操作は実行されません。`,inputSchema:y(X(di,q)),annotations:Ga},()=>(n(),Z(Mi(),Q(t,q)))),e.registerTool(J,{title:`ご利用ガイドの検索`,description:li,inputSchema:y(X(fi,J)),annotations:Ga},e=>{let n=Va(e),r=typeof n.query==`string`?n.query:``,i=typeof n.maxResults==`number`?n.maxResults:10;return Z(Ni(r,i),Q(t,J))}),e.registerTool(Y,{title:`ご利用ガイドの記事を読む`,description:ui(!0),inputSchema:y(X(pi,Y)),annotations:Ga},e=>{let n=Va(e).article;return Z(Pi(typeof n==`string`?n:``),Q(t,Y))})},qa=(e,t)=>{let n=new ae({name:`flyle-ai-operator`,version:Le},{capabilities:{tools:{}},instructions:Pa(e.config.tenantName,V(e.config.baseUrl))}),r=!1;Ka(n,e,()=>{r=!0});for(let i of ce(t))n.registerTool(i.operationId,{title:i.summary,description:La(i),inputSchema:y(X(i.inputSchema,i.operationId)),annotations:Di(i)},async t=>Z(r?await Na(e,i,Va(t)):yi(),Q(e,i.operationId)));return Wa(n,e),n},Ja=e=>new Promise(t=>setTimeout(t,e)),$=()=>Date.now(),Ya=()=>({cwd:process.cwd(),homeDir:e(),hostname:t(),username:n().username,now:()=>/* @__PURE__ */ new Date}),Xa=()=>ut({platform:process.platform,env:process.env,homeDir:e()}),Za=(e,t)=>{console.error(e),process.exit(t)},Qa=async e=>{try{return await pt(e)}catch(e){if(e instanceof x&&e.kind===`login_required`)return null;throw e}},$a=async e=>{let{cwd:t}=e;rt(process.env);let n=await Tn(e);if(n==null)throw new B("この作業ディレクトリはまだログインしていません。このディレクトリで `npx @flyle/ai-operator-mcp@latest login --tenant <テナント名>` を実行してから、MCP サーバーを起動し直してください。");let r=at(process.env,t,n),i=dt(Xa(),n.workspaceId),a=await Qa(i);return a!=null&&$t(a,r.baseUrl,r.tenantName),{config:r,workspace:n,credentialsFile:i,loggedIn:a!=null}},eo=async()=>{let e=Ya(),{cwd:t}=e,n=await $a(e).catch(e=>Za(Nn(e),1)),{config:i,workspace:a,credentialsFile:o}=n,s=()=>[],c=Ar(()=>s()),l=tn({credentialsFile:o,baseUrl:i.baseUrl,tenantName:i.tenantName,tokenClient:on({config:i,auth:null,workspaceId:a.workspaceId,fetch:globalThis.fetch,now:$,sleep:Ja,logger:c},qt),now:$,lock:_t($,Ja)});s=l.secrets;let u=ti(),d={config:i,auth:l,client:on({config:i,auth:l,workspaceId:a.workspaceId,fetch:globalThis.fetch,now:$,sleep:Ja,logger:c}),registry:_r($),fetch:globalThis.fetch,logger:c,now:$,cwd:t,workspace:a},f=r(()=>qa(d,u));c.info(`flygate mcp server started`,{environment:V(i.baseUrl),tenantName:i.tenantName,workspace:a.root,loggedIn:n.loggedIn,operations:ce(u).length});let p=!1,m=()=>{p||(p=!0,Promise.race([l.whenIdle(),Ja(25e3)]).then(()=>f.close()).catch(O).finally(()=>process.exit(0)))};process.on(`SIGINT`,m),process.on(`SIGTERM`,m),process.stdin.once(`end`,m)},to=()=>({env:process.env,workspaceEnv:Ya(),credentialsDir:Xa(),fetch:globalThis.fetch,now:$,sleep:Ja,lock:_t($,Ja),logger:Ar(()=>[]),out:e=>console.log(e),err:e=>console.error(e)}),no=async e=>{try{await e()}catch(e){Za(Nn(e),1)}};await(async()=>{let[e,...t]=process.argv.slice(2);if(e==null){await eo();return}let n={login:()=>ar({...to(),argv:t,openBrowser:e=>rn(e),callbackTimeoutMs:6e5}),logout:()=>Fn(to()),status:()=>cr(to())},r=k(n,e)?n[e]:null;if(r==null)return Za(`使い方: flyle-ai-operator-mcp [login [--tenant <テナント名>] [--api-base-url <URL>] | logout | status]
95
+ 引数なしで起動すると MCP サーバー(stdio)として動きます。`,2);await no(async()=>{rt(process.env),await r()})})();export{};
Binary file
package/package.json CHANGED
@@ -1,6 +1 @@
1
- {
2
- "name": "@flyle/ai-operator-mcp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {"name":"@flyle/ai-operator-mcp","version":"0.6.1-develop.20261101093550.g442b937","description":"MCP server for the Flyle AI Operator public API","keywords":["flyle","mcp","modelcontextprotocol"],"license":"SEE LICENSE IN LICENSE","author":"Flyle.inc","repository":{"type":"git","url":"git+https://github.com/flyle-io/flyle-nexus.git","directory":"apps/flygate/mcp"},"type":"module","engines":{"node":">=22.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"bin":{"flyle-ai-operator-mcp":"./main.js"},"dependencies":{"@modelcontextprotocol/server":"2.3.1"}}