Repository navigation
OSPP2: Add local and federated MCP resources - #7669
Conversation
Aias00
left a comment
There was a problem hiding this comment.
Review: OSPP2: Add local and federated MCP resources
Verdict: APPROVE
This is a large but well-engineered feature addition that exposes MCP resources/list, resources/templates/list and resources/read through the existing Agent Gateway entry point, with an independent, deny-by-default authorization model. I read the core new classes, traced the full request path, ran the new test classes locally, and reviewed CI.
Security model (the strongest part of this PR)
The design consistently treats the resource URI as an identifier, never a destination, and backs it with multiple independent guards:
- No caller-selected endpoints.
RemoteResourceDirectory.readresolves the requested URI to a registeredEntry, then calls that entry's fixedTarget.readscallback (bound to the configured server). The URI is never used to open a connection or read a file. The remote server endpoint itself is constrained byManagedRemoteMcpCatalog.allowedEndpoints+RemoteTransportPolicy.endpoint, so even the remote hop is allowlisted. - Canonical, fixed-scheme identifiers.
AgentResourceNamespace.exposebuildsmcp-resource://<server>/<encoded>whereserveris validated[A-Za-z0-9_-]{1,48}andoriginalis percent-encoded viaUriUtils.encode;original()requires a round-trip-equal canonical form, rejecting encoding tricks.AgentResourceContentfurther requires the URI to beURI.create(...).isAbsolute()with no userinfo and no whitespace/control chars (nouser:pass@host, nofile:smuggling) — and explicitly "is never dereferenced". - Independent, intersected authorization.
AgentMcpExecutionContextcomputesallowedResources = ruleResources ∩ resourceGrantsandallowedTools = ruleTools ∩ securityGrants.AgentMcpResourceDispatcherandRemoteResourceDirectoryboth re-checkallowedResources.contains(name)anddefinition.matches(uri); ambiguous matches (size != 1) are rejected with 403. Admin rejects wildcard*and non-unique/blank grant values (AgentGatewayMcpConfig.strings), and theresourcescapability is only advertised whenruleResourcesis non-empty. - Bounded everywhere. Local registry ≤ 16 providers; remote directory ≤ 16 entries; pagination capped at 4 pages with cycle detection; contents arrays capped at 16; URI/description ≤ 4096; config ≤ 16384 bytes with queue backpressure.
AgentResourceContent.rewritealso verifies each returned content's URI equals the requested original (confused-deputy protection) and transforms it to the exposed identifier. - Strict request parsing.
AgentMcpRequestParserenforces JSON-RPC 2.0 shape, strict duplicate detection, max nesting depth 64, trailing-token rejection, strict UTF-8, body byte limit, and verifies mirroredMcp-Name/Mcp-Method/MCP-Protocol-Versionheaders match the body (anti-header-injection).resources/readURI is validated as an absolute identifier before dispatch.
Correctness & lifecycle
- Hot updates preserve in-flight reads:
ManagedRemoteMcpCataloguses a single owned control-plane subscription, revision fencing, and a request-ownedSnapshot;closeAsyncdrains before exit.AgentMcpDispatcher.dispatchis request-local, no retry, and mapsSecurityException/CatalogUnavailableExceptionto structured 403/503 errors. - Remote resource discovery is disabled by default (
resourcesEnabledflows intoRemoteCatalogLifecycle), exactly as documented.
Verification
- Local:
mvn -pl shenyu-plugin/shenyu-plugin-agent-gateway -am testfor the resource-related suites → 170 tests, 0 failures, 0 errors (AgentMcpResourceIntegrationTest,RemoteResourceDirectoryTest,RemoteResourceLifecycleTest,RemoteResourceNetworkTest,AgentResourceContentTest,AgentResourceRegistryTest,AgentMcpRequestParserTest,AgentMcpHttpHandlerTest, plus existing suites). BUILD SUCCESS. - CI:
pr_build,Analyze (java),CodeQL,list-contract,native-sql(all 5 matrix entries),sql-matrix,scope,check-license-header,rat_check, and the storage e2e matrix (h2/mysql/opengauss/postgres) all pass. The only reds are thee2eaggregate and severale2e-case*sync-compose/logging-rocketmqjobs, which are orthogonal to this PR (Agent Gateway MCP resources; remote discovery off by default) and are known-infra-flaky — thee2e-http-sync-composejob log I inspected actually shows BUILD SUCCESS. None of the failing cases exercise agent-gateway resource code.
Non-blocking suggestions
- Minor dead call:
AgentResourceRegistry.read(line ~104) callsAgentResourceContent.text(uri, null, "")and discards the result — it serves only as a URI-validation side effect. Harmless, but a namedvalidateUrihelper would read more clearly. - Large feature surface: at +2346/−28 this is a substantial addition; the per-class encapsulation (registry / directory / namespace / content / identity) is clean and test-covered, so I see no structural concern, only a note that ongoing hardening (e.g. further e2e coverage for the federated read path) can follow as separate PRs.
No changes requested. The implementation is careful, security-conscious, and well tested.
Aias00
left a comment
There was a problem hiding this comment.
Re-approving after the master merge dismissed the previous approval.
I checked the update rather than re-reading the whole PR: the only new commit is a merge of master, and every file this PR introduces is byte-identical to the version I approved (compared the blob shas at 71fe4acf/d80bda94/c831b431/58f16918 against the current head). The files that did change are the ones master touched in parallel — RELEASE-NOTES.md, the other agent-gateway sources, and AbstractShenyuPluginTest's setLogged rename — i.e. the merge brought them in, it did not rewrite this PR's content.
CI is green on the new head (52 pass / 3 skipping, no failures). No further changes requested from me.
|
This branch now has merge conflicts with Could you rebase onto the latest |
…resources # Conflicts: # RELEASE-NOTES.md # shenyu-admin/src/test/java/org/apache/shenyu/admin/validation/validator/AgentGatewayRuleHandleValidatorTest.java # shenyu-common/src/main/java/org/apache/shenyu/common/dto/AgentGatewayMcpConfig.java # shenyu-plugin/shenyu-plugin-agent-gateway/README.md # shenyu-plugin/shenyu-plugin-agent-gateway/src/main/java/org/apache/shenyu/plugin/agent/gateway/protocol/AgentMcpDispatcher.java # shenyu-plugin/shenyu-plugin-agent-gateway/src/main/java/org/apache/shenyu/plugin/agent/gateway/protocol/AgentMcpExecutionContext.java # shenyu-plugin/shenyu-plugin-agent-gateway/src/main/java/org/apache/shenyu/plugin/agent/gateway/protocol/AgentMcpHttpHandler.java # shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-agent-gateway/src/main/java/org/apache/shenyu/springboot/starter/plugin/agent/gateway/AgentGatewayPluginConfiguration.java
Aias00
left a comment
There was a problem hiding this comment.
Thanks for this contribution. The MCP resources support is cleanly layered: a new resource package (AgentResourceRegistry, AgentResourceDefinition, AgentResourceInvocation, AgentResourceContent, AgentResourceNamespace, AgentResourceProvider), an AgentMcpResourceDispatcher that maps resources/* MCP methods, capability advertisement gated on ruleResources being non-empty, and the remote-catalog path also validates resources before dispatch. The dispatcher routing (validate -> resources/ branch before route) reads correctly and the SecurityException -> 403 mapping is appropriate.
Notes (non-blocking):
- This PR and #8095 both modify
AgentMcpDispatcher.java(resource handling / admission). Please coordinate the merge order and rebase so the two do not collide on the dispatcher. - Consider adding a unit test that exercises
AgentMcpResourceDispatcher.dispatchwith an allowed vs denied resource to lock in the 403 path.
Approving. CI is green.
Background
The Agent Gateway currently aggregates MCP tools, but cannot expose resources from local providers or remote MCP servers through the same request-scoped entry. This draft adds the resources part of the OSPP scope without expanding the merged tools-only PR or depending on other unmerged PRs.
Changes
resources/list,resources/templates/listandresources/readfor explicit local providers and managed remote servers;resourceGrantswith rule-levelallowedResources, independently of tool permissions. Admin validates resource grants before saving;server.nameand expose reversiblemcp-resource://server/...identifiers. Resource URIs are identifiers, not caller-selected HTTP or file destinations;shenyu.plugins.agent.gateway.aggregation.resources-enabled;Verification
clean verifyacross Admin, Agent Gateway, Starter and dependencies: 654 tests / 35 suites, 0 failures, errors or skipped tests; all 38 reactor modules passed Checkstyle and RAT;clean verifyacross Agent Gateway, Starter and dependencies: 620 tests / 33 suites, 0 failures, errors or skipped tests; all 15 reactor modules passed Checkstyle and RAT. Admin is not included in this run;git diff --checkpassed. A subsequent README clarification changed documentation only.