Skip to content

--mcp-stdio blocks initialize response until all schema introspection completes, causing MCP reconnect timeouts #3430

@sdasari-mdvip

Description

@sdasari-mdvip

Summary

When DAB starts in --mcp-stdio mode, it does not send the MCP initialize response until it has finished introspecting the schema for every registered entity. Against a remote Azure SQL Managed Instance (~160 ms round-trip per query × 2 queries per entity × 53 entities), this results in a ~17-second startup delay before any MCP message is emitted on stdout.

This works fine on the initial connection because MCP clients wait indefinitely for first contact. However, on reconnect, clients typically apply a shorter timeout. Any client whose reconnect timeout is less than the schema-introspection time fails with a connection error, even though the DAB process is healthy and the database is reachable.

Environment

  • DAB version: Microsoft.DataApiBuilder 1.7.92
  • Database: Azure SQL Managed Instance (remote, ~160 ms RTT)
  • Entities registered: 53
  • MCP client: Claude Code (desktop app)
  • OS: Windows 11

Steps to Reproduce

  1. Register 50+ entities backed by a remote Azure SQL MI (≥ 100 ms RTT).
  2. Run dab start --config dab-config.json --mcp-stdio.
  3. Connect an MCP client (e.g. Claude Code). First connection succeeds after ~17 s.
  4. Trigger a client reconnect (e.g. /mcp command in Claude Code). Reconnect fails — "Failed to reconnect" — because the client's reconnect timeout (< 17 s) expires before DAB emits the initialize response.

Observed Behavior

DAB performs the full schema introspection synchronously before responding to the MCP initialize request:

t=0s    Claude Code sends initialize
t=0s    DAB starts schema introspection (53 entities × 2 queries × ~160ms = ~17s)
t=17s   DAB sends initialize response  ← too late for reconnect timeout
t=17s   Claude Code has already given up; closes stdin

Wrapper log evidence:

[01:49:16.922Z] wrapper invoked
[01:49:16.922Z] client protocolVersion: 2025-11-25   ← initialize received immediately
[01:49:34.383Z] forwarding initialize response        ← 17s later
[01:49:34.390Z] stdin EOF                             ← client already closed connection

Expected Behavior

DAB should send the MCP initialize response immediately upon receiving the client's initialize request, then complete schema introspection in the background. The tools/list response can be delayed until introspection is done — the client will wait because the connection is already established.

Proposed flow:

t=0s    Claude Code sends initialize
t=0s    DAB sends initialize response immediately  ← handshake complete
t=0s    DAB starts schema introspection in background
t=17s   DAB sends tools/list response (client has been waiting, connection alive)

Workaround

Wrap the dab process in a Node.js stdio proxy that:

  1. Intercepts the client's initialize request and replies immediately with a minimal valid response.
  2. Discards DAB's own initialize response when it eventually arrives.
  3. Passes all subsequent traffic (tools/list, tools/call, etc.) through normally.

This workaround is required to make reconnects usable against remote databases with non-trivial schema introspection times.

Impact

  • Any MCP client with a reconnect timeout shorter than the schema-introspection time cannot use reconnect commands — only a full client restart works.
  • Severity increases with entity count and database RTT. On a local SQL Server instance this is unlikely to manifest; on a remote managed instance with 50+ entities it is reliably reproducible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions