@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.
- package/dist/approval.d.ts +33 -0
- package/dist/approval.js +36 -0
- package/dist/approval.js.map +1 -0
- package/dist/audit.d.ts +123 -0
- package/dist/audit.js +221 -0
- package/dist/audit.js.map +1 -0
- package/dist/build-cli.d.ts +1 -0
- package/dist/build-cli.js.map +1 -1
- package/dist/build.d.ts +2 -0
- package/dist/build.js +30 -3
- package/dist/build.js.map +1 -1
- package/dist/caller.d.ts +53 -0
- package/dist/caller.js +51 -0
- package/dist/caller.js.map +1 -0
- package/dist/cli/build.js +4 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev-audit.d.ts +25 -0
- package/dist/cli/dev-audit.js +84 -0
- package/dist/cli/dev-audit.js.map +1 -0
- package/dist/cli/dev-lock.d.ts +3 -1
- package/dist/cli/dev-lock.js +12 -5
- package/dist/cli/dev-lock.js.map +1 -1
- package/dist/cli/dev-server.d.ts +9 -0
- package/dist/cli/dev-server.js +24 -1
- package/dist/cli/dev-server.js.map +1 -1
- package/dist/cli/dev-tap.d.ts +20 -0
- package/dist/cli/dev-tap.js +70 -0
- package/dist/cli/dev-tap.js.map +1 -0
- package/dist/cli/dev.js +16 -4
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/help.js +2 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/inspect.d.ts +7 -0
- package/dist/cli/inspect.js +699 -0
- package/dist/cli/inspect.js.map +1 -0
- package/dist/cli/main.js +8 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/output.d.ts +1 -1
- package/dist/cli/output.js +3 -2
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/run.js +28 -4
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/types.d.ts +9 -0
- package/dist/cli/types.js +77 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/client/index.d.ts +10 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/manifest.js +6 -2
- package/dist/client/manifest.js.map +1 -1
- package/dist/client/runner.js +37 -3
- package/dist/client/runner.js.map +1 -1
- package/dist/client/typed.d.ts +54 -0
- package/dist/client/typed.js +490 -0
- package/dist/client/typed.js.map +1 -0
- package/dist/client/types.d.ts +196 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/command.d.ts +61 -5
- package/dist/command.js +42 -1
- package/dist/command.js.map +1 -1
- package/dist/config.d.ts +42 -10
- package/dist/config.js +32 -7
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +21 -3
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -1
- package/dist/expose.d.ts +9 -0
- package/dist/expose.js +52 -0
- package/dist/expose.js.map +1 -0
- package/dist/index.d.ts +15 -6
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/inspect/agent.d.ts +104 -0
- package/dist/inspect/agent.js +125 -0
- package/dist/inspect/agent.js.map +1 -0
- package/dist/inspect/audit.d.ts +46 -0
- package/dist/inspect/audit.js +133 -0
- package/dist/inspect/audit.js.map +1 -0
- package/dist/inspect/compare.d.ts +12 -0
- package/dist/inspect/compare.js +31 -0
- package/dist/inspect/compare.js.map +1 -0
- package/dist/inspect/index.d.ts +17 -0
- package/dist/inspect/index.js +12 -0
- package/dist/inspect/index.js.map +1 -0
- package/dist/inspect/inspector.d.ts +168 -0
- package/dist/inspect/inspector.js +392 -0
- package/dist/inspect/inspector.js.map +1 -0
- package/dist/inspect/profiles.d.ts +95 -0
- package/dist/inspect/profiles.js +235 -0
- package/dist/inspect/profiles.js.map +1 -0
- package/dist/inspect/scenario.d.ts +126 -0
- package/dist/inspect/scenario.js +555 -0
- package/dist/inspect/scenario.js.map +1 -0
- package/dist/inspect/ui-server.d.ts +31 -0
- package/dist/inspect/ui-server.js +378 -0
- package/dist/inspect/ui-server.js.map +1 -0
- package/dist/inspect/ui.html +917 -0
- package/dist/instrumentation.d.ts +13 -2
- package/dist/instrumentation.js +11 -1
- package/dist/instrumentation.js.map +1 -1
- package/dist/invoke.d.ts +32 -5
- package/dist/invoke.js +150 -16
- package/dist/invoke.js.map +1 -1
- package/dist/manifest.d.ts +13 -2
- package/dist/manifest.js +5 -1
- package/dist/manifest.js.map +1 -1
- package/dist/mcp/constants.d.ts +5 -0
- package/dist/mcp/constants.js +5 -0
- package/dist/mcp/constants.js.map +1 -1
- package/dist/mcp/dispatch.d.ts +1 -1
- package/dist/mcp/dispatch.js +14 -3
- package/dist/mcp/dispatch.js.map +1 -1
- package/dist/mcp/help.d.ts +2 -0
- package/dist/mcp/help.js +6 -1
- package/dist/mcp/help.js.map +1 -1
- package/dist/mcp/http.d.ts +16 -2
- package/dist/mcp/http.js +76 -7
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.d.ts +12 -1
- package/dist/mcp/server.js +63 -17
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts +4 -0
- package/dist/mcp/stdio.js +3 -0
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/mcp/tasks.d.ts +3 -1
- package/dist/mcp/tasks.js +6 -3
- package/dist/mcp/tasks.js.map +1 -1
- package/dist/principal.d.ts +22 -0
- package/dist/principal.js +29 -0
- package/dist/principal.js.map +1 -1
- package/dist/registry.d.ts +5 -0
- package/dist/registry.js +21 -0
- package/dist/registry.js.map +1 -1
- package/dist/remote/client.d.ts +2 -0
- package/dist/remote/client.js +3 -2
- package/dist/remote/client.js.map +1 -1
- package/dist/remote/oauth.d.ts +1 -1
- package/dist/remote/oauth.js +1 -1
- package/dist/remote/oauth.js.map +1 -1
- package/dist/start.js +6 -2
- package/dist/start.js.map +1 -1
- package/dist/suggest.js +1 -1
- package/dist/suggest.js.map +1 -1
- package/dist/typegen.d.ts +27 -0
- package/dist/typegen.js +62 -0
- package/dist/typegen.js.map +1 -0
- package/dist/version-constant.d.ts +5 -0
- package/dist/version-constant.js +6 -0
- package/dist/version-constant.js.map +1 -0
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -2
- package/dist/version.js.map +1 -1
- package/package.json +12 -2
package/dist/manifest.d.ts
CHANGED
|
@@ -13,7 +13,10 @@ export interface ManifestCommand {
|
|
|
13
13
|
file?: string;
|
|
14
14
|
readOnly: boolean;
|
|
15
15
|
destructive: boolean;
|
|
16
|
+
/** 항상 승인 필요 (requiresConfirmation: true · needsApproval: true, §4 승인) */
|
|
16
17
|
requiresConfirmation: boolean;
|
|
18
|
+
/** 승인이 조건식 (needsApproval 함수) 일 때만: 호출에 따라 승인이 필요할 수 있다. 없음 = 조건식 아님 */
|
|
19
|
+
needsApproval?: "conditional";
|
|
17
20
|
scopes: string[];
|
|
18
21
|
positional: string[];
|
|
19
22
|
examples: unknown[];
|
|
@@ -48,6 +51,11 @@ export declare function generateManifest(dir: string): Promise<Manifest>;
|
|
|
48
51
|
export interface BuildManifestCommand extends ManifestCommand {
|
|
49
52
|
/** .mext/ 기준 상대 경로 (posix). commands/users/get.ts → "commands/users/get.js". default export = defineCommand 결과 */
|
|
50
53
|
module: string;
|
|
54
|
+
/**
|
|
55
|
+
* 표면별 노출 (defineCommand expose, §4). 없음 = 모든 표면. 서버 (mext start · handler.js · 로컬 bin) 가 실행 시 판정.
|
|
56
|
+
* help · tools/list · 고객 CLI 내장 manifest 에는 싣지 않는다
|
|
57
|
+
*/
|
|
58
|
+
expose?: Record<string, boolean>;
|
|
51
59
|
}
|
|
52
60
|
/** mext build 의 .mext/manifest.json 자원: 자원 메타데이터 + 번들 모듈 경로 */
|
|
53
61
|
export interface BuildManifestResource extends ManifestResource {
|
|
@@ -68,7 +76,10 @@ export interface BuildManifest extends Omit<Manifest, "commands"> {
|
|
|
68
76
|
mextVersion: string;
|
|
69
77
|
/** 빌드 식별자 (D3: mextVersion · manifestHash · 번들 코드의 sha256 앞 16자, 같은 입력 = 같은 값) */
|
|
70
78
|
buildId: string;
|
|
71
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* manifestHash(commands, { resources: 자원 uri, prompts: 이름 · argsSchema }). 전체 명령어 기준.
|
|
81
|
+
* expose 로 숨긴 명령어가 있는 호출자에게는 서버가 그 보기의 값을 계산해 보낸다 (§4)
|
|
82
|
+
*/
|
|
72
83
|
manifestHash: string;
|
|
73
84
|
/** MCP 도구 노출 방식 (mext.config.ts tools, 기본 execute). 고객 CLI 번들 형태의 호출 방식 (§12.2) */
|
|
74
85
|
tools: ToolExposure;
|
|
@@ -98,7 +109,7 @@ export interface BuildManifestRoute {
|
|
|
98
109
|
}
|
|
99
110
|
/**
|
|
100
111
|
* 명령어 계약의 지문: ID · 별칭 · positional · 입력 스키마 · 안전성 메타데이터 (readOnly · destructive ·
|
|
101
|
-
* requiresConfirmation · scopes) 의 정규화 JSON (키 정렬, ID 순) sha256 hex.
|
|
112
|
+
* requiresConfirmation · needsApproval (조건식일 때만) · scopes) 의 정규화 JSON (키 정렬, ID 순) sha256 hex.
|
|
102
113
|
* 설명 · examples · outputSchema · task · 파일 경로는 제외 (클라이언트의 help 캐시 · 플래그 파싱에 영향 없음).
|
|
103
114
|
* extra.resources = 자원 uri (고정 URI · 템플릿 원문, §12.3), extra.prompts = 프롬프트 이름 · args JSON Schema (§12.3).
|
|
104
115
|
* 둘 다 없거나 비면 명령어만의 값과 같다.
|
package/dist/manifest.js
CHANGED
|
@@ -16,6 +16,8 @@ export function describeCommand(entry) {
|
|
|
16
16
|
examples: [...c.examples],
|
|
17
17
|
inputSchema: entry.inputSchema,
|
|
18
18
|
};
|
|
19
|
+
if (c.needsApproval !== undefined)
|
|
20
|
+
out.needsApproval = "conditional";
|
|
19
21
|
if (entry.file !== undefined)
|
|
20
22
|
out.file = entry.file;
|
|
21
23
|
if (entry.outputSchema !== undefined)
|
|
@@ -46,7 +48,7 @@ export async function generateManifest(dir) {
|
|
|
46
48
|
}
|
|
47
49
|
/**
|
|
48
50
|
* 명령어 계약의 지문: ID · 별칭 · positional · 입력 스키마 · 안전성 메타데이터 (readOnly · destructive ·
|
|
49
|
-
* requiresConfirmation · scopes) 의 정규화 JSON (키 정렬, ID 순) sha256 hex.
|
|
51
|
+
* requiresConfirmation · needsApproval (조건식일 때만) · scopes) 의 정규화 JSON (키 정렬, ID 순) sha256 hex.
|
|
50
52
|
* 설명 · examples · outputSchema · task · 파일 경로는 제외 (클라이언트의 help 캐시 · 플래그 파싱에 영향 없음).
|
|
51
53
|
* extra.resources = 자원 uri (고정 URI · 템플릿 원문, §12.3), extra.prompts = 프롬프트 이름 · args JSON Schema (§12.3).
|
|
52
54
|
* 둘 다 없거나 비면 명령어만의 값과 같다.
|
|
@@ -63,6 +65,8 @@ export function manifestHash(commands, extra = {}) {
|
|
|
63
65
|
readOnly: c.readOnly,
|
|
64
66
|
destructive: c.destructive,
|
|
65
67
|
requiresConfirmation: c.requiresConfirmation,
|
|
68
|
+
// 조건식일 때만 (없으면 속성 생략 = 기존 값과 같다)
|
|
69
|
+
needsApproval: c.needsApproval,
|
|
66
70
|
scopes: [...c.scopes].sort(),
|
|
67
71
|
}));
|
|
68
72
|
const resources = [...(extra.resources ?? [])].sort();
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\"\nimport type { ToolExposure } from \"./mcp/dispatch.ts\"\nimport type { JsonSchema, RegisteredCommand, Registry } from \"./registry.ts\"\nimport type { ManifestPrompt } from \"./prompt.ts\"\nimport type { ManifestResource } from \"./resource.ts\"\nimport type { RouteMethod } from \"./route.ts\"\nimport { loadRegistry } from \"./scan.ts\"\n\nexport const MANIFEST_SCHEMA_VERSION = 1\n\nexport interface ManifestCommand {\n id: string\n description: string\n /** 별칭 전체 ID */\n aliases: string[]\n /** commands/ 기준 상대 경로 (posix) */\n file?: string\n readOnly: boolean\n destructive: boolean\n requiresConfirmation: boolean\n scopes: string[]\n positional: string[]\n examples: unknown[]\n /** JSON Schema 2020-12 */\n inputSchema: JsonSchema\n outputSchema?: JsonSchema\n /** task 명령어 (§12.6). 없음 = 동기 명령어 */\n task?: { ttlMs: number }\n}\n\nexport interface ManifestNamespace {\n id: string\n /** _index.md 내용 */\n description?: string\n}\n\nexport interface Manifest {\n schemaVersion: typeof MANIFEST_SCHEMA_VERSION\n /** commands/_index.md 내용 */\n description?: string\n /** 루트 제외, ID 순 */\n namespaces: ManifestNamespace[]\n /** ID 순 */\n commands: ManifestCommand[]\n}\n\n/** 명령어 하나의 메타데이터 (manifest · help 공통) */\nexport function describeCommand(entry: RegisteredCommand): ManifestCommand {\n const c = entry.command\n const out: ManifestCommand = {\n id: entry.id,\n description: c.description,\n aliases: [...entry.aliases],\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n scopes: [...c.scopes],\n positional: [...c.positional],\n examples: [...c.examples],\n inputSchema: entry.inputSchema,\n }\n if (entry.file !== undefined) out.file = entry.file\n if (entry.outputSchema !== undefined) out.outputSchema = entry.outputSchema\n if (c.task !== undefined) out.task = { ttlMs: c.task.ttlMs }\n return out\n}\n\nexport function buildManifest(registry: Registry): Manifest {\n const manifest: Manifest = {\n schemaVersion: MANIFEST_SCHEMA_VERSION,\n namespaces: [],\n commands: [...registry.commands.values()].map(describeCommand),\n }\n for (const ns of registry.namespaces.values()) {\n if (ns.id === \"\") {\n if (ns.description !== undefined) manifest.description = ns.description\n continue\n }\n manifest.namespaces.push(ns.description === undefined ? { id: ns.id } : { id: ns.id, description: ns.description })\n }\n return manifest\n}\n\n/** 빌드 시 manifest 생성: commands/ 스캔 → Manifest (JSON 직렬화 가능) */\nexport async function generateManifest(dir: string): Promise<Manifest> {\n return buildManifest(await loadRegistry(dir))\n}\n\n/** mext build 의 .mext/manifest.json 명령어: Manifest 명령어 + 번들 모듈 경로 */\nexport interface BuildManifestCommand extends ManifestCommand {\n /** .mext/ 기준 상대 경로 (posix). commands/users/get.ts → \"commands/users/get.js\". default export = defineCommand 결과 */\n module: string\n}\n\n/** mext build 의 .mext/manifest.json 자원: 자원 메타데이터 + 번들 모듈 경로 */\nexport interface BuildManifestResource extends ManifestResource {\n /** .mext/ 기준 상대 경로 (posix). resources/users/profile.ts → \"resources/users/profile.js\". default export = defineResource 결과 */\n module: string\n}\n\n/** mext build 의 .mext/manifest.json 프롬프트: 프롬프트 메타데이터 + 번들 모듈 경로 */\nexport interface BuildManifestPrompt extends ManifestPrompt {\n /** .mext/ 기준 상대 경로 (posix). prompts/github/review.ts → \"prompts/github/review.js\". default export = definePrompt 결과 */\n module: string\n}\n\n/**\n * .mext/manifest.json (mext build 산출, mext start · handler.js 가 읽는다).\n * namespaces · description = Manifest 와 같음\n */\nexport interface BuildManifest extends Omit<Manifest, \"commands\"> {\n /** 빌드한 @obov/mext 버전. 실행 시 설치된 버전과 다르면 시작 오류 */\n mextVersion: string\n /** 빌드 식별자 (D3: mextVersion · manifestHash · 번들 코드의 sha256 앞 16자, 같은 입력 = 같은 값) */\n buildId: string\n /** manifestHash(commands, { resources: 자원 uri, prompts: 이름 · argsSchema }) */\n manifestHash: string\n /** MCP 도구 노출 방식 (mext.config.ts tools, 기본 execute). 고객 CLI 번들 형태의 호출 방식 (§12.2) */\n tools: ToolExposure\n /** mext.config.ts 번들 (.mext/ 기준). 설정 파일이 없으면 생략 */\n config?: string\n /** instrumentation.ts 번들 (.mext/ 기준). 없으면 생략 */\n instrumentation?: string\n /** ID 순 */\n commands: BuildManifestCommand[]\n /** MCP 자원 (§12.3). uri 순. 자원이 없으면 생략 */\n resources?: BuildManifestResource[]\n /** MCP 프롬프트 (§12.3). 이름 순. 프롬프트가 없으면 생략 */\n prompts?: BuildManifestPrompt[]\n /** routes/ (§12.4). 경로 순. route 가 없으면 생략. manifestHash 에 포함하지 않는다 (명령어 계약 아님) */\n routes?: BuildManifestRoute[]\n}\n\n/** .mext/manifest.json 의 route */\nexport interface BuildManifestRoute {\n /** URL 경로 패턴 (\"/items/[id]\") */\n path: string\n /** routes/ 기준 상대 경로 (posix) */\n file: string\n /** export 한 메서드. 그 외 = 405 (모듈 import 없음) */\n methods: RouteMethod[]\n /** .mext/ 기준 상대 경로. routes/items/[id].ts → \"routes/items/[id].js\" */\n module: string\n}\n\n/**\n * 명령어 계약의 지문: ID · 별칭 · positional · 입력 스키마 · 안전성 메타데이터 (readOnly · destructive ·\n * requiresConfirmation · scopes) 의 정규화 JSON (키 정렬, ID 순) sha256 hex.\n * 설명 · examples · outputSchema · task · 파일 경로는 제외 (클라이언트의 help 캐시 · 플래그 파싱에 영향 없음).\n * extra.resources = 자원 uri (고정 URI · 템플릿 원문, §12.3), extra.prompts = 프롬프트 이름 · args JSON Schema (§12.3).\n * 둘 다 없거나 비면 명령어만의 값과 같다.\n * 빌드 manifest · 서버 (_meta[\"dev.mext/manifestHash\"]) · 클라이언트가 같은 함수로 계산한다\n */\nexport function manifestHash(\n commands: readonly ManifestCommand[],\n extra: { resources?: readonly string[]; prompts?: readonly { name: string; argsSchema?: JsonSchema | undefined }[] } = {},\n): string {\n const normalized = [...commands]\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))\n .map((c) => ({\n id: c.id,\n aliases: [...c.aliases].sort(),\n positional: c.positional,\n inputSchema: c.inputSchema,\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n scopes: [...c.scopes].sort(),\n }))\n const resources = [...(extra.resources ?? [])].sort()\n const prompts = [...(extra.prompts ?? [])]\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))\n .map((p) => ({ name: p.name, argsSchema: p.argsSchema }))\n const value =\n resources.length > 0 || prompts.length > 0\n ? { commands: normalized, ...(resources.length > 0 ? { resources } : {}), ...(prompts.length > 0 ? { prompts } : {}) }\n : normalized\n return createHash(\"sha256\").update(canonicalJson(value)).digest(\"hex\")\n}\n\n/** 키 정렬 JSON (배열 순서 유지, undefined 속성 생략) */\nfunction canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"null\"\n if (Array.isArray(value)) return `[${value.map((v) => (v === undefined ? \"null\" : canonicalJson(v))).join(\",\")}]`\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(\",\")}}`\n}\n"]}
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\"\nimport type { ToolExposure } from \"./mcp/dispatch.ts\"\nimport type { JsonSchema, RegisteredCommand, Registry } from \"./registry.ts\"\nimport type { ManifestPrompt } from \"./prompt.ts\"\nimport type { ManifestResource } from \"./resource.ts\"\nimport type { RouteMethod } from \"./route.ts\"\nimport { loadRegistry } from \"./scan.ts\"\n\nexport const MANIFEST_SCHEMA_VERSION = 1\n\nexport interface ManifestCommand {\n id: string\n description: string\n /** 별칭 전체 ID */\n aliases: string[]\n /** commands/ 기준 상대 경로 (posix) */\n file?: string\n readOnly: boolean\n destructive: boolean\n /** 항상 승인 필요 (requiresConfirmation: true · needsApproval: true, §4 승인) */\n requiresConfirmation: boolean\n /** 승인이 조건식 (needsApproval 함수) 일 때만: 호출에 따라 승인이 필요할 수 있다. 없음 = 조건식 아님 */\n needsApproval?: \"conditional\"\n scopes: string[]\n positional: string[]\n examples: unknown[]\n /** JSON Schema 2020-12 */\n inputSchema: JsonSchema\n outputSchema?: JsonSchema\n /** task 명령어 (§12.6). 없음 = 동기 명령어 */\n task?: { ttlMs: number }\n}\n\nexport interface ManifestNamespace {\n id: string\n /** _index.md 내용 */\n description?: string\n}\n\nexport interface Manifest {\n schemaVersion: typeof MANIFEST_SCHEMA_VERSION\n /** commands/_index.md 내용 */\n description?: string\n /** 루트 제외, ID 순 */\n namespaces: ManifestNamespace[]\n /** ID 순 */\n commands: ManifestCommand[]\n}\n\n/** 명령어 하나의 메타데이터 (manifest · help 공통) */\nexport function describeCommand(entry: RegisteredCommand): ManifestCommand {\n const c = entry.command\n const out: ManifestCommand = {\n id: entry.id,\n description: c.description,\n aliases: [...entry.aliases],\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n scopes: [...c.scopes],\n positional: [...c.positional],\n examples: [...c.examples],\n inputSchema: entry.inputSchema,\n }\n if (c.needsApproval !== undefined) out.needsApproval = \"conditional\"\n if (entry.file !== undefined) out.file = entry.file\n if (entry.outputSchema !== undefined) out.outputSchema = entry.outputSchema\n if (c.task !== undefined) out.task = { ttlMs: c.task.ttlMs }\n return out\n}\n\nexport function buildManifest(registry: Registry): Manifest {\n const manifest: Manifest = {\n schemaVersion: MANIFEST_SCHEMA_VERSION,\n namespaces: [],\n commands: [...registry.commands.values()].map(describeCommand),\n }\n for (const ns of registry.namespaces.values()) {\n if (ns.id === \"\") {\n if (ns.description !== undefined) manifest.description = ns.description\n continue\n }\n manifest.namespaces.push(ns.description === undefined ? { id: ns.id } : { id: ns.id, description: ns.description })\n }\n return manifest\n}\n\n/** 빌드 시 manifest 생성: commands/ 스캔 → Manifest (JSON 직렬화 가능) */\nexport async function generateManifest(dir: string): Promise<Manifest> {\n return buildManifest(await loadRegistry(dir))\n}\n\n/** mext build 의 .mext/manifest.json 명령어: Manifest 명령어 + 번들 모듈 경로 */\nexport interface BuildManifestCommand extends ManifestCommand {\n /** .mext/ 기준 상대 경로 (posix). commands/users/get.ts → \"commands/users/get.js\". default export = defineCommand 결과 */\n module: string\n /**\n * 표면별 노출 (defineCommand expose, §4). 없음 = 모든 표면. 서버 (mext start · handler.js · 로컬 bin) 가 실행 시 판정.\n * help · tools/list · 고객 CLI 내장 manifest 에는 싣지 않는다\n */\n expose?: Record<string, boolean>\n}\n\n/** mext build 의 .mext/manifest.json 자원: 자원 메타데이터 + 번들 모듈 경로 */\nexport interface BuildManifestResource extends ManifestResource {\n /** .mext/ 기준 상대 경로 (posix). resources/users/profile.ts → \"resources/users/profile.js\". default export = defineResource 결과 */\n module: string\n}\n\n/** mext build 의 .mext/manifest.json 프롬프트: 프롬프트 메타데이터 + 번들 모듈 경로 */\nexport interface BuildManifestPrompt extends ManifestPrompt {\n /** .mext/ 기준 상대 경로 (posix). prompts/github/review.ts → \"prompts/github/review.js\". default export = definePrompt 결과 */\n module: string\n}\n\n/**\n * .mext/manifest.json (mext build 산출, mext start · handler.js 가 읽는다).\n * namespaces · description = Manifest 와 같음\n */\nexport interface BuildManifest extends Omit<Manifest, \"commands\"> {\n /** 빌드한 @obov/mext 버전. 실행 시 설치된 버전과 다르면 시작 오류 */\n mextVersion: string\n /** 빌드 식별자 (D3: mextVersion · manifestHash · 번들 코드의 sha256 앞 16자, 같은 입력 = 같은 값) */\n buildId: string\n /**\n * manifestHash(commands, { resources: 자원 uri, prompts: 이름 · argsSchema }). 전체 명령어 기준.\n * expose 로 숨긴 명령어가 있는 호출자에게는 서버가 그 보기의 값을 계산해 보낸다 (§4)\n */\n manifestHash: string\n /** MCP 도구 노출 방식 (mext.config.ts tools, 기본 execute). 고객 CLI 번들 형태의 호출 방식 (§12.2) */\n tools: ToolExposure\n /** mext.config.ts 번들 (.mext/ 기준). 설정 파일이 없으면 생략 */\n config?: string\n /** instrumentation.ts 번들 (.mext/ 기준). 없으면 생략 */\n instrumentation?: string\n /** ID 순 */\n commands: BuildManifestCommand[]\n /** MCP 자원 (§12.3). uri 순. 자원이 없으면 생략 */\n resources?: BuildManifestResource[]\n /** MCP 프롬프트 (§12.3). 이름 순. 프롬프트가 없으면 생략 */\n prompts?: BuildManifestPrompt[]\n /** routes/ (§12.4). 경로 순. route 가 없으면 생략. manifestHash 에 포함하지 않는다 (명령어 계약 아님) */\n routes?: BuildManifestRoute[]\n}\n\n/** .mext/manifest.json 의 route */\nexport interface BuildManifestRoute {\n /** URL 경로 패턴 (\"/items/[id]\") */\n path: string\n /** routes/ 기준 상대 경로 (posix) */\n file: string\n /** export 한 메서드. 그 외 = 405 (모듈 import 없음) */\n methods: RouteMethod[]\n /** .mext/ 기준 상대 경로. routes/items/[id].ts → \"routes/items/[id].js\" */\n module: string\n}\n\n/**\n * 명령어 계약의 지문: ID · 별칭 · positional · 입력 스키마 · 안전성 메타데이터 (readOnly · destructive ·\n * requiresConfirmation · needsApproval (조건식일 때만) · scopes) 의 정규화 JSON (키 정렬, ID 순) sha256 hex.\n * 설명 · examples · outputSchema · task · 파일 경로는 제외 (클라이언트의 help 캐시 · 플래그 파싱에 영향 없음).\n * extra.resources = 자원 uri (고정 URI · 템플릿 원문, §12.3), extra.prompts = 프롬프트 이름 · args JSON Schema (§12.3).\n * 둘 다 없거나 비면 명령어만의 값과 같다.\n * 빌드 manifest · 서버 (_meta[\"dev.mext/manifestHash\"]) · 클라이언트가 같은 함수로 계산한다\n */\nexport function manifestHash(\n commands: readonly ManifestCommand[],\n extra: { resources?: readonly string[]; prompts?: readonly { name: string; argsSchema?: JsonSchema | undefined }[] } = {},\n): string {\n const normalized = [...commands]\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))\n .map((c) => ({\n id: c.id,\n aliases: [...c.aliases].sort(),\n positional: c.positional,\n inputSchema: c.inputSchema,\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n // 조건식일 때만 (없으면 속성 생략 = 기존 값과 같다)\n needsApproval: c.needsApproval,\n scopes: [...c.scopes].sort(),\n }))\n const resources = [...(extra.resources ?? [])].sort()\n const prompts = [...(extra.prompts ?? [])]\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))\n .map((p) => ({ name: p.name, argsSchema: p.argsSchema }))\n const value =\n resources.length > 0 || prompts.length > 0\n ? { commands: normalized, ...(resources.length > 0 ? { resources } : {}), ...(prompts.length > 0 ? { prompts } : {}) }\n : normalized\n return createHash(\"sha256\").update(canonicalJson(value)).digest(\"hex\")\n}\n\n/** 키 정렬 JSON (배열 순서 유지, undefined 속성 생략) */\nfunction canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"null\"\n if (Array.isArray(value)) return `[${value.map((v) => (v === undefined ? \"null\" : canonicalJson(v))).join(\",\")}]`\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(\",\")}}`\n}\n"]}
|
package/dist/mcp/constants.d.ts
CHANGED
|
@@ -9,5 +9,10 @@ export declare const DEFAULT_PORT = 3100;
|
|
|
9
9
|
export declare const MANIFEST_HASH_META_KEY = "dev.mext/manifestHash";
|
|
10
10
|
/** server/discover 결과 _meta 의 도구 노출 방식 (execute · split · command). 원격 CLI 범용 형태가 호출 방식을 고른다 (§12.2) */
|
|
11
11
|
export declare const TOOLS_META_KEY = "dev.mext/tools";
|
|
12
|
+
/**
|
|
13
|
+
* tools/call 요청 params._meta 의 확인 표시 키 (§4 승인). 값 = { confirmed: true }.
|
|
14
|
+
* client 방식 표면 (mext.config.ts approval.surfaces) + 서버가 정한 행위자 human 일 때만 인정한다
|
|
15
|
+
*/
|
|
16
|
+
export declare const APPROVAL_META_KEY = "dev.mext/approval";
|
|
12
17
|
/** command 노출 도구의 tools/list _meta: 명령어 메타데이터 (aliases · 안전성 · scopes · positional · examples) */
|
|
13
18
|
export declare const COMMAND_META_KEY = "dev.mext/command";
|
package/dist/mcp/constants.js
CHANGED
|
@@ -9,6 +9,11 @@ export const DEFAULT_PORT = 3100;
|
|
|
9
9
|
export const MANIFEST_HASH_META_KEY = "dev.mext/manifestHash";
|
|
10
10
|
/** server/discover 결과 _meta 의 도구 노출 방식 (execute · split · command). 원격 CLI 범용 형태가 호출 방식을 고른다 (§12.2) */
|
|
11
11
|
export const TOOLS_META_KEY = "dev.mext/tools";
|
|
12
|
+
/**
|
|
13
|
+
* tools/call 요청 params._meta 의 확인 표시 키 (§4 승인). 값 = { confirmed: true }.
|
|
14
|
+
* client 방식 표면 (mext.config.ts approval.surfaces) + 서버가 정한 행위자 human 일 때만 인정한다
|
|
15
|
+
*/
|
|
16
|
+
export const APPROVAL_META_KEY = "dev.mext/approval";
|
|
12
17
|
/** command 노출 도구의 tools/list _meta: 명령어 메타데이터 (aliases · 안전성 · scopes · positional · examples) */
|
|
13
18
|
export const COMMAND_META_KEY = "dev.mext/command";
|
|
14
19
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/mcp/constants.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAA;AAC9B,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAA;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAA;AAEhC;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAE7D,wGAAwG;AACxG,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAA;AAE9C,kGAAkG;AAClG,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAA","sourcesContent":["/** MCP 엔드포인트 경로 (POST 만) */\nexport const MCP_PATH = \"/mcp\"\nexport const DEFAULT_HOST = \"127.0.0.1\"\nexport const DEFAULT_PORT = 3100\n\n/**\n * server/discover · tools/call 결과 _meta 의 현재 manifestHash 키 (스키마 drift 감지, §5).\n * 고객 CLI 번들도 import (의존 없는 모듈)\n */\nexport const MANIFEST_HASH_META_KEY = \"dev.mext/manifestHash\"\n\n/** server/discover 결과 _meta 의 도구 노출 방식 (execute · split · command). 원격 CLI 범용 형태가 호출 방식을 고른다 (§12.2) */\nexport const TOOLS_META_KEY = \"dev.mext/tools\"\n\n/** command 노출 도구의 tools/list _meta: 명령어 메타데이터 (aliases · 안전성 · scopes · positional · examples) */\nexport const COMMAND_META_KEY = \"dev.mext/command\"\n"]}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/mcp/constants.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAA;AAC9B,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAA;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAA;AAEhC;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAE7D,wGAAwG;AACxG,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAA;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAA;AAEpD,kGAAkG;AAClG,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAA","sourcesContent":["/** MCP 엔드포인트 경로 (POST 만) */\nexport const MCP_PATH = \"/mcp\"\nexport const DEFAULT_HOST = \"127.0.0.1\"\nexport const DEFAULT_PORT = 3100\n\n/**\n * server/discover · tools/call 결과 _meta 의 현재 manifestHash 키 (스키마 drift 감지, §5).\n * 고객 CLI 번들도 import (의존 없는 모듈)\n */\nexport const MANIFEST_HASH_META_KEY = \"dev.mext/manifestHash\"\n\n/** server/discover 결과 _meta 의 도구 노출 방식 (execute · split · command). 원격 CLI 범용 형태가 호출 방식을 고른다 (§12.2) */\nexport const TOOLS_META_KEY = \"dev.mext/tools\"\n\n/**\n * tools/call 요청 params._meta 의 확인 표시 키 (§4 승인). 값 = { confirmed: true }.\n * client 방식 표면 (mext.config.ts approval.surfaces) + 서버가 정한 행위자 human 일 때만 인정한다\n */\nexport const APPROVAL_META_KEY = \"dev.mext/approval\"\n\n/** command 노출 도구의 tools/list _meta: 명령어 메타데이터 (aliases · 안전성 · scopes · positional · examples) */\nexport const COMMAND_META_KEY = \"dev.mext/command\"\n"]}
|
package/dist/mcp/dispatch.d.ts
CHANGED
|
@@ -67,7 +67,7 @@ export interface DispatchOptions extends Omit<InvokeOptions, "readOnly"> {
|
|
|
67
67
|
/** tools/call 결과: 완료 (CallToolResult 형태) · 입력 요청 (InputRequiredResult) · task 생성 (options.detach, §12.6) */
|
|
68
68
|
export type DispatchResult = ToolCallResult | InputRequiredResult | CreateTaskResult;
|
|
69
69
|
/**
|
|
70
|
-
* dispatcher 도구 호출: { command, args } → help 또는 invoke.
|
|
70
|
+
* dispatcher 도구 호출: { command, args } → help 또는 invoke. registry = 전체 (expose 판정은 여기와 invoke 가 주체의 표면으로 한다).
|
|
71
71
|
* MextError · 핸들러 예외는 isError 결과로 (throw 하지 않음). 인증 (UNAUTHENTICATED → 401) 은 transport 몫.
|
|
72
72
|
* options.input 이 있으면 ctx.ask 가 InputRequiredResult 를 돌려준다 (mrtr.ts).
|
|
73
73
|
*/
|
package/dist/mcp/dispatch.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { surfaceOf } from "../caller.js";
|
|
2
|
+
import { exposedRegistry } from "../expose.js";
|
|
1
3
|
import { isDeclaredError, MextError } from "../errors.js";
|
|
2
4
|
import { invoke } from "../invoke.js";
|
|
3
5
|
import { describeCommand } from "../manifest.js";
|
|
@@ -73,7 +75,7 @@ export function findDispatcherTool(tools, name) {
|
|
|
73
75
|
return tools.find((t) => t.name === name);
|
|
74
76
|
}
|
|
75
77
|
/**
|
|
76
|
-
* dispatcher 도구 호출: { command, args } → help 또는 invoke.
|
|
78
|
+
* dispatcher 도구 호출: { command, args } → help 또는 invoke. registry = 전체 (expose 판정은 여기와 invoke 가 주체의 표면으로 한다).
|
|
77
79
|
* MextError · 핸들러 예외는 isError 결과로 (throw 하지 않음). 인증 (UNAUTHENTICATED → 401) 은 transport 몫.
|
|
78
80
|
* options.input 이 있으면 ctx.ask 가 InputRequiredResult 를 돌려준다 (mrtr.ts).
|
|
79
81
|
*/
|
|
@@ -91,7 +93,9 @@ export async function callDispatcher(registry, tool, rawArguments, options) {
|
|
|
91
93
|
});
|
|
92
94
|
}
|
|
93
95
|
const toolFor = splitToolFor(options.tools);
|
|
94
|
-
|
|
96
|
+
// help = 주체의 표면에서 보이는 명령어만 (§4 expose). 실행은 invoke 가 같은 판정을 한다
|
|
97
|
+
const view = exposedRegistry(registry, surfaceOf(options.principal, options.transport ?? "local"));
|
|
98
|
+
const value = help(view, target, toolFor ? { toolFor } : {});
|
|
95
99
|
return { content: [{ type: "text", text: formatHelp(value, tool.name) }], structuredContent: value };
|
|
96
100
|
}
|
|
97
101
|
const { input, tools: _tools, ...invokeOptions } = options;
|
|
@@ -139,7 +143,14 @@ async function invokeRound(registry, tool, command, args, options, input) {
|
|
|
139
143
|
const session = createAskSession(answers, modes);
|
|
140
144
|
const signal = options.signal ? AbortSignal.any([options.signal, session.signal]) : session.signal;
|
|
141
145
|
try {
|
|
142
|
-
const result = await invoke(registry, command, args, {
|
|
146
|
+
const result = await invoke(registry, command, args, {
|
|
147
|
+
...rest,
|
|
148
|
+
signal,
|
|
149
|
+
ask: session.ask,
|
|
150
|
+
readOnly: tool.readOnly,
|
|
151
|
+
// 입력 대기로 끝난 라운드 = 감사 이벤트 없음 (§11.1)
|
|
152
|
+
pendingInput: () => hasPending(session),
|
|
153
|
+
});
|
|
143
154
|
return hasPending(session) ? inputRequiredResult(session, input.signer, binding) : result;
|
|
144
155
|
}
|
|
145
156
|
catch (error) {
|
package/dist/mcp/dispatch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/mcp/dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["import { isDeclaredError, MextError } from \"../errors.ts\"\nimport { invoke, type InvokeOptions, type InvokeResult } from \"../invoke.ts\"\nimport type { JsonSchema, RegisteredCommand, Registry } from \"../registry.ts\"\nimport { describeCommand } from \"../manifest.ts\"\nimport { COMMAND_META_KEY } from \"./constants.ts\"\nimport { formatHelp, help, HELP_COMMAND } from \"./help.ts\"\nimport {\n createAskSession,\n hasPending,\n inputRequiredResult,\n type InputRequiredResult,\n type InputRound,\n type RequestStateBinding,\n type RequestStateSigner,\n} from \"./mrtr.ts\"\nimport type { CreateTaskResult } from \"./tasks.ts\"\n\n/**\n * MCP 어댑터의 transport 무관 부분: dispatcher 도구 정의 · tools/call 실행 · help · 오류 → 결과 변환.\n * SDK · HTTP 에 의존하지 않는다 (HTTP · stdio 가 공유).\n */\n\n/**\n * execute = 도구 1개 (기본), split = query (readOnly · help) + mutate (그 외),\n * command = 명령어 1개 = 도구 1개 (도구 이름 = 명령어 ID, outputSchema, help 없음, §12.2)\n */\nexport type ToolExposure = \"execute\" | \"split\" | \"command\"\n\nexport type DispatcherToolName = \"execute\" | \"query\" | \"mutate\"\n\n/** MCP ToolAnnotations 중 mext 가 쓰는 항목 */\nexport interface DispatcherAnnotations {\n title?: string\n readOnlyHint: boolean\n destructiveHint?: boolean\n idempotentHint?: boolean\n openWorldHint?: boolean\n}\n\n/** tools/list 도구 하나. dispatcher (execute · query · mutate) 또는 명령어별 도구 (command 노출) */\nexport interface DispatcherTool {\n /** dispatcher = DispatcherToolName, command 노출 = 명령어 ID */\n name: string\n description: string\n /** JSON Schema 2020-12. dispatcher = command 에 x-mcp-header: \"Command\", command 노출 = 명령어 input */\n inputSchema: JsonSchema\n annotations: DispatcherAnnotations\n /** readOnly 명령어만 실행 (split 의 query). 그 외 = PERMISSION_DENIED */\n readOnly: boolean\n /** command 노출: 이 도구가 실행하는 명령어 ID (인자 = 명령어 input 그대로). 없음 = dispatcher ({ command, args }) */\n command?: string\n /** command 노출: output 의 JSON Schema 2020-12 (output 이 있을 때) */\n outputSchema?: JsonSchema\n /** command 노출: tools/list 도구 _meta (COMMAND_META_KEY = CLI 원격의 help · 플래그 파싱용 메타데이터) */\n _meta?: Record<string, unknown>\n}\n\nexport interface TextContent {\n type: \"text\"\n text: string\n}\n\n/** MCP CallToolResult 와 같은 형태 (SDK 타입 비의존) */\nexport interface ToolCallResult {\n content: TextContent[]\n /** 성공 = 핸들러 반환값 (undefined 는 null), 오류 = { error: MextError.toJSON() } */\n structuredContent: unknown\n isError?: true\n}\n\n/** 핸들러 예외 (MextError 외) 의 결과 code. CLI --json 과 같음 */\nexport const EXECUTION_ERROR = \"EXECUTION_ERROR\"\n\n/** 도구 설명에 나열할 명령어 수 상한. 넘으면 help 안내만 */\nconst DESCRIPTION_COMMAND_LIMIT = 50\n\n/** 노출 방식별 도구 (정렬 순서 고정: execute · query, mutate · 명령어 ID 순) */\nexport function dispatcherTools(registry: Registry, exposure: ToolExposure = \"execute\"): DispatcherTool[] {\n const all = [...registry.commands.values()]\n if (exposure === \"command\") return all.map(commandTool)\n if (exposure === \"split\") {\n const reads = all.filter((e) => e.command.readOnly)\n const writes = all.filter((e) => !e.command.readOnly)\n return [\n {\n name: \"query\",\n description: describeTool(\n \"query\",\n \"Run a read-only command.\",\n reads,\n 'Commands that are not read-only are rejected here; call them with the \"mutate\" tool.',\n ),\n inputSchema: dispatcherInputSchema(),\n annotations: { title: \"Query\", readOnlyHint: true, destructiveHint: false, idempotentHint: true },\n readOnly: true,\n },\n {\n name: \"mutate\",\n description: describeTool(\"mutate\", \"Run a command that changes state.\", writes),\n inputSchema: dispatcherInputSchema(),\n annotations: { title: \"Mutate\", readOnlyHint: false, destructiveHint: true },\n readOnly: false,\n },\n ]\n }\n const readOnly = all.every((e) => e.command.readOnly)\n return [\n {\n name: \"execute\",\n description: describeTool(\"execute\", \"Run a command.\", all),\n inputSchema: dispatcherInputSchema(),\n // 단일 dispatcher 는 최악값 (researches/others.md 9)\n annotations: readOnly\n ? { title: \"Execute\", readOnlyHint: true, destructiveHint: false }\n : { title: \"Execute\", readOnlyHint: false, destructiveHint: all.some((e) => e.command.destructive) },\n readOnly: false,\n },\n ]\n}\n\n/**\n * command 노출의 명령어별 도구 (§12.2). 이름 = 정식 ID (별칭은 도구 아님), annotations = execute 와 같은 계산을 명령어 하나에.\n * _meta[COMMAND_META_KEY] = tools/list 만으로 CLI 원격의 help · 별칭 · positional 을 만들 메타데이터\n */\nfunction commandTool(entry: RegisteredCommand): DispatcherTool {\n const { id, description: _d, inputSchema: _i, outputSchema: _o, file: _f, ...meta } = describeCommand(entry)\n const c = entry.command\n const tool: DispatcherTool = {\n name: id,\n description: c.description,\n inputSchema: entry.inputSchema,\n annotations: c.readOnly\n ? { title: id, readOnlyHint: true, destructiveHint: false }\n : { title: id, readOnlyHint: false, destructiveHint: c.destructive },\n readOnly: false,\n command: id,\n _meta: { [COMMAND_META_KEY]: meta },\n }\n if (entry.outputSchema !== undefined) tool.outputSchema = entry.outputSchema\n return tool\n}\n\nexport function findDispatcherTool(tools: readonly DispatcherTool[], name: string): DispatcherTool | undefined {\n return tools.find((t) => t.name === name)\n}\n\nexport interface DispatchOptions extends Omit<InvokeOptions, \"readOnly\"> {\n /** help 의 tool 표시용. dispatcherTools 결과 */\n tools?: readonly DispatcherTool[]\n /**\n * MRTR (MCP 2026-07-28). 지정하면 ctx.ask = InputRequiredResult 반환 · 재시도의 inputResponses 로 resolve\n * (ask 옵션 무시). requiresConfirmation 확인도 이 경로\n */\n input?: InputRound & { signer: RequestStateSigner }\n}\n\n/** tools/call 결과: 완료 (CallToolResult 형태) · 입력 요청 (InputRequiredResult) · task 생성 (options.detach, §12.6) */\nexport type DispatchResult = ToolCallResult | InputRequiredResult | CreateTaskResult\n\n/**\n * dispatcher 도구 호출: { command, args } → help 또는 invoke.\n * MextError · 핸들러 예외는 isError 결과로 (throw 하지 않음). 인증 (UNAUTHENTICATED → 401) 은 transport 몫.\n * options.input 이 있으면 ctx.ask 가 InputRequiredResult 를 돌려준다 (mrtr.ts).\n */\nexport async function callDispatcher(\n registry: Registry,\n tool: DispatcherTool,\n rawArguments: unknown,\n options: DispatchOptions,\n): Promise<DispatchResult> {\n try {\n // command 노출: 인자 = 명령어 input 그대로 (검증 = invoke 의 Zod safeParse)\n const { command, args } =\n tool.command !== undefined ? { command: tool.command, args: rawArguments } : parseDispatcherArguments(tool, rawArguments)\n if (command === HELP_COMMAND) {\n const target = (args as { target?: unknown } | undefined)?.target\n if (target !== undefined && typeof target !== \"string\") {\n throw dispatcherArgumentError(tool, \"help\", \"args.target must be a string\", [], {\n path: \"args.target\",\n code: \"invalid_type\",\n message: \"expected string\",\n })\n }\n const toolFor = splitToolFor(options.tools)\n const value = help(registry, target, toolFor ? { toolFor } : {})\n return { content: [{ type: \"text\", text: formatHelp(value, tool.name) }], structuredContent: value }\n }\n const { input, tools: _tools, ...invokeOptions } = options\n const result = input\n ? await invokeRound(registry, tool, command, args, invokeOptions, input)\n : await invoke(registry, command, args, { ...invokeOptions, readOnly: tool.readOnly })\n if (\"resultType\" in result) return result\n if (result.detached !== undefined) return result.detached as CreateTaskResult\n return valueResult(result.value)\n } catch (error) {\n return errorResult(error)\n }\n}\n\n/** 핸들러 반환값 → 성공 결과 (undefined = null). task 완료 결과도 같은 변환 */\nexport function valueResult(value: unknown): ToolCallResult {\n const structured = value === undefined ? null : value\n return { content: [{ type: \"text\", text: stringify(structured) }], structuredContent: structured }\n}\n\n/**\n * MRTR 한 라운드: requestState 검증 → ask 세션으로 invoke. 답 없는 ask 가 있으면 (핸들러가 오류를 삼켜도)\n * 결과를 버리고 InputRequiredResult. elicitation 미선언 클라이언트 = ask 미주입 (INPUT_UNAVAILABLE).\n * 선언한 mode 만 요청 (form · url). 미선언 mode 의 ask = INPUT_UNAVAILABLE\n */\nasync function invokeRound(\n registry: Registry,\n tool: DispatcherTool,\n command: string,\n args: unknown,\n options: Omit<InvokeOptions, \"readOnly\">,\n input: NonNullable<DispatchOptions[\"input\"]>,\n): Promise<InvokeResult | InputRequiredResult> {\n const { ask: _ask, ...rest } = options\n const modes = { form: input.elicitation, url: input.urlElicitation === true }\n if (!modes.form && !modes.url) return invoke(registry, command, args, { ...rest, readOnly: tool.readOnly })\n const binding: RequestStateBinding = {\n principal: `${options.principal.kind}:${options.principal.id}`,\n tool: tool.name,\n command,\n args: args ?? {},\n }\n let answers: Record<string, unknown> = { ...input.inputResponses }\n if (input.requestState !== undefined) {\n const prior = input.signer.verify(input.requestState, binding)\n if (!prior) throw invalidRequestState(tool, command)\n answers = { ...answers, ...prior }\n }\n const session = createAskSession(answers, modes)\n const signal = options.signal ? AbortSignal.any([options.signal, session.signal]) : session.signal\n try {\n const result = await invoke(registry, command, args, { ...rest, signal, ask: session.ask, readOnly: tool.readOnly })\n return hasPending(session) ? inputRequiredResult(session, input.signer, binding) : result\n } catch (error) {\n if (hasPending(session)) return inputRequiredResult(session, input.signer, binding)\n throw error\n }\n}\n\n/** 서명 · 만료 · 바인딩 검증 실패한 requestState. 처음부터 다시 호출하도록 안내 */\nfunction invalidRequestState(tool: DispatcherTool, command: string): MextError<\"INVALID_ARGUMENT\"> {\n return new MextError(\n \"INVALID_ARGUMENT\",\n `Invalid arguments for ${command}: requestState is invalid or expired. Call ${tool.name} again without requestState and inputResponses.`,\n {\n command,\n missing_fields: [],\n issues: [\n {\n path: \"requestState\",\n code: \"invalid_request_state\",\n message: \"requestState failed verification (tampered, expired, or for a different call or server key)\",\n },\n ],\n expected_schema: tool.inputSchema,\n examples: [],\n },\n )\n}\n\n/** 오류 → isError 결과. MextError · CommandError = toJSON, 그 외 = EXECUTION_ERROR (message 만) */\nexport function errorResult(error: unknown): ToolCallResult {\n const body: Record<string, unknown> & { code: string; message: string } = isDeclaredError(error)\n ? error.toJSON()\n : { code: EXECUTION_ERROR, message: error instanceof Error ? error.message : String(error) }\n return {\n content: [{ type: \"text\", text: `${body.code}: ${body.message}\\n${stringify(body)}` }],\n structuredContent: { error: body },\n isError: true,\n }\n}\n\n/** dispatcher 도구 inputSchema. command 를 Mcp-Param-Command 헤더로 복사 (SEP-2243) */\nexport function dispatcherInputSchema(): JsonSchema {\n return {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: 'Command ID (e.g. \"users.get\"), or \"help\" to list namespaces and commands.',\n \"x-mcp-header\": \"Command\",\n },\n args: {\n type: \"object\",\n description: 'Command input. For \"help\": { \"target\": \"<namespace or command ID>\" }.',\n additionalProperties: true,\n },\n },\n required: [\"command\"],\n additionalProperties: false,\n }\n}\n\nfunction parseDispatcherArguments(tool: DispatcherTool, raw: unknown): { command: string; args: unknown } {\n const input = raw === undefined ? {} : raw\n if (input === null || typeof input !== \"object\" || Array.isArray(input)) {\n throw dispatcherArgumentError(tool, tool.name, \"arguments must be an object\", [], {\n path: \"\",\n code: \"invalid_type\",\n message: \"expected object\",\n })\n }\n const { command, args, ...rest } = input as Record<string, unknown>\n if (command === undefined) {\n throw dispatcherArgumentError(tool, tool.name, \"missing required: command\", [\"command\"], {\n path: \"command\",\n code: \"invalid_type\",\n message: \"expected string, received undefined\",\n })\n }\n if (typeof command !== \"string\") {\n throw dispatcherArgumentError(tool, tool.name, \"command must be a string\", [], {\n path: \"command\",\n code: \"invalid_type\",\n message: \"expected string\",\n })\n }\n const unknownKeys = Object.keys(rest)\n if (unknownKeys.length > 0) {\n throw dispatcherArgumentError(tool, tool.name, `unrecognized keys: ${unknownKeys.join(\", \")}`, [], {\n path: \"\",\n code: \"unrecognized_keys\",\n message: `Unrecognized keys: ${unknownKeys.join(\", \")}. Put command input under \"args\".`,\n })\n }\n if (args !== undefined && (args === null || typeof args !== \"object\" || Array.isArray(args))) {\n throw dispatcherArgumentError(tool, command, \"args must be an object\", [], {\n path: \"args\",\n code: \"invalid_type\",\n message: \"expected object\",\n })\n }\n return { command, args }\n}\n\nfunction dispatcherArgumentError(\n tool: DispatcherTool,\n command: string,\n summary: string,\n missing: string[],\n issue: { path: string; code: string; message: string },\n): MextError<\"INVALID_ARGUMENT\"> {\n return new MextError(\"INVALID_ARGUMENT\", `Invalid arguments for ${command}: ${summary}`, {\n command,\n missing_fields: missing,\n issues: [issue],\n expected_schema: tool.inputSchema,\n examples: [{ command: HELP_COMMAND }],\n })\n}\n\nfunction splitToolFor(tools: readonly DispatcherTool[] | undefined): ((e: RegisteredCommand) => string) | undefined {\n if (!tools || tools.length < 2) return undefined\n const query = tools.find((t) => t.readOnly)?.name\n const mutate = tools.find((t) => !t.readOnly)?.name\n if (query === undefined || mutate === undefined) return undefined\n return (e) => (e.command.readOnly ? query : mutate)\n}\n\nfunction describeTool(name: string, lead: string, commands: readonly RegisteredCommand[], note?: string): string {\n const lines = [\n lead,\n `Arguments: { \"command\": \"<command ID>\", \"args\": { ...input } }. ` +\n `Call ${name}({ \"command\": \"help\" }) to list namespaces and commands, ` +\n `${name}({ \"command\": \"help\", \"args\": { \"target\": \"<namespace or command ID>\" } }) for input schemas and examples.`,\n ]\n if (note) lines.push(note)\n if (commands.length > 0 && commands.length <= DESCRIPTION_COMMAND_LIMIT) {\n lines.push(\"\", \"Commands:\")\n for (const e of commands) lines.push(`- ${e.id}: ${firstLine(e.command.description)}`)\n }\n return lines.join(\"\\n\")\n}\n\nfunction firstLine(text: string): string {\n return text.split(\"\\n\", 1)[0]!.trim()\n}\n\nfunction stringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2) ?? \"null\"\n } catch {\n return String(value)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/mcp/dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["import { surfaceOf } from \"../caller.ts\"\nimport { exposedRegistry } from \"../expose.ts\"\nimport { isDeclaredError, MextError } from \"../errors.ts\"\nimport { invoke, type InvokeOptions, type InvokeResult } from \"../invoke.ts\"\nimport type { JsonSchema, RegisteredCommand, Registry } from \"../registry.ts\"\nimport { describeCommand } from \"../manifest.ts\"\nimport { COMMAND_META_KEY } from \"./constants.ts\"\nimport { formatHelp, help, HELP_COMMAND } from \"./help.ts\"\nimport {\n createAskSession,\n hasPending,\n inputRequiredResult,\n type InputRequiredResult,\n type InputRound,\n type RequestStateBinding,\n type RequestStateSigner,\n} from \"./mrtr.ts\"\nimport type { CreateTaskResult } from \"./tasks.ts\"\n\n/**\n * MCP 어댑터의 transport 무관 부분: dispatcher 도구 정의 · tools/call 실행 · help · 오류 → 결과 변환.\n * SDK · HTTP 에 의존하지 않는다 (HTTP · stdio 가 공유).\n */\n\n/**\n * execute = 도구 1개 (기본), split = query (readOnly · help) + mutate (그 외),\n * command = 명령어 1개 = 도구 1개 (도구 이름 = 명령어 ID, outputSchema, help 없음, §12.2)\n */\nexport type ToolExposure = \"execute\" | \"split\" | \"command\"\n\nexport type DispatcherToolName = \"execute\" | \"query\" | \"mutate\"\n\n/** MCP ToolAnnotations 중 mext 가 쓰는 항목 */\nexport interface DispatcherAnnotations {\n title?: string\n readOnlyHint: boolean\n destructiveHint?: boolean\n idempotentHint?: boolean\n openWorldHint?: boolean\n}\n\n/** tools/list 도구 하나. dispatcher (execute · query · mutate) 또는 명령어별 도구 (command 노출) */\nexport interface DispatcherTool {\n /** dispatcher = DispatcherToolName, command 노출 = 명령어 ID */\n name: string\n description: string\n /** JSON Schema 2020-12. dispatcher = command 에 x-mcp-header: \"Command\", command 노출 = 명령어 input */\n inputSchema: JsonSchema\n annotations: DispatcherAnnotations\n /** readOnly 명령어만 실행 (split 의 query). 그 외 = PERMISSION_DENIED */\n readOnly: boolean\n /** command 노출: 이 도구가 실행하는 명령어 ID (인자 = 명령어 input 그대로). 없음 = dispatcher ({ command, args }) */\n command?: string\n /** command 노출: output 의 JSON Schema 2020-12 (output 이 있을 때) */\n outputSchema?: JsonSchema\n /** command 노출: tools/list 도구 _meta (COMMAND_META_KEY = CLI 원격의 help · 플래그 파싱용 메타데이터) */\n _meta?: Record<string, unknown>\n}\n\nexport interface TextContent {\n type: \"text\"\n text: string\n}\n\n/** MCP CallToolResult 와 같은 형태 (SDK 타입 비의존) */\nexport interface ToolCallResult {\n content: TextContent[]\n /** 성공 = 핸들러 반환값 (undefined 는 null), 오류 = { error: MextError.toJSON() } */\n structuredContent: unknown\n isError?: true\n}\n\n/** 핸들러 예외 (MextError 외) 의 결과 code. CLI --json 과 같음 */\nexport const EXECUTION_ERROR = \"EXECUTION_ERROR\"\n\n/** 도구 설명에 나열할 명령어 수 상한. 넘으면 help 안내만 */\nconst DESCRIPTION_COMMAND_LIMIT = 50\n\n/** 노출 방식별 도구 (정렬 순서 고정: execute · query, mutate · 명령어 ID 순) */\nexport function dispatcherTools(registry: Registry, exposure: ToolExposure = \"execute\"): DispatcherTool[] {\n const all = [...registry.commands.values()]\n if (exposure === \"command\") return all.map(commandTool)\n if (exposure === \"split\") {\n const reads = all.filter((e) => e.command.readOnly)\n const writes = all.filter((e) => !e.command.readOnly)\n return [\n {\n name: \"query\",\n description: describeTool(\n \"query\",\n \"Run a read-only command.\",\n reads,\n 'Commands that are not read-only are rejected here; call them with the \"mutate\" tool.',\n ),\n inputSchema: dispatcherInputSchema(),\n annotations: { title: \"Query\", readOnlyHint: true, destructiveHint: false, idempotentHint: true },\n readOnly: true,\n },\n {\n name: \"mutate\",\n description: describeTool(\"mutate\", \"Run a command that changes state.\", writes),\n inputSchema: dispatcherInputSchema(),\n annotations: { title: \"Mutate\", readOnlyHint: false, destructiveHint: true },\n readOnly: false,\n },\n ]\n }\n const readOnly = all.every((e) => e.command.readOnly)\n return [\n {\n name: \"execute\",\n description: describeTool(\"execute\", \"Run a command.\", all),\n inputSchema: dispatcherInputSchema(),\n // 단일 dispatcher 는 최악값 (researches/others.md 9)\n annotations: readOnly\n ? { title: \"Execute\", readOnlyHint: true, destructiveHint: false }\n : { title: \"Execute\", readOnlyHint: false, destructiveHint: all.some((e) => e.command.destructive) },\n readOnly: false,\n },\n ]\n}\n\n/**\n * command 노출의 명령어별 도구 (§12.2). 이름 = 정식 ID (별칭은 도구 아님), annotations = execute 와 같은 계산을 명령어 하나에.\n * _meta[COMMAND_META_KEY] = tools/list 만으로 CLI 원격의 help · 별칭 · positional 을 만들 메타데이터\n */\nfunction commandTool(entry: RegisteredCommand): DispatcherTool {\n const { id, description: _d, inputSchema: _i, outputSchema: _o, file: _f, ...meta } = describeCommand(entry)\n const c = entry.command\n const tool: DispatcherTool = {\n name: id,\n description: c.description,\n inputSchema: entry.inputSchema,\n annotations: c.readOnly\n ? { title: id, readOnlyHint: true, destructiveHint: false }\n : { title: id, readOnlyHint: false, destructiveHint: c.destructive },\n readOnly: false,\n command: id,\n _meta: { [COMMAND_META_KEY]: meta },\n }\n if (entry.outputSchema !== undefined) tool.outputSchema = entry.outputSchema\n return tool\n}\n\nexport function findDispatcherTool(tools: readonly DispatcherTool[], name: string): DispatcherTool | undefined {\n return tools.find((t) => t.name === name)\n}\n\nexport interface DispatchOptions extends Omit<InvokeOptions, \"readOnly\"> {\n /** help 의 tool 표시용. dispatcherTools 결과 */\n tools?: readonly DispatcherTool[]\n /**\n * MRTR (MCP 2026-07-28). 지정하면 ctx.ask = InputRequiredResult 반환 · 재시도의 inputResponses 로 resolve\n * (ask 옵션 무시). requiresConfirmation 확인도 이 경로\n */\n input?: InputRound & { signer: RequestStateSigner }\n}\n\n/** tools/call 결과: 완료 (CallToolResult 형태) · 입력 요청 (InputRequiredResult) · task 생성 (options.detach, §12.6) */\nexport type DispatchResult = ToolCallResult | InputRequiredResult | CreateTaskResult\n\n/**\n * dispatcher 도구 호출: { command, args } → help 또는 invoke. registry = 전체 (expose 판정은 여기와 invoke 가 주체의 표면으로 한다).\n * MextError · 핸들러 예외는 isError 결과로 (throw 하지 않음). 인증 (UNAUTHENTICATED → 401) 은 transport 몫.\n * options.input 이 있으면 ctx.ask 가 InputRequiredResult 를 돌려준다 (mrtr.ts).\n */\nexport async function callDispatcher(\n registry: Registry,\n tool: DispatcherTool,\n rawArguments: unknown,\n options: DispatchOptions,\n): Promise<DispatchResult> {\n try {\n // command 노출: 인자 = 명령어 input 그대로 (검증 = invoke 의 Zod safeParse)\n const { command, args } =\n tool.command !== undefined ? { command: tool.command, args: rawArguments } : parseDispatcherArguments(tool, rawArguments)\n if (command === HELP_COMMAND) {\n const target = (args as { target?: unknown } | undefined)?.target\n if (target !== undefined && typeof target !== \"string\") {\n throw dispatcherArgumentError(tool, \"help\", \"args.target must be a string\", [], {\n path: \"args.target\",\n code: \"invalid_type\",\n message: \"expected string\",\n })\n }\n const toolFor = splitToolFor(options.tools)\n // help = 주체의 표면에서 보이는 명령어만 (§4 expose). 실행은 invoke 가 같은 판정을 한다\n const view = exposedRegistry(registry, surfaceOf(options.principal, options.transport ?? \"local\"))\n const value = help(view, target, toolFor ? { toolFor } : {})\n return { content: [{ type: \"text\", text: formatHelp(value, tool.name) }], structuredContent: value }\n }\n const { input, tools: _tools, ...invokeOptions } = options\n const result = input\n ? await invokeRound(registry, tool, command, args, invokeOptions, input)\n : await invoke(registry, command, args, { ...invokeOptions, readOnly: tool.readOnly })\n if (\"resultType\" in result) return result\n if (result.detached !== undefined) return result.detached as CreateTaskResult\n return valueResult(result.value)\n } catch (error) {\n return errorResult(error)\n }\n}\n\n/** 핸들러 반환값 → 성공 결과 (undefined = null). task 완료 결과도 같은 변환 */\nexport function valueResult(value: unknown): ToolCallResult {\n const structured = value === undefined ? null : value\n return { content: [{ type: \"text\", text: stringify(structured) }], structuredContent: structured }\n}\n\n/**\n * MRTR 한 라운드: requestState 검증 → ask 세션으로 invoke. 답 없는 ask 가 있으면 (핸들러가 오류를 삼켜도)\n * 결과를 버리고 InputRequiredResult. elicitation 미선언 클라이언트 = ask 미주입 (INPUT_UNAVAILABLE).\n * 선언한 mode 만 요청 (form · url). 미선언 mode 의 ask = INPUT_UNAVAILABLE\n */\nasync function invokeRound(\n registry: Registry,\n tool: DispatcherTool,\n command: string,\n args: unknown,\n options: Omit<InvokeOptions, \"readOnly\">,\n input: NonNullable<DispatchOptions[\"input\"]>,\n): Promise<InvokeResult | InputRequiredResult> {\n const { ask: _ask, ...rest } = options\n const modes = { form: input.elicitation, url: input.urlElicitation === true }\n if (!modes.form && !modes.url) return invoke(registry, command, args, { ...rest, readOnly: tool.readOnly })\n const binding: RequestStateBinding = {\n principal: `${options.principal.kind}:${options.principal.id}`,\n tool: tool.name,\n command,\n args: args ?? {},\n }\n let answers: Record<string, unknown> = { ...input.inputResponses }\n if (input.requestState !== undefined) {\n const prior = input.signer.verify(input.requestState, binding)\n if (!prior) throw invalidRequestState(tool, command)\n answers = { ...answers, ...prior }\n }\n const session = createAskSession(answers, modes)\n const signal = options.signal ? AbortSignal.any([options.signal, session.signal]) : session.signal\n try {\n const result = await invoke(registry, command, args, {\n ...rest,\n signal,\n ask: session.ask,\n readOnly: tool.readOnly,\n // 입력 대기로 끝난 라운드 = 감사 이벤트 없음 (§11.1)\n pendingInput: () => hasPending(session),\n })\n return hasPending(session) ? inputRequiredResult(session, input.signer, binding) : result\n } catch (error) {\n if (hasPending(session)) return inputRequiredResult(session, input.signer, binding)\n throw error\n }\n}\n\n/** 서명 · 만료 · 바인딩 검증 실패한 requestState. 처음부터 다시 호출하도록 안내 */\nfunction invalidRequestState(tool: DispatcherTool, command: string): MextError<\"INVALID_ARGUMENT\"> {\n return new MextError(\n \"INVALID_ARGUMENT\",\n `Invalid arguments for ${command}: requestState is invalid or expired. Call ${tool.name} again without requestState and inputResponses.`,\n {\n command,\n missing_fields: [],\n issues: [\n {\n path: \"requestState\",\n code: \"invalid_request_state\",\n message: \"requestState failed verification (tampered, expired, or for a different call or server key)\",\n },\n ],\n expected_schema: tool.inputSchema,\n examples: [],\n },\n )\n}\n\n/** 오류 → isError 결과. MextError · CommandError = toJSON, 그 외 = EXECUTION_ERROR (message 만) */\nexport function errorResult(error: unknown): ToolCallResult {\n const body: Record<string, unknown> & { code: string; message: string } = isDeclaredError(error)\n ? error.toJSON()\n : { code: EXECUTION_ERROR, message: error instanceof Error ? error.message : String(error) }\n return {\n content: [{ type: \"text\", text: `${body.code}: ${body.message}\\n${stringify(body)}` }],\n structuredContent: { error: body },\n isError: true,\n }\n}\n\n/** dispatcher 도구 inputSchema. command 를 Mcp-Param-Command 헤더로 복사 (SEP-2243) */\nexport function dispatcherInputSchema(): JsonSchema {\n return {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: 'Command ID (e.g. \"users.get\"), or \"help\" to list namespaces and commands.',\n \"x-mcp-header\": \"Command\",\n },\n args: {\n type: \"object\",\n description: 'Command input. For \"help\": { \"target\": \"<namespace or command ID>\" }.',\n additionalProperties: true,\n },\n },\n required: [\"command\"],\n additionalProperties: false,\n }\n}\n\nfunction parseDispatcherArguments(tool: DispatcherTool, raw: unknown): { command: string; args: unknown } {\n const input = raw === undefined ? {} : raw\n if (input === null || typeof input !== \"object\" || Array.isArray(input)) {\n throw dispatcherArgumentError(tool, tool.name, \"arguments must be an object\", [], {\n path: \"\",\n code: \"invalid_type\",\n message: \"expected object\",\n })\n }\n const { command, args, ...rest } = input as Record<string, unknown>\n if (command === undefined) {\n throw dispatcherArgumentError(tool, tool.name, \"missing required: command\", [\"command\"], {\n path: \"command\",\n code: \"invalid_type\",\n message: \"expected string, received undefined\",\n })\n }\n if (typeof command !== \"string\") {\n throw dispatcherArgumentError(tool, tool.name, \"command must be a string\", [], {\n path: \"command\",\n code: \"invalid_type\",\n message: \"expected string\",\n })\n }\n const unknownKeys = Object.keys(rest)\n if (unknownKeys.length > 0) {\n throw dispatcherArgumentError(tool, tool.name, `unrecognized keys: ${unknownKeys.join(\", \")}`, [], {\n path: \"\",\n code: \"unrecognized_keys\",\n message: `Unrecognized keys: ${unknownKeys.join(\", \")}. Put command input under \"args\".`,\n })\n }\n if (args !== undefined && (args === null || typeof args !== \"object\" || Array.isArray(args))) {\n throw dispatcherArgumentError(tool, command, \"args must be an object\", [], {\n path: \"args\",\n code: \"invalid_type\",\n message: \"expected object\",\n })\n }\n return { command, args }\n}\n\nfunction dispatcherArgumentError(\n tool: DispatcherTool,\n command: string,\n summary: string,\n missing: string[],\n issue: { path: string; code: string; message: string },\n): MextError<\"INVALID_ARGUMENT\"> {\n return new MextError(\"INVALID_ARGUMENT\", `Invalid arguments for ${command}: ${summary}`, {\n command,\n missing_fields: missing,\n issues: [issue],\n expected_schema: tool.inputSchema,\n examples: [{ command: HELP_COMMAND }],\n })\n}\n\nfunction splitToolFor(tools: readonly DispatcherTool[] | undefined): ((e: RegisteredCommand) => string) | undefined {\n if (!tools || tools.length < 2) return undefined\n const query = tools.find((t) => t.readOnly)?.name\n const mutate = tools.find((t) => !t.readOnly)?.name\n if (query === undefined || mutate === undefined) return undefined\n return (e) => (e.command.readOnly ? query : mutate)\n}\n\nfunction describeTool(name: string, lead: string, commands: readonly RegisteredCommand[], note?: string): string {\n const lines = [\n lead,\n `Arguments: { \"command\": \"<command ID>\", \"args\": { ...input } }. ` +\n `Call ${name}({ \"command\": \"help\" }) to list namespaces and commands, ` +\n `${name}({ \"command\": \"help\", \"args\": { \"target\": \"<namespace or command ID>\" } }) for input schemas and examples.`,\n ]\n if (note) lines.push(note)\n if (commands.length > 0 && commands.length <= DESCRIPTION_COMMAND_LIMIT) {\n lines.push(\"\", \"Commands:\")\n for (const e of commands) lines.push(`- ${e.id}: ${firstLine(e.command.description)}`)\n }\n return lines.join(\"\\n\")\n}\n\nfunction firstLine(text: string): string {\n return text.split(\"\\n\", 1)[0]!.trim()\n}\n\nfunction stringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2) ?? \"null\"\n } catch {\n return String(value)\n }\n}\n"]}
|
package/dist/mcp/help.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface HelpCommandSummary {
|
|
|
13
13
|
readOnly: boolean;
|
|
14
14
|
destructive: boolean;
|
|
15
15
|
requiresConfirmation: boolean;
|
|
16
|
+
/** 승인이 조건식일 때만 (§4 승인) */
|
|
17
|
+
needsApproval?: "conditional";
|
|
16
18
|
/** split 노출에서 이 명령어를 호출할 도구 (query · mutate). execute 노출에서는 없음 */
|
|
17
19
|
tool?: string;
|
|
18
20
|
}
|
package/dist/mcp/help.js
CHANGED
|
@@ -50,6 +50,8 @@ function commandSummary(entry, options) {
|
|
|
50
50
|
destructive: c.destructive,
|
|
51
51
|
requiresConfirmation: c.requiresConfirmation,
|
|
52
52
|
};
|
|
53
|
+
if (c.needsApproval !== undefined)
|
|
54
|
+
out.needsApproval = "conditional";
|
|
53
55
|
const tool = options.toolFor?.(entry);
|
|
54
56
|
if (tool !== undefined)
|
|
55
57
|
out.tool = tool;
|
|
@@ -61,7 +63,8 @@ function commandHelp(entry, options) {
|
|
|
61
63
|
const errors = ["INVALID_ARGUMENT"];
|
|
62
64
|
if (!c.readOnly || c.scopes.length > 0)
|
|
63
65
|
errors.push("UNAUTHENTICATED", "PERMISSION_DENIED");
|
|
64
|
-
|
|
66
|
+
// 승인 (항상 · 조건식) = ask 방식의 확인 오류. APPROVAL_REQUIRED 는 표면 설정 · 행위자에 따라 승인 명령어 모두에서 가능 (§4 승인)
|
|
67
|
+
if (c.requiresConfirmation || c.needsApproval !== undefined)
|
|
65
68
|
errors.push("INPUT_UNAVAILABLE", "INPUT_DECLINED");
|
|
66
69
|
const out = { kind: "command", ...meta, errors };
|
|
67
70
|
const tool = options.toolFor?.(entry);
|
|
@@ -131,6 +134,8 @@ function safetyFlags(c) {
|
|
|
131
134
|
flags.push("destructive");
|
|
132
135
|
if (c.requiresConfirmation)
|
|
133
136
|
flags.push("requires confirmation");
|
|
137
|
+
else if (c.needsApproval !== undefined)
|
|
138
|
+
flags.push("may require confirmation");
|
|
134
139
|
return flags.join(", ");
|
|
135
140
|
}
|
|
136
141
|
//# sourceMappingURL=help.js.map
|
package/dist/mcp/help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/mcp/help.ts"],"names":[],"mappings":"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","sourcesContent":["import { findCommand } from \"../invoke.ts\"\nimport { describeCommand, type ManifestCommand } from \"../manifest.ts\"\nimport type { RegisteredCommand, Registry } from \"../registry.ts\"\n\n/** help 의 예약 명령어 이름. 루트 세그먼트 help 는 Registry 에서 금지 */\nexport const HELP_COMMAND = \"help\"\n\nexport interface HelpNamespaceSummary {\n id: string\n /** _index.md 첫 줄 */\n description?: string\n}\n\nexport interface HelpCommandSummary {\n id: string\n description: string\n readOnly: boolean\n destructive: boolean\n requiresConfirmation: boolean\n /** split 노출에서 이 명령어를 호출할 도구 (query · mutate). execute 노출에서는 없음 */\n tool?: string\n}\n\n/** execute({ command: \"help\" }) */\nexport interface RootHelp {\n kind: \"root\"\n /** commands/_index.md */\n description?: string\n namespaces: HelpNamespaceSummary[]\n /** 루트 직속 명령어 */\n commands: HelpCommandSummary[]\n}\n\n/** execute({ command: \"help\", args: { target: \"users\" } }) */\nexport interface NamespaceHelp {\n kind: \"namespace\"\n id: string\n /** _index.md 전체 */\n description?: string\n namespaces: HelpNamespaceSummary[]\n commands: HelpCommandSummary[]\n /** 같은 ID 의 명령어 (users/index.ts) */\n command?: CommandHelp\n}\n\n/** execute({ command: \"help\", args: { target: \"users.get\" } }) */\nexport interface CommandHelp extends Omit<ManifestCommand, \"file\"> {\n kind: \"command\"\n /** 이 명령어 호출이 돌려줄 수 있는 구조화 오류 code */\n errors: string[]\n tool?: string\n}\n\nexport type Help = RootHelp | NamespaceHelp | CommandHelp\n\nexport interface HelpOptions {\n /** 명령어 → 호출할 도구 이름. split 노출이 지정 */\n toolFor?: (entry: RegisteredCommand) => string | undefined\n}\n\n/**\n * help 3단계: target 없음 = 루트 (네임스페이스 · 루트 명령어), 네임스페이스 ID = 그 명령어 목록,\n * 명령어 ID · 별칭 = 설명 · 입력 스키마 · 예시 · 오류 · 권한. 없는 target = UNKNOWN_COMMAND.\n */\nexport function help(registry: Registry, target: string | undefined, options: HelpOptions = {}): Help {\n const id = target?.trim() ?? \"\"\n if (id === \"\") {\n const root = registry.namespaces.get(\"\")!\n const out: RootHelp = {\n kind: \"root\",\n namespaces: root.namespaces.map((n) => namespaceSummary(registry, n)),\n commands: root.commands.map((c) => commandSummary(registry.commands.get(c)!, options)),\n }\n if (root.description !== undefined) out.description = root.description\n return out\n }\n const ns = registry.namespaces.get(id)\n if (ns) {\n const out: NamespaceHelp = {\n kind: \"namespace\",\n id,\n namespaces: ns.namespaces.map((n) => namespaceSummary(registry, n)),\n commands: ns.commands.map((c) => commandSummary(registry.commands.get(c)!, options)),\n }\n if (ns.description !== undefined) out.description = ns.description\n const self = registry.commands.get(id)\n if (self) out.command = commandHelp(self, options)\n return out\n }\n return commandHelp(findCommand(registry, id), options)\n}\n\nfunction namespaceSummary(registry: Registry, id: string): HelpNamespaceSummary {\n const description = registry.namespaces.get(id)?.description\n const first = description?.split(\"\\n\").find((l) => l.trim() !== \"\")\n return first === undefined ? { id } : { id, description: first.replace(/^#+\\s*/, \"\").trim() }\n}\n\nfunction commandSummary(entry: RegisteredCommand, options: HelpOptions): HelpCommandSummary {\n const c = entry.command\n const out: HelpCommandSummary = {\n id: entry.id,\n description: c.description,\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n }\n const tool = options.toolFor?.(entry)\n if (tool !== undefined) out.tool = tool\n return out\n}\n\nfunction commandHelp(entry: RegisteredCommand, options: HelpOptions): CommandHelp {\n const { file: _file, ...meta } = describeCommand(entry)\n const c = entry.command\n const errors = [\"INVALID_ARGUMENT\"]\n if (!c.readOnly || c.scopes.length > 0) errors.push(\"UNAUTHENTICATED\", \"PERMISSION_DENIED\")\n if (c.requiresConfirmation) errors.push(\"INPUT_UNAVAILABLE\", \"INPUT_DECLINED\")\n const out: CommandHelp = { kind: \"command\", ...meta, errors }\n const tool = options.toolFor?.(entry)\n if (tool !== undefined) out.tool = tool\n return out\n}\n\n/** help 의 사람용 텍스트 (MCP text content). 구조는 structuredContent 가 원본 */\nexport function formatHelp(value: Help, call = \"execute\"): string {\n const lines: string[] = []\n const hint = (target: string) => `${call}({ command: \"help\", args: { target: \"${target}\" } })`\n const listCommands = (commands: HelpCommandSummary[]) => {\n if (commands.length === 0) return\n lines.push(\"Commands:\")\n const width = Math.max(...commands.map((c) => c.id.length))\n for (const c of commands) {\n const flags = safetyFlags(c)\n const via = c.tool !== undefined ? ` (via ${c.tool})` : \"\"\n lines.push(` ${c.id.padEnd(width)} ${c.description}${flags ? ` [${flags}]` : \"\"}${via}`)\n }\n }\n const listNamespaces = (namespaces: HelpNamespaceSummary[]) => {\n if (namespaces.length === 0) return\n lines.push(\"Namespaces:\")\n const width = Math.max(...namespaces.map((n) => n.id.length))\n for (const n of namespaces) lines.push(` ${n.id.padEnd(width)} ${n.description ?? \"\"}`.trimEnd())\n }\n\n if (value.kind === \"command\") {\n lines.push(`${value.id}: ${value.description}`)\n if (value.aliases.length > 0) lines.push(`Aliases: ${value.aliases.join(\", \")}`)\n const flags = safetyFlags(value)\n lines.push(`Safety: ${flags || \"none\"}`)\n if (value.scopes.length > 0) lines.push(`Scopes: ${value.scopes.join(\", \")}`)\n if (value.tool !== undefined) lines.push(`Tool: ${value.tool}`)\n lines.push(\"Input schema:\", JSON.stringify(value.inputSchema, null, 2))\n if (value.examples.length > 0) {\n lines.push(\"Examples:\")\n for (const e of value.examples) lines.push(` ${JSON.stringify(e)}`)\n }\n lines.push(`Errors: ${value.errors.join(\", \")}`)\n return lines.join(\"\\n\")\n }\n\n if (value.kind === \"namespace\") lines.push(value.id)\n if (value.description !== undefined) lines.push(value.description, \"\")\n listNamespaces(value.namespaces)\n listCommands(value.commands)\n if (value.kind === \"namespace\" && value.command !== undefined) {\n lines.push(\"\", formatHelp(value.command, call))\n }\n lines.push(\"\", `Details: ${hint(value.kind === \"root\" ? \"<namespace or command>\" : `${value.id}.<command>`)}`)\n return lines.join(\"\\n\").replace(/^\\n+/, \"\")\n}\n\nfunction safetyFlags(c: { readOnly: boolean; destructive: boolean; requiresConfirmation: boolean }): string {\n const flags: string[] = []\n if (c.readOnly) flags.push(\"read-only\")\n if (c.destructive) flags.push(\"destructive\")\n if (c.requiresConfirmation) flags.push(\"requires confirmation\")\n return flags.join(\", \")\n}\n"]}
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/mcp/help.ts"],"names":[],"mappings":"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","sourcesContent":["import { findCommand } from \"../invoke.ts\"\nimport { describeCommand, type ManifestCommand } from \"../manifest.ts\"\nimport type { RegisteredCommand, Registry } from \"../registry.ts\"\n\n/** help 의 예약 명령어 이름. 루트 세그먼트 help 는 Registry 에서 금지 */\nexport const HELP_COMMAND = \"help\"\n\nexport interface HelpNamespaceSummary {\n id: string\n /** _index.md 첫 줄 */\n description?: string\n}\n\nexport interface HelpCommandSummary {\n id: string\n description: string\n readOnly: boolean\n destructive: boolean\n requiresConfirmation: boolean\n /** 승인이 조건식일 때만 (§4 승인) */\n needsApproval?: \"conditional\"\n /** split 노출에서 이 명령어를 호출할 도구 (query · mutate). execute 노출에서는 없음 */\n tool?: string\n}\n\n/** execute({ command: \"help\" }) */\nexport interface RootHelp {\n kind: \"root\"\n /** commands/_index.md */\n description?: string\n namespaces: HelpNamespaceSummary[]\n /** 루트 직속 명령어 */\n commands: HelpCommandSummary[]\n}\n\n/** execute({ command: \"help\", args: { target: \"users\" } }) */\nexport interface NamespaceHelp {\n kind: \"namespace\"\n id: string\n /** _index.md 전체 */\n description?: string\n namespaces: HelpNamespaceSummary[]\n commands: HelpCommandSummary[]\n /** 같은 ID 의 명령어 (users/index.ts) */\n command?: CommandHelp\n}\n\n/** execute({ command: \"help\", args: { target: \"users.get\" } }) */\nexport interface CommandHelp extends Omit<ManifestCommand, \"file\"> {\n kind: \"command\"\n /** 이 명령어 호출이 돌려줄 수 있는 구조화 오류 code */\n errors: string[]\n tool?: string\n}\n\nexport type Help = RootHelp | NamespaceHelp | CommandHelp\n\nexport interface HelpOptions {\n /** 명령어 → 호출할 도구 이름. split 노출이 지정 */\n toolFor?: (entry: RegisteredCommand) => string | undefined\n}\n\n/**\n * help 3단계: target 없음 = 루트 (네임스페이스 · 루트 명령어), 네임스페이스 ID = 그 명령어 목록,\n * 명령어 ID · 별칭 = 설명 · 입력 스키마 · 예시 · 오류 · 권한. 없는 target = UNKNOWN_COMMAND.\n */\nexport function help(registry: Registry, target: string | undefined, options: HelpOptions = {}): Help {\n const id = target?.trim() ?? \"\"\n if (id === \"\") {\n const root = registry.namespaces.get(\"\")!\n const out: RootHelp = {\n kind: \"root\",\n namespaces: root.namespaces.map((n) => namespaceSummary(registry, n)),\n commands: root.commands.map((c) => commandSummary(registry.commands.get(c)!, options)),\n }\n if (root.description !== undefined) out.description = root.description\n return out\n }\n const ns = registry.namespaces.get(id)\n if (ns) {\n const out: NamespaceHelp = {\n kind: \"namespace\",\n id,\n namespaces: ns.namespaces.map((n) => namespaceSummary(registry, n)),\n commands: ns.commands.map((c) => commandSummary(registry.commands.get(c)!, options)),\n }\n if (ns.description !== undefined) out.description = ns.description\n const self = registry.commands.get(id)\n if (self) out.command = commandHelp(self, options)\n return out\n }\n return commandHelp(findCommand(registry, id), options)\n}\n\nfunction namespaceSummary(registry: Registry, id: string): HelpNamespaceSummary {\n const description = registry.namespaces.get(id)?.description\n const first = description?.split(\"\\n\").find((l) => l.trim() !== \"\")\n return first === undefined ? { id } : { id, description: first.replace(/^#+\\s*/, \"\").trim() }\n}\n\nfunction commandSummary(entry: RegisteredCommand, options: HelpOptions): HelpCommandSummary {\n const c = entry.command\n const out: HelpCommandSummary = {\n id: entry.id,\n description: c.description,\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n }\n if (c.needsApproval !== undefined) out.needsApproval = \"conditional\"\n const tool = options.toolFor?.(entry)\n if (tool !== undefined) out.tool = tool\n return out\n}\n\nfunction commandHelp(entry: RegisteredCommand, options: HelpOptions): CommandHelp {\n const { file: _file, ...meta } = describeCommand(entry)\n const c = entry.command\n const errors = [\"INVALID_ARGUMENT\"]\n if (!c.readOnly || c.scopes.length > 0) errors.push(\"UNAUTHENTICATED\", \"PERMISSION_DENIED\")\n // 승인 (항상 · 조건식) = ask 방식의 확인 오류. APPROVAL_REQUIRED 는 표면 설정 · 행위자에 따라 승인 명령어 모두에서 가능 (§4 승인)\n if (c.requiresConfirmation || c.needsApproval !== undefined) errors.push(\"INPUT_UNAVAILABLE\", \"INPUT_DECLINED\")\n const out: CommandHelp = { kind: \"command\", ...meta, errors }\n const tool = options.toolFor?.(entry)\n if (tool !== undefined) out.tool = tool\n return out\n}\n\n/** help 의 사람용 텍스트 (MCP text content). 구조는 structuredContent 가 원본 */\nexport function formatHelp(value: Help, call = \"execute\"): string {\n const lines: string[] = []\n const hint = (target: string) => `${call}({ command: \"help\", args: { target: \"${target}\" } })`\n const listCommands = (commands: HelpCommandSummary[]) => {\n if (commands.length === 0) return\n lines.push(\"Commands:\")\n const width = Math.max(...commands.map((c) => c.id.length))\n for (const c of commands) {\n const flags = safetyFlags(c)\n const via = c.tool !== undefined ? ` (via ${c.tool})` : \"\"\n lines.push(` ${c.id.padEnd(width)} ${c.description}${flags ? ` [${flags}]` : \"\"}${via}`)\n }\n }\n const listNamespaces = (namespaces: HelpNamespaceSummary[]) => {\n if (namespaces.length === 0) return\n lines.push(\"Namespaces:\")\n const width = Math.max(...namespaces.map((n) => n.id.length))\n for (const n of namespaces) lines.push(` ${n.id.padEnd(width)} ${n.description ?? \"\"}`.trimEnd())\n }\n\n if (value.kind === \"command\") {\n lines.push(`${value.id}: ${value.description}`)\n if (value.aliases.length > 0) lines.push(`Aliases: ${value.aliases.join(\", \")}`)\n const flags = safetyFlags(value)\n lines.push(`Safety: ${flags || \"none\"}`)\n if (value.scopes.length > 0) lines.push(`Scopes: ${value.scopes.join(\", \")}`)\n if (value.tool !== undefined) lines.push(`Tool: ${value.tool}`)\n lines.push(\"Input schema:\", JSON.stringify(value.inputSchema, null, 2))\n if (value.examples.length > 0) {\n lines.push(\"Examples:\")\n for (const e of value.examples) lines.push(` ${JSON.stringify(e)}`)\n }\n lines.push(`Errors: ${value.errors.join(\", \")}`)\n return lines.join(\"\\n\")\n }\n\n if (value.kind === \"namespace\") lines.push(value.id)\n if (value.description !== undefined) lines.push(value.description, \"\")\n listNamespaces(value.namespaces)\n listCommands(value.commands)\n if (value.kind === \"namespace\" && value.command !== undefined) {\n lines.push(\"\", formatHelp(value.command, call))\n }\n lines.push(\"\", `Details: ${hint(value.kind === \"root\" ? \"<namespace or command>\" : `${value.id}.<command>`)}`)\n return lines.join(\"\\n\").replace(/^\\n+/, \"\")\n}\n\nfunction safetyFlags(c: { readOnly: boolean; destructive: boolean; requiresConfirmation: boolean; needsApproval?: \"conditional\" }): string {\n const flags: string[] = []\n if (c.readOnly) flags.push(\"read-only\")\n if (c.destructive) flags.push(\"destructive\")\n if (c.requiresConfirmation) flags.push(\"requires confirmation\")\n else if (c.needsApproval !== undefined) flags.push(\"may require confirmation\")\n return flags.join(\", \")\n}\n"]}
|
package/dist/mcp/http.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
2
|
import type { MextApp } from "../command.ts";
|
|
3
|
+
import { type BuiltinSurface, type ReportedClient } from "../caller.ts";
|
|
3
4
|
import { type Principal } from "../principal.ts";
|
|
4
5
|
import type { Registry } from "../registry.ts";
|
|
5
6
|
import { type RouteEntry } from "../route.ts";
|
|
@@ -12,6 +13,12 @@ export declare const MAX_BODY_BYTES: number;
|
|
|
12
13
|
export interface McpAuthRequest {
|
|
13
14
|
/** Authorization 헤더 원문 */
|
|
14
15
|
authorization: string | undefined;
|
|
16
|
+
/** 요청 헤더 (세션 쿠키 · 프록시가 붙인 헤더). 복사본 */
|
|
17
|
+
headers: Headers;
|
|
18
|
+
/** 어댑터 기본 표면. POST /mcp = "mcp". 반환 Principal.surface 로 논리 표면을 바꿀 수 있다 */
|
|
19
|
+
surface: BuiltinSurface;
|
|
20
|
+
/** 요청 _meta 의 clientInfo (2026-07-28). 자가 신고 값: 주체 · 행위자 · 표면 판정에 쓰지 않는다 */
|
|
21
|
+
client: ReportedClient | undefined;
|
|
15
22
|
}
|
|
16
23
|
export interface McpHttpOptions {
|
|
17
24
|
registry: Registry;
|
|
@@ -28,7 +35,7 @@ export interface McpHttpOptions {
|
|
|
28
35
|
/** 기본 3100. 0 = 임의 포트 */
|
|
29
36
|
port?: number;
|
|
30
37
|
/**
|
|
31
|
-
* Origin 허용 목록 (https://app.example.com 형식, "*" =
|
|
38
|
+
* Origin 허용 목록 (https://app.example.com · chrome-extension://<id> 형식, "*" = 전체, "loopback" = loopback).
|
|
32
39
|
* 미지정 = loopback (localhost · 127.0.0.1 · [::1], 포트 무관) 만. Origin 헤더 없는 요청은 항상 통과
|
|
33
40
|
*/
|
|
34
41
|
allowedOrigins?: string[];
|
|
@@ -63,6 +70,10 @@ export interface McpHttpOptions {
|
|
|
63
70
|
taskTiming?: McpCoreOptions["taskTiming"];
|
|
64
71
|
/** McpCoreOptions.taskExecution. handler.js = "waitUntil" */
|
|
65
72
|
taskExecution?: McpCoreOptions["taskExecution"];
|
|
73
|
+
/** 감사 (config.audit, §11.1) */
|
|
74
|
+
audit?: McpCoreOptions["audit"];
|
|
75
|
+
/** 승인의 표면별 확인 방식 (config.approval, §4 승인) */
|
|
76
|
+
approval?: McpCoreOptions["approval"];
|
|
66
77
|
}
|
|
67
78
|
/** fetch 의 두 번째 인자. waitUntil = 응답 후 실행 유지 (handler.js 플랫폼, tasks §10) */
|
|
68
79
|
export interface McpFetchContext {
|
|
@@ -110,5 +121,8 @@ export interface McpHttpServer {
|
|
|
110
121
|
}
|
|
111
122
|
/** createMcpHttpHandler + node:http listen. 기본 127.0.0.1:3100 */
|
|
112
123
|
export declare function startMcpHttpServer(options: McpHttpOptions): Promise<McpHttpServer>;
|
|
113
|
-
/**
|
|
124
|
+
/**
|
|
125
|
+
* Origin 허용 여부. allowed 미지정 = loopback 만, 지정 = 목록의 origin 과 정확히 일치 ("*" = 전체, "loopback" = loopback).
|
|
126
|
+
* http · https 외 scheme (chrome-extension://<id>) = URL.origin 이 "null" 이라 목록과 문자열 비교
|
|
127
|
+
*/
|
|
114
128
|
export declare function originAllowed(origin: string, allowed: readonly string[] | undefined): boolean;
|