Conversation
openapi-to-mcp turns every operation of an OpenAPI document into a tool, and a route that serves it hands the whole set to whoever connects. That is rarely what a given client should get: a read-only agent has no business calling deletePet, and it should not even be told the tool exists. mcp-tools-acl runs at priority 539, below openapi-to-mcp (540) and below the auth plugins, so the consumer is known by the time a rule is matched. It refuses a tools/call for a tool the matched rule does not allow, and removes the same tools from the tools/list answer -- over both transports, which means filtering the JSON body of a streamable_http answer and the SSE events of an sse one, buffering an incomplete event across body_filter chunks. Rules are picked per request with lua-resty-expr, so one route can serve a different set of tools to each consumer. A rule without an expression always matches; when no rule matches, nothing is enforced. openapi-to-mcp gains one line, `ctx.openapi_to_mcp_active = true`. The ACL plugin has no other way to tell an MCP conversation from an ordinary route -- the request body alone looks the same -- and on a route without openapi-to-mcp it now stands aside with a warning instead of trying to police plain JSON. The plugin is the one API7 Enterprise has been shipping; this is that code, with its tests rewritten against the in-process openapi-to-mcp implementation this repository has rather than the sidecar the enterprise build used.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
openapi-to-mcpturns every operation of an OpenAPI document into a tool, and a route serving it hands the whole set to whoever connects. That is rarely what a given client should get: a read-only agent has no business callingdeletePet, and it should not even be told the tool exists.mcp-tools-aclnarrows that set per consumer. It runs at priority 539 — belowopenapi-to-mcp(540) and below the auth plugins, so the consumer is already known when a rule is matched. It:tools/callfor a tool the matched rule does not allow, so the API is never called;tools/listanswer, over both transports — the JSON body of astreamable_httpanswer, and the SSE events of ansseone, buffering an incomplete event acrossbody_filterchunks.Rules are selected per request with lua-resty-expr, so one route can serve a different tool set to each consumer. A rule without an expression always matches; when no rule matches, nothing is enforced.
{ "mcp-tools-acl": { "rules": [ { "expr": [["consumer_name", "==", "reader"]], "allow_tools": ["getPetById"] }, { "deny_tools": ["deletePet"], "rejected_msg": "deletePet is not allowed" } ] } }openapi-to-mcpgains one line,ctx.openapi_to_mcp_active = true. The ACL plugin has no other way to tell an MCP conversation from an ordinary route — the request body alone looks the same — and on a route withoutopenapi-to-mcpit now stands aside with a warning rather than trying to police plain JSON.This is the plugin API7 Enterprise has been shipping, contributed here unchanged. Its tests are new: the enterprise suite drives the Node sidecar that build used, which says nothing about the in-process implementation this repository has, so the suite was rewritten against
lib.openapi_to_mcp_fixture.Which issue(s) this PR fixes
Checklist