Skip to content

Commit 7c38b56

Browse files
authored
Merge pull request #492 from pottekkat/fix/nil-pointer-dereference
2 parents baa7153 + 800e529 commit 7c38b56

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

client/transport/streamable_http.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,13 @@ func (c *StreamableHTTP) SendRequest(
252252
return nil, fmt.Errorf("failed to send request: %w", err)
253253
}
254254
}
255+
256+
// Only proceed if we have a valid response.
257+
// When sendHTTP fails and resp is nil but method is mcp.MethodInitialize
258+
// defer resp.Body.Close() fails with nil pointer dereference.
259+
if resp == nil {
260+
return nil, fmt.Errorf("failed to send request: %w", err)
261+
}
255262
defer resp.Body.Close()
256263

257264
// Check if we got an error response

server/sse_test.go

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,10 +1446,14 @@ func TestSSEServer(t *testing.T) {
14461446

14471447
t.Run("Headers are passed through to tool requests", func(t *testing.T) {
14481448
hooks := &Hooks{}
1449-
var headerVerified bool
1449+
headerVerified := make(chan struct{})
14501450
hooks.AddAfterCallTool(func(ctx context.Context, id any, message *mcp.CallToolRequest, result *mcp.CallToolResult) {
14511451
if message.Params.Name == "verify-headers" {
1452-
headerVerified = true
1452+
select {
1453+
case <-headerVerified:
1454+
default:
1455+
close(headerVerified)
1456+
}
14531457
}
14541458
})
14551459

@@ -1506,20 +1510,24 @@ func TestSSEServer(t *testing.T) {
15061510
t.Errorf("Expected status 202, got %d", resp.StatusCode)
15071511
}
15081512

1509-
// Wait briefly for hook to be called
1510-
time.Sleep(100 * time.Millisecond)
1511-
1512-
if !headerVerified {
1513-
t.Error("Header verification hook was not called")
1513+
// Wait for hook to be called
1514+
select {
1515+
case <-headerVerified:
1516+
case <-time.After(1 * time.Second):
1517+
t.Error("Header verification hook was not called within timeout")
15141518
}
15151519
})
15161520

15171521
t.Run("Headers are not nil when no headers are set", func(t *testing.T) {
15181522
hooks := &Hooks{}
1519-
var headersChecked bool
1523+
headersChecked := make(chan struct{})
15201524
hooks.AddAfterCallTool(func(ctx context.Context, id any, message *mcp.CallToolRequest, result *mcp.CallToolResult) {
15211525
if message.Params.Name == "check-headers-not-nil" {
1522-
headersChecked = true
1526+
select {
1527+
case <-headersChecked:
1528+
default:
1529+
close(headersChecked)
1530+
}
15231531
}
15241532
})
15251533

@@ -1591,11 +1599,11 @@ func TestSSEServer(t *testing.T) {
15911599
t.Errorf("Expected status 202, got %d", resp.StatusCode)
15921600
}
15931601

1594-
// Wait briefly for hook to be called
1595-
time.Sleep(100 * time.Millisecond)
1596-
1597-
if !headersChecked {
1598-
t.Error("Headers check hook was not called")
1602+
// Wait for hook to be called
1603+
select {
1604+
case <-headersChecked:
1605+
case <-time.After(1 * time.Second):
1606+
t.Error("Headers check hook was not called within timeout")
15991607
}
16001608
})
16011609
}

0 commit comments

Comments
 (0)