Skip to content

feat: add MCP server support (Phase 1 — HTTP/SSE and basic stdio)#113

Merged
alexeykazakov merged 3 commits intocodeready-toolchain:masterfrom
alexeykazakov:feat/mcp-servers-phase1
May 9, 2026
Merged

feat: add MCP server support (Phase 1 — HTTP/SSE and basic stdio)#113
alexeykazakov merged 3 commits intocodeready-toolchain:masterfrom
alexeykazakov:feat/mcp-servers-phase1

Conversation

@alexeykazakov
Copy link
Copy Markdown
Contributor

@alexeykazakov alexeykazakov commented May 9, 2026

  • Add McpServerSpec type with CEL validation (command xor url)
  • Add spec.mcpServers map field to ClawSpec
  • Inject mcp.servers config into operator.json at reconciliation
  • Auto-extract HTTP MCP URL domains as proxy passthrough routes
  • Add McpServersConfigured status condition (set when non-empty)
  • Mark builtin domains in coveredDomains to prevent MCP duplicates

Summary by CodeRabbit

  • New Features

    • Added MCP server support to Claw: declare stdio or HTTP MCP servers, injected into operator configuration, and new proxy passthrough routes for HTTP MCP URLs
    • New status condition reflects whether MCP servers are configured
  • Tests

    • Added unit/integration/validation tests covering injection, proxy domain extraction, and schema validation
  • Documentation

    • Marked MCP support Phase 1 as complete

- Add McpServerSpec type with CEL validation (command xor url)
- Add spec.mcpServers map field to ClawSpec
- Inject mcp.servers config into operator.json at reconciliation
- Auto-extract HTTP MCP URL domains as proxy passthrough routes
- Add McpServersConfigured status condition (set when non-empty)
- Mark builtin domains in coveredDomains to prevent MCP duplicates

Signed-off-by: Alexey Kazakov <alkazako@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: 2a9d2de9-ab31-48d1-857a-3717d51e5d5e

📥 Commits

Reviewing files that changed from the base of the PR and between af709e6 and dafd024.

📒 Files selected for processing (4)
  • internal/controller/claw_mcp_test.go
  • internal/controller/claw_proxy.go
  • internal/controller/claw_proxy_test.go
  • internal/controller/claw_resource_controller.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • internal/controller/claw_proxy.go
  • internal/controller/claw_resource_controller.go
  • internal/controller/claw_mcp_test.go
  • internal/controller/claw_proxy_test.go
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: E2E Tests
  • GitHub Check: Unit Tests

Walkthrough

Adds MCP server support: new McpServerSpec and spec.mcpServers, CRD CEL validation, deepcopy support, injection of MCP configs into operator.json ConfigMap, proxy passthrough route generation from HTTP MCP URLs, reconciler status condition, and tests + docs update.

Changes

MCP Server Support Implementation

Layer / File(s) Summary
Type & Schema Definitions
api/v1alpha1/claw_types.go, config/crd/bases/claw.sandbox.redhat.com_claws.yaml
Added McpServerSpec type (command, args, url, transport, env), added McpServers map[string]McpServerSpec to ClawSpec, and CRD schema/CEL validation enforcing exactly one of command or url. Also added condition constant ConditionTypeMcpServersConfigured.
Generated Deepcopy Methods
api/v1alpha1/zz_generated.deepcopy.go
Autogenerated deepcopy methods for McpServerSpec and updated ClawSpec.DeepCopyInto to deep-copy McpServers.
MCP Configuration Injection
internal/controller/claw_mcp.go
New injectMcpServersIntoConfigMap reads data.operator.json from gateway ConfigMap, builds per-server JSON via buildMcpServerConfig, sets mcp.servers, marshals with indentation, and updates the ConfigMap; returns descriptive errors on failure.
Proxy Route Generation
internal/controller/claw_proxy.go
generateProxyConfig signature extended to accept mcpServers; added mcpPassthroughRoutes to parse HTTP MCP URLs into exact-match passthrough proxy routes (Injector: "none"), with ordering/coverage logic to avoid duplicates or shadowing.
Controller Reconciliation
internal/controller/claw_resource_controller.go
Reconciler injects MCP config into gateway ConfigMap during enrichment, passes instance.Spec.McpServers into generateProxyConfig, and sets/removes ConditionTypeMcpServersConfigured based on Spec.McpServers presence.
Tests & Integration
internal/controller/claw_mcp_test.go, internal/controller/claw_proxy_test.go, internal/controller/claw_channels_test.go
Added unit/integration/CEL validation tests for MCP injection and reconciler behavior, new TestMcpServerDomainExtraction, and updated existing tests to pass the new mcpServers argument to generateProxyConfig.
Documentation
docs/proposals/mcp-support-design.md
Marked Phase 1 ("HTTP/SSE and basic stdio MCP support") as DONE.

Sequence Diagram

sequenceDiagram
    actor User
    participant Controller as Claw Controller
    participant GatewayCM as Gateway ConfigMap
    participant ProxyCM as Proxy ConfigMap

    User->>Controller: Create/Update Claw with spec.mcpServers
    activate Controller
    Controller->>Controller: Detect non-empty McpServers\nSet McpServersConfigured condition

    Controller->>GatewayCM: Read operator.json
    activate GatewayCM
    GatewayCM-->>Controller: Return operator.json
    deactivate GatewayCM

    Controller->>Controller: Unmarshal JSON\nBuild MCP server configs
    Controller->>GatewayCM: Write updated operator.json with mcp.servers
    activate GatewayCM
    GatewayCM-->>Controller: ConfigMap updated
    deactivate GatewayCM

    Controller->>Controller: Generate proxy config including MCP servers\nExtract domains from HTTP MCP URLs
    Controller->>ProxyCM: Write proxy routes (includes MCP passthrough routes)
    activate ProxyCM
    ProxyCM-->>Controller: Proxy ConfigMap updated
    deactivate ProxyCM

    Controller-->>User: Reconciliation complete
    deactivate Controller
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested labels

feature, test, documentation

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding MCP server support for Phase 1 (HTTP/SSE and basic stdio), which is the primary feature across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation feature New feature or request test Work that adds, fixes, or maintains automated tests or coverage (unit, integration, e2e, flakiness) labels May 9, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/controller/claw_mcp_test.go`:
- Around line 85-109: The test and code currently persist plaintext MCP env
values into the operator.json ConfigMap (via
injectMcpServersIntoConfigMap/getMcpConfig), which leaks secrets; change
injectMcpServersIntoConfigMap to not write env map entries into the ConfigMap
but instead create or reference a Kubernetes Secret for each MCP server that has
env values and store only a secret reference (e.g., secret name and key or an
envRef field) in the ConfigMap entry for that server; update related helpers
(makeMcpConfigMap, testClawWithMcpServers, and the test expectations in this
test) so the ConfigMap no longer contains the plaintext env map and tests assert
a secretRef is present and env is not persisted in operator.json.

In `@internal/controller/claw_proxy.go`:
- Around line 235-256: mcpPassthroughRoutes currently treats coveredDomains as
exact matches only, allowing an MCP host like "api.example.com" to bypass a
credential entry for the suffix ".example.com"; update mcpPassthroughRoutes to
treat coveredDomains keys that begin with '.' as suffix rules by checking for
any coveredKey where strings.HasPrefix(coveredKey, ".") &&
strings.HasSuffix(domain, coveredKey[1:]) (or the reverse exact match), and skip
adding the proxyRoute if such a suffix match exists; keep adding exact domain
keys to coveredDomains as before and reference the mcpPassthroughRoutes,
coveredDomains and proxyRoute symbols when making this change.

In `@internal/controller/claw_resource_controller.go`:
- Around line 486-489: The code only sets the MCP condition to True when
instance.Spec.McpServers is present; update the full MCP condition lifecycle by
(1) ensuring any MCP injection failure paths call setCondition(instance,
clawv1alpha1.ConditionTypeMcpServersConfigured, metav1.ConditionFalse,
<appropriateReason>, <error message>) so failures are recorded, and (2) when
instance.Spec.McpServers is empty/removed, clear or mark the condition as
False/Removed (e.g., setCondition(..., metav1.ConditionFalse,
clawv1alpha1.ConditionReasonRemoved, "MCP servers removed") or remove the
condition) instead of leaving a stale True; reference the existing setCondition
function and ConditionTypeMcpServersConfigured/ConditionReasonConfigured symbols
to implement these status updates in the MCP injection and reconciliation
branches.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: a7071ca1-7e1a-455b-8ae0-87af5f447514

📥 Commits

Reviewing files that changed from the base of the PR and between 07cf88f and af709e6.

📒 Files selected for processing (10)
  • api/v1alpha1/claw_types.go
  • api/v1alpha1/zz_generated.deepcopy.go
  • config/crd/bases/claw.sandbox.redhat.com_claws.yaml
  • docs/proposals/mcp-support-design.md
  • internal/controller/claw_channels_test.go
  • internal/controller/claw_mcp.go
  • internal/controller/claw_mcp_test.go
  • internal/controller/claw_proxy.go
  • internal/controller/claw_proxy_test.go
  • internal/controller/claw_resource_controller.go
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: E2E Tests
  • GitHub Check: Unit Tests
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • internal/controller/claw_mcp.go
  • api/v1alpha1/zz_generated.deepcopy.go
  • internal/controller/claw_proxy.go
  • config/crd/bases/claw.sandbox.redhat.com_claws.yaml
  • docs/proposals/mcp-support-design.md
  • internal/controller/claw_resource_controller.go
  • internal/controller/claw_mcp_test.go
  • internal/controller/claw_channels_test.go
  • api/v1alpha1/claw_types.go
  • internal/controller/claw_proxy_test.go
🔇 Additional comments (5)
internal/controller/claw_channels_test.go (1)

464-517: Signature update in tests looks correct.

Passing nil for the new MCP argument keeps these channel-companion tests behaviorally equivalent while matching the updated API.

api/v1alpha1/zz_generated.deepcopy.go (1)

209-215: Deep-copy coverage for MCP fields looks correct.

McpServers, Args, and Env are copied into fresh allocations, preventing shared mutable state across object copies.

Also applies to: 322-347

api/v1alpha1/claw_types.go (1)

218-244: MCP API shape and validation are well-scoped for Phase 1.

The command/url XOR rules and map-based mcpServers addition are clean and consistent with the controller integration.

Also applies to: 260-263

internal/controller/claw_proxy_test.go (1)

1288-1420: Strong MCP domain-extraction regression coverage.

This test block meaningfully protects the new behavior (extraction, dedup against credentials/builtins, invalid URL handling, stdio exclusion, and case normalization).

internal/controller/claw_mcp_test.go (1)

393-466: CEL xor validation coverage is solid.

The negative/positive matrix for command vs url is clear and directly protects the CRD contract.

Comment thread internal/controller/claw_mcp_test.go
Comment thread internal/controller/claw_proxy.go
Comment thread internal/controller/claw_resource_controller.go
alexeykazakov and others added 2 commits May 9, 2026 12:36
- Add domainCovered() to check suffix-match credential domains
- Prevents MCP passthrough routes from shadowing auth injection
  when a suffix credential (e.g. ".googleapis.com") covers the domain

Signed-off-by: Alexey Kazakov <alkazako@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Remove McpServersConfigured condition when spec.mcpServers is
  empty/removed instead of leaving a stale True
- Add integration test verifying condition lifecycle across
  add-then-remove reconciliation cycles

Signed-off-by: Alexey Kazakov <alkazako@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@alexeykazakov alexeykazakov merged commit ff3d59d into codeready-toolchain:master May 9, 2026
4 checks passed
@alexeykazakov alexeykazakov deleted the feat/mcp-servers-phase1 branch May 9, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation feature New feature or request test Work that adds, fixes, or maintains automated tests or coverage (unit, integration, e2e, flakiness)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant