vercel/ai · error

ACP MCP server ${JSON.stringify(name)} must be configured wi

Error message

ACP MCP server ${JSON.stringify(name)} must be configured with an object value.

What it means

createExternalMcpServers maps the user-supplied mcpServers record into ACP McpServer configurations and requires each entry's value to be an object (isRecord check). Non-object values (strings, numbers, booleans, arrays) are rejected with this Error because the ACP protocol needs a structured server config. This validates user configuration before it is sent to the agent.

Source

Thrown at packages/harness-acp/src/v1/bridge/index.ts:640

  initializationDiagnostic = createACPInitializationDiagnostic({
    initialization,
    sessionId: createdSession.sessionId,
  });
  sessionConfigurationFingerprint = fingerprint;
  return { initialHostToolCatalogRefreshRequired: tools.length > 0 };
}

function createExternalMcpServers({
  mcpServers,
  initialization,
}: {
  mcpServers: Record<string, unknown> | undefined;
  initialization: acp.InitializeResponse;
}): acp.McpServer[] {
  if (mcpServers == null) return [];
  return Object.entries(mcpServers).map(([name, value]) => {
    if (!isRecord(value)) {
      throw new Error(
        `ACP MCP server ${JSON.stringify(name)} must be configured with an object value.`,
      );
    }
    if (value.type === 'acp') {
      throw new HarnessBridgeCapabilityUnsupportedError({
        harnessId: bridgeType,
        message:
          'ACP-transport MCP servers require client-side mcp/connect handling, which this harness does not provide.',
      });
    }
    const mcpCapabilities = initialization.agentCapabilities?.mcpCapabilities;
    if (
      (value.type === 'http' && mcpCapabilities?.http !== true) ||
      (value.type === 'sse' && mcpCapabilities?.sse !== true)
    ) {
      throw new HarnessBridgeCapabilityUnsupportedError({
        harnessId: bridgeType,
        message: `The ACP agent does not advertise support for ${value.type.toUpperCase()} MCP servers.`,

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Wrap each MCP server entry in an object with the expected fields (e.g. { type: 'http', url } or { type: 'stdio', command, args }).
  2. Validate the mcpServers record shape before creating the bridge (each value an object).
  3. Compare against the harness-acp docs/examples for the exact McpServer config schema supported by your agent.

Example fix

// before
mcpServers: { context7: 'https://mcp.example.com/mcp' }
// after
mcpServers: {
  context7: { type: 'http', url: 'https://mcp.example.com/mcp' },
}
Defensive patterns

Strategy: validation

Validate before calling

function isMcpServerConfig(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}
for (const [name, value] of Object.entries(mcpServers ?? {})) {
  if (!isMcpServerConfig(value)) {
    throw new Error(`MCP server '${name}' must be an object config`);
  }
}

Type guard

function isRecord(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try {
  await createBridge({ mcpServers });
} catch (error) {
  if (error instanceof Error && error.message.includes('must be configured with an object value')) {
    // fix the mcpServers entry shape before retrying
  }
  throw error;
}

Prevention

When it happens

Trigger: Passing mcpServers where any key's value is not a plain object — e.g. mcpServers: { context7: 'https://mcp.example.com' } or { fs: ['npx', '-y', 'fs-mcp'] } — during bridge/session creation.

Common situations: Copying CLI-style MCP config (command arrays or URL strings) from another tool (e.g. a claude-style JSON) into the harness mcpServers option without wrapping it in the expected object shape; typos that flatten the object; template expansion producing a scalar.

Related errors


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