@obov/mext 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/dist/approval.d.ts +33 -0
  2. package/dist/approval.js +36 -0
  3. package/dist/approval.js.map +1 -0
  4. package/dist/audit.d.ts +123 -0
  5. package/dist/audit.js +221 -0
  6. package/dist/audit.js.map +1 -0
  7. package/dist/build-cli.d.ts +1 -0
  8. package/dist/build-cli.js.map +1 -1
  9. package/dist/build.d.ts +2 -0
  10. package/dist/build.js +30 -3
  11. package/dist/build.js.map +1 -1
  12. package/dist/caller.d.ts +53 -0
  13. package/dist/caller.js +51 -0
  14. package/dist/caller.js.map +1 -0
  15. package/dist/cli/build.js +4 -2
  16. package/dist/cli/build.js.map +1 -1
  17. package/dist/cli/dev-audit.d.ts +25 -0
  18. package/dist/cli/dev-audit.js +84 -0
  19. package/dist/cli/dev-audit.js.map +1 -0
  20. package/dist/cli/dev-lock.d.ts +3 -1
  21. package/dist/cli/dev-lock.js +12 -5
  22. package/dist/cli/dev-lock.js.map +1 -1
  23. package/dist/cli/dev-server.d.ts +9 -0
  24. package/dist/cli/dev-server.js +24 -1
  25. package/dist/cli/dev-server.js.map +1 -1
  26. package/dist/cli/dev-tap.d.ts +20 -0
  27. package/dist/cli/dev-tap.js +70 -0
  28. package/dist/cli/dev-tap.js.map +1 -0
  29. package/dist/cli/dev.js +16 -4
  30. package/dist/cli/dev.js.map +1 -1
  31. package/dist/cli/help.js +2 -0
  32. package/dist/cli/help.js.map +1 -1
  33. package/dist/cli/inspect.d.ts +7 -0
  34. package/dist/cli/inspect.js +699 -0
  35. package/dist/cli/inspect.js.map +1 -0
  36. package/dist/cli/main.js +8 -0
  37. package/dist/cli/main.js.map +1 -1
  38. package/dist/cli/output.d.ts +1 -1
  39. package/dist/cli/output.js +3 -2
  40. package/dist/cli/output.js.map +1 -1
  41. package/dist/cli/run.js +28 -4
  42. package/dist/cli/run.js.map +1 -1
  43. package/dist/cli/types.d.ts +9 -0
  44. package/dist/cli/types.js +77 -0
  45. package/dist/cli/types.js.map +1 -0
  46. package/dist/client/index.d.ts +10 -0
  47. package/dist/client/index.js +7 -0
  48. package/dist/client/index.js.map +1 -0
  49. package/dist/client/manifest.js +6 -2
  50. package/dist/client/manifest.js.map +1 -1
  51. package/dist/client/runner.js +37 -3
  52. package/dist/client/runner.js.map +1 -1
  53. package/dist/client/typed.d.ts +54 -0
  54. package/dist/client/typed.js +490 -0
  55. package/dist/client/typed.js.map +1 -0
  56. package/dist/client/types.d.ts +196 -0
  57. package/dist/client/types.js +2 -0
  58. package/dist/client/types.js.map +1 -0
  59. package/dist/command.d.ts +61 -5
  60. package/dist/command.js +42 -1
  61. package/dist/command.js.map +1 -1
  62. package/dist/config.d.ts +42 -10
  63. package/dist/config.js +32 -7
  64. package/dist/config.js.map +1 -1
  65. package/dist/errors.d.ts +21 -3
  66. package/dist/errors.js +13 -0
  67. package/dist/errors.js.map +1 -1
  68. package/dist/expose.d.ts +9 -0
  69. package/dist/expose.js +52 -0
  70. package/dist/expose.js.map +1 -0
  71. package/dist/index.d.ts +15 -6
  72. package/dist/index.js +7 -2
  73. package/dist/index.js.map +1 -1
  74. package/dist/inspect/agent.d.ts +104 -0
  75. package/dist/inspect/agent.js +125 -0
  76. package/dist/inspect/agent.js.map +1 -0
  77. package/dist/inspect/audit.d.ts +46 -0
  78. package/dist/inspect/audit.js +133 -0
  79. package/dist/inspect/audit.js.map +1 -0
  80. package/dist/inspect/compare.d.ts +12 -0
  81. package/dist/inspect/compare.js +31 -0
  82. package/dist/inspect/compare.js.map +1 -0
  83. package/dist/inspect/index.d.ts +17 -0
  84. package/dist/inspect/index.js +12 -0
  85. package/dist/inspect/index.js.map +1 -0
  86. package/dist/inspect/inspector.d.ts +168 -0
  87. package/dist/inspect/inspector.js +392 -0
  88. package/dist/inspect/inspector.js.map +1 -0
  89. package/dist/inspect/profiles.d.ts +95 -0
  90. package/dist/inspect/profiles.js +235 -0
  91. package/dist/inspect/profiles.js.map +1 -0
  92. package/dist/inspect/scenario.d.ts +126 -0
  93. package/dist/inspect/scenario.js +555 -0
  94. package/dist/inspect/scenario.js.map +1 -0
  95. package/dist/inspect/ui-server.d.ts +31 -0
  96. package/dist/inspect/ui-server.js +378 -0
  97. package/dist/inspect/ui-server.js.map +1 -0
  98. package/dist/inspect/ui.html +917 -0
  99. package/dist/instrumentation.d.ts +13 -2
  100. package/dist/instrumentation.js +11 -1
  101. package/dist/instrumentation.js.map +1 -1
  102. package/dist/invoke.d.ts +32 -5
  103. package/dist/invoke.js +150 -16
  104. package/dist/invoke.js.map +1 -1
  105. package/dist/manifest.d.ts +13 -2
  106. package/dist/manifest.js +5 -1
  107. package/dist/manifest.js.map +1 -1
  108. package/dist/mcp/constants.d.ts +5 -0
  109. package/dist/mcp/constants.js +5 -0
  110. package/dist/mcp/constants.js.map +1 -1
  111. package/dist/mcp/dispatch.d.ts +1 -1
  112. package/dist/mcp/dispatch.js +14 -3
  113. package/dist/mcp/dispatch.js.map +1 -1
  114. package/dist/mcp/help.d.ts +2 -0
  115. package/dist/mcp/help.js +6 -1
  116. package/dist/mcp/help.js.map +1 -1
  117. package/dist/mcp/http.d.ts +16 -2
  118. package/dist/mcp/http.js +76 -7
  119. package/dist/mcp/http.js.map +1 -1
  120. package/dist/mcp/index.d.ts +1 -1
  121. package/dist/mcp/index.js +1 -1
  122. package/dist/mcp/index.js.map +1 -1
  123. package/dist/mcp/server.d.ts +12 -1
  124. package/dist/mcp/server.js +63 -17
  125. package/dist/mcp/server.js.map +1 -1
  126. package/dist/mcp/stdio.d.ts +4 -0
  127. package/dist/mcp/stdio.js +3 -0
  128. package/dist/mcp/stdio.js.map +1 -1
  129. package/dist/mcp/tasks.d.ts +3 -1
  130. package/dist/mcp/tasks.js +6 -3
  131. package/dist/mcp/tasks.js.map +1 -1
  132. package/dist/principal.d.ts +22 -0
  133. package/dist/principal.js +29 -0
  134. package/dist/principal.js.map +1 -1
  135. package/dist/registry.d.ts +5 -0
  136. package/dist/registry.js +21 -0
  137. package/dist/registry.js.map +1 -1
  138. package/dist/remote/client.d.ts +2 -0
  139. package/dist/remote/client.js +3 -2
  140. package/dist/remote/client.js.map +1 -1
  141. package/dist/remote/oauth.d.ts +1 -1
  142. package/dist/remote/oauth.js +1 -1
  143. package/dist/remote/oauth.js.map +1 -1
  144. package/dist/start.js +6 -2
  145. package/dist/start.js.map +1 -1
  146. package/dist/suggest.js +1 -1
  147. package/dist/suggest.js.map +1 -1
  148. package/dist/typegen.d.ts +27 -0
  149. package/dist/typegen.js +62 -0
  150. package/dist/typegen.js.map +1 -0
  151. package/dist/version-constant.d.ts +5 -0
  152. package/dist/version-constant.js +6 -0
  153. package/dist/version-constant.js.map +1 -0
  154. package/dist/version.d.ts +1 -2
  155. package/dist/version.js +1 -2
  156. package/dist/version.js.map +1 -1
  157. package/package.json +12 -2
@@ -0,0 +1,490 @@
1
+ import { MextError } from "../errors.js";
2
+ import { APPROVAL_META_KEY, COMMAND_META_KEY, MANIFEST_HASH_META_KEY, TOOLS_META_KEY } from "../mcp/constants.js";
3
+ import { createRemoteClient, isRecord, RemoteInputRequiredError, RemoteRpcError, RemoteTransportError, RemoteUnauthorizedError, TASKS_EXTENSION_ID, } from "../remote/client.js";
4
+ import { VERSION } from "../version-constant.js";
5
+ import { manifestFromTools, manifestHelp } from "./manifest.js";
6
+ import { awaitTask, isTaskResult, RemoteTaskError } from "./task.js";
7
+ /**
8
+ * 타입 client (specs/client.md). 고객 CLI (client/runner.ts) 와 같은 원격 호출 코드 위의 얇은 계층:
9
+ * 전송 · MRTR 재시도 = remote/client.ts, task 폴링 = client/task.ts, command 노출의 목록 = client/manifest.ts.
10
+ * 이 모듈 (와 import 대상) 은 브라우저 번들에 들어간다: Node 내장 모듈 · Zod · MCP 서버 SDK import 금지.
11
+ * 자격 증명 (token · headers) 은 요청마다 호출자 함수에서 받고 저장하지 않는다
12
+ */
13
+ export { APPROVAL_META_KEY };
14
+ /** 결과 _meta 의 serverInfo 키 (MCP 2026-07-28) */
15
+ const SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
16
+ /** 진행률을 받을 때 싣는 progressToken */
17
+ const PROGRESS_TOKEN = "mext-client";
18
+ /** dispatcher 도구 (execute · query · mutate) 의 command 인자 = Mcp-Param-Command 헤더 (mext.md §6) */
19
+ const DISPATCHER_INPUT_SCHEMA = { type: "object", properties: { command: { type: "string", "x-mcp-header": "Command" } } };
20
+ /**
21
+ * 호출 실패. code = 서버 구조화 오류 code (UNKNOWN_COMMAND · INVALID_ARGUMENT · PERMISSION_DENIED · APPROVAL_REQUIRED ·
22
+ * CommandError code …) 또는 client code (UNAUTHENTICATED · REMOTE_ERROR · INPUT_UNAVAILABLE). 모르는 code 도 그대로 전달
23
+ */
24
+ export class CallError extends Error {
25
+ code;
26
+ /** 본문의 code · message 외 필드 */
27
+ details;
28
+ /** 서버 본문 그대로 { code, message, ...details } */
29
+ body;
30
+ /** 호출한 명령어 ID */
31
+ command;
32
+ /** HTTP status (401 · JSON-RPC 오류) */
33
+ status;
34
+ constructor(body, command, options = {}) {
35
+ super(body.message, options.cause === undefined ? undefined : { cause: options.cause });
36
+ this.name = "CallError";
37
+ this.code = body.code;
38
+ const { code: _code, message: _message, ...details } = body;
39
+ this.details = details;
40
+ this.body = body;
41
+ this.command = command;
42
+ this.status = options.status;
43
+ }
44
+ }
45
+ export function isCallError(error, code) {
46
+ return error instanceof CallError && (code === undefined || error.code === code);
47
+ }
48
+ export function createClient(options) {
49
+ const baseFetch = options.fetch ?? ((input, init) => fetch(input, init));
50
+ const headersOf = options.headers;
51
+ const tokenOf = options.token;
52
+ const remote = createRemoteClient({
53
+ url: options.url,
54
+ clientInfo: options.clientInfo ?? { name: "mext-client", version: VERSION },
55
+ ...(tokenOf !== undefined ? { token: typeof tokenOf === "function" ? tokenOf : () => tokenOf } : {}),
56
+ fetch: (async (input, init) => {
57
+ const extra = typeof headersOf === "function" ? await headersOf() : headersOf;
58
+ if (!extra)
59
+ return baseFetch(input, init);
60
+ const headers = new Headers(init?.headers);
61
+ for (const [name, value] of Object.entries(extra))
62
+ headers.set(name, value);
63
+ return baseFetch(input, { ...init, headers });
64
+ }),
65
+ });
66
+ /* 캐시 (메모리). manifestHash 가 바뀐 것을 보면 비운다 */
67
+ let server;
68
+ let listing;
69
+ let helps = new Map();
70
+ let knownHash;
71
+ const refresh = () => {
72
+ server = undefined;
73
+ listing = undefined;
74
+ helps = new Map();
75
+ knownHash = undefined;
76
+ };
77
+ const observe = (hash) => {
78
+ if (hash === undefined)
79
+ return;
80
+ if (knownHash !== undefined && knownHash !== hash)
81
+ refresh();
82
+ knownHash = hash;
83
+ };
84
+ /** 실패한 조회는 캐시에 남기지 않는다 */
85
+ const cached = (get, set, load) => {
86
+ const existing = get();
87
+ if (existing)
88
+ return existing;
89
+ const p = load();
90
+ set(p);
91
+ p.catch(() => {
92
+ if (get() === p)
93
+ set(undefined);
94
+ });
95
+ return p;
96
+ };
97
+ const tools = (o) => cached(() => listing, (p) => (listing = p), () => remote.listTools(sig(o)));
98
+ const loadServer = async (o) => {
99
+ let discover;
100
+ try {
101
+ discover = await remote.request("server/discover", {}, sig(o));
102
+ }
103
+ catch (error) {
104
+ // discover 없는 서버 = 도구 이름으로 추정
105
+ if (!(error instanceof RemoteRpcError))
106
+ throw error;
107
+ }
108
+ const meta = isRecord(discover?._meta) ? discover._meta : {};
109
+ const declared = options.tools ?? meta[TOOLS_META_KEY];
110
+ const exposure = isExposure(declared) ? declared : exposureOfTools(await tools(o));
111
+ const info = { tools: exposure, tasks: false };
112
+ if (typeof meta[MANIFEST_HASH_META_KEY] === "string") {
113
+ info.manifestHash = meta[MANIFEST_HASH_META_KEY];
114
+ observe(info.manifestHash);
115
+ }
116
+ // 2026-07-28 = 결과 _meta 의 serverInfo (2025 initialize 결과는 최상위)
117
+ const reported = meta[SERVER_INFO_META_KEY] ?? discover?.serverInfo;
118
+ const serverInfo = isRecord(reported) ? reported : {};
119
+ if (typeof serverInfo.name === "string")
120
+ info.name = serverInfo.name;
121
+ if (typeof serverInfo.version === "string")
122
+ info.version = serverInfo.version;
123
+ if (typeof discover?.instructions === "string")
124
+ info.instructions = discover.instructions;
125
+ const capabilities = isRecord(discover?.capabilities) ? discover.capabilities : {};
126
+ info.tasks = isRecord(capabilities.extensions) && isRecord(capabilities.extensions[TASKS_EXTENSION_ID]);
127
+ return info;
128
+ };
129
+ const serverInfo = (o) => cached(() => server, (p) => (server = p), () => loadServer(o));
130
+ const exposureOf = async (o) => options.tools ?? (await serverInfo(o)).tools;
131
+ /** help 1회 (캐시). command 노출 = tools/list 로 만든 manifest 의 help (help 도구 없음) */
132
+ const help = (target, o) => cached(() => helps.get(target), (p) => (p ? helps.set(target, p) : helps.delete(target)), async () => {
133
+ const exposure = await exposureOf(o);
134
+ if (exposure === "command")
135
+ return withToolMeta(manifestHelp(manifestFromTools(await tools(o)), target), await tools(o));
136
+ const args = target === "" ? { command: "help" } : { command: "help", args: { target } };
137
+ const result = await remote.callTool(dispatcherTool(exposure === "split" ? "query" : "execute"), args, sig(o));
138
+ observe(metaHash(result));
139
+ if (result.isError === true)
140
+ throw toolError(result, target);
141
+ const value = result.structuredContent;
142
+ if (!isRecord(value) || (value.kind !== "root" && value.kind !== "namespace" && value.kind !== "command")) {
143
+ throw new RemoteTransportError(`${options.url} returned an unexpected help result.`);
144
+ }
145
+ return value;
146
+ });
147
+ const describe = async (id, o) => {
148
+ const value = await help(id, o);
149
+ const command = value.kind === "command" ? value : value.kind === "namespace" ? value.command : undefined;
150
+ if (!command) {
151
+ throw new CallError({ code: "UNKNOWN_COMMAND", message: id === "" ? "No command given." : `"${id}" is a namespace, not a command.`, command: id, suggested: [], usage: id === "" ? "help" : `help ${id}` }, id);
152
+ }
153
+ const { kind: _kind, ...info } = command;
154
+ return info;
155
+ };
156
+ const commands = async (o) => {
157
+ const root = await help("", o);
158
+ if (root.kind !== "root")
159
+ throw new RemoteTransportError(`${options.url} returned an unexpected help result.`);
160
+ const namespaces = [];
161
+ const list = [...root.commands];
162
+ // 네임스페이스마다 help 1회 (너비 우선). command 노출 = 캐시된 tools/list 에서 계산 (요청 없음)
163
+ for (let queue = [...root.namespaces]; queue.length > 0;) {
164
+ const next = [];
165
+ for (const ns of queue)
166
+ namespaces.push(ns);
167
+ for (const value of await Promise.all(queue.map((ns) => help(ns.id, o)))) {
168
+ if (value.kind !== "namespace")
169
+ continue;
170
+ list.push(...value.commands);
171
+ next.push(...value.namespaces);
172
+ }
173
+ queue = next;
174
+ }
175
+ const byId = (a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
176
+ const out = { namespaces: namespaces.sort(byId), commands: list.sort(byId) };
177
+ if (root.description !== undefined)
178
+ out.description = root.description;
179
+ return out;
180
+ };
181
+ /** 명령어를 호출할 도구 · 인자 (노출 방식별, specs/client.md §2.2) */
182
+ const target = async (id, input, o) => {
183
+ const exposure = await exposureOf(o);
184
+ if (exposure === "command")
185
+ return { tool: { name: id }, args: input };
186
+ if (exposure === "execute")
187
+ return { tool: dispatcherTool("execute"), args: { command: id, args: input } };
188
+ const info = await describe(id, o);
189
+ return { tool: dispatcherTool(info.tool ?? (info.readOnly ? "query" : "mutate")), args: { command: id, args: input } };
190
+ };
191
+ const finish = (result, command) => {
192
+ observe(metaHash(result));
193
+ if (result.isError === true)
194
+ throw toolError(result, command);
195
+ return result.structuredContent === undefined ? (textValue(result) ?? null) : result.structuredContent;
196
+ };
197
+ /** task 폴링 (client/task.ts awaitTask). tasks/get 을 감싸 상태 변화마다 onTask */
198
+ const waitTask = (created, command, o) => {
199
+ let last = "";
200
+ const notify = (view) => {
201
+ const status = { taskId: created.taskId, status: typeof view.status === "string" ? view.status : "working" };
202
+ if (typeof view.statusMessage === "string")
203
+ status.statusMessage = view.statusMessage;
204
+ const key = `${status.status}\n${status.statusMessage ?? ""}`;
205
+ if (key === last)
206
+ return;
207
+ last = key;
208
+ o.onTask?.(status);
209
+ };
210
+ notify(created);
211
+ const watched = {
212
+ ...remote,
213
+ getTask: async (taskId, opts) => {
214
+ const view = await remote.getTask(taskId, opts);
215
+ notify(view);
216
+ return view;
217
+ },
218
+ };
219
+ return awaitTask(created, {
220
+ client: watched,
221
+ call: (fn) => fn({ signal: o.signal ?? NEVER }),
222
+ signal: o.signal ?? NEVER,
223
+ onInputRequired: inputHandler(command, o),
224
+ onStatus: (message) => o.onProgress?.({ message }),
225
+ });
226
+ };
227
+ const run = async (id, input, o) => {
228
+ try {
229
+ const { tool, args } = await target(id, input, o);
230
+ const callOptions = { ...sig(o), onInputRequired: inputHandler(id, o) };
231
+ if (o.confirmed === true)
232
+ callOptions.meta = { [APPROVAL_META_KEY]: { confirmed: true } };
233
+ if (o.onProgress) {
234
+ const onProgress = o.onProgress;
235
+ callOptions.progressToken = PROGRESS_TOKEN;
236
+ callOptions.onNotification = (method, params) => {
237
+ if (method !== "notifications/progress" || typeof params.progress !== "number")
238
+ return;
239
+ onProgress({
240
+ progress: params.progress,
241
+ ...(typeof params.total === "number" ? { total: params.total } : {}),
242
+ ...(typeof params.message === "string" ? { message: params.message } : {}),
243
+ });
244
+ };
245
+ }
246
+ let result;
247
+ try {
248
+ result = await remote.callTool(tool, args, callOptions);
249
+ }
250
+ catch (error) {
251
+ // command 노출: 없는 도구 = JSON-RPC 오류. 별칭이면 정식 ID 로 다시, 없는 ID 면 UNKNOWN_COMMAND (dispatcher 와 같은 본문)
252
+ const canonical = error instanceof RemoteRpcError && tool.name === id ? await canonicalId(id, o) : undefined;
253
+ if (canonical === undefined)
254
+ throw error;
255
+ result = await remote.callTool({ name: canonical }, args, callOptions);
256
+ }
257
+ if (isTaskResult(result))
258
+ result = await waitTask(result, id, o);
259
+ return finish(result, id);
260
+ }
261
+ catch (error) {
262
+ throw normalize(error, id, o.signal);
263
+ }
264
+ };
265
+ /** command 노출에서 실패한 도구 이름: 별칭 → 정식 ID, 정식 ID 그대로 = undefined (원래 오류), 없는 ID = MextError UNKNOWN_COMMAND */
266
+ const canonicalId = async (id, o) => {
267
+ if ((await exposureOf(o)) !== "command")
268
+ return undefined;
269
+ listing = undefined;
270
+ helps = new Map();
271
+ const found = manifestHelp(manifestFromTools(await tools(o)), id);
272
+ const command = found.kind === "command" ? found : undefined;
273
+ return command !== undefined && command.id !== id ? command.id : undefined;
274
+ };
275
+ const taskHandle = (taskId) => ({
276
+ taskId,
277
+ async get(o = {}) {
278
+ try {
279
+ return taskStatus(taskId, await remote.getTask(taskId, sig(o)));
280
+ }
281
+ catch (error) {
282
+ throw normalize(error, "", o.signal);
283
+ }
284
+ },
285
+ async wait(o = {}) {
286
+ try {
287
+ const view = await remote.getTask(taskId, sig(o));
288
+ return finish(await waitTask({ ...view, taskId }, "", o), "");
289
+ }
290
+ catch (error) {
291
+ throw normalize(error, "", o.signal);
292
+ }
293
+ },
294
+ async cancel(o = {}) {
295
+ try {
296
+ await remote.cancelTask(taskId, sig(o));
297
+ }
298
+ catch (error) {
299
+ throw normalize(error, "", o.signal);
300
+ }
301
+ },
302
+ });
303
+ const guarded = async (command, o, fn) => {
304
+ try {
305
+ return await fn();
306
+ }
307
+ catch (error) {
308
+ throw normalize(error, command, o.signal);
309
+ }
310
+ };
311
+ const call = (id, input, o) => run(id, (input ?? {}), o ?? {});
312
+ return {
313
+ url: options.url,
314
+ call: call,
315
+ safeCall: (async (id, input, o) => {
316
+ try {
317
+ return { ok: true, value: await call(id, input, o) };
318
+ }
319
+ catch (error) {
320
+ if (error instanceof CallError)
321
+ return { ok: false, error };
322
+ throw error;
323
+ }
324
+ }),
325
+ commands: (o = {}) => guarded("", o, () => commands(o)),
326
+ describe: (id, o = {}) => guarded(id, o, () => describe(id, o)),
327
+ help: (t = "", o = {}) => guarded(t, o, () => help(t.trim(), o)),
328
+ server: (o = {}) => guarded("", o, () => serverInfo(o)),
329
+ task: taskHandle,
330
+ refresh,
331
+ };
332
+ }
333
+ /* 입력 요청 (MRTR · task input_required) */
334
+ /**
335
+ * InputRequiredResult → inputResponses. confirmed = confirm 요청에 묻지 않고 승인. 그 외 = onInput.
336
+ * onInput 없음 · 모르는 요청 = CallError INPUT_UNAVAILABLE (호출은 실행되지 않았다)
337
+ */
338
+ function inputHandler(command, o) {
339
+ return async (required) => {
340
+ const out = {};
341
+ for (const [key, raw] of Object.entries(required.inputRequests ?? {})) {
342
+ const info = describeInput(key, raw, command);
343
+ if (info === undefined)
344
+ throw inputUnavailable(command, required, `unsupported input request ${raw.method}`);
345
+ const confirmKey = info.kind === "confirm" ? confirmField(info.schema ?? {}) : undefined;
346
+ if (confirmKey !== undefined && o.confirmed === true) {
347
+ out[key] = { action: "accept", content: { [confirmKey]: true } };
348
+ continue;
349
+ }
350
+ if (!o.onInput)
351
+ throw inputUnavailable(command, required, `asked "${info.message}"`);
352
+ const answer = await o.onInput(info);
353
+ if (answer === true)
354
+ out[key] = confirmKey !== undefined ? { action: "accept", content: { [confirmKey]: true } } : { action: "accept" };
355
+ else if (answer === false)
356
+ out[key] = { action: "decline" };
357
+ else
358
+ out[key] = answer;
359
+ }
360
+ return out;
361
+ };
362
+ }
363
+ function describeInput(key, raw, command) {
364
+ if (raw.method !== "elicitation/create")
365
+ return undefined;
366
+ const params = isRecord(raw.params) ? raw.params : {};
367
+ const message = typeof params.message === "string" ? params.message : "Input required";
368
+ if (params.mode === "url") {
369
+ if (typeof params.url !== "string")
370
+ return undefined;
371
+ return { key, kind: "url", message, url: params.url, command, raw };
372
+ }
373
+ const schema = isRecord(params.requestedSchema) ? params.requestedSchema : { type: "object", properties: {} };
374
+ return { key, kind: confirmField(schema) !== undefined ? "confirm" : "form", message, schema, command, raw };
375
+ }
376
+ /** requestedSchema 의 속성이 boolean 하나면 그 키 (확인 요청. 고객 CLI 와 같은 판정) */
377
+ function confirmField(schema) {
378
+ const props = schema.properties;
379
+ if (!isRecord(props))
380
+ return undefined;
381
+ const keys = Object.keys(props);
382
+ if (keys.length !== 1)
383
+ return undefined;
384
+ const p = props[keys[0]];
385
+ return isRecord(p) && p.type === "boolean" ? keys[0] : undefined;
386
+ }
387
+ function inputUnavailable(command, required, why) {
388
+ return new CallError({
389
+ code: "INPUT_UNAVAILABLE",
390
+ message: `${command || "The task"} ${why}, but this call has no handler for it. Pass onInput (or confirmed: true for confirmations).`,
391
+ command,
392
+ requests: required.inputRequests ?? {},
393
+ }, command);
394
+ }
395
+ /* 결과 · 오류 */
396
+ /** isError 결과 → CallError. 본문 = structuredContent.error (없으면 text 로 EXECUTION_FAILED) */
397
+ function toolError(result, command) {
398
+ const sc = result.structuredContent;
399
+ const body = isRecord(sc) && isRecord(sc.error) ? sc.error : undefined;
400
+ if (body && typeof body.code === "string") {
401
+ return new CallError({ ...body, code: body.code, message: typeof body.message === "string" ? body.message : body.code }, command);
402
+ }
403
+ return new CallError({ code: "EXECUTION_FAILED", message: textValue(result) ?? "Remote command failed." }, command);
404
+ }
405
+ /** 원격 호출 계층의 오류 → CallError. 취소 = signal.reason. 그 외 (호출 코드 콜백의 예외 등) = 그대로 */
406
+ function normalize(error, command, signal) {
407
+ if (signal?.aborted)
408
+ return signal.reason;
409
+ if (error instanceof CallError)
410
+ return error;
411
+ if (error instanceof MextError)
412
+ return new CallError(error.toJSON(), command);
413
+ if (error instanceof RemoteUnauthorizedError) {
414
+ const data = isRecord(error.data) ? error.data : {};
415
+ const reason = data.reason === "invalid_token" || error.challenge.error === "invalid_token" ? "invalid_token" : "missing_token";
416
+ return new CallError({ ...data, code: "UNAUTHENTICATED", message: error.message, reason }, command, { status: 401, cause: error });
417
+ }
418
+ if (error instanceof RemoteInputRequiredError) {
419
+ return new CallError({ code: "INPUT_UNAVAILABLE", message: error.message, command, requests: error.request.inputRequests ?? {} }, command, { cause: error });
420
+ }
421
+ if (error instanceof RemoteRpcError) {
422
+ const rpc = { code: error.code, status: error.status, data: error.data };
423
+ return new CallError({ code: "REMOTE_ERROR", message: error.message, rpc }, command, { status: error.status, cause: error });
424
+ }
425
+ if (error instanceof RemoteTaskError) {
426
+ const task = { taskId: error.taskId, status: error.status, ...(error.error ? { error: error.error } : {}) };
427
+ return new CallError({ code: "REMOTE_ERROR", message: error.message, task }, command, { cause: error });
428
+ }
429
+ if (error instanceof RemoteTransportError)
430
+ return new CallError({ code: "REMOTE_ERROR", message: error.message }, command, { cause: error });
431
+ return error;
432
+ }
433
+ function textValue(result) {
434
+ const texts = (result.content ?? []).flatMap((c) => (isRecord(c) && c.type === "text" && typeof c.text === "string" ? [c.text] : []));
435
+ return texts.length > 0 ? texts.join("\n") : undefined;
436
+ }
437
+ function metaHash(result) {
438
+ const value = isRecord(result._meta) ? result._meta[MANIFEST_HASH_META_KEY] : undefined;
439
+ return typeof value === "string" ? value : undefined;
440
+ }
441
+ function taskStatus(taskId, view) {
442
+ const status = { taskId, status: typeof view.status === "string" ? view.status : "working" };
443
+ if (typeof view.statusMessage === "string")
444
+ status.statusMessage = view.statusMessage;
445
+ return status;
446
+ }
447
+ /* 노출 방식 */
448
+ function isExposure(value) {
449
+ return value === "execute" || value === "split" || value === "command";
450
+ }
451
+ /** server/discover 가 없는 서버: 도구 이름으로 추정 */
452
+ function exposureOfTools(tools) {
453
+ const names = new Set(tools.map((t) => t.name));
454
+ if (names.has("execute"))
455
+ return "execute";
456
+ if (names.has("query") && names.has("mutate"))
457
+ return "split";
458
+ return "command";
459
+ }
460
+ function dispatcherTool(name) {
461
+ return { name, inputSchema: DISPATCHER_INPUT_SCHEMA };
462
+ }
463
+ /**
464
+ * command 노출의 help 에 도구 _meta["dev.mext/command"] 의 모르는 필드를 더한다 (manifestFromTools 는 아는 필드만 옮긴다).
465
+ * 서버가 client 보다 새 버전일 때 메타데이터 (예: needsApproval) 가 사라지지 않게
466
+ */
467
+ function withToolMeta(value, tools) {
468
+ const extra = (id) => {
469
+ const meta = tools.find((t) => t.name === id)?._meta;
470
+ return isRecord(meta) && isRecord(meta[COMMAND_META_KEY]) ? meta[COMMAND_META_KEY] : {};
471
+ };
472
+ const merge = (item, keys) => {
473
+ const meta = extra(item.id);
474
+ const picked = keys ? Object.fromEntries(Object.entries(meta).filter(([k]) => keys.includes(k))) : meta;
475
+ return { ...picked, ...item };
476
+ };
477
+ if (value.kind === "command")
478
+ return merge(value);
479
+ const commands = value.commands.map((c) => merge(c, SUMMARY_EXTRA_KEYS));
480
+ if (value.kind === "namespace" && value.command)
481
+ return { ...value, commands, command: merge(value.command) };
482
+ return { ...value, commands };
483
+ }
484
+ /** 요약 (목록) 에 싣는 추가 메타데이터 */
485
+ const SUMMARY_EXTRA_KEYS = ["needsApproval"];
486
+ const NEVER = new AbortController().signal;
487
+ function sig(o) {
488
+ return o.signal ? { signal: o.signal } : {};
489
+ }
490
+ //# sourceMappingURL=typed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typed.js","sourceRoot":"","sources":["../../src/client/typed.ts"],"names":[],"mappings":"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","sourcesContent":["import { MextError } from \"../errors.ts\"\nimport { APPROVAL_META_KEY, COMMAND_META_KEY, MANIFEST_HASH_META_KEY, TOOLS_META_KEY } from \"../mcp/constants.ts\"\nimport type { ToolExposure } from \"../mcp/dispatch.ts\"\nimport type { Help } from \"../mcp/help.ts\"\nimport {\n createRemoteClient,\n isRecord,\n RemoteInputRequiredError,\n RemoteRpcError,\n RemoteTransportError,\n RemoteUnauthorizedError,\n TASKS_EXTENSION_ID,\n type CallToolOptions,\n type CallToolResult,\n type InputRequired,\n type InputRequestObject,\n type InputResponses,\n type RemoteClient,\n type RemoteTool,\n} from \"../remote/client.ts\"\nimport { VERSION } from \"../version-constant.ts\"\nimport { manifestFromTools, manifestHelp } from \"./manifest.ts\"\nimport { awaitTask, isTaskResult, RemoteTaskError } from \"./task.ts\"\nimport type {\n AnyCommands,\n CallArgs,\n CallOptions,\n ClientOptions,\n CommandInfo,\n CommandList,\n CommandMap,\n CommandSummary,\n InputAnswer,\n InputRequestInfo,\n NamespaceSummary,\n RequestOptions,\n SafeResult,\n ServerInfo,\n TaskHandle,\n TaskStatus,\n} from \"./types.ts\"\n\n/**\n * 타입 client (specs/client.md). 고객 CLI (client/runner.ts) 와 같은 원격 호출 코드 위의 얇은 계층:\n * 전송 · MRTR 재시도 = remote/client.ts, task 폴링 = client/task.ts, command 노출의 목록 = client/manifest.ts.\n * 이 모듈 (와 import 대상) 은 브라우저 번들에 들어간다: Node 내장 모듈 · Zod · MCP 서버 SDK import 금지.\n * 자격 증명 (token · headers) 은 요청마다 호출자 함수에서 받고 저장하지 않는다\n */\n\nexport { APPROVAL_META_KEY }\n\n/** 결과 _meta 의 serverInfo 키 (MCP 2026-07-28) */\nconst SERVER_INFO_META_KEY = \"io.modelcontextprotocol/serverInfo\"\n\n/** 진행률을 받을 때 싣는 progressToken */\nconst PROGRESS_TOKEN = \"mext-client\"\n\n/** dispatcher 도구 (execute · query · mutate) 의 command 인자 = Mcp-Param-Command 헤더 (mext.md §6) */\nconst DISPATCHER_INPUT_SCHEMA = { type: \"object\", properties: { command: { type: \"string\", \"x-mcp-header\": \"Command\" } } }\n\n/**\n * 호출 실패. code = 서버 구조화 오류 code (UNKNOWN_COMMAND · INVALID_ARGUMENT · PERMISSION_DENIED · APPROVAL_REQUIRED ·\n * CommandError code …) 또는 client code (UNAUTHENTICATED · REMOTE_ERROR · INPUT_UNAVAILABLE). 모르는 code 도 그대로 전달\n */\nexport class CallError<Code extends string = string> extends Error {\n readonly code: Code\n /** 본문의 code · message 외 필드 */\n readonly details: Record<string, unknown>\n /** 서버 본문 그대로 { code, message, ...details } */\n readonly body: Record<string, unknown>\n /** 호출한 명령어 ID */\n readonly command: string\n /** HTTP status (401 · JSON-RPC 오류) */\n readonly status: number | undefined\n\n constructor(body: Record<string, unknown> & { code: Code; message: string }, command: string, options: { status?: number; cause?: unknown } = {}) {\n super(body.message, options.cause === undefined ? undefined : { cause: options.cause })\n this.name = \"CallError\"\n this.code = body.code\n const { code: _code, message: _message, ...details } = body\n this.details = details\n this.body = body\n this.command = command\n this.status = options.status\n }\n}\n\nexport function isCallError<Code extends string = string>(error: unknown, code?: Code): error is CallError<Code> {\n return error instanceof CallError && (code === undefined || error.code === code)\n}\n\nexport interface MextClient<C extends CommandMap<C> = AnyCommands> {\n /** MCP 엔드포인트 */\n readonly url: string\n /** 명령어 호출. 성공 = 핸들러 반환값. 실패 = CallError (취소 = signal.reason) */\n call<K extends keyof C & string>(id: K, ...args: CallArgs<C[K][\"input\"]>): Promise<C[K][\"output\"]>\n /** call 과 같고 CallError 를 던지지 않는다 (취소 · 호출 코드 콜백의 예외는 던진다) */\n safeCall<K extends keyof C & string>(id: K, ...args: CallArgs<C[K][\"input\"]>): Promise<SafeResult<C[K][\"output\"], CallError>>\n /** 이 호출자에게 보이는 네임스페이스 · 명령어 요약 */\n commands(options?: RequestOptions): Promise<CommandList>\n /** 명령어 하나 (ID · 별칭) 의 스키마 · 메타데이터. 없음 = CallError UNKNOWN_COMMAND */\n describe(id: string, options?: RequestOptions): Promise<CommandInfo>\n /** 서버 help 그대로 (target 없음 = 루트). command 노출 = tools/list 로 만든 같은 모양 */\n help(target?: string, options?: RequestOptions): Promise<Help>\n /** 노출 방식 · manifestHash · serverInfo */\n server(options?: RequestOptions): Promise<ServerInfo>\n /** 이미 만든 task 의 조회 · 대기 · 취소 */\n task(taskId: string): TaskHandle\n /** 목록 · 스키마 · 노출 방식 캐시 비움 */\n refresh(): void\n}\n\nexport function createClient<C extends CommandMap<C> = AnyCommands>(options: ClientOptions): MextClient<C> {\n const baseFetch: typeof fetch = options.fetch ?? ((input, init) => fetch(input, init))\n const headersOf = options.headers\n const tokenOf = options.token\n const remote = createRemoteClient({\n url: options.url,\n clientInfo: options.clientInfo ?? { name: \"mext-client\", version: VERSION },\n ...(tokenOf !== undefined ? { token: typeof tokenOf === \"function\" ? tokenOf : () => tokenOf } : {}),\n fetch: (async (input, init) => {\n const extra = typeof headersOf === \"function\" ? await headersOf() : headersOf\n if (!extra) return baseFetch(input, init)\n const headers = new Headers(init?.headers)\n for (const [name, value] of Object.entries(extra)) headers.set(name, value)\n return baseFetch(input, { ...init, headers })\n }) as typeof fetch,\n })\n\n /* 캐시 (메모리). manifestHash 가 바뀐 것을 보면 비운다 */\n let server: Promise<ServerInfo> | undefined\n let listing: Promise<RemoteTool[]> | undefined\n let helps = new Map<string, Promise<Help>>()\n let knownHash: string | undefined\n const refresh = (): void => {\n server = undefined\n listing = undefined\n helps = new Map()\n knownHash = undefined\n }\n const observe = (hash: string | undefined): void => {\n if (hash === undefined) return\n if (knownHash !== undefined && knownHash !== hash) refresh()\n knownHash = hash\n }\n /** 실패한 조회는 캐시에 남기지 않는다 */\n const cached = <T>(get: () => Promise<T> | undefined, set: (p: Promise<T> | undefined) => void, load: () => Promise<T>): Promise<T> => {\n const existing = get()\n if (existing) return existing\n const p = load()\n set(p)\n p.catch(() => {\n if (get() === p) set(undefined)\n })\n return p\n }\n\n const tools = (o: RequestOptions): Promise<RemoteTool[]> =>\n cached(\n () => listing,\n (p) => (listing = p),\n () => remote.listTools(sig(o)),\n )\n\n const loadServer = async (o: RequestOptions): Promise<ServerInfo> => {\n let discover: Record<string, unknown> | undefined\n try {\n discover = await remote.request(\"server/discover\", {}, sig(o))\n } catch (error) {\n // discover 없는 서버 = 도구 이름으로 추정\n if (!(error instanceof RemoteRpcError)) throw error\n }\n const meta = isRecord(discover?._meta) ? discover._meta : {}\n const declared = options.tools ?? meta[TOOLS_META_KEY]\n const exposure: ToolExposure = isExposure(declared) ? declared : exposureOfTools(await tools(o))\n const info: ServerInfo = { tools: exposure, tasks: false }\n if (typeof meta[MANIFEST_HASH_META_KEY] === \"string\") {\n info.manifestHash = meta[MANIFEST_HASH_META_KEY]\n observe(info.manifestHash)\n }\n // 2026-07-28 = 결과 _meta 의 serverInfo (2025 initialize 결과는 최상위)\n const reported = meta[SERVER_INFO_META_KEY] ?? discover?.serverInfo\n const serverInfo = isRecord(reported) ? reported : {}\n if (typeof serverInfo.name === \"string\") info.name = serverInfo.name\n if (typeof serverInfo.version === \"string\") info.version = serverInfo.version\n if (typeof discover?.instructions === \"string\") info.instructions = discover.instructions\n const capabilities = isRecord(discover?.capabilities) ? discover.capabilities : {}\n info.tasks = isRecord(capabilities.extensions) && isRecord(capabilities.extensions[TASKS_EXTENSION_ID])\n return info\n }\n const serverInfo = (o: RequestOptions): Promise<ServerInfo> =>\n cached(\n () => server,\n (p) => (server = p),\n () => loadServer(o),\n )\n const exposureOf = async (o: RequestOptions): Promise<ToolExposure> => options.tools ?? (await serverInfo(o)).tools\n\n /** help 1회 (캐시). command 노출 = tools/list 로 만든 manifest 의 help (help 도구 없음) */\n const help = (target: string, o: RequestOptions): Promise<Help> =>\n cached(\n () => helps.get(target),\n (p) => (p ? helps.set(target, p) : helps.delete(target)),\n async () => {\n const exposure = await exposureOf(o)\n if (exposure === \"command\") return withToolMeta(manifestHelp(manifestFromTools(await tools(o)), target), await tools(o))\n const args = target === \"\" ? { command: \"help\" } : { command: \"help\", args: { target } }\n const result = await remote.callTool(dispatcherTool(exposure === \"split\" ? \"query\" : \"execute\"), args, sig(o))\n observe(metaHash(result))\n if (result.isError === true) throw toolError(result, target)\n const value = result.structuredContent\n if (!isRecord(value) || (value.kind !== \"root\" && value.kind !== \"namespace\" && value.kind !== \"command\")) {\n throw new RemoteTransportError(`${options.url} returned an unexpected help result.`)\n }\n return value as unknown as Help\n },\n )\n\n const describe = async (id: string, o: RequestOptions): Promise<CommandInfo> => {\n const value = await help(id, o)\n const command = value.kind === \"command\" ? value : value.kind === \"namespace\" ? value.command : undefined\n if (!command) {\n throw new CallError(\n { code: \"UNKNOWN_COMMAND\", message: id === \"\" ? \"No command given.\" : `\"${id}\" is a namespace, not a command.`, command: id, suggested: [], usage: id === \"\" ? \"help\" : `help ${id}` },\n id,\n )\n }\n const { kind: _kind, ...info } = command\n return info as unknown as CommandInfo\n }\n\n const commands = async (o: RequestOptions): Promise<CommandList> => {\n const root = await help(\"\", o)\n if (root.kind !== \"root\") throw new RemoteTransportError(`${options.url} returned an unexpected help result.`)\n const namespaces: NamespaceSummary[] = []\n const list: CommandSummary[] = [...(root.commands as unknown as CommandSummary[])]\n // 네임스페이스마다 help 1회 (너비 우선). command 노출 = 캐시된 tools/list 에서 계산 (요청 없음)\n for (let queue = [...root.namespaces]; queue.length > 0; ) {\n const next: typeof queue = []\n for (const ns of queue) namespaces.push(ns)\n for (const value of await Promise.all(queue.map((ns) => help(ns.id, o)))) {\n if (value.kind !== \"namespace\") continue\n list.push(...(value.commands as unknown as CommandSummary[]))\n next.push(...value.namespaces)\n }\n queue = next\n }\n const byId = (a: { id: string }, b: { id: string }): number => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)\n const out: CommandList = { namespaces: namespaces.sort(byId), commands: list.sort(byId) }\n if (root.description !== undefined) out.description = root.description\n return out\n }\n\n /** 명령어를 호출할 도구 · 인자 (노출 방식별, specs/client.md §2.2) */\n const target = async (id: string, input: Record<string, unknown>, o: RequestOptions): Promise<{ tool: RemoteTool; args: Record<string, unknown> }> => {\n const exposure = await exposureOf(o)\n if (exposure === \"command\") return { tool: { name: id }, args: input }\n if (exposure === \"execute\") return { tool: dispatcherTool(\"execute\"), args: { command: id, args: input } }\n const info = await describe(id, o)\n return { tool: dispatcherTool(info.tool ?? (info.readOnly ? \"query\" : \"mutate\")), args: { command: id, args: input } }\n }\n\n const finish = (result: CallToolResult, command: string): unknown => {\n observe(metaHash(result))\n if (result.isError === true) throw toolError(result, command)\n return result.structuredContent === undefined ? (textValue(result) ?? null) : result.structuredContent\n }\n\n /** task 폴링 (client/task.ts awaitTask). tasks/get 을 감싸 상태 변화마다 onTask */\n const waitTask = (created: CallToolResult & { taskId: string }, command: string, o: CallOptions): Promise<CallToolResult> => {\n let last = \"\"\n const notify = (view: Record<string, unknown>): void => {\n const status: TaskStatus = { taskId: created.taskId, status: typeof view.status === \"string\" ? view.status : \"working\" }\n if (typeof view.statusMessage === \"string\") status.statusMessage = view.statusMessage\n const key = `${status.status}\\n${status.statusMessage ?? \"\"}`\n if (key === last) return\n last = key\n o.onTask?.(status)\n }\n notify(created)\n const watched: RemoteClient = {\n ...remote,\n getTask: async (taskId, opts) => {\n const view = await remote.getTask(taskId, opts)\n notify(view)\n return view\n },\n }\n return awaitTask(created, {\n client: watched,\n call: (fn) => fn({ signal: o.signal ?? NEVER }),\n signal: o.signal ?? NEVER,\n onInputRequired: inputHandler(command, o),\n onStatus: (message) => o.onProgress?.({ message }),\n })\n }\n\n const run = async (id: string, input: Record<string, unknown>, o: CallOptions): Promise<unknown> => {\n try {\n const { tool, args } = await target(id, input, o)\n const callOptions: CallToolOptions = { ...sig(o), onInputRequired: inputHandler(id, o) }\n if (o.confirmed === true) callOptions.meta = { [APPROVAL_META_KEY]: { confirmed: true } }\n if (o.onProgress) {\n const onProgress = o.onProgress\n callOptions.progressToken = PROGRESS_TOKEN\n callOptions.onNotification = (method, params) => {\n if (method !== \"notifications/progress\" || typeof params.progress !== \"number\") return\n onProgress({\n progress: params.progress,\n ...(typeof params.total === \"number\" ? { total: params.total } : {}),\n ...(typeof params.message === \"string\" ? { message: params.message } : {}),\n })\n }\n }\n let result: CallToolResult\n try {\n result = await remote.callTool(tool, args, callOptions)\n } catch (error) {\n // command 노출: 없는 도구 = JSON-RPC 오류. 별칭이면 정식 ID 로 다시, 없는 ID 면 UNKNOWN_COMMAND (dispatcher 와 같은 본문)\n const canonical = error instanceof RemoteRpcError && tool.name === id ? await canonicalId(id, o) : undefined\n if (canonical === undefined) throw error\n result = await remote.callTool({ name: canonical }, args, callOptions)\n }\n if (isTaskResult(result)) result = await waitTask(result, id, o)\n return finish(result, id)\n } catch (error) {\n throw normalize(error, id, o.signal)\n }\n }\n\n /** command 노출에서 실패한 도구 이름: 별칭 → 정식 ID, 정식 ID 그대로 = undefined (원래 오류), 없는 ID = MextError UNKNOWN_COMMAND */\n const canonicalId = async (id: string, o: RequestOptions): Promise<string | undefined> => {\n if ((await exposureOf(o)) !== \"command\") return undefined\n listing = undefined\n helps = new Map()\n const found = manifestHelp(manifestFromTools(await tools(o)), id)\n const command = found.kind === \"command\" ? found : undefined\n return command !== undefined && command.id !== id ? command.id : undefined\n }\n\n const taskHandle = (taskId: string): TaskHandle => ({\n taskId,\n async get(o = {}) {\n try {\n return taskStatus(taskId, await remote.getTask(taskId, sig(o)))\n } catch (error) {\n throw normalize(error, \"\", o.signal)\n }\n },\n async wait(o = {}) {\n try {\n const view = await remote.getTask(taskId, sig(o))\n return finish(await waitTask({ ...view, taskId }, \"\", o), \"\")\n } catch (error) {\n throw normalize(error, \"\", o.signal)\n }\n },\n async cancel(o = {}) {\n try {\n await remote.cancelTask(taskId, sig(o))\n } catch (error) {\n throw normalize(error, \"\", o.signal)\n }\n },\n })\n\n const guarded = async <T>(command: string, o: RequestOptions, fn: () => Promise<T>): Promise<T> => {\n try {\n return await fn()\n } catch (error) {\n throw normalize(error, command, o.signal)\n }\n }\n\n const call = (id: string, input?: unknown, o?: CallOptions): Promise<unknown> =>\n run(id, (input ?? {}) as Record<string, unknown>, o ?? {})\n\n return {\n url: options.url,\n call: call as MextClient<C>[\"call\"],\n safeCall: (async (id: string, input?: unknown, o?: CallOptions) => {\n try {\n return { ok: true, value: await call(id, input, o) }\n } catch (error) {\n if (error instanceof CallError) return { ok: false, error }\n throw error\n }\n }) as MextClient<C>[\"safeCall\"],\n commands: (o = {}) => guarded(\"\", o, () => commands(o)),\n describe: (id, o = {}) => guarded(id, o, () => describe(id, o)),\n help: (t = \"\", o = {}) => guarded(t, o, () => help(t.trim(), o)),\n server: (o = {}) => guarded(\"\", o, () => serverInfo(o)),\n task: taskHandle,\n refresh,\n }\n}\n\n/* 입력 요청 (MRTR · task input_required) */\n\n/**\n * InputRequiredResult → inputResponses. confirmed = confirm 요청에 묻지 않고 승인. 그 외 = onInput.\n * onInput 없음 · 모르는 요청 = CallError INPUT_UNAVAILABLE (호출은 실행되지 않았다)\n */\nfunction inputHandler(command: string, o: CallOptions): NonNullable<CallToolOptions[\"onInputRequired\"]> {\n return async (required: InputRequired): Promise<InputResponses> => {\n const out: InputResponses = {}\n for (const [key, raw] of Object.entries(required.inputRequests ?? {})) {\n const info = describeInput(key, raw, command)\n if (info === undefined) throw inputUnavailable(command, required, `unsupported input request ${raw.method}`)\n const confirmKey = info.kind === \"confirm\" ? confirmField(info.schema ?? {}) : undefined\n if (confirmKey !== undefined && o.confirmed === true) {\n out[key] = { action: \"accept\", content: { [confirmKey]: true } }\n continue\n }\n if (!o.onInput) throw inputUnavailable(command, required, `asked \"${info.message}\"`)\n const answer: InputAnswer = await o.onInput(info)\n if (answer === true) out[key] = confirmKey !== undefined ? { action: \"accept\", content: { [confirmKey]: true } } : { action: \"accept\" }\n else if (answer === false) out[key] = { action: \"decline\" }\n else out[key] = answer\n }\n return out\n }\n}\n\nfunction describeInput(key: string, raw: InputRequestObject, command: string): InputRequestInfo | undefined {\n if (raw.method !== \"elicitation/create\") return undefined\n const params = isRecord(raw.params) ? raw.params : {}\n const message = typeof params.message === \"string\" ? params.message : \"Input required\"\n if (params.mode === \"url\") {\n if (typeof params.url !== \"string\") return undefined\n return { key, kind: \"url\", message, url: params.url, command, raw }\n }\n const schema = isRecord(params.requestedSchema) ? params.requestedSchema : { type: \"object\", properties: {} }\n return { key, kind: confirmField(schema) !== undefined ? \"confirm\" : \"form\", message, schema, command, raw }\n}\n\n/** requestedSchema 의 속성이 boolean 하나면 그 키 (확인 요청. 고객 CLI 와 같은 판정) */\nfunction confirmField(schema: Record<string, unknown>): string | undefined {\n const props = schema.properties\n if (!isRecord(props)) return undefined\n const keys = Object.keys(props)\n if (keys.length !== 1) return undefined\n const p = props[keys[0]!]\n return isRecord(p) && p.type === \"boolean\" ? keys[0] : undefined\n}\n\nfunction inputUnavailable(command: string, required: InputRequired, why: string): CallError {\n return new CallError(\n {\n code: \"INPUT_UNAVAILABLE\",\n message: `${command || \"The task\"} ${why}, but this call has no handler for it. Pass onInput (or confirmed: true for confirmations).`,\n command,\n requests: required.inputRequests ?? {},\n },\n command,\n )\n}\n\n/* 결과 · 오류 */\n\n/** isError 결과 → CallError. 본문 = structuredContent.error (없으면 text 로 EXECUTION_FAILED) */\nfunction toolError(result: CallToolResult, command: string): CallError {\n const sc = result.structuredContent\n const body = isRecord(sc) && isRecord(sc.error) ? sc.error : undefined\n if (body && typeof body.code === \"string\") {\n return new CallError({ ...body, code: body.code, message: typeof body.message === \"string\" ? body.message : body.code }, command)\n }\n return new CallError({ code: \"EXECUTION_FAILED\", message: textValue(result) ?? \"Remote command failed.\" }, command)\n}\n\n/** 원격 호출 계층의 오류 → CallError. 취소 = signal.reason. 그 외 (호출 코드 콜백의 예외 등) = 그대로 */\nfunction normalize(error: unknown, command: string, signal: AbortSignal | undefined): unknown {\n if (signal?.aborted) return signal.reason\n if (error instanceof CallError) return error\n if (error instanceof MextError) return new CallError(error.toJSON(), command)\n if (error instanceof RemoteUnauthorizedError) {\n const data = isRecord(error.data) ? error.data : {}\n const reason = data.reason === \"invalid_token\" || error.challenge.error === \"invalid_token\" ? \"invalid_token\" : \"missing_token\"\n return new CallError({ ...data, code: \"UNAUTHENTICATED\", message: error.message, reason }, command, { status: 401, cause: error })\n }\n if (error instanceof RemoteInputRequiredError) {\n return new CallError({ code: \"INPUT_UNAVAILABLE\", message: error.message, command, requests: error.request.inputRequests ?? {} }, command, { cause: error })\n }\n if (error instanceof RemoteRpcError) {\n const rpc = { code: error.code, status: error.status, data: error.data }\n return new CallError({ code: \"REMOTE_ERROR\", message: error.message, rpc }, command, { status: error.status, cause: error })\n }\n if (error instanceof RemoteTaskError) {\n const task = { taskId: error.taskId, status: error.status, ...(error.error ? { error: error.error } : {}) }\n return new CallError({ code: \"REMOTE_ERROR\", message: error.message, task }, command, { cause: error })\n }\n if (error instanceof RemoteTransportError) return new CallError({ code: \"REMOTE_ERROR\", message: error.message }, command, { cause: error })\n return error\n}\n\nfunction textValue(result: CallToolResult): string | undefined {\n const texts = (result.content ?? []).flatMap((c) => (isRecord(c) && c.type === \"text\" && typeof c.text === \"string\" ? [c.text] : []))\n return texts.length > 0 ? texts.join(\"\\n\") : undefined\n}\n\nfunction metaHash(result: CallToolResult): string | undefined {\n const value = isRecord(result._meta) ? result._meta[MANIFEST_HASH_META_KEY] : undefined\n return typeof value === \"string\" ? value : undefined\n}\n\nfunction taskStatus(taskId: string, view: Record<string, unknown>): TaskStatus {\n const status: TaskStatus = { taskId, status: typeof view.status === \"string\" ? view.status : \"working\" }\n if (typeof view.statusMessage === \"string\") status.statusMessage = view.statusMessage\n return status\n}\n\n/* 노출 방식 */\n\nfunction isExposure(value: unknown): value is ToolExposure {\n return value === \"execute\" || value === \"split\" || value === \"command\"\n}\n\n/** server/discover 가 없는 서버: 도구 이름으로 추정 */\nfunction exposureOfTools(tools: readonly RemoteTool[]): ToolExposure {\n const names = new Set(tools.map((t) => t.name))\n if (names.has(\"execute\")) return \"execute\"\n if (names.has(\"query\") && names.has(\"mutate\")) return \"split\"\n return \"command\"\n}\n\nfunction dispatcherTool(name: string): RemoteTool {\n return { name, inputSchema: DISPATCHER_INPUT_SCHEMA }\n}\n\n/**\n * command 노출의 help 에 도구 _meta[\"dev.mext/command\"] 의 모르는 필드를 더한다 (manifestFromTools 는 아는 필드만 옮긴다).\n * 서버가 client 보다 새 버전일 때 메타데이터 (예: needsApproval) 가 사라지지 않게\n */\nfunction withToolMeta(value: Help, tools: readonly RemoteTool[]): Help {\n const extra = (id: string): Record<string, unknown> => {\n const meta = tools.find((t) => t.name === id)?._meta\n return isRecord(meta) && isRecord(meta[COMMAND_META_KEY]) ? meta[COMMAND_META_KEY] : {}\n }\n const merge = <T extends { id: string }>(item: T, keys?: readonly string[]): T => {\n const meta = extra(item.id)\n const picked = keys ? Object.fromEntries(Object.entries(meta).filter(([k]) => keys.includes(k))) : meta\n return { ...picked, ...item }\n }\n if (value.kind === \"command\") return merge(value)\n const commands = value.commands.map((c) => merge(c, SUMMARY_EXTRA_KEYS))\n if (value.kind === \"namespace\" && value.command) return { ...value, commands, command: merge(value.command) }\n return { ...value, commands }\n}\n\n/** 요약 (목록) 에 싣는 추가 메타데이터 */\nconst SUMMARY_EXTRA_KEYS: readonly string[] = [\"needsApproval\"]\n\nconst NEVER: AbortSignal = new AbortController().signal\n\nfunction sig(o: RequestOptions): { signal?: AbortSignal } {\n return o.signal ? { signal: o.signal } : {}\n}\n"]}