(spec: McpServerSpec, opts: AddServerOptions = {})
| 45 | |
| 46 | /** Build a config entry object from a registry spec + provided secrets. */ |
| 47 | export function buildServerEntry(spec: McpServerSpec, opts: AddServerOptions = {}): BuiltServerEntry { |
| 48 | const secrets = opts.secrets ?? {}; |
| 49 | const ref = (envVar: string): string => |
| 50 | opts.inlineToken && secrets[envVar] ? secrets[envVar]! : `\${${envVar}}`; |
| 51 | |
| 52 | const entry: BuiltServerEntry = { enabled: true }; |
| 53 | if (spec.destructive) entry.destructive = true; |
| 54 | if (spec.startupTimeoutSeconds) entry.startupTimeoutSeconds = spec.startupTimeoutSeconds; |
| 55 | |
| 56 | if (spec.transport === 'stdio') { |
| 57 | entry.command = spec.command; |
| 58 | entry.args = [...(spec.args ?? [])]; |
| 59 | |
| 60 | // connstr / templated-arg servers: append the credential as an argument. |
| 61 | if (spec.tokenArgTemplate && spec.credentials[0]) { |
| 62 | const cred = spec.credentials[0]; |
| 63 | for (const t of spec.tokenArgTemplate) { |
| 64 | entry.args.push(t.replace('{TOKEN}', ref(cred.envVar))); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | // token servers (stdio): expose every credential as an env var. |
| 69 | const env: Record<string, string> = {}; |
| 70 | for (const cred of spec.credentials) { |
| 71 | // Skip ones already consumed by tokenArgTemplate |
| 72 | if (spec.tokenArgTemplate) continue; |
| 73 | env[cred.envVar] = ref(cred.envVar); |
| 74 | } |
| 75 | if (Object.keys(env).length > 0) entry.env = env; |
| 76 | } else { |
| 77 | // remote |
| 78 | entry.url = spec.url; |
| 79 | if (spec.streamable) entry.streamable = true; |
| 80 | if (spec.auth === 'token' && spec.authHeader && spec.credentials[0]) { |
| 81 | const cred = spec.credentials[0]; |
| 82 | const fmt = spec.authHeaderFormat ?? '{TOKEN}'; |
| 83 | entry.headers = { [spec.authHeader]: fmt.replace('{TOKEN}', ref(cred.envVar)) }; |
| 84 | } |
| 85 | // oauth remote: no headers — the MCP client negotiates in the browser. |
| 86 | } |
| 87 | return entry; |
| 88 | } |
| 89 | |
| 90 | async function readRawUserConfig(): Promise<any> { |
| 91 | try { |
no test coverage detected