{"record":{"id":"a90f4b985e8837d2","repo":"siyuan-note/siyuan","slug":"connect-w","errorCode":null,"errorMessage":"connect: %w","messagePattern":"connect: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/client/mcp.go","lineNumber":485,"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":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/mcp/client/mcp.go#L467-L503","documentation":"Returned when the MCP handshake (client.Connect over the stdio IOTransport) fails after the child process was successfully started. The child is killed and waited on before returning, so no zombie is left. The wrapped error is the MCP SDK's connect/initialize error.","triggerScenarios":"connectStdio reaches client.Connect within serverTimeout; the child process starts but does not complete the MCP initialize handshake in time, or speaks a non-MCP protocol on stdout, or crashes immediately, or closes stdout. The code then calls cmd.Process.Kill() and cmd.Wait().","commonSituations":"The configured command is not actually an MCP server (e.g. a plain CLI that prints a banner then waits); the server needs additional arguments/env it did not get; the server hangs on startup waiting on a TTY or network; serverTimeout is too short for a slow-starting server (e.g. npx downloading a package); protocol-version mismatch between client and server.","solutions":["Run the same command with the same args/env manually in a terminal and confirm it prints a valid MCP initialize response on stdout, not a usage banner or interactive prompt.","Increase server.Timeout (parsed by serverTimeout) if the server legitimately needs longer to start (cold npx/npm/pip installs).","Check the MCP client and server speak a compatible protocol version; update the server or pin a compatible version.","If the server writes diagnostics to stderr, note that cmd.Stderr = io.Discard — temporarily route stderr to a file in a local build to capture the server's startup error.","Because the child is killed on this path, no manual cleanup is needed; just fix the config/restart and retry."],"exampleFix":"// before\nserver.Command = \"my-cli\"\nserver.Args = []string{\"serve\"}\nserver.Timeout = 5  // seconds, too short for cold start\n// after\nserver.Command = \"my-cli\"\nserver.Args = []string{\"serve\"}\nserver.Timeout = 60","handlingStrategy":"validation","validationCode":"// Smoke-test that the command speaks MCP before relying on it.\n// Run: <command> <args...> and confirm a JSON-RPC initialize response on stdout.\n// Pseudocode used in a config validator:\nfunc dryRunInitialize(server conf.MCPServer) error {\n    // send {\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\", ...} on stdin\n    // expect a JSON-RPC response within server.Timeout\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// After connect failure, child is already killed; surface wrapped SDK error.\n// Look for context.DeadlineExceeded to recommend raising server.Timeout.\nif errors.Is(err, context.DeadlineExceeded) {\n    // suggest increasing server.Timeout\n}","preventionTips":["Use a generous server.Timeout for cold-starting runtimes (npx, uvx).","Confirm the configured command is genuinely an MCP server.","Capture stderr locally when debugging (the production code discards it)."],"tags":["mcp","stdio","handshake","timeout","protocol"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}