(input: {
readonly pluginRoot: string;
readonly name: string;
readonly config: McpServerConfig;
readonly diagnostics: PluginDiagnostic[];
})
| 386 | } |
| 387 | |
| 388 | async function normalizePluginMcpServer(input: { |
| 389 | readonly pluginRoot: string; |
| 390 | readonly name: string; |
| 391 | readonly config: McpServerConfig; |
| 392 | readonly diagnostics: PluginDiagnostic[]; |
| 393 | }): Promise<McpServerConfig | undefined> { |
| 394 | const { config } = input; |
| 395 | if (config.transport === 'http' || config.transport === 'sse') return config; |
| 396 | |
| 397 | let command = config.command; |
| 398 | if (command.startsWith('./')) { |
| 399 | const resolvedCommand = await resolvePluginPathField({ |
| 400 | pluginRoot: input.pluginRoot, |
| 401 | field: `mcpServers.${input.name}.command`, |
| 402 | value: command, |
| 403 | diagnostics: input.diagnostics, |
| 404 | }); |
| 405 | if (resolvedCommand === undefined) return undefined; |
| 406 | command = resolvedCommand; |
| 407 | } else if (command.includes('/') || path.isAbsolute(command)) { |
| 408 | input.diagnostics.push({ |
| 409 | severity: 'warn', |
| 410 | message: `"mcpServers.${input.name}.command" must be a PATH command or start with "./"`, |
| 411 | }); |
| 412 | return undefined; |
| 413 | } |
| 414 | |
| 415 | let cwd = config.cwd; |
| 416 | if (cwd !== undefined) { |
| 417 | const resolvedCwd = await resolvePluginPathField({ |
| 418 | pluginRoot: input.pluginRoot, |
| 419 | field: `mcpServers.${input.name}.cwd`, |
| 420 | value: cwd, |
| 421 | diagnostics: input.diagnostics, |
| 422 | }); |
| 423 | if (resolvedCwd === undefined) return undefined; |
| 424 | cwd = resolvedCwd; |
| 425 | } |
| 426 | |
| 427 | return { ...config, command, cwd }; |
| 428 | } |
| 429 | |
| 430 | function readAuthor(raw: unknown): PluginManifest['author'] { |
| 431 | if (typeof raw === 'string') return { name: raw }; |
no test coverage detected