Describe the bug
mcp-server-git pass raise_exceptions=True; mcp-server-time and mcp-server-sqlite use the default. With set flag, the SDK turns an exception from stdin_reader into a process exit; without it, the same exception is sent back to the client as a JSON-RPC error and the server keeps running.
I'm not filing this as a CVE-class issue - the README is clear these are reference implementations, not production code. But the divergence itself is worth straightening out.
To Reproduce
The way to trigger (and how i found it) this is a JSON-RPC request with params.arguments nested ~200 levels deep -pydantic-core hits its built-in recursion limit and JSONRPCMessage.model_validate_json() raises ValidationError: recursion limit exceeded. stdin_reader catches that exception correctly and sends it down the stream; the receiver re-raises it because raise_exceptions=True was set, the task group tears down, and the process exits with code 1.
- Run python repro.py.
- Assertions pass — server exited with code 1 and the stderr contains the recursion-limit ValidationError.
import json, subprocess, tempfile, pathlib
repo = pathlib.Path(tempfile.mkdtemp())
subprocess.run(["git", "init", str(repo)], check=True, capture_output=True)
inner = {"leaf": True}
for _ in range(200):
inner = {"child": inner}
msgs = [
{"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": {"protocolVersion": "2025-03-26", "capabilities": {},
"clientInfo": {"name": "repro", "version": "0.1"}}},
{"jsonrpc": "2.0", "method": "notifications/initialized"},
{"jsonrpc": "2.0", "id": 1001, "method": "tools/call",
"params": {"name": "git_add", "arguments": inner}},
]
payload = ("\n".join(json.dumps(m) for m in msgs) + "\n").encode()
proc = subprocess.Popen(
["uvx", "--from", "mcp-server-git==2026.1.14",
"mcp-server-git", "-r", str(repo)],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate(payload, timeout=15)
assert proc.returncode == 1, f"expected crash, got rc={proc.returncode}"
assert b"ValidationError" in err and b"recursion limit exceeded" in err
print("Confirmed: mcp-server-git exited with code 1 on nested JSON-RPC")
Expected behavior
Same as mcp-server-time and mcp-server-sqlite: an unparseable JSON-RPC request should yield a JSON-RPC error response, not crash the server.
Logs
Traceback (most recent call last):
File ".../mcp/server/lowlevel/server.py", line 714, in _handle_message
raise message
File ".../mcp/server/stdio.py", line 65, in stdin_reader
message = types.JSONRPCMessage.model_validate_json(line)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../pydantic/main.py", line 782, in model_validate_json
return cls.__pydantic_validator__.validate_json(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 1 validation error for JSONRPCMessage
Invalid JSON: recursion limit exceeded at line 1 column 2089
[type=json_invalid, input_value='{"jsonrpc": "2.0", "id":...}}}}}}}}}}}}}}}}}}}}}\n', input_type=str]
For further information visit https://errors.pydantic.dev/2.13/v/json_invalid
ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
Additional context
I noticed that a very similar issue was previously fixed for mcp-server-fetch in PR #3515. Thanks to @anshul-garg27 for that fix — this looks like the same kind of follow-up cleanup for mcp-server-git.
Describe the bug
mcp-server-git pass raise_exceptions=True; mcp-server-time and mcp-server-sqlite use the default. With set flag, the SDK turns an exception from stdin_reader into a process exit; without it, the same exception is sent back to the client as a JSON-RPC error and the server keeps running.
I'm not filing this as a CVE-class issue - the README is clear these are reference implementations, not production code. But the divergence itself is worth straightening out.
To Reproduce
The way to trigger (and how i found it) this is a JSON-RPC request with params.arguments nested ~200 levels deep -pydantic-core hits its built-in recursion limit and JSONRPCMessage.model_validate_json() raises ValidationError: recursion limit exceeded. stdin_reader catches that exception correctly and sends it down the stream; the receiver re-raises it because raise_exceptions=True was set, the task group tears down, and the process exits with code 1.
Expected behavior
Same as mcp-server-time and mcp-server-sqlite: an unparseable JSON-RPC request should yield a JSON-RPC error response, not crash the server.
Logs
Additional context
I noticed that a very similar issue was previously fixed for mcp-server-fetch in PR #3515. Thanks to @anshul-garg27 for that fix — this looks like the same kind of follow-up cleanup for mcp-server-git.