MCPcopy Create free account
hub / github.com/MatterAIOrg/OrbCode / normalizeExternalServer

Function normalizeExternalServer

src/commands/migrate.ts:124–181  ·  view source on GitHub ↗

* Normalize a single MCP server config from an external source. We do not run * the full `normalizeServerConfig` from `mcp/config.ts` because it has side * effects (env expansion) and Claude's shape is already a subset of ours. * Only stdio / http / sse entries with the required fields survive.

(raw: unknown)

Source from the content-addressed store, hash-verified

122 * Only stdio / http / sse entries with the required fields survive.
123 */
124function normalizeExternalServer(raw: unknown): McpServerConfig | undefined {
125 if (!isPlainObject(raw)) return undefined;
126 const type = typeof raw.type === "string" ? raw.type : "stdio";
127
128 if (type === "stdio") {
129 if (typeof raw.command !== "string" || !raw.command.trim())
130 return undefined;
131 const config: McpStdioServerConfig = {
132 type: "stdio",
133 command: raw.command,
134 };
135 if (Array.isArray(raw.args)) {
136 const args = raw.args.filter((a): a is string => typeof a === "string");
137 if (args.length > 0) config.args = args;
138 }
139 if (isPlainObject(raw.env)) {
140 const env: Record<string, string> = {};
141 for (const [k, v] of Object.entries(raw.env)) {
142 if (typeof v === "string") env[k] = v;
143 }
144 if (Object.keys(env).length > 0) config.env = env;
145 }
146 return config;
147 }
148
149 if (type === "http" || type === "sse") {
150 if (typeof raw.url !== "string" || !raw.url.trim()) return undefined;
151 const config: McpHttpServerConfig | McpSseServerConfig = {
152 type,
153 url: raw.url,
154 };
155 if (isPlainObject(raw.headers)) {
156 const headers: Record<string, string> = {};
157 for (const [k, v] of Object.entries(raw.headers)) {
158 if (typeof v === "string") headers[k] = v;
159 }
160 if (Object.keys(headers).length > 0) config.headers = headers;
161 }
162 return config;
163 }
164
165 // `streamable-http` is Claude Code's preferred name for the modern HTTP
166 // transport; OrbCode aliases it as "http".
167 if (type === "streamable-http" || type === "streamable_http") {
168 if (typeof raw.url !== "string" || !raw.url.trim()) return undefined;
169 const config: McpHttpServerConfig = { type: "http", url: raw.url };
170 if (isPlainObject(raw.headers)) {
171 const headers: Record<string, string> = {};
172 for (const [k, v] of Object.entries(raw.headers)) {
173 if (typeof v === "string") headers[k] = v;
174 }
175 if (Object.keys(headers).length > 0) config.headers = headers;
176 }
177 return config;
178 }
179
180 return undefined;
181}

Callers 2

readMcpServersFunction · 0.85
readMcpServersFromObjectFunction · 0.85

Calls 1

isPlainObjectFunction · 0.70

Tested by

no test coverage detected