@obov/mext 0.1.0 → 0.2.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 +10 -3
- package/dist/build-cli.js.map +1 -1
- package/dist/cli/dev-server.js +2 -1
- package/dist/cli/dev-server.js.map +1 -1
- package/dist/cli/dev.js +2 -1
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/output.d.ts +44 -0
- package/dist/cli/output.js +57 -0
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/run.js +10 -10
- package/dist/cli/run.js.map +1 -1
- package/dist/client/main.d.ts +8 -2
- package/dist/client/main.js +4 -3
- package/dist/client/main.js.map +1 -1
- package/dist/client/runner.d.ts +3 -0
- package/dist/client/runner.js +13 -12
- package/dist/client/runner.js.map +1 -1
- package/dist/config.d.ts +58 -0
- package/dist/config.js +77 -2
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/http.d.ts +4 -0
- package/dist/mcp/http.js +2 -0
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/server.d.ts +5 -0
- package/dist/mcp/server.js +7 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts +18 -0
- package/dist/mcp/stdio.js +155 -12
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/start.js +3 -1
- package/dist/start.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export { formatBuildSummary, runBuild } from "./cli/build.ts";
|
|
|
21
21
|
export { mextVersion } from "./version.ts";
|
|
22
22
|
export * from "./mcp/index.ts";
|
|
23
23
|
export { CLI_BUILTIN_COMMANDS, CONFIG_FILE, createApp, defineConfig, loadConfig, resolveCommandsDir, resolveLocalPrincipal } from "./config.ts";
|
|
24
|
-
export type { CliConfig, MextConfig } from "./config.ts";
|
|
24
|
+
export type { CliConfig, McpCapabilities, McpConfig, McpConnectHandler, McpConnection, MextConfig } from "./config.ts";
|
|
25
25
|
export { buildCustomerCli, CLI_BIN_FILE, CLI_DIR, customerCliIssues } from "./build-cli.ts";
|
|
26
26
|
export type { BuildCustomerCliOptions, CustomerCliBuild } from "./build-cli.ts";
|
|
27
27
|
export { runCustomerCli } from "./client/main.ts";
|
|
@@ -38,6 +38,7 @@ export type { CliField, CliSpec, FieldKind, ParseArgsOptions, ParsedArgs, Primit
|
|
|
38
38
|
export { cliPath, formatInvocation, renderCommandHelp, renderHelp, renderNamespaceHelp, resolveHelpTarget, } from "./cli/help.ts";
|
|
39
39
|
export type { HelpOptions, HelpTarget } from "./cli/help.ts";
|
|
40
40
|
export { errorJson, exitCodeOf, formatError, formatJson, formatResult } from "./cli/output.ts";
|
|
41
|
+
export type { CliErrorFormatter, CliErrorInfo, CliErrorOutput } from "./cli/output.ts";
|
|
41
42
|
export { loginCommand, resolveServerUrl } from "./cli/login.ts";
|
|
42
43
|
export type { AuthCommandOptions } from "./cli/login.ts";
|
|
43
44
|
export { logoutCommand } from "./cli/logout.ts";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAavD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAEpG,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE5G,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,sBAAsB,CAAA;AAS7B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAWhH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAErF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEvH,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAE,wBAAwB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAEvI,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAE/I,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAE3F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAE9C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGnD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAE/H,OAAO,EACL,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAavD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAEpG,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE5G,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,sBAAsB,CAAA;AAS7B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAWhH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAErF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEvH,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAE,wBAAwB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAEvI,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAE/I,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAE3F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAE9C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGnD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAE/H,OAAO,EACL,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9F,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA","sourcesContent":["export { VERSION } from \"./version.ts\"\n\nexport { defineCommand, isCommand } from \"./command.ts\"\nexport type {\n Ask,\n AskRequest,\n Command,\n CommandContext,\n CommandDefinition,\n ConfirmRequest,\n InputRequest,\n InputSchema,\n MextApp,\n ProgressUpdate,\n} from \"./command.ts\"\nexport { ANONYMOUS, hasScope, localPrincipal } from \"./principal.ts\"\nexport type { Principal } from \"./principal.ts\"\nexport { inputDeclined, isMextError, MextBuildError, MextError, unauthenticated } from \"./errors.ts\"\nexport type { ArgumentIssue, BuildIssue, BuildIssueCode, MextErrorCode, MextErrorDetails } from \"./errors.ts\"\nexport { authorize, confirmationMessage, createContext, findCommand, invoke, parseInput } from \"./invoke.ts\"\nexport type { AskHandler, AskHandlerRequest, InvokeOptions, InvokeResult } from \"./invoke.ts\"\nexport {\n findInstrumentation,\n INSTRUMENTATION_FILE,\n loadInstrumentation,\n loadProjectInstrumentation,\n} from \"./instrumentation.ts\"\nexport type {\n CommandErrorInfo,\n Instrumentation,\n InstrumentationModule,\n LoadInstrumentationOptions,\n OtelApi,\n Transport,\n} from \"./instrumentation.ts\"\nexport { collectRegistry, createLazyRegistry, createRegistry, loadCommand, resolveCommand } from \"./registry.ts\"\nexport type {\n JsonSchema,\n LazyCommandInput,\n NamespaceInfo,\n RegisteredCommand,\n Registry,\n RegistryCommandInput,\n RegistryInput,\n RegistryNamespaceInput,\n} from \"./registry.ts\"\nexport { collectCommands, loadRegistry, scanCommands, walkCommands } from \"./scan.ts\"\nexport type { ScannedFile, ScanResult } from \"./scan.ts\"\nexport { buildManifest, describeCommand, generateManifest, MANIFEST_SCHEMA_VERSION, manifestHash } from \"./manifest.ts\"\nexport type { BuildManifest, BuildManifestCommand, Manifest, ManifestCommand, ManifestNamespace } from \"./manifest.ts\"\nexport { BUILD_DIR, BUILD_MANIFEST_FILE, buildProject, HANDLER_JS, RolldownUnavailableError, SERVER_JS, START_ENTRY } from \"./build.ts\"\nexport type { BuildOptions, BuildResult, BuildWarning, RolldownModule, RolldownOutputItem } from \"./build.ts\"\nexport { formatBuildSummary, runBuild } from \"./cli/build.ts\"\nexport { mextVersion } from \"./version.ts\"\nexport * from \"./mcp/index.ts\"\nexport { CLI_BUILTIN_COMMANDS, CONFIG_FILE, createApp, defineConfig, loadConfig, resolveCommandsDir, resolveLocalPrincipal } from \"./config.ts\"\nexport type { CliConfig, McpCapabilities, McpConfig, McpConnectHandler, McpConnection, MextConfig } from \"./config.ts\"\nexport { buildCustomerCli, CLI_BIN_FILE, CLI_DIR, customerCliIssues } from \"./build-cli.ts\"\nexport type { BuildCustomerCliOptions, CustomerCliBuild } from \"./build-cli.ts\"\nexport { runCustomerCli } from \"./client/main.ts\"\nexport type { CustomerCliConfig } from \"./client/main.ts\"\nexport { clientManifest, manifestHelp } from \"./client/manifest.ts\"\nexport type { ClientManifest, ClientManifestCommand } from \"./client/manifest.ts\"\nexport { runRemote } from \"./client/runner.ts\"\nexport type { HelpSource, RemoteRunOptions } from \"./client/runner.ts\"\nexport { runCli, SUBCOMMANDS } from \"./cli/main.ts\"\nexport type { CliSubcommand } from \"./cli/main.ts\"\nexport type { CliIo, CliWriter } from \"./cli/io.ts\"\nexport { analyzeInput, assertCliConvertible, cliBuildIssues, cliSpec, parseArgs, RESERVED_FLAGS, toKebab } from \"./cli/args.ts\"\nexport type { CliField, CliSpec, FieldKind, ParseArgsOptions, ParsedArgs, Primitive, ScalarKind } from \"./cli/args.ts\"\nexport {\n cliPath,\n formatInvocation,\n renderCommandHelp,\n renderHelp,\n renderNamespaceHelp,\n resolveHelpTarget,\n} from \"./cli/help.ts\"\nexport type { HelpOptions, HelpTarget } from \"./cli/help.ts\"\nexport { errorJson, exitCodeOf, formatError, formatJson, formatResult } from \"./cli/output.ts\"\nexport type { CliErrorFormatter, CliErrorInfo, CliErrorOutput } from \"./cli/output.ts\"\nexport { loginCommand, resolveServerUrl } from \"./cli/login.ts\"\nexport type { AuthCommandOptions } from \"./cli/login.ts\"\nexport { logoutCommand } from \"./cli/logout.ts\"\nexport * from \"./remote/index.ts\"\nexport { cliSpecFromJsonSchema, defineCliSpec } from \"./cli/args.ts\"\n"]}
|
package/dist/mcp/http.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ export interface McpHttpOptions {
|
|
|
33
33
|
};
|
|
34
34
|
/** serverInfo.name · 안내 문구. 기본 "mext" */
|
|
35
35
|
name?: string;
|
|
36
|
+
/** initialize · server/discover 결과 instructions */
|
|
37
|
+
instructions?: string;
|
|
38
|
+
/** 서버 capabilities 에 병합 (experimental) */
|
|
39
|
+
capabilities?: McpCoreOptions["capabilities"];
|
|
36
40
|
/** 응답에 영향 없는 오류 보고 (auth 예외 · SDK 내부 오류) */
|
|
37
41
|
onerror?: (error: Error) => void;
|
|
38
42
|
/** MRTR requestState 서명 키. McpCoreOptions.requestStateKey */
|
package/dist/mcp/http.js
CHANGED
|
@@ -21,6 +21,8 @@ export function createMcpFetchHandler(options) {
|
|
|
21
21
|
...(options.app ? { app: options.app } : {}),
|
|
22
22
|
...(options.tools ? { tools: options.tools } : {}),
|
|
23
23
|
...(options.name ? { name: options.name } : {}),
|
|
24
|
+
...(options.instructions !== undefined ? { instructions: options.instructions } : {}),
|
|
25
|
+
...(options.capabilities ? { capabilities: options.capabilities } : {}),
|
|
24
26
|
...(options.requestStateKey !== undefined ? { requestStateKey: options.requestStateKey } : {}),
|
|
25
27
|
...(options.progressInterval !== undefined ? { progressInterval: options.progressInterval } : {}),
|
|
26
28
|
...(options.instrumentation ? { instrumentation: options.instrumentation } : {}),
|
package/dist/mcp/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport { Readable } from \"node:stream\"\nimport { createMcpHandler, isLegacyRequest, type McpHttpHandler } from \"@modelcontextprotocol/server\"\nimport type { MextApp } from \"../command.ts\"\nimport { isMextError, type MextError } from \"../errors.ts\"\nimport { ANONYMOUS, type Principal } from \"../principal.ts\"\nimport type { Registry } from \"../registry.ts\"\nimport { DEFAULT_HOST, DEFAULT_PORT, MCP_PATH } from \"./constants.ts\"\nimport type { Instrumentation } from \"../instrumentation.ts\"\nimport type { ToolExposure } from \"./dispatch.ts\"\nimport { createMcpServerFactory, principalAuthInfo, type McpCoreOptions } from \"./server.ts\"\n\n/** 요청 본문 상한 (SDK 기본과 같음) */\nexport const MAX_BODY_BYTES = 4 * 1024 * 1024\n\nexport interface McpAuthRequest {\n /** Authorization 헤더 원문 */\n authorization: string | undefined\n}\n\nexport interface McpHttpOptions {\n registry: Registry\n app?: () => MextApp | Promise<MextApp>\n /**\n * 요청마다 Authorization → Principal. 없으면 모든 요청 = ANONYMOUS (readOnly 명령어만).\n * 잘못된 토큰은 unauthenticated() 를 던진다 → HTTP 401. anonymous 로 낮추지 않는다\n */\n auth?: (req: McpAuthRequest) => Principal | Promise<Principal>\n tools?: ToolExposure\n server?: {\n /** 기본 127.0.0.1 */\n host?: string\n /** 기본 3100. 0 = 임의 포트 */\n port?: number\n /**\n * Origin 허용 목록 (https://app.example.com 형식, \"*\" = 전체).\n * 미지정 = loopback (localhost · 127.0.0.1 · [::1], 포트 무관) 만. Origin 헤더 없는 요청은 항상 통과\n */\n allowedOrigins?: string[]\n }\n /** serverInfo.name · 안내 문구. 기본 \"mext\" */\n name?: string\n /** 응답에 영향 없는 오류 보고 (auth 예외 · SDK 내부 오류) */\n onerror?: (error: Error) => void\n /** MRTR requestState 서명 키. McpCoreOptions.requestStateKey */\n requestStateKey?: McpCoreOptions[\"requestStateKey\"]\n /** 주기 progress 간격 (ms). McpCoreOptions.progressInterval */\n progressInterval?: number\n /** loadInstrumentation 결과 (onCommandError · span, transport = \"http\") */\n instrumentation?: Instrumentation\n /** _meta[\"dev.mext/manifestHash\"]. McpCoreOptions.manifestHash (기본 = registry 로 계산) */\n manifestHash?: string\n /**\n * OAuth 보호 자원 메타데이터 (RFC 9728). 지정하면 GET /.well-known/oauth-protected-resource/mcp ·\n * /.well-known/oauth-protected-resource 응답, 401 의 WWW-Authenticate 에 resource_metadata.\n * 클라이언트 (mext login · MCP 클라이언트) 가 인가 서버를 찾는 데 쓴다\n */\n oauth?: OAuthResourceOptions\n}\n\nexport interface OAuthResourceOptions {\n /** 인가 서버 issuer URL (1개 이상) */\n authorizationServers: string[]\n scopesSupported?: string[]\n /** 토큰 대상 자원 ID (RFC 8707). 기본 = 요청 Host 기준 http://<host>/mcp (프록시 · TLS 뒤에서는 지정) */\n resource?: string\n}\n\n/** RFC 9728 well-known 경로 */\nexport const PROTECTED_RESOURCE_METADATA_PATH = \"/.well-known/oauth-protected-resource\"\n\nexport type McpHttpListener = ((req: IncomingMessage, res: ServerResponse) => void) & {\n /** 진행 중인 요청 abort · SDK handler 정리 */\n close(): Promise<void>\n}\n\n/** Web 표준 (Request → Response) MCP 처리기. handler.js · 다른 런타임 · node:http 어댑터가 공유 */\nexport interface McpFetchHandler {\n /** 거부하지 않는다 (내부 오류 = 500 JSON-RPC 오류). request.signal abort = 핸들러 ctx.signal abort */\n fetch(request: Request): Promise<Response>\n /** SDK handler 정리 */\n close(): Promise<void>\n}\n\n/**\n * Streamable HTTP (2026-07-28) 의 transport 무관 처리 (Web Request → Response).\n * 순서: 경로 (404) → Origin (403) → 메서드 (POST 외 405) → 본문 (413) → auth (401) → SDK createMcpHandler.\n * SDK 가 요청별 버전 · 헤더 검증 (-32020) · server/discover · Mcp-Param-Command · 2025 레거시 stateless 를 처리.\n * progressToken 있는 2026-07-28 요청 = SSE 응답 (진행률 알림), 그 외 = JSON.\n */\nexport function createMcpFetchHandler(options: McpHttpOptions): McpFetchHandler {\n const factory = createMcpServerFactory({\n registry: options.registry,\n ...(options.app ? { app: options.app } : {}),\n ...(options.tools ? { tools: options.tools } : {}),\n ...(options.name ? { name: options.name } : {}),\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 transport: \"http\",\n })\n const report = reporter(options.onerror)\n const sdkOptions = options.onerror ? { onerror: report } : {}\n // 진행률 없는 요청 = JSON (auto: 관련 메시지가 없으면 단일 JSON), 진행률 있는 요청 = SSE\n const jsonHandler = createMcpHandler(factory, { ...sdkOptions, responseMode: \"auto\" })\n const sseHandler = createMcpHandler(factory, { ...sdkOptions, responseMode: \"sse\" })\n const allowedOrigins = options.server?.allowedOrigins\n\n const handle = async (request: Request): Promise<Response> => {\n const url = new URL(request.url)\n const oauth = options.oauth\n if (oauth && (url.pathname === PROTECTED_RESOURCE_METADATA_PATH || url.pathname === protectedResourceMetadataPath())) {\n if (request.method !== \"GET\") return jsonResponse(405, { error: \"method_not_allowed\" }, { Allow: \"GET\" })\n return jsonResponse(200, protectedResourceMetadata(oauth, url))\n }\n if (url.pathname !== MCP_PATH) return jsonResponse(404, rpcError(-32_000, `Not found. The MCP endpoint is POST ${MCP_PATH}.`))\n const origin = request.headers.get(\"origin\") ?? undefined\n if (origin !== undefined && origin !== \"\" && !originAllowed(origin, allowedOrigins)) {\n return jsonResponse(403, rpcError(-32_000, `Forbidden: origin ${origin} is not allowed.`))\n }\n if (request.method !== \"POST\") {\n return jsonResponse(405, rpcError(-32_000, \"Method not allowed.\"), { Allow: \"POST\" })\n }\n\n const body = await readBody(request.body, MAX_BODY_BYTES)\n if (body === \"too-large\") return jsonResponse(413, rpcError(-32_000, \"Request body too large.\"))\n const parsed = parseJson(body)\n const id = requestId(parsed)\n\n let principal: Principal = ANONYMOUS\n if (options.auth) {\n try {\n principal = await options.auth({ authorization: request.headers.get(\"authorization\") ?? undefined })\n } catch (error) {\n if (isMextError(error, \"UNAUTHENTICATED\")) {\n return unauthenticatedResponse(error, id, oauth ? resourceMetadataUrl(oauth, url) : undefined)\n }\n report(error)\n return jsonResponse(500, rpcError(-32_603, \"Internal server error\", undefined, id))\n }\n }\n\n const sdkRequest = new Request(url, {\n method: \"POST\",\n headers: statelessHeaders(request.headers),\n body,\n signal: request.signal,\n })\n const parsedBody = parsed === NOT_JSON ? undefined : parsed\n // 2025-11-25 이하 (envelope 없음) = SDK stateless 레거시 경로. 진행률 기반 SSE 전환은 2026-07-28 요청만\n const legacy = await isLegacyRequest(sdkRequest, parsedBody, { maxRequestBodySize: MAX_BODY_BYTES })\n const handler: McpHttpHandler = !legacy && hasProgressToken(parsedBody) ? sseHandler : jsonHandler\n return handler.fetch(sdkRequest, {\n authInfo: principalAuthInfo(principal),\n ...(parsedBody !== undefined ? { parsedBody } : {}),\n })\n }\n\n return {\n async fetch(request) {\n try {\n return await handle(request)\n } catch (error) {\n report(error)\n return jsonResponse(500, rpcError(-32_603, \"Internal server error\"))\n }\n },\n async close() {\n await Promise.all([jsonHandler.close(), sseHandler.close()])\n },\n }\n}\n\n/** createMcpFetchHandler 의 node:http 어댑터. 응답 · SSE 를 스트리밍, 클라이언트 연결 종료 = request.signal abort */\nexport function createMcpHttpHandler(options: McpHttpOptions): McpHttpListener {\n const core = createMcpFetchHandler(options)\n const report = reporter(options.onerror)\n const inflight = new Set<AbortController>()\n\n const listener = ((req: IncomingMessage, res: ServerResponse) => {\n const controller = new AbortController()\n inflight.add(controller)\n res.on(\"close\", () => {\n if (!res.writableFinished) controller.abort()\n inflight.delete(controller)\n })\n const hasBody = req.method !== \"GET\" && req.method !== \"HEAD\"\n const request = new Request(requestUrl(req), {\n method: req.method ?? \"GET\",\n headers: nodeHeaders(req),\n ...(hasBody ? { body: Readable.toWeb(req) as ReadableStream<Uint8Array>, duplex: \"half\" as const } : {}),\n signal: controller.signal,\n })\n core\n .fetch(request)\n .then((response) => sendResponse(res, response))\n .catch((error: unknown) => {\n report(error)\n if (!res.headersSent && !res.destroyed) sendJson(res, 500, rpcError(-32_603, \"Internal server error\"))\n else res.destroy()\n })\n }) as McpHttpListener\n listener.close = async () => {\n for (const c of inflight) c.abort()\n inflight.clear()\n await core.close()\n }\n return listener\n}\n\n/** 응답에 영향 없는 오류 보고 (보고 자체의 예외는 삼킨다) */\nfunction reporter(onerror: ((error: Error) => void) | undefined): (error: unknown) => void {\n return (error) => {\n try {\n onerror?.(error instanceof Error ? error : new Error(String(error)))\n } catch {\n // 보고는 응답을 바꾸지 않는다\n }\n }\n}\n\nexport interface McpHttpServer {\n /** http://<host>:<port>/mcp */\n url: string\n host: string\n port: number\n close(): Promise<void>\n}\n\n/** createMcpHttpHandler + node:http listen. 기본 127.0.0.1:3100 */\nexport async function startMcpHttpServer(options: McpHttpOptions): Promise<McpHttpServer> {\n const listener = createMcpHttpHandler(options)\n const server = createServer(listener)\n const host = options.server?.host ?? DEFAULT_HOST\n const port = options.server?.port ?? DEFAULT_PORT\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(port, host, () => {\n server.off(\"error\", reject)\n resolve()\n })\n })\n const address = server.address() as AddressInfo\n return {\n url: `http://${formatHost(host)}:${address.port}${MCP_PATH}`,\n host,\n port: address.port,\n async close() {\n await listener.close()\n server.closeAllConnections()\n await new Promise<void>((resolve) => server.close(() => resolve()))\n },\n }\n}\n\n/* Origin */\n\nconst LOOPBACK_HOSTNAMES = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\"])\n\n/** Origin 허용 여부. allowed 미지정 = loopback 만, 지정 = 목록의 origin 과 정확히 일치 (\"*\" = 전체) */\nexport function originAllowed(origin: string, allowed: readonly string[] | undefined): boolean {\n if (allowed?.includes(\"*\")) return true\n let url: URL\n try {\n url = new URL(origin)\n } catch {\n return false\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return false\n if (allowed === undefined) return LOOPBACK_HOSTNAMES.has(url.hostname)\n return allowed.some((entry) => normalizeOrigin(entry) === url.origin)\n}\n\nfunction normalizeOrigin(entry: string): string | undefined {\n try {\n return new URL(entry).origin\n } catch {\n return undefined\n }\n}\n\n/* node:http ↔ fetch */\n\n/** 무시하는 헤더 (stateless): 세션 · SSE 재개 */\nconst DROPPED_HEADERS = new Set([\"mcp-session-id\", \"last-event-id\"])\n\nfunction statelessHeaders(source: Headers): Headers {\n const headers = new Headers(source)\n for (const name of DROPPED_HEADERS) headers.delete(name)\n return headers\n}\n\nfunction nodeHeaders(req: IncomingMessage): Headers {\n const headers = new Headers()\n for (const [name, value] of Object.entries(req.headers)) {\n if (value === undefined || name.startsWith(\":\")) continue\n if (Array.isArray(value)) for (const v of value) headers.append(name, v)\n else headers.set(name, value)\n }\n return headers\n}\n\nfunction requestUrl(req: IncomingMessage): URL {\n try {\n return new URL(req.url ?? \"/\", `http://${req.headers.host ?? \"localhost\"}`)\n } catch {\n return new URL(req.url ?? \"/\", \"http://localhost\")\n }\n}\n\n/** 본문을 limit 바이트까지. 넘으면 스트림 취소 후 \"too-large\" */\nasync function readBody(body: ReadableStream<Uint8Array> | null, limit: number): Promise<Uint8Array<ArrayBuffer> | \"too-large\"> {\n if (body === null) return new Uint8Array(0)\n const chunks: Uint8Array[] = []\n let size = 0\n const reader = body.getReader()\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n size += value.byteLength\n if (size > limit) {\n await reader.cancel().catch(() => {})\n return \"too-large\"\n }\n chunks.push(value)\n }\n const out = new Uint8Array(size)\n let offset = 0\n for (const c of chunks) {\n out.set(c, offset)\n offset += c.byteLength\n }\n return out\n}\n\nasync function sendResponse(res: ServerResponse, response: Response): Promise<void> {\n if (res.destroyed) {\n await response.body?.cancel().catch(() => {})\n return\n }\n res.statusCode = response.status\n response.headers.forEach((value, name) => res.setHeader(name, value))\n if (response.body === null) {\n res.end()\n return\n }\n const reader = response.body.getReader()\n // 클라이언트가 SSE 스트림을 닫으면 = 취소. SDK 가 transport 를 닫고 핸들러 signal 을 abort, 이후 메시지는 버린다\n const onClose = () => {\n if (!res.writableFinished) void reader.cancel().catch(() => {})\n }\n res.on(\"close\", onClose)\n res.flushHeaders()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done || res.destroyed) break\n res.write(value)\n }\n } catch {\n // 스트림 취소 · 생산자 오류: 아래에서 응답을 닫는다\n } finally {\n res.off(\"close\", onClose)\n }\n if (!res.destroyed) res.end()\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown, headers: Record<string, string> = {}): void {\n const text = JSON.stringify(body)\n res.writeHead(status, { \"Content-Type\": \"application/json\", \"Content-Length\": Buffer.byteLength(text), ...headers })\n res.end(text)\n}\n\nfunction jsonResponse(status: number, body: unknown, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), { status, headers: { \"Content-Type\": \"application/json\", ...headers } })\n}\n\nfunction unauthenticatedResponse(\n error: MextError<\"UNAUTHENTICATED\">,\n id: string | number | null,\n resourceMetadata: string | undefined,\n): Response {\n const params: string[] = []\n if (error.details.reason === \"invalid_token\") params.push('error=\"invalid_token\"')\n if (resourceMetadata !== undefined) params.push(`resource_metadata=\"${resourceMetadata}\"`)\n const challenge = params.length > 0 ? `Bearer ${params.join(\", \")}` : \"Bearer\"\n return jsonResponse(401, rpcError(-32_001, error.message, error.toJSON(), id), { \"WWW-Authenticate\": challenge })\n}\n\n/* OAuth 보호 자원 메타데이터 (RFC 9728) */\n\n/** MCP 엔드포인트 경로를 삽입한 well-known 경로 (/.well-known/oauth-protected-resource/mcp) */\nfunction protectedResourceMetadataPath(): string {\n return `${PROTECTED_RESOURCE_METADATA_PATH}${MCP_PATH}`\n}\n\nfunction resourceOf(oauth: OAuthResourceOptions, url: URL): string {\n return oauth.resource ?? `${url.origin}${MCP_PATH}`\n}\n\nfunction resourceMetadataUrl(oauth: OAuthResourceOptions, url: URL): string {\n const resource = new URL(resourceOf(oauth, url))\n const path = resource.pathname.replace(/\\/$/, \"\")\n return `${resource.origin}${PROTECTED_RESOURCE_METADATA_PATH}${path}`\n}\n\nfunction protectedResourceMetadata(oauth: OAuthResourceOptions, url: URL): Record<string, unknown> {\n const doc: Record<string, unknown> = {\n resource: resourceOf(oauth, url),\n authorization_servers: [...oauth.authorizationServers],\n bearer_methods_supported: [\"header\"],\n }\n if (oauth.scopesSupported) doc.scopes_supported = [...oauth.scopesSupported]\n return doc\n}\n\nfunction rpcError(code: number, message: string, data?: unknown, id: string | number | null = null) {\n return { jsonrpc: \"2.0\", id, error: data === undefined ? { code, message } : { code, message, data } }\n}\n\nconst NOT_JSON = Symbol(\"not-json\")\n\nfunction parseJson(body: Uint8Array): unknown {\n if (body.length === 0) return NOT_JSON\n try {\n return JSON.parse(new TextDecoder().decode(body))\n } catch {\n return NOT_JSON\n }\n}\n\nfunction requestId(body: unknown): string | number | null {\n if (body === null || typeof body !== \"object\" || Array.isArray(body)) return null\n const { id, method } = body as { id?: unknown; method?: unknown }\n if (typeof method !== \"string\") return null\n return typeof id === \"string\" || typeof id === \"number\" ? id : null\n}\n\nfunction hasProgressToken(body: unknown): boolean {\n if (body === null || typeof body !== \"object\" || Array.isArray(body)) return false\n const meta = (body as { params?: { _meta?: { progressToken?: unknown } } }).params?._meta\n return meta !== null && typeof meta === \"object\" && meta.progressToken !== undefined\n}\n\nfunction formatHost(host: string): string {\n return host.includes(\":\") && !host.startsWith(\"[\") ? `[${host}]` : host\n}\n"]}
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport { Readable } from \"node:stream\"\nimport { createMcpHandler, isLegacyRequest, type McpHttpHandler } from \"@modelcontextprotocol/server\"\nimport type { MextApp } from \"../command.ts\"\nimport { isMextError, type MextError } from \"../errors.ts\"\nimport { ANONYMOUS, type Principal } from \"../principal.ts\"\nimport type { Registry } from \"../registry.ts\"\nimport { DEFAULT_HOST, DEFAULT_PORT, MCP_PATH } from \"./constants.ts\"\nimport type { Instrumentation } from \"../instrumentation.ts\"\nimport type { ToolExposure } from \"./dispatch.ts\"\nimport { createMcpServerFactory, principalAuthInfo, type McpCoreOptions } from \"./server.ts\"\n\n/** 요청 본문 상한 (SDK 기본과 같음) */\nexport const MAX_BODY_BYTES = 4 * 1024 * 1024\n\nexport interface McpAuthRequest {\n /** Authorization 헤더 원문 */\n authorization: string | undefined\n}\n\nexport interface McpHttpOptions {\n registry: Registry\n app?: () => MextApp | Promise<MextApp>\n /**\n * 요청마다 Authorization → Principal. 없으면 모든 요청 = ANONYMOUS (readOnly 명령어만).\n * 잘못된 토큰은 unauthenticated() 를 던진다 → HTTP 401. anonymous 로 낮추지 않는다\n */\n auth?: (req: McpAuthRequest) => Principal | Promise<Principal>\n tools?: ToolExposure\n server?: {\n /** 기본 127.0.0.1 */\n host?: string\n /** 기본 3100. 0 = 임의 포트 */\n port?: number\n /**\n * Origin 허용 목록 (https://app.example.com 형식, \"*\" = 전체).\n * 미지정 = loopback (localhost · 127.0.0.1 · [::1], 포트 무관) 만. Origin 헤더 없는 요청은 항상 통과\n */\n allowedOrigins?: string[]\n }\n /** serverInfo.name · 안내 문구. 기본 \"mext\" */\n name?: string\n /** initialize · server/discover 결과 instructions */\n instructions?: string\n /** 서버 capabilities 에 병합 (experimental) */\n capabilities?: McpCoreOptions[\"capabilities\"]\n /** 응답에 영향 없는 오류 보고 (auth 예외 · SDK 내부 오류) */\n onerror?: (error: Error) => void\n /** MRTR requestState 서명 키. McpCoreOptions.requestStateKey */\n requestStateKey?: McpCoreOptions[\"requestStateKey\"]\n /** 주기 progress 간격 (ms). McpCoreOptions.progressInterval */\n progressInterval?: number\n /** loadInstrumentation 결과 (onCommandError · span, transport = \"http\") */\n instrumentation?: Instrumentation\n /** _meta[\"dev.mext/manifestHash\"]. McpCoreOptions.manifestHash (기본 = registry 로 계산) */\n manifestHash?: string\n /**\n * OAuth 보호 자원 메타데이터 (RFC 9728). 지정하면 GET /.well-known/oauth-protected-resource/mcp ·\n * /.well-known/oauth-protected-resource 응답, 401 의 WWW-Authenticate 에 resource_metadata.\n * 클라이언트 (mext login · MCP 클라이언트) 가 인가 서버를 찾는 데 쓴다\n */\n oauth?: OAuthResourceOptions\n}\n\nexport interface OAuthResourceOptions {\n /** 인가 서버 issuer URL (1개 이상) */\n authorizationServers: string[]\n scopesSupported?: string[]\n /** 토큰 대상 자원 ID (RFC 8707). 기본 = 요청 Host 기준 http://<host>/mcp (프록시 · TLS 뒤에서는 지정) */\n resource?: string\n}\n\n/** RFC 9728 well-known 경로 */\nexport const PROTECTED_RESOURCE_METADATA_PATH = \"/.well-known/oauth-protected-resource\"\n\nexport type McpHttpListener = ((req: IncomingMessage, res: ServerResponse) => void) & {\n /** 진행 중인 요청 abort · SDK handler 정리 */\n close(): Promise<void>\n}\n\n/** Web 표준 (Request → Response) MCP 처리기. handler.js · 다른 런타임 · node:http 어댑터가 공유 */\nexport interface McpFetchHandler {\n /** 거부하지 않는다 (내부 오류 = 500 JSON-RPC 오류). request.signal abort = 핸들러 ctx.signal abort */\n fetch(request: Request): Promise<Response>\n /** SDK handler 정리 */\n close(): Promise<void>\n}\n\n/**\n * Streamable HTTP (2026-07-28) 의 transport 무관 처리 (Web Request → Response).\n * 순서: 경로 (404) → Origin (403) → 메서드 (POST 외 405) → 본문 (413) → auth (401) → SDK createMcpHandler.\n * SDK 가 요청별 버전 · 헤더 검증 (-32020) · server/discover · Mcp-Param-Command · 2025 레거시 stateless 를 처리.\n * progressToken 있는 2026-07-28 요청 = SSE 응답 (진행률 알림), 그 외 = JSON.\n */\nexport function createMcpFetchHandler(options: McpHttpOptions): McpFetchHandler {\n const factory = createMcpServerFactory({\n registry: options.registry,\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 transport: \"http\",\n })\n const report = reporter(options.onerror)\n const sdkOptions = options.onerror ? { onerror: report } : {}\n // 진행률 없는 요청 = JSON (auto: 관련 메시지가 없으면 단일 JSON), 진행률 있는 요청 = SSE\n const jsonHandler = createMcpHandler(factory, { ...sdkOptions, responseMode: \"auto\" })\n const sseHandler = createMcpHandler(factory, { ...sdkOptions, responseMode: \"sse\" })\n const allowedOrigins = options.server?.allowedOrigins\n\n const handle = async (request: Request): Promise<Response> => {\n const url = new URL(request.url)\n const oauth = options.oauth\n if (oauth && (url.pathname === PROTECTED_RESOURCE_METADATA_PATH || url.pathname === protectedResourceMetadataPath())) {\n if (request.method !== \"GET\") return jsonResponse(405, { error: \"method_not_allowed\" }, { Allow: \"GET\" })\n return jsonResponse(200, protectedResourceMetadata(oauth, url))\n }\n if (url.pathname !== MCP_PATH) return jsonResponse(404, rpcError(-32_000, `Not found. The MCP endpoint is POST ${MCP_PATH}.`))\n const origin = request.headers.get(\"origin\") ?? undefined\n if (origin !== undefined && origin !== \"\" && !originAllowed(origin, allowedOrigins)) {\n return jsonResponse(403, rpcError(-32_000, `Forbidden: origin ${origin} is not allowed.`))\n }\n if (request.method !== \"POST\") {\n return jsonResponse(405, rpcError(-32_000, \"Method not allowed.\"), { Allow: \"POST\" })\n }\n\n const body = await readBody(request.body, MAX_BODY_BYTES)\n if (body === \"too-large\") return jsonResponse(413, rpcError(-32_000, \"Request body too large.\"))\n const parsed = parseJson(body)\n const id = requestId(parsed)\n\n let principal: Principal = ANONYMOUS\n if (options.auth) {\n try {\n principal = await options.auth({ authorization: request.headers.get(\"authorization\") ?? undefined })\n } catch (error) {\n if (isMextError(error, \"UNAUTHENTICATED\")) {\n return unauthenticatedResponse(error, id, oauth ? resourceMetadataUrl(oauth, url) : undefined)\n }\n report(error)\n return jsonResponse(500, rpcError(-32_603, \"Internal server error\", undefined, id))\n }\n }\n\n const sdkRequest = new Request(url, {\n method: \"POST\",\n headers: statelessHeaders(request.headers),\n body,\n signal: request.signal,\n })\n const parsedBody = parsed === NOT_JSON ? undefined : parsed\n // 2025-11-25 이하 (envelope 없음) = SDK stateless 레거시 경로. 진행률 기반 SSE 전환은 2026-07-28 요청만\n const legacy = await isLegacyRequest(sdkRequest, parsedBody, { maxRequestBodySize: MAX_BODY_BYTES })\n const handler: McpHttpHandler = !legacy && hasProgressToken(parsedBody) ? sseHandler : jsonHandler\n return handler.fetch(sdkRequest, {\n authInfo: principalAuthInfo(principal),\n ...(parsedBody !== undefined ? { parsedBody } : {}),\n })\n }\n\n return {\n async fetch(request) {\n try {\n return await handle(request)\n } catch (error) {\n report(error)\n return jsonResponse(500, rpcError(-32_603, \"Internal server error\"))\n }\n },\n async close() {\n await Promise.all([jsonHandler.close(), sseHandler.close()])\n },\n }\n}\n\n/** createMcpFetchHandler 의 node:http 어댑터. 응답 · SSE 를 스트리밍, 클라이언트 연결 종료 = request.signal abort */\nexport function createMcpHttpHandler(options: McpHttpOptions): McpHttpListener {\n const core = createMcpFetchHandler(options)\n const report = reporter(options.onerror)\n const inflight = new Set<AbortController>()\n\n const listener = ((req: IncomingMessage, res: ServerResponse) => {\n const controller = new AbortController()\n inflight.add(controller)\n res.on(\"close\", () => {\n if (!res.writableFinished) controller.abort()\n inflight.delete(controller)\n })\n const hasBody = req.method !== \"GET\" && req.method !== \"HEAD\"\n const request = new Request(requestUrl(req), {\n method: req.method ?? \"GET\",\n headers: nodeHeaders(req),\n ...(hasBody ? { body: Readable.toWeb(req) as ReadableStream<Uint8Array>, duplex: \"half\" as const } : {}),\n signal: controller.signal,\n })\n core\n .fetch(request)\n .then((response) => sendResponse(res, response))\n .catch((error: unknown) => {\n report(error)\n if (!res.headersSent && !res.destroyed) sendJson(res, 500, rpcError(-32_603, \"Internal server error\"))\n else res.destroy()\n })\n }) as McpHttpListener\n listener.close = async () => {\n for (const c of inflight) c.abort()\n inflight.clear()\n await core.close()\n }\n return listener\n}\n\n/** 응답에 영향 없는 오류 보고 (보고 자체의 예외는 삼킨다) */\nfunction reporter(onerror: ((error: Error) => void) | undefined): (error: unknown) => void {\n return (error) => {\n try {\n onerror?.(error instanceof Error ? error : new Error(String(error)))\n } catch {\n // 보고는 응답을 바꾸지 않는다\n }\n }\n}\n\nexport interface McpHttpServer {\n /** http://<host>:<port>/mcp */\n url: string\n host: string\n port: number\n close(): Promise<void>\n}\n\n/** createMcpHttpHandler + node:http listen. 기본 127.0.0.1:3100 */\nexport async function startMcpHttpServer(options: McpHttpOptions): Promise<McpHttpServer> {\n const listener = createMcpHttpHandler(options)\n const server = createServer(listener)\n const host = options.server?.host ?? DEFAULT_HOST\n const port = options.server?.port ?? DEFAULT_PORT\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(port, host, () => {\n server.off(\"error\", reject)\n resolve()\n })\n })\n const address = server.address() as AddressInfo\n return {\n url: `http://${formatHost(host)}:${address.port}${MCP_PATH}`,\n host,\n port: address.port,\n async close() {\n await listener.close()\n server.closeAllConnections()\n await new Promise<void>((resolve) => server.close(() => resolve()))\n },\n }\n}\n\n/* Origin */\n\nconst LOOPBACK_HOSTNAMES = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\"])\n\n/** Origin 허용 여부. allowed 미지정 = loopback 만, 지정 = 목록의 origin 과 정확히 일치 (\"*\" = 전체) */\nexport function originAllowed(origin: string, allowed: readonly string[] | undefined): boolean {\n if (allowed?.includes(\"*\")) return true\n let url: URL\n try {\n url = new URL(origin)\n } catch {\n return false\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return false\n if (allowed === undefined) return LOOPBACK_HOSTNAMES.has(url.hostname)\n return allowed.some((entry) => normalizeOrigin(entry) === url.origin)\n}\n\nfunction normalizeOrigin(entry: string): string | undefined {\n try {\n return new URL(entry).origin\n } catch {\n return undefined\n }\n}\n\n/* node:http ↔ fetch */\n\n/** 무시하는 헤더 (stateless): 세션 · SSE 재개 */\nconst DROPPED_HEADERS = new Set([\"mcp-session-id\", \"last-event-id\"])\n\nfunction statelessHeaders(source: Headers): Headers {\n const headers = new Headers(source)\n for (const name of DROPPED_HEADERS) headers.delete(name)\n return headers\n}\n\nfunction nodeHeaders(req: IncomingMessage): Headers {\n const headers = new Headers()\n for (const [name, value] of Object.entries(req.headers)) {\n if (value === undefined || name.startsWith(\":\")) continue\n if (Array.isArray(value)) for (const v of value) headers.append(name, v)\n else headers.set(name, value)\n }\n return headers\n}\n\nfunction requestUrl(req: IncomingMessage): URL {\n try {\n return new URL(req.url ?? \"/\", `http://${req.headers.host ?? \"localhost\"}`)\n } catch {\n return new URL(req.url ?? \"/\", \"http://localhost\")\n }\n}\n\n/** 본문을 limit 바이트까지. 넘으면 스트림 취소 후 \"too-large\" */\nasync function readBody(body: ReadableStream<Uint8Array> | null, limit: number): Promise<Uint8Array<ArrayBuffer> | \"too-large\"> {\n if (body === null) return new Uint8Array(0)\n const chunks: Uint8Array[] = []\n let size = 0\n const reader = body.getReader()\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n size += value.byteLength\n if (size > limit) {\n await reader.cancel().catch(() => {})\n return \"too-large\"\n }\n chunks.push(value)\n }\n const out = new Uint8Array(size)\n let offset = 0\n for (const c of chunks) {\n out.set(c, offset)\n offset += c.byteLength\n }\n return out\n}\n\nasync function sendResponse(res: ServerResponse, response: Response): Promise<void> {\n if (res.destroyed) {\n await response.body?.cancel().catch(() => {})\n return\n }\n res.statusCode = response.status\n response.headers.forEach((value, name) => res.setHeader(name, value))\n if (response.body === null) {\n res.end()\n return\n }\n const reader = response.body.getReader()\n // 클라이언트가 SSE 스트림을 닫으면 = 취소. SDK 가 transport 를 닫고 핸들러 signal 을 abort, 이후 메시지는 버린다\n const onClose = () => {\n if (!res.writableFinished) void reader.cancel().catch(() => {})\n }\n res.on(\"close\", onClose)\n res.flushHeaders()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done || res.destroyed) break\n res.write(value)\n }\n } catch {\n // 스트림 취소 · 생산자 오류: 아래에서 응답을 닫는다\n } finally {\n res.off(\"close\", onClose)\n }\n if (!res.destroyed) res.end()\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown, headers: Record<string, string> = {}): void {\n const text = JSON.stringify(body)\n res.writeHead(status, { \"Content-Type\": \"application/json\", \"Content-Length\": Buffer.byteLength(text), ...headers })\n res.end(text)\n}\n\nfunction jsonResponse(status: number, body: unknown, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), { status, headers: { \"Content-Type\": \"application/json\", ...headers } })\n}\n\nfunction unauthenticatedResponse(\n error: MextError<\"UNAUTHENTICATED\">,\n id: string | number | null,\n resourceMetadata: string | undefined,\n): Response {\n const params: string[] = []\n if (error.details.reason === \"invalid_token\") params.push('error=\"invalid_token\"')\n if (resourceMetadata !== undefined) params.push(`resource_metadata=\"${resourceMetadata}\"`)\n const challenge = params.length > 0 ? `Bearer ${params.join(\", \")}` : \"Bearer\"\n return jsonResponse(401, rpcError(-32_001, error.message, error.toJSON(), id), { \"WWW-Authenticate\": challenge })\n}\n\n/* OAuth 보호 자원 메타데이터 (RFC 9728) */\n\n/** MCP 엔드포인트 경로를 삽입한 well-known 경로 (/.well-known/oauth-protected-resource/mcp) */\nfunction protectedResourceMetadataPath(): string {\n return `${PROTECTED_RESOURCE_METADATA_PATH}${MCP_PATH}`\n}\n\nfunction resourceOf(oauth: OAuthResourceOptions, url: URL): string {\n return oauth.resource ?? `${url.origin}${MCP_PATH}`\n}\n\nfunction resourceMetadataUrl(oauth: OAuthResourceOptions, url: URL): string {\n const resource = new URL(resourceOf(oauth, url))\n const path = resource.pathname.replace(/\\/$/, \"\")\n return `${resource.origin}${PROTECTED_RESOURCE_METADATA_PATH}${path}`\n}\n\nfunction protectedResourceMetadata(oauth: OAuthResourceOptions, url: URL): Record<string, unknown> {\n const doc: Record<string, unknown> = {\n resource: resourceOf(oauth, url),\n authorization_servers: [...oauth.authorizationServers],\n bearer_methods_supported: [\"header\"],\n }\n if (oauth.scopesSupported) doc.scopes_supported = [...oauth.scopesSupported]\n return doc\n}\n\nfunction rpcError(code: number, message: string, data?: unknown, id: string | number | null = null) {\n return { jsonrpc: \"2.0\", id, error: data === undefined ? { code, message } : { code, message, data } }\n}\n\nconst NOT_JSON = Symbol(\"not-json\")\n\nfunction parseJson(body: Uint8Array): unknown {\n if (body.length === 0) return NOT_JSON\n try {\n return JSON.parse(new TextDecoder().decode(body))\n } catch {\n return NOT_JSON\n }\n}\n\nfunction requestId(body: unknown): string | number | null {\n if (body === null || typeof body !== \"object\" || Array.isArray(body)) return null\n const { id, method } = body as { id?: unknown; method?: unknown }\n if (typeof method !== \"string\") return null\n return typeof id === \"string\" || typeof id === \"number\" ? id : null\n}\n\nfunction hasProgressToken(body: unknown): boolean {\n if (body === null || typeof body !== \"object\" || Array.isArray(body)) return false\n const meta = (body as { params?: { _meta?: { progressToken?: unknown } } }).params?._meta\n return meta !== null && typeof meta === \"object\" && meta.progressToken !== undefined\n}\n\nfunction formatHost(host: string): string {\n return host.includes(\":\") && !host.startsWith(\"[\") ? `[${host}]` : host\n}\n"]}
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type AuthInfo, type McpRequestContext, type McpServerFactory } from "@modelcontextprotocol/server";
|
|
2
2
|
import type { MextApp } from "../command.ts";
|
|
3
|
+
import type { McpCapabilities } from "../config.ts";
|
|
3
4
|
import type { Instrumentation, Transport } from "../instrumentation.ts";
|
|
4
5
|
import { type Principal } from "../principal.ts";
|
|
5
6
|
import type { Registry } from "../registry.ts";
|
|
@@ -22,6 +23,10 @@ export interface McpCoreOptions {
|
|
|
22
23
|
tools?: ToolExposure;
|
|
23
24
|
/** serverInfo.name. 기본 "mext" */
|
|
24
25
|
name?: string;
|
|
26
|
+
/** initialize · server/discover 결과 instructions */
|
|
27
|
+
instructions?: string;
|
|
28
|
+
/** 서버 capabilities 에 병합 (experimental). tools capability 는 mext 가 고정 */
|
|
29
|
+
capabilities?: McpCapabilities;
|
|
25
30
|
/** serverInfo.version. 기본 mext 버전 */
|
|
26
31
|
version?: string;
|
|
27
32
|
/**
|
package/dist/mcp/server.js
CHANGED
|
@@ -22,10 +22,16 @@ export function createMcpServerFactory(options) {
|
|
|
22
22
|
const serverInfo = { name: options.name ?? "mext", version: options.version ?? VERSION };
|
|
23
23
|
const signer = createRequestStateSigner(options.requestStateKey === undefined ? {} : { key: options.requestStateKey });
|
|
24
24
|
const meta = { [MANIFEST_HASH_META_KEY]: options.manifestHash ?? registryManifestHash(options.registry) };
|
|
25
|
+
const experimental = options.capabilities?.experimental;
|
|
26
|
+
const capabilities = {
|
|
27
|
+
...(experimental && Object.keys(experimental).length > 0 ? { experimental: { ...experimental } } : {}),
|
|
28
|
+
tools: { listChanged: false },
|
|
29
|
+
};
|
|
25
30
|
return (requestContext) => {
|
|
26
31
|
const principal = resolvePrincipal(options.principal, requestContext);
|
|
27
32
|
const server = new McpServer(serverInfo, {
|
|
28
|
-
capabilities
|
|
33
|
+
capabilities,
|
|
34
|
+
...(options.instructions !== undefined && options.instructions !== "" ? { instructions: options.instructions } : {}),
|
|
29
35
|
cacheHints: { "tools/list": TOOLS_LIST_CACHE, "server/discover": TOOLS_LIST_CACHE },
|
|
30
36
|
});
|
|
31
37
|
withDiscoverMeta(server, meta);
|
package/dist/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CLIENT_CAPABILITIES_META_KEY,\n McpServer,\n type AuthInfo,\n type CallToolResult,\n type InputRequiredResult,\n type McpRequestContext,\n type McpServerFactory,\n type ServerContext,\n type StandardSchemaWithJSON,\n} from \"@modelcontextprotocol/server\"\nimport type { MextApp, ProgressUpdate } from \"../command.ts\"\nimport type { Instrumentation, Transport } from \"../instrumentation.ts\"\nimport { ANONYMOUS, type Principal } from \"../principal.ts\"\nimport type { JsonSchema, Registry } from \"../registry.ts\"\nimport { VERSION } from \"../index.ts\"\nimport { describeCommand, manifestHash } from \"../manifest.ts\"\nimport { MANIFEST_HASH_META_KEY } from \"./constants.ts\"\nimport { callDispatcher, dispatcherTools, type DispatcherTool, type ToolExposure } from \"./dispatch.ts\"\nimport { createRequestStateSigner, type InputRound, type RequestStateSigner } from \"./mrtr.ts\"\n\n/** tools/list · server/discover 캐시 힌트. 도구 정의는 principal 과 무관하게 고정 → public */\nexport const TOOLS_LIST_CACHE = { ttlMs: 300_000, cacheScope: \"public\" } as const\n\n/**\n * progressToken 있는 요청의 주기 progress 간격 (ms). 마지막 알림 후 이 시간 동안 알림이 없으면 보낸다.\n * TS SDK 클라이언트 기본 타임아웃 60초 · 프록시 유휴 타임아웃 (보통 60초) 보다 충분히 짧게\n */\nexport const PROGRESS_INTERVAL_MS = 15_000\n\n\nexport interface McpCoreOptions {\n registry: Registry\n /** ctx.app 생성. 처음 필요할 때 한 번 호출 (실패하면 다음 요청에서 재시도) */\n app?: () => MextApp | Promise<MextApp>\n /** 기본 execute */\n tools?: ToolExposure\n /** serverInfo.name. 기본 \"mext\" */\n name?: string\n /** serverInfo.version. 기본 mext 버전 */\n version?: string\n /**\n * 요청 주체. 기본 = HTTP transport 가 authInfo 로 넘긴 principal, 없으면 ANONYMOUS.\n * stdio = localPrincipal()\n */\n principal?: Principal | ((ctx: McpRequestContext) => Principal)\n /**\n * MRTR requestState 서명 키 (HMAC-SHA256, 32바이트 이상). requestState 는 2번째 이후 ctx.ask 에서만 쓴다.\n * 기본 = 프로세스별 임의 키. 여러 인스턴스 · 재시작을 넘는 재시도에는 공유 키를 지정한다\n */\n requestStateKey?: string | Uint8Array\n /** 주기 progress 간격 (ms). 기본 PROGRESS_INTERVAL_MS, 0 = 끔 */\n progressInterval?: number\n /** loadInstrumentation 결과 (onCommandError · span) */\n instrumentation?: Instrumentation\n /** onCommandError · span 의 transport. HTTP · stdio 어댑터가 지정 */\n transport?: Transport\n /**\n * _meta[\"dev.mext/manifestHash\"] 값. 기본 = registry 명령어로 계산 (mext dev = 스캔 결과).\n * mext start = manifest.json 의 manifestHash (같은 함수로 계산한 값)\n */\n manifestHash?: string\n}\n\n/**\n * Registry → MCP 서버 factory (SDK McpServerFactory). 요청 (HTTP) · 연결 (stdio) 마다 새 McpServer.\n * HTTP 의 createMcpHandler 와 stdio 의 serveStdio 가 같은 factory 를 쓴다.\n */\nexport function createMcpServerFactory(options: McpCoreOptions): McpServerFactory {\n const tools = dispatcherTools(options.registry, options.tools ?? \"execute\")\n const getApp = memoizeApp(options.app)\n const serverInfo = { name: options.name ?? \"mext\", version: options.version ?? VERSION }\n const signer = createRequestStateSigner(options.requestStateKey === undefined ? {} : { key: options.requestStateKey })\n const meta = { [MANIFEST_HASH_META_KEY]: options.manifestHash ?? registryManifestHash(options.registry) }\n return (requestContext) => {\n const principal = resolvePrincipal(options.principal, requestContext)\n const server = new McpServer(serverInfo, {\n capabilities: { tools: { listChanged: false } },\n cacheHints: { \"tools/list\": TOOLS_LIST_CACHE, \"server/discover\": TOOLS_LIST_CACHE },\n })\n withDiscoverMeta(server, meta)\n for (const tool of tools) {\n server.registerTool(\n tool.name,\n {\n title: tool.annotations.title,\n description: tool.description,\n inputSchema: passthroughSchema(tool.inputSchema),\n annotations: tool.annotations,\n },\n async (args, ctx) => withMeta(await runTool(options, tools, tool, args, ctx, principal, getApp, signer), meta),\n )\n }\n return server\n }\n}\n\n/** registry 명령어 메타데이터의 manifestHash (빌드 manifest 와 같은 계산) */\nexport function registryManifestHash(registry: Registry): string {\n return manifestHash([...registry.commands.values()].map(describeCommand))\n}\n\n/** 결과 _meta 에 mext 키 추가 (SDK 의 serverInfo 등 기존 _meta 유지) */\nfunction withMeta<T extends { _meta?: Record<string, unknown> }>(result: T, meta: Record<string, unknown>): T {\n return { ...result, _meta: { ...result._meta, ...meta } }\n}\n\n/**\n * server/discover 결과에 _meta 추가. SDK 의 discover handler 는 McpServer 생성 후 transport 진입점이\n * (재)설치하고 매번 server._ondiscover() 를 부르므로 인스턴스 메서드를 감싼다 (공개 API 에 discover _meta 옵션 없음)\n */\nfunction withDiscoverMeta(server: McpServer, meta: Record<string, unknown>): void {\n const inner = server.server as unknown as { _ondiscover?: () => Record<string, unknown> }\n const original = inner._ondiscover\n if (typeof original !== \"function\") return\n inner._ondiscover = function (this: unknown) {\n return withMeta(original.call(inner) as { _meta?: Record<string, unknown> }, meta)\n }\n}\n\nasync function runTool(\n options: McpCoreOptions,\n tools: readonly DispatcherTool[],\n tool: DispatcherTool,\n args: unknown,\n ctx: ServerContext,\n principal: Principal,\n getApp: () => Promise<MextApp>,\n signer: RequestStateSigner,\n): Promise<CallToolResult | InputRequiredResult> {\n const progress = progressReporter(ctx, options.progressInterval ?? PROGRESS_INTERVAL_MS)\n try {\n const app = await getApp()\n const result = await callDispatcher(options.registry, tool, args, {\n principal,\n signal: ctx.mcpReq.signal,\n ...(progress ? { progress: progress.report } : {}),\n app,\n tools,\n input: { ...inputRound(ctx), signer },\n ...(options.instrumentation ? { instrumentation: options.instrumentation, traceContext: traceCarrier(ctx) } : {}),\n ...(options.transport ? { transport: options.transport } : {}),\n })\n return result as CallToolResult | InputRequiredResult\n } finally {\n progress?.stop()\n }\n}\n\n/** 요청의 MRTR 입력: elicitation (form) 선언 · inputResponses · requestState (SDK 가 params 에서 분리) */\nfunction inputRound(ctx: ServerContext): InputRound {\n const envelope = ctx.mcpReq.envelope as Record<string, unknown> | undefined\n const capabilities = envelope?.[CLIENT_CAPABILITIES_META_KEY] as { elicitation?: unknown } | undefined\n const state = ctx.mcpReq.requestState()\n return {\n elicitation: declaresFormElicitation(capabilities?.elicitation),\n ...(ctx.mcpReq.inputResponses ? { inputResponses: ctx.mcpReq.inputResponses } : {}),\n ...(typeof state === \"string\" ? { requestState: state } : {}),\n }\n}\n\n/** D6: params._meta 의 W3C trace context (traceparent · tracestate · baggage). 등록된 propagator 가 해석 */\nfunction traceCarrier(ctx: ServerContext): Record<string, string> | undefined {\n const meta = ctx.mcpReq._meta as Record<string, unknown> | undefined\n let carrier: Record<string, string> | undefined\n for (const key of [\"traceparent\", \"tracestate\", \"baggage\"]) {\n const value = meta?.[key]\n if (typeof value === \"string\") (carrier ??= {})[key] = value\n }\n return carrier\n}\n\n/** elicitation.form 선언 또는 mode 없는 elicitation: {} (SDK 와 같은 해석). 2025 레거시 요청 = envelope 없음 → false */\nfunction declaresFormElicitation(value: unknown): boolean {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false\n const modes = value as { form?: unknown; url?: unknown }\n return modes.form !== undefined || modes.url === undefined\n}\n\n/**\n * ctx.progress → notifications/progress. 요청에 progressToken 이 있을 때만 (없으면 undefined = 무시).\n * HTTP 는 progressToken 이 있는 요청을 SSE 로 응답하므로 알림이 스트림으로 간다.\n * 주기 progress: 마지막 알림 후 intervalMs 동안 알림이 없으면 마지막 total · message 를 다시 보낸다 (keepalive).\n * progress 값은 항상 증가 (사양 MUST): 증가하지 않는 값 · keepalive 는 직전 값에 아주 작은 값을 더한다.\n */\nfunction progressReporter(\n ctx: ServerContext,\n intervalMs: number,\n): { report: (update: ProgressUpdate) => void; stop: () => void } | undefined {\n const token = ctx.mcpReq._meta?.progressToken\n if (token === undefined) return undefined\n let last: ProgressUpdate | undefined\n let timer: ReturnType<typeof setTimeout> | undefined\n let stopped = false\n const schedule = () => {\n if (timer !== undefined) clearTimeout(timer)\n if (intervalMs > 0 && !stopped) timer = setTimeout(() => report({ ...(last ?? { progress: 0 }) }), intervalMs)\n }\n const report = (update: ProgressUpdate) => {\n if (stopped || ctx.mcpReq.signal.aborted) return\n const progress = last === undefined || update.progress > last.progress ? update.progress : increase(last.progress)\n last = { progress, ...(update.total !== undefined ? { total: update.total } : {}), ...(update.message !== undefined ? { message: update.message } : {}) }\n const params: Record<string, unknown> = { progressToken: token, ...last }\n void ctx.mcpReq.notify({ method: \"notifications/progress\", params }).catch(() => {})\n schedule()\n }\n schedule()\n return {\n report,\n stop() {\n stopped = true\n if (timer !== undefined) clearTimeout(timer)\n },\n }\n}\n\n/** 직전 값보다 큰 가장 가까운 값 (표시에는 드러나지 않는 크기) */\nfunction increase(value: number): number {\n return value + Math.max(Math.abs(value), 1) * 1e-9\n}\n\n/* principal 은 SDK 의 pass-through authInfo 로 transport → factory 에 전달 */\n\nconst PRINCIPAL_KEY = \"mext.principal\"\n\n/** HTTP transport: 검증된 principal → SDK authInfo (토큰 원문은 담지 않는다) */\nexport function principalAuthInfo(principal: Principal): AuthInfo {\n return { token: \"\", clientId: principal.id, scopes: [...principal.scopes], extra: { [PRINCIPAL_KEY]: principal } }\n}\n\nexport function principalFromAuthInfo(authInfo: AuthInfo | undefined): Principal | undefined {\n const value = authInfo?.extra?.[PRINCIPAL_KEY]\n return isPrincipal(value) ? value : undefined\n}\n\nfunction resolvePrincipal(option: McpCoreOptions[\"principal\"], ctx: McpRequestContext): Principal {\n if (typeof option === \"function\") return option(ctx)\n if (option) return option\n return principalFromAuthInfo(ctx.authInfo) ?? ANONYMOUS\n}\n\nfunction isPrincipal(value: unknown): value is Principal {\n const p = value as Partial<Principal> | undefined\n return typeof p?.id === \"string\" && typeof p.kind === \"string\" && Array.isArray(p.scopes)\n}\n\nfunction memoizeApp(factory: McpCoreOptions[\"app\"]): () => Promise<MextApp> {\n if (!factory) return async () => ({}) as MextApp\n let pending: Promise<MextApp> | undefined\n return () => {\n pending ??= Promise.resolve()\n .then(factory)\n .catch((error: unknown) => {\n pending = undefined\n throw error\n })\n return pending\n }\n}\n\n/**\n * 고정 JSON Schema 를 그대로 광고하고 검증은 하지 않는 Standard Schema.\n * dispatcher 인자 검증은 callDispatcher 가 구조화 오류 (INVALID_ARGUMENT) 로 수행한다.\n */\nfunction passthroughSchema(schema: JsonSchema): StandardSchemaWithJSON<Record<string, unknown>> {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"mext\",\n validate: (value: unknown) => ({ value: value as Record<string, unknown> }),\n jsonSchema: { input: () => schema, output: () => schema },\n },\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,SAAS,GAQV,MAAM,8BAA8B,CAAA;AAIrC,OAAO,EAAE,SAAS,EAAkB,MAAM,iBAAiB,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,eAAe,EAA0C,MAAM,eAAe,CAAA;AACvG,OAAO,EAAE,wBAAwB,EAA4C,MAAM,WAAW,CAAA;AAI9F,8EAA8E;AAC9E,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAW,CAAA;AAEjF;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAA;AAwC1C;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAuB;IAC5D,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC,CAAA;IAC3E,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACtC,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO,EAAE,CAAA;IACxF,MAAM,MAAM,GAAG,wBAAwB,CAAC,OAAO,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IACtH,MAAM,IAAI,GAAG,EAAE,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC,YAAY,IAAI,oBAAoB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAA;IACzG,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,YAAY,CAAA;IACvD,MAAM,YAAY,GAAG;QACnB,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,GAAG,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtG,KAAK,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;KACR,CAAA;IACvB,OAAO,CAAC,cAAc,EAAE,EAAE;QACxB,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;QACrE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,UAAU,EAAE;YACvC,YAAY;YACZ,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpH,UAAU,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE;SACpF,CAAC,CAAA;QACF,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,IAAI,EACT;gBACE,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK;gBAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,WAAW,EAAE,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC;gBAChD,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B,EACD,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAC/G,CAAA;QACH,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;AACH,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,oBAAoB,CAAC,QAAkB;IACrD,OAAO,YAAY,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAA;AAC3E,CAAC;AAED,4DAA4D;AAC5D,SAAS,QAAQ,CAAgD,MAAS,EAAE,IAA6B;IACvG,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,CAAA;AAC3D,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,MAAiB,EAAE,IAA6B;IACxE,MAAM,KAAK,GAAG,MAAM,CAAC,MAAoE,CAAA;IACzF,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAA;IAClC,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAM;IAC1C,KAAK,CAAC,WAAW,GAAG;QAClB,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAwC,EAAE,IAAI,CAAC,CAAA;IACpF,CAAC,CAAA;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CACpB,OAAuB,EACvB,KAAgC,EAChC,IAAoB,EACpB,IAAa,EACb,GAAkB,EAClB,SAAoB,EACpB,MAA8B,EAC9B,MAA0B;IAE1B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,CAAA;IACxF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,EAAE,CAAA;QAC1B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE;YAChE,SAAS;YACT,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM;YACzB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,GAAG;YACH,KAAK;YACL,KAAK,EAAE,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE;YACrC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,YAAY,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjH,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/D,CAAC,CAAA;QACF,OAAO,MAA8C,CAAA;IACvD,CAAC;YAAS,CAAC;QACT,QAAQ,EAAE,IAAI,EAAE,CAAA;IAClB,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,SAAS,UAAU,CAAC,GAAkB;IACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,QAA+C,CAAA;IAC3E,MAAM,YAAY,GAAG,QAAQ,EAAE,CAAC,4BAA4B,CAA0C,CAAA;IACtG,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;IACvC,OAAO;QACL,WAAW,EAAE,uBAAuB,CAAC,YAAY,EAAE,WAAW,CAAC;QAC/D,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAA;AACH,CAAC;AAED,qGAAqG;AACrG,SAAS,YAAY,CAAC,GAAkB;IACtC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,KAA4C,CAAA;IACpE,IAAI,OAA2C,CAAA;IAC/C,KAAK,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;QAC3D,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;QACzB,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IAC9D,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,sGAAsG;AACtG,SAAS,uBAAuB,CAAC,KAAc;IAC7C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACrF,MAAM,KAAK,GAAG,KAA0C,CAAA;IACxD,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,CAAA;AAC5D,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CACvB,GAAkB,EAClB,UAAkB;IAElB,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,aAAa,CAAA;IAC7C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACzC,IAAI,IAAgC,CAAA;IACpC,IAAI,KAAgD,CAAA;IACpD,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,IAAI,KAAK,KAAK,SAAS;YAAE,YAAY,CAAC,KAAK,CAAC,CAAA;QAC5C,IAAI,UAAU,GAAG,CAAC,IAAI,CAAC,OAAO;YAAE,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAA;IAChH,CAAC,CAAA;IACD,MAAM,MAAM,GAAG,CAAC,MAAsB,EAAE,EAAE;QACxC,IAAI,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO;YAAE,OAAM;QAChD,MAAM,QAAQ,GAAG,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAClH,IAAI,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;QACzJ,MAAM,MAAM,GAA4B,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,CAAA;QACzE,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACpF,QAAQ,EAAE,CAAA;IACZ,CAAC,CAAA;IACD,QAAQ,EAAE,CAAA;IACV,OAAO;QACL,MAAM;QACN,IAAI;YACF,OAAO,GAAG,IAAI,CAAA;YACd,IAAI,KAAK,KAAK,SAAS;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAA;QAC9C,CAAC;KACF,CAAA;AACH,CAAC;AAED,0CAA0C;AAC1C,SAAS,QAAQ,CAAC,KAAa;IAC7B,OAAO,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAA;AACpD,CAAC;AAED,wEAAwE;AAExE,MAAM,aAAa,GAAG,gBAAgB,CAAA;AAEtC,mEAAmE;AACnE,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,EAAE,CAAA;AACpH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAA8B;IAClE,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,EAAE,CAAC,aAAa,CAAC,CAAA;IAC9C,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;AAC/C,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAmC,EAAE,GAAsB;IACnF,IAAI,OAAO,MAAM,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;IACpD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IACzB,OAAO,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAA;AACzD,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,CAAC,GAAG,KAAuC,CAAA;IACjD,OAAO,OAAO,CAAC,EAAE,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAC3F,CAAC;AAED,SAAS,UAAU,CAAC,OAA8B;IAChD,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAY,CAAA;IAChD,IAAI,OAAqC,CAAA;IACzC,OAAO,GAAG,EAAE;QACV,OAAO,KAAK,OAAO,CAAC,OAAO,EAAE;aAC1B,IAAI,CAAC,OAAO,CAAC;aACb,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACxB,OAAO,GAAG,SAAS,CAAA;YACnB,MAAM,KAAK,CAAA;QACb,CAAC,CAAC,CAAA;QACJ,OAAO,OAAO,CAAA;IAChB,CAAC,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,MAAkB;IAC3C,OAAO;QACL,WAAW,EAAE;YACX,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAgC,EAAE,CAAC;YAC3E,UAAU,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;SAC1D;KACF,CAAA;AACH,CAAC","sourcesContent":["import {\n CLIENT_CAPABILITIES_META_KEY,\n McpServer,\n type AuthInfo,\n type CallToolResult,\n type InputRequiredResult,\n type McpRequestContext,\n type McpServerFactory,\n type ServerContext,\n type StandardSchemaWithJSON,\n} from \"@modelcontextprotocol/server\"\nimport type { MextApp, ProgressUpdate } from \"../command.ts\"\nimport type { McpCapabilities } from \"../config.ts\"\nimport type { Instrumentation, Transport } from \"../instrumentation.ts\"\nimport { ANONYMOUS, type Principal } from \"../principal.ts\"\nimport type { JsonSchema, Registry } from \"../registry.ts\"\nimport { VERSION } from \"../index.ts\"\nimport { describeCommand, manifestHash } from \"../manifest.ts\"\nimport { MANIFEST_HASH_META_KEY } from \"./constants.ts\"\nimport { callDispatcher, dispatcherTools, type DispatcherTool, type ToolExposure } from \"./dispatch.ts\"\nimport { createRequestStateSigner, type InputRound, type RequestStateSigner } from \"./mrtr.ts\"\n\ntype ServerCapabilities = NonNullable<NonNullable<ConstructorParameters<typeof McpServer>[1]>[\"capabilities\"]>\n\n/** tools/list · server/discover 캐시 힌트. 도구 정의는 principal 과 무관하게 고정 → public */\nexport const TOOLS_LIST_CACHE = { ttlMs: 300_000, cacheScope: \"public\" } as const\n\n/**\n * progressToken 있는 요청의 주기 progress 간격 (ms). 마지막 알림 후 이 시간 동안 알림이 없으면 보낸다.\n * TS SDK 클라이언트 기본 타임아웃 60초 · 프록시 유휴 타임아웃 (보통 60초) 보다 충분히 짧게\n */\nexport const PROGRESS_INTERVAL_MS = 15_000\n\n\nexport interface McpCoreOptions {\n registry: Registry\n /** ctx.app 생성. 처음 필요할 때 한 번 호출 (실패하면 다음 요청에서 재시도) */\n app?: () => MextApp | Promise<MextApp>\n /** 기본 execute */\n tools?: ToolExposure\n /** serverInfo.name. 기본 \"mext\" */\n name?: string\n /** initialize · server/discover 결과 instructions */\n instructions?: string\n /** 서버 capabilities 에 병합 (experimental). tools capability 는 mext 가 고정 */\n capabilities?: McpCapabilities\n /** serverInfo.version. 기본 mext 버전 */\n version?: string\n /**\n * 요청 주체. 기본 = HTTP transport 가 authInfo 로 넘긴 principal, 없으면 ANONYMOUS.\n * stdio = localPrincipal()\n */\n principal?: Principal | ((ctx: McpRequestContext) => Principal)\n /**\n * MRTR requestState 서명 키 (HMAC-SHA256, 32바이트 이상). requestState 는 2번째 이후 ctx.ask 에서만 쓴다.\n * 기본 = 프로세스별 임의 키. 여러 인스턴스 · 재시작을 넘는 재시도에는 공유 키를 지정한다\n */\n requestStateKey?: string | Uint8Array\n /** 주기 progress 간격 (ms). 기본 PROGRESS_INTERVAL_MS, 0 = 끔 */\n progressInterval?: number\n /** loadInstrumentation 결과 (onCommandError · span) */\n instrumentation?: Instrumentation\n /** onCommandError · span 의 transport. HTTP · stdio 어댑터가 지정 */\n transport?: Transport\n /**\n * _meta[\"dev.mext/manifestHash\"] 값. 기본 = registry 명령어로 계산 (mext dev = 스캔 결과).\n * mext start = manifest.json 의 manifestHash (같은 함수로 계산한 값)\n */\n manifestHash?: string\n}\n\n/**\n * Registry → MCP 서버 factory (SDK McpServerFactory). 요청 (HTTP) · 연결 (stdio) 마다 새 McpServer.\n * HTTP 의 createMcpHandler 와 stdio 의 serveStdio 가 같은 factory 를 쓴다.\n */\nexport function createMcpServerFactory(options: McpCoreOptions): McpServerFactory {\n const tools = dispatcherTools(options.registry, options.tools ?? \"execute\")\n const getApp = memoizeApp(options.app)\n const serverInfo = { name: options.name ?? \"mext\", version: options.version ?? VERSION }\n const signer = createRequestStateSigner(options.requestStateKey === undefined ? {} : { key: options.requestStateKey })\n const meta = { [MANIFEST_HASH_META_KEY]: options.manifestHash ?? registryManifestHash(options.registry) }\n const experimental = options.capabilities?.experimental\n const capabilities = {\n ...(experimental && Object.keys(experimental).length > 0 ? { experimental: { ...experimental } } : {}),\n tools: { listChanged: false },\n } as ServerCapabilities\n return (requestContext) => {\n const principal = resolvePrincipal(options.principal, requestContext)\n const server = new McpServer(serverInfo, {\n capabilities,\n ...(options.instructions !== undefined && options.instructions !== \"\" ? { instructions: options.instructions } : {}),\n cacheHints: { \"tools/list\": TOOLS_LIST_CACHE, \"server/discover\": TOOLS_LIST_CACHE },\n })\n withDiscoverMeta(server, meta)\n for (const tool of tools) {\n server.registerTool(\n tool.name,\n {\n title: tool.annotations.title,\n description: tool.description,\n inputSchema: passthroughSchema(tool.inputSchema),\n annotations: tool.annotations,\n },\n async (args, ctx) => withMeta(await runTool(options, tools, tool, args, ctx, principal, getApp, signer), meta),\n )\n }\n return server\n }\n}\n\n/** registry 명령어 메타데이터의 manifestHash (빌드 manifest 와 같은 계산) */\nexport function registryManifestHash(registry: Registry): string {\n return manifestHash([...registry.commands.values()].map(describeCommand))\n}\n\n/** 결과 _meta 에 mext 키 추가 (SDK 의 serverInfo 등 기존 _meta 유지) */\nfunction withMeta<T extends { _meta?: Record<string, unknown> }>(result: T, meta: Record<string, unknown>): T {\n return { ...result, _meta: { ...result._meta, ...meta } }\n}\n\n/**\n * server/discover 결과에 _meta 추가. SDK 의 discover handler 는 McpServer 생성 후 transport 진입점이\n * (재)설치하고 매번 server._ondiscover() 를 부르므로 인스턴스 메서드를 감싼다 (공개 API 에 discover _meta 옵션 없음)\n */\nfunction withDiscoverMeta(server: McpServer, meta: Record<string, unknown>): void {\n const inner = server.server as unknown as { _ondiscover?: () => Record<string, unknown> }\n const original = inner._ondiscover\n if (typeof original !== \"function\") return\n inner._ondiscover = function (this: unknown) {\n return withMeta(original.call(inner) as { _meta?: Record<string, unknown> }, meta)\n }\n}\n\nasync function runTool(\n options: McpCoreOptions,\n tools: readonly DispatcherTool[],\n tool: DispatcherTool,\n args: unknown,\n ctx: ServerContext,\n principal: Principal,\n getApp: () => Promise<MextApp>,\n signer: RequestStateSigner,\n): Promise<CallToolResult | InputRequiredResult> {\n const progress = progressReporter(ctx, options.progressInterval ?? PROGRESS_INTERVAL_MS)\n try {\n const app = await getApp()\n const result = await callDispatcher(options.registry, tool, args, {\n principal,\n signal: ctx.mcpReq.signal,\n ...(progress ? { progress: progress.report } : {}),\n app,\n tools,\n input: { ...inputRound(ctx), signer },\n ...(options.instrumentation ? { instrumentation: options.instrumentation, traceContext: traceCarrier(ctx) } : {}),\n ...(options.transport ? { transport: options.transport } : {}),\n })\n return result as CallToolResult | InputRequiredResult\n } finally {\n progress?.stop()\n }\n}\n\n/** 요청의 MRTR 입력: elicitation (form) 선언 · inputResponses · requestState (SDK 가 params 에서 분리) */\nfunction inputRound(ctx: ServerContext): InputRound {\n const envelope = ctx.mcpReq.envelope as Record<string, unknown> | undefined\n const capabilities = envelope?.[CLIENT_CAPABILITIES_META_KEY] as { elicitation?: unknown } | undefined\n const state = ctx.mcpReq.requestState()\n return {\n elicitation: declaresFormElicitation(capabilities?.elicitation),\n ...(ctx.mcpReq.inputResponses ? { inputResponses: ctx.mcpReq.inputResponses } : {}),\n ...(typeof state === \"string\" ? { requestState: state } : {}),\n }\n}\n\n/** D6: params._meta 의 W3C trace context (traceparent · tracestate · baggage). 등록된 propagator 가 해석 */\nfunction traceCarrier(ctx: ServerContext): Record<string, string> | undefined {\n const meta = ctx.mcpReq._meta as Record<string, unknown> | undefined\n let carrier: Record<string, string> | undefined\n for (const key of [\"traceparent\", \"tracestate\", \"baggage\"]) {\n const value = meta?.[key]\n if (typeof value === \"string\") (carrier ??= {})[key] = value\n }\n return carrier\n}\n\n/** elicitation.form 선언 또는 mode 없는 elicitation: {} (SDK 와 같은 해석). 2025 레거시 요청 = envelope 없음 → false */\nfunction declaresFormElicitation(value: unknown): boolean {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false\n const modes = value as { form?: unknown; url?: unknown }\n return modes.form !== undefined || modes.url === undefined\n}\n\n/**\n * ctx.progress → notifications/progress. 요청에 progressToken 이 있을 때만 (없으면 undefined = 무시).\n * HTTP 는 progressToken 이 있는 요청을 SSE 로 응답하므로 알림이 스트림으로 간다.\n * 주기 progress: 마지막 알림 후 intervalMs 동안 알림이 없으면 마지막 total · message 를 다시 보낸다 (keepalive).\n * progress 값은 항상 증가 (사양 MUST): 증가하지 않는 값 · keepalive 는 직전 값에 아주 작은 값을 더한다.\n */\nfunction progressReporter(\n ctx: ServerContext,\n intervalMs: number,\n): { report: (update: ProgressUpdate) => void; stop: () => void } | undefined {\n const token = ctx.mcpReq._meta?.progressToken\n if (token === undefined) return undefined\n let last: ProgressUpdate | undefined\n let timer: ReturnType<typeof setTimeout> | undefined\n let stopped = false\n const schedule = () => {\n if (timer !== undefined) clearTimeout(timer)\n if (intervalMs > 0 && !stopped) timer = setTimeout(() => report({ ...(last ?? { progress: 0 }) }), intervalMs)\n }\n const report = (update: ProgressUpdate) => {\n if (stopped || ctx.mcpReq.signal.aborted) return\n const progress = last === undefined || update.progress > last.progress ? update.progress : increase(last.progress)\n last = { progress, ...(update.total !== undefined ? { total: update.total } : {}), ...(update.message !== undefined ? { message: update.message } : {}) }\n const params: Record<string, unknown> = { progressToken: token, ...last }\n void ctx.mcpReq.notify({ method: \"notifications/progress\", params }).catch(() => {})\n schedule()\n }\n schedule()\n return {\n report,\n stop() {\n stopped = true\n if (timer !== undefined) clearTimeout(timer)\n },\n }\n}\n\n/** 직전 값보다 큰 가장 가까운 값 (표시에는 드러나지 않는 크기) */\nfunction increase(value: number): number {\n return value + Math.max(Math.abs(value), 1) * 1e-9\n}\n\n/* principal 은 SDK 의 pass-through authInfo 로 transport → factory 에 전달 */\n\nconst PRINCIPAL_KEY = \"mext.principal\"\n\n/** HTTP transport: 검증된 principal → SDK authInfo (토큰 원문은 담지 않는다) */\nexport function principalAuthInfo(principal: Principal): AuthInfo {\n return { token: \"\", clientId: principal.id, scopes: [...principal.scopes], extra: { [PRINCIPAL_KEY]: principal } }\n}\n\nexport function principalFromAuthInfo(authInfo: AuthInfo | undefined): Principal | undefined {\n const value = authInfo?.extra?.[PRINCIPAL_KEY]\n return isPrincipal(value) ? value : undefined\n}\n\nfunction resolvePrincipal(option: McpCoreOptions[\"principal\"], ctx: McpRequestContext): Principal {\n if (typeof option === \"function\") return option(ctx)\n if (option) return option\n return principalFromAuthInfo(ctx.authInfo) ?? ANONYMOUS\n}\n\nfunction isPrincipal(value: unknown): value is Principal {\n const p = value as Partial<Principal> | undefined\n return typeof p?.id === \"string\" && typeof p.kind === \"string\" && Array.isArray(p.scopes)\n}\n\nfunction memoizeApp(factory: McpCoreOptions[\"app\"]): () => Promise<MextApp> {\n if (!factory) return async () => ({}) as MextApp\n let pending: Promise<MextApp> | undefined\n return () => {\n pending ??= Promise.resolve()\n .then(factory)\n .catch((error: unknown) => {\n pending = undefined\n throw error\n })\n return pending\n }\n}\n\n/**\n * 고정 JSON Schema 를 그대로 광고하고 검증은 하지 않는 Standard Schema.\n * dispatcher 인자 검증은 callDispatcher 가 구조화 오류 (INVALID_ARGUMENT) 로 수행한다.\n */\nfunction passthroughSchema(schema: JsonSchema): StandardSchemaWithJSON<Record<string, unknown>> {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"mext\",\n validate: (value: unknown) => ({ value: value as Record<string, unknown> }),\n jsonSchema: { input: () => schema, output: () => schema },\n },\n }\n}\n"]}
|
package/dist/mcp/stdio.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Readable } from "node:stream";
|
|
2
2
|
import { Writable } from "node:stream";
|
|
3
3
|
import type { MextApp } from "../command.ts";
|
|
4
|
+
import type { McpCapabilities, McpConnectHandler } from "../config.ts";
|
|
4
5
|
import { type Principal } from "../principal.ts";
|
|
5
6
|
import type { Registry } from "../registry.ts";
|
|
6
7
|
import type { Instrumentation } from "../instrumentation.ts";
|
|
@@ -12,6 +13,21 @@ export interface McpStdioOptions {
|
|
|
12
13
|
tools?: ToolExposure;
|
|
13
14
|
/** serverInfo.name. 기본 "mext" */
|
|
14
15
|
name?: string;
|
|
16
|
+
/** initialize · server/discover 결과 instructions */
|
|
17
|
+
instructions?: string;
|
|
18
|
+
/** 서버 capabilities 에 병합 (experimental) */
|
|
19
|
+
capabilities?: McpCapabilities;
|
|
20
|
+
/**
|
|
21
|
+
* 연결 하나에 1회 (2025 = notifications/initialized 후, 2026-07-28 = 연결 직후).
|
|
22
|
+
* conn.notify = 요청과 무관한 서버 발신 알림. 반환 함수 = 연결 종료 시 cleanup. 예외 = onerror
|
|
23
|
+
*/
|
|
24
|
+
onConnect?: McpConnectHandler;
|
|
25
|
+
/**
|
|
26
|
+
* auto = 2026-07-28 · 2025 모두 (SDK serveStdio 가 판별). legacy = 2025 만:
|
|
27
|
+
* server/discover = -32601 → 클라이언트가 initialize 로 재시도 (Claude Code channel 은 2025 연결에서만 전달).
|
|
28
|
+
* 기본 = capabilities.experimental["claude/channel"] 선언 시 legacy, 그 외 auto
|
|
29
|
+
*/
|
|
30
|
+
era?: "auto" | "legacy";
|
|
15
31
|
/** 연결 주체 (로컬 모드). 기본 localPrincipal() */
|
|
16
32
|
principal?: Principal;
|
|
17
33
|
/** 기본 process.stdin */
|
|
@@ -43,6 +59,8 @@ export interface McpStdioServer {
|
|
|
43
59
|
* 헤더 검증 · Origin · 바인딩 · Authorization 은 해당 없음. 주체 = 로컬 (kind local).
|
|
44
60
|
*/
|
|
45
61
|
export declare function serveMcpStdio(options: McpStdioOptions): McpStdioServer;
|
|
62
|
+
/** 연결 종료 후 onConnect cleanup 대기 상한 (ms). 넘으면 오류 보고 후 종료 진행 */
|
|
63
|
+
export declare const CLEANUP_TIMEOUT_MS = 5000;
|
|
46
64
|
export interface StdoutRedirect {
|
|
47
65
|
/** 원래 process.stdout 으로 쓰는 스트림. MCP transport 전용 */
|
|
48
66
|
wire: Writable;
|
package/dist/mcp/stdio.js
CHANGED
|
@@ -8,42 +8,185 @@ import { createMcpServerFactory } from "./server.js";
|
|
|
8
8
|
* 헤더 검증 · Origin · 바인딩 · Authorization 은 해당 없음. 주체 = 로컬 (kind local).
|
|
9
9
|
*/
|
|
10
10
|
export function serveMcpStdio(options) {
|
|
11
|
-
const
|
|
11
|
+
const core = createMcpServerFactory({
|
|
12
12
|
registry: options.registry,
|
|
13
13
|
principal: options.principal ?? localPrincipal(),
|
|
14
14
|
...(options.app ? { app: options.app } : {}),
|
|
15
15
|
...(options.tools ? { tools: options.tools } : {}),
|
|
16
16
|
...(options.name ? { name: options.name } : {}),
|
|
17
|
+
...(options.instructions !== undefined ? { instructions: options.instructions } : {}),
|
|
18
|
+
...(options.capabilities ? { capabilities: options.capabilities } : {}),
|
|
17
19
|
...(options.requestStateKey !== undefined ? { requestStateKey: options.requestStateKey } : {}),
|
|
18
20
|
...(options.progressInterval !== undefined ? { progressInterval: options.progressInterval } : {}),
|
|
19
21
|
...(options.instrumentation ? { instrumentation: options.instrumentation } : {}),
|
|
20
22
|
...(options.manifestHash !== undefined ? { manifestHash: options.manifestHash } : {}),
|
|
21
23
|
transport: "stdio",
|
|
22
24
|
});
|
|
25
|
+
const onConnect = options.onConnect;
|
|
26
|
+
const report = (error) => options.onerror?.(error instanceof Error ? error : new Error(String(error)));
|
|
27
|
+
/** 인스턴스별 정리 완료 (onConnect settle + cleanup). closed 는 이것들을 기다린다 */
|
|
28
|
+
const settled = new Set();
|
|
29
|
+
const factory = onConnect
|
|
30
|
+
? async (ctx) => {
|
|
31
|
+
const server = (await core(ctx));
|
|
32
|
+
settled.add(attachConnection(server, ctx.era, onConnect, report));
|
|
33
|
+
return server;
|
|
34
|
+
}
|
|
35
|
+
: core;
|
|
23
36
|
const transport = new StdioServerTransport(options.stdin, options.stdout);
|
|
24
37
|
let resolveClosed;
|
|
25
38
|
const closed = new Promise((resolve) => {
|
|
26
39
|
resolveClosed = resolve;
|
|
27
40
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
let finishing = false;
|
|
42
|
+
const finish = () => {
|
|
43
|
+
if (finishing)
|
|
44
|
+
return;
|
|
45
|
+
finishing = true;
|
|
46
|
+
void waitCleanups(settled, report).then(resolveClosed);
|
|
47
|
+
};
|
|
48
|
+
const wrapClose = () => {
|
|
49
|
+
const sdkOnClose = transport.onclose;
|
|
50
|
+
transport.onclose = () => {
|
|
51
|
+
try {
|
|
52
|
+
sdkOnClose?.();
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
finish();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
38
58
|
};
|
|
59
|
+
let handle;
|
|
60
|
+
const era = options.era ?? (options.capabilities?.experimental?.[CLAUDE_CHANNEL] !== undefined ? "legacy" : "auto");
|
|
61
|
+
if (era === "legacy") {
|
|
62
|
+
// serveStdio 는 server/discover 를 받으면 2026-07-28 로 고정한다 → 우회.
|
|
63
|
+
// SDK 기본 supportedProtocolVersions = 2025 버전만 → McpServer 생성자가 server/discover 를 등록하지 않는다
|
|
64
|
+
const ready = Promise.resolve(factory({ era: "legacy" })).then(async (product) => {
|
|
65
|
+
const server = product;
|
|
66
|
+
server.server.onerror = report;
|
|
67
|
+
await server.connect(transport);
|
|
68
|
+
wrapClose();
|
|
69
|
+
return server;
|
|
70
|
+
});
|
|
71
|
+
ready.catch((error) => {
|
|
72
|
+
report(error);
|
|
73
|
+
finish();
|
|
74
|
+
});
|
|
75
|
+
handle = {
|
|
76
|
+
async close() {
|
|
77
|
+
const server = await ready.catch(() => undefined);
|
|
78
|
+
await server?.close();
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
handle = serveStdio(factory, options.onerror ? { transport, onerror: options.onerror } : { transport });
|
|
84
|
+
// serveStdio 가 onclose 를 동기적으로 설정한 뒤 감싼다 (stdin 이벤트는 비동기)
|
|
85
|
+
wrapClose();
|
|
86
|
+
}
|
|
39
87
|
return {
|
|
40
88
|
closed,
|
|
41
89
|
async close() {
|
|
42
90
|
await handle.close();
|
|
43
|
-
|
|
91
|
+
finish();
|
|
92
|
+
await closed;
|
|
44
93
|
},
|
|
45
94
|
};
|
|
46
95
|
}
|
|
96
|
+
/** Claude Code channel capability. 선언하면 stdio 기본 era = legacy */
|
|
97
|
+
const CLAUDE_CHANNEL = "claude/channel";
|
|
98
|
+
/** 연결 종료 후 onConnect cleanup 대기 상한 (ms). 넘으면 오류 보고 후 종료 진행 */
|
|
99
|
+
export const CLEANUP_TIMEOUT_MS = 5_000;
|
|
100
|
+
async function waitCleanups(settled, report) {
|
|
101
|
+
if (settled.size === 0)
|
|
102
|
+
return;
|
|
103
|
+
let timer;
|
|
104
|
+
const timeout = new Promise((resolve) => {
|
|
105
|
+
timer = setTimeout(() => resolve("timeout"), CLEANUP_TIMEOUT_MS);
|
|
106
|
+
timer.unref?.();
|
|
107
|
+
});
|
|
108
|
+
const result = await Promise.race([Promise.all(settled), timeout]);
|
|
109
|
+
clearTimeout(timer);
|
|
110
|
+
if (result === "timeout")
|
|
111
|
+
report(new Error(`mcp.onConnect cleanup did not finish within ${CLEANUP_TIMEOUT_MS}ms`));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* McpServer 인스턴스 하나 = stdio 연결 하나. onConnect 시점: 2025 = notifications/initialized
|
|
115
|
+
* (initialize 응답 전 알림은 클라이언트가 버릴 수 있음), 2026-07-28 = connect 직후 (handshake 없음).
|
|
116
|
+
* SDK 가 era 판별용 probe 인스턴스를 버리면 그 인스턴스의 onclose 로 cleanup 된다.
|
|
117
|
+
* 반환 = 인스턴스 종료 후 (onConnect settle · cleanup 완료) resolve. 시작 전 종료 = 바로 resolve
|
|
118
|
+
*/
|
|
119
|
+
function attachConnection(server, era, onConnect, report) {
|
|
120
|
+
const inner = server.server;
|
|
121
|
+
let connected;
|
|
122
|
+
let resolveDone;
|
|
123
|
+
const done = new Promise((resolve) => {
|
|
124
|
+
resolveDone = resolve;
|
|
125
|
+
});
|
|
126
|
+
let closed = false;
|
|
127
|
+
const handlers = new Map();
|
|
128
|
+
// SDK 가 등록하지 않은 method 만 fallback 으로 온다 (사양 알림은 SDK handler · era 필터가 먼저)
|
|
129
|
+
inner.fallbackNotificationHandler = async (notification) => {
|
|
130
|
+
const handler = handlers.get(notification.method);
|
|
131
|
+
if (!handler)
|
|
132
|
+
return;
|
|
133
|
+
const params = (notification.params ?? {});
|
|
134
|
+
try {
|
|
135
|
+
await handler(params);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
report(error);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const conn = {
|
|
142
|
+
era,
|
|
143
|
+
notify: (method, params) => inner.notification({ method, ...(params !== undefined ? { params } : {}) }),
|
|
144
|
+
onNotification(method, handler) {
|
|
145
|
+
handlers.set(method, handler);
|
|
146
|
+
return () => {
|
|
147
|
+
if (handlers.get(method) === handler)
|
|
148
|
+
handlers.delete(method);
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
const start = () => {
|
|
153
|
+
if (connected || closed)
|
|
154
|
+
return;
|
|
155
|
+
connected = Promise.resolve().then(() => onConnect(conn));
|
|
156
|
+
connected.catch(report);
|
|
157
|
+
};
|
|
158
|
+
const previousClose = inner.onclose;
|
|
159
|
+
inner.onclose = () => {
|
|
160
|
+
previousClose?.();
|
|
161
|
+
if (closed)
|
|
162
|
+
return;
|
|
163
|
+
closed = true;
|
|
164
|
+
if (!connected)
|
|
165
|
+
return resolveDone();
|
|
166
|
+
connected
|
|
167
|
+
.then(async (cleanup) => {
|
|
168
|
+
if (typeof cleanup === "function")
|
|
169
|
+
await cleanup();
|
|
170
|
+
}, () => { })
|
|
171
|
+
.catch(report)
|
|
172
|
+
.finally(resolveDone);
|
|
173
|
+
};
|
|
174
|
+
if (era === "legacy") {
|
|
175
|
+
const previousInit = inner.oninitialized;
|
|
176
|
+
inner.oninitialized = () => {
|
|
177
|
+
previousInit?.();
|
|
178
|
+
start();
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const connect = server.connect.bind(server);
|
|
183
|
+
server.connect = async (transport) => {
|
|
184
|
+
await connect(transport);
|
|
185
|
+
start();
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return done;
|
|
189
|
+
}
|
|
47
190
|
/**
|
|
48
191
|
* D4: stdio 모드에서 transport 외의 stdout 쓰기 (console.log · process.stdout.write) 를 stderr 로 돌린다.
|
|
49
192
|
* 반환된 wire 만 실제 stdout 에 쓴다. 명령어 모듈 import 전에 호출해야 top-level 출력도 막는다.
|