mcp: relax SSE connection response handling in non-strict mode (#611)
Some MCP servers do not support SSE, but when receiving a request, they return 400 Bad Request or 404 Not Found instead of the standard 405 Method Not Allowed. The TypeScript and Python SDK ignore this error, while the Go SDK terminates the session. This patch addresses the issue in the non-strict mode. Fixes #610 --------- Signed-off-by: Xie Zhihao <zhihao.xie@bytedance.com>
This commit is contained in:
parent
32d84d8421
commit
d297272705
2 changed files with 15 additions and 6 deletions
|
|
@ -1377,13 +1377,14 @@ func (c *streamableClientConn) connectStandaloneSSE() {
|
|||
resp.Body.Close()
|
||||
return
|
||||
}
|
||||
if resp.StatusCode == http.StatusNotFound && !c.strict {
|
||||
// modelcontextprotocol/gosdk#393: some servers return NotFound instead
|
||||
// of MethodNotAllowed for the standalone SSE stream.
|
||||
if resp.StatusCode >= 400 && resp.StatusCode < 500 && !c.strict {
|
||||
// modelcontextprotocol/go-sdk#393,#610: some servers return NotFound or
|
||||
// other status codes instead of MethodNotAllowed for the standalone SSE
|
||||
// stream.
|
||||
//
|
||||
// Treat this like MethodNotAllowed in non-strict mode.
|
||||
if c.logger != nil {
|
||||
c.logger.Warn("got 404 instead of 405 for standalone SSE stream")
|
||||
c.logger.Warn(fmt.Sprintf("got %d instead of 405 for standalone SSE stream", resp.StatusCode))
|
||||
}
|
||||
resp.Body.Close()
|
||||
return
|
||||
|
|
|
|||
|
|
@ -239,7 +239,11 @@ func TestStreamableClientGETHandling(t *testing.T) {
|
|||
}{
|
||||
{http.StatusOK, ""},
|
||||
{http.StatusMethodNotAllowed, ""},
|
||||
{http.StatusBadRequest, "standalone SSE"},
|
||||
// The client error status code is not treated as an error in non-strict
|
||||
// mode.
|
||||
{http.StatusNotFound, ""},
|
||||
{http.StatusBadRequest, ""},
|
||||
{http.StatusInternalServerError, "standalone SSE"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
@ -305,7 +309,11 @@ func TestStreamableClientStrictness(t *testing.T) {
|
|||
{"strict initialized", true, http.StatusOK, http.StatusMethodNotAllowed, true},
|
||||
{"unstrict initialized", false, http.StatusOK, http.StatusMethodNotAllowed, false},
|
||||
{"strict GET", true, http.StatusAccepted, http.StatusNotFound, true},
|
||||
{"unstrict GET", false, http.StatusOK, http.StatusNotFound, false},
|
||||
// The client error status code is not treated as an error in non-strict
|
||||
// mode.
|
||||
{"unstrict GET on StatusNotFound", false, http.StatusOK, http.StatusNotFound, false},
|
||||
{"unstrict GET on StatusBadRequest", false, http.StatusOK, http.StatusBadRequest, false},
|
||||
{"GET on InternlServerError", false, http.StatusOK, http.StatusInternalServerError, true},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.label, func(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue