diff --git a/mcp/protocol/generate.go b/mcp/protocol/generate.go index 60b0f0a..e082502 100644 --- a/mcp/protocol/generate.go +++ b/mcp/protocol/generate.go @@ -22,11 +22,12 @@ import ( "net/http" "os" "reflect" + "regexp" "slices" "strings" - "github.com/modelcontextprotocol/go-sdk/internal/jsonschema" "github.com/modelcontextprotocol/go-sdk/internal/util" + "github.com/modelcontextprotocol/go-sdk/jsonschema" ) var schemaFile = flag.String("schema_file", "", "if set, use this file as the persistent schema file") @@ -138,7 +139,7 @@ package protocol import ( "encoding/json" - "github.com/modelcontextprotocol/go-sdk/internal/jsonschema" + "github.com/modelcontextprotocol/go-sdk/jsonschema" ) `) @@ -381,11 +382,44 @@ func canHaveAdditionalProperties(s *jsonschema.Schema) bool { // exportName returns an exported name for a Go symbol, based on the given name // in the JSON schema, removing leading underscores and capitalizing. +// It also rewrites initialisms. func exportName(s string) string { if strings.HasPrefix(s, "_") { s = s[1:] } - return strings.ToUpper(s[:1]) + s[1:] + s = strings.ToUpper(s[:1]) + s[1:] + // Replace an initialism if it is its own "word": see the init function below for + // a definition. + // There is probably a clever way to write this whole thing with one regexp and + // a Replace method, but it would be quite obscure. + // This doesn't have to be fast, because the first match will rarely succeed. + for ism, re := range initialisms { + replacement := strings.ToUpper(ism) + // Find the index of one match at a time, and replace. (We can't find all + // at once, because the replacement will change the indices.) + for { + if loc := re.FindStringIndex(s); loc != nil { + s = s[:loc[0]] + replacement + s[loc[1]:] + } else { + break + } + } + } + return s +} + +// Map from initialism to the regexp that matches it. +var initialisms = map[string]*regexp.Regexp{ + "Id": nil, + "Url": nil, + "Uri": nil, +} + +func init() { + for ism := range initialisms { + // Match ism if it is at the end, or followed by an uppercase letter or a number. + initialisms[ism] = regexp.MustCompile(ism + `($|[A-Z0-9])`) + } } func assert(cond bool, msg string) { diff --git a/mcp/protocol/protocol.go b/mcp/protocol/protocol.go index 800ed88..a993a62 100644 --- a/mcp/protocol/protocol.go +++ b/mcp/protocol/protocol.go @@ -62,7 +62,7 @@ type CancelledParams struct { // // This MUST correspond to the ID of a request previously issued in the same // direction. - RequestId any `json:"requestId"` + RequestID any `json:"requestId"` } // Capabilities a client may support. Known capabilities are defined here, in diff --git a/mcp/transport.go b/mcp/transport.go index 6bbe5a5..0b9aa0b 100644 --- a/mcp/transport.go +++ b/mcp/transport.go @@ -135,7 +135,7 @@ func (c *canceller) Preempt(ctx context.Context, req *jsonrpc2.Request) (result if err := json.Unmarshal(req.Params, ¶ms); err != nil { return nil, err } - id, err := jsonrpc2.MakeID(params.RequestId) + id, err := jsonrpc2.MakeID(params.RequestID) if err != nil { return nil, err } @@ -156,7 +156,7 @@ func call(ctx context.Context, conn *jsonrpc2.Connection, method string, params, // Notify the peer of cancellation. err := conn.Notify(xcontext.Detach(ctx), "notifications/cancelled", &protocol.CancelledParams{ Reason: ctx.Err().Error(), - RequestId: call.ID().Raw(), + RequestID: call.ID().Raw(), }) return errors.Join(ctx.Err(), err) case err != nil: