{"record":{"id":"a90f4b985e8837d2","repo":"siyuan-note/siyuan","slug":"connect-w","errorCode":null,"errorMessage":"connect: %w","messagePattern":"connect: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/client/mcp.go","lineNumber":487,"sourceCode":"\t}\n\tstdout, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"stdout pipe: %w\", err)\n\t}\n\tcmd.Stderr = io.Discard\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"start command: %w\", err)\n\t}\n\n\tconnectCtx, connectCancel := context.WithTimeout(ctx, serverTimeout(server))\n\tdefer connectCancel()\n\ttransport := &mcp.IOTransport{Reader: stdout, Writer: stdin}\n\tsession, err := client.Connect(connectCtx, transport, nil)\n\tif err != nil {\n\t\tcmd.Process.Kill()\n\t\tcmd.Wait()\n\t\treturn nil, cmd, fmt.Errorf(\"connect: %w\", err)\n\t}\n\n\treturn session, cmd, nil\n}\n\ntype environmentEntry struct {\n\tname  string\n\tvalue string\n}\n\n// buildStdioEnvironment 仅传递用户允许继承的变量，并用显式配置覆盖同名项。\nfunc buildStdioEnvironment(server conf.MCPServer, lookup func(string) (string, bool), resolve func(string) string,\n\tgoos string) ([]string, error) {\n\tif err := validateMCPServerEnvironment(server, goos); err != nil {\n\t\treturn nil, err\n\t}\n\n\tentries := map[string]environmentEntry{}","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/mcp/client/mcp.go#L469-L505","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: server writes banner to stdout, breaking the handshake\nconsole.log(\"starting server...\")\n// after\nconsole.error(\"starting server...\") // stdout is reserved for JSON-RPC","handlingStrategy":"retry","validationCode":"// pre-flight: confirm the child stays alive and stdout is clean\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\nif err := probeStdioHandshake(ctx, server); err != nil {\n    return fmt.Errorf(\"probe handshake for %s: %w\", server.Name, err)\n}","typeGuard":"null","tryCatchPattern":"session, cmd, err := connectStdio(ctx, client, server)\nif err != nil {\n    if strings.Contains(err.Error(), \"connect:\") {\n        if cmd != nil && cmd.Process != nil {\n            cmd.Process.Kill()\n            cmd.Wait()\n        }\n        return fmt.Errorf(\"server %q failed MCP handshake: %w\", server.Name, err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["mcp","stdio","handshake","timeout","protocol"],"backgroundTag":"request-timeout","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}