We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bobmatnyc/mcp-skills'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""AI Agent Detection Module.
Detects installed AI agents (Claude Desktop, Claude Code, Auggie, Cursor,
Windsurf, Continue, Codex, Gemini CLI) by checking for their configuration
files in platform-specific directories.
Design Decision: Cross-platform path detection with environment variable support
Rationale: Different platforms store application data in different locations.
This module abstracts platform-specific logic to provide consistent detection
across macOS, Windows, and Linux.
Trade-offs:
- Simplicity: Hard-coded paths vs. registry/config scanning
- Coverage: Known agents vs. plugin architecture for extensibility
- Performance: File system checks are fast enough for this use case
Alternatives Considered:
1. Registry scanning (Windows): Rejected - adds complexity, not all agents register
2. Process scanning: Rejected - agent may not be running during install
3. Plugin architecture: Deferred - YAGNI until more agents need support
Future Extensibility: AgentConfig dataclass allows easy addition of new agents
by simply adding entries to AGENT_CONFIGS list.
"""
from __future__ import annotations
import os
import platform
from dataclasses import dataclass
from pathlib import Path
@dataclass
class AgentConfig:
"""Configuration for an AI agent detection.
Attributes:
name: Human-readable agent name (e.g., "Claude Desktop")
id: Machine-readable identifier (e.g., "claude-desktop")
config_paths: Platform-specific paths to config directory
config_file: Name of the config file to modify
config_key_path: JSON path to MCP servers configuration
"""
name: str
id: str
config_paths: dict[str, Path]
config_file: str
config_key_path: str = "mcpServers"
@dataclass
class DetectedAgent:
"""Information about a detected AI agent.
Attributes:
name: Human-readable agent name
id: Machine-readable identifier
config_path: Absolute path to the configuration file
exists: Whether the config file currently exists
"""
name: str
id: str
config_path: Path
exists: bool
# Agent configuration registry
AGENT_CONFIGS = [
AgentConfig(
name="Claude Desktop",
id="claude-desktop",
config_paths={
"darwin": Path.home() / "Library" / "Application Support" / "Claude",
"win32": (
Path(os.environ.get("APPDATA", "")) / "Claude"
if platform.system() == "Windows"
else Path()
),
"linux": Path.home() / ".config" / "Claude",
},
config_file="claude_desktop_config.json",
),
AgentConfig(
name="Claude Code",
id="claude-code",
config_paths={
"darwin": Path.home() / "Library" / "Application Support" / "Code" / "User",
"win32": (
Path(os.environ.get("APPDATA", "")) / "Code" / "User"
if platform.system() == "Windows"
else Path()
),
"linux": Path.home() / ".config" / "Code" / "User",
},
config_file="settings.json",
),
AgentConfig(
name="Auggie",
id="auggie",
config_paths={
"darwin": Path.home() / "Library" / "Application Support" / "Auggie",
"win32": (
Path(os.environ.get("APPDATA", "")) / "Auggie"
if platform.system() == "Windows"
else Path()
),
"linux": Path.home() / ".config" / "Auggie",
},
config_file="config.json",
),
AgentConfig(
name="Cursor",
id="cursor",
config_paths={
"darwin": Path.home() / ".cursor",
"win32": (
Path.home() / ".cursor" if platform.system() == "Windows" else Path()
),
"linux": Path.home() / ".cursor",
},
config_file="mcp.json",
),
AgentConfig(
name="Windsurf",
id="windsurf",
config_paths={
"darwin": Path.home() / ".codeium" / "windsurf",
"win32": (
Path.home() / ".codeium" / "windsurf"
if platform.system() == "Windows"
else Path()
),
"linux": Path.home() / ".codeium" / "windsurf",
},
config_file="mcp_config.json",
),
AgentConfig(
name="Continue",
id="continue",
config_paths={
"darwin": Path.home() / ".continue",
"win32": (
Path.home() / ".continue" if platform.system() == "Windows" else Path()
),
"linux": Path.home() / ".continue",
},
config_file="config.json",
),
AgentConfig(
name="Codex",
id="codex",
config_paths={
"darwin": Path.home() / ".codex",
"win32": (
Path.home() / ".codex" if platform.system() == "Windows" else Path()
),
"linux": Path.home() / ".codex",
},
config_file="config.toml",
),
AgentConfig(
name="Gemini CLI",
id="gemini-cli",
config_paths={
"darwin": Path.home() / ".gemini",
"win32": (
Path.home() / ".gemini" if platform.system() == "Windows" else Path()
),
"linux": Path.home() / ".gemini",
},
config_file="settings.json",
),
]
class AgentDetector:
"""Detects installed AI agents on the current system.
Performance:
- Time Complexity: O(n) where n is number of configured agents
- Space Complexity: O(n) for storing detection results
- File system checks are I/O bound, typically <10ms per agent
Usage:
detector = AgentDetector()
agents = detector.detect_all()
for agent in agents:
if agent.exists:
print(f"Found {agent.name} at {agent.config_path}")
"""
def __init__(self) -> None:
"""Initialize agent detector with current platform."""
self.platform = self._get_platform()
def _get_platform(self) -> str:
"""Get normalized platform identifier.
Returns:
Platform identifier: 'darwin', 'win32', or 'linux'
Error Handling:
Unknown platforms default to 'linux' (most compatible)
"""
system = platform.system().lower()
if system == "darwin":
return "darwin"
elif system == "windows":
return "win32"
else:
return "linux"
def detect_agent(self, agent_id: str) -> DetectedAgent | None:
"""Detect a specific AI agent by ID.
Args:
agent_id: Agent identifier (e.g., 'claude-desktop')
Returns:
DetectedAgent if found, None if agent_id is unknown
Example:
agent = detector.detect_agent("claude-desktop")
if agent and agent.exists:
print(f"Config at: {agent.config_path}")
"""
config = self._get_agent_config(agent_id)
if not config:
return None
config_dir = config.config_paths.get(self.platform)
if not config_dir:
return None
config_path = config_dir / config.config_file
exists = config_path.exists()
return DetectedAgent(
name=config.name,
id=config.id,
config_path=config_path,
exists=exists,
)
def detect_all(self) -> list[DetectedAgent]:
"""Detect all configured AI agents.
Returns:
List of DetectedAgent objects for all known agents on this platform
Example:
agents = detector.detect_all()
installed = [a for a in agents if a.exists]
print(f"Found {len(installed)} installed agents")
"""
detected = []
for config in AGENT_CONFIGS:
config_dir = config.config_paths.get(self.platform)
if not config_dir:
continue
config_path = config_dir / config.config_file
exists = config_path.exists()
detected.append(
DetectedAgent(
name=config.name,
id=config.id,
config_path=config_path,
exists=exists,
)
)
return detected
def _get_agent_config(self, agent_id: str) -> AgentConfig | None:
"""Get configuration for a specific agent.
Args:
agent_id: Agent identifier
Returns:
AgentConfig if found, None otherwise
"""
for config in AGENT_CONFIGS:
if config.id == agent_id:
return config
return None