mcp: custom methods rejected on a StreamableServerTransport connected with Server.Connect
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 62/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- go
調査の方向性
Start with the POST pre-check in mcp/streamable.go:1695 and compare how connectStreamable sets c.server and toolLookup with the path used by Server.Connect. The report says custom methods fail on directly connected StreamableServerTransport sessions while standard methods succeed; trace that setup and add a regression test based on the supplied reproduction. Done means the custom method reaches its handler and the request returns HTTP 200.
索引モデルが issue の本文から書いたものです。
説明
Checklist
- I searched the existing issues, and this has not been reported before.
- This is a real problem that I ran into myself, using the latest release of the SDK.
- I ran into it in a production system, not in a toy example, a benchmark, or an automated or AI-driven scan of the code.
- I (a human) examined the relevant SDK code, and wrote or reviewed every line of this report. It is not unreviewed AI output.
- This report is brief and concise, and sticks to the facts needed to understand the problem.
What happened?
A method registered with AddReceivingCustomMethod fails with HTTP 400 (JSON RPC not handled: "acme/search" unsupported) on a StreamableServerTransport connected with Server.Connect and served through its ServeHTTP. Standard methods on the same session succeed, and the custom method works through StreamableHTTPHandler.
The POST pre-check falls back to the standard-only serverMethodInfos when c.server is nil (mcp/streamable.go:1695). c.server is set only in connectStreamable (streamable.go:603), which Server.Connect does not call. This is the Streamable HTTP counterpart of #1291 (fixed for SSE in #1292).
Expected: the custom method reaches its handler. A possible fix is for Server.Connect to set the connection's server (and toolLookup, which has the same gap) as connectStreamable does.
We hit this serving the Skills extension (SEP-2640): skills/list, skills/get and resources/directory/read are custom methods, so they fail this way on a resumed session.
How to reproduce
package repro
import (
"context"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
type searchParams struct {
mcp.ParamsBase
Query string `json:"query"`
}
type searchResult struct {
mcp.ResultBase
Hits []string `json:"hits"`
}
func TestCustomMethodOnDirectlyConnectedSession(t *testing.T) {
s := mcp.NewServer(&mcp.Implementation{Name: "s", Version: "1"}, nil)
if err := mcp.AddReceivingCustomMethod(s, "acme/search",
func(context.Context, *mcp.ServerSession, *searchParams) (*searchResult, error) {
return &searchResult{Hits: []string{"hit"}}, nil
}); err != nil {
t.Fatal(err)
}
// Connect a session directly, e.g. to resume one from a shared store.
tr := &mcp.StreamableServerTransport{SessionID: "s1"}
state := &mcp.ServerSessionState{
InitializeParams: &mcp.InitializeParams{ProtocolVersion: "2025-11-25"},
InitializedParams: &mcp.InitializedParams{},
}
ss, err := s.Connect(context.Background(), tr, &mcp.ServerSessionOptions{State: state})
if err != nil {
t.Fatal(err)
}
defer ss.Close()
ts := httptest.NewServer(tr)
defer ts.Close()
req, _ := http.NewRequest(http.MethodPost, ts.URL,
strings.NewReader(`{"jsonrpc":"2.0","id":1,"method":"acme/search","params":{"query":"x"}}`))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json, text/event-stream")
req.Header.Set("Mcp-Session-Id", "s1")
req.Header.Set("Mcp-Protocol-Version", "2025-11-25")
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
t.Fatalf("got HTTP %d: %s", resp.StatusCode, body)
}
}
Output: `got HTTP 400: JSON RPC not handled: "acme/search" unsupported`. The same request with method `tools/list` returns 200, and calling `acme/search` through `NewStreamableHTTPHandler` with `CallCustomMethod` succeeds.
Paste everything between the outer four-backtick fence, including the inner fence, so GitHub renders it as code.
Where did you hit this?
ToolHive's multi-replica Virtual MCP Server, which serves MCP through go-sdk and resumes a session on another replica by connecting a StreamableServerTransport with Server.Connect.
Go MCP SDK version
v1.8.0; also reproduced on main at caa354d.
Go version
go version go1.27.1 darwin/arm64
Logs
acme/search: 400 JSON RPC not handled: "acme/search" unsupported
- 主要言語
- Go
- スター
- 5.3k
- フォーク
- 607
- 平均マージ
- 1日 11時間
- マージ済み PR(30日)
- 82
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
modelcontextprotocol/go-sdk のほかの issue
-
Expose generic `SendNotification` on `ServerSession` for custom protocol extensions再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンneeds investigation
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
modelcontextprotocol/go-sdk#745 · コメント 13 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
mcp: whether MaxLineLength rejects a message depends on how the stream is read対応中かも @Tangerg が今日担当しました。 オープン
modelcontextprotocol/go-sdk#1509 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
mcp: closing a session right after a cancelled call drops notifications/cancelled, so the server handler keeps running対応中かも @vshalpnjabi が今日担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
modelcontextprotocol/go-sdk#1505 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
mcp: a canceled write on IOTransport/StdioTransport cannot leave the write queue対応中かも @Tangerg が 1 日前に担当しました。 オープン
modelcontextprotocol/go-sdk#1498 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
mcp: list_changed can only be broadcast; a server cannot notify one session (2026-07-28 subscriptions/listen)対応中かも @huynle-dev が 4 日前に担当しました。 オープン
難易度 4/5 1〜2日 初心者へのやさしさ 32/100
modelcontextprotocol/go-sdk#1480 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
modelcontextprotocol/go-sdk の issue をすべて見る
似ている issue
-
enhancement needs:sonnet ready-for-agent
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
microsoft/TypeScript#65370 ·
メンテナーはふだん 1 日以内に返信
-
docs: data-ownership invites vendors to build add-ons around the OS対応中かも @brandli が今日担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
gentian-org/gentian-os#894 ·
メンテナーはふだん 1 日以内に返信
-
bug tech debt testing
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
aws/amazon-vpc-cni-k8s#3976 ·
メンテナーはふだん 1 日以内に返信
-
bug raised-by:desk
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
medici-finance/assay#5678 ·
メンテナーはふだん 1 日以内に返信