Skip to content
This repository was archived by the owner on Jun 29, 2025. It is now read-only.

Commit 83e1397

Browse files
committed
Allow application/vnd.api+json; ext=bulk
1 parent 9246d7a commit 83e1397

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

pkg/openapi2mcp/register.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,12 +1096,12 @@ func RegisterOpenAPITools(server *mcpserver.MCPServer, ops []OpenAPIOperation, d
10961096
var body []byte
10971097
var requestContentType string
10981098
if opCopy.RequestBody != nil && opCopy.RequestBody.Value != nil {
1099-
// Check for application/json first, then application/vnd.api+json
1100-
mt := opCopy.RequestBody.Value.Content.Get("application/json")
1099+
// Check for application/json first, then application/vnd.api+json (including with parameters)
1100+
mt := getContentByType(opCopy.RequestBody.Value.Content, "application/json")
11011101
if mt != nil {
11021102
requestContentType = "application/json"
11031103
} else {
1104-
mt = opCopy.RequestBody.Value.Content.Get("application/vnd.api+json")
1104+
mt = getContentByType(opCopy.RequestBody.Value.Content, "application/vnd.api+json")
11051105
if mt != nil {
11061106
requestContentType = "application/vnd.api+json"
11071107
}

pkg/openapi2mcp/schema.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,19 @@ func BuildInputSchema(params openapi3.Parameters, requestBody *openapi3.RequestB
182182
// Request body (application/json and application/vnd.api+json)
183183
if requestBody != nil && requestBody.Value != nil {
184184
for mtName := range requestBody.Value.Content {
185-
if mtName != "application/json" && mtName != "application/vnd.api+json" {
185+
// Check base content type without parameters
186+
baseMT := mtName
187+
if idx := strings.IndexByte(mtName, ';'); idx > 0 {
188+
baseMT = strings.TrimSpace(mtName[:idx])
189+
}
190+
if baseMT != "application/json" && baseMT != "application/vnd.api+json" {
186191
fmt.Fprintf(os.Stderr, "[WARN] Request body uses media type '%s'. Only 'application/json' and 'application/vnd.api+json' are fully supported.\n", mtName)
187192
}
188193
}
189-
// Try application/json first, then application/vnd.api+json
190-
mt := requestBody.Value.Content.Get("application/json")
194+
// Try application/json first, then application/vnd.api+json (including with parameters)
195+
mt := getContentByType(requestBody.Value.Content, "application/json")
191196
if mt == nil {
192-
mt = requestBody.Value.Content.Get("application/vnd.api+json")
197+
mt = getContentByType(requestBody.Value.Content, "application/vnd.api+json")
193198
}
194199
if mt != nil && mt.Schema != nil && mt.Schema.Value != nil {
195200
bodyProp := extractProperty(mt.Schema)

pkg/openapi2mcp/types.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
// and github.com/jedisct1/openapi-mcp/pkg/mcp/server
44
package openapi2mcp
55

6+
import (
7+
"strings"
8+
9+
"github.com/getkin/kin-openapi/openapi3"
10+
)
11+
612
// LintIssue represents a single linting issue found in an OpenAPI spec
713
type LintIssue struct {
814
Type string `json:"type"` // "error" or "warning"
@@ -28,3 +34,24 @@ type LintResult struct {
2834
type HTTPLintRequest struct {
2935
OpenAPISpec string `json:"openapi_spec"` // The OpenAPI spec as a YAML or JSON string
3036
}
37+
38+
// getContentByType finds content in an OpenAPI Content map by base content type,
39+
// ignoring parameters like charset or extensions.
40+
// For example, it will match "application/vnd.api+json; ext=bulk" when looking for "application/vnd.api+json"
41+
func getContentByType(content openapi3.Content, baseType string) *openapi3.MediaType {
42+
// First try exact match for performance
43+
if mt := content.Get(baseType); mt != nil {
44+
return mt
45+
}
46+
47+
// Then check for content types that start with the base type followed by semicolon
48+
for contentType, mediaType := range content {
49+
// Split on semicolon to get base content type
50+
parts := strings.Split(contentType, ";")
51+
if len(parts) > 0 && strings.TrimSpace(parts[0]) == baseType {
52+
return mediaType
53+
}
54+
}
55+
56+
return nil
57+
}

0 commit comments

Comments
 (0)