siyuan-note/siyuan · error
connect
Error message
connect: %w
What it means
After successfully starting the stdio child process, connectStdio calls client.Connect with a timeout of serverTimeout(server) to perform the MCP initialize handshake over the stdin/stdout pipes. On failure it kills and waits for the child, then wraps the error with the "connect:" prefix. This means the process started but never completed the MCP protocol handshake.
Solutions
- Run the command manually and confirm it stays alive and speaks MCP on stdout (move any logging to stderr)
- Increase the server's timeout configuration if startup is legitimately slow (e.g. npx cold start)
- Fix Args/Env so the child starts correctly — check that referenced secrets/variables resolve
- Upgrade the server to a compatible MCP protocol version and retry
Example fix
// before: server writes banner to stdout, breaking the handshake
console.log("starting server...")
// after
console.error("starting server...") // stdout is reserved for JSON-RPC Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: confirm the child stays alive and stdout is clean
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := probeStdioHandshake(ctx, server); err != nil {
return fmt.Errorf("probe handshake for %s: %w", server.Name, err)
} Type guard
null
Try / catch
session, cmd, err := connectStdio(ctx, client, server)
if err != nil {
if strings.Contains(err.Error(), "connect:") {
if cmd != nil && cmd.Process != nil {
cmd.Process.Kill()
cmd.Wait()
}
return fmt.Errorf("server %q failed MCP handshake: %w", server.Name, err)
}
return err
} Prevention
- Ensure the server writes only JSON-RPC to stdout; all logs go to stderr
- Configure a timeout comfortably above cold-start time (npx downloads can be slow)
- Keep the MCP SDK/protocol versions of client and server compatible
When it happens
Trigger: connectStdio calls client.Connect(connectCtx, &mcp.IOTransport{Reader: stdout, Writer: stdin}, nil); the child exits immediately, prints non-protocol output on stdout, or does not answer the initialize request before serverTimeout elapses.
Common situations: Wrong command that crashes on startup (bad args, missing env/secrets), slow first start (downloading packages via npx) exceeding the timeout, server writing logs or banners to stdout instead of stderr, or an incompatible MCP protocol version.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/a90f4b985e8837d2.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/mcp/client/mcp.go:487
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, nil, fmt.Errorf("stdout pipe: %w", err)
}
cmd.Stderr = io.Discard
if err := cmd.Start(); err != nil {
return nil, nil, fmt.Errorf("start command: %w", err)
}
connectCtx, connectCancel := context.WithTimeout(ctx, serverTimeout(server))
defer connectCancel()
transport := &mcp.IOTransport{Reader: stdout, Writer: stdin}
session, err := client.Connect(connectCtx, transport, nil)
if err != nil {
cmd.Process.Kill()
cmd.Wait()
return nil, cmd, fmt.Errorf("connect: %w", err)
}
return session, cmd, nil
}
type environmentEntry struct {
name string
value string
}
// buildStdioEnvironment 仅传递用户允许继承的变量,并用显式配置覆盖同名项。
func buildStdioEnvironment(server conf.MCPServer, lookup func(string) (string, bool), resolve func(string) string,
goos string) ([]string, error) {
if err := validateMCPServerEnvironment(server, goos); err != nil {
return nil, err
}
entries := map[string]environmentEntry{}View on GitHub (pinned to 9f775e8a12)