McpServerConfig.fromYaml constructor

McpServerConfig.fromYaml(
  1. String name,
  2. Object? node
)

Parses one mcp.servers.<name> entry: a map with either command (stdio) or url (remote). Having both or neither is a schema error.

Implementation

factory McpServerConfig.fromYaml(String name, Object? node) {
  if (name.trim().isEmpty) {
    throw const ConfigException(
      'mcp.servers: server names must be non-empty',
    );
  }
  if (node is! YamlMap) {
    throw ConfigException(
      'mcp.servers.$name must be a map with "command" (stdio) or "url" '
      '(remote), got ${node.runtimeType}',
    );
  }
  final command = node['command'];
  final url = node['url'];
  if (command != null && url != null) {
    throw ConfigException(
      'mcp.servers.$name must not mix "command" (stdio) and "url" (remote)',
    );
  }
  if (command != null) {
    if (command is! String || command.trim().isEmpty) {
      throw ConfigException(
        'mcp.servers.$name.command must be a non-empty string',
      );
    }
    return McpStdioServerConfig(
      name: name,
      command: command.trim(),
      args: _stringList(node['args'], 'mcp.servers.$name.args'),
      env: _stringMap(node['env'], 'mcp.servers.$name.env'),
    );
  }
  if (url is! String || url.trim().isEmpty) {
    throw ConfigException(
      'mcp.servers.$name requires a non-empty "command" (stdio) or "url" '
      '(remote) string',
    );
  }
  final transportLabel = node['transport'];
  if (transportLabel != null && transportLabel is! String) {
    throw ConfigException('mcp.servers.$name.transport must be a string');
  }
  return McpHttpServerConfig(
    name: name,
    url: url.trim(),
    transport: transportLabel == null
        ? McpHttpTransportKind.streamableHttp
        : McpHttpTransportKind.parse(transportLabel, server: name),
    headers: _stringMap(node['headers'], 'mcp.servers.$name.headers'),
  );
}