Repository navigation
feat: MCP server integrations — connect Atmos to external MCP servers - #2267
Conversation
…ase 1) Add the ability to configure, manage, and consume external MCP servers from within Atmos. This enables using existing MCP servers from the ecosystem (AWS, GCP, Azure) instead of reimplementing their functionality. Schema: - Add MCPIntegrationConfig type to pkg/schema/mcp.go with command, args, env, auto_start, timeout, and description fields - Extend MCPSettings with Integrations map Client package (pkg/mcp/client/): - config.go: ParseConfig with validation and timeout parsing - session.go: Session lifecycle (Start/Stop/CallTool/Ping) using the Go MCP SDK's Client, CommandTransport, and ClientSession - manager.go: Manager for multiple sessions with Test/List/Start/Stop - bridge.go: BridgedTool wrapping external MCP tools with namespaced names (server.tool_name) for the Atmos tool registry CLI commands (cmd/mcp/): - list.go: atmos mcp list — show configured integrations - tools.go: atmos mcp tools <name> — connect and list tools - test_cmd.go: atmos mcp test <name> — verify connectivity Error sentinels: - ErrMCPIntegrationNotFound, NotRunning, StartFailed, CommandEmpty, InvalidTimeout Tests: 34 unit tests at 73% coverage (uncovered paths require real MCP server subprocess). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Mark Phase 1 as SHIPPED with implementation details table - Add shipped files, line counts, test coverage, and design decisions - Update config path from ai.mcp.integrations to mcp.integrations (matches actual implementation — MCP is a top-level config section) - Fix all YAML examples to use correct config paths - Mark BridgedTool and namespaced tool names as done in Phase 2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bridge external MCP server tools into the Atmos AI tool registry so they appear alongside native Atmos tools in conversations. Registration (pkg/mcp/client/register.go): - RegisterMCPTools starts configured integrations, bridges their tools into the registry, returns Manager for cleanup - Failed integrations log warnings but don't block other tools Bridge updates (pkg/mcp/client/bridge.go): - BridgedTool implements tools.Tool interface (compile-time verified) - Execute returns *tools.Result with success/error/output - Parameters() extracts from MCP InputSchema JSON Schema - mapJSONSchemaType converts JSON Schema types to Atmos ParamType AI initialization (cmd/ai/init.go): - Return aiToolsResult struct (avoids 4-return-value lint error) - Calls RegisterMCPTools after native tool registration - MCP integrations are best-effort (warn on failure, continue) Caller updates: - cmd/ai/chat.go: defer MCPMgr.StopAll() for subprocess cleanup - cmd/ai/exec.go: defer MCPMgr.StopAll() for subprocess cleanup - cmd/ai/init_test.go: use aiToolsResult struct Tests: 45 unit tests for MCP client package. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Mark Phase 2 as SHIPPED with implementation details table - Document shipped items: tool bridge, AI chat/exec integration, graceful shutdown, interface compliance, parameter extraction - Document key design decisions (best-effort, aiToolsResult struct, compile-time interface check, JSON Schema type mapping) - Note remaining items (lazy init, --ai flag tool integration) - Update status to Phase 1 + Phase 2 Implemented, version 2.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…se 3) New CLI commands for managing external MCP integrations: - atmos mcp add <name> — add integration to atmos.yaml with flags for --command, --args, --env, --description. Uses StandardParser. - atmos mcp remove <name> — remove integration from atmos.yaml. - atmos mcp status — start all integrations, display connection status. - atmos mcp restart <name> — stop and restart an integration. Error sentinels: - ErrMCPIntegrationAlreadyExists added to errors/errors.go Tests: 7 tests for config file operations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ase 4) Add Atmos Auth credential injection for external MCP servers. When auth_identity is configured on an integration, credentials are automatically injected into the subprocess environment. Schema: - Add auth_identity field to MCPIntegrationConfig and ParsedConfig Session options pattern: - StartOption functional option for extending Start behavior - WithAuthManager(provider) injects credentials when auth_identity set - AuthEnvProvider interface for testability (subset of auth.AuthManager) - Extract prepareEnv and connectAndDiscover helpers from Start Manager/Register updates: - Start and Test accept variadic StartOption parameters - RegisterMCPTools accepts optional AuthEnvProvider PRD update: - Mark Phase 3 as SHIPPED with implementation details - Move toolchain/template items to Phase 4 - Update status to Phases 1-3 Implemented, version 3.0 Tests: 8 new auth tests covering credential injection, passthrough, nil provider, error handling, and config parsing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename the MCP configuration path from mcp.integrations to mcp.servers to align with the standard MCP server configuration format used by Claude Code (mcpServers), Codex CLI (mcp_servers), and Gemini CLI. The core fields (command, args, env) now match the standard format. Atmos-specific extensions (description, auto_start, timeout, auth_identity) are clearly separated in the schema comments. Schema: - MCPIntegrationConfig → MCPServerConfig - MCPSettings.Integrations → MCPSettings.Servers - YAML path: mcp.servers (was mcp.integrations) Error sentinels: - ErrMCPIntegration* → ErrMCPServer* (5 errors renamed) - Fix over-renamed auth integration errors restored All code, tests, CLI commands, and PRD docs updated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…derations - Remove stack-level MCP server overrides from Phase 4 and all YAML examples - Remove composite MCP server from Phase 4 remaining items - Both moved to Future Considerations section - Remove per-stack auth override examples - Update comparison table (remove stack overrides scope) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resolve MCP server command binaries via the Atmos toolchain before spawning subprocesses. This ensures prerequisites like uvx/npx are available even if not on the system PATH. New start option: - WithToolchain(resolver) resolves command binaries and prepends toolchain PATH to subprocess environment - ToolchainResolver interface (Resolve + EnvVars) matches ToolchainEnvironment for zero-adapter integration Registration: - RegisterMCPTools accepts optional ToolchainResolver parameter - Extract registerMCPServerTools helper from initializeAIToolsAndExecutor YAML functions note: - !env, !exec, !repo-root, !cwd already work in atmos.yaml env values via preprocessAtmosYamlFunc — no code needed Tests: 3 new toolchain tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ations - Phase 4 marked as SHIPPED (auth, toolchain, YAML functions) - Move connection pooling, tools/list_changed, server registry to Future Considerations alongside stack overrides and composite server - Update status to Complete — All 4 Phases Shipped, version 5.0 - Fix comparison table transport column Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Client package (75.1% → 79.3%): - Add TestPrepareEnv (no opts, failing opt, success opt) - Add TestSession_Start_WithOpts (verify opts called before failure) - Add TestManager_Start_WithOpts (opts passed through) - Add TestManager_Test_WithFailedStart (error propagation) - Add TestBridgedTool_Parameters_NonMapProperty (skip non-map) - Add TestBridgedTool_Parameters_NoTypeField (default to string) Command package (44.1% → 48.0%): - Add TestPrintTestResult (all success, failed start, no tools) Remaining uncovered paths all require a real MCP server subprocess (connectAndDiscover success, Stop with live session, Execute/CallTool/ Ping with live connection). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reorganize cmd/mcp/ into subpackages for clear separation between Atmos MCP server commands and external MCP client commands. CLI surface is unchanged — all commands remain under 'atmos mcp <cmd>'. Structure: cmd/mcp/ ├── mcp.go # CommandProvider, blank imports subpackages ├── mcpcmd/cmd.go # Shared McpCmd variable (breaks import cycle) ├── server/start.go # atmos mcp start └── client/ # add, list, remove, restart, status, test, tools Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add markdown files for Long descriptions embedded via //go:embed, matching the pattern used by cmd/ai/markdown/. 9 markdown files covering root, server start, and all 7 client commands. Each includes usage examples, expected output, and config snippets. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…gents Error handling: - Add 4 sentinel errors, replace dynamic errors with sentinel wrapping Performance tracking: - Add perf.Track to all exported MCP functions and command handlers UI output: - Replace fmt.Fprintln(os.Stdout) with ui.Info() for user messages Cross-platform: - Replace string concatenation with filepath.Join in findAtmosYAML Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t flags Tables (tui-expert/tui-list): - Replace tabwriter.NewWriter(os.Stdout) with theme.CreateMinimalTable() in list.go, tools.go, and status.go for themed table rendering Flags (flag-handler): - Replace direct cmd.Flags().String/Int() in start.go init() with flags.NewStandardParser (WithStringFlag, WithIntFlag) - Register parser and bind to Viper for env var support - getTransportConfig reads from Cobra flags (Viper-bound via parser) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create examples/mcp/ demonstrating how to configure and use external MCP servers from the AWS ecosystem with Atmos. Configured servers: - aws-api: Direct AWS CLI access with safety controls (READ_OPERATIONS_ONLY) - aws-docs: AWS documentation search (no credentials needed) - aws-knowledge: Managed remote AWS knowledge base (no credentials needed) - aws-pricing: Real-time pricing and cost analysis (free API) - aws-security: Well-Architected security posture assessment - aws-diagram: Architecture diagram generation (deprecated) README covers: - Quick start with atmos mcp list/test/tools commands - CLI command reference for all 8 mcp subcommands - AI chat integration with example prompts for each server - YAML functions in env vars (!env, !exec, !repo-root) - Atmos Auth integration with auth_identity credential injection - Atmos Toolchain integration for auto-installing uvx - Detailed server descriptions with IAM requirements Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uncomment toolchain section to auto-install uv (provides uvx) before MCP servers start. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clarify that uv is auto-installed by toolchain, list credential options (AWS CLI vs Atmos Auth), add brew command for GraphViz. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AWS deprecated the diagram MCP server. Remove from atmos.yaml, README table, server details, and prerequisites. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…exploration Add comprehensive usage examples for all AI surfaces: - atmos ai ask — one-shot questions (pricing, docs, security, knowledge) - atmos ai exec — multi-step tasks (security reports, pricing research) - --ai flag — terraform plan analysis with MCP context - atmos mcp tools/status — direct server exploration without AI - Updated intro listing all 6 integration points Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add step-by-step commands users can run immediately (no credentials needed): test, tools, ai ask, and ai chat examples. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move toolchain section before mcp (dependency before consumer) - Order servers by credential requirements (no-creds first) - Replace !env AWS_DEFAULT_REGION with hardcoded "us-east-1" to avoid empty-string issues when env var is unset - Remove misleading mcp.enabled comment (that's for the Atmos MCP server, not the client) - Remove double blank line - Add atmos ai ask to header quick-start example - Add note that !env returns empty string if var is unset Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Docusaurus MDX pages for 7 new MCP commands: - mcp list — list configured external servers - mcp add — add server to atmos.yaml - mcp remove — remove server from atmos.yaml - mcp tools — list tools from a server - mcp test — test server connectivity - mcp status — show all server statuses - mcp restart — restart a server Each page follows the existing pattern from ai/ commands with Intro, Experimental, Usage, Arguments/Flags, and Examples sections. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace custom theme.CreateMinimalTable with the standard list pipeline used by atmos list stacks/components for consistent look & feel. - Add --format (table/json/yaml/csv/tsv), --columns, --sort, --delimiter flags - Wire ATMOS_LIST_* environment variables - 6-stage pipeline: filter → column selection → sort → format → output - TTY-aware rendering (styled table vs plain/TSV) - 20 new tests covering columns, parsing, sorting, rendering, and formats Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace single quotes with backticks in "no servers configured" messages - Replace %q with backtick-wrapped %s in server/tool name messages - Add guidance text to status.go empty state message - Consistent formatting across list, status, tools, restart, generate-config, register, and init Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shorter, clearer command name per Erik's suggestion. - Rename generate_config.go → export.go, all variables and functions - Add embedded markdown help (atmos_mcp_export.md) - Add export_test.go with 5 tests (registration, flag, markdown, perms, struct) - Update all docs: website, blog, PRD, example README, screengrab list, roadmap - Rename website/docs/cli/commands/mcp/generate-config.mdx → export.mdx - Update all cross-references in ai.mdx, mcp config docs, DocCardList Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (1)
pkg/mcp/client/register.go (1)
14-15:⚠️ Potential issue | 🟠 MajorGive each MCP session its own startup deadline.
The timeout is created once before the loop and then reused for every
session.Start. A slow first server can burn most of the budget and make later servers fail even when their own configured timeout would have succeeded. Build a fresh timeout inside the loop, preferably fromsession.ParsedConfig.Timeout, and keepregistrationTimeoutonly as the fallback.💡 Suggested shape
func startAndRegisterTools(mgr *Manager, registry *tools.Registry, startOpts []StartOption, suppressStderr ...bool) int { - ctx, cancel := context.WithTimeout(context.Background(), registrationTimeout) - defer cancel() - suppress := len(suppressStderr) > 0 && suppressStderr[0] var totalTools int for _, session := range mgr.List() { + timeout := session.ParsedConfig.Timeout + if timeout <= 0 { + timeout = registrationTimeout + } + ctx, cancel := context.WithTimeout(context.Background(), timeout) if suppress { session.SetSuppressStderr(true) } if err := session.Start(ctx, startOpts...); err != nil { + cancel() ui.Error(fmt.Sprintf("MCP server `%s` failed to start: %v", session.Name(), err)) continue } + cancel() bridged := BridgeTools(session)Also applies to: 68-80
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mcp/client/register.go` around lines 14 - 15, The loop reuses a single global registrationTimeout for every session.Start, which can let a slow first session exhaust the budget for subsequent sessions; change the loop to construct a fresh per-session deadline (e.g., compute a timeout duration from session.ParsedConfig.Timeout for each iteration) and pass that to session.Start, using the existing registrationTimeout constant only as a fallback when ParsedConfig.Timeout is unset or invalid; update any calls to session.Start and related context/deadline creation in register.go so each session gets its own timeout.
🧹 Nitpick comments (4)
cmd/mcp/client/status.go (2)
83-91: Minor: leading space when description is empty.If
descriptionis empty and there's an error, the result is" (error message)"with a leading space. Consider trimming or using a conditional separator.desc := description if result.Error != nil { const maxErrLen = 50 errMsg := result.Error.Error() if len(errMsg) > maxErrLen { errMsg = errMsg[:maxErrLen-3] + "..." } - desc += " (" + errMsg + ")" + if desc != "" { + desc += " " + } + desc += "(" + errMsg + ")" }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/mcp/client/status.go` around lines 83 - 91, The current construction of desc appends " (" + errMsg + ")" unconditionally, producing a leading space when description is empty; update the logic in the status/error formatting block handling result.Error (the variables description, desc, errMsg) to only prepend a separator when description is non-empty—e.g., if description == "" set desc = errMsg (or "(" + errMsg + ")") otherwise set desc = description + " (" + errMsg + ")"; alternatively trim spaces from the final desc before use.
39-42: Consider wrapping the error with context.Per coding guidelines, errors should be wrapped with context. A simple wrap helps users understand where the failure occurred.
mgr, err := mcpclient.NewManager(atmosConfig.MCP.Servers) if err != nil { - return err + return fmt.Errorf("creating MCP manager: %w", err) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/mcp/client/status.go` around lines 39 - 42, The call to mcpclient.NewManager(atmosConfig.MCP.Servers) returns an unwrapped error; update the error handling in the function containing this call (where mgr is assigned) to wrap the returned err with contextual text (e.g., "failed to create MCP manager" or similar) using Go error wrapping (%w or errors.Wrap) before returning so callers know the operation and inputs that failed.cmd/mcp/client/list_test.go (1)
265-273: Usestrings.Indexfrom the standard library.This helper reimplements
strings.Index. The stdlib version is clearer and handles edge cases consistently.Proposed fix
+import ( + "strings" + "testing" + ... +) + // indexOfInString returns the byte index of substr in s, or -1 if not found. func indexOfInString(s, substr string) int { - for i := 0; i <= len(s)-len(substr); i++ { - if s[i:i+len(substr)] == substr { - return i - } - } - return -1 + return strings.Index(s, substr) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/mcp/client/list_test.go` around lines 265 - 273, The function indexOfInString reimplements standard library behavior; replace its usage with strings.Index from the "strings" package and remove the custom indexOfInString implementation. Update any callers to call strings.Index(s, substr) and add/import "strings" where needed so the build compiles. Ensure no remaining references to indexOfInString remain in the file.cmd/mcp/client/export_test.go (1)
10-49: Good baseline tests; please add behavior-path coverage forexecuteMCPExport.Current tests are mostly command wiring/constant checks. Add table-driven cases for runtime behavior (e.g., empty
mcp.servers, identity wrapping, write/chmod failure paths) to better protect the new feature contract.As per coding guidelines: “Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages”, “Use table-driven tests for testing multiple scenarios in Go”, and “Test behavior, not implementation.”
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/mcp/client/export_test.go` around lines 10 - 49, Add table-driven unit tests that exercise executeMCPExport's behavior paths using mcpJSONConfig inputs: include cases for empty MCPServers, a normal server entry (identity wrapping), and simulated failure paths for writing/chmod; for each case assert returned error (or nil) and expected side-effects (file created content or no file). To simulate write/chmod failures, make executeMCPExport use injectable file-op hooks (e.g., replaceable vars for writeFile/chmod used by executeMCPExport) or create temp directories with permissions that cause os.WriteFile/Chmod to fail in the test; reuse temp files and clean up. Ensure tests are table-driven, reference executeMCPExport, mcpJSONConfig and configFilePermissions, and assert both error messages and file permission behavior when applicable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cmd/ai/init.go`:
- Around line 219-226: The loop building serverInfos from
atmosConfig.MCP.Servers is iterating a map (non-deterministic order); change it
to iterate over a deterministic slice by calling
sortedServerNames(atmosConfig.MCP.Servers) and append router.ServerInfo entries
in that order (keep Name and Description assignment as before). Update the code
that constructs serverInfos (the for loop that currently ranges over
atmosConfig.MCP.Servers) to use the sortedServerNames result so the routing
prompt is stable.
- Around line 97-99: The initializeAIReadOnlyTools helper registers external MCP
tools (MCP server tools) before it builds a permissive permission checker, which
allows non-read-only MCP tools to bypass confirmation; fix by removing MCP tool
registration from initializeAIReadOnlyTools (keep only in the full initializer)
or, if MCP must be available here, replace the permissive checker creation with
the standard permission configuration used elsewhere (do not use
permission.ModeAllow unconditionally); update code paths that call
initializeAIReadOnlyTools and the MCP registration logic so MCP servers are
either excluded from this read-only initializer or validated by the same
permission checker used for write-capable tools (refer to
initializeAIReadOnlyTools and the permission.ModeAllow usage to locate the
changes).
- Around line 199-208: routeWithAI returns untrusted model output (selected)
which is passed straight into filterServersByName and silently drops unknown
names; validate that each name in selected actually exists in the servers
collection before filtering (use the servers list/keys to build a
validatedSelected slice), log a warning via ui.Info or ui.Warn listing any
hallucinated/unknown names, and if validatedSelected is empty fall back to
returning the original servers (or at minimum log that we are falling back)
instead of returning an empty set; update the code paths around routeWithAI,
selected, filterServersByName and the ui.Info call to use validatedSelected for
filtering and logging.
In `@cmd/mcp/client/export.go`:
- Around line 24-33: The export command currently sets flags directly and lacks
positional-arg validation; update the exportCmd declaration to include Args:
cobra.NoArgs, and in init() replace the direct exportCmd.Flags().StringP call
with creating a standard parser via flags.NewStandardParser(), call
parser.RegisterFlags(exportCmd.Flags()) (or the specific RegisterFlags() method
used in this repo), then add exportCmd to mcpcmd.McpCmd. Finally, in
executeMCPExport (the RunE) call parser.BindFlagsToViper() at the start so flags
are bound to viper before use. Use the symbols exportCmd, init,
executeMCPExport, flags.NewStandardParser(), RegisterFlags(), and
BindFlagsToViper() to locate the changes.
In `@cmd/mcp/client/list.go`:
- Around line 84-86: The error returned by mcpListParser.BindFlagsToViper(cmd,
v) should be wrapped with context using fmt.Errorf so callers get command-level
information; modify the error path in the function (around the call to
mcpListParser.BindFlagsToViper) to return a wrapped error that includes the
command identity (e.g., cmd.Name() or a descriptive string) and the original
error via %w, and add an import for fmt if missing.
---
Duplicate comments:
In `@pkg/mcp/client/register.go`:
- Around line 14-15: The loop reuses a single global registrationTimeout for
every session.Start, which can let a slow first session exhaust the budget for
subsequent sessions; change the loop to construct a fresh per-session deadline
(e.g., compute a timeout duration from session.ParsedConfig.Timeout for each
iteration) and pass that to session.Start, using the existing
registrationTimeout constant only as a fallback when ParsedConfig.Timeout is
unset or invalid; update any calls to session.Start and related context/deadline
creation in register.go so each session gets its own timeout.
---
Nitpick comments:
In `@cmd/mcp/client/export_test.go`:
- Around line 10-49: Add table-driven unit tests that exercise
executeMCPExport's behavior paths using mcpJSONConfig inputs: include cases for
empty MCPServers, a normal server entry (identity wrapping), and simulated
failure paths for writing/chmod; for each case assert returned error (or nil)
and expected side-effects (file created content or no file). To simulate
write/chmod failures, make executeMCPExport use injectable file-op hooks (e.g.,
replaceable vars for writeFile/chmod used by executeMCPExport) or create temp
directories with permissions that cause os.WriteFile/Chmod to fail in the test;
reuse temp files and clean up. Ensure tests are table-driven, reference
executeMCPExport, mcpJSONConfig and configFilePermissions, and assert both error
messages and file permission behavior when applicable.
In `@cmd/mcp/client/list_test.go`:
- Around line 265-273: The function indexOfInString reimplements standard
library behavior; replace its usage with strings.Index from the "strings"
package and remove the custom indexOfInString implementation. Update any callers
to call strings.Index(s, substr) and add/import "strings" where needed so the
build compiles. Ensure no remaining references to indexOfInString remain in the
file.
In `@cmd/mcp/client/status.go`:
- Around line 83-91: The current construction of desc appends " (" + errMsg +
")" unconditionally, producing a leading space when description is empty; update
the logic in the status/error formatting block handling result.Error (the
variables description, desc, errMsg) to only prepend a separator when
description is non-empty—e.g., if description == "" set desc = errMsg (or "(" +
errMsg + ")") otherwise set desc = description + " (" + errMsg + ")";
alternatively trim spaces from the final desc before use.
- Around line 39-42: The call to mcpclient.NewManager(atmosConfig.MCP.Servers)
returns an unwrapped error; update the error handling in the function containing
this call (where mgr is assigned) to wrap the returned err with contextual text
(e.g., "failed to create MCP manager" or similar) using Go error wrapping (%w or
errors.Wrap) before returning so callers know the operation and inputs that
failed.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 01fd8f8e-c212-4ec6-b523-21a267145a73
📒 Files selected for processing (19)
cmd/ai/init.gocmd/mcp/client/export.gocmd/mcp/client/export_test.gocmd/mcp/client/list.gocmd/mcp/client/list_test.gocmd/mcp/client/markdown/atmos_mcp_export.mdcmd/mcp/client/restart.gocmd/mcp/client/status.gocmd/mcp/client/tools.gocmd/mcp/mcpcmd/markdown/atmos_mcp.mddemo/screengrabs/demo-stacks.txtdocs/prd/atmos-mcp-integrations.mdexamples/mcp/README.mdpkg/mcp/client/register.gowebsite/blog/2026-03-29-mcp-server-integrations.mdxwebsite/docs/ai/ai.mdxwebsite/docs/cli/commands/mcp/export.mdxwebsite/docs/cli/configuration/mcp/index.mdxwebsite/src/data/roadmap.js
✅ Files skipped from review due to trivial changes (4)
- demo/screengrabs/demo-stacks.txt
- cmd/mcp/client/markdown/atmos_mcp_export.md
- cmd/mcp/mcpcmd/markdown/atmos_mcp.md
- website/docs/cli/commands/mcp/export.mdx
🚧 Files skipped from review as they are similar to previous changes (3)
- cmd/mcp/client/restart.go
- website/src/data/roadmap.js
- website/docs/ai/ai.mdx
…iew feedback - Delete initializeAIReadOnlyTools — ask command now uses initializeAIToolsAndExecutor (same tools, permissions, and auth as chat/exec) - Delete RegisterReadOnlyTools from setup.go (no longer used) - Validate router output: warn on hallucinated server names, fall back to all servers if none are valid - Make routing prompt deterministic (sort server names before building prompt) - Extract selectManualServers and selectRoutedServers to reduce cyclomatic complexity - Add cobra.NoArgs to export command - Fix empty description edge case in formatStatusRow - Replace custom indexOfInString with strings.Index - Use backtick quoting in all MCP ui messages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add TestSelectManualServers (3 cases: all valid, some unknown, all unknown) - Add TestMCPJSONConfig_Marshal (verify JSON structure and omitempty) - Add TestExportCmd_NoArgs (verify Args validator is set) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
cmd/mcp/client/export.go (1)
32-34:⚠️ Potential issue | 🟠 MajorUse
StandardParserfor--outputinstead of direct flag wiring.This subcommand still uses
exportCmd.Flags().StringP(...); repo convention requiresflags.NewStandardParser()+RegisterFlags(...)in init andBindFlagsToViper(...)inRunE.#!/bin/bash # Verify parser pattern mismatch against repo reference. rg -n -C3 'Flags\(\)\.StringP|NewStandardParser|RegisterFlags|BindFlagsToViper' \ cmd/mcp/client/export.go cmd/version/version.goBased on learnings: In Atmos command files, command-specific flags should follow
flags.NewStandardParser()withRegisterFlags/BindFlagsToViper, rather than direct flag registration.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/mcp/client/export.go` around lines 32 - 34, Replace the direct flag registration in init() for exportCmd with the repo-standard parser flow: create a parser via flags.NewStandardParser(), call parser.RegisterFlags(...) to add the "output" flag for exportCmd, and keep mcpcmd.McpCmd.AddCommand(exportCmd) in init(); then in exportCmd's RunE bind parser flags to viper with parser.BindFlagsToViper(cmd, viper) before reading the value. Locate symbols exportCmd, init, RunE, flags.NewStandardParser, RegisterFlags, and BindFlagsToViper to apply these changes.cmd/mcp/client/status.go (1)
29-29:⚠️ Potential issue | 🟠 MajorHonor global config-selection flags before loading CLI config.
Line 29 passes an empty
schema.ConfigAndStacksInfo{}intocfg.InitCliConfig, so--base-path,--config,--config-path, and--profilemay be ignored foratmos mcp status.Based on learnings:
cfg.InitCliConfigmust receiveConfigAndStacksInfopopulated viaflags.ParseGlobalFlags(cmd, v)or config-selection flags are silently ignored.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/mcp/client/status.go` at line 29, The call to cfg.InitCliConfig currently passes an empty schema.ConfigAndStacksInfo{}, so global config-selection flags (--base-path, --config, --config-path, --profile) are ignored; call flags.ParseGlobalFlags(cmd, v) to populate a ConfigAndStacksInfo instance and then pass that populated struct into cfg.InitCliConfig (replace schema.ConfigAndStacksInfo{} with the result from flags.ParseGlobalFlags) in the atmos mcp status command so cfg.InitCliConfig sees the global flags.
🧹 Nitpick comments (3)
cmd/ai/init_test.go (1)
186-217: Consider adding tests for routing-dependent functions.Functions like
routeWithAI,createRoutingClient, andselectRoutedServersaren't directly tested. They depend onai.NewClient, which would need interface extraction for mocking. Not blocking, but worth tracking for future coverage improvements.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/ai/init_test.go` around lines 186 - 217, Add unit tests for the routing-dependent functions routeWithAI, createRoutingClient, and selectRoutedServers by extracting ai.NewClient behind an interface so you can mock AI client behavior; introduce a small ai.ClientFactory (or ai.Client interface) used by createRoutingClient/routeWithAI, update those functions to accept the interface (or a factory) instead of directly calling ai.NewClient, and then add tests that inject a fake/mocked client to verify routing logic and server selection paths (including error and edge cases) without calling the real ai.NewClient.cmd/ai/init.go (2)
148-161: Log the filtered result, not the original request.Line 158 logs
mcpServerNames(the user's request) after warnings have been shown for invalid names. This could mislead users into thinking all requested servers were started. Consider logging the actual filtered keys instead.♻️ Suggested tweak
if len(filtered) > 0 { - ui.Info(fmt.Sprintf("MCP servers selected via --mcp flag: %s", strings.Join(mcpServerNames, ", "))) + ui.Info(fmt.Sprintf("MCP servers selected via --mcp flag: %s", strings.Join(sortedServerNames(filtered), ", "))) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/ai/init.go` around lines 148 - 161, In selectManualServers, the Info log currently prints the original mcpServerNames (the user request) which can mislead; change the log to report the actual filtered result by deriving the list of selected server names from the filtered map (variable filtered) and logging those (e.g., use sortedServerNames(filtered) joined with ", "). Keep the warnings for unknown names as-is but ensure the Info message reflects the real started/selected servers using filtered's keys.
260-276: Consider debug logging on toolchain resolution fallback.Both resolution attempts silently swallow errors. A debug log would help users troubleshoot when toolchain resolution unexpectedly falls back or returns nil.
♻️ Optional debug logging
func resolveToolchain(atmosConfig *schema.AtmosConfiguration) mcpclient.ToolchainResolver { // Load tool dependencies from .tool-versions so uvx/npx are resolved from the toolchain. deps, depsErr := dependencies.LoadToolVersionsDependencies(atmosConfig) if depsErr == nil && len(deps) > 0 { tenv, tenvErr := dependencies.NewEnvironmentFromDeps(atmosConfig, deps) if tenvErr == nil && tenv != nil { return tenv } + log.Debug("Failed to create environment from .tool-versions deps", "error", tenvErr) } // Fall back to component-based resolution. tenv, tenvErr := dependencies.ForComponent(atmosConfig, "terraform", nil, nil) if tenvErr == nil && tenv != nil { return tenv } + log.Debug("Toolchain resolution failed, MCP servers will use system PATH", "error", tenvErr) return nil }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/ai/init.go` around lines 260 - 276, resolveToolchain currently swallows errors from dependencies.LoadToolVersionsDependencies, dependencies.NewEnvironmentFromDeps and dependencies.ForComponent; add debug logging that records depsErr and tenvErr (and a message when falling back to component resolution or when returning nil) so callers can see why toolchain resolution fell back or failed; instrument the function resolveToolchain to log the errors and decision points (e.g., after depsErr, after tenvErr from NewEnvironmentFromDeps, and after tenvErr from ForComponent) using the module’s existing logger (or the appropriate logger in scope) so the values of depsErr and tenvErr are visible in debug output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cmd/mcp/client/export.go`:
- Line 61: The call to cmd.Flags().GetString("output") currently discards the
error; change it to capture the returned error (e.g., outputFile, err :=
cmd.Flags().GetString("output")) and, in the surrounding command handler (the
function containing this call), return a wrapped error like fmt.Errorf("failed
to read --output flag: %w", err) so the CLI surface propagates a clear,
diagnosable error; update any variable uses to the new names and ensure the
command uses RunE or otherwise returns the error instead of ignoring it.
In `@cmd/mcp/client/status.go`:
- Around line 45-57: The loop uses ctx directly when calling mgr.Test, causing
indefinite hangs and no progress output; change to create a per-server context
with a timeout (use context.WithTimeout) for each iteration, call cancel() after
the test, and pass that timed context to mgr.Test(session.Name(), startOpts...);
also emit progress feedback (e.g., call ui.Info or similar) before testing each
server using the session.Name() so users see per-server progress; update
references: buildStartOptions, mgr.List(), mgr.Test(...), formatStatusRow to use
the result from the timed ctx.
---
Duplicate comments:
In `@cmd/mcp/client/export.go`:
- Around line 32-34: Replace the direct flag registration in init() for
exportCmd with the repo-standard parser flow: create a parser via
flags.NewStandardParser(), call parser.RegisterFlags(...) to add the "output"
flag for exportCmd, and keep mcpcmd.McpCmd.AddCommand(exportCmd) in init(); then
in exportCmd's RunE bind parser flags to viper with parser.BindFlagsToViper(cmd,
viper) before reading the value. Locate symbols exportCmd, init, RunE,
flags.NewStandardParser, RegisterFlags, and BindFlagsToViper to apply these
changes.
In `@cmd/mcp/client/status.go`:
- Line 29: The call to cfg.InitCliConfig currently passes an empty
schema.ConfigAndStacksInfo{}, so global config-selection flags (--base-path,
--config, --config-path, --profile) are ignored; call
flags.ParseGlobalFlags(cmd, v) to populate a ConfigAndStacksInfo instance and
then pass that populated struct into cfg.InitCliConfig (replace
schema.ConfigAndStacksInfo{} with the result from flags.ParseGlobalFlags) in the
atmos mcp status command so cfg.InitCliConfig sees the global flags.
---
Nitpick comments:
In `@cmd/ai/init_test.go`:
- Around line 186-217: Add unit tests for the routing-dependent functions
routeWithAI, createRoutingClient, and selectRoutedServers by extracting
ai.NewClient behind an interface so you can mock AI client behavior; introduce a
small ai.ClientFactory (or ai.Client interface) used by
createRoutingClient/routeWithAI, update those functions to accept the interface
(or a factory) instead of directly calling ai.NewClient, and then add tests that
inject a fake/mocked client to verify routing logic and server selection paths
(including error and edge cases) without calling the real ai.NewClient.
In `@cmd/ai/init.go`:
- Around line 148-161: In selectManualServers, the Info log currently prints the
original mcpServerNames (the user request) which can mislead; change the log to
report the actual filtered result by deriving the list of selected server names
from the filtered map (variable filtered) and logging those (e.g., use
sortedServerNames(filtered) joined with ", "). Keep the warnings for unknown
names as-is but ensure the Info message reflects the real started/selected
servers using filtered's keys.
- Around line 260-276: resolveToolchain currently swallows errors from
dependencies.LoadToolVersionsDependencies, dependencies.NewEnvironmentFromDeps
and dependencies.ForComponent; add debug logging that records depsErr and
tenvErr (and a message when falling back to component resolution or when
returning nil) so callers can see why toolchain resolution fell back or failed;
instrument the function resolveToolchain to log the errors and decision points
(e.g., after depsErr, after tenvErr from NewEnvironmentFromDeps, and after
tenvErr from ForComponent) using the module’s existing logger (or the
appropriate logger in scope) so the values of depsErr and tenvErr are visible in
debug output.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 16fbc2f6-c814-4e5b-adb9-71345b88fae6
📒 Files selected for processing (9)
cmd/ai/ask.gocmd/ai/init.gocmd/ai/init_test.gocmd/mcp/client/export.gocmd/mcp/client/export_test.gocmd/mcp/client/helpers_test.gocmd/mcp/client/list_test.gocmd/mcp/client/status.gopkg/ai/tools/atmos/setup.go
💤 Files with no reviewable changes (1)
- pkg/ai/tools/atmos/setup.go
🚧 Files skipped from review as they are similar to previous changes (4)
- cmd/mcp/client/helpers_test.go
- cmd/mcp/client/export_test.go
- cmd/ai/ask.go
- cmd/mcp/client/list_test.go
…eout, path handling - Log actual filtered server names in --mcp output (not the original request) - Add debug logging to toolchain resolution fallback paths - Add 120s timeout to status command's server test loop - Fix hardcoded Unix paths in auth_test.go and session_test.go (use filepath.Join) - Validate routing output: warn on hallucinated names, fall back on all invalid Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
cmd/ai/init.go (1)
149-160:⚠️ Potential issue | 🟠 MajorStill make explicit
--mcpselections fail fast.This path warns and keeps going with a partial or empty server set. For an explicit
--mcprequest, unknown names should abort initialization so the command does not silently drop the requested MCP tools. HaveselectManualServers()return an error and bubble it throughregisterMCPServerTools()/initializeAIToolsAndExecutor().As per coding guidelines, "Provide clear error messages to users, include troubleshooting hints when appropriate."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/ai/init.go` around lines 149 - 160, selectManualServers currently only warns on unknown --mcp names and continues; change its signature to return (map[string]schema.MCPServerConfig, error), detect any requested names that are missing (compare mcpServerNames to keys in servers), and return a descriptive error (including the unknown names and available names) instead of calling ui.Warning when any are missing; update callers registerMCPServerTools and initializeAIToolsAndExecutor to propagate that error and abort initialization (return the error) so explicit --mcp selections fail fast and produce a clear user-facing message and troubleshooting hint.
🧹 Nitpick comments (4)
cmd/mcp/client/status.go (2)
60-63: Progress feedback during iteration.The timeout addition (lines 52-54) addresses the hang concern. However, users still see no output until all servers finish testing. For transparency, emit progress before each test.
♻️ Proposed fix
for _, session := range mgr.List() { + ui.Info(fmt.Sprintf("Testing server: %s", session.Name())) result := mgr.Test(ctx, session.Name(), startOpts...) rows = append(rows, formatStatusRow(session.Name(), session.Config().Description, result)) }As per coding guidelines: "Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/mcp/client/status.go` around lines 60 - 63, Before running each test in the loop that iterates mgr.List(), emit a progress message so the user sees which session is being tested; specifically, add a progress print/log call right before calling mgr.Test(ctx, session.Name(), startOpts...) that references session.Name() (and optionally session.Config().Description) so users know which server is currently being tested, then proceed to collect result and call formatStatusRow as before. Ensure the progress output uses the same CLI output mechanism as the command (not stderr) and is non-blocking so it appears immediately during long-running iterations.
33-35: Wrap errors with context.Returning raw errors loses call-site context. Wrap them to help users understand where failures occur.
♻️ Proposed fix
atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false) if err != nil { - return err + return fmt.Errorf("initializing config: %w", err) }mgr, err := mcpclient.NewManager(atmosConfig.MCP.Servers) if err != nil { - return err + return fmt.Errorf("creating MCP manager: %w", err) }As per coding guidelines: "Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using
fmt.Errorf("context: %w", err)".Also applies to: 43-45
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/mcp/client/status.go` around lines 33 - 35, Replace bare returns of err in the two locations that currently read "if err != nil { return err }" with wrapped errors that add call-site context using fmt.Errorf("context: %w", err); for example change to return fmt.Errorf("fetching status: %w", err) or a short context that describes the failed operation in the current function (wrap both occurrences referenced in the review). Ensure fmt is imported if not already.pkg/mcp/client/auth_test.go (2)
37-99: Consider table-driven tests for the auth/toolchain scenario sets.The scenario coverage is good; converting these repeated cases into table-driven tests will reduce duplication and make new cases cheaper to add.
As per coding guidelines, "Use table-driven tests for testing multiple scenarios in Go."
Also applies to: 144-201
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mcp/client/auth_test.go` around lines 37 - 99, The four nearly-identical tests for WithAuthManager (TestWithAuthManager_InjectsCredentials, _NoIdentity_Passthrough, _NilProvider_Passthrough, _Error_ReturnsError) should be consolidated into a single table-driven test: create a slice of test cases with fields (name, provider/mocked values, ParsedConfig, input env, wantEnv, wantCalledWith, wantErr) and iterate over them calling opt := WithAuthManager(tc.provider) and result, err := opt(ctx, tc.config, tc.env), then assert expectations per case; reference mockAuthProvider, WithAuthManager, ParsedConfig and the existing assertions to port expected behaviors and include the nil provider and error-producing provider cases as distinct table entries.
102-120: Add a compile-time sentinel forschema.MCPServerConfig.Identity.These tests depend on that field; a sentinel will fail fast on schema rename/refactor.
Suggested guard.
import ( @@ "github.com/cloudposse/atmos/pkg/schema" ) + +var _ = schema.MCPServerConfig{Identity: "compile-guard"}Based on learnings, "Add compile-time sentinels for schema field references in tests: when a test uses a specific struct field ... add ... as a compile guard so a field rename immediately fails the build."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mcp/client/auth_test.go` around lines 102 - 120, Add a compile-time sentinel that references the field schema.MCPServerConfig.Identity so renaming/removing the field breaks the build; put a package-level unused variable referencing that field (e.g. just assign schema.MCPServerConfig{}.Identity to an underscore var) near the tests in auth_test.go (close to TestParseConfig_Identity/TestParseConfig_EmptyIdentity and newTestServerConfig) so the tests fail to compile if the Identity field is renamed or removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cmd/ai/init.go`:
- Around line 280-292: The helper resolveAuthProvider currently returns nil on
auth manager creation failure which allows MCP startup to proceed without
required credentials; change resolveAuthProvider to return
(mcpclient.AuthEnvProvider, error) instead of mcpclient.AuthEnvProvider,
propagate and return the error from
auth.CreateAndAuthenticateManagerWithAtmosConfig (include context like "failed
to create auth manager for MCP servers"), and update callers to abort MCP
registration when an error is returned (use
serversNeedAuth(atmosConfig.MCP.Servers) to guard the call). Ensure all
references to resolveAuthProvider are updated to handle the error and stop
startup when it fails.
In `@pkg/mcp/client/auth_test.go`:
- Line 124: The comment "// WithToolchain tests" is missing a trailing period;
update that comment to "// WithToolchain tests." in the test file (look for the
comment immediately above the WithToolchain-related test cases in auth_test.go)
so it satisfies the godot linter requirement that all comments end with periods.
- Around line 56-71: The test TestWithAuthManager_NoIdentity_Passthrough
currently asserts mock.calledWith == "" which can false-positive if the mock was
invoked with an empty identity; update the mockAuthProvider used in this test to
track invocation (e.g., a bool or callCount field) and change the assertion to
require that the mock was not called (callCount == 0 or called == false) after
invoking WithAuthManager(opt) with a ParsedConfig that has Identity == ""; keep
the rest of the test (env/result assertions) unchanged and reference
mockAuthProvider and WithAuthManager when making the change.
- Around line 16-20: Tests use handwritten mockAuthProvider and mockToolchain
instead of generated mocks; replace them by adding go:generate directives to
generate mocks for the AuthEnvProvider and ToolchainResolver interfaces (named
in session.go as AuthEnvProvider and ToolchainResolver), run mockgen to produce
the mock package, import the generated mocks in pkg/mcp/client/auth_test.go and
other affected tests (where mockAuthProvider and mockToolchain are referenced),
and update test usage to use the generated mock types and EXPECT-style method
setups rather than the manual preparedEnv/err/calledWith fields.
---
Duplicate comments:
In `@cmd/ai/init.go`:
- Around line 149-160: selectManualServers currently only warns on unknown --mcp
names and continues; change its signature to return
(map[string]schema.MCPServerConfig, error), detect any requested names that are
missing (compare mcpServerNames to keys in servers), and return a descriptive
error (including the unknown names and available names) instead of calling
ui.Warning when any are missing; update callers registerMCPServerTools and
initializeAIToolsAndExecutor to propagate that error and abort initialization
(return the error) so explicit --mcp selections fail fast and produce a clear
user-facing message and troubleshooting hint.
---
Nitpick comments:
In `@cmd/mcp/client/status.go`:
- Around line 60-63: Before running each test in the loop that iterates
mgr.List(), emit a progress message so the user sees which session is being
tested; specifically, add a progress print/log call right before calling
mgr.Test(ctx, session.Name(), startOpts...) that references session.Name() (and
optionally session.Config().Description) so users know which server is currently
being tested, then proceed to collect result and call formatStatusRow as before.
Ensure the progress output uses the same CLI output mechanism as the command
(not stderr) and is non-blocking so it appears immediately during long-running
iterations.
- Around line 33-35: Replace bare returns of err in the two locations that
currently read "if err != nil { return err }" with wrapped errors that add
call-site context using fmt.Errorf("context: %w", err); for example change to
return fmt.Errorf("fetching status: %w", err) or a short context that describes
the failed operation in the current function (wrap both occurrences referenced
in the review). Ensure fmt is imported if not already.
In `@pkg/mcp/client/auth_test.go`:
- Around line 37-99: The four nearly-identical tests for WithAuthManager
(TestWithAuthManager_InjectsCredentials, _NoIdentity_Passthrough,
_NilProvider_Passthrough, _Error_ReturnsError) should be consolidated into a
single table-driven test: create a slice of test cases with fields (name,
provider/mocked values, ParsedConfig, input env, wantEnv, wantCalledWith,
wantErr) and iterate over them calling opt := WithAuthManager(tc.provider) and
result, err := opt(ctx, tc.config, tc.env), then assert expectations per case;
reference mockAuthProvider, WithAuthManager, ParsedConfig and the existing
assertions to port expected behaviors and include the nil provider and
error-producing provider cases as distinct table entries.
- Around line 102-120: Add a compile-time sentinel that references the field
schema.MCPServerConfig.Identity so renaming/removing the field breaks the build;
put a package-level unused variable referencing that field (e.g. just assign
schema.MCPServerConfig{}.Identity to an underscore var) near the tests in
auth_test.go (close to TestParseConfig_Identity/TestParseConfig_EmptyIdentity
and newTestServerConfig) so the tests fail to compile if the Identity field is
renamed or removed.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9581a364-cf4f-4961-aa4c-7fc65f4dbe86
📒 Files selected for processing (4)
cmd/ai/init.gocmd/mcp/client/status.gopkg/mcp/client/auth_test.gopkg/mcp/client/session_test.go
✅ Files skipped from review due to trivial changes (1)
- pkg/mcp/client/session_test.go
- WithAuthManager now returns error when authMgr is nil but server has identity set (prevents silent fallback to ambient credentials) - Add ErrMCPServerAuthUnavailable sentinel error - Add callCount to mockAuthProvider for precise invocation tracking - Split NilProvider test into WithIdentity (error) and NoIdentity (passthrough) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Warning Release Documentation RequiredThis PR is labeled
|
|
These changes were released in v1.214.0-test.1. |
what
atmos ai ask,atmos ai chat, andatmos ai execatmos mcp list,tools,test,status,restart,start,export--mcpflag on all AI commands for manual server selection (supports--mcp aws-iam,aws-billingand--mcp aws-iam --mcp aws-billing), env varATMOS_AI_MCPatmos mcp exportto emit.mcp.jsonfor Claude Code / Cursor / IDE integrationidentityfield on server config for automatic credential injection (references identities from theauthsection)uvx/npxfrom.tool-versionsbefore starting serversBridgedToolpattern to wrap external MCP tools as native Atmostools.Toolinterfaceaws-iam → list_rolesinstead ofaws-iam__list_roles)atmos ai askoutput via MarkdownFormatterai.max_tool_iterations(default 25, was hardcoded 10) to support complex multi-tool queriesexamples/mcp/why
references
docs/prd/atmos-mcp-integrations.mdwebsite/blog/2026-03-29-mcp-server-integrations.mdxexamples/mcp/— complete working example with 8 AWS MCP serversSee It in Action
List configured servers
Explore tools from a server
Test server connectivity
Ask AI — documentation search (smart routing selects aws-knowledge)
Ask AI — billing analysis (smart routing selects aws-billing)
Ask AI — security posture across all regions (smart routing selects aws-api + aws-security)
Ask AI — IAM audit (smart routing selects aws-iam)
Check status of all servers
Summary by CodeRabbit
New Features
Documentation