Skip to content

Commit 0c90960

Browse files
authored
Upgrade mcp/go-sdk (#3)
1 parent 8ef3ec1 commit 0c90960

10 files changed

Lines changed: 37 additions & 181 deletions

File tree

description_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"strings"
55
"testing"
66

7-
"github.com/modelcontextprotocol/go-sdk/jsonschema"
7+
"github.com/google/jsonschema-go/jsonschema"
88
)
99

1010
func TestGenerateAIFriendlyDescription_WithJsonSchema(t *testing.T) {

error.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"fmt"
66
"strings"
77

8-
"github.com/modelcontextprotocol/go-sdk/jsonschema"
8+
"github.com/google/jsonschema-go/jsonschema"
99
)
1010

1111
// generateAI400ErrorResponse creates a comprehensive, AI-optimized error response for 400 HTTP errors

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ toolchain go1.24.6
66

77
require (
88
github.com/getkin/kin-openapi v0.132.0
9-
github.com/modelcontextprotocol/go-sdk v0.2.0
9+
github.com/google/jsonschema-go v0.2.0
10+
github.com/modelcontextprotocol/go-sdk v0.3.0
1011
go.yaml.in/yaml/v3 v3.0.4
1112
)
1213

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
1010
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
1111
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
1212
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
13+
github.com/google/jsonschema-go v0.2.0 h1:Uh19091iHC56//WOsAd1oRg6yy1P9BpSvpjOL6RcjLQ=
14+
github.com/google/jsonschema-go v0.2.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
1315
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
1416
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
1517
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -18,8 +20,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
1820
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
1921
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
2022
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
21-
github.com/modelcontextprotocol/go-sdk v0.2.0 h1:PESNYOmyM1c369tRkzXLY5hHrazj8x9CY1Xu0fLCryM=
22-
github.com/modelcontextprotocol/go-sdk v0.2.0/go.mod h1:0sL9zUKKs2FTTkeCCVnKqbLJTw5TScefPAzojjU459E=
23+
github.com/modelcontextprotocol/go-sdk v0.3.0 h1:/1XC6+PpdKfE4CuFJz8/goo0An31bu8n8G8d3BkeJoY=
24+
github.com/modelcontextprotocol/go-sdk v0.3.0/go.mod h1:71VUZVa8LL6WARvSgLJ7DMpDWSeomT4uBv8g97mGBvo=
2325
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
2426
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
2527
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=

openapi2mcp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"net/http"
77

88
"github.com/getkin/kin-openapi/openapi3"
9-
"github.com/modelcontextprotocol/go-sdk/jsonschema"
9+
"github.com/google/jsonschema-go/jsonschema"
1010
)
1111

1212
// OpenAPIOperation describes a single OpenAPI operation to be mapped to an MCP tool.

postprocess_test.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"testing"
55

66
"github.com/getkin/kin-openapi/openapi3"
7-
"github.com/modelcontextprotocol/go-sdk/jsonschema"
7+
"github.com/google/jsonschema-go/jsonschema"
88
)
99

1010
func TestPostProcessSchema_Integration(t *testing.T) {
@@ -29,7 +29,7 @@ func TestPostProcessSchema_Integration(t *testing.T) {
2929

3030
// Build the initial schema
3131
originalSchema := BuildInputSchema(params, nil)
32-
32+
3333
// Verify original schema doesn't have the custom description
3434
if originalSchema.Description != "" {
3535
t.Errorf("Original schema should not have description, got: %s", originalSchema.Description)
@@ -48,11 +48,11 @@ func TestPostProcessSchema_Integration(t *testing.T) {
4848
if processedSchema.Type != "object" {
4949
t.Errorf("Expected type 'object', got %q", processedSchema.Type)
5050
}
51-
51+
5252
if processedSchema.Properties == nil {
5353
t.Error("Properties should be preserved")
5454
}
55-
55+
5656
if _, ok := processedSchema.Properties["testParam"]; !ok {
5757
t.Error("testParam property should be preserved")
5858
}
@@ -64,8 +64,7 @@ func TestPostProcessSchema_Integration(t *testing.T) {
6464

6565
func TestPostProcessSchema_TypesIntegrity(t *testing.T) {
6666
// Test that the function signature change maintains type safety
67-
var postProcessor func(string, jsonschema.Schema) jsonschema.Schema
68-
postProcessor = func(toolName string, schema jsonschema.Schema) jsonschema.Schema {
67+
postProcessor := func(toolName string, schema jsonschema.Schema) jsonschema.Schema {
6968
// This demonstrates the function signature is correct
7069
return schema
7170
}
@@ -83,9 +82,9 @@ func TestPostProcessSchema_TypesIntegrity(t *testing.T) {
8382
testSchema := jsonschema.Schema{
8483
Type: "object",
8584
}
86-
85+
8786
result := opts.PostProcessSchema("test", testSchema)
8887
if result.Type != "object" {
8988
t.Error("Function should return the schema")
9089
}
91-
}
90+
}

register.go

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/getkin/kin-openapi/openapi3"
14-
"github.com/modelcontextprotocol/go-sdk/jsonschema"
14+
"github.com/google/jsonschema-go/jsonschema"
1515
"github.com/modelcontextprotocol/go-sdk/mcp"
1616
)
1717

@@ -189,58 +189,6 @@ func generateAIFriendlyDescription(op OpenAPIOperation, inputSchema jsonschema.S
189189
return desc.String()
190190
}
191191

192-
// generateExampleValue creates appropriate example values based on the parameter schema
193-
func generateExampleValue(prop map[string]any) any {
194-
typeStr, _ := prop["type"].(string)
195-
196-
// Check for enum values first
197-
if enum, ok := prop["enum"].([]any); ok && len(enum) > 0 {
198-
return enum[0]
199-
}
200-
201-
// Check for example values in schema
202-
if example, ok := prop["example"]; ok {
203-
return example
204-
}
205-
206-
// Generate based on type
207-
switch typeStr {
208-
case "string":
209-
if format, ok := prop["format"].(string); ok {
210-
switch format {
211-
case "email":
212-
return "user@example.com"
213-
case "uri", "url":
214-
return "https://example.com"
215-
case "date":
216-
return "2024-01-01"
217-
case "date-time":
218-
return "2024-01-01T00:00:00Z"
219-
case "uuid":
220-
return "123e4567-e89b-12d3-a456-426614174000"
221-
default:
222-
return "example_string"
223-
}
224-
}
225-
return "example_string"
226-
case "number":
227-
return 123.45
228-
case "integer":
229-
return 123
230-
case "boolean":
231-
return true
232-
case "array":
233-
if items, ok := prop["items"].(map[string]any); ok {
234-
return []any{generateExampleValue(items)}
235-
}
236-
return []any{"item1", "item2"}
237-
case "object":
238-
return map[string]any{"key": "value"}
239-
default:
240-
return nil
241-
}
242-
}
243-
244192
// generateExampleValueFromSchema creates appropriate example values based on the jsonschema.Schema
245193
func generateExampleValueFromSchema(prop *jsonschema.Schema) any {
246194
if prop == nil {
@@ -492,7 +440,6 @@ func RegisterOpenAPITools(server *mcp.Server, ops []OpenAPIOperation, doc *opena
492440
tool := &mcp.Tool{
493441
Name: "externalDocs",
494442
Description: "Show the OpenAPI external documentation URL and description.",
495-
InputSchema: &jsonschema.Schema{Type: "object", Properties: map[string]*jsonschema.Schema{}},
496443
}
497444

498445
if opts != nil && opts.Version != "" {
@@ -501,7 +448,7 @@ func RegisterOpenAPITools(server *mcp.Server, ops []OpenAPIOperation, doc *opena
501448
}
502449
}
503450

504-
mcp.AddTool(server, tool, func(ctx context.Context, session *mcp.ServerSession, params *mcp.CallToolParams) (*mcp.CallToolResult, error) {
451+
mcp.AddTool(server, tool, func(_ context.Context, req *mcp.CallToolRequest, _ any) (*mcp.CallToolResult, any, error) {
505452
info := "External documentation URL: " + doc.ExternalDocs.URL
506453
if doc.ExternalDocs.Description != "" {
507454
info += "\nDescription: " + doc.ExternalDocs.Description
@@ -512,7 +459,7 @@ func RegisterOpenAPITools(server *mcp.Server, ops []OpenAPIOperation, doc *opena
512459
Text: info,
513460
},
514461
},
515-
}, nil
462+
}, nil, nil
516463
})
517464
toolNames = append(toolNames, "externalDocs")
518465
}
@@ -522,7 +469,6 @@ func RegisterOpenAPITools(server *mcp.Server, ops []OpenAPIOperation, doc *opena
522469
tool := &mcp.Tool{
523470
Name: "info",
524471
Description: "Show API metadata: title, version, description, and terms of service.",
525-
InputSchema: &jsonschema.Schema{Type: "object", Properties: map[string]*jsonschema.Schema{}},
526472
}
527473

528474
if opts != nil && opts.Version != "" {
@@ -531,7 +477,7 @@ func RegisterOpenAPITools(server *mcp.Server, ops []OpenAPIOperation, doc *opena
531477
}
532478
}
533479

534-
mcp.AddTool(server, tool, func(ctx context.Context, session *mcp.ServerSession, params *mcp.CallToolParams) (*mcp.CallToolResult, error) {
480+
mcp.AddTool(server, tool, func(_ context.Context, req *mcp.CallToolRequest, _ any) (*mcp.CallToolResult, any, error) {
535481
var sb strings.Builder
536482
if doc.Info.Title != "" {
537483
sb.WriteString("Title: " + doc.Info.Title + "\n")
@@ -551,7 +497,7 @@ func RegisterOpenAPITools(server *mcp.Server, ops []OpenAPIOperation, doc *opena
551497
Text: strings.TrimSpace(sb.String()),
552498
},
553499
},
554-
}, nil
500+
}, nil, nil
555501
})
556502
toolNames = append(toolNames, "info")
557503
}
@@ -584,7 +530,7 @@ func RegisterOpenAPITools(server *mcp.Server, ops []OpenAPIOperation, doc *opena
584530
MIMEType: "application/json",
585531
}
586532

587-
server.AddResource(&timestampResource, func(ctx context.Context, session *mcp.ServerSession, params *mcp.ReadResourceParams) (*mcp.ReadResourceResult, error) {
533+
server.AddResource(&timestampResource, func(ctx context.Context, req *mcp.ServerRequest[*mcp.ReadResourceParams]) (*mcp.ReadResourceResult, error) {
588534
now := time.Now().Unix()
589535
content := fmt.Sprintf(`{"unix_timestamp": %d, "iso8601": "%s", "timezone": "%s"}`,
590536
now,

schema.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"strings"
99

1010
"github.com/getkin/kin-openapi/openapi3"
11-
"github.com/modelcontextprotocol/go-sdk/jsonschema"
11+
"github.com/google/jsonschema-go/jsonschema"
1212
)
1313

1414
// escapeParameterName converts parameter names with brackets to MCP-compatible names.
@@ -31,15 +31,6 @@ func escapeParameterName(name string) string {
3131
return escaped
3232
}
3333

34-
// unescapeParameterName converts escaped parameter names back to their original form.
35-
// This maintains a mapping from escaped names to original names for parameter lookup.
36-
func unescapeParameterName(escaped string, originalNames map[string]string) string {
37-
if original, exists := originalNames[escaped]; exists {
38-
return original
39-
}
40-
return escaped // Return as-is if not found in mapping
41-
}
42-
4334
// buildParameterNameMapping creates a mapping from escaped parameter names to original names.
4435
// This is used to reverse the escaping when looking up parameter values.
4536
func buildParameterNameMapping(params openapi3.Parameters) map[string]string {

server.go

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -5,84 +5,12 @@ import (
55
"context"
66
"fmt"
77
"net/http"
8-
"os"
98
"strings"
109

1110
"github.com/getkin/kin-openapi/openapi3"
1211
"github.com/modelcontextprotocol/go-sdk/mcp"
1312
)
1413

15-
// authContextFunc extracts authentication headers from HTTP requests and sets them
16-
// as environment variables for the duration of each request. This allows API keys
17-
// and other authentication to be provided via HTTP headers when using HTTP mode.
18-
func authContextFunc(ctx context.Context, r *http.Request) context.Context {
19-
// Save original environment values to restore them later
20-
origAPIKey := os.Getenv("API_KEY")
21-
origBearerToken := os.Getenv("BEARER_TOKEN")
22-
origBasicAuth := os.Getenv("BASIC_AUTH")
23-
24-
// Extract authentication from HTTP headers
25-
if apiKey := r.Header.Get("X-API-Key"); apiKey != "" {
26-
os.Setenv("API_KEY", apiKey)
27-
} else if apiKey := r.Header.Get("Api-Key"); apiKey != "" {
28-
os.Setenv("API_KEY", apiKey)
29-
}
30-
31-
if bearerToken := r.Header.Get("Authorization"); bearerToken != "" {
32-
if len(bearerToken) > 7 && bearerToken[:7] == "Bearer " {
33-
os.Setenv("BEARER_TOKEN", bearerToken[7:])
34-
} else if len(bearerToken) > 6 && bearerToken[:6] == "Basic " {
35-
os.Setenv("BASIC_AUTH", bearerToken[6:])
36-
}
37-
}
38-
39-
// Create a context that restores the original environment when done
40-
return &authContext{
41-
Context: ctx,
42-
origAPIKey: origAPIKey,
43-
origBearerToken: origBearerToken,
44-
origBasicAuth: origBasicAuth,
45-
}
46-
}
47-
48-
// authContext wraps a context and restores original environment variables when done
49-
type authContext struct {
50-
context.Context
51-
origAPIKey string
52-
origBearerToken string
53-
origBasicAuth string
54-
}
55-
56-
// Done restores the original environment variables when the context is done
57-
func (c *authContext) Done() <-chan struct{} {
58-
done := c.Context.Done()
59-
if done != nil {
60-
go func() {
61-
<-done
62-
c.restoreEnv()
63-
}()
64-
}
65-
return done
66-
}
67-
68-
func (c *authContext) restoreEnv() {
69-
if c.origAPIKey != "" {
70-
os.Setenv("API_KEY", c.origAPIKey)
71-
} else {
72-
os.Unsetenv("API_KEY")
73-
}
74-
if c.origBearerToken != "" {
75-
os.Setenv("BEARER_TOKEN", c.origBearerToken)
76-
} else {
77-
os.Unsetenv("BEARER_TOKEN")
78-
}
79-
if c.origBasicAuth != "" {
80-
os.Setenv("BASIC_AUTH", c.origBasicAuth)
81-
} else {
82-
os.Unsetenv("BASIC_AUTH")
83-
}
84-
}
85-
8614
// NewServer creates a new MCP server, registers all OpenAPI tools, and returns the server.
8715
// Equivalent to calling RegisterOpenAPITools with all operations from the spec.
8816
// Example usage for NewServer:
@@ -118,8 +46,8 @@ func NewServerWithOps(name, version string, doc *openapi3.T, ops []OpenAPIOperat
11846
//
11947
// openapi2mcp.ServeStdio(srv)
12048
func ServeStdio(server *mcp.Server) error {
121-
transport := mcp.NewStdioTransport()
122-
_, err := server.Connect(context.Background(), transport)
49+
transport := new(mcp.StdioTransport)
50+
_, err := server.Connect(context.Background(), transport, nil)
12351
return err
12452
}
12553

0 commit comments

Comments
 (0)