mcp: reject requests with bad IDs (#202)

Add an isRequest field to methodInfo, used it to reject non-notification
requests that lack a valid ID. Furthermore, lift this validation to the
transport layer for HTTP server transports, so that we can preemptively
reject bad HTTP requests.

Fixes #194
Fixes #197
This commit is contained in:
Robert Findley 2025-07-30 12:26:40 -04:00 • committed by GitHub
commit 64493be392
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -688,22 +688,22 @@ func (s *Server) AddReceivingMiddleware(middleware ...Middleware[*ServerSession]
// serverMethodInfos maps from the RPC method name to serverMethodInfos.
var serverMethodInfos = map[string]methodInfo{
methodComplete: newMethodInfo(serverMethod((*Server).complete)),
methodInitialize: newMethodInfo(sessionMethod((*ServerSession).initialize)),
methodPing: newMethodInfo(sessionMethod((*ServerSession).ping)),
methodListPrompts: newMethodInfo(serverMethod((*Server).listPrompts)),
methodGetPrompt: newMethodInfo(serverMethod((*Server).getPrompt)),
methodListTools: newMethodInfo(serverMethod((*Server).listTools)),
methodCallTool: newMethodInfo(serverMethod((*Server).callTool)),
methodListResources: newMethodInfo(serverMethod((*Server).listResources)),
methodListResourceTemplates: newMethodInfo(serverMethod((*Server).listResourceTemplates)),
methodReadResource: newMethodInfo(serverMethod((*Server).readResource)),
methodSetLevel: newMethodInfo(sessionMethod((*ServerSession).setLevel)),
methodSubscribe: newMethodInfo(serverMethod((*Server).subscribe)),
methodUnsubscribe: newMethodInfo(serverMethod((*Server).unsubscribe)),
notificationInitialized: newMethodInfo(serverMethod((*Server).callInitializedHandler)),
notificationRootsListChanged: newMethodInfo(serverMethod((*Server).callRootsListChangedHandler)),
notificationProgress: newMethodInfo(sessionMethod((*ServerSession).callProgressNotificationHandler)),
methodComplete: newMethodInfo(serverMethod((*Server).complete), true),
methodInitialize: newMethodInfo(sessionMethod((*ServerSession).initialize), true),
methodPing: newMethodInfo(sessionMethod((*ServerSession).ping), true),
methodListPrompts: newMethodInfo(serverMethod((*Server).listPrompts), true),
methodGetPrompt: newMethodInfo(serverMethod((*Server).getPrompt), true),
methodListTools: newMethodInfo(serverMethod((*Server).listTools), true),
methodCallTool: newMethodInfo(serverMethod((*Server).callTool), true),
methodListResources: newMethodInfo(serverMethod((*Server).listResources), true),
methodListResourceTemplates: newMethodInfo(serverMethod((*Server).listResourceTemplates), true),
methodReadResource: newMethodInfo(serverMethod((*Server).readResource), true),
methodSetLevel: newMethodInfo(sessionMethod((*ServerSession).setLevel), true),
methodSubscribe: newMethodInfo(serverMethod((*Server).subscribe), true),
methodUnsubscribe: newMethodInfo(serverMethod((*Server).unsubscribe), true),
notificationInitialized: newMethodInfo(serverMethod((*Server).callInitializedHandler), false),
notificationRootsListChanged: newMethodInfo(serverMethod((*Server).callRootsListChangedHandler), false),
notificationProgress: newMethodInfo(sessionMethod((*ServerSession).callProgressNotificationHandler), false),
}
func (ss *ServerSession) sendingMethodInfos() map[string]methodInfo { return clientMethodInfos }