feat: Phase 2 — OAuth2 refresh, SMTP transport, persistent MCP state - #13
Merged
Conversation
… path params
Add complete OAuth2/password-grant token refresh with caching to hub-auth.
Wire all 7 auth types (Bearer, Basic, Header, Custom, OAuth2, PasswordGrant,
HMAC) through dispatch with resolved headers and base URLs.
Add SMTP email transport via lettre: SmtpConfig, MailClient::send() with
multipart/alternative support, TLS/STARTTLS, and full to/cc/bcc/subject/
body/body_html handling. Register email.send operation with JSON Schema.
Implement path parameter substitution for URL templates ({param} and {+param}
RFC 6570 reserved expansion), with automatic removal of consumed params and
userId→me defaulting. Detect absolute URLs from Discovery specs to prevent
double base-URL prepend.
Make MCP server stateful: Arc<Dispatcher/AuthStore/Policy/NetClient> built
once at startup instead of per-request reconstruction.
152 operations total (79 Gmail, 72 Hetzner, 1 email.send), 26 tests passing,
clean clippy and fmt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0176k7T6i3B197hY6TqPdWqj
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176k7T6i3B197hY6TqPdWqj
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176k7T6i3B197hY6TqPdWqj
The Dependabot merge left uv.lock pinned to mcp 1.29.0 while pyproject.toml requires 2.0.0. CI uses --frozen so it installed the stale version, breaking test_mcp_protocol.py imports. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176k7T6i3B197hY6TqPdWqj
mcp 2.0 removed create_connected_server_and_client_session. Use the new InMemoryTransport + ClientSession pattern with explicit initialize(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176k7T6i3B197hY6TqPdWqj
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176k7T6i3B197hY6TqPdWqj
mcp 2.0.0 removed the Server decorator API (list_tools/call_tool) that hub/mcp_server.py relies on. Since the Python server is being replaced by the Rust implementation, pin to the last compatible version rather than porting the legacy code to the new API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176k7T6i3B197hY6TqPdWqj
CodeWithJuber
marked this pull request as ready for review
August 12, 2026 03:37
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
Phase 2 of the Rust rebuild adds the execution layer that turns the Phase 1 scaffold into a working actuator: OAuth2 token refresh, SMTP email transport, path parameter substitution, persistent MCP server state, and full auth-type wiring across all 7 credential patterns.
What changed:
OAuth2 / password-grant token refresh (
hub-auth): Asyncresolve()method handles Bearer, Basic, Header, Custom, OAuth2, PasswordGrant, and HMAC auth types. Token cache withArc<RwLock>for thread-safe async refresh. Form-encoded POST to token endpoints with 60s early-refresh buffer.SMTP email transport (
hub-net/mail.rs):MailClient::send()via lettre with multipart/alternative (text + HTML), TLS/STARTTLS, full to/cc/bcc support.email.sendoperation registered with JSON Schema at startup.Path parameter substitution (
hub-core/dispatch.rs): Replaces{param}and{+param}(RFC 6570 reserved expansion) in URL templates, removes consumed params from args, defaults{userId}tome. Detects absolute URLs from Discovery specs to prevent double base-URL prepend.Persistent MCP state (
connector-hub/mcp.rs):Arc<Dispatcher/AuthStore/Policy/NetClient>built once at server startup instead of reconstructed per request.Transport routing:
Transportenum (Http/Smtp) on operations; dispatcher routes SMTP operations toexecute_smtp()bypassing the HTTP path entirely.152 operations total (79 Gmail, 72 Hetzner, 1 email.send), 26 tests passing.
Validation
Security and operations
.envfiles are included.Generated by Claude Code