mcp: typed tool handler adds zero structuredContent to an IsError result
Maintainer thường phản hồi trong vòng 1 ngày
Một pull request liên quan đã được merge.
- #1397 của @Ilyuha888 — đã merge
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 74/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- go
- Lĩnh vực
- backend-api-design
Hướng nghiên cứu
Bắt đầu tại mcp/server.go, ở toolForErr, nơi đầu ra có kiểu của handler được chuyển đổi và xác thực; so sánh cách xử lý các yêu cầu đầu vào và kết quả lỗi. Báo cáo có kèm một đoạn mã tái hiện lỗi và cho biết một bài kiểm thử đã chạy thành công với thay đổi được đề xuất. Xác nhận rằng các kết quả IsError bỏ qua nội dung có cấu trúc được tạo ra và bỏ qua bước xác thực đầu ra, trong khi StructuredContent được cung cấp tường minh vẫn khả dụng.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
What did you do?
A typed tool handler reports a tool execution error the way the spec describes: it returns a result with IsError: true and text content, the zero Out, and a nil error. (Returning a Go error avoids the problem below, but then the SDK discards the handler's own result.)
type Out struct {
Items []string `json:"items"`
}
func search(ctx context.Context, _ *mcp.CallToolRequest, in In) (*mcp.CallToolResult, Out, error) {
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: "no shop with this id"}},
}, Out{}, nil
}
What did you see?
The result carries a zero structuredContent next to the error:
{"content":[{"type":"text","text":"no shop with this id"}],"structuredContent":{"items":null},"isError":true}
A client that reads structuredContent first gets {"items":null}, which looks like an empty successful result.
When the output schema rejects the zero value, the call fails with a protocol error instead of returning the tool error. With an OutputSchema whose required status property has "enum": ["ok", "partial"]:
calling "tools/call": validating tool output: validating root: validating /properties/status: enum: does not equal any of: [ok partial]
What did you expect to see?
The error result as the handler built it: no structuredContent and no output validation, as in the spec's tool execution error example. The err != nil path already behaves this way.
Versions
go-sdk v1.8.0; same code on main at 452ac5a. Go 1.27.1, darwin/arm64.
Possible fix
In toolForErr (mcp/server.go), skip the output step for an error result, the same way it is skipped when the handler asks for input:
if asksForInput(res) || res.IsError {
outval = nil
}
A handler that wants structured data on an error result can still set res.StructuredContent itself. I have this change with a test (go test ./... passes) and can send a PR if the approach works for you.
Full reproduction
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/google/jsonschema-go/jsonschema"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
type In struct {
Query string `json:"query"`
}
type Out struct {
Items []string `json:"items"`
}
type Report struct {
Status string `json:"status"`
}
func failing[O any](ctx context.Context, _ *mcp.CallToolRequest, _ In) (*mcp.CallToolResult, O, error) {
var zero O
return &mcp.CallToolResult{
IsError: true,
Content: []mcp.Content{&mcp.TextContent{Text: "no shop with this id"}},
}, zero, nil
}
func main() {
ctx := context.Background()
server := mcp.NewServer(&mcp.Implementation{Name: "repro", Version: "v0"}, nil)
mcp.AddTool(server, &mcp.Tool{Name: "search"}, failing[Out])
mcp.AddTool(server, &mcp.Tool{
Name: "report",
OutputSchema: &jsonschema.Schema{
Type: "object",
Required: []string{"status"},
Properties: map[string]*jsonschema.Schema{"status": {Type: "string", Enum: []any{"ok", "partial"}}},
},
}, failing[Report])
ct, st := mcp.NewInMemoryTransports()
if _, err := server.Connect(ctx, st, nil); err != nil {
panic(err)
}
cs, err := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0"}, nil).Connect(ctx, ct, nil)
if err != nil {
panic(err)
}
defer cs.Close()
for _, name := range []string{"search", "report"} {
res, err := cs.CallTool(ctx, &mcp.CallToolParams{Name: name, Arguments: map[string]any{"query": "x"}})
if err != nil {
fmt.Printf("%s: error: %v\n", name, err)
continue
}
b, _ := json.Marshal(res)
fmt.Printf("%s: %s\n", name, b)
}
}
Output on v1.8.0 (_meta and resultType trimmed from the first line):
search: {"content":[{"type":"text","text":"no shop with this id"}],"structuredContent":{"items":null},"isError":true}
report: error: calling "tools/call": validating tool output: validating root: validating /properties/status: enum: does not equal any of: [ok partial]
- Ngôn ngữ chính
- Go
- Star
- 5.3k
- Fork
- 606
- Merge trung bình
- 1 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 70
Chuẩn bị môi trường
Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của modelcontextprotocol/go-sdk
-
Session-lifecycle bookkeeping logs at info, spamming multiple log lines per request on stateless streamable HTTPCó thể đã có người làm @anneheartrecord đã nhận 62 ngày trước. Đang mởP3
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
modelcontextprotocol/go-sdk#1204 · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Expose generic `SendNotification` on `ServerSession` for custom protocol extensionsCó thể đã có người làm @ajuijas đã nhận 227 ngày trước. Đang mởneeds investigation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
modelcontextprotocol/go-sdk#745 · 13 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
internal/json: Unmarshal allocates a 32 KiB stream buffer on every callCó thể đã có người làm @raveesh-me đã nhận 3 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 25/100
modelcontextprotocol/go-sdk#1453 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
auth/extauth: ClientCredentialsHandler does not send the resource parameterCó thể đã có người làm @shlee1223 đã nhận 3 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 25/100
modelcontextprotocol/go-sdk#1450 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
mcp: LoggingHandler drops records logged at custom slog levelsCó thể đã có người làm @kaankucukx đã nhận 4 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 45/100
modelcontextprotocol/go-sdk#1445 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của modelcontextprotocol/go-sdk
Issue tương tự
-
VLAgent `spec.k8sCollector.includePodLabels: false` has no effectCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
VictoriaMetrics/operator#2772 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Gaurav-Gosain/tuios#1316 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
needs: investigation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
area:auth documentation priority:low
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 86/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Mend: dependency security vulnerability
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
kube-tarian/sigrun#203 ·