Title: [FEATURE] MCP stdio server exits silently when JSON-RPC messages are CRLF-terminated · Issue #668 · stackql/stackql · GitHub
Open Graph Title: [FEATURE] MCP stdio server exits silently when JSON-RPC messages are CRLF-terminated · Issue #668 · stackql/stackql
X Title: [FEATURE] MCP stdio server exits silently when JSON-RPC messages are CRLF-terminated · Issue #668 · stackql/stackql
Description: Summary stackql mcp --mcp.server.type=stdio exits immediately with code 0 and no error output if an incoming JSON-RPC line is terminated with \r\n instead of \n. The stray \r at the end of the line appears to kill the server's message lo...
Open Graph Description: Summary stackql mcp --mcp.server.type=stdio exits immediately with code 0 and no error output if an incoming JSON-RPC line is terminated with \r\n instead of \n. The stray \r at the end of the line...
X Description: Summary stackql mcp --mcp.server.type=stdio exits immediately with code 0 and no error output if an incoming JSON-RPC line is terminated with \r\n instead of \n. The stray \r at the end of the line...
Opengraph URL: https://github.com/stackql/stackql/issues/668
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[FEATURE] MCP stdio server exits silently when JSON-RPC messages are CRLF-terminated","articleBody":"## Summary\n\n`stackql mcp --mcp.server.type=stdio` exits immediately with code 0 and no error output if an incoming JSON-RPC line is terminated with `\\r\\n` instead of `\\n`. The stray `\\r` at the end of the line appears to kill the server's message loop. Nothing is written to stdout, stderr, or the sink log, so from the client's side the server just dies with a clean exit code, which makes this very hard to diagnose.\n\n## Environment\n\n- stackql version: 0.10.500\n- OS: Windows 11 (also reproducible anywhere by sending CRLF line endings)\n- Invocation: `stackql mcp --mcp.server.type=stdio --auth='{\"github\":{\"type\":\"null_auth\"}}'`\n\n## Steps to reproduce\n\nLF-terminated message - works (server responds to `initialize`):\n\n~~~bash\n{ printf '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"repro\",\"version\":\"1\"}},\"id\":1}\\n'; sleep 8; } \\\n | stackql mcp --mcp.server.type=stdio --auth='{\"github\":{\"type\":\"null_auth\"}}'\n~~~\n\nCRLF-terminated message - server exits with code 0, no response, no error:\n\n~~~bash\n{ printf '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"repro\",\"version\":\"1\"}},\"id\":1}\\r\\n'; sleep 8; } \\\n | stackql mcp --mcp.server.type=stdio --auth='{\"github\":{\"type\":\"null_auth\"}}'\n~~~\n\nEquivalent Python repro (this is how it was found - `subprocess.Popen(..., text=True)` on Windows translates `\\n` to `\\r\\n` on the child's stdin):\n\n~~~python\nimport json, subprocess, time\n\ncmd = [\"stackql\", \"mcp\", \"--mcp.server.type=stdio\",\n '--auth={\"github\":{\"type\":\"null_auth\"}}']\n\n# text=True on Windows writes \\r\\n to the child's stdin\nproc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,\n stderr=subprocess.PIPE, text=True)\nmsg = {\"jsonrpc\": \"2.0\", \"method\": \"initialize\",\n \"params\": {\"protocolVersion\": \"2024-11-05\", \"capabilities\": {},\n \"clientInfo\": {\"name\": \"repro\", \"version\": \"1\"}}, \"id\": 1}\nproc.stdin.write(json.dumps(msg) + \"\\n\")\nproc.stdin.flush()\ntime.sleep(10)\nprint(\"returncode:\", proc.poll()) # 0 - exited, no response ever written\n~~~\n\nSwitching the same script to binary pipes (no newline translation) makes the handshake succeed.\n\n## Expected behaviour\n\nEither of:\n\n1. Tolerate CRLF: strip a trailing `\\r` from each line before JSON parsing. The MCP spec's stdio transport delimits messages with newlines, and CRLF-emitting clients exist in practice (anything spawning the server through a text-mode pipe on Windows).\n2. At minimum, fail loudly: log a parse error to stderr and/or the sink log, and exit non-zero, instead of exiting 0 in silence.\n\n## Actual behaviour\n\nThe process exits with code 0. Nothing is written to stdout. The sink log file is created but empty. The only stderr output is the usual `sink file: \u003cpath\u003e` line.\n\n## Impact\n\nAny MCP client (or test harness) that ends up writing CRLF-terminated lines on Windows sees the server \"start and immediately die\" with a success exit code and zero diagnostics. This cost real debugging time while smoke testing the Windows `.mcpb` bundle.\n\n","author":{"url":"https://github.com/jeffreyaven","@type":"Person","name":"jeffreyaven"},"datePublished":"2026-06-12T04:09:45.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/668/stackql/issues/668"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:b6c7f2e0-b40c-363a-fa5f-d89880c68626 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D806:53D51:12C8F95:1ACE74E:6A4CBED9 |
| html-safe-nonce | 5691d07ab9e0c0effd214d0bba54ee041592d45da43887db239076b8d76c23c2 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEODA2OjUzRDUxOjEyQzhGOTU6MUFDRTc0RTo2QTRDQkVEOSIsInZpc2l0b3JfaWQiOiI0NTMyODIxNzU3NzA3MjA2MzYxIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 6728067043ec2ae22394c1d85f7507a5afefb93bbea21fa76f683d0a0ec8eac2 |
| hovercard-subject-tag | issue:4646189533 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/stackql/stackql/668/issue_layout |
| twitter:image | https://opengraph.githubassets.com/e798dc7fff78dd7e9f4ce23ac20f31533858ea602a96cba58e8b2edd66ae4b02/stackql/stackql/issues/668 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/e798dc7fff78dd7e9f4ce23ac20f31533858ea602a96cba58e8b2edd66ae4b02/stackql/stackql/issues/668 |
| og:image:alt | Summary stackql mcp --mcp.server.type=stdio exits immediately with code 0 and no error output if an incoming JSON-RPC line is terminated with \r\n instead of \n. The stray \r at the end of the line... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | jeffreyaven |
| hostname | github.com |
| expected-hostname | github.com |
| None | 3d11bb817438277de2a940854450e83a7d32b6aeb5014e9e6b00a6423900251c |
| turbo-cache-control | no-preview |
| go-import | github.com/stackql/stackql git https://github.com/stackql/stackql.git |
| octolytics-dimension-user_id | 95105302 |
| octolytics-dimension-user_login | stackql |
| octolytics-dimension-repository_id | 443987542 |
| octolytics-dimension-repository_nwo | stackql/stackql |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 443987542 |
| octolytics-dimension-repository_network_root_nwo | stackql/stackql |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | c03e7e569190bc89b638cdd4acb4b6c6b38a170a |
| ui-target | canary-1 |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width