Skip to content

Conversation

@niechen
Copy link
Contributor

@niechen niechen commented Jul 2, 2025

PR Type

Enhancement, Tests, Bug fix


Description

• Complete architectural overhaul from MCPM v1 to v2, introducing global server configuration management and virtual profile system
• Implemented comprehensive v1 to v2 migration system with interactive prompts, backup creation, and conflict detection
• Added FastMCP integration replacing mcp-proxy, including authentication, middleware, and proxy factory for server aggregation
• Introduced SQLite-based access monitoring with async event tracking, session management, and usage analytics
• Created interactive command interfaces using InquirerPy for server/profile selection, editing, and configuration management
• Added new commands: edit (interactive server editor), inspect (MCP Inspector integration), usage (analytics), and profile sharing
• Implemented secure tunneling system for public server sharing with authentication and port management
• Deprecated v1 commands (stash, pop, mv, cp, target) with proper migration guidance and error messages
• Updated all client managers and configurations to align with v2 architecture
• Comprehensive test suite updates covering new functionality, migration system, and deprecated command handling


Changes walkthrough 📝

Relevant files
Enhancement
18 files
client.py
Complete rewrite of client commands for v2 architecture   

src/mcpm/commands/client.py

• Complete rewrite of client command functionality from v1 to v2
architecture
• Added interactive server/profile selection using
InquirerPy with checkbox interface
• Implemented new client import
functionality to migrate server configurations
• Added support for
MCPM profiles and individual server management in client configs

+1041/-117
v1_migrator.py
New v1 to v2 migration system implementation                         

src/mcpm/migration/v1_migrator.py

• New migration system to handle v1 to v2 configuration upgrades

Interactive migration prompts with comprehensive user guidance

Backup creation and cleanup functionality for v1 configurations

Profile and server migration with conflict detection

+487/-0 
share.py
Modernized share command with FastMCP integration               

src/mcpm/commands/share.py

• Replaced mcp-proxy dependency with FastMCP proxy integration
• Added
authentication support with API key generation
• Simplified server
sharing using global configuration lookup
• Improved error handling
and async operation support

+190/-307
edit.py
Interactive Server Configuration Editor Implementation     

src/mcpm/commands/edit.py

• Added comprehensive interactive server configuration editor with
InquirerPy forms
• Supports editing existing servers, creating new
servers, and opening global config in external editor
• Includes
validation, confirmation prompts, and real-time feedback for server
properties
• Handles both STDIO and Remote server types with
type-specific configuration fields

+545/-0 
sqlite.py
SQLite Access Monitor with Async Event Tracking                   

src/mcpm/monitor/sqlite.py

• Implemented SQLite-based access monitoring with async operations
using thread pools
• Added comprehensive event tracking for sessions,
tools, resources, and prompts
• Includes database schema with proper
indexing and WAL mode for performance
• Computes usage statistics from
events rather than separate session tracking

+599/-0 
cli.py
CLI Restructure for MCPM V2.0 Architecture                             

src/mcpm/cli.py

• Major CLI restructure for MCPM v2.0 with simplified global
configuration model
• Removed active target system, added v1 to v2
migration detection and prompts
• Added deprecated command handlers
with migration guidance for removed commands
• Updated command
registration and help system for new architecture

+169/-88
middleware.py
FastMCP Middleware for Authentication and Tracking             

src/mcpm/fastmcp_integration/middleware.py

• Added FastMCP middleware for MCPM authentication and unified
tracking
• Implements session-level analytics with request origin
classification
• Includes comprehensive event tracking for tools,
resources, and prompts
• Provides client IP extraction and origin
detection for security monitoring

+402/-0 
global_config.py
Global Server Configuration Manager Implementation             

src/mcpm/global_config.py

• Implemented global server configuration manager for MCPM v2.0

Manages centralized server registry with virtual profile tagging
system
• Includes profile metadata management and server-to-profile
relationships
• Provides comprehensive server lifecycle management
with JSON persistence

+381/-0 
proxy.py
FastMCP Proxy Factory for Server Aggregation                         

src/mcpm/fastmcp_integration/proxy.py

• Created FastMCP proxy factory for MCPM server aggregation
• Supports
both STDIO and Remote server configurations with proper middleware
integration
• Includes authentication and monitoring middleware setup
for proxy instances
• Provides convenience functions for profile-based
and server-based proxy creation

+195/-0 
usage.py
Enhanced usage analytics command with SQLite integration 

src/mcpm/commands/usage.py

• Added comprehensive usage analytics command with SQLite backend

Displays server/profile statistics, session data, and activity
patterns
• Supports filtering by days, server name, or profile name

Includes rich formatting with tables and panels for data visualization

+301/-0 
profile_config.py
Virtual profile system migration with backward compatibility

src/mcpm/profile/profile_config.py

• Migrated from file-based profiles to virtual profile system using
server tags
• Added backward compatibility for legacy profiles.json
migration
• Implemented profile metadata management and server tagging
functionality
• Enhanced profile operations with global configuration
integration

+200/-62
tunnel.py
Tunnel implementation for secure public sharing                   

src/mcpm/core/tunnel.py

• Added complete tunnel implementation for sharing functionality

Includes binary download, checksum verification, and process
management
• Supports HTTP/HTTPS tunneling with configurable
parameters
• Implements frpc client integration for secure public
access

[link]   
share.py
Profile sharing command with secure tunneling                       

src/mcpm/commands/profile/share.py

• Added profile sharing command with FastMCP proxy integration

Implements secure tunneling with optional authentication
• Supports
multiple servers in a profile with unified endpoint
• Includes port
management and public URL generation

+217/-0 
v1_detector.py
V1 configuration detection and backup system                         

src/mcpm/migration/v1_detector.py

• Added v1 configuration detection and analysis functionality

Implements backup creation with timestamped directories
• Provides
detailed analysis of v1 features and migration requirements
• Includes
comprehensive documentation generation for backups

+220/-0 
inspect.py
MCP Inspector command with server integration                       

src/mcpm/commands/inspect.py

• Added inspect command for launching MCP Inspector with server
configurations
• Supports both specific server inspection and raw
inspector mode
• Integrates with global configuration for server
discovery
• Includes comprehensive error handling and user guidance

+200/-0 
base.py
Enhanced monitoring base with session tracking and statistics

src/mcpm/monitor/base.py

• Enhanced monitoring base classes with session tracking and usage
statistics
• Added new event types for session management and
transport tracking
• Implemented comprehensive statistics models for
servers and profiles
• Extended abstract methods for usage analytics
and reporting

+137/-5 
add.py
Migrated add command to global configuration model             

src/mcpm/commands/target_operations/add.py

• Migrated add command to use global configuration instead of
client-specific configs
• Deprecated target parameter and simplified
installation flow
• Removed profile-to-client functionality in favor
of global server management
• Updated command description and examples
for v2.0 architecture

+29/-72 
edit.py
Interactive profile editing command with modern UI             

src/mcpm/commands/profile/edit.py

• Added interactive profile editing command with modern UI
• Supports
both interactive form-based editing and non-interactive options

Implements server selection with search and checkbox interface

Includes profile renaming and server tagging functionality

+188/-0 
Formatting
1 files
get_manifest.py
Code formatting and style improvements                                     

scripts/get_manifest.py

• Code formatting improvements with consistent spacing and line breaks

• Simplified string concatenation and parameter formatting
• Removed
redundant whitespace and improved readability

+79/-149
Tests
8 files
test_stash_pop.py
Updated tests for deprecated v1 commands                                 

tests/test_stash_pop.py

• Replaced comprehensive stash/pop functionality tests with
deprecation error tests
• Added tests for deprecated commands (stash,
pop, mv, cp, target)
• Simplified test structure to verify proper
deprecation messages

+38/-193
test_profile.py
Virtual Profile System Test Updates                                           

tests/test_profile.py

• Updated tests for virtual profile system migration from legacy
profiles.json
• Added tests for profile metadata functionality and
server tagging system
• Includes legacy migration testing and virtual
profile-specific features
• Tests profile operations like creation,
deletion, renaming with global server management

+265/-122
test_client.py
Client Command Tests for V2.0 Architecture                             

tests/test_client.py

• Updated client command tests for new v2.0 architecture without
active client concept
• Modified tests to handle client-specific
server management and MCPM server detection
• Added verbose flag
testing and mixed server type handling (MCPM vs other servers)

Updated command signatures to match new client management approach

+201/-76
test_run.py
Test suite for v2.0 run command functionality                       

tests/test_run.py

• Added comprehensive tests for v2.0 run command with global
configuration
• Tests server execution, error handling, and usage
recording
• Includes tests for missing servers, interrupts, and
command validation
• Note: Tests marked as skipped pending FastMCP
proxy architecture update

+244/-0 
test_access_monitor.py
Updated access monitor tests for SQLite backend                   

tests/test_access_monitor.py

• Updated tests to use SQLiteAccessMonitor instead of
DuckDBAccessMonitor
• Modified test assertions to work with new query
response format
• Updated event querying to use monitor's query_events
method
• Enhanced test coverage for metadata handling and backward
compatibility

+59/-66 
test_migration.py
Migration system test suite for v1 to v2 upgrade                 

tests/test_migration.py

• Added comprehensive test suite for v1 to v2 migration system
• Tests
configuration detection, backup creation, and migration logic

Includes tests for profile migration and stashed server handling

Validates CLI integration and start-fresh functionality

+219/-0 
test_remove.py
Updated remove command tests for global configuration       

tests/test_remove.py

• Updated remove command tests for v2.0 global configuration model

Replaced client-specific tests with global configuration tests
• Added
tests for server removal, confirmation, and error handling

Simplified test structure to match new architecture

+110/-97
test_inspect.py
Inspect command test suite with global configuration         

tests/test_inspect.py

• Added comprehensive test suite for inspect command functionality

Tests server inspection, error handling, and raw inspector mode

Includes tests for missing servers, interrupts, and permission errors

• Validates integration with global configuration system

+203/-0 
Bug fix
1 files
test_windsurf.py
Updated client manager parameter name                                       

tests/test_clients/test_windsurf.py

• Updated parameter name from config_path to config_path_override

Minor API change to align with new client manager interface

+1/-7     
Miscellaneous
3 files
client_config.py
Simplified client configuration manager for v2.0                 

src/mcpm/clients/client_config.py

• Simplified client configuration manager by removing scope-related
functionality
• Removed unused imports and methods related to v1
architecture
• Streamlined class to focus on core client configuration
management

+2/-182 
claude_desktop.py
Updated Claude Desktop manager constructor parameters       

src/mcpm/clients/managers/claude_desktop.py

• Updated constructor parameter from config_path to
config_path_override
• Removed router server import that's no longer
needed
• Maintained backward compatibility while aligning with new
architecture

+5/-22   
goose.py
Updated Goose client manager constructor parameters           

src/mcpm/clients/managers/goose.py

• Updated constructor parameter from config_path to
config_path_override
• Aligned parameter naming with other client
managers
• Maintained existing functionality while improving
consistency

+5/-5     
Additional files
80 files
CLAUDE.md +7/-0     
GEMINI.md +7/-0     
MCPM_Command_Specification.md +196/-0 
MIGRATION_GUIDE.md +187/-0 
README.md +74/-102
README.zh-CN.md +6/-5     
custom-server-config-explained.md +132/-0 
proxy_transport_types.md +88/-0   
index.html +679/-981
index.html +606/-927
pyproject.toml +2/-0     
utils.py +3/-2     
validate_manifest.py +5/-0     
__init__.py +1/-5     
__init__.py +1/-1     
base.py +7/-99   
client_registry.py +23/-74 
claude_code.py +6/-6     
cline.py +41/-17 
continue_extension.py +5/-9     
cursor.py +5/-5     
fiveire.py +5/-5     
trae.py +5/-5     
vscode.py +30/-4   
windsurf.py +5/-5     
__init__.py +22/-8   
config.py +31/-5   
doctor.py +186/-0 
info.py +8/-16   
list.py +58/-70 
migrate.py +51/-0   
profile.py +8/-128 
__init__.py +28/-0   
create.py +26/-0   
inspect.py +130/-0 
interactive.py +73/-0   
list.py +43/-0   
remove.py +66/-0   
run.py +173/-0 
router.py +0/-507 
run.py +167/-0 
target.py +0/-80   
common.py +66/-30 
custom.py +0/-206 
pop.py +0/-81   
remove.py +22/-33 
stash.py +0/-84   
transfer.py +0/-181 
client_connection.py +0/-94   
router.py +0/-377 
schema.py +35/-3   
__init__.py +6/-0     
config.py +51/-0   
__init__.py +8/-0     
__init__.py +5/-3     
duckdb.py +0/-388 
__init__.py +0/-7     
app.py +0/-32   
router.py +0/-445 
router_config.py +0/-20   
sse_app.py +0/-153 
transport.py +0/-273 
watcher.py +0/-72   
config.py +34/-58 
display.py +15/-13 
logging_config.py +91/-0   
router_server.py +0/-31   
scope.py +1/-0     
conftest.py +3/-5     
test_add.py +57/-24 
test_arguments.py +12/-2   
test_cli.py +17/-4   
test_goose.py +1/-1     
test_edit.py +96/-0   
test_fastmcp_proxy.py +148/-0 
test_global_config.py +78/-0   
test_info.py +8/-19   
test_router.py +0/-294 
test_share.py +66/-106
test_virtual_profiles.py +188/-0 

Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • @niechen niechen force-pushed the 198-general-mcpm-v2-command-design branch from 614f6bf to d1aa74d Compare July 2, 2025 08:56
    @qodo-merge-pro
    Copy link
    Contributor

    qodo-merge-pro bot commented Jul 2, 2025

    PR Reviewer Guide 🔍

    (Review updated until commit 396fb81)

    Here are some key observations to aid the review process:

    🎫 Ticket compliance analysis 🔶

    198 - Partially compliant

    Compliant requirements:

    • Complete architectural overhaul implemented with global configuration management
    • New commands added: edit, inspect, usage, run, profile commands, import
    • Profile management system implemented with virtual groups/tags
    • Server sharing functionality implemented via tunnels
    • Migration system from v1 to v2 implemented
    • Client managers updated for v2 architecture
    • Comprehensive test suite added

    Non-compliant requirements:

    • Command aliases (install/uninstall for add/rm) not clearly visible in the diff
    • Doctor command implementation not fully visible in diff

    Requires further human verification:

    • Migration system functionality and user experience
    • FastMCP integration and proxy functionality
    • Tunnel security and authentication mechanisms
    • Interactive command interfaces and user experience
    • Performance impact of SQLite-based monitoring

    ⏱️ Estimated effort to review: 5 🔵🔵🔵🔵🔵
    🧪 PR contains tests
    🔒 Security concerns

    API Key Management:
    The share command generates and stores API keys using secrets.token_urlsafe(32) and saves them via ConfigManager. Need to verify that keys are stored securely, not logged, and properly rotated. The authentication mechanism in FastMCP proxy should be reviewed for proper implementation of Bearer token validation.

    ⚡ Recommended focus areas for review

    Complex Logic

    The client edit command contains very complex logic with multiple nested functions and extensive error handling. The interactive selection logic and conflict detection should be carefully reviewed for edge cases and potential bugs.

    def _interactive_profile_server_selection(
        client_manager,
        config_path,
        current_config,
        current_profiles,
        current_individual_servers,
        available_profiles,
        global_servers,
        client_name,
    ):
        """Interactive profile and server selection using InquirerPy with checkboxes."""
        try:
            # Build choices with current status - profiles first, then servers
            choices = []
    
            # Add profiles (without Rich markup since InquirerPy doesn't support it)
            for profile_name in sorted(available_profiles.keys()):
                profile_servers = available_profiles[profile_name]
                server_names = [server.name for server in profile_servers]
                server_list = ", ".join(server_names[:3])  # Show first 3 servers
                if len(server_names) > 3:
                    server_list += f" +{len(server_names) - 3} more"
                choice_name = f"📦 {profile_name} - Profile ({server_list})"
                is_currently_enabled = profile_name in current_profiles
                choices.append(Choice(value=f"profile:{profile_name}", name=choice_name, enabled=is_currently_enabled))
    
            # Add individual servers with server emoji
            for server_name in sorted(global_servers.keys()):
                server_config = global_servers[server_name]
                description = getattr(server_config, "description", "") or ""
                choice_name = f"🔧 {server_name} - {description[:40]}" + ("..." if len(description) > 40 else "")
                is_currently_enabled = server_name in current_individual_servers
                choices.append(Choice(value=f"server:{server_name}", name=choice_name, enabled=is_currently_enabled))
    
            if not choices:
                console.print("[yellow]No MCPM profiles or servers available to configure.[/]")
                return
    
            # Use InquirerPy checkbox for selection with retry loop for conflicts
            console.print(f"\n[bold]Select profiles/servers to enable in {client_name}:[/]")
            console.print(
                "[dim]📦 = Profiles, 🔧 = Individual servers. Use space to toggle, enter to confirm, ESC to cancel[/]"
            )
    
            while True:  # Retry loop for conflict resolution
                selected_items = inquirer.checkbox(
                    message="Select profiles/servers to enable:",
                    choices=choices,
                    keybindings={"interrupt": [{"key": "escape"}]},
                ).execute()
    
                if selected_items is None:
                    console.print("[yellow]Operation cancelled.[/]")
                    return
    
                # Separate profiles and servers from selection
                selected_profiles = []
                selected_servers = []
    
                for item in selected_items:
                    if item.startswith("profile:"):
                        profile_name = item[8:]  # Remove "profile:" prefix
                        selected_profiles.append(profile_name)
                    elif item.startswith("server:"):
                        server_name = item[7:]  # Remove "server:" prefix
                        selected_servers.append(server_name)
    
                # Check for conflicts
                conflicts = _check_profile_server_conflicts(selected_profiles, selected_servers, available_profiles)
                if conflicts:
                    console.print("\n[red]⚠️  Configuration conflicts detected:[/]")
                    for conflict in conflicts:
                        console.print(f"  [yellow]•[/] {conflict}")
                    console.print("\n[dim]Profiles and individual servers cannot both contain the same server.[/]")
                    console.print("[dim]Please adjust your selection below:[/]\n")
    
                    # Update the choices to reflect current selection for retry
                    for choice in choices:
                        if choice.value in selected_items:
                            choice.enabled = True
                        else:
                            choice.enabled = False
                    continue  # Go back to selection
                else:
                    break  # No conflicts, proceed
    
            # Check if changes were made
            current_profiles_set = set(current_profiles)
            current_servers_set = set(current_individual_servers)
            new_profiles_set = set(selected_profiles)
            new_servers_set = set(selected_servers)
    
            if new_profiles_set == current_profiles_set and new_servers_set == current_servers_set:
                console.print("[yellow]No changes made.[/]")
                return
    
            # Save the updated configuration
            _save_config_with_profiles_and_servers(
                client_manager, config_path, current_config, selected_profiles, selected_servers, client_name
            )
    
            # Show what changed
            added_profiles = new_profiles_set - current_profiles_set
            removed_profiles = current_profiles_set - new_profiles_set
            added_servers = new_servers_set - current_servers_set
            removed_servers = current_servers_set - new_servers_set
    
            if added_profiles:
                console.print(f"[green]Enabled profiles: {', '.join(sorted(added_profiles))}[/]")
            if removed_profiles:
                console.print(f"[red]Disabled profiles: {', '.join(sorted(removed_profiles))}[/]")
            if added_servers:
                console.print(f"[green]Enabled servers: {', '.join(sorted(added_servers))}[/]")
            if removed_servers:
                console.print(f"[red]Disabled servers: {', '.join(sorted(removed_servers))}[/]")
    
        except KeyboardInterrupt:
            console.print("\n[yellow]Operation cancelled.[/]")
        except OSError as e:
            if e.errno == 22:  # Invalid argument - likely terminal issue
                console.print("\n[red]Error: Cannot run interactive selection in this environment.[/]")
                console.print("[yellow]This command requires a proper terminal for interactive selection.[/]")
                console.print("[dim]Try running from a standard terminal or shell.[/]")
            else:
                print_error("System error during selection", str(e))
        except Exception as e:
            console.print(f"[red]Error running interactive selection: {e}[/]")
    
    
    def _check_profile_server_conflicts(selected_profiles, selected_servers, available_profiles):
        """Check for conflicts between selected profiles and individual servers."""
        conflicts = []
    
        # Get all servers that are in selected profiles
        profile_servers = set()
        for profile_name in selected_profiles:
            if profile_name in available_profiles:
                profile_server_configs = available_profiles[profile_name]
                for server_config in profile_server_configs:
                    profile_servers.add(server_config.name)
    
        # Check for overlaps
        conflicting_servers = profile_servers.intersection(set(selected_servers))
    
        for server_name in conflicting_servers:
            # Find which profiles contain this server
            containing_profiles = []
            for profile_name in selected_profiles:
                if profile_name in available_profiles:
                    profile_server_configs = available_profiles[profile_name]
                    for server_config in profile_server_configs:
                        if server_config.name == server_name:
                            containing_profiles.append(profile_name)
                            break
    
            profile_list = "', '".join(containing_profiles)
            conflicts.append(f"Server '{server_name}' is in profile(s) '{profile_list}' and also selected individually")
    
        return conflicts
    Security Concern

    The sharing functionality generates API keys and handles authentication. The security implementation, key generation, and storage mechanisms need thorough review to ensure no vulnerabilities.

    if not no_auth:
        from mcpm.utils.config import ConfigManager
    
        config_manager = ConfigManager()
        auth_config = config_manager.get_auth_config()
        api_key = auth_config.get("api_key")
        if not api_key:
            api_key = secrets.token_urlsafe(32)
            config_manager.save_auth_config(api_key)
            console.print(f"[green]Generated new API key:[/] [cyan]{api_key}[/]")
    
    try:
        # Start FastMCP proxy
        logger.debug(f"Starting FastMCP proxy to share server '{server_name}'")
        actual_port, proxy = await start_fastmcp_proxy(
            server_config, server_name, port, auth_enabled=not no_auth, api_key=api_key
        )
    
        # Start the FastMCP proxy as an HTTP server in a background task
        server_task = asyncio.create_task(
            proxy.run_http_async(port=actual_port, uvicorn_config={"log_level": get_uvicorn_log_level()})
        )
    
        # Wait a moment for server to start
        await asyncio.sleep(2)
    
        # Create and start the tunnel
        logger.debug(f"Creating tunnel from localhost:{actual_port} to {remote_host}:{remote_port}")
        share_token = secrets.token_urlsafe(32)
        tunnel = Tunnel(
            remote_host=remote_host,
            remote_port=remote_port,
            local_host="localhost",
            local_port=actual_port,
            share_token=share_token,
            http=http,
            share_server_tls_certificate=None,
        )
    
        share_url = tunnel.start_tunnel()
    
        if not share_url:
            raise RuntimeError("Could not get share URL from tunnel.")
    
        # Display critical information in a nice panel
        http_url = f"{share_url}/mcp/"
    
        # Build panel content based on auth status
        panel_content = f"[bold]Server:[/] {server_name}\n[bold]URL:[/] [cyan]{http_url}[/cyan]\n"
    
        if not no_auth and api_key:
            panel_content += f"[bold]HEADER Authorization:[/] [cyan]Bearer {api_key}[/cyan]\n"
        else:
            panel_content += "[bold red]⚠️  Warning:[/] Anyone with the URL can access your server\n"
    
        panel_content += "\n[dim]Press Ctrl+C to stop sharing[/]"
    
        panel = Panel(
            panel_content, title="🌍 Server Shared Publicly", title_align="left", border_style="blue", padding=(1, 2)
        )
        console.print(panel)
    
        # Keep running until interrupted
        await server_task
    
    except (KeyboardInterrupt, asyncio.CancelledError):
        console.print("\n[yellow]Stopping...[/]")
    except Exception as e:
        console.print(f"[bold red]Error: {e}[/]")
        logger.exception("Detailed error information")
    finally:
        if tunnel:
            tunnel.kill()
        if server_task and not server_task.done():
            server_task.cancel()
        logger.debug("Sharing stopped")
    Code Quality

    Multiple formatting changes that reduce code readability by condensing multi-line statements into single lines. This makes the code harder to maintain and debug.

    while retry_count < max_retries:
        try:
            completion = self.client.chat.completions.create(
                extra_headers={"HTTP-Referer": os.environ.get("SITE_URL", "https://mcpm.sh"), "X-Title": "MCPM"},
                model="anthropic/claude-3-sonnet",
                messages=[
                    {"role": "system", "content": "Extract concise descriptions from README content."},
                    {
                        "role": "user",
                        "content": (
                            f"Extract a single concise description paragraph from this README "
                            f"content. Focus on what the project does, not how to use it. "
                            f"Keep it under 200 characters if possible:\n\n{readme_content}"
                        ),
                    },
                ],
                temperature=0,
                max_tokens=200,
            )
    
            if not completion.choices or not completion.choices[0].message:
                logger.warning(f"Retry {retry_count + 1}/{max_retries}: Empty completion response")
                retry_count += 1
                continue
    
            description = completion.choices[0].message.content.strip()
    
            # Validate the description
            if not description:
                logger.warning(f"Retry {retry_count + 1}/{max_retries}: Empty description")
                retry_count += 1
                continue
    
            if len(description) < 10:
                logger.warning(f"Retry {retry_count + 1}/{max_retries}: Description too short: {description}")
                retry_count += 1
                continue
    
            return description
    
        except Exception as e:
            logger.error(f"Error extracting description with LLM (try {retry_count + 1}/{max_retries}): {e}")
            retry_count += 1
    
    # If all retries failed, return empty string
    logger.error(f"All {max_retries} attempts to extract description failed")
    return ""

    @qodo-merge-pro
    Copy link
    Contributor

    qodo-merge-pro bot commented Jul 2, 2025

    PR Code Suggestions ✨

    Latest suggestions up to 396fb81
    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Add missing server type field

    The legacy configuration is missing the required type field for server
    configuration. This could cause validation errors during migration since the
    schema expects a server type to be specified.

    tests/test_profile.py [46-50]

     # Create legacy profiles.json file
     legacy_config = {
    -    "test_profile": [{"name": "test-server", "url": "http://localhost:8080/sse", "headers": {}}],
    +    "test_profile": [{"name": "test-server", "type": "sse", "url": "http://localhost:8080/sse", "headers": {}}],
         "empty_profile": [],
     }

    [To ensure code accuracy, apply this suggestion manually]

    Suggestion importance[1-10]: 8

    __

    Why: The suggestion correctly identifies that the type field is missing from the test's legacy configuration, which would cause the ServerConfig validation to fail and the test to be invalid.

    Medium
    General
    Handle non-interactive input gracefully

    The Windows fallback will fail if sys.stdin is not a TTY or in non-interactive
    environments. Add proper error handling to gracefully handle cases where input
    is not available.

    src/mcpm/migration/v1_migrator.py [35-57]

     def _wait_for_keypress(self, message: str):
         """Wait for any key press (cross-platform)"""
         import sys
         import termios
         import tty
     
         console.print(message, end="")
     
         try:
             # Unix/Linux/macOS
             fd = sys.stdin.fileno()
             old_settings = termios.tcgetattr(fd)
             try:
                 tty.setraw(sys.stdin.fileno())
                 sys.stdin.read(1)
             finally:
                 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
         except (ImportError, AttributeError):
             # Windows fallback - use input() which requires Enter
    -        input()
    +        try:
    +            input()
    +        except (EOFError, KeyboardInterrupt):
    +            # Handle non-interactive environments gracefully
    +            pass
     
         console.print()  # Add newline after keypress

    [To ensure code accuracy, apply this suggestion manually]

    Suggestion importance[1-10]: 7

    __

    Why: The suggestion correctly identifies that the input() fallback for Windows can fail in non-interactive environments and proposes adding error handling, which improves the robustness of the migration script.

    Medium
    Remove redundant condition check

    The condition len(args) >= 2 and args[0] == "run" is redundant since it's
    already checked in the parent if statement. This creates unnecessary nested
    logic and could lead to confusion.

    src/mcpm/commands/client.py [279-286]

     # Check if this is an MCPM-managed server (prefixed with mcpm_)
     if client_server_name.startswith("mcpm_") and (
         command == "mcpm" and len(args) >= 2 and args[0] == "run"
     ):
    -    if len(args) >= 2 and args[0] == "run":
    -        # Remove mcpm_ prefix to get actual server name
    -        actual_server_name = args[1]
    -        mcpm_servers.add(actual_server_name)
    +    # Remove mcpm_ prefix to get actual server name
    +    actual_server_name = args[1]
    +    mcmp_servers.add(actual_server_name)
    • Apply / Chat
    Suggestion importance[1-10]: 4

    __

    Why: The suggestion correctly identifies a redundant conditional check, which improves code quality, but the provided improved_code introduces a new bug by misspelling the mcpm_servers variable.

    Low
    Organization
    best practice
    Add formatted examples block

    The import_client command follows the help option pattern but lacks properly
    formatted examples with backslash-escaped blocks. Add structured examples using
    \b blocks to ensure proper display formatting in the help text.

    src/mcpm/commands/client.py [737-747]

     @click.command(name="import", context_settings=dict(help_option_names=["-h", "--help"]))
     @click.argument("client_name")
     def import_client(client_name):
         """Import and manage MCP server configurations from a client.
     
         This command imports server configurations from a supported MCP client,
         shows non-MCPM servers as a selection list, and offers to create profiles
         and replace client config with MCPM managed servers.
     
         CLIENT_NAME is the name of the MCP client to import from (e.g., cursor, claude-desktop, windsurf).
    +
    +    Examples:
    +
    +    \b
    +        mcpm client import cursor           # Import from Cursor
    +        mcpm client import claude-desktop   # Import from Claude Desktop
    +        mcpm client import windsurf         # Import from Windsurf
         """

    [To ensure code accuracy, apply this suggestion manually]

    Suggestion importance[1-10]: 6

    __

    Why:
    Relevant best practice - When implementing command-line interfaces with Click, use consistent help option patterns and provide clear, structured help text with examples. Include both short (-h) and long (--help) options, and format examples using backslash-escaped blocks for proper display.

    Low
    • Update

    Previous suggestions

    ✅ Suggestions up to commit 614f6bf
    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Fix invalid f-string docstring syntax
    Suggestion Impact:The suggestion was implemented - the invalid f-string docstring on line 60 was fixed by removing the 'f' prefix, changing it from 'f"""The '{command_name}' command has been removed in MCPM v2.0."""' to '"""The '{command_name}' command has been removed in MCPM v2.0."""'

    code diff:

    -        f"""The '{command_name}' command has been removed in MCPM v2.0."""

    The f-string docstring is invalid syntax and will cause a runtime error. Remove
    the 'f' prefix from the docstring since it's not being used for formatting.

    src/mcpm/cli.py [49-51]

     def deprecated_command(help_requested, args):
    -    f"""The '{command_name}' command has been removed in MCPM v2.0."""
    +    """The '{command_name}' command has been removed in MCPM v2.0."""
         console.print(f"[bold red]Error:[/] The 'mcpm {command_name}' command has been removed in MCPM v2.0.")
    Suggestion importance[1-10]: 9

    __

    Why: The suggestion correctly identifies an f-string used as a docstring, which is a syntax error that would cause the program to crash at runtime.

    High
    General
    Separate usage tracking from command execution
    Suggestion Impact:The suggestion was implemented but in a different way. Instead of adding a try-except block around the usage tracking import, the commit completely refactored the code to use FastMCP proxy which handles usage tracking through middleware, effectively achieving the same goal of separating usage tracking from core execution

    code diff:

    +        # Note: Usage tracking is handled by proxy middleware

    If the usage tracking import fails, the server execution should still proceed.
    The current code structure could cause the entire command to fail if usage
    tracking is unavailable.

    src/mcpm/commands/run.py [55-61]

     try:
    -    # Record usage
    +    # Record usage (optional)
         from mcpm.commands.usage import record_server_usage
         record_server_usage(server_name, "run")
    +except ImportError:
    +    # Usage tracking not available - continue without it
    +    pass
         
    +try:
         # Execute the command
         result = subprocess.run(...)
    Suggestion importance[1-10]: 7

    __

    Why: The suggestion correctly points out that an ImportError in the optional usage tracking module would prevent the main server execution, and proposes a correct fix by isolating the import in its own try...except block.

    Medium
    Return consistent error structure

    The function should return a consistent error structure instead of None when
    terminal is not available. This ensures callers can handle the error case
    uniformly with the other return values.

    src/mcpm/commands/profile/interactive.py [14-18]

     # Check if we're in a terminal that supports interactive input
     if not sys.stdin.isatty():
         console.print("[yellow]Interactive editing not available in this environment[/]")
         console.print("[dim]Use --name and --servers options for non-interactive editing[/]")
    -    return None
    +    return {"cancelled": True, "error": "Terminal not available"}
    Suggestion importance[1-10]: 6

    __

    Why: The suggestion correctly points out that returning a dictionary instead of None improves the return type consistency of the function, making it easier for the caller to handle different outcomes.

    Low
    Improve error handling specificity

    The bare except clause silently ignores all import errors, which could mask
    legitimate issues. Consider logging the import failure or being more specific
    about which module is expected to be missing.

    src/mcpm/commands/profile/run.py [82-83]

     except ImportError:
    -    pass  # Usage tracking not available
    +    # Usage tracking module not available - this is optional
    +    if debug:
    +        console.print("[dim]Usage tracking not available[/]", err=True)
    Suggestion importance[1-10]: 3

    __

    Why: This is a minor improvement that adds a debug message when the optional usage tracking module is not found, which can aid in debugging.

    Low
    Organization
    best practice
    Add backslash-escaped examples block
    Suggestion Impact:The suggestion was already implemented in the original code. The commit shows that the examples block with backslash-escaped formatting (\b) was already present in the edit_client command help text, exactly as suggested.

    code diff:

         Examples:
     
    @@ -37,54 +38,183 @@
             mcpm client edit cursor           # Interactive server selection for Cursor
             mcpm client edit claude-desktop   # Interactive server selection for Claude Desktop
             mcpm client edit cursor -e        # Open Cursor config in external editor
    +        mcpm client import cursor         # Import server configurations from Cursor
         """

    The help text should use backslash-escaped blocks for proper display of
    examples. Add explicit examples section with \b formatting to ensure proper
    display in the terminal.

    src/mcpm/commands/client.py [84-98]

     @client.command(name="edit", context_settings=dict(help_option_names=["-h", "--help"]))
     @click.argument("client_name")
     @click.option("-e", "--external", is_flag=True, help="Open config file in external editor instead of interactive mode")
     def edit_client(client_name, external):
         """Enable/disable MCPM-managed servers in the specified client configuration.
     
         This command provides an interactive interface to integrate MCPM-managed
         servers into your MCP client by adding or removing 'mcpm run {server}'
         entries in the client config. Uses checkbox selection for easy management.
     
         Use --external/-e to open the config file directly in your default editor
         instead of using the interactive interface.
     
    +    Examples:
    +
    +    \b
    +        mcpm client edit cursor           # Interactive server selection for Cursor
    +        mcpm client edit claude-desktop   # Interactive server selection for Claude Desktop
    +        mcpm client edit cursor -e        # Open Cursor config in external editor
    +
         CLIENT_NAME is the name of the MCP client to configure (e.g., cursor, claude-desktop, windsurf).
         """
    Suggestion importance[1-10]: 6

    __

    Why:
    Relevant best practice - When implementing command-line interfaces with Click, use consistent help option patterns and provide clear, structured help text with examples. Include both short (-h) and long (--help) options, and format examples using backslash-escaped blocks for proper display.

    Low

    @niechen niechen marked this pull request as draft July 2, 2025 09:46
    niechen and others added 15 commits July 3, 2025 02:14
    Remove legacy router daemon and active profile concepts while maintaining
    all v2 command functionalities. Profiles now work as virtual tags only.
    
    ## Major Changes
    
    ### Removed Router Infrastructure
    - Router command and all subcommands (mcpm router on/off/status/set/share/unshare)
    - Router daemon functionality (/src/mcpm/router/ directory)
    - Router configuration management methods
    - Router-based tunneling and sharing
    
    ### Removed Active Profile Concept
    - activate_profile() and deactivate_profile() methods from client managers
    - client_add_profile() function that used router for profile activation
    - Router server formatting utilities
    
    ### Preserved Core Functionality
    - All v2 commands work as before (mcpm install, mcpm profile, mcpm share, etc.)
    - Profile system now works as virtual tags only
    - FastMCP-based sharing via mcpm share and mcpm profile share
    - Client configuration management
    
    ### Backward Compatibility
    - Created minimal RouterConfig class for FastMCP middleware compatibility
    - Created simple Tunnel class to replace router-based tunneling
    - Updated imports throughout codebase
    - Fixed all tests (113 passing)
    
    ### Technical Details
    - No daemon processes required anymore
    - Sharing uses FastMCP proxies directly
    - Profile activation shows proper error message for v2.0
    - Updated connection URLs to show streamable HTTP and SSE endpoints
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    - Fixed 760 linting issues automatically with ruff check --fix --unsafe-fixes
    - Formatted 36 files with ruff format for consistent code style
    - Removed unused variables and improved code quality
    - Fixed whitespace, trailing spaces, and formatting inconsistencies
    - All 113 tests still passing after formatting
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    - Add --verbose/-v flag for detailed server configurations
    - Show only server names and profiles by default for cleaner output
    - Change "tags" to "profiles" in UI for better user understanding
    - Remove duplicate server names (shown only once)
    - Highlight profile names in bright yellow for better visibility
    - Add helpful tip about -v flag when not using verbose mode
    - Maintain backward compatibility with show_name parameter
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    - Add profile support to client edit and ls commands
    - Implement mixed selection UI allowing both profiles and servers
    - Replace color coding with emoji icons (📦 for profiles, 🔧 for servers)
    - Add conflict detection to prevent duplicate servers across profiles
    - Implement retry loop for better UX when conflicts occur
    - Show blank instead of "No description" for servers without descriptions
    - Display actual server names in profile descriptions
    - Update tests to reflect new table structure with profiles column
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    - Add new mcpm edit command for interactive server configuration editing
    - Support STDIO servers (command, args, env) and remote servers (URL, headers)
    - Interactive form-based editing with InquirerPy for better UX
    - Real-time validation and confirmation before applying changes
    - Graceful fallback with clear messaging in non-terminal environments
    - Comprehensive test suite with proper error handling
    - Clean, single-file implementation for maintainability
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    Adds two new arguments to enhance the edit command functionality:
    - -N/--new: Interactive creation of new server configurations
    - -e/--editor: Opens global config file in external editor
    
    Also fixes help formatting and config path reference bug.
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    Implements a global error handler using a decorator to catch all unhandled
    exceptions. This improves user experience by providing a clear message
    and a link to the GitHub issues page.
    
    Tracebacks are now pretty-printed using the 'rich' library for better
    readability and easier debugging.
    Adds a GEMINI.md file to document project-specific conventions for
    the Gemini assistant. This includes instructions to use 'ruff' for
    formatting and 'uv' for dependency management.
    Adds links to the GitHub Issues and Discussions pages in the main help
    documentation. This makes it easier for users to report bugs, request
    features, or provide feedback.
    niechen and others added 3 commits July 4, 2025 17:52
    - Remove active_client, active_target, and active_profile concepts
    - Remove stashed_servers functionality
    - Remove save_share_config and read_share_config methods
    - Simplify ClientConfigManager to only essential methods
    - Update client ls command to remove ACTIVE indicator
    - Fix all tests to work without outdated concepts
    - Update test fixtures to use config_path_override parameter
    
    🤖 Generated with Claude Code
    
    Co-Authored-By: Claude <[email protected]>
    - Add V1ConfigDetector to identify v1 configurations with smart detection
    - Add V1ToV2Migrator with progressive disclosure migration prompts
    - Support three migration paths: migrate, start fresh, or ignore
    - Create timestamped backups in ~/.config/mcpm/backups/ with documentation
    - Migrate v1 profiles to v2 virtual profiles with global servers
    - Handle stashed servers with restore or documentation options
    - Remove v1 config.json completely after migration (not just null values)
    - Exclude auth.json from v1 detection as it's a v2 feature
    - Add cross-platform "press any key" functionality
    - Integrate migration check into all CLI commands
    - Add manual migration command: mcpm migrate
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    This commit completes the middleware consolidation by removing deprecated
    components and switching to a unified event-driven architecture:
    
    **Removed old middleware classes:**
    - MCPMMonitoringMiddleware -> replaced by MCPMUnifiedTrackingMiddleware
    - MCPMUsageTrackingMiddleware -> replaced by MCPMUnifiedTrackingMiddleware
    
    **Removed deprecated database code:**
    - usage_sessions table and all related queries
    - track_session method from AccessMonitor interface
    - session_tracker.py module and its exports
    
    **Updated tracking approach:**
    - All tracking now uses events (SESSION_START/SESSION_END) with session_id linking
    - Usage statistics computed at query time from events table
    - Simplified method delegation to computed stats
    - Maintained backward compatibility for metadata formats
    
    **Benefits:**
    - Single unified middleware handles all tracking automatically
    - Event-driven architecture enables rich analytics
    - Simplified codebase with consistent patterns
    - Better session correlation via session_id
    
    All tests pass and usage command works correctly with computed statistics.
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    @niechen niechen marked this pull request as ready for review July 6, 2025 05:21
    niechen and others added 5 commits July 7, 2025 00:42
    This commit enhances the CLI experience with rich-click integration,
    providing modern, colorful, and well-organized help screens.
    
    **Added rich-click integration:**
    - Added rich-click>=1.8.0 dependency
    - Created comprehensive configuration in utils/rich_click_config.py
    - Updated all 26 command files to use rich-click module
    - Preserved custom main help with ASCII art while enhancing subcommands
    
    **Enhanced CLI features:**
    - Beautiful colored output with syntax highlighting
    - Arguments and options in bordered boxes for clarity
    - Consistent color scheme (cyan for options/commands, yellow for metavars)
    - Smart width handling and better typography
    - Enhanced error messages with helpful suggestions
    - Professional formatting matching modern CLI tools
    
    **Code quality improvements:**
    - Applied ruff formatting to all Python files
    - Fixed all linting issues (unused variables, trailing whitespace)
    - Fixed test failures for changed output format
    - Cleaned up imports and formatting inconsistencies
    
    **Benefits:**
    - More intuitive and visually appealing help screens
    - Better organization of command options and arguments
    - Consistent styling across all commands
    - Improved readability with proper spacing and colors
    - Modern CLI experience while maintaining MCPM branding
    
    All tests pass (122 passed, 6 skipped).
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    - Remove inspector command and related code (separate from inspect command)
    - Reorganize command groups with new structure:
      * Server Execution: run, share, inspect, usage
      * Reorder: Server Management → Server Execution → Client → Profile → System & Configuration
      * Move migrate to System & Configuration group
      * Remove empty Advanced Tools group
    - Update CLI imports and command registration
    - Clean up test files for removed inspector functionality
    - Update migration help text references
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    - Update main CLI description to be more direct about MCPM capabilities
    - Improve client and profile command descriptions with specific examples
    - Add consistent grey-purple footer to all commands for GitHub issues
    - Remove header/footer from subcommands while keeping for main CLI help
    - Implement custom help handling for main command with proper header/footer display
    - Remove duplicate information and streamline footer messaging
    - Use Text objects instead of markup strings to fix rendering issues
    
    Key improvements:
    - Main CLI: Centralized MCP server management with clear value proposition
    - Client command: Explains MCP clients and supported applications
    - Profile command: Describes workflow organization with concrete examples
    - Consistent support footer across all commands with proper styling
    - Clean main command help with ASCII art header and minimal footer
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    Remove unused configuration fields and deprecated modules:
    - Remove deprecated REQUIRED_FIELDS and OPTIONAL_FIELDS ClassVar from FullServerConfig
    - Delete deprecated server_config.py module
    - Remove deprecated --target options from add.py and list.py commands
    - Fix import order and remove unused variables to pass ruff checks
    - Update test expectations for new help output format
    - Restore rich-click command grouping configuration
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    @github-actions
    Copy link
    Contributor

    github-actions bot commented Jul 7, 2025

    PR Summary

    Large-scale refactor that removes the legacy router/middleware stack and replaces it with a unified, event-driven tracking system. Adds FastMCP integration, global config, new CLI command groups (profile, usage, migrate, etc.), switches monitoring from DuckDB to SQLite, updates docs/tests, and cleans up obsolete code.

    Review

    Great cleanup and architectural simplification! A few points to double-check before merge:

    • Migration: README mentions v1→v2 but doesn’t show the exact mcpm migrate example—might trip up existing users.
    • Monitor backend: SQLite is simpler, yet DuckDB offered concurrency; note any limitations in docs.
    • Removed router/* means third-party scripts calling it will break—consider a deprecation stub or clear changelog entry.
    • FastMCP integration looks solid; add a quick smoke test in CI to ensure proxy still starts.
    • Please run pre-commit run --all-files once more; a few changed files (e.g., new commands) lack isort formatting.

    Overall, the consolidation and new features are very welcome—just tighten the migration and docs for a smooth upgrade.


    View workflow run

    niechen and others added 2 commits July 7, 2025 02:03
    Previously, ProfileConfigManager would automatically migrate v1 profiles.json
    files on initialization, which happened before users confirmed they wanted
    to migrate. This caused profiles to be migrated prematurely.
    
    Changes:
    - Removed automatic migration from ProfileConfigManager.__init__
    - Removed unused _migrate_legacy_profiles methods from ProfileConfigManager
    - Added create_profile() method to ProfileConfigManager for V1ToV2Migrator
    - Updated V1ToV2Migrator to also remove profiles.json after migration
    - Updated test to reflect that ProfileConfigManager no longer auto-migrates
    - Fixed ASCII art logo spacing in cli.py and rich_click_config.py
    
    Now profile migration only happens after user explicitly chooses to migrate
    via the V1ToV2Migrator prompt.
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    niechen and others added 3 commits July 7, 2025 02:40
    Comprehensive documentation overhaul to reflect the new v2.0 architecture and
    commands. Based on the actual CLI help output and current implementation.
    
    Changes:
    - Removed MCPM_Command_Specification.md (no longer needed)
    - Updated MIGRATION_GUIDE.md with accurate migration flow and options
    - Updated README.md with correct v2.0 command structure and features
    - Updated docs/advanced_features.md for v2.0 FastMCP integration
    - Updated docs/router_share.md for new sharing system (no separate router)
    
    All documentation now accurately reflects:
    - Global configuration model with virtual profiles
    - Correct command names and options from CLI help
    - v2.0 migration process with user confirmation
    - FastMCP-based sharing instead of router daemon
    - Client integration features
    - Current feature set without deprecated v1 concepts
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    Comprehensive update of all documentation to accurately reflect the v2.0
    implementation and command structure based on actual CLI help output.
    
    Major changes:
    - Removed MCPM_Command_Specification.md (no longer needed)
    - Completely rewrote MIGRATION_GUIDE.md to match actual migration flow
    - Updated README.md with correct v2.0 command structure and features
    - Updated README.zh-CN.md to match English version with v2.0 content
    - Rewrote docs/advanced_features.md for FastMCP integration
    - Updated docs/router_share.md for new sharing system (no router daemon)
    - Completely rewrote docs/router_tech_design.md for v2.0 architecture
    
    Key updates:
    - Global configuration model with virtual profiles
    - Correct command names from CLI help (install/uninstall vs add/rm)
    - v2.0 migration process with user confirmation options
    - FastMCP-based execution and sharing instead of router daemon
    - Client integration commands (mcpm client ls/edit/import)
    - Removed all deprecated v1 target-based concepts
    - Updated Chinese documentation to match English version
    - Consistent terminology and examples throughout
    
    All documentation now accurately reflects the current v2.0 implementation
    without any outdated v1 references.
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
    @niechen niechen changed the title mcpm v2 feat!: mcpm v2 Jul 7, 2025
    @niechen niechen changed the title feat!: mcpm v2 BREAKING CHANGE: mcpm v2 Jul 7, 2025
    @niechen niechen changed the title BREAKING CHANGE: mcpm v2 BREAKING CHANGE: introducing mcpm v2 Jul 7, 2025
    @niechen niechen merged commit e974fb7 into main Jul 7, 2025
    7 checks passed
    @niechen niechen deleted the 198-general-mcpm-v2-command-design branch July 7, 2025 10:31
    @mcpm-semantic-release
    Copy link

    🎉 This PR is included in version 2.0.0 🎉

    The release is available on GitHub release

    Your semantic-release bot 📦🚀

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

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    3 participants