Skip to content

Conversation

saqadri
Copy link
Collaborator

@saqadri saqadri commented Sep 29, 2025

Makes the app name optional in the deploy command. In case it's not specified, we now look in the config to see if an app name is defined there, and if not, default to "default" as the name.

Also improved the wording for the secrets prompt.

Summary by CodeRabbit

  • New Features

    • Configure app name and description in settings; app uses these values when available.
    • Add a "Default Model" option for Google settings.
    • Deploy command supports working_dir and optional config_dir, and auto-defaults app name/description from config.
  • Refactor

    • Simplified OpenTelemetry exporter config to a string list (console, file, otlp); clarified OTLP settings requirement.
  • Tests

    • Added deploy tests for config-driven defaults and updated test formatting/fixtures.

@saqadri saqadri requested a review from rholinshead September 29, 2025 15:53
Copy link

coderabbitai bot commented Sep 29, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds root name/description to the config schema and Settings model; defers MCPApp name/description resolution to use config-first fallbacks; simplifies OpenTelemetry exporters schema to an enum list; enhances deploy CLI to resolve config/working dirs and default app name/description from config; updates and extends related tests.

Changes

Cohort / File(s) Summary
Schema: Config + OTel
schema/mcp-agent.config.schema.json
Adds root name and description; adds GoogleSettings.default_model; replaces OpenTelemetrySettings.exporters discriminated union with an enum string array ["console","file","otlp"]; removes OTel*ExporterSettings definitions; updates otlp_settings description.
Config Model
src/mcp_agent/config.py
Adds `Settings.name: str
App Initialization
src/mcp_agent/app.py
Defers MCPApp name/description assignment until after settings/config load; uses config values first, then MCP instance fallbacks.
CLI Deploy Flow
src/mcp_agent/cli/cloud/commands/deploy/main.py
Adds config_dir and working_dir options; resolves config_dir relative to working_dir; loads config files earlier; derives default app name/description from config via new _get_app_info_from_config; adjusts update/reuse-secrets prompt and secrets handling.
Deploy Command Tests
tests/cli/commands/test_deploy_command.py
Adds tests for falling back to config-defined app name/description and for config load failures; preserves secrets-file test with minor formatting tweak.
Test Adjustments (formatting/scaffolding)
tests/cli/commands/test_wrangler_wrapper.py, tests/utils/test_config_preload.py, tests/test_app.py
Mostly formatting or fixture scaffolding changes (wrapping patches, single-line assertions, setting mock settings .name/.description to None).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Config Loader
  participant A as MCPApp
  participant M as MCP Instance

  Note over C,A: App startup / initialization
  C->>A: Load settings (including name, description)
  alt Config provides name/description
    A->>A: Set app.name / app.description from config
  else Config missing fields
    A->>M: Read mcp.name / mcp.instructions
    A->>A: Use MCP values as fallback (if present)
  end
Loading
sequenceDiagram
  autonumber
  participant U as User (CLI)
  participant D as deploy_config
  participant P as Path Resolver
  participant CF as get_config_files
  participant GS as get_settings
  participant W as wrangler_deploy

  U->>D: deploy --config-dir [opt] --working-dir [opt] [--app-name/--description]
  D->>P: Resolve config_dir relative to working_dir
  P-->>D: Validated config_dir
  D->>CF: Load config files from config_dir
  D->>GS: Read settings (name, description)
  GS-->>D: Settings (name, description)
  alt CLI app-name/description not provided
    D->>D: Default app_name/app_description from Settings or directory name
  end
  D->>U: Prompt update/reuse secrets (default: reuse)
  alt Reuse secrets
    D->>D: Use existing deployed secrets path
  else Regenerate
    D->>D: Set deployed_secrets_file = None
  end
  D->>W: Deploy with resolved app_name/description and secrets handling
  W-->>D: Result
  D-->>U: Exit status
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • rholinshead

Poem

I twitch my whiskers at the change,
Name and tale now in the range.
I hop through configs, neat and spry,
Paths resolved beneath my sky.
Exporters trimmed — a carrot find, joy in every deploy. 🥕🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the primary change of making the app name optional in the deploy command, reflecting the core functionality added by this pull request.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84dc0d7 and 3ab88ca.

📒 Files selected for processing (1)
  • tests/cli/commands/test_deploy_command.py (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@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: 1

🧹 Nitpick comments (5)
src/mcp_agent/app.py (1)

113-120: Config-first resolution for name/description looks good

Behavior: CLI arg → config → MCP instance; description falls back to static default. Consider guaranteeing a non-empty string for self.name if callers pass None (optional).

src/mcp_agent/cli/cloud/commands/deploy/main.py (4)

142-156: Config directory resolution/validation looks correct

Handles absolute/relative paths against working_dir. Optional: call .resolve() on resolved_config_dir for clearer logs.


221-224: Tiny grammar fix in confirm prompt

“Do you want to deploy an update…” reads better.

-                        f"Do you want deploy an update to the existing app ID: {app_id}?",
+                        f"Do you want to deploy an update to the existing app ID: {app_id}?",

278-281: Path join style

Prefer Path composition over f-strings for portability.

-            secrets_transformed_path = Path(
-                f"{config_dir}/{MCP_DEPLOYED_SECRETS_FILENAME}"
-            )
+            secrets_transformed_path = config_dir / MCP_DEPLOYED_SECRETS_FILENAME

492-517: Adjust return typing and doc for _get_app_info_from_config

Function always returns a 2-tuple (possibly Nones), not Optional[tuple]. Also update docstring to mention description.

-def _get_app_info_from_config(config_file: Path) -> Optional[tuple[str, str]]:
-    """Return a default deployment name sourced from configuration if available."""
+def _get_app_info_from_config(
+    config_file: Path,
+) -> tuple[Optional[str], Optional[str]]:
+    """Return (app_name, app_description) sourced from configuration if available."""
@@
-    except Exception:
-        return None, None
+    except Exception:
+        return None, None
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ceeabb and b256d73.

📒 Files selected for processing (8)
  • schema/mcp-agent.config.schema.json (4 hunks)
  • src/mcp_agent/app.py (1 hunks)
  • src/mcp_agent/cli/cloud/commands/deploy/main.py (6 hunks)
  • src/mcp_agent/config.py (1 hunks)
  • tests/cli/commands/test_deploy_command.py (2 hunks)
  • tests/cli/commands/test_wrangler_wrapper.py (11 hunks)
  • tests/test_app.py (2 hunks)
  • tests/utils/test_config_preload.py (10 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-22T18:59:49.368Z
Learnt from: CR
PR: lastmile-ai/mcp-agent#0
File: examples/usecases/reliable_conversation/CLAUDE.md:0-0
Timestamp: 2025-07-22T18:59:49.368Z
Learning: Applies to examples/usecases/reliable_conversation/examples/reliable_conversation/src/utils/config.py : Configuration values such as quality_threshold, max_refinement_attempts, consolidation_interval, and evaluator_model_provider must be loaded from mcp_agent.config.yaml.

Applied to files:

  • tests/utils/test_config_preload.py
  • src/mcp_agent/app.py
🧬 Code graph analysis (6)
tests/utils/test_config_preload.py (1)
src/mcp_agent/config.py (1)
  • get_settings (770-870)
src/mcp_agent/app.py (1)
src/mcp_agent/core/context.py (1)
  • mcp (102-103)
src/mcp_agent/cli/cloud/commands/deploy/main.py (3)
src/mcp_agent/config.py (1)
  • get_settings (770-870)
src/mcp_agent/cli/exceptions.py (1)
  • CLIError (4-10)
src/mcp_agent/cli/utils/ux.py (1)
  • print_info (32-49)
tests/cli/commands/test_wrangler_wrapper.py (1)
src/mcp_agent/cli/cloud/commands/deploy/wrangler_wrapper.py (1)
  • _needs_requirements_modification (35-41)
tests/cli/commands/test_deploy_command.py (2)
src/mcp_agent/cli/mcp_app/api_client.py (2)
  • get_app_id_by_name (286-308)
  • create_app (134-164)
src/mcp_agent/cli/mcp_app/mock_client.py (2)
  • get_app_id_by_name (36-45)
  • create_app (86-124)
tests/test_app.py (2)
tests/workflows/router/conftest.py (1)
  • mock_context (17-67)
src/mcp_agent/app.py (1)
  • config (173-174)
🪛 GitHub Actions: Pull Request Checks
tests/cli/commands/test_deploy_command.py

[error] 266-266: Deploy defaults to directory name when config missing name. AssertionError: expected temp_config_dir.name but got 'default'. The test fails because deployment uses 'default' instead of the working directory name.

🔇 Additional comments (11)
tests/test_app.py (2)

20-21: LGTM: explicit None config fields for name/description

Good setup to exercise config-first fallback paths.


121-122: LGTM: custom settings with None name/description

Keeps constructor paths deterministic in tests.

tests/cli/commands/test_deploy_command.py (4)

145-202: Test asserts config-derived app name when CLI omits name

Covers expected happy path; will pass once deploy fallback logic prefers config, else directory (see main.py fix below).


204-267: Test asserts directory-name fallback when config lacks name

This is the source of the pipeline failure; current implementation defaults to "default". The fix is to use config_dir.name. See proposed diff in deploy/main.py.


269-328: Test asserts config-derived description reuse

Good coverage for description defaulting. Aligns with helper that reads description from config.


394-396: Nit: assertion simplification is fine

Inline equality read is clearer.

src/mcp_agent/cli/cloud/commands/deploy/main.py (2)

61-83: New --config-dir and --working-dir options

Solid ergonomics. Minor: help text for --config-dir mentions resolution against --working-dir (good). No change required.


255-266: Secrets reuse prompt defaults to reuse=True

Nice UX; behavior matches non_interactive path. No change requested.

schema/mcp-agent.config.schema.json (3)

361-373: GoogleSettings.default_model added

Schema looks correct (string|null, default null). Ensure config model maps this field.


882-892: OTel exporters simplified to enum array

Simplifies config. Verify downstream code tolerates string list vs prior discriminated union.

Also applies to: 938-938


1182-1207: Root-level name/description fields

Matches app/config/test changes; good addition.

Comment on lines +157 to +179
config_file, secrets_file, deployed_secrets_file = get_config_files(config_dir)

default_app_name, default_app_description = _get_app_info_from_config(
config_file
)

if app_name is None:
if default_app_name:
print_info(
f"No app name provided. Using '{default_app_name}' from configuration."
)
app_name = default_app_name
else:
app_name = "default"
print_info("No app name provided. Using 'default' as app name.")

if app_description is None:
if default_app_description:
print_info(
"No app description provided. Using description from configuration."
)
app_description = default_app_description

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Fix fallback: use directory name when config has no name (test blocker)

Current code defaults to "default" when CLI name and config name are missing; tests expect config_dir.name. Apply this change.

-        if app_name is None:
-            if default_app_name:
-                print_info(
-                    f"No app name provided. Using '{default_app_name}' from configuration."
-                )
-                app_name = default_app_name
-            else:
-                app_name = "default"
-                print_info("No app name provided. Using 'default' as app name.")
+        if app_name is None:
+            if default_app_name:
+                print_info(
+                    f"No app name provided. Using '{default_app_name}' from configuration."
+                )
+                app_name = default_app_name
+            else:
+                # Fallback: use directory name when config does not define one
+                app_name = config_dir.name
+                print_info(
+                    f"No app name provided. Using directory name '{app_name}' as app name."
+                )

After this change, test_deploy_defaults_to_directory_name_when_config_missing_name should pass.

Also applies to: 163-172


🏁 Script executed:

#!/usr/bin/env bash
set -eux

# Print lines 130-230 for context in main.py
sed -n '130,230p' src/mcp_agent/cli/cloud/commands/deploy/main.py || true

# Search for the specific test
rg -n "test_deploy_defaults_to_directory_name_when_config_missing_name" -C3 -g "*.py" . || true

Length of output: 4743


Fix fallback: use directory name when config has no name

File: src/mcp_agent/cli/cloud/commands/deploy/main.py
Replace the "default" fallback under if app_name is None with config_dir.name so the test passes:

-        if app_name is None:
-            if default_app_name:
-                print_info(
-                    f"No app name provided. Using '{default_app_name}' from configuration."
-                )
-                app_name = default_app_name
-            else:
-                app_name = "default"
-                print_info("No app name provided. Using 'default' as app name.")
+        if app_name is None:
+            if default_app_name:
+                print_info(
+                    f"No app name provided. Using '{default_app_name}' from configuration."
+                )
+                app_name = default_app_name
+            else:
+                # Fallback: use directory name when config does not define one
+                app_name = config_dir.name
+                print_info(
+                    f"No app name provided. Using directory name '{app_name}' as app name."
+                )

After this change, test_deploy_defaults_to_directory_name_when_config_missing_name will pass.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
config_file, secrets_file, deployed_secrets_file = get_config_files(config_dir)
default_app_name, default_app_description = _get_app_info_from_config(
config_file
)
if app_name is None:
if default_app_name:
print_info(
f"No app name provided. Using '{default_app_name}' from configuration."
)
app_name = default_app_name
else:
app_name = "default"
print_info("No app name provided. Using 'default' as app name.")
if app_description is None:
if default_app_description:
print_info(
"No app description provided. Using description from configuration."
)
app_description = default_app_description
if app_name is None:
if default_app_name:
print_info(
f"No app name provided. Using '{default_app_name}' from configuration."
)
app_name = default_app_name
else:
# Fallback: use directory name when config does not define one
app_name = config_dir.name
print_info(
f"No app name provided. Using directory name '{app_name}' as app name."
)
🤖 Prompt for AI Agents
In src/mcp_agent/cli/cloud/commands/deploy/main.py around lines 157 to 179, the
fallback that sets app_name to the literal "default" when no app name is
provided should be replaced to use the directory name; change the assignment to
set app_name = config_dir.name and update the accompanying print_info message to
reflect using the config directory name instead of the string "default".

Copy link

@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: 0

🧹 Nitpick comments (3)
tests/cli/commands/test_deploy_command.py (3)

145-202: Strengthen assertions to verify create_app uses the resolved name.

You assert the lookup used "fixture-app"; also assert the app creation used the same name (and optionally that wrangler_deploy was called).

@@
     ):
-        result = runner.invoke(
+        result = runner.invoke(
             app,
             [
                 "deploy",
                 "--working-dir",
                 temp_config_dir,
@@
         )
 
     assert result.exit_code == 0, f"Deploy command failed: {result.stdout}"
     first_call = mock_client.get_app_id_by_name.await_args_list[0]
     assert first_call.args[0] == "fixture-app"
+    # Ensure we created the app with the resolved name
+    create_call = mock_client.create_app.await_args
+    assert create_call.args[0] == "fixture-app"

If the deploy flow changed to pass name by keyword, switch to create_call.kwargs["name"]. Also consider naming the wrangler patch (as mock_wrangler_deploy) and asserting mock_wrangler_deploy.assert_called_once().


204-267: Rename test to reflect behavior (“default” string), and assert create_app uses it.

Function name says “directory name” but behavior expects literal "default". Rename for clarity and add an assertion on create_app’s name.

-def test_deploy_defaults_to_directory_name_when_config_missing_name(
+def test_deploy_defaults_to_default_name_when_config_missing_name(
     runner, temp_config_dir
 ):
-    """Fallback uses the default name when config doesn't define one."""
+    """Fallback uses the literal 'default' name when config doesn't define one."""
@@
     assert result.exit_code == 0, f"Deploy command failed: {result.stdout}"
     first_call = mock_client.get_app_id_by_name.await_args_list[0]
     assert first_call.args[0] == "default"
+    # Ensure create_app was invoked with the defaulted name
+    create_call = mock_client.create_app.await_args
+    assert create_call.args[0] == "default"

269-328: Also assert name passed to create_app when only description comes from config.

This verifies both defaults: name fallback and description reuse.

@@
     assert result.exit_code == 0, f"Deploy command failed: {result.stdout}"
     create_call = mock_client.create_app.await_args
     assert create_call.kwargs["description"] == "Configured app description"
+    # Name should fall back when not provided in CLI or config
+    assert create_call.args[0] == "default"

Optionally add a complementary test where a CLI description overrides the config description.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b256d73 and 84dc0d7.

📒 Files selected for processing (1)
  • tests/cli/commands/test_deploy_command.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/cli/commands/test_deploy_command.py (2)
src/mcp_agent/cli/mcp_app/api_client.py (2)
  • get_app_id_by_name (286-308)
  • create_app (134-164)
src/mcp_agent/cli/mcp_app/mock_client.py (2)
  • get_app_id_by_name (36-45)
  • create_app (86-124)
🔇 Additional comments (1)
tests/cli/commands/test_deploy_command.py (1)

394-396: LGTM: clearer one-line assertion with message.

@saqadri saqadri merged commit 650f055 into main Sep 29, 2025
7 of 8 checks passed
"title": "MCPSettings",
"type": "object"
},
"OTelConsoleExporterSettings": {
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated, but I suppose we can also clean up the fallback handling for the deprecated settings now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes will do

@rholinshead
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants