Add deck file openapi2mcp#286
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #286 +/- ##
==========================================
- Coverage 69.82% 69.36% -0.47%
==========================================
Files 24 25 +1
Lines 2751 3470 +719
==========================================
+ Hits 1921 2407 +486
- Misses 653 807 +154
- Partials 177 256 +79 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds a new deck file openapi2mcp transformation that converts OpenAPI 3.x specs into decK declarative config containing an ai-mcp-proxy plugin with generated MCP tool definitions (plus docs, fixtures, and tests).
Changes:
- Introduces
openapi2mcpconverter (tool generation, schema simplification, optional direct routes, and oauth2-based ACL generation viax-kong-mcp-acl). - Adds new Cobra command
deck file openapi2mcpwith flags and history tracking. - Adds documentation + example OpenAPI, and a fixture-based test suite (with expected outputs).
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
openapi2mcp/openapi2mcp.go |
Core OpenAPI→decK conversion logic for MCP tools, routes, and ACL config. |
openapi2mcp/openapi2mcp_test.go |
Fixture-based unit tests and targeted behavior tests (kebab-case, schema simplification, ACL). |
openapi2mcp/openapi2mcp_suite_test.go |
Ginkgo suite bootstrap for the new package. |
openapi2mcp/oas3_testfiles/invalid/no-paths.yaml |
Negative fixture for missing .paths. |
openapi2mcp/oas3_testfiles/01-basic-conversion.yaml |
Basic conversion fixture. |
openapi2mcp/oas3_testfiles/01-basic-conversion.expected.json |
Expected output for basic conversion. |
openapi2mcp/oas3_testfiles/02-mcp-extensions.yaml |
Fixture covering MCP-specific extensions. |
openapi2mcp/oas3_testfiles/02-mcp-extensions.expected.json |
Expected output for MCP extension handling. |
openapi2mcp/oas3_testfiles/03-mode-conversion.yaml |
Fixture for mode=conversion. |
openapi2mcp/oas3_testfiles/03-mode-conversion.expected.json |
Expected output for mode=conversion. |
openapi2mcp/oas3_testfiles/04-direct-route.yaml |
Fixture for --include-direct-route. |
openapi2mcp/oas3_testfiles/04-direct-route.expected.json |
Expected output including direct routes. |
openapi2mcp/oas3_testfiles/05-kong-extensions.yaml |
Fixture for Kong extensions at document level. |
openapi2mcp/oas3_testfiles/05-kong-extensions.expected.json |
Expected output for Kong extensions fixture. |
openapi2mcp/oas3_testfiles/06-custom-path-prefix.yaml |
Fixture for custom MCP route path prefix. |
openapi2mcp/oas3_testfiles/06-custom-path-prefix.expected.json |
Expected output for custom path prefix. |
openapi2mcp/oas3_testfiles/07-multiple-servers.yaml |
Fixture for multiple server URLs (upstream generation). |
openapi2mcp/oas3_testfiles/07-multiple-servers.expected.json |
Expected output including upstream + targets. |
openapi2mcp/oas3_testfiles/08-security-acl.yaml |
Fixture for oauth2 ACL generation (x-kong-mcp-acl + default ACL). |
openapi2mcp/oas3_testfiles/08-security-acl.expected.json |
Expected output including plugin + per-tool ACL fields. |
cmd/openapi2mcp.go |
Adds the deck file openapi2mcp CLI command + flags. |
docs/openapi2mcp/README.md |
User documentation for the new command, flags, extensions, and ACL behavior. |
docs/openapi2mcp/example_oas.yaml |
Annotated example spec demonstrating features/extensions. |
docs/README.md |
Adds openapi2mcp to the docs index. |
.gitignore |
Ignores generated JSON outputs from openapi2mcp fixture tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func findFilesBySuffix(t *testing.T, dir string, suffix string) []fs.DirEntry { | ||
| files, err := os.ReadDir(dir) | ||
| if err != nil { | ||
| t.Error("failed reading test data: %w", err) |
There was a problem hiding this comment.
t.Error doesn't support printf-style formatting, so the %w verb will be printed literally and the wrapped error is lost. Use t.Errorf(...) or (preferably here) t.Fatalf(...) to stop the test when fixtures can't be read.
| t.Error("failed reading test data: %w", err) | |
| t.Fatalf("failed reading test data: %v", err) |
| | `--output-file`, `-o` | Output file path. Use `-` for stdout | `-` | | ||
| | `--format` | Output format: `yaml` or `json` | `yaml` | | ||
| | `--select-tag` | Tags to select from the spec (can be repeated) | - | | ||
| | `--uuid-base` | Base UUID namespace for deterministic ID generation | - | |
There was a problem hiding this comment.
The --uuid-base flag is described here as a “UUID namespace”, but the CLI actually uses it as the document/base name (DocName) which influences both deterministic UUID generation and the generated service/route names. Updating the wording would help avoid confusion for users expecting to pass a UUID namespace value.
| | `--uuid-base` | Base UUID namespace for deterministic ID generation | - | | |
| | `--uuid-base` | Base document name used for deterministic UUID generation and service/route naming | - | |
| | `x-kong-service-defaults` | Document, Path, Operation | Default values for Kong Service entities | | ||
| | `x-kong-route-defaults` | Document, Path, Operation | Default values for Kong Route entities | | ||
| | `x-kong-upstream-defaults` | Document | Default values for Kong Upstream entities | | ||
| | `x-kong-plugin-<name>` | Document, Path, Operation | Add Kong plugins to generated entities | | ||
|
|
There was a problem hiding this comment.
This table claims x-kong-service-defaults, x-kong-route-defaults, and x-kong-plugin-<name> are supported at Path/Operation levels, but the current converter implementation only reads these extensions from the document root. Either implement path/operation-level handling or update the documentation to match the current behavior.
| | `x-kong-service-defaults` | Document, Path, Operation | Default values for Kong Service entities | | |
| | `x-kong-route-defaults` | Document, Path, Operation | Default values for Kong Route entities | | |
| | `x-kong-upstream-defaults` | Document | Default values for Kong Upstream entities | | |
| | `x-kong-plugin-<name>` | Document, Path, Operation | Add Kong plugins to generated entities | | |
| | `x-kong-service-defaults` | Document | Default values for Kong Service entities | | |
| | `x-kong-route-defaults` | Document | Default values for Kong Route entities | | |
| | `x-kong-upstream-defaults` | Document | Default values for Kong Upstream entities | | |
| | `x-kong-plugin-<name>` | Document | Add Kong plugins to generated entities | | |
| > Note: Path- and operation-level usage of these extensions is not currently supported by `openapi2mcp`; only document-level extensions are read. |
| paramNames[p.Name] = true | ||
| } | ||
| } | ||
|
|
||
| // Add path params that aren't overridden | ||
| for _, p := range pathParams { | ||
| if p != nil && !paramNames[p.Name] { |
There was a problem hiding this comment.
Parameter override detection only keys on p.Name. OpenAPI parameters are uniquely identified by the tuple (name,in), so a query/header parameter that shares a name with a path parameter would be incorrectly treated as an override and dropped. Consider keying by p.In+":"+p.Name (or a small struct) when building paramNames and when checking for overrides.
| paramNames[p.Name] = true | |
| } | |
| } | |
| // Add path params that aren't overridden | |
| for _, p := range pathParams { | |
| if p != nil && !paramNames[p.Name] { | |
| paramNames[p.In+":"+p.Name] = true | |
| } | |
| } | |
| // Add path params that aren't overridden | |
| for _, p := range pathParams { | |
| if p != nil && !paramNames[p.In+":"+p.Name] { |
| func MustConvert(content []byte, opts O2MOptions) map[string]interface{} { | ||
| result, err := Convert(content, opts) | ||
| if err != nil { | ||
| log.Fatal(err) |
There was a problem hiding this comment.
The comment says this function will panic on error, but the implementation uses log.Fatal, which exits the process and cannot be recovered from. Either change the comment to reflect the behavior, or use panic/log.Panic so callers can recover in tests and libraries.
| log.Fatal(err) | |
| log.Panic(err) |
| @@ -0,0 +1,13 @@ | |||
| package openapi2mcp | |||
There was a problem hiding this comment.
This Ginkgo suite is declared in the openapi2mcp package, while other suites in this repo use the external <pkg>_test package (e.g. openapi2kong_test). Using the external test package helps avoid coupling tests to unexported APIs and keeps suite naming consistent; consider switching this file to package openapi2mcp_test and importing the package where needed.
| package openapi2mcp | |
| package openapi2mcp_test |
7114358 to
e1d1be7
Compare
|
Closing as it was merged through #290 |
Add support for
openapi2mcpfor configuring the MCP plugin