-
Notifications
You must be signed in to change notification settings - Fork 266
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Describe the bug
A clear and concise description of what the bug is.
If an SSE server response does not start with a message event, but a ping event, the streamable client will try to decode the ping data as JSON and fail.
I have observed this on some calls to the DeepWiki MCP server.
To Reproduce
Steps to reproduce the behaviour:
func TestStreamableClientWithDelayedResponse(t *testing.T) {
// This test simulates a server that takes a while to respond and sends a ping before its message
ctx := context.Background()
fake := &fakeStreamableServer{
t: t,
responses: fakeResponses{
{"POST", "", methodInitialize}: {
header: header{
"Content-Type": "application/json",
sessionIDHeader: "123",
},
body: jsonBody(t, initResp),
},
{"POST", "123", notificationInitialized}: {
status: http.StatusAccepted,
wantProtocolVersion: latestProtocolVersion,
},
{"GET", "123", ""}: {
header: header{
"Content-Type": "text/event-stream",
},
wantProtocolVersion: latestProtocolVersion,
},
{"POST", "123", methodCallTool}: {
header: header{
"Content-Type": "text/event-stream",
},
wantProtocolVersion: latestProtocolVersion,
body: `event: ping
data: ping
event: message
data: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"tool result"}]}}
event: ping
data: ping
`,
},
{"DELETE", "123", ""}: {},
},
}
httpServer := httptest.NewServer(fake)
defer httpServer.Close()
transport := &StreamableClientTransport{Endpoint: httpServer.URL}
client := NewClient(testImpl, nil)
session, err := client.Connect(ctx, transport, nil)
if err != nil {
t.Fatalf("client.Connect() failed: %v", err)
}
toolAndArgs := &CallToolParams{Name: "tool", Arguments: map[string]interface{}{}}
result, err := session.CallTool(ctx, toolAndArgs)
if err != nil {
t.Fatalf("client.CallTool() failed: %v", err)
}
expected := "tool result"
if result == nil || len(result.Content) == 0 {
t.Errorf("CallTool result is nil or empty")
}
if result.Content[0].(*TextContent).Text != expected {
t.Errorf("CallTool result: got %q, want %q", result.Content[0].(*TextContent).Text, expected)
}
if err := session.Close(); err != nil {
t.Errorf("closing session: %v", err)
}
}Expected behavior
A clear and concise description of what you expected to happen.
The logic taking apart an event stream should skip ping events and only tro to decode message events.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working