feat(mcpServer): probe_mcp_server looks at a URL before it is registered (CLEAN-78) - #105
Merged
Merged
Conversation
maksymhryzodub-prog
added this pull request to stack #107
September 23, 2026 12:16
…red (CLEAN-78) The registry tools from CLEAN-109 register whatever they are told; nothing could look at an endpoint first. Pasting https://mcp.silpo.ua/mcp into the Rancher chat meant the person had to know it speaks streamable HTTP and wants OAuth. Now the operator tool probe_mcp_server({ url } | { id }) reports the transport that answered, whether a credential is required and which authType to register with (oauth when the origin publishes RFC 8414 metadata next to a 401, bearer otherwise, none when the handshake went through), the OAuth capabilities (dynamic registration, PKCE, scopes), the server name and its tool list when it could be asked, and one line on what to call next. McpProbeService holds the decisions (streamable HTTP first, SSE only on a 404/405, a refusal is an answer) behind IMcpProbeConnector; the data-layer connector uses the MCP SDK's own client transports the way the runtime does, so "reachable" here and "the agent can connect" mean the same thing. A pasted url passes the A2A public-address guard; a registered row (by id) skips it, because the built-ins live on cluster hosts. Results never carry a credential. Admin: the form gains the oauth auth type (no value field, a note on how the connect happens), the header label now shows the `Header-Name: value` form the runtime actually parses instead of a JSON spelling it never read, and the MCP servers page points at the Rancher chat and its Tools panel. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KtJu4QscRKbDdj8WLL9aVL
maksymhryzodub-prog
force-pushed
the
feat/CLEAN-78-mcp-probe
branch
from
September 24, 2026 11:44
89e0286 to
cd7cbd7
Compare
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.
Jira: CLEAN-78
Why
CLEAN-109 gave the Rancher agent the MCP registry tools, but nothing could look at an endpoint first: to register
https://mcp.silpo.ua/mcpthe person had to know it speaks streamable HTTP and wants OAuth. The admin form also still had nooauthoption.What
API —
probe_mcp_server({ url } | { id }), operator-only like the rest of the registry (api/src/slices/mcpServer/mcpProbe.tool.ts):McpProbeServiceholds the decisions: OAuth metadata on the origin first, then a handshake over streamable HTTP, SSE only when the endpoint answers 404/405; a 401 next to RFC 8414 metadata reads asauthType: oauth(with dynamic-registration / PKCE / scopes), a 401 without it asbearer, a clean handshake asnoneplus the tool list and server name. Onenextline tells the model what to call.McpProbeConnectoris the SDK half (same client transports the runtime uses), behind an interface so the service is unit-tested without a socket.tools/listinto the chat — exactly what an SSRF wants); a registered row by id skips it, since built-ins live on cluster hosts. Results never carry a credential; a stored bearer/header is sent and only its verdict comes back. Both spellings of aheadercredential are accepted (Header-Name: valueas the runtime parses, and the JSON the form used to show).specs/016-agent-tool-parity/contracts/tools.md; 21 new tests.Admin —
oauthin the auth-type select (no value field, a note on how the connect happens), the header label now shows theHeader-Name: valueform the runtime actually reads, and the MCP servers page points at the Rancher chat and its Tools panel. Twin-console check:app/has nomcpServerslice, nothing to mirror.Verification
api: jest onmcpServer+mcp→ 15 suites, 154 tests green;tsc --noEmitclean; eslint clean on the new files.admin:npx nuxt typecheckclean.transport: streamableHttp,authType: oauth,oauth.dynamicRegistration: true,tools: null, and anextline pointing atregister_mcp_server+start_mcp_oauth.Stacked on top: #CLEAN-80 PR (per-user tokens) targets this branch.
Live test (2026-09-23, Rancher chat tools over the ranch MCP endpoint, real Silpo)
probe_mcp_server { url: https://mcp.silpo.ua/mcp }→authType: oauth, dynamic registration + PKCE detected,tools: null,nextpointing atregister_mcp_server/start_mcp_oauth.register_mcp_server→set_template_mcps→list_agent_mcpsworked as a chain for Silpo.🤖 Generated with Claude Code
https://claude.ai/code/session_01KtJu4QscRKbDdj8WLL9aVL