modelcontextprotocol / modelcontextprotocol/go-sdk
MCP go-sdk implementation Gap-2: SDK does not enforce MCP spec "MUST NOT" rule for stdio transport stdout writes
@guglielmo-san is already working on this.
Since Apr 14, 2026.
- Dominant language
- Go
- Stars
- 5.1k
- Forks
- 543
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 37
Description
Describe the bug
The MCP Go SDK does not enforce the MCP specification requirement that "In the stdio transport, the server MUST NOT write anything to its stdout that is not a valid MCP message." Applications using the SDK can easily bypass the transport layer and write arbitrary content directly to os.Stdout, violating the MCP protocol.
To Reproduce
Current stdio transport Implementation (How it fails to ensure compliance)
1. Transport Layer Implementation:
// mcp/transport.go:92-94
func (*StdioTransport) Connect(context.Context) (Connection, error) {
return newIOConn(rwc{os.Stdin, os.Stdout}), nil
}
2. rwc Wrapper:
// mcp/transport.go:273-288
type rwc struct {
rc io.ReadCloser
wc io.WriteCloser
}
func (r rwc) Write(p []byte) (n int, err error) {
return r.wc.Write(p) // Direct passthrough to os.Stdout
}
3. ioConn Write Method:
// mcp/transport.go:541-590
func (t *ioConn) Write(ctx context.Context, msg jsonrpc.Message) error {
data, err := jsonrpc2.EncodeMessage(msg) // Only validates JSON-RPC format
if err != nil {
return err
}
data = append(data, '\n')
_, err = t.rwc.Write(data) // Writes to wrapped stdout
return err
}
Expected behavior
From MCP Spec (stdio transport):
"The server MUST NOT write anything to its
stdoutthat is not a valid MCP message."
Key Points:
- This is a MUST NOT requirement (mandatory compliance)
- Applies specifically to stdout writes
- Requires prevention of non-MCP content, not just correctness validation
How MCP Server Can Violate the Rule:
1. In the MCP Server, direct os.Stdout Access:
// This bypasses the SDK entirely
fmt.Fprintf(os.Stdout, "DEBUG: Server started\n")
os.Stdout.WriteString("Hello World!\n")
fmt.Print("Another violation!\n")
2. No Prevention Mechanisms:
os.Stdoutremains globally accessible- No wrapper or interceptor around stdout
- No runtime validation of stdout content
- No warnings or errors when non-MCP content is written
Logs
If applicable, add logs to help explain your problem.
Additional context
Possible Fix
Option 1: Wrapper-Based Prevention (Recommended)
type mcpStdout struct {
original *os.File
validator func([]byte) error
}
func (m *mcpStdout) Write(p []byte) (n int, err error) {
if err := m.validator(p); err != nil {
return 0, fmt.Errorf("MCP compliance violation: %w", err)
}
return m.original.Write(p)
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.