feat(mcp): add MCP server exposing all oastools capabilities#310
feat(mcp): add MCP server exposing all oastools capabilities#310
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📝 WalkthroughWalkthroughAdds a stdio-based MCP (Model Context Protocol) server to oastools (new Changes
Sequence Diagram(s)sequenceDiagram
participant Client as MCP Client (Claude)
participant Stdio as Stdio Transport
participant Server as oastools MCP Server
participant Tool as Tool Handler
participant Lib as OpenAPI Libraries
Client->>Stdio: JSON-RPC Request (ListTools / CallTool)
Stdio->>Server: Deliver request
Server->>Server: Route request by tool name
alt ListTools
Server-->>Stdio: Tool catalog (15 tools)
else CallTool
Server->>Tool: Dispatch CallTool
Tool->>Tool: Resolve spec (file|url|content)
Tool->>Lib: Parse / Validate / Transform
Lib-->>Tool: Result
Tool->>Server: Formatted result
end
Server-->>Stdio: JSON-RPC Response
Stdio-->>Client: Return response
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 20
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
README.md (1)
19-19:⚠️ Potential issue | 🟡 MinorClarify the "Minimal Dependencies" claim to distinguish library vs. CLI dependency scope.
The go.mod file lists
github.com/modelcontextprotocol/go-sdk v1.3.0as a direct dependency (alongside yaml, x/tools, and x/text). While library users importing the package won't pull the MCP SDK (it's isolated ininternal/mcpserver), the CLI binary requires it. Add a note on line 19 to clarify that the minimal dependencies apply to library consumption, with the MCP SDK being a CLI-only runtime dependency.
🤖 Fix all issues with AI agents
In `@cmd/oastools/main.go`:
- Around line 132-136: The mcp subcommand uses context.Background() so
SIGINT/SIGTERM won't cancel the server; change it to use a cancellable context
wired to OS signals (e.g., use signal.NotifyContext or create context.WithCancel
and signal.Notify for os.Interrupt and syscall.SIGTERM), add the "os/signal" and
"syscall" imports, pass that signal-aware ctx into mcpserver.Run(ctx), and
ensure you handle the returned error (and cancel/cleanup) before exiting so the
server can shut down gracefully.
In `@docs/mcp-server.md`:
- Around line 354-369: The fenced directory-tree block in docs/mcp-server.md is
missing a language specifier (MD040); update the opening fence for that block
(the one containing the internal/mcpserver/ tree) to include a plain text
language tag (e.g., change the opening "```" to "```text" or "```plaintext") so
the linter recognizes it as a code block with a language.
- Around line 1-3: The docs/mcp-server.md file was added directly under docs/
but docs are generated by the mkdocs build; move the canonical source out of
docs (e.g., create mcp-server.md at repo root or mcp-server/README.md) and
update the build preparation script scripts/prepare-docs.sh to copy or process
that source into docs/mcp-server.md during the prepare-docs step (follow the
same pattern used for examples/deep dives in prepare-docs.sh), and if this is
new content, add the chosen source location to the repository and the
prepare-docs.sh flow before committing the generated file under docs/.
In `@internal/mcpserver/server.go`:
- Line 8: The import line uses a redundant named alias "oastools" for the
package github.com/erraggy/oastools; remove the explicit alias and import the
package using its default name (i.e., change the import entry that currently
reads with the alias "oastools" to a regular import of
github.com/erraggy/oastools) so code references to oastools remain unchanged but
the alias is not duplicated.
In `@internal/mcpserver/tools_convert.go`:
- Around line 58-65: The code uses makeSlice to initialize output.Issues then
appends converted entries, which will create leading zero-value entries if
makeSlice returns make([]T, n); either change makeSlice to return a zero-length,
capacity-n slice (make([]convertIssue, 0, n)) or avoid append by allocating a
length-n slice and assigning by index (e.g., create output.Issues with length
len(result.Issues) and set output.Issues[i] = convertIssue{...}); update the
implementation or this loop accordingly for the makeSlice, output.Issues,
convertIssue, and result.Issues usage.
- Around line 97-113: The default branch in buildConverterOptions currently
calls input.Spec.resolve() only to capture and return its error; instead, detect
the empty-input case and return a clear, direct error (e.g., fmt.Errorf("no
input provided") or similar) without calling input.Spec.resolve(); update the
default case to avoid invoking parser.ParseResult or resolve() and return the
new explicit error so the code is clearer and avoids unnecessary work tied to
resolve().
In `@internal/mcpserver/tools_diff.go`:
- Around line 93-98: The buildDiffSummary function contains an unreachable
branch: when TotalChanges == 0 the counts (BreakingCount, WarningCount,
InfoCount) will also be zero, so the second return path can never be hit; fix by
simplifying the logic in buildDiffSummary to first return "No changes detected."
when output.TotalChanges == 0 and move the "No breaking changes detected." check
into the else path (i.e., only evaluate output.BreakingCount == 0 etc. when
TotalChanges > 0), ensuring you update the conditional flow around
buildDiffSummary to remove the dead branch.
- Around line 45-52: The code currently always sets
differ.WithMode(differ.ModeBreaking) when building opts in the function around
opts := []differ.Option{...}, which contradicts input.BreakingOnly and the CLI
pattern; change the logic so that you pass differ.WithMode(differ.ModeBreaking)
only when input.BreakingOnly (or input.BreakingOnly == true) is set and
otherwise pass differ.WithMode(differ.ModeSimple) (or omit the WithMode if
default is simple), removing the need for client-side filtering later; update
the opts construction that references differ.WithSourceParsed,
differ.WithTargetParsed and differ.WithMode so it conditionally selects
differ.ModeBreaking vs differ.ModeSimple based on input.BreakingOnly.
In `@internal/mcpserver/tools_fix_test.go`:
- Around line 76-84: Test uses raw string literals to check fix types; replace
those literals with the fixer package constants (e.g., use
string(fixer.FixTypeDuplicateOperationId) instead of "duplicate-operation-id"
and string(fixer.FixTypeMissingPathParameter) where applicable) so the loop that
sets found and the final assert.True check compare against the canonical
constants from the fixer package.
In `@internal/mcpserver/tools_fix.go`:
- Around line 86-103: The default branch should not call input.Spec.resolve()
just to get an error because that triggers parsing side effects; replace that
call with a direct returned error (e.g. fmt.Errorf("must provide exactly one of
Spec.File, Spec.URL, or Spec.Content")) and return it instead. Update the switch
default to return the new fmt.Errorf message, leaving the other branches that
append fixer.WithFilePath, fixer.WithParsed and fixer.WithMutableInput (and the
parser.ParseWithOptions usage) unchanged so no parsing occurs when no input is
provided.
In `@internal/mcpserver/tools_generate.go`:
- Around line 85-91: Replace the explicit slice allocation for output.Files with
the shared helper to preserve nil/omitempty semantics and keep consistency:
instead of using make([]generatedFileInfo, 0, len(result.Files)) and appending,
initialize output.Files via makeSlice[generatedFileInfo](len(result.Files)) and
then populate entries from result.Files (referencing output.Files,
generatedFileInfo, result.Files and the makeSlice[T](n) helper) so behavior
matches other tool handlers.
In `@internal/mcpserver/tools_overlay.go`:
- Around line 210-217: The loop appends to output.Errors without pre-allocating,
which differs from other handlers and can break nil/omitempty semantics; change
construction to pre-allocate output.Errors using the same makeSlice pattern used
in handleOverlayApply/handleValidate by creating a slice of overlayValidateIssue
with length 0 and capacity len(errs) (e.g., via makeSlice-like helper) and then
append each overlayValidateIssue built from errs (using
e.Field/e.Path/e.Message) into output.Errors so output.Errors remains nil when
errs is empty and avoids extra allocations when not.
- Around line 164-174: The code uses http.Get (in the case handling s.URL in
resolveOverlayInput) which blocks without context or timeout; modify
resolveOverlayInput (and its callers if needed) to accept a context.Context,
create an http.Request with http.NewRequestWithContext(ctx, "GET", s.URL, nil),
use an http.Client with a sensible timeout (or the caller-provided client) to do
the request, and propagate ctx cancellation to the request and the resp.Body
read; ensure you remove the //nolint:noctx and handle context/cancellation and
timeout errors appropriately before calling overlay.ParseOverlay.
In `@internal/mcpserver/tools_validate.go`:
- Around line 49-73: The output currently sets WarningCount from
result.WarningCount even when input.NoWarnings is true, causing a non-zero
"warning_count" while the Warnings slice is omitted; update the logic in the
block around validateOutput creation (validateOutput, result.WarningCount,
input.NoWarnings, output.Warnings) so that when input.NoWarnings is true you
also set output.WarningCount = 0 (and keep output.Warnings empty/omitted),
ensuring the summary count matches the suppressed details.
In `@internal/mcpserver/tools_walk_parameters_test.go`:
- Around line 58-66: The test helper callWalkParameters currently uses a direct
type assertion out.(walkParametersOutput) which can panic on unexpected types;
update callWalkParameters to perform a safe comma-ok assertion (e.g., v, ok :=
out.(walkParametersOutput)) and use test assertions
(require.True/require.IsType) to fail with a clear message if the type is wrong,
then return v when ok is true; keep the existing nil check for out.
In `@internal/mcpserver/tools_walk_responses.go`:
- Around line 136-138: The extension filter currently short-circuits when
info.Response is nil because the condition uses "hasExtFilter && info.Response
!= nil && !matchExtension(...)", allowing nil responses to slip through; change
the condition in the loop to explicitly continue when hasExtFilter and
(info.Response == nil || !matchExtension(info.Response.Extra, extKey, extValue))
so nil responses are treated as missing the extension and properly skipped
(update the condition referencing hasExtFilter, info.Response, matchExtension,
extKey, extValue).
In `@internal/mcpserver/tools_walk_schemas.go`:
- Around line 176-182: schemaTypeString currently prints slices like []string as
"[string null]" via fmt.Sprintf which is inconsistent with parameterTypeString's
"string, null"; update schemaTypeString to detect when t is a []string (or []any
representing strings), join elements with ", " (similar to parameterTypeString)
and return that string, keeping the nil check and falling back to
fmt.Sprintf("%v", t) for non-slice types; reference function names
schemaTypeString and parameterTypeString to locate the code to change.
In `@internal/mcpserver/tools_walk_security_test.go`:
- Around line 47-55: The type assertion on out in callWalkSecurity is unsafe and
can panic if handleWalkSecurity returns a non-nil value of a different type;
update callWalkSecurity to use the comma-ok form when casting out to
walkSecurityOutput (reference: function callWalkSecurity, variable out, return
value from handleWalkSecurity) and if the assertion fails call t.Fatalf with a
message including the unexpected %T so tests fail clearly instead of panicking.
In `@plugin/skills/explore-api.md`:
- Around line 1-91: The doc headings (e.g., "## Step 1: Get the high-level
overview", "## Step 2: List endpoints", "## Step 3: List data models", "## Step
4: Drill into specifics", "## Step 5: Summarize findings") should include the
approved scannability emojis (✅❌🔴🟡⚠️) as per guidelines; update each step
header to prepend an appropriate emoji (for example "🔍" or "✅" from the allowed
set) to improve visual scanning while keeping the rest of the header text
unchanged and ensure consistency across all step headings in explore-api.md.
- Around line 61-82: Step 4 contains multiple fenced code blocks (the ```json
blocks under "Specific endpoint details:", "Parameters for a path:", "Responses
for an endpoint:", and "Security schemes:") that are not surrounded by blank
lines; update explore-api.md so each fenced block has a blank line before and
after it (i.e., ensure a blank line precedes the ```json line and follows the
closing ``` for the examples like {"spec": {"file": "<path>"}, "operation_id":
"getUser", "detail": true} and the other JSON examples) to satisfy MD031.
477afe6 to
b6cc614
Compare
There was a problem hiding this comment.
Actionable comments posted: 15
🤖 Fix all issues with AI agents
In `@docs/claude-code-plugin.md`:
- Around line 1-3: The file docs/claude-code-plugin.md is a generated artifact
and must not be edited directly; move its source content out of docs/ into the
canonical source location at the repo root (the same pattern used for
docs/mcp-server.md), update the mkdocs/mkdocs.yml build config or the existing
generation script so the file is produced into docs/ during the build, and
replace docs/claude-code-plugin.md with either the generated output only (kept
via CI) or a short autogenerated stub pointing to the real source; ensure you
update any references to claude-code-plugin.md to point to the new source file
and keep the same slug/title so links remain stable.
In `@docs/mcp-server.md`:
- Around line 17-20: Add the missing Markdown fenced-code language tag "text" to
the block containing the `/plugin marketplace add erraggy/oastools` and `/plugin
install oastools` commands so the snippet is treated as plain text (fixes
MD040); locate the fenced block in the docs file that wraps those two lines and
change the opening fence from ``` to ```text, leaving the content and closing
fence unchanged.
In `@internal/mcpserver/input_test.go`:
- Around line 1-51: Add a positive test that exercises the URL resolution path
of specInput.resolve: create a specInput with the URL field set to a known
public OpenAPI spec (e.g., petstore), call specInput.resolve(), assert no error
and that the returned result is non-nil and has a non-empty Version; this
ensures the parser.WithFilePath(s.URL) path and URL fetching logic in resolve
are covered (look for specInput and resolve in input_test.go/input.go).
In `@internal/mcpserver/input.go`:
- Around line 12-16: specInput.File and specInput.URL accept arbitrary
paths/URLs which enable path traversal and SSRF; add validation where inputs are
parsed/used (e.g., wherever specInput is handled) to reject risky values: for
File, reject absolute paths and any "../" traversal by running a filepath.Clean
and ensuring the final path is within the server working directory (or an
explicit allowed directory/allowlist); for URL, require http/https, parse via
net/url, resolve the host and block private/loopback/metadata IP ranges (or
enforce a public-host allowlist) and timeouts, and return clear errors when
validation fails; apply these checks in the function that loads/reads the spec
from specInput (referencing specInput.File and specInput.URL).
In `@internal/mcpserver/tools_join.go`:
- Around line 82-85: The code pre-allocates output.Warnings with
makeSlice[joinWarning](len(result.Warnings)) then appends, which results in
extra zero-value entries; either allocate a zero-length slice with capacity
(e.g. makeSlice[joinWarning](0, len(result.Warnings))) before using append, or
keep the current allocation and write by index instead (for i, w := range
result.Warnings { output.Warnings[i] = joinWarning{Message: w} }); update the
code that fills output.Warnings (references: output.Warnings, makeSlice,
joinWarning, result.Warnings) to use one of these fixes so no zero-value gaps
are produced.
In `@internal/mcpserver/tools_overlay.go`:
- Around line 40-49: handleOverlayApply and handleOverlayValidate drop the
request context and call resolveOverlayInput which uses context.Background(), so
HTTP fetches can't be cancelled; change both handler signatures to accept the
passed context (replace the discarded _ context.Context) and pass that context
into resolveOverlayInput, then modify resolveOverlayInput to accept a context
parameter and use http.NewRequestWithContext for any outbound HTTP requests
instead of creating context.Background(); update all call sites (both apply and
validate) to pass the same context through.
In `@internal/mcpserver/tools_validate_test.go`:
- Around line 12-41: Add tests that exercise strict mode, the NoWarnings flag,
and the spec-resolution error path for handleValidate: extend/ add
TestValidateTool cases that call handleValidate with validateInput.Spec set via
specInput and set Strict: true to exercise WithStrictMode behavior, assert the
first return (*mcp.CallToolResult) is nil on successful validations and non-nil
when resolution fails (e.g., point Content to a non-existent file path) and that
the validateOutput is empty on error; add a NoWarnings test that sets
NoWarnings:true and an input that would produce warnings and assert
output.WarningCount == 0 and output.Warnings == nil; reference handleValidate,
validateInput, specInput, WithStrictMode, WarningCount, Warnings, and
*mcp.CallToolResult when locating where to add/modify tests.
In `@internal/mcpserver/tools_walk_operations_test.go`:
- Around line 63-71: callWalkOperations currently uses a direct type assertion
on out which can panic on unexpected types; update it to use the comma-ok form
(like callWalkSecurity) when asserting out to walkOperationsOutput, handle the
false case by returning an empty walkOperationsOutput and no panic, and keep the
existing nil check for out before asserting; locate function callWalkOperations
and replace the direct assertion of out.(walkOperationsOutput) with the safe "v,
ok := out.(walkOperationsOutput)" pattern and return v when ok, otherwise return
walkOperationsOutput{}.
In `@internal/mcpserver/tools_walk_parameters_test.go`:
- Around line 96-135: Tests TestWalkParameters_FilterByMethod use raw HTTP
method strings ("post" and "POST"); replace those literals with the
httputil.MethodPost constant when setting walkParametersInput.Method and when
asserting output.Summaries[0].Method to follow coding guidelines and avoid
hard-coded method strings while preserving the case-normalization behavior being
tested.
In `@internal/mcpserver/tools_walk_paths_test.go`:
- Around line 53-61: callWalkPaths currently uses an unsafe type assertion on
out (out.(walkPathsOutput)); change it to the comma-ok form to match
callWalkSecurity: after calling handleWalkPaths, do outTyped, ok :=
out.(walkPathsOutput) and require.True(t, ok) (or require.Failf/t.Fatalf with a
clear message) before returning outTyped; reference the callWalkPaths helper and
the handleWalkPaths function to locate the change.
In `@internal/mcpserver/tools_walk_responses_test.go`:
- Around line 46-54: The test uses an unsafe type assertion when converting out
to walkResponsesOutput in callWalkResponses; update the return logic to use the
comma-ok form (e.g., v, ok := out.(walkResponsesOutput)) and assert that ok is
true before returning v (mirror the pattern used in callWalkSecurity) so the
test fails with a clear message rather than panicking if the type is unexpected.
In `@internal/mcpserver/tools_walk_schemas_test.go`:
- Around line 74-82: The helper callWalkSchemas currently does a bare type
assertion on out from handleWalkSchemas which can panic; change it to the
comma-ok form (like callWalkSecurity) when casting out to walkSchemasOutput: use
outTyped, ok := out.(walkSchemasOutput) and if !ok return result,
walkSchemasOutput{} so the test fails safely; keep the same behaviour when out
is nil and retain the call to handleWalkSchemas and require.NoError(t, err).
In `@mkdocs.yml`:
- Around line 63-64: The mkdocs configuration is missing the pymdownx.tabbed
extension so the tabbed syntax used in claude-code-plugin.md (e.g., the ===
"Homebrew (macOS/Linux)" tab blocks) will render as raw text; update the
mkdocs.yml markdown_extensions list to include "pymdownx.tabbed" (alongside any
existing pymdownx extensions) so the tabbed content in claude-code-plugin.md is
rendered correctly.
In `@README.md`:
- Around line 124-127: The fenced code block containing the two commands
"/plugin marketplace add erraggy/oastools" and "/plugin install oastools" needs
a language tag to satisfy MD040; update the opening fence from ``` to ```text so
the block becomes a ```text fenced code block, leaving the commands unchanged.
- Line 25: The README line uses the same anchor for both links; update the
second link so "[Claude Code plugin]" points to the correct distinct anchor
"#claude-code-plugin" instead of "#mcp-server" (and verify the corresponding
header "Claude Code plugin" exists or add it if missing) so the two links
resolve to separate sections.
b6cc614 to
def556e
Compare
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Fix all issues with AI agents
In `@internal/mcpserver/integration_test.go`:
- Around line 261-283: The test helper unmarshalStructured currently marshals
result.StructuredContent to JSON and back which is unnecessary; change
unmarshalStructured to first attempt a type assertion on
result.StructuredContent (e.g., if v, ok :=
result.StructuredContent.(map[string]any) { return v }), and only fall back to
JSON round-trip if the assertion fails (or if it’s another compatible map type
like map[string]interface{}). Update the function logic around StructuredContent
handling in unmarshalStructured to prefer direct type assertions and only use
json.Marshal/json.Unmarshal as a fallback to preserve current behavior.
In `@internal/mcpserver/tools_fix_test.go`:
- Around line 130-137: Replace the raw string comparison
"missing-path-parameter" with the fixer package constant by comparing f.Type to
string(fixer.FixTypeMissingPathParameter); locate the loop iterating over
output.Fixes (the for _, f := range output.Fixes block) and change the if check
from f.Type == "missing-path-parameter" to f.Type ==
string(fixer.FixTypeMissingPathParameter) so it matches the existing usage
pattern (see the earlier line using string(fixer.FixTypeDuplicateOperationId))
and keeps constants consistent.
In `@internal/mcpserver/tools_generate.go`:
- Around line 37-44: The handler handleGenerate currently uses
generateInput.OutputDir directly (later passed to result.WriteFiles) which
allows path traversal or absolute paths; sanitize by cleaning and resolving the
absolute path (use filepath.Clean + filepath.Abs) then validate it is inside a
configured workspace root (compute rel, e.g. filepath.Rel(workspaceRoot,
resolved) and ensure it does not start with ".."), reject and return an error if
it is outside, and log the resolved absolute path before calling
result.WriteFiles; perform this check on the OutputDir value early in
handleGenerate (before calling input.Spec.resolve or result.WriteFiles).
In `@internal/mcpserver/tools_overlay_test.go`:
- Around line 244-254: Update the test TestOverlayValidateTool_MissingFields to
assert the exact expected number of validation errors instead of a loose bound:
replace the assert.GreaterOrEqual(t, output.ErrorCount, 3) check with an exact
equality assertion expecting 4 errors (the case created from
overlayTestMissingFieldsOverlay via handleOverlayValidate/overlay.Validate
should produce exactly 4 errors). Ensure you reference the output variable
(output.ErrorCount) in the equality assertion so the test fails on regressions.
In `@internal/mcpserver/tools_overlay.go`:
- Line 176: The call to io.ReadAll(resp.Body) in the HTTP response handling
(look for the resp variable in the function around tools_overlay.go) is
unbounded and can OOM; replace it with a limited read using io.LimitReader
(e.g., wrap resp.Body with io.LimitReader(resp.Body, maxResponseSize)) or use
io.CopyN into a buffer, and define a sensible maxResponseSize constant (for
example 1<<20 or configurable) and return an error if the response exceeds that
limit; ensure you still close resp.Body and propagate the error when the limit
is reached.
- Around line 171-180: The current fetch logic calls client.Do(req) and blindly
reads resp.Body into data and passes it to overlay.ParseOverlay, which yields
confusing parse errors for non-2xx responses; update the code after receiving
resp to check resp.StatusCode (e.g., if resp.StatusCode < 200 || resp.StatusCode
>= 300) and return a clear error containing the status code and status text
(optionally include a short snippet of resp.Body) instead of calling
overlay.ParseOverlay; keep the existing defer resp.Body.Close(), only read the
body for the error message when the status is non-2xx, and otherwise continue to
read and parse the body as before with overlay.ParseOverlay.
In `@internal/mcpserver/tools_walk_security.go`:
- Line 42: The handler currently returns an opaque any for its output; change
the signature of handleWalkSecurity from returning any to returning the concrete
type walkSecurityOutput (i.e., func handleWalkSecurity(... )
(*mcp.CallToolResult, walkSecurityOutput, error)), update the return statements
inside handleWalkSecurity to return a walkSecurityOutput value (constructed as
before), and update any local variables/zero-values accordingly so callers no
longer need to type-assert; keep the mcp.CallToolResult and error returns
unchanged.
Add a Model Context Protocol (MCP) server that exposes all oastools functionality as 15 MCP tools over stdio transport, enabling LLM agents to validate, fix, convert, diff, join, parse, overlay, generate, and walk OpenAPI Specification documents programmatically. ## Architecture New `internal/mcpserver` package with clean separation: - `server.go` — Entry point (`Run()`) and tool registration - `input.go` — Shared `specInput` type supporting file/URL/inline content - `tools_*.go` — One file per tool (or tool group), each with typed input/output structs and a handler function The server is invoked via `oastools mcp` subcommand. ## Tools (15 total) Core tools (9): - `validate` — Validate OAS against version schema - `parse` — Parse and summarize OAS structure - `fix` — Auto-fix common OAS issues (duplicate IDs, missing params, etc.) - `convert` — Convert between OAS versions (2.0, 3.0, 3.1) - `diff` — Compare two specs, detect breaking changes - `join` — Merge multiple specs with collision strategies - `overlay_apply` — Apply Overlay document to a spec - `overlay_validate` — Validate Overlay document structure - `generate` — Generate Go client/server code from OAS Walk tools (6): - `walk_operations` — Query operations by method/path/tag/operationId - `walk_schemas` — Query schemas by name/type/location - `walk_parameters` — Query parameters by location/name/path - `walk_responses` — Query responses by status code/path - `walk_security` — Query security schemes by name/type - `walk_paths` — Query path items by pattern ## Input model All tools accept specs via three modes through `specInput`: - `file` — Path to OAS file on disk - `url` — URL to fetch OAS document from - `content` — Inline OAS document (JSON or YAML) Tools use single (`spec`), dual (`base`+`revision`), or array (`specs[]`) input patterns depending on their needs. ## Testing - Unit tests for every tool handler (120+ test cases) - Integration tests using in-process MCP client-server pair via SDK transport, covering tool listing, successful calls, and error handling ## Claude Code Plugin Includes a `plugin/` directory with Claude Code plugin configuration: - `.claude-plugin/plugin.json` — Plugin manifest - `.mcp.json` — MCP server configuration - `CLAUDE.md` — Plugin-specific instructions - `skills/` — 5 guided workflow skills (validate, fix, explore, diff, generate) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
def556e to
2623dc2
Compare
Summary
internal/mcpserverpackage implementing a Model Context Protocol (MCP) server that exposes all oastools capabilities as structured tools: parse, validate, fix, convert, diff, join, overlay (apply & validate), generate, and 6 walker tools (paths, operations, schemas, parameters, responses, security)oastools mcpCLI subcommand for stdio-based MCP transportplugin/) with skills for common workflows (validate-spec, fix-spec, diff-specs, explore-api, generate-code)Highlights
makeSlice[T]generic helper that preservesomitemptyJSON semanticsTest plan
make check)go vet/ linter: 0 issuesoastools mcpstarts and responds to MCP tool calls via stdio🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com