@obov/mext 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-cli.js +2 -1
- package/dist/build-cli.js.map +1 -1
- package/dist/cli/build.js +2 -1
- package/dist/cli/build.js.map +1 -1
- package/dist/mcp/install.d.ts +1 -1
- package/dist/mcp/install.js +3 -2
- package/dist/mcp/install.js.map +1 -1
- package/dist/mcp/stdio.js +25 -0
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/runtime.d.ts +10 -0
- package/dist/runtime.js +11 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +3 -2
package/dist/build-cli.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import { clientManifest } from "./client/manifest.js";
|
|
6
6
|
import { CLI_BUILTIN_COMMANDS, LOCAL_BIN_BUILTIN_COMMANDS } from "./config.js";
|
|
7
7
|
import { MextBuildError } from "./errors.js";
|
|
8
|
+
import { BUN_ENGINE } from "./runtime.js";
|
|
8
9
|
import { envPrefix } from "./remote/credentials.js";
|
|
9
10
|
/**
|
|
10
11
|
* 고객 CLI 패키지 (.mext/cli/, §5). mext build 가 config.cli 가 있을 때 호출.
|
|
@@ -117,7 +118,7 @@ export async function buildCustomerCli(options) {
|
|
|
117
118
|
type: "module",
|
|
118
119
|
bin: { [cli.bin]: `./${CLI_BIN_FILE}` },
|
|
119
120
|
files: [CLI_BIN_FILE],
|
|
120
|
-
engines: { node: CLI_NODE_ENGINE },
|
|
121
|
+
engines: { node: CLI_NODE_ENGINE, bun: BUN_ENGINE },
|
|
121
122
|
};
|
|
122
123
|
writeFileSync(join(dir, "package.json"), `${JSON.stringify(pkg, null, 2)}\n`);
|
|
123
124
|
writeFileSync(join(dir, "README.md"), readme(cli.bin, url, packageName));
|
package/dist/build-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-cli.js","sourceRoot":"","sources":["../src/build-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\"\nimport { isBuiltin } from \"node:module\"\nimport { join, resolve } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport type { RolldownModule, RolldownOutputItem } from \"./build.ts\"\nimport { clientManifest } from \"./client/manifest.ts\"\nimport type { CustomerCliConfig } from \"./client/main.ts\"\nimport { CLI_BUILTIN_COMMANDS, LOCAL_BIN_BUILTIN_COMMANDS, type CliConfig } from \"./config.ts\"\nimport { MextBuildError, type BuildIssue } from \"./errors.ts\"\nimport type { BuildManifest } from \"./manifest.ts\"\nimport type { Registry } from \"./registry.ts\"\nimport { envPrefix } from \"./remote/credentials.ts\"\n\n/**\n * 고객 CLI 패키지 (.mext/cli/, §5). mext build 가 config.cli 가 있을 때 호출.\n * bin.js = client/main.ts (고객 CLI 런타임) + 인라인 설정 (CustomerCliConfig) 의 rolldown 단일 번들. 외부 = Node 내장만\n * (의존성 전부 번들 → package.json dependencies 없음). 런타임은 Zod · MCP 서버 SDK · 핸들러 · 스캔 · 빌드 코드를 import 하지 않는다\n */\n\n/** .mext/ 아래 고객 CLI 폴더 */\nexport const CLI_DIR = \"cli\"\nexport const CLI_BIN_FILE = \"bin.js\"\n/** 고객 CLI package.json engines.node (번들 target node22, 타입 제거 불필요) */\nexport const CLI_NODE_ENGINE = \">=22\"\n\n/** 고객 CLI 런타임 엔트리 (src = .ts, dist = .js: 이 파일과 같은 확장자) */\nconst RUNTIME_ENTRY = fileURLToPath(new URL(`./client/main${import.meta.url.slice(import.meta.url.lastIndexOf(\".\"))}`, import.meta.url))\nconst ENTRY_ID = \"\\0mext-customer-cli\"\n\nexport interface CustomerCliBuild {\n /** 절대 경로 (.mext/cli) */\n dir: string\n bin: string\n packageName: string\n version: string\n form: \"bundled\" | \"universal\"\n /** .mext/cli 기준 생성 파일 (정렬) */\n files: string[]\n /** bin.js 바이트 */\n size: number\n}\n\n/** cli 설정이 있을 때 루트 세그먼트가 고객 CLI 내장 명령 (login · logout · mcp, 로컬 bin = help · mcp) 과 겹치면 RESERVED_ID */\nexport function customerCliIssues(cli: CliConfig | undefined, registry: Registry): BuildIssue[] {\n if (!cli) return []\n const builtins = cli.local === true ? LOCAL_BIN_BUILTIN_COMMANDS : CLI_BUILTIN_COMMANDS\n // 루트 별칭은 Registry 가 금지하므로 루트 명령어 · 네임스페이스만 본다\n const root = registry.namespaces.get(\"\")\n const ids = new Set([...(root?.commands ?? []), ...(root?.namespaces ?? [])])\n return [...ids]\n .filter((id) => builtins.includes(id))\n .sort()\n .map((id) => {\n const file = registry.commands.get(id)?.file\n return {\n code: \"RESERVED_ID\",\n message: `\"${id}\" is a built-in command of the customer CLI (${cli.bin} ${id}). Rename it or remove cli from mext.config.ts`,\n id,\n ...(file !== undefined ? { file } : {}),\n }\n })\n}\n\nexport interface BuildCustomerCliOptions {\n rolldown: RolldownModule\n /** 도입 프로젝트 루트 (package.json version) */\n cwd: string\n /** .mext/ 절대 경로 */\n outDir: string\n cli: CliConfig\n manifest: BuildManifest\n}\n\nexport async function buildCustomerCli(options: BuildCustomerCliOptions): Promise<CustomerCliBuild> {\n const { cli, manifest } = options\n if (cli.url === undefined) throw new Error(\"mext build: customer CLI requires cli.url\")\n const url = cli.url\n const dir = join(options.outDir, CLI_DIR)\n mkdirSync(dir, { recursive: true })\n const version = cli.version ?? projectVersion(options.cwd) ?? \"0.0.0\"\n const packageName = cli.packageName ?? cli.bin\n const bundled = cli.manifest !== false\n const config: CustomerCliConfig = {\n bin: cli.bin,\n url,\n version,\n packageName,\n mextVersion: manifest.mextVersion,\n manifestHash: manifest.manifestHash,\n ...(bundled ? { manifest: clientManifest(manifest) } : {}),\n }\n const errorsFile = cli.errors === undefined ? undefined : resolve(options.cwd, cli.errors)\n if (errorsFile !== undefined && !existsSync(errorsFile)) {\n throw new MextBuildError([{ code: \"INVALID_CONFIG\", message: `cli.errors file not found: ${cli.errors}` }])\n }\n const entry = [\n `import { main } from ${JSON.stringify(RUNTIME_ENTRY)}`,\n ...(errorsFile !== undefined ? [`import formatError from ${JSON.stringify(errorsFile)}`] : []),\n \"\",\n errorsFile !== undefined\n ? `await main(${JSON.stringify(config)}, { formatError })`\n : `await main(${JSON.stringify(config)})`,\n \"\",\n ].join(\"\\n\")\n\n let output: readonly RolldownOutputItem[]\n try {\n ;({ output } = await options.rolldown.build({\n cwd: options.cwd,\n input: { bin: ENTRY_ID },\n platform: \"node\",\n external: (id: string): boolean => id.startsWith(\"node:\") || isBuiltin(id),\n plugins: [\n {\n name: \"mext-customer-cli\",\n resolveId: (id: string) => (id === ENTRY_ID ? ENTRY_ID : null),\n load: (id: string) => (id === ENTRY_ID ? entry : null),\n },\n ],\n transform: { target: \"node22\" },\n logLevel: \"warn\",\n output: {\n dir,\n format: \"esm\",\n entryFileNames: CLI_BIN_FILE,\n banner: \"#!/usr/bin/env node\",\n codeSplitting: false,\n sourcemap: false,\n },\n }))\n } catch (error) {\n throw new MextBuildError([\n { code: \"BUNDLE_FAILED\", message: `customer CLI: ${error instanceof Error ? error.message : String(error)}` },\n ])\n }\n const emitted = output.map((o) => o.fileName)\n if (emitted.length !== 1 || emitted[0] !== CLI_BIN_FILE) {\n throw new Error(`mext build: customer CLI bundle must be a single ${CLI_BIN_FILE} (got ${emitted.join(\", \")})`)\n }\n const binPath = join(dir, CLI_BIN_FILE)\n chmodSync(binPath, 0o755)\n\n const pkg = {\n name: packageName,\n version,\n description: `Command-line client for ${url}`,\n type: \"module\",\n bin: { [cli.bin]: `./${CLI_BIN_FILE}` },\n files: [CLI_BIN_FILE],\n engines: { node: CLI_NODE_ENGINE },\n }\n writeFileSync(join(dir, \"package.json\"), `${JSON.stringify(pkg, null, 2)}\\n`)\n writeFileSync(join(dir, \"README.md\"), readme(cli.bin, url, packageName))\n\n return {\n dir,\n bin: cli.bin,\n packageName,\n version,\n form: bundled ? \"bundled\" : \"universal\",\n files: [CLI_BIN_FILE, \"README.md\", \"package.json\"],\n size: statSync(binPath).size,\n }\n}\n\nexport function projectVersion(cwd: string): string | undefined {\n try {\n const pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as { version?: unknown }\n return typeof pkg.version === \"string\" && pkg.version !== \"\" ? pkg.version : undefined\n } catch {\n return undefined\n }\n}\n\nfunction readme(bin: string, url: string, packageName: string): string {\n const prefix = envPrefix(bin)\n return [\n `# ${packageName}`,\n \"\",\n `Command-line client for ${url}. Generated by mext build.`,\n \"\",\n \"```sh\",\n `npm install -g ${packageName}`,\n `${bin} login # log in (browser, device code, or --with-token)`,\n `${bin} help # commands`,\n `${bin} <namespace> <command> --help`,\n `${bin} mcp install # MCP client registration commands`,\n `${bin} logout`,\n \"```\",\n \"\",\n \"Environment:\",\n \"\",\n `- \\`${prefix}_TOKEN\\`: API token (used instead of the stored login)`,\n `- \\`${prefix}_URL\\`: server URL (default: ${url})`,\n `- \\`${prefix}_NO_KEYRING=1\\`: store the token in \\`~/.config/${bin}/credentials.json\\` instead of the OS keychain`,\n `- \\`${prefix}_CACHE_DIR\\`: server schema cache folder (default: \\`\\${XDG_CACHE_HOME:-~/.cache}/${bin}\\`)`,\n \"\",\n \"Exit codes: 0 success · 1 error · 2 invalid arguments or unknown command · 77 authentication or permission · 130 interrupted.\",\n \"\",\n ].join(\"\\n\")\n}\n"]}
|
|
1
|
+
{"version":3,"file":"build-cli.js","sourceRoot":"","sources":["../src/build-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\"\nimport { isBuiltin } from \"node:module\"\nimport { join, resolve } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport type { RolldownModule, RolldownOutputItem } from \"./build.ts\"\nimport { clientManifest } from \"./client/manifest.ts\"\nimport type { CustomerCliConfig } from \"./client/main.ts\"\nimport { CLI_BUILTIN_COMMANDS, LOCAL_BIN_BUILTIN_COMMANDS, type CliConfig } from \"./config.ts\"\nimport { MextBuildError, type BuildIssue } from \"./errors.ts\"\nimport type { BuildManifest } from \"./manifest.ts\"\nimport type { Registry } from \"./registry.ts\"\nimport { BUN_ENGINE } from \"./runtime.ts\"\nimport { envPrefix } from \"./remote/credentials.ts\"\n\n/**\n * 고객 CLI 패키지 (.mext/cli/, §5). mext build 가 config.cli 가 있을 때 호출.\n * bin.js = client/main.ts (고객 CLI 런타임) + 인라인 설정 (CustomerCliConfig) 의 rolldown 단일 번들. 외부 = Node 내장만\n * (의존성 전부 번들 → package.json dependencies 없음). 런타임은 Zod · MCP 서버 SDK · 핸들러 · 스캔 · 빌드 코드를 import 하지 않는다\n */\n\n/** .mext/ 아래 고객 CLI 폴더 */\nexport const CLI_DIR = \"cli\"\nexport const CLI_BIN_FILE = \"bin.js\"\n/** 고객 CLI package.json engines.node (번들 target node22, 타입 제거 불필요) */\nexport const CLI_NODE_ENGINE = \">=22\"\n\n/** 고객 CLI 런타임 엔트리 (src = .ts, dist = .js: 이 파일과 같은 확장자) */\nconst RUNTIME_ENTRY = fileURLToPath(new URL(`./client/main${import.meta.url.slice(import.meta.url.lastIndexOf(\".\"))}`, import.meta.url))\nconst ENTRY_ID = \"\\0mext-customer-cli\"\n\nexport interface CustomerCliBuild {\n /** 절대 경로 (.mext/cli) */\n dir: string\n bin: string\n packageName: string\n version: string\n form: \"bundled\" | \"universal\"\n /** .mext/cli 기준 생성 파일 (정렬) */\n files: string[]\n /** bin.js 바이트 */\n size: number\n}\n\n/** cli 설정이 있을 때 루트 세그먼트가 고객 CLI 내장 명령 (login · logout · mcp, 로컬 bin = help · mcp) 과 겹치면 RESERVED_ID */\nexport function customerCliIssues(cli: CliConfig | undefined, registry: Registry): BuildIssue[] {\n if (!cli) return []\n const builtins = cli.local === true ? LOCAL_BIN_BUILTIN_COMMANDS : CLI_BUILTIN_COMMANDS\n // 루트 별칭은 Registry 가 금지하므로 루트 명령어 · 네임스페이스만 본다\n const root = registry.namespaces.get(\"\")\n const ids = new Set([...(root?.commands ?? []), ...(root?.namespaces ?? [])])\n return [...ids]\n .filter((id) => builtins.includes(id))\n .sort()\n .map((id) => {\n const file = registry.commands.get(id)?.file\n return {\n code: \"RESERVED_ID\",\n message: `\"${id}\" is a built-in command of the customer CLI (${cli.bin} ${id}). Rename it or remove cli from mext.config.ts`,\n id,\n ...(file !== undefined ? { file } : {}),\n }\n })\n}\n\nexport interface BuildCustomerCliOptions {\n rolldown: RolldownModule\n /** 도입 프로젝트 루트 (package.json version) */\n cwd: string\n /** .mext/ 절대 경로 */\n outDir: string\n cli: CliConfig\n manifest: BuildManifest\n}\n\nexport async function buildCustomerCli(options: BuildCustomerCliOptions): Promise<CustomerCliBuild> {\n const { cli, manifest } = options\n if (cli.url === undefined) throw new Error(\"mext build: customer CLI requires cli.url\")\n const url = cli.url\n const dir = join(options.outDir, CLI_DIR)\n mkdirSync(dir, { recursive: true })\n const version = cli.version ?? projectVersion(options.cwd) ?? \"0.0.0\"\n const packageName = cli.packageName ?? cli.bin\n const bundled = cli.manifest !== false\n const config: CustomerCliConfig = {\n bin: cli.bin,\n url,\n version,\n packageName,\n mextVersion: manifest.mextVersion,\n manifestHash: manifest.manifestHash,\n ...(bundled ? { manifest: clientManifest(manifest) } : {}),\n }\n const errorsFile = cli.errors === undefined ? undefined : resolve(options.cwd, cli.errors)\n if (errorsFile !== undefined && !existsSync(errorsFile)) {\n throw new MextBuildError([{ code: \"INVALID_CONFIG\", message: `cli.errors file not found: ${cli.errors}` }])\n }\n const entry = [\n `import { main } from ${JSON.stringify(RUNTIME_ENTRY)}`,\n ...(errorsFile !== undefined ? [`import formatError from ${JSON.stringify(errorsFile)}`] : []),\n \"\",\n errorsFile !== undefined\n ? `await main(${JSON.stringify(config)}, { formatError })`\n : `await main(${JSON.stringify(config)})`,\n \"\",\n ].join(\"\\n\")\n\n let output: readonly RolldownOutputItem[]\n try {\n ;({ output } = await options.rolldown.build({\n cwd: options.cwd,\n input: { bin: ENTRY_ID },\n platform: \"node\",\n external: (id: string): boolean => id.startsWith(\"node:\") || isBuiltin(id),\n plugins: [\n {\n name: \"mext-customer-cli\",\n resolveId: (id: string) => (id === ENTRY_ID ? ENTRY_ID : null),\n load: (id: string) => (id === ENTRY_ID ? entry : null),\n },\n ],\n transform: { target: \"node22\" },\n logLevel: \"warn\",\n output: {\n dir,\n format: \"esm\",\n entryFileNames: CLI_BIN_FILE,\n banner: \"#!/usr/bin/env node\",\n codeSplitting: false,\n sourcemap: false,\n },\n }))\n } catch (error) {\n throw new MextBuildError([\n { code: \"BUNDLE_FAILED\", message: `customer CLI: ${error instanceof Error ? error.message : String(error)}` },\n ])\n }\n const emitted = output.map((o) => o.fileName)\n if (emitted.length !== 1 || emitted[0] !== CLI_BIN_FILE) {\n throw new Error(`mext build: customer CLI bundle must be a single ${CLI_BIN_FILE} (got ${emitted.join(\", \")})`)\n }\n const binPath = join(dir, CLI_BIN_FILE)\n chmodSync(binPath, 0o755)\n\n const pkg = {\n name: packageName,\n version,\n description: `Command-line client for ${url}`,\n type: \"module\",\n bin: { [cli.bin]: `./${CLI_BIN_FILE}` },\n files: [CLI_BIN_FILE],\n engines: { node: CLI_NODE_ENGINE, bun: BUN_ENGINE },\n }\n writeFileSync(join(dir, \"package.json\"), `${JSON.stringify(pkg, null, 2)}\\n`)\n writeFileSync(join(dir, \"README.md\"), readme(cli.bin, url, packageName))\n\n return {\n dir,\n bin: cli.bin,\n packageName,\n version,\n form: bundled ? \"bundled\" : \"universal\",\n files: [CLI_BIN_FILE, \"README.md\", \"package.json\"],\n size: statSync(binPath).size,\n }\n}\n\nexport function projectVersion(cwd: string): string | undefined {\n try {\n const pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as { version?: unknown }\n return typeof pkg.version === \"string\" && pkg.version !== \"\" ? pkg.version : undefined\n } catch {\n return undefined\n }\n}\n\nfunction readme(bin: string, url: string, packageName: string): string {\n const prefix = envPrefix(bin)\n return [\n `# ${packageName}`,\n \"\",\n `Command-line client for ${url}. Generated by mext build.`,\n \"\",\n \"```sh\",\n `npm install -g ${packageName}`,\n `${bin} login # log in (browser, device code, or --with-token)`,\n `${bin} help # commands`,\n `${bin} <namespace> <command> --help`,\n `${bin} mcp install # MCP client registration commands`,\n `${bin} logout`,\n \"```\",\n \"\",\n \"Environment:\",\n \"\",\n `- \\`${prefix}_TOKEN\\`: API token (used instead of the stored login)`,\n `- \\`${prefix}_URL\\`: server URL (default: ${url})`,\n `- \\`${prefix}_NO_KEYRING=1\\`: store the token in \\`~/.config/${bin}/credentials.json\\` instead of the OS keychain`,\n `- \\`${prefix}_CACHE_DIR\\`: server schema cache folder (default: \\`\\${XDG_CACHE_HOME:-~/.cache}/${bin}\\`)`,\n \"\",\n \"Exit codes: 0 success · 1 error · 2 invalid arguments or unknown command · 77 authentication or permission · 130 interrupted.\",\n \"\",\n ].join(\"\\n\")\n}\n"]}
|
package/dist/cli/build.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { relative } from "node:path";
|
|
2
2
|
import { buildProject } from "../build.js";
|
|
3
|
+
import { runtimeExec } from "../runtime.js";
|
|
3
4
|
import { table } from "./help.js";
|
|
4
5
|
import { EXIT, exitCodeOf, formatError } from "./output.js";
|
|
5
6
|
export const BUILD_PROG = "mext build";
|
|
@@ -45,7 +46,7 @@ export function formatBuildSummary(result, cwd) {
|
|
|
45
46
|
...(manifest.routes?.length
|
|
46
47
|
? [...table([["Route", "Methods"], ...manifest.routes.map((r) => [r.path, r.methods.join(" · ")])]).map((l) => ` ${l}`), ""]
|
|
47
48
|
: []),
|
|
48
|
-
`Start:
|
|
49
|
+
`Start: ${runtimeExec} ${dir}/server.js [--stdio]`,
|
|
49
50
|
];
|
|
50
51
|
const cli = result.cli;
|
|
51
52
|
if (cli) {
|
package/dist/cli/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"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","sourcesContent":["import { relative } from \"node:path\"\nimport { buildProject, type BuildOptions, type BuildResult } from \"../build.ts\"\nimport type { BuildManifestCommand } from \"../manifest.ts\"\nimport { runtimeExec } from \"../runtime.ts\"\nimport { table } from \"./help.ts\"\nimport type { CliIo } from \"./io.ts\"\nimport { EXIT, exitCodeOf, formatError } from \"./output.ts\"\n\nexport const BUILD_PROG = \"mext build\"\n\n/**\n * mext build: commands/ → .mext/. 경고 · 오류 = stderr, 성공 요약 · 명령어 표 = stdout.\n * 검증 오류는 MextBuildError 하나에 모아 한 번에 출력, exit 1\n */\nexport async function runBuild(argv: readonly string[], io: CliIo, options: Omit<BuildOptions, \"cwd\"> = {}): Promise<number> {\n for (const tok of argv) {\n if (tok === \"--help\" || tok === \"-h\") {\n io.stdout.write(buildHelp())\n return EXIT.ok\n }\n io.stderr.write(`error: unexpected argument \"${tok}\"\\nRun \"${BUILD_PROG} --help\" for usage.\\n`)\n return EXIT.usage\n }\n let result: BuildResult\n try {\n result = await buildProject({ ...options, cwd: io.cwd })\n } catch (error) {\n io.stderr.write(formatError(error, BUILD_PROG))\n return exitCodeOf(error)\n }\n for (const w of result.warnings) io.stderr.write(`warning: ${w.message}\\n`)\n io.stdout.write(formatBuildSummary(result, io.cwd))\n return EXIT.ok\n}\n\n/** 성공 요약 + 명령어 표 (ID · 안전성 · scopes), next build 의 route 표와 같은 역할 */\nexport function formatBuildSummary(result: BuildResult, cwd: string): string {\n const { manifest } = result\n const dir = relative(cwd, result.outDir) || \".\"\n const n = manifest.commands.length\n const lines = [\n `Built ${dir}/ (${n} command${n === 1 ? \"\" : \"s\"}, buildId ${manifest.buildId})`,\n \"\",\n ...table([\n [\"Command\", \"Safety\", \"Scopes\"],\n ...manifest.commands.map((c) => [c.id, safetyOf(c), c.scopes.join(\", \") || \"-\"]),\n ]).map((l) => ` ${l}`),\n \"\",\n ...(manifest.routes?.length\n ? [...table([[\"Route\", \"Methods\"], ...manifest.routes.map((r) => [r.path, r.methods.join(\" · \")])]).map((l) => ` ${l}`), \"\"]\n : []),\n `Start: ${runtimeExec} ${dir}/server.js [--stdio]`,\n ]\n const cli = result.cli\n if (cli) {\n const kb = (cli.size / 1024).toFixed(1)\n lines.push(\n `Customer CLI: ${dir}/cli/ (${cli.packageName}@${cli.version}, bin ${cli.bin}, ${cli.form}, ${kb} KB). Publish: npm publish ${dir}/cli`,\n )\n }\n const local = result.localBin\n if (local) lines.push(`Local bin: ${dir}/bin.js (bin ${local.bin}@${local.version}). Run: ${local.bin} help (after npm link · npm install -g)`)\n return `${lines.join(\"\\n\")}\\n`\n}\n\n/** readOnly · destructive · confirm. 아무것도 없으면 write */\nfunction safetyOf(c: BuildManifestCommand): string {\n const flags = [\n ...(c.readOnly ? [\"readOnly\"] : []),\n ...(c.destructive ? [\"destructive\"] : []),\n ...(c.requiresConfirmation ? [\"confirm\"] : []),\n ]\n return flags.length === 0 ? \"write\" : flags.join(\" · \")\n}\n\nexport function buildHelp(): string {\n const lines = [\n \"Build commands/ into .mext/ for production (mext start · node .mext/server.js).\",\n \"\",\n \"Usage:\",\n ` ${BUILD_PROG}`,\n \"\",\n \"Output (.mext/):\",\n ...table([\n [\"manifest.json\", \"schemaVersion · mextVersion · buildId · manifestHash · namespaces · commands · resources · prompts · routes (+ module)\"],\n [\"server.js\", \"node .mext/server.js [--stdio]. PORT · HOST environment variables\"],\n [\"handler.js\", \"export default { fetch(request) } (Web Request → Response)\"],\n [\"config.js\", \"mext.config.ts bundle (when present)\"],\n [\"instrumentation.js\", \"instrumentation.ts bundle (when present)\"],\n [\"commands/**/*.js\", \"one module per command\"],\n [\"resources/**/*.js\", \"one module per MCP resource (resources/, when present)\"],\n [\"prompts/**/*.js\", \"one module per MCP prompt (prompts/, when present)\"],\n [\"routes/**/*.js\", \"one module per HTTP route (routes/, when present)\"],\n [\"chunks/\", \"shared code\"],\n [\"cli/\", \"customer CLI npm package (when mext.config.ts has cli): package.json · bin.js · README.md\"],\n [\"bin.js\", \"local bin (cli.local: true, instead of cli/). package.json bin points here\"],\n [\"cli-errors.js\", \"cli.errors bundle for the local bin\"],\n ]).map((l) => ` ${l}`),\n \"\",\n \"Requires rolldown (npm install --save-dev rolldown). Package imports stay external.\",\n \"All validation errors are reported at once (exit 1).\",\n ]\n return `${lines.join(\"\\n\")}\\n`\n}\n"]}
|
package/dist/mcp/install.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export interface McpInstallOptions {
|
|
|
4
4
|
/** Streamable HTTP 엔드포인트. 기본 http://127.0.0.1:3100/mcp. false = HTTP 안내 생략 (로컬 bin 은 stdio 만) */
|
|
5
5
|
url?: string | false;
|
|
6
6
|
/**
|
|
7
|
-
* stdio 실행 명령. 기본 "npx mext dev --stdio" (운영 = "npx mext start --stdio"). false = stdio 안내 생략 (고객 CLI 는 원격만)
|
|
7
|
+
* stdio 실행 명령. 기본 "<npx|bunx> mext dev --stdio" (운영 = "<npx|bunx> mext start --stdio", 현재 런타임 기준). false = stdio 안내 생략 (고객 CLI 는 원격만)
|
|
8
8
|
*/
|
|
9
9
|
stdioCommand?: string | false;
|
|
10
10
|
/** 토큰이 필요한 서버면 Authorization 헤더 예시 포함 */
|
package/dist/mcp/install.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_HOST, DEFAULT_PORT, MCP_PATH } from "./constants.js";
|
|
2
|
+
import { packageExec } from "../runtime.js";
|
|
2
3
|
/**
|
|
3
4
|
* `mext mcp install` · `myapp mcp install` 의 안내 텍스트.
|
|
4
5
|
* MCP 클라이언트 등록 명령만 출력한다. 클라이언트 설정 파일은 쓰지 않는다.
|
|
@@ -6,7 +7,7 @@ import { DEFAULT_HOST, DEFAULT_PORT, MCP_PATH } from "./constants.js";
|
|
|
6
7
|
export function mcpInstallText(options = {}) {
|
|
7
8
|
const name = options.name ?? "mext";
|
|
8
9
|
const url = options.url ?? `http://${DEFAULT_HOST}:${DEFAULT_PORT}${MCP_PATH}`;
|
|
9
|
-
const stdio = options.stdioCommand === undefined ?
|
|
10
|
+
const stdio = options.stdioCommand === undefined ? `${packageExec} mext dev --stdio` : options.stdioCommand;
|
|
10
11
|
const n = shellQuote(name);
|
|
11
12
|
if (url === false) {
|
|
12
13
|
if (stdio === false)
|
|
@@ -38,7 +39,7 @@ export function mcpInstallText(options = {}) {
|
|
|
38
39
|
if (stdio !== false) {
|
|
39
40
|
lines.push("", "Claude Code (stdio, runs commands locally):", ` claude mcp add ${n} -- ${stdio}`);
|
|
40
41
|
if (options.stdioCommand === undefined)
|
|
41
|
-
lines.push(" # production (after mext build):", ` claude mcp add ${n} --
|
|
42
|
+
lines.push(" # production (after mext build):", ` claude mcp add ${n} -- ${packageExec} mext start --stdio`);
|
|
42
43
|
}
|
|
43
44
|
const config = { type: "http", url };
|
|
44
45
|
if (options.auth)
|
package/dist/mcp/install.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/mcp/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/mcp/install.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_HOST, DEFAULT_PORT, MCP_PATH } from \"./constants.ts\"\nimport { packageExec } from \"../runtime.ts\"\n\nexport interface McpInstallOptions {\n /** MCP 클라이언트에 등록할 서버 이름. 기본 \"mext\" */\n name?: string\n /** Streamable HTTP 엔드포인트. 기본 http://127.0.0.1:3100/mcp. false = HTTP 안내 생략 (로컬 bin 은 stdio 만) */\n url?: string | false\n /**\n * stdio 실행 명령. 기본 \"<npx|bunx> mext dev --stdio\" (운영 = \"<npx|bunx> mext start --stdio\", 현재 런타임 기준). false = stdio 안내 생략 (고객 CLI 는 원격만)\n */\n stdioCommand?: string | false\n /** 토큰이 필요한 서버면 Authorization 헤더 예시 포함 */\n auth?: boolean\n}\n\n/**\n * `mext mcp install` · `myapp mcp install` 의 안내 텍스트.\n * MCP 클라이언트 등록 명령만 출력한다. 클라이언트 설정 파일은 쓰지 않는다.\n */\nexport function mcpInstallText(options: McpInstallOptions = {}): string {\n const name = options.name ?? \"mext\"\n const url = options.url ?? `http://${DEFAULT_HOST}:${DEFAULT_PORT}${MCP_PATH}`\n const stdio = options.stdioCommand === undefined ? `${packageExec} mext dev --stdio` : options.stdioCommand\n const n = shellQuote(name)\n if (url === false) {\n if (stdio === false) throw new TypeError(\"mcpInstallText: url and stdioCommand cannot both be false\")\n const [command, ...args] = stdio.split(\" \")\n return [\n `Register the \"${name}\" MCP server with your MCP client.`,\n \"\",\n \"Claude Code (stdio, runs commands locally):\",\n ` claude mcp add ${n} -- ${stdio}`,\n \"\",\n \"Other MCP clients (JSON config):\",\n ...JSON.stringify({ mcpServers: { [name]: { command, args } } }, null, 2)\n .split(\"\\n\")\n .map((l) => ` ${l}`),\n \"\",\n \"This command only prints instructions; it does not modify client configuration files.\",\n ].join(\"\\n\")\n }\n const lines = [\n `Register the \"${name}\" MCP server with your MCP client.`,\n \"\",\n \"Claude Code (Streamable HTTP):\",\n ` claude mcp add --transport http ${n} ${shellQuote(url)}`,\n ]\n if (options.auth) {\n lines.push(\n \" # with an API token:\",\n ` claude mcp add --transport http ${n} ${shellQuote(url)} --header \"Authorization: Bearer <token>\"`,\n )\n }\n if (stdio !== false) {\n lines.push(\"\", \"Claude Code (stdio, runs commands locally):\", ` claude mcp add ${n} -- ${stdio}`)\n if (options.stdioCommand === undefined) lines.push(\" # production (after mext build):\", ` claude mcp add ${n} -- ${packageExec} mext start --stdio`)\n }\n const config: Record<string, unknown> = { type: \"http\", url }\n if (options.auth) config.headers = { Authorization: \"Bearer <token>\" }\n lines.push(\n \"\",\n \"Other MCP clients (JSON config):\",\n ...JSON.stringify({ mcpServers: { [name]: config } }, null, 2)\n .split(\"\\n\")\n .map((l) => ` ${l}`),\n \"\",\n \"This command only prints instructions; it does not modify client configuration files.\",\n )\n return lines.join(\"\\n\")\n}\n\nfunction shellQuote(value: string): string {\n return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : `'${value.replaceAll(\"'\", `'\\\\''`)}'`\n}\n"]}
|
package/dist/mcp/stdio.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { Console } from "node:console";
|
|
1
2
|
import { Writable } from "node:stream";
|
|
2
3
|
import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
|
|
4
|
+
import { isBun } from "../runtime.js";
|
|
3
5
|
import { localPrincipal } from "../principal.js";
|
|
4
6
|
import { createMcpServerFactory } from "./server.js";
|
|
5
7
|
import { narrowListenRequest } from "./subscriptions.js";
|
|
@@ -210,6 +212,7 @@ export function redirectStdout() {
|
|
|
210
212
|
const original = stdout.write;
|
|
211
213
|
const toStderr = (...args) => process.stderr.write.apply(process.stderr, args);
|
|
212
214
|
stdout.write = toStderr;
|
|
215
|
+
const restoreConsole = !isBun ? () => { } : redirectBunConsole(toStderr);
|
|
213
216
|
// EPIPE 등은 wire 의 write 콜백으로 transport 에 전달된다. process.stdout 의 미처리 error 로 죽지 않게
|
|
214
217
|
const ignore = () => { };
|
|
215
218
|
stdout.on("error", ignore);
|
|
@@ -228,8 +231,30 @@ export function redirectStdout() {
|
|
|
228
231
|
restored = true;
|
|
229
232
|
if (stdout.write === toStderr)
|
|
230
233
|
stdout.write = original;
|
|
234
|
+
restoreConsole();
|
|
231
235
|
stdout.off("error", ignore);
|
|
232
236
|
},
|
|
233
237
|
};
|
|
234
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Bun 의 console 은 process.stdout.write 를 거치지 않고 fd 1 에 직접 쓴다.
|
|
241
|
+
* console 메서드를 stderr 로 쓰는 Console 의 메서드로 바꾸고 (Bun 전용 console.write 포함), 원복 함수를 반환한다.
|
|
242
|
+
* Node 의 console 은 process.stdout.write 를 거치므로 바꾸지 않는다 (group 들여쓰기 등 기존 출력 유지)
|
|
243
|
+
*/
|
|
244
|
+
function redirectBunConsole(toStderr) {
|
|
245
|
+
const target = console;
|
|
246
|
+
const stderrConsole = new Console({ stdout: process.stderr, stderr: process.stderr });
|
|
247
|
+
const saved = new Map();
|
|
248
|
+
for (const key of Object.keys(target)) {
|
|
249
|
+
const replacement = key === "write" ? toStderr : typeof stderrConsole[key] === "function" ? stderrConsole[key].bind(stderrConsole) : undefined;
|
|
250
|
+
if (typeof target[key] !== "function" || key === "Console" || replacement === undefined)
|
|
251
|
+
continue;
|
|
252
|
+
saved.set(key, target[key]);
|
|
253
|
+
target[key] = replacement;
|
|
254
|
+
}
|
|
255
|
+
return () => {
|
|
256
|
+
for (const [key, value] of saved)
|
|
257
|
+
target[key] = value;
|
|
258
|
+
};
|
|
259
|
+
}
|
|
235
260
|
//# sourceMappingURL=stdio.js.map
|
package/dist/mcp/stdio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/mcp/stdio.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Readable } from \"node:stream\"\nimport { Writable } from \"node:stream\"\nimport type { McpServer, McpServerFactory } from \"@modelcontextprotocol/server\"\nimport { serveStdio, StdioServerTransport } from \"@modelcontextprotocol/server/stdio\"\nimport type { MextApp } from \"../command.ts\"\nimport type { McpCapabilities, McpConnectHandler, McpConnection } from \"../config.ts\"\nimport { localPrincipal, type Principal } from \"../principal.ts\"\nimport type { Registry } from \"../registry.ts\"\nimport type { Instrumentation } from \"../instrumentation.ts\"\nimport type { ToolExposure } from \"./dispatch.ts\"\nimport { createMcpServerFactory, type McpCoreOptions } from \"./server.ts\"\nimport type { MextState } from \"../state.ts\"\nimport { narrowListenRequest } from \"./subscriptions.ts\"\n\nexport interface McpStdioOptions {\n registry: Registry\n app?: () => MextApp | Promise<MextApp>\n tools?: ToolExposure\n /** serverInfo.name. 기본 \"mext\" */\n name?: string\n /** initialize · server/discover 결과 instructions */\n instructions?: string\n /** 서버 capabilities 에 병합 (experimental) */\n capabilities?: McpCapabilities\n /**\n * 연결 하나에 1회 (2025 = notifications/initialized 후, 2026-07-28 = 연결 직후).\n * conn.notify = 요청과 무관한 서버 발신 알림. 반환 함수 = 연결 종료 시 cleanup. 예외 = onerror\n */\n onConnect?: McpConnectHandler\n /**\n * auto = 2026-07-28 · 2025 모두 (SDK serveStdio 가 판별). legacy = 2025 만:\n * server/discover = -32601 → 클라이언트가 initialize 로 재시도 (Claude Code channel 은 2025 연결에서만 전달).\n * 기본 = capabilities.experimental[\"claude/channel\"] 선언 시 legacy, 그 외 auto\n */\n era?: \"auto\" | \"legacy\"\n /** 연결 주체 (로컬 모드). 기본 localPrincipal() */\n principal?: Principal\n /** 기본 process.stdin */\n stdin?: Readable\n /**\n * MCP 메시지 출력. 기본 process.stdout.\n * D4: process.stdout 을 쓰는 경우 redirectStdout() 의 wire 를 넘겨 핸들러 출력이 메시지와 섞이지 않게 한다\n */\n stdout?: Writable\n /** 응답에 영향 없는 오류 보고 (SDK 내부 오류 · 깨진 메시지) */\n onerror?: (error: Error) => void\n /** MRTR requestState 서명 키 (createMcpServerFactory 와 같음) */\n requestStateKey?: McpCoreOptions[\"requestStateKey\"]\n /** 주기 progress 간격 (ms). 0 = 끔 */\n progressInterval?: number\n /** loadInstrumentation 결과 (onCommandError · span, transport = \"stdio\") */\n instrumentation?: Instrumentation\n /** _meta[\"dev.mext/manifestHash\"]. McpCoreOptions.manifestHash (기본 = registry 로 계산) */\n manifestHash?: string\n /** 주입 state (§12.1). 자원 구독 · ctx.resourceUpdated (§12.5) */\n state?: MextState\n /** McpCoreOptions.taskTiming (테스트) */\n taskTiming?: McpCoreOptions[\"taskTiming\"]\n}\n\nexport interface McpStdioServer {\n /** stdin EOF · stdout 오류 · close() 로 연결이 끝나면 resolve */\n closed: Promise<void>\n close(): Promise<void>\n}\n\n/**\n * MCP stdio (2026-07-28 · 2025 레거시 모두 SDK serveStdio). 줄 단위 JSON-RPC, 연결 하나 = McpServer 하나.\n * notifications/cancelled → ctx.signal abort (SDK). stdin EOF = 연결 종료, 진행 중 요청은 abort 되고 응답하지 않는다.\n * 헤더 검증 · Origin · 바인딩 · Authorization 은 해당 없음. 주체 = 로컬 (kind local).\n */\nexport function serveMcpStdio(options: McpStdioOptions): McpStdioServer {\n const principal = options.principal ?? localPrincipal()\n const core = createMcpServerFactory({\n registry: options.registry,\n principal,\n ...(options.app ? { app: options.app } : {}),\n ...(options.tools ? { tools: options.tools } : {}),\n ...(options.name ? { name: options.name } : {}),\n ...(options.instructions !== undefined ? { instructions: options.instructions } : {}),\n ...(options.capabilities ? { capabilities: options.capabilities } : {}),\n ...(options.requestStateKey !== undefined ? { requestStateKey: options.requestStateKey } : {}),\n ...(options.progressInterval !== undefined ? { progressInterval: options.progressInterval } : {}),\n ...(options.instrumentation ? { instrumentation: options.instrumentation } : {}),\n ...(options.manifestHash !== undefined ? { manifestHash: options.manifestHash } : {}),\n ...(options.state ? { state: options.state } : {}),\n ...(options.onerror ? { onerror: options.onerror } : {}),\n ...(options.taskTiming ? { taskTiming: options.taskTiming } : {}),\n transport: \"stdio\",\n })\n const onConnect = options.onConnect\n const report = (error: unknown): void => options.onerror?.(error instanceof Error ? error : new Error(String(error)))\n /** 인스턴스별 정리 완료 (onConnect settle + cleanup). closed 는 이것들을 기다린다 */\n const settled = new Set<Promise<void>>()\n const factory: McpServerFactory = onConnect\n ? async (ctx) => {\n const server = (await core(ctx)) as McpServer\n settled.add(attachConnection(server, ctx.era, onConnect, report))\n return server\n }\n : core\n const transport = new StdioServerTransport(options.stdin, options.stdout)\n let resolveClosed!: () => void\n const closed = new Promise<void>((resolve) => {\n resolveClosed = resolve\n })\n let finishing = false\n const finish = (): void => {\n if (finishing) return\n finishing = true\n // 실행 중 task = 취소 · cancelled 기록 (상한 5초, §12.6)\n void Promise.all([waitCleanups(settled, report), core.close().catch(report)]).then(() => resolveClosed())\n }\n const wrapClose = (): void => {\n const sdkOnClose = transport.onclose\n transport.onclose = () => {\n try {\n sdkOnClose?.()\n } finally {\n finish()\n }\n }\n }\n let handle: { close(): Promise<void> }\n const era = options.era ?? (options.capabilities?.experimental?.[CLAUDE_CHANNEL] !== undefined ? \"legacy\" : \"auto\")\n if (era === \"legacy\") {\n // serveStdio 는 server/discover 를 받으면 2026-07-28 로 고정한다 → 우회.\n // SDK 기본 supportedProtocolVersions = 2025 버전만 → McpServer 생성자가 server/discover 를 등록하지 않는다\n const ready = Promise.resolve(factory({ era: \"legacy\" } as Parameters<McpServerFactory>[0])).then(async (product) => {\n const server = product as McpServer\n server.server.onerror = report\n await server.connect(transport)\n wrapClose()\n return server\n })\n ready.catch((error: unknown) => {\n report(error)\n finish()\n })\n handle = {\n async close() {\n const server = await ready.catch(() => undefined)\n await server?.close()\n },\n }\n } else {\n handle = serveStdio(factory, options.onerror ? { transport, onerror: options.onerror } : { transport })\n // serveStdio 가 onclose · onmessage 를 동기적으로 설정한 뒤 감싼다 (stdin 이벤트는 비동기)\n wrapClose()\n // subscriptions/listen (§12.5): SDK StdioListenRouter 가 ack 하기 전에 notifications 를 허용 부분으로\n const subscriptions = { state: options.state, resources: options.registry.resources }\n const sdkOnMessage = transport.onmessage\n transport.onmessage = (message) => {\n const listen = narrowListenRequest(message, subscriptions, principal)\n sdkOnMessage?.((listen ?? message) as typeof message)\n }\n }\n return {\n closed,\n async close() {\n await handle.close()\n finish()\n await closed\n },\n }\n}\n\n/** Claude Code channel capability. 선언하면 stdio 기본 era = legacy */\nconst CLAUDE_CHANNEL = \"claude/channel\"\n\n/** 연결 종료 후 onConnect cleanup 대기 상한 (ms). 넘으면 오류 보고 후 종료 진행 */\nexport const CLEANUP_TIMEOUT_MS = 5_000\n\nasync function waitCleanups(settled: ReadonlySet<Promise<void>>, report: (error: unknown) => void): Promise<void> {\n if (settled.size === 0) return\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<\"timeout\">((resolve) => {\n timer = setTimeout(() => resolve(\"timeout\"), CLEANUP_TIMEOUT_MS)\n timer.unref?.()\n })\n const result = await Promise.race([Promise.all(settled), timeout])\n clearTimeout(timer)\n if (result === \"timeout\") report(new Error(`mcp.onConnect cleanup did not finish within ${CLEANUP_TIMEOUT_MS}ms`))\n}\n\n/**\n * McpServer 인스턴스 하나 = stdio 연결 하나. onConnect 시점: 2025 = notifications/initialized\n * (initialize 응답 전 알림은 클라이언트가 버릴 수 있음), 2026-07-28 = connect 직후 (handshake 없음).\n * SDK 가 era 판별용 probe 인스턴스를 버리면 그 인스턴스의 onclose 로 cleanup 된다.\n * 반환 = 인스턴스 종료 후 (onConnect settle · cleanup 완료) resolve. 시작 전 종료 = 바로 resolve\n */\nfunction attachConnection(\n server: McpServer,\n era: McpConnection[\"era\"],\n onConnect: McpConnectHandler,\n report: (error: unknown) => void,\n): Promise<void> {\n const inner = server.server\n let connected: Promise<unknown> | undefined\n let resolveDone!: () => void\n const done = new Promise<void>((resolve) => {\n resolveDone = resolve\n })\n let closed = false\n const handlers = new Map<string, (params: Record<string, unknown>) => void | Promise<void>>()\n // SDK 가 등록하지 않은 method 만 fallback 으로 온다 (사양 알림은 SDK handler · era 필터가 먼저)\n inner.fallbackNotificationHandler = async (notification) => {\n const handler = handlers.get(notification.method)\n if (!handler) return\n const params = (notification.params ?? {}) as Record<string, unknown>\n try {\n await handler(params)\n } catch (error) {\n report(error)\n }\n }\n const conn: McpConnection = {\n era,\n notify: (method, params) => inner.notification({ method, ...(params !== undefined ? { params } : {}) } as never),\n onNotification(method, handler) {\n handlers.set(method, handler)\n return () => {\n if (handlers.get(method) === handler) handlers.delete(method)\n }\n },\n }\n const start = (): void => {\n if (connected || closed) return\n connected = Promise.resolve().then(() => onConnect(conn))\n connected.catch(report)\n }\n const previousClose = inner.onclose\n inner.onclose = () => {\n previousClose?.()\n if (closed) return\n closed = true\n if (!connected) return resolveDone()\n connected\n .then(async (cleanup) => {\n if (typeof cleanup === \"function\") await cleanup()\n }, () => {})\n .catch(report)\n .finally(resolveDone)\n }\n if (era === \"legacy\") {\n const previousInit = inner.oninitialized\n inner.oninitialized = () => {\n previousInit?.()\n start()\n }\n } else {\n const connect = server.connect.bind(server)\n server.connect = async (transport) => {\n await connect(transport)\n start()\n }\n }\n return done\n}\n\nexport interface StdoutRedirect {\n /** 원래 process.stdout 으로 쓰는 스트림. MCP transport 전용 */\n wire: Writable\n /** process.stdout.write 원복 */\n restore(): void\n}\n\n/**\n * D4: stdio 모드에서 transport 외의 stdout 쓰기 (console.log · process.stdout.write) 를 stderr 로 돌린다.\n * 반환된 wire 만 실제 stdout 에 쓴다. 명령어 모듈 import 전에 호출해야 top-level 출력도 막는다.\n * 자식 프로세스 · fd 1 직접 쓰기 (fs.writeSync(1)) 는 막지 못한다.\n */\nexport function redirectStdout(): StdoutRedirect {\n const stdout = process.stdout\n const original = stdout.write\n const toStderr = (...args: unknown[]): boolean =>\n (process.stderr.write as (...a: unknown[]) => boolean).apply(process.stderr, args)\n stdout.write = toStderr as typeof stdout.write\n // EPIPE 등은 wire 의 write 콜백으로 transport 에 전달된다. process.stdout 의 미처리 error 로 죽지 않게\n const ignore = (): void => {}\n stdout.on(\"error\", ignore)\n const wire = new Writable({\n write(chunk: Buffer | string, _encoding, callback) {\n const write = original as (chunk: Buffer | string, done: (error?: Error | null) => void) => boolean\n write.call(stdout, chunk, (error) => callback(error ?? null))\n },\n })\n let restored = false\n return {\n wire,\n restore() {\n if (restored) return\n restored = true\n if (stdout.write === (toStderr as typeof stdout.write)) stdout.write = original\n stdout.off(\"error\", ignore)\n },\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/mcp/stdio.ts"],"names":[],"mappings":"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","sourcesContent":["import { Console } from \"node:console\"\nimport type { Readable } from \"node:stream\"\nimport { Writable } from \"node:stream\"\nimport type { McpServer, McpServerFactory } from \"@modelcontextprotocol/server\"\nimport { serveStdio, StdioServerTransport } from \"@modelcontextprotocol/server/stdio\"\nimport type { MextApp } from \"../command.ts\"\nimport { isBun } from \"../runtime.ts\"\nimport type { McpCapabilities, McpConnectHandler, McpConnection } from \"../config.ts\"\nimport { localPrincipal, type Principal } from \"../principal.ts\"\nimport type { Registry } from \"../registry.ts\"\nimport type { Instrumentation } from \"../instrumentation.ts\"\nimport type { ToolExposure } from \"./dispatch.ts\"\nimport { createMcpServerFactory, type McpCoreOptions } from \"./server.ts\"\nimport type { MextState } from \"../state.ts\"\nimport { narrowListenRequest } from \"./subscriptions.ts\"\n\nexport interface McpStdioOptions {\n registry: Registry\n app?: () => MextApp | Promise<MextApp>\n tools?: ToolExposure\n /** serverInfo.name. 기본 \"mext\" */\n name?: string\n /** initialize · server/discover 결과 instructions */\n instructions?: string\n /** 서버 capabilities 에 병합 (experimental) */\n capabilities?: McpCapabilities\n /**\n * 연결 하나에 1회 (2025 = notifications/initialized 후, 2026-07-28 = 연결 직후).\n * conn.notify = 요청과 무관한 서버 발신 알림. 반환 함수 = 연결 종료 시 cleanup. 예외 = onerror\n */\n onConnect?: McpConnectHandler\n /**\n * auto = 2026-07-28 · 2025 모두 (SDK serveStdio 가 판별). legacy = 2025 만:\n * server/discover = -32601 → 클라이언트가 initialize 로 재시도 (Claude Code channel 은 2025 연결에서만 전달).\n * 기본 = capabilities.experimental[\"claude/channel\"] 선언 시 legacy, 그 외 auto\n */\n era?: \"auto\" | \"legacy\"\n /** 연결 주체 (로컬 모드). 기본 localPrincipal() */\n principal?: Principal\n /** 기본 process.stdin */\n stdin?: Readable\n /**\n * MCP 메시지 출력. 기본 process.stdout.\n * D4: process.stdout 을 쓰는 경우 redirectStdout() 의 wire 를 넘겨 핸들러 출력이 메시지와 섞이지 않게 한다\n */\n stdout?: Writable\n /** 응답에 영향 없는 오류 보고 (SDK 내부 오류 · 깨진 메시지) */\n onerror?: (error: Error) => void\n /** MRTR requestState 서명 키 (createMcpServerFactory 와 같음) */\n requestStateKey?: McpCoreOptions[\"requestStateKey\"]\n /** 주기 progress 간격 (ms). 0 = 끔 */\n progressInterval?: number\n /** loadInstrumentation 결과 (onCommandError · span, transport = \"stdio\") */\n instrumentation?: Instrumentation\n /** _meta[\"dev.mext/manifestHash\"]. McpCoreOptions.manifestHash (기본 = registry 로 계산) */\n manifestHash?: string\n /** 주입 state (§12.1). 자원 구독 · ctx.resourceUpdated (§12.5) */\n state?: MextState\n /** McpCoreOptions.taskTiming (테스트) */\n taskTiming?: McpCoreOptions[\"taskTiming\"]\n}\n\nexport interface McpStdioServer {\n /** stdin EOF · stdout 오류 · close() 로 연결이 끝나면 resolve */\n closed: Promise<void>\n close(): Promise<void>\n}\n\n/**\n * MCP stdio (2026-07-28 · 2025 레거시 모두 SDK serveStdio). 줄 단위 JSON-RPC, 연결 하나 = McpServer 하나.\n * notifications/cancelled → ctx.signal abort (SDK). stdin EOF = 연결 종료, 진행 중 요청은 abort 되고 응답하지 않는다.\n * 헤더 검증 · Origin · 바인딩 · Authorization 은 해당 없음. 주체 = 로컬 (kind local).\n */\nexport function serveMcpStdio(options: McpStdioOptions): McpStdioServer {\n const principal = options.principal ?? localPrincipal()\n const core = createMcpServerFactory({\n registry: options.registry,\n principal,\n ...(options.app ? { app: options.app } : {}),\n ...(options.tools ? { tools: options.tools } : {}),\n ...(options.name ? { name: options.name } : {}),\n ...(options.instructions !== undefined ? { instructions: options.instructions } : {}),\n ...(options.capabilities ? { capabilities: options.capabilities } : {}),\n ...(options.requestStateKey !== undefined ? { requestStateKey: options.requestStateKey } : {}),\n ...(options.progressInterval !== undefined ? { progressInterval: options.progressInterval } : {}),\n ...(options.instrumentation ? { instrumentation: options.instrumentation } : {}),\n ...(options.manifestHash !== undefined ? { manifestHash: options.manifestHash } : {}),\n ...(options.state ? { state: options.state } : {}),\n ...(options.onerror ? { onerror: options.onerror } : {}),\n ...(options.taskTiming ? { taskTiming: options.taskTiming } : {}),\n transport: \"stdio\",\n })\n const onConnect = options.onConnect\n const report = (error: unknown): void => options.onerror?.(error instanceof Error ? error : new Error(String(error)))\n /** 인스턴스별 정리 완료 (onConnect settle + cleanup). closed 는 이것들을 기다린다 */\n const settled = new Set<Promise<void>>()\n const factory: McpServerFactory = onConnect\n ? async (ctx) => {\n const server = (await core(ctx)) as McpServer\n settled.add(attachConnection(server, ctx.era, onConnect, report))\n return server\n }\n : core\n const transport = new StdioServerTransport(options.stdin, options.stdout)\n let resolveClosed!: () => void\n const closed = new Promise<void>((resolve) => {\n resolveClosed = resolve\n })\n let finishing = false\n const finish = (): void => {\n if (finishing) return\n finishing = true\n // 실행 중 task = 취소 · cancelled 기록 (상한 5초, §12.6)\n void Promise.all([waitCleanups(settled, report), core.close().catch(report)]).then(() => resolveClosed())\n }\n const wrapClose = (): void => {\n const sdkOnClose = transport.onclose\n transport.onclose = () => {\n try {\n sdkOnClose?.()\n } finally {\n finish()\n }\n }\n }\n let handle: { close(): Promise<void> }\n const era = options.era ?? (options.capabilities?.experimental?.[CLAUDE_CHANNEL] !== undefined ? \"legacy\" : \"auto\")\n if (era === \"legacy\") {\n // serveStdio 는 server/discover 를 받으면 2026-07-28 로 고정한다 → 우회.\n // SDK 기본 supportedProtocolVersions = 2025 버전만 → McpServer 생성자가 server/discover 를 등록하지 않는다\n const ready = Promise.resolve(factory({ era: \"legacy\" } as Parameters<McpServerFactory>[0])).then(async (product) => {\n const server = product as McpServer\n server.server.onerror = report\n await server.connect(transport)\n wrapClose()\n return server\n })\n ready.catch((error: unknown) => {\n report(error)\n finish()\n })\n handle = {\n async close() {\n const server = await ready.catch(() => undefined)\n await server?.close()\n },\n }\n } else {\n handle = serveStdio(factory, options.onerror ? { transport, onerror: options.onerror } : { transport })\n // serveStdio 가 onclose · onmessage 를 동기적으로 설정한 뒤 감싼다 (stdin 이벤트는 비동기)\n wrapClose()\n // subscriptions/listen (§12.5): SDK StdioListenRouter 가 ack 하기 전에 notifications 를 허용 부분으로\n const subscriptions = { state: options.state, resources: options.registry.resources }\n const sdkOnMessage = transport.onmessage\n transport.onmessage = (message) => {\n const listen = narrowListenRequest(message, subscriptions, principal)\n sdkOnMessage?.((listen ?? message) as typeof message)\n }\n }\n return {\n closed,\n async close() {\n await handle.close()\n finish()\n await closed\n },\n }\n}\n\n/** Claude Code channel capability. 선언하면 stdio 기본 era = legacy */\nconst CLAUDE_CHANNEL = \"claude/channel\"\n\n/** 연결 종료 후 onConnect cleanup 대기 상한 (ms). 넘으면 오류 보고 후 종료 진행 */\nexport const CLEANUP_TIMEOUT_MS = 5_000\n\nasync function waitCleanups(settled: ReadonlySet<Promise<void>>, report: (error: unknown) => void): Promise<void> {\n if (settled.size === 0) return\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<\"timeout\">((resolve) => {\n timer = setTimeout(() => resolve(\"timeout\"), CLEANUP_TIMEOUT_MS)\n timer.unref?.()\n })\n const result = await Promise.race([Promise.all(settled), timeout])\n clearTimeout(timer)\n if (result === \"timeout\") report(new Error(`mcp.onConnect cleanup did not finish within ${CLEANUP_TIMEOUT_MS}ms`))\n}\n\n/**\n * McpServer 인스턴스 하나 = stdio 연결 하나. onConnect 시점: 2025 = notifications/initialized\n * (initialize 응답 전 알림은 클라이언트가 버릴 수 있음), 2026-07-28 = connect 직후 (handshake 없음).\n * SDK 가 era 판별용 probe 인스턴스를 버리면 그 인스턴스의 onclose 로 cleanup 된다.\n * 반환 = 인스턴스 종료 후 (onConnect settle · cleanup 완료) resolve. 시작 전 종료 = 바로 resolve\n */\nfunction attachConnection(\n server: McpServer,\n era: McpConnection[\"era\"],\n onConnect: McpConnectHandler,\n report: (error: unknown) => void,\n): Promise<void> {\n const inner = server.server\n let connected: Promise<unknown> | undefined\n let resolveDone!: () => void\n const done = new Promise<void>((resolve) => {\n resolveDone = resolve\n })\n let closed = false\n const handlers = new Map<string, (params: Record<string, unknown>) => void | Promise<void>>()\n // SDK 가 등록하지 않은 method 만 fallback 으로 온다 (사양 알림은 SDK handler · era 필터가 먼저)\n inner.fallbackNotificationHandler = async (notification) => {\n const handler = handlers.get(notification.method)\n if (!handler) return\n const params = (notification.params ?? {}) as Record<string, unknown>\n try {\n await handler(params)\n } catch (error) {\n report(error)\n }\n }\n const conn: McpConnection = {\n era,\n notify: (method, params) => inner.notification({ method, ...(params !== undefined ? { params } : {}) } as never),\n onNotification(method, handler) {\n handlers.set(method, handler)\n return () => {\n if (handlers.get(method) === handler) handlers.delete(method)\n }\n },\n }\n const start = (): void => {\n if (connected || closed) return\n connected = Promise.resolve().then(() => onConnect(conn))\n connected.catch(report)\n }\n const previousClose = inner.onclose\n inner.onclose = () => {\n previousClose?.()\n if (closed) return\n closed = true\n if (!connected) return resolveDone()\n connected\n .then(async (cleanup) => {\n if (typeof cleanup === \"function\") await cleanup()\n }, () => {})\n .catch(report)\n .finally(resolveDone)\n }\n if (era === \"legacy\") {\n const previousInit = inner.oninitialized\n inner.oninitialized = () => {\n previousInit?.()\n start()\n }\n } else {\n const connect = server.connect.bind(server)\n server.connect = async (transport) => {\n await connect(transport)\n start()\n }\n }\n return done\n}\n\nexport interface StdoutRedirect {\n /** 원래 process.stdout 으로 쓰는 스트림. MCP transport 전용 */\n wire: Writable\n /** process.stdout.write 원복 */\n restore(): void\n}\n\n/**\n * D4: stdio 모드에서 transport 외의 stdout 쓰기 (console.log · process.stdout.write) 를 stderr 로 돌린다.\n * 반환된 wire 만 실제 stdout 에 쓴다. 명령어 모듈 import 전에 호출해야 top-level 출력도 막는다.\n * 자식 프로세스 · fd 1 직접 쓰기 (fs.writeSync(1)) 는 막지 못한다.\n */\nexport function redirectStdout(): StdoutRedirect {\n const stdout = process.stdout\n const original = stdout.write\n const toStderr = (...args: unknown[]): boolean =>\n (process.stderr.write as (...a: unknown[]) => boolean).apply(process.stderr, args)\n stdout.write = toStderr as typeof stdout.write\n const restoreConsole = !isBun ? () => {} : redirectBunConsole(toStderr)\n // EPIPE 등은 wire 의 write 콜백으로 transport 에 전달된다. process.stdout 의 미처리 error 로 죽지 않게\n const ignore = (): void => {}\n stdout.on(\"error\", ignore)\n const wire = new Writable({\n write(chunk: Buffer | string, _encoding, callback) {\n const write = original as (chunk: Buffer | string, done: (error?: Error | null) => void) => boolean\n write.call(stdout, chunk, (error) => callback(error ?? null))\n },\n })\n let restored = false\n return {\n wire,\n restore() {\n if (restored) return\n restored = true\n if (stdout.write === (toStderr as typeof stdout.write)) stdout.write = original\n restoreConsole()\n stdout.off(\"error\", ignore)\n },\n }\n}\n\n/**\n * Bun 의 console 은 process.stdout.write 를 거치지 않고 fd 1 에 직접 쓴다.\n * console 메서드를 stderr 로 쓰는 Console 의 메서드로 바꾸고 (Bun 전용 console.write 포함), 원복 함수를 반환한다.\n * Node 의 console 은 process.stdout.write 를 거치므로 바꾸지 않는다 (group 들여쓰기 등 기존 출력 유지)\n */\nfunction redirectBunConsole(toStderr: (...args: unknown[]) => boolean): () => void {\n const target = console as unknown as Record<string, unknown>\n const stderrConsole = new Console({ stdout: process.stderr, stderr: process.stderr }) as unknown as Record<string, unknown>\n const saved = new Map<string, unknown>()\n for (const key of Object.keys(target)) {\n const replacement =\n key === \"write\" ? toStderr : typeof stderrConsole[key] === \"function\" ? (stderrConsole[key] as Function).bind(stderrConsole) : undefined\n if (typeof target[key] !== \"function\" || key === \"Console\" || replacement === undefined) continue\n saved.set(key, target[key])\n target[key] = replacement\n }\n return () => {\n for (const [key, value] of saved) target[key] = value\n }\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 실행 중인 런타임 (§10 런타임). 안내 명령 (build Start: · mcp install stdio) 을 현재 런타임 기준으로 만든다
|
|
3
|
+
*/
|
|
4
|
+
export declare const isBun: boolean;
|
|
5
|
+
/** 파일 실행 명령 (node · bun) */
|
|
6
|
+
export declare const runtimeExec: string;
|
|
7
|
+
/** 패키지 bin 실행 명령 (npx · bunx) */
|
|
8
|
+
export declare const packageExec: string;
|
|
9
|
+
/** package.json engines.bun (@obov/mext · 고객 CLI 공통) */
|
|
10
|
+
export declare const BUN_ENGINE = ">=1.4";
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 실행 중인 런타임 (§10 런타임). 안내 명령 (build Start: · mcp install stdio) 을 현재 런타임 기준으로 만든다
|
|
3
|
+
*/
|
|
4
|
+
export const isBun = process.versions.bun !== undefined;
|
|
5
|
+
/** 파일 실행 명령 (node · bun) */
|
|
6
|
+
export const runtimeExec = isBun ? "bun" : "node";
|
|
7
|
+
/** 패키지 bin 실행 명령 (npx · bunx) */
|
|
8
|
+
export const packageExec = isBun ? "bunx" : "npx";
|
|
9
|
+
/** package.json engines.bun (@obov/mext · 고객 CLI 공통) */
|
|
10
|
+
export const BUN_ENGINE = ">=1.4";
|
|
11
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,SAAS,CAAA;AAEvD,4BAA4B;AAC5B,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;AAEjD,iCAAiC;AACjC,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;AAEjD,wDAAwD;AACxD,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAA","sourcesContent":["/**\n * 실행 중인 런타임 (§10 런타임). 안내 명령 (build Start: · mcp install stdio) 을 현재 런타임 기준으로 만든다\n */\n\nexport const isBun = process.versions.bun !== undefined\n\n/** 파일 실행 명령 (node · bun) */\nexport const runtimeExec = isBun ? \"bun\" : \"node\"\n\n/** 패키지 bin 실행 명령 (npx · bunx) */\nexport const packageExec = isBun ? \"bunx\" : \"npx\"\n\n/** package.json engines.bun (@obov/mext · 고객 CLI 공통) */\nexport const BUN_ENGINE = \">=1.4\"\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obov/mext",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "File-based commands exposed as both CLI and MCP server (Streamable HTTP · stdio, MCP 2026-07-28)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"prepack": "npm run build"
|
|
28
28
|
},
|
|
29
29
|
"engines": {
|
|
30
|
-
"node": ">=22.18"
|
|
30
|
+
"node": ">=22.18",
|
|
31
|
+
"bun": ">=1.4"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
34
|
"@modelcontextprotocol/server": "^2.4.0",
|