internal/mcp: implement streamable HTTP transport
Add an (almost) complete implementation of the streamable HTTP transport, including: - A StreamableHTTPHandler for serving sessions. - A StreamableHTTPServerTransport that supports session resumption. - A minimal StreamableHTTPClientTransport. Additionally, include the following minor changes: - Refactor SSE event reading to use an iterator. - Start to to aliases for JSON-RPC types (incomplete) - Fix handling for null tool arguments (again) Still to do: - The streamable client does not support retry/resumption, or the side-channel GET requests. - Support configurable session and event retention (garbage collection). - Expose the HTTP client used for HTTP requests (for auth). Change-Id: Ieba216ef901169b4660d601386fa0c7c7bb4c4b2 Reviewed-on: https://go-review.googlesource.com/c/tools/+/667515 Reviewed-by: Jonathan Amsterdam <jba@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
11b17f5858
commit
d2f2f87bbe
1 changed files with 1570 additions and 149 deletions
|
|
@ -34,13 +34,13 @@ type ServerPrompt struct {
|
|||
//
|
||||
// The handler is passed [GetPromptParams] so it can have access to prompt parameters other than name and arguments.
|
||||
// At present, there are no such parameters.
|
||||
func NewPrompt[TReq any](name, description string, handler func(context.Context, *ServerSession, TReq, *GetPromptParams) (*GetPromptResult, error), opts ...PromptOption) *ServerPrompt {
|
||||
schema, err := jsonschema.For[TReq]()
|
||||
func NewPrompt[In any](name, description string, handler func(context.Context, *ServerSession, In, *GetPromptParams) (*GetPromptResult, error), opts ...PromptOption) *ServerPrompt {
|
||||
schema, err := jsonschema.For[In]()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if schema.Type != "object" || !reflect.DeepEqual(schema.AdditionalProperties, &jsonschema.Schema{Not: &jsonschema.Schema{}}) {
|
||||
panic(fmt.Sprintf("handler request type must be a struct"))
|
||||
panic(fmt.Sprintf("invalid input type %q: handler input type must be a struct", schema.Type))
|
||||
}
|
||||
resolved, err := schema.Resolve(nil)
|
||||
if err != nil {
|
||||
|
|
@ -58,7 +58,7 @@ func NewPrompt[TReq any](name, description string, handler func(context.Context,
|
|||
}
|
||||
for name, prop := range util.Sorted(schema.Properties) {
|
||||
if prop.Type != "string" {
|
||||
panic(fmt.Sprintf("handler type must consist only of string fields"))
|
||||
panic(fmt.Sprintf("invalid property type %q: handler type must consist only of string fields", prop.Type))
|
||||
}
|
||||
prompt.Prompt.Arguments = append(prompt.Prompt.Arguments, &PromptArgument{
|
||||
Name: name,
|
||||
|
|
@ -73,7 +73,7 @@ func NewPrompt[TReq any](name, description string, handler func(context.Context,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var v TReq
|
||||
var v In
|
||||
if err := unmarshalSchema(rawArgs, resolved, &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue