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

  1. Run the command manually and confirm it stays alive and speaks MCP on stdout (move any logging to stderr)
  2. Increase the server's timeout configuration if startup is legitimately slow (e.g. npx cold start)
  3. Fix Args/Env so the child starts correctly — check that referenced secrets/variables resolve
  4. 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

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)