-
Notifications
You must be signed in to change notification settings - Fork 567
fix(Srv/stream): add ID field to PingRequest
#353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
""" WalkthroughThis change updates the streamable HTTP server by adding a Changes
Assessment against linked issues
Assessment against linked issues: Out-of-scope changesNo out-of-scope changes found. Possibly related PRs
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (1.64.8)Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requestID
will always be 1, because handleGet
will always create a new session
. for the same sessionID, the requestID
should be unique.
From specification: The session ID SHOULD be globally unique ...
therefore, we consider sessions with the same sessionID to be the same session.
message := mcp.JSONRPCRequest{ | ||
JSONRPC: "2.0", | ||
ID: mcp.NewRequestId(session.requestID.Add(1)), | ||
Request: mcp.Request{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requestID
will always be 1, because handleGet
will always create a new session
. for the same sessionID, the requestID
should be unique.
From specification: The session ID SHOULD be globally unique ...
therefore, we consider sessions with the same sessionID to be the same session.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requestID
will always be 1, becausehandleGet
will always create a newsession
. for the same sessionID, therequestID
should be unique.From specification: The session ID SHOULD be globally unique ...
therefore, we consider sessions with the same sessionID to be the same session.
sorry for my mistake, I have updated it to make requestID
unique and monotonically increasing within each session. What do you think of this change ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, thank you for the quick fix on this issue. I have verified that it makes the clients I tested on happy.
However I am not sure this implementation is per the spec. In the spec they state:
If present, the ID MUST be globally unique across all streams within that session—or all streams with that specific client, if session management is not in use.
In the current implementation the ID is unique for ping requests but doesn't account for other requests happening in the session like tool lists or calls, resulting in multiple requests with the same ID happening for a given session.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. The problem is that the ID of the result returned by our handlePost function uses the value of RequestID from the client request. And I think we should change the ID value instead of using RequestID directly.
In other words, these event IDs should be assigned by servers on a per-stream basis, to act as a cursor within that particular stream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. The problem is that the ID of the result returned by our handlePost function uses the value of RequestID from the client request. And I think we should change the ID value instead of using RequestID directly.
In other words, these event IDs should be assigned by servers on a per-stream basis, to act as a cursor within that particular stream.
[difference between mcp-go's writeSSEEvent and typescript-sdk's (link )WriteSSEEvent]
func writeSSEEvent(w io.Writer, data any) error {
jsonData, err := json.Marshal(data)
if err != nil {
return fmt.Errorf("failed to marshal data: %w", err)
}
// only message and data field, no field "event ID", id inside jsonrpcresponse/jsonrpcrequest != event ID
_, err = fmt.Fprintf(w, "event: message\ndata: %s\n\n", jsonData)
if err != nil {
return fmt.Errorf("failed to write SSE event: %w", err)
}
return nil
}
private writeSSEEvent(res: ServerResponse, message: JSONRPCMessage, eventId?: string): boolean {
let eventData = `event: message\n`;
// Include event ID if provided - this is important for resumability<===[event ID]
if (eventId) {
eventData += `id: ${eventId}\n`;
}
eventData += `data: ${JSON.stringify(message)}\n\n`;
return res.write(eventData);
}
Description
Fixes #351
Also encountered, and I also think that adding
ID
field toping
message will result in better compatibility and protocol-compliant designType of Change
Checklist
MCP Spec Compliance
Additional Information
Summary by CodeRabbit