vercel/ai · error

Cline MCP server ${JSON.stringify(input.serverName)} must de

Error message

Cline MCP server ${JSON.stringify(input.serverName)} must define a transport, command, or URL.

What it means

resolveTransport normalizes a Cline MCP server registration into a concrete transport (stdio via command, or SSE/streamable-HTTP via URL). If the server entry has none of a transport definition, a command, or a URL, no transport can be derived, so it throws this error. It is a configuration-validation error for the MCP server config.

Source

Thrown at packages/harness-cline/src/cline-mcp.ts:79

        : {}),
      ...(env ? { env } : {}),
    };
  }

  if (typeof input.config.url === 'string') {
    const configuredType = input.config.type ?? input.config.transportType;
    const headers = optionalStringRecord(input.config.headers);
    return {
      type:
        configuredType === 'http' || configuredType === 'streamableHttp'
          ? 'streamableHttp'
          : 'sse',
      url: input.config.url,
      ...(headers ? { headers } : {}),
    };
  }

  throw new Error(
    `Cline MCP server ${JSON.stringify(input.serverName)} must define a transport, command, or URL.`,
  );
}

function resolveRegistration(input: {
  serverName: string;
  config: unknown;
}): McpServerRegistration {
  if (!isRecord(input.config)) {
    throw new Error(
      `Cline MCP server ${JSON.stringify(input.serverName)} must be configured with an object value.`,
    );
  }

  return {
    name: input.serverName,
    transport: resolveTransport({
      serverName: input.serverName,

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Add a `command` (with args) for a local stdio MCP server to the server's config
  2. Add a `url` for a remote MCP server (SSE or streamable HTTP)
  3. Or set an explicit `transport` definition in the config
  4. Double-check field spelling/nesting so the existing command/url is actually read by the resolver

Example fix

// before
const registration = {
  serverName: 'my-mcp',
  config: { env: { FOO: 'bar' } } // no transport/command/url
};

// after
const registration = {
  serverName: 'my-mcp',
  config: { command: 'npx', args: ['-y', 'my-mcp-server'], env: { FOO: 'bar' } }
};
Defensive patterns

Strategy: validation

Validate before calling

function assertClineMcpConfig(input) {
  const { config = {} } = input;
  const hasTransport = config.transport != null;
  const hasCommand = typeof config.command === 'string' && config.command.length > 0;
  const hasUrl = typeof config.url === 'string' && config.url.length > 0;
  if (!hasTransport && !hasCommand && !hasUrl) {
    throw new Error(`Cline MCP server ${JSON.stringify(input.serverName)} must define a transport, command, or URL.`);
  }
}

Type guard

interface ClineMcpInput { serverName: string; config?: { transport?: unknown; command?: string; url?: string } }
function hasValidTransport(input: ClineMcpInput): boolean {
  const c = input.config ?? {};
  return c.transport != null || !!c.command || !!c.url;
}

Try / catch

try {
  const registration = resolveRegistration({ serverName, config });
} catch (err) {
  if (err instanceof Error && err.message.includes('must define a transport, command, or URL')) {
    // fix config or skip this server with a clear log message
  }
  throw err;
}

Prevention

When it happens

Trigger: Registering a Cline MCP server whose config object omits all of: a transport spec, a `command` (stdio), and a `url` (remote server) — e.g. an empty or near-empty config object under that server name.

Common situations: Copy-pasting a server entry and deleting the command/url fields; a config file where the actual connection details live under a differently-named key so they are not picked up; partially migrating config formats where `transport` was renamed; typo'd field names (e.g. `cmd` instead of `command`, `endpoint` instead of `url`).

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/d2d143d9e37ecb18. Report an issue: GitHub.