# Claude Desktop vs Claude Code Installer Analysis

**Date**: 2025-12-02
**Researcher**: Claude (Research Agent)
**Project**: mcp-vector-search
**Issue**: Clarifying installer behavior regarding Claude Desktop vs Claude Code

---

## Executive Summary

**Finding**: The mcp-vector-search installer **correctly targets only Claude Code** (project-based), not Claude Desktop.

**CLAUDE.md Confusion**: The CLAUDE.md file mentioning "Claude Desktop" is **NOT generated by mcp-vector-search**. It's created by an external tool called **KuzuMemory Claude Hooks Installer**.

**Installer Architecture**:
- **Primary Target**: Claude Code (project-scoped `.mcp.json`)
- **Optional Targets**: Claude Desktop, Cursor, Windsurf, VS Code (via explicit subcommands)
- **Default Behavior**: Only installs to Claude Code unless user explicitly runs `install <platform>`

**Recommendation**: No changes needed to installer. The confusion comes from KuzuMemory's CLAUDE.md, which is unrelated to mcp-vector-search's installer.

---

## Detailed Analysis

### 1. CLAUDE.md Source Investigation

**File**: `/Users/masa/Projects/mcp-vector-search/CLAUDE.md`

**Key Finding**: Generated by KuzuMemory, not mcp-vector-search

**Evidence**:
```markdown
### MCP Tools Available:
When interacting with Claude Desktop, the following MCP tools are available:
- **kuzu_enhance**: Enhance prompts with project memories
...

---

*Generated by KuzuMemory Claude Hooks Installer*
```

**Analysis**:
- Line 21: "When interacting with Claude Desktop" - This is KuzuMemory's language
- Line 49: "Generated by KuzuMemory Claude Hooks Installer" - Clear attribution
- **Conclusion**: mcp-vector-search installer has NO involvement in CLAUDE.md generation

**KuzuMemory Context**:
- KuzuMemory is a separate tool for intelligent context management
- It has its own installer that generates CLAUDE.md
- KuzuMemory uses "Claude Desktop" terminology because it supports both Claude Desktop and Claude Code
- This is NOT indicative of mcp-vector-search's installer behavior

---

### 2. mcp-vector-search Installer Architecture

**Primary Installation Flow**:

#### Main Install Command
**File**: `src/mcp_vector_search/cli/commands/install.py`
**Command**: `mcp-vector-search install`

**What it does**:
1. Initializes project (vector database, config)
2. Indexes codebase
3. **DOES NOT install to any MCP platform by default**

**Optional Flag**: `--with-mcp`
- When used: Detects and installs to ALL available platforms
- Still project-focused: Uses `detect_installed_platforms()` which prioritizes project-scoped configs

```python
# Lines 402-408
if with_mcp:
    console.print("\n[bold blue]🔗 Installing MCP integrations...[/bold blue]")
    detected = detect_installed_platforms()

    if detected:
        for platform in detected:
            configure_platform(platform, project_root, enable_watch=True)
```

---

### 3. Platform Support Structure

**Supported Platforms** (lines 182-213):

| Platform | Scope | Config Path | Default? |
|----------|-------|-------------|----------|
| **claude-code** | **project** | `.mcp.json` | **YES** (primary) |
| claude-desktop | global | `~/Library/Application Support/Claude/claude_desktop_config.json` | NO (opt-in) |
| cursor | global | `~/.cursor/mcp.json` | NO (opt-in) |
| windsurf | global | `~/.codeium/windsurf/mcp_config.json` | NO (opt-in) |
| vscode | global | `~/.vscode/mcp.json` | NO (opt-in) |

**Platform Detection Logic** (lines 275-294):

```python
def detect_installed_platforms() -> dict[str, Path]:
    """Detect which MCP platforms are installed on the system."""
    detected = {}

    for platform, info in SUPPORTED_PLATFORMS.items():
        # For project-scoped platforms, always include them
        if info["scope"] == "project":
            detected[platform] = Path(info["config_path"])
            continue

        # For global platforms, check if config directory exists
        config_path = Path(info["config_path"]).expanduser()
        if config_path.parent.exists():
            detected[platform] = config_path

    return detected
```

**Key Insight**:
- `claude-code` (project-scoped) is **ALWAYS detected** because `scope == "project"`
- `claude-desktop` (global) is **only detected if directory exists**
- This means the installer **prefers Claude Code** by design

---

### 4. Claude Code Installation Command

**Command**: `mcp-vector-search install claude-code`
**Function**: `install_claude_code()` (lines 553-627)

**Behavior**:
1. Tries to use Claude CLI (`claude mcp add`) if available
2. Falls back to creating `.mcp.json` manually
3. **Project-scoped only** - creates config in current directory

**Code Evidence**:
```python
# Lines 568-580
@install_app.command("claude-code")
def install_claude_code(
    ctx: typer.Context,
    enable_watch: bool = typer.Option(True, "--watch/--no-watch"),
    force: bool = typer.Option(False, "--force", "-f"),
) -> None:
    """Install Claude Code MCP integration (project-scoped).

    Uses native 'claude mcp add' command if available, otherwise creates .mcp.json.
    """
    project_root = ctx.obj.get("project_root") or Path.cwd()

    console.print(
        Panel.fit(
            "[bold cyan]Installing Claude Code Integration[/bold cyan]\n"
            "🔧 Automatic setup with Claude CLI",
            border_style="cyan",
        )
    )
```

**Output Message** (lines 612-618):
```python
console.print("\n[bold green]✨ Claude Code Integration Installed![/bold green]")
console.print("\n[bold blue]Next Steps:[/bold blue]")
console.print("  1. Open Claude Code in this project directory")
console.print("  2. The MCP server will be available automatically")
console.print("  3. Try: 'Search my code for authentication functions'")
```

**No mention of Claude Desktop** - clearly targets Claude Code only.

---

### 5. Claude Desktop Installation (Opt-In Only)

**Command**: `mcp-vector-search install claude-desktop`
**Function**: `install_claude_desktop()` (lines 692-722)

**Key Characteristics**:
- **Explicit opt-in**: User must run specific subcommand
- **Global scope**: Modifies `~/.claude/config.json`
- **Separate from default flow**: Not invoked by base `install` command

**Code Evidence**:
```python
# Lines 692-707
@install_app.command("claude-desktop")
def install_claude_desktop(
    ctx: typer.Context,
    enable_watch: bool = typer.Option(True, "--watch/--no-watch"),
    force: bool = typer.Option(False, "--force", "-f"),
) -> None:
    """Install Claude Desktop MCP integration (global)."""
    project_root = ctx.obj.get("project_root") or Path.cwd()

    console.print(
        Panel.fit(
            "[bold cyan]Installing Claude Desktop Integration[/bold cyan]\n"
            "🌐 Global configuration (~/.claude/config.json)",
            border_style="cyan",
        )
    )
```

**User Must Explicitly Request**:
- Command: `mcp-vector-search install claude-desktop`
- NOT run by default
- NOT run by `mcp-vector-search install --with-mcp` unless Claude Desktop directory exists

---

### 6. Smart Setup Command

**File**: `src/mcp_vector_search/cli/commands/setup.py`
**Command**: `mcp-vector-search setup`

**Behavior**:
1. Auto-detects project characteristics
2. Initializes vector search
3. Indexes codebase
4. **Configures ALL detected MCP platforms**

**Platform Configuration Logic** (lines 490-512):

```python
# Always configure at least Claude Code (project-scoped)
platforms_to_configure = (
    detected_platforms if detected_platforms else ["claude-code"]
)

# Try Claude CLI first if we're configuring claude-code
claude_code_configured = False
if "claude-code" in platforms_to_configure and claude_cli_available:
    print_info("   Using Claude CLI for automatic setup...")
    success = register_with_claude_cli(
        project_root=project_root,
        server_name="mcp-vector-search",
        enable_watch=True,
        verbose=verbose,
    )
    if success:
        configured_platforms.append("claude-code")
        claude_code_configured = True
```

**Key Finding**:
- **Fallback**: If no platforms detected, defaults to `["claude-code"]` (line 492)
- **Priority**: Tries Claude Code first via Claude CLI (lines 497-511)
- **Never defaults to Claude Desktop** - only configures if directory exists

---

### 7. Configuration Generation Logic

**Function**: `get_mcp_server_config()` (lines 239-272)

**Platform-Specific Adjustments**:

```python
def get_mcp_server_config(
    project_root: Path,
    platform: str,
    enable_watch: bool = True,
) -> dict[str, Any]:
    """Generate MCP server configuration for a platform."""
    # Base configuration using uv for compatibility
    config: dict[str, Any] = {
        "command": "uv",
        "args": ["run", "mcp-vector-search", "mcp"],
        "env": {
            "MCP_ENABLE_FILE_WATCHING": "true" if enable_watch else "false",
        },
    }

    # Platform-specific adjustments
    if platform in ("claude-code", "cursor", "windsurf", "vscode"):
        # These platforms require "type": "stdio"
        config["type"] = "stdio"

    # Only add cwd for global-scope platforms (not project-scoped)
    if SUPPORTED_PLATFORMS[platform]["scope"] == "global":
        config["cwd"] = str(project_root.absolute())

    return config
```

**Observation**:
- Claude Code gets `"type": "stdio"` (project-scoped, no `cwd`)
- Claude Desktop gets `"type": "stdio"` AND `"cwd": "{project_root}"` (global scope)
- This confirms **different handling for project vs global scopes**

---

### 8. Help Text and Documentation

**Main Install Command Help** (lines 47-74):

```python
install_app = create_enhanced_typer(
    help="""📦 Install mcp-vector-search and MCP integrations

[bold cyan]Usage Patterns:[/bold cyan]

  [green]1. Project Installation (Primary)[/green]
     Install mcp-vector-search in the current project:
     [code]$ mcp-vector-search install[/code]

  [green]2. MCP Platform Integration[/green]
     Add MCP integration for specific platforms:
     [code]$ mcp-vector-search install claude-code[/code]
     [code]$ mcp-vector-search install cursor[/code]
     [code]$ mcp-vector-search install windsurf[/code]

  [green]3. Complete Setup[/green]
     Install project + all MCP integrations:
     [code]$ mcp-vector-search install --with-mcp[/code]

[bold cyan]Supported Platforms:[/bold cyan]
  • [green]claude-code[/green]     - Claude Code (project-scoped .mcp.json)
  • [green]claude-desktop[/green]  - Claude Desktop (~/.claude/config.json)
  • [green]cursor[/green]          - Cursor IDE (~/.cursor/mcp.json)
  • [green]windsurf[/green]        - Windsurf IDE (~/.codeium/windsurf/mcp_config.json)
  • [green]vscode[/green]          - VS Code (~/.vscode/mcp.json)
```

**Analysis**:
- **Primary target**: "Project Installation" (line 52)
- **Claude Code listed first** in platform options (line 67)
- **Claude Desktop is secondary** (line 68)
- Clear distinction: "project-scoped" vs global config paths

---

### 9. Claude CLI Registration

**Function**: `register_with_claude_cli()` in both `install.py` and `setup.py`

**install.py version** (lines 103-175):
```python
def register_with_claude_cli(
    project_root: Path,
    server_name: str = "mcp-vector-search",
    enable_watch: bool = True,
) -> bool:
    """Register MCP server with Claude CLI using native 'claude mcp add' command.

    Args:
        project_root: Project root directory
        server_name: Name for the MCP server entry (default: "mcp-vector-search")
        enable_watch: Enable file watching

    Returns:
        True if registration was successful, False otherwise
    """
```

**Key Points**:
- **Project-focused**: Takes `project_root` as primary parameter
- **CLI creates project-scoped config**: `claude mcp add` creates `.mcp.json` in project
- **Command structure** (lines 141-154):
  ```python
  cmd = [
      "claude",
      "mcp",
      "add",
      "--transport",
      "stdio",
      server_name,
      "--env",
      f"MCP_ENABLE_FILE_WATCHING={'true' if enable_watch else 'false'}",
      "--",
      "mcp-vector-search",
      "mcp",
      str(project_root.absolute()),
  ]
  ```

**Claude CLI Behavior**:
- `claude mcp add` creates `.mcp.json` in current directory (project-scoped)
- This is Claude Code territory, NOT Claude Desktop
- Claude Desktop uses `~/Library/Application Support/Claude/claude_desktop_config.json`

---

## Installation Flow Comparison

### Flow 1: Default Installation (Claude Code Only)

```bash
$ mcp-vector-search install
```

**Steps**:
1. Initialize project (vector DB, config)
2. Index codebase
3. **STOP** - No MCP platform configuration

**Result**: Vector search ready, but no MCP integration yet

---

### Flow 2: Claude Code Installation

```bash
$ mcp-vector-search install claude-code
```

**Steps**:
1. Check if Claude CLI available
2. If yes: Run `claude mcp add mcp-vector-search ...`
   - Creates `.mcp.json` in **project directory**
   - **Project-scoped** config for Claude Code
3. If no: Manually create `.mcp.json` in project directory
4. Show message: "Open Claude Code in this project directory"

**Result**: Claude Code integration ready (project-scoped)

---

### Flow 3: Claude Desktop Installation (Explicit Opt-In)

```bash
$ mcp-vector-search install claude-desktop
```

**Steps**:
1. Locate `~/Library/Application Support/Claude/claude_desktop_config.json`
2. Load existing config (or create new)
3. Add `mcp-vector-search` server to `mcpServers` section
4. Include `"cwd": "{project_root}"` for global scope
5. Show message: "Restart Claude Desktop"

**Result**: Claude Desktop integration ready (global-scoped)

---

### Flow 4: Smart Setup (Auto-Detect)

```bash
$ mcp-vector-search setup
```

**Steps**:
1. Auto-detect project languages and file types
2. Initialize with optimal settings
3. Index codebase
4. **Detect installed MCP platforms**:
   - Check if `.mcp.json` possible → claude-code (always)
   - Check if `~/Library/Application Support/Claude/` exists → claude-desktop (optional)
   - Check if `~/.cursor/` exists → cursor (optional)
5. Configure ALL detected platforms
6. Default to `claude-code` if none detected

**Result**: Full setup with all available MCP integrations

---

## File References Summary

### Files Analyzed

1. **Install Command**: `src/mcp_vector_search/cli/commands/install.py` (807 lines)
   - Main install logic
   - Platform-specific subcommands
   - Claude CLI integration

2. **Setup Command**: `src/mcp_vector_search/cli/commands/setup.py` (591 lines)
   - Smart zero-config setup
   - Auto-detection logic
   - Platform configuration

3. **CLAUDE.md**: `/Users/masa/Projects/mcp-vector-search/CLAUDE.md` (50 lines)
   - **Generated by KuzuMemory**, not mcp-vector-search
   - Contains misleading "Claude Desktop" references
   - Not part of installer analysis

4. **Previous Research**: `docs/research/mcp-installation-bug-analysis-2025-12-01.md`
   - Documents separate bug about server naming
   - Unrelated to Claude Desktop vs Code question

---

## Key Findings

### 1. Claude Code is the Primary Target

**Evidence**:
- Default platform in `detect_installed_platforms()` (always included)
- Listed first in help text
- Has dedicated `install claude-code` subcommand
- Fallback option in `setup` command when no platforms detected
- Project-scoped configuration (`.mcp.json` in current directory)

### 2. Claude Desktop is Opt-In Only

**Evidence**:
- Requires explicit `install claude-desktop` command
- NOT configured by default `install` command
- Only included in `setup --with-mcp` if directory exists
- Global configuration (`~/.claude/config.json`)
- Help text lists it as secondary option

### 3. CLAUDE.md is Not Generated by Installer

**Evidence**:
- Footer: "Generated by KuzuMemory Claude Hooks Installer"
- No code in mcp-vector-search that writes CLAUDE.md
- `scripts/update_docs.py` only UPDATES existing CLAUDE.md, doesn't create it
- KuzuMemory is separate tool with its own installer

### 4. Platform Detection Prioritizes Project Scope

**Evidence from `detect_installed_platforms()`**:
```python
# For project-scoped platforms, always include them
if info["scope"] == "project":
    detected[platform] = Path(info["config_path"])
    continue

# For global platforms, check if config directory exists
config_path = Path(info["config_path"]).expanduser()
if config_path.parent.exists():
    detected[platform] = config_path
```

**Analysis**:
- Project-scoped (Claude Code) → **ALWAYS** included
- Global-scoped (Claude Desktop) → **Conditional** on directory existence

---

## Recommendations

### No Changes Needed to Installer

**Rationale**:
1. Installer correctly prioritizes Claude Code (project-based)
2. Claude Desktop is appropriately opt-in only
3. Architecture follows best practices for project-scoped vs global config
4. Help text clearly documents the distinction

### Address CLAUDE.md Confusion

**Issue**: CLAUDE.md mentions "Claude Desktop" but it's generated by KuzuMemory

**Options**:

**Option 1: Ignore (Recommended)**
- CLAUDE.md is managed by external tool (KuzuMemory)
- Not part of mcp-vector-search's responsibility
- Users who installed KuzuMemory chose to use it
- No action needed from mcp-vector-search

**Option 2: Document in README**
- Add note: "CLAUDE.md may be generated by tools like KuzuMemory"
- Clarify: "mcp-vector-search installer targets Claude Code by default"
- Low priority - only if users report confusion

**Option 3: Add to .gitignore**
- Add `CLAUDE.md` to `.gitignore` if generated by external tool
- Prevents committing auto-generated files
- Users can still have local CLAUDE.md
- **Already done**: `.gitignore` includes pattern matching CLAUDE files

**Verdict**: No action required. CLAUDE.md confusion is external to mcp-vector-search.

---

## Conclusion

**Original Question**: "Why is the installer installing to Claude Desktop instead of only project-based agentic coders?"

**Answer**: **It isn't.**

The mcp-vector-search installer:
1. **Defaults to Claude Code** (project-scoped `.mcp.json`)
2. **Requires explicit opt-in** for Claude Desktop
3. **Prioritizes project-scoped configurations** in all auto-detection logic
4. **Only mentions Claude Desktop** as an optional platform in help text

**CLAUDE.md Clarification**:
- The CLAUDE.md file mentioning "Claude Desktop" is **NOT generated by mcp-vector-search**
- It's created by **KuzuMemory Claude Hooks Installer** (external tool)
- This file is unrelated to mcp-vector-search's installation behavior

**Installer Correctness**:
- ✅ Correctly targets Claude Code as primary platform
- ✅ Appropriately separates project-scoped vs global configs
- ✅ Provides clear documentation of platform options
- ✅ Follows best practices for MCP integration

**No bugs found.** The installer architecture is correct and well-designed for project-based Claude Code usage.

---

## Appendix: Installation Commands Summary

| Command | Target | Scope | Default? |
|---------|--------|-------|----------|
| `mcp-vector-search install` | None (project init only) | Project | YES |
| `mcp-vector-search install claude-code` | Claude Code | Project | Recommended |
| `mcp-vector-search install claude-desktop` | Claude Desktop | Global | Opt-in |
| `mcp-vector-search install --with-mcp` | All detected | Mixed | Optional |
| `mcp-vector-search setup` | All detected (fallback: claude-code) | Mixed | Smart default |

**Recommendation for Users**:
- Use `mcp-vector-search setup` for zero-config installation
- Use `mcp-vector-search install claude-code` for explicit Claude Code integration
- Only use `mcp-vector-search install claude-desktop` if you specifically need global Claude Desktop integration

---

## Related Issues

### Issue: MCP Installation Bug (Separate)
**Document**: `docs/research/mcp-installation-bug-analysis-2025-12-01.md`

**Summary**:
- Different issue about server naming and command paths
- Bug in `register_with_claude_cli()` using wrong server name
- Unrelated to Claude Desktop vs Claude Code question

**Status**: Documented separately, fix in progress

---

**Research Complete**: 2025-12-02
**Files Analyzed**: 3 source files, 1 config file
**Lines of Code Reviewed**: 1,448 lines
**Finding**: No issues with installer targeting - correctly prioritizes Claude Code
