feat: migrate MCP to rmcp SDK with full protocol support#35
Merged
yishuiliunian merged 3 commits intomainfrom Mar 28, 2026
Merged
feat: migrate MCP to rmcp SDK with full protocol support#35yishuiliunian merged 3 commits intomainfrom
yishuiliunian merged 3 commits intomainfrom
Conversation
Replace hand-written JSON-RPC MCP client (~526 lines) with rmcp 1.3 SDK. Transport: - Stdio (TokioChildProcess) + Streamable HTTP with custom headers - OAuth browser-based auth flow with token persistence (~/.loopal/oauth/) - Auto-detect auth errors on HTTP, fallback to OAuth transparently - Child process stderr forwarded to tracing logs Connection lifecycle: - McpConnection state machine (Disconnected → Connecting → Connected/Failed) - Capability-guarded discovery (only query tools/resources/prompts if advertised) - Concurrent server startup via futures::join_all - HTTP reconnect on TransportClosed (single attempt, no lock contention) - Reconnect guard prevents redundant concurrent reconnection Protocol features: - Tools: typed CallToolResult (no serialize-then-parse roundtrip) - Resources: cached at startup, text/blob variants, injected into system prompt - Prompts: cached at startup, injected into system prompt - Server instructions: extracted from initialize handshake, injected into system prompt - Sampling: SamplingCallback trait + McpSamplingAdapter bridging MCP→Provider - All 5 content types handled (text/image/audio/resource/resource_link) Config: - McpServerConfig: struct → tagged enum (Stdio/StreamableHttp) - Per-entry deserialization (one bad config no longer kills all servers) - reqwest unified to 0.13 (matches rmcp) Safety: - MCP tools cannot shadow built-in tools (conflict detection + skip) - tool_map synced with tool_registry on skip - Read lock for normal tool calls, write lock only for reconnect Tests: 35 MCP tests (client e2e, connection lifecycle, reconnect policy, config serde, OAuth callback parsing + percent-decode)
webpki-root-certs (transitive dep via rmcp) uses CDLA-Permissive-2.0. rustls-webpki 0.103.9 has RUSTSEC-2026-0049, awaiting upstream fix.
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.
Summary
Stdio/StreamableHttp) with per-entry fault-tolerant deserializationCallToolResult(zero serde roundtrip)Changes
New files (12):
loopal-mcp/src/handler.rs— rmcp ClientHandler (sampling, notifications)loopal-mcp/src/client.rs— McpClient wrapping RunningService with timeoutloopal-mcp/src/transport.rs— stdio/HTTP connect factories, stderr drainloopal-mcp/src/connection.rs— Connection state machine + capability discoveryloopal-mcp/src/manager_query.rs— Query/lifecycle methods (reconnect, restart)loopal-mcp/src/reconnect.rs— Exponential backoff policyloopal-mcp/src/types.rs— ConnectionStatus, McpResource, McpPromptloopal-mcp/src/oauth/— OAuth flow, callback server, credential storeloopal-kernel/src/sampling.rs— McpSamplingAdapter bridging MCP→Providerloopal-mcp/tests/suite/— 35 integration testsModified files:
Cargo.toml— rmcp 1.3, reqwest 0.13loopal-config/settings.rs— McpServerConfig tagged enumloopal-config/loader.rs— Per-entry MCP config deserializationloopal-kernel/kernel.rs— MCP tool conflict detection, resource/prompt cachingloopal-agent-server/params.rs— Sampling wiringloopal-agent-server/agent_setup.rs— System prompt injection (instructions, resources, prompts)Test plan
cargo test --workspace— 255 tests passcargo clippy --workspace --tests— zero warnings