feat: add MCP server config, session labels, and HTTP tools#695
feat: add MCP server config, session labels, and HTTP tools#695jeremyeder wants to merge 1 commit intoambient-code:mainfrom
Conversation
This comment has been minimized.
This comment has been minimized.
Add workspace-scoped MCP server configuration with CRUD, test connection, and import/export (Claude Desktop and OpenCode formats). Add session label editor to create-session dialog with label filtering in sessions list. Add HTTP tools management tab. Inject MCP config into session pods via operator ConfigMap mount. Includes security hardening (arg/env validation, SecurityContext on test pods), structured proxy error logging, and deduplication of integration status cards in the create-session dialog. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Code ReviewSummaryThis PR adds MCP server configuration management, session label support, and HTTP tool management — a substantial feature set (~1937 additions). The core architecture is sound, but there are several security and pattern-adherence issues worth addressing before merge. Issues by Severity🔴 Critical Issues1. Sensitive values stored in plain ConfigMap ( MCP server environment variables and HTTP tool headers (which typically include API keys, auth tokens, and credentials) are stored unencrypted in a // mcp_config.go — credentials land in a ConfigMap, not a Secret
cm.Data[key] = string(configJSON)
k8sClient.CoreV1().ConfigMaps(projectName).Update(...)MCP env vars like 2. Write operations bypass the validate-then-escalate pattern ( Both files use the user-scoped token (
// updateConfigMapKey — user token used directly for ConfigMap writes
k8sClient, _ := GetK8sClientsForRequest(c)
k8sClient.CoreV1().ConfigMaps(projectName).Create(...) // should be K8sClient (service account)// TestMcpServer — user token used directly for Pod creation
k8sClient, _ := GetK8sClientsForRequest(c)
k8sClient.CoreV1().Pods(projectName).Create(...) // should be K8sClient (service account)See 3. Internal K8s error exposed to user ( c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to create test pod: %v", err)})This returns raw K8s API error details to the client. Per the error handling pattern: log internally with full details, return a generic user message: log.Printf("Failed to create MCP test pod in %s: %v", projectName, err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create test pod"})🟡 Major Issues4. No explicit RBAC check before pod creation in The handler validates the command allowlist and env blocklist correctly, but never asks K8s whether the authenticated user has permission to trigger MCP tests. If a user lacks the required permission they receive an opaque K8s error (leaking internals). An explicit 5. "docker": true,
"podman": true,These commands cannot realistically function as MCP stdio servers, and having them in the allowlist adds unnecessary surface area. Consider removing them unless there is a concrete validated use-case. 6. MCP mount path may be incorrect ( MountPath: "/home/user/.mcp.json",
SubPath: "mcp.json",Claude Code reads MCP configuration from 7. config.K8sClient.CoreV1().ConfigMaps(sessionNamespace).Get(context.TODO(), ...)
🔵 Minor Issues8. Untyped JSON round-trip in Go ( Config is parsed into 9. c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})For consistency with project error handling patterns, return a fixed string like 10. Comma-separated args don't handle embedded commas ( const parsedArgs = args.split(",").map((a) => a.trim()).filter(Boolean);Arguments containing commas would be split incorrectly. Consider a tag/pill input similar to 11. Label selector built without client-side validation ( const labelSelector = Object.entries(labelFilters)
.map(([k, v]) => `${k}=${v}`)
.join(',') || undefined;Special characters in filter values produce an invalid selector that K8s rejects with a generic failure in the UI. Adding client-side validation of K8s label key/value format would give a better UX. 12. Missing The 13. queryKey: [...sessionKeys.list(projectName, params), labelSelector ?? ""] as const,
Positive Highlights
Recommendations
🤖 Generated with Claude Code 🔍 View AI decision process (logs available for 90 days) 📋 View memory system files loaded (click to expand)What Amber Loaded for Code ReviewAmber automatically loaded these repository standards from the memory system:
Impact: This review used your repository's specific code quality standards, security patterns, and best practices from the memory system (PRs #359, #360) - not just generic code review guidelines. |
|
Superseded by #697 (labels) and upcoming MCP-only PR. Splitting for easier review. |
Summary
Rebased and refined version of #629 with all review feedback addressed.
Review feedback addressed
Refinements
Closes #629
Test plan
🤖 Generated with Claude Code