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
"""
Setup command implementation.
"""
import builtins
import logging
from pathlib import Path
import click
from rich.console import Console
from rich.progress import (
BarColumn,
DownloadColumn,
Progress,
SpinnerColumn,
TextColumn,
TimeRemainingColumn,
TransferSpeedColumn,
)
from mcp_skills.cli.commands.install import _install_hooks
from mcp_skills.models.repository import Repository
from mcp_skills.services.agent_detector import AgentDetector
from mcp_skills.services.agent_installer import AgentInstaller
from mcp_skills.services.indexing import IndexingEngine
from mcp_skills.services.repository_manager import RepositoryManager
from mcp_skills.services.skill_manager import SkillManager
from mcp_skills.services.toolchain_detector import ToolchainDetector
console = Console()
logger = logging.getLogger(__name__)
# Store builtin list to avoid shadowing in annotations
ListType = builtins.list
@click.command()
@click.option(
"--project-dir",
default=".",
type=click.Path(exists=True),
help="Project directory to analyze",
)
@click.option(
"--config",
default="~/.mcp-skillset/config.yaml",
type=click.Path(),
help="Config file location",
)
@click.option("--auto", is_flag=True, help="Non-interactive setup with defaults")
@click.option(
"--skip-agents",
is_flag=True,
help="Skip automatic installation for AI agents",
)
def setup(project_dir: str, config: str, auto: bool, skip_agents: bool) -> None:
"""Auto-configure mcp-skillset for your project.
This command will:
1. Detect your project's toolchain
2. Clone relevant skill repositories
3. Index skills with vector + KG
4. Configure MCP server
5. Validate setup
6. Install for AI agents (Claude Code, Auggie by default; excludes Claude Desktop)
7. Optionally install Claude Code hooks for automatic skill hints
"""
console.print("π [bold green]Starting mcp-skillset setup...[/bold green]")
console.print(f"π Project directory: {project_dir}")
console.print(f"βοΈ Config location: {config}\n")
try:
# 1. Toolchain detection
console.print("[bold cyan]Step 1/7:[/bold cyan] Detecting project toolchain...")
detector = ToolchainDetector()
project_path = Path(project_dir).resolve()
toolchain = detector.detect(project_path)
console.print(
f" β Primary language: [bold]{toolchain.primary_language}[/bold]"
)
if toolchain.frameworks:
console.print(f" β Frameworks: {', '.join(toolchain.frameworks)}")
if toolchain.test_frameworks:
console.print(
f" β Test frameworks: {', '.join(toolchain.test_frameworks)}"
)
console.print(f" β Confidence: {toolchain.confidence:.0%}\n")
# 2. Repository cloning
console.print(
"[bold cyan]Step 2/7:[/bold cyan] Setting up skill repositories..."
)
repo_manager = RepositoryManager()
# Get default repos or prompt user
if auto:
repos_to_add = RepositoryManager.DEFAULT_REPOS
console.print(" Using default repositories (--auto mode)")
else:
console.print("\n Available default repositories:")
for i, repo in enumerate(RepositoryManager.DEFAULT_REPOS, 1):
console.print(f" {i}. {repo['url']} (priority: {repo['priority']})")
if click.confirm("\n Clone default repositories?", default=True):
repos_to_add = RepositoryManager.DEFAULT_REPOS
else:
repos_to_add = []
console.print(
" [dim]You can add repositories later with: mcp-skillset repo add <url>[/dim]"
)
# Clone repositories with per-repository progress bars
added_repos: ListType[Repository] = []
with Progress(
SpinnerColumn(),
TextColumn("[bold blue]{task.description}"),
BarColumn(bar_width=40),
DownloadColumn(),
TransferSpeedColumn(),
TimeRemainingColumn(),
console=console,
) as progress:
for repo_config in repos_to_add:
# Extract repo name from URL for display
repo_name = repo_config["url"].split("/")[-1].replace(".git", "")
try:
# Check if already exists
repo_id = repo_manager._generate_repo_id(repo_config["url"])
existing = repo_manager.get_repository(repo_id)
if existing:
console.print(
f" β Repository already exists: {repo_config['url']}"
)
added_repos.append(existing)
else:
# Create task for this repository
task_id = progress.add_task(
f"Cloning {repo_name}",
total=100, # Will be updated by callback
start=False,
)
# Progress callback updates this specific task
def make_callback(tid: int): # type: ignore[misc]
def update_progress(
current: int, total: int, _message: str
) -> None:
if total > 0:
progress.update(tid, completed=current, total=total)
if not progress.tasks[tid].started:
progress.start_task(tid)
return update_progress
new_repo = repo_manager.add_repository_with_progress(
url=repo_config["url"],
priority=repo_config["priority"],
license=repo_config.get("license", "Unknown"),
progress_callback=make_callback(task_id),
)
progress.update(
task_id, description=f"β {repo_name}", completed=100
)
added_repos.append(new_repo)
console.print(f" β Cloned {new_repo.skill_count} skills")
except Exception as e:
console.print(
f" [red]β Failed to clone {repo_config['url']}: {e}[/red]"
)
logger.error(f"Repository clone failed: {e}")
if not added_repos:
console.print(
"\n [yellow]No repositories configured. Add some with: mcp-skillset repo add <url>[/yellow]"
)
console.print()
# 3. Indexing
console.print("[bold cyan]Step 3/7:[/bold cyan] Building skill indices...")
skill_manager = SkillManager()
indexing_engine = IndexingEngine(skill_manager=skill_manager)
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
console=console,
) as progress:
task = progress.add_task(" Indexing skills...", total=None)
try:
stats = indexing_engine.reindex_all(force=True)
progress.update(task, completed=True)
console.print(f" β Indexed {stats.total_skills} skills")
console.print(f" β Vector store: {stats.vector_store_size // 1024} KB")
console.print(
f" β Knowledge graph: {stats.graph_nodes} nodes, {stats.graph_edges} edges\n"
)
except Exception as e:
progress.stop()
console.print(f" [red]β Indexing failed: {e}[/red]")
logger.error(f"Indexing failed: {e}")
# 4. MCP configuration
console.print("[bold cyan]Step 4/7:[/bold cyan] Configuring MCP server...")
base_dir = Path.home() / ".mcp-skillset"
console.print(f" β Base directory: {base_dir}")
console.print(f" β ChromaDB: {base_dir / 'chromadb'}")
console.print(f" β Repositories: {base_dir / 'repos'}\n")
# 5. Validation
console.print("[bold cyan]Step 5/7:[/bold cyan] Validating setup...")
repos = repo_manager.list_repositories()
skills = skill_manager.discover_skills()
validation_ok = True
if not repos:
console.print(" [red]β No repositories configured[/red]")
validation_ok = False
else:
console.print(f" β {len(repos)} repositories configured")
if not skills:
console.print(" [red]β No skills discovered[/red]")
validation_ok = False
else:
console.print(f" β {len(skills)} skills available")
if stats.total_skills == 0:
console.print(" [red]β No skills indexed[/red]")
validation_ok = False
else:
console.print(f" β {stats.total_skills} skills indexed")
console.print()
# 6. Agent installation (if not skipped)
agents_installed = 0
if not skip_agents:
console.print()
console.print(
"[bold cyan]Step 6/7:[/bold cyan] Installing for AI agents..."
)
agent_detector = AgentDetector()
# Exclude Claude Desktop by default (config path conflicts with Claude Code)
all_agents = agent_detector.detect_all()
found_agents = [
a for a in all_agents if a.exists and a.id != "claude-desktop"
]
if found_agents:
console.print(f" β Detected {len(found_agents)} agent(s):")
for agent in found_agents:
console.print(f" β’ {agent.name}")
# Ask for confirmation (respect auto flag)
should_install = auto or click.confirm(
"\n Install mcp-skillset for these agents?", default=True
)
if should_install:
installer = AgentInstaller()
success_count = 0
for agent in found_agents:
try:
result = installer.install(agent)
if result.success:
console.print(f" β {agent.name} configured")
success_count += 1
else:
console.print(
f" β {agent.name} failed: {result.error or 'Unknown error'}"
)
except Exception as e:
console.print(f" β {agent.name} error: {str(e)}")
console.print(
f"\n Installed for {success_count}/{len(found_agents)} agent(s)"
)
agents_installed = success_count
else:
console.print(" Skipped agent installation")
else:
console.print(
" No AI agents detected (Claude Desktop, Claude Code, Auggie)"
)
console.print(
" You can install manually later with: mcp-skillset install"
)
else:
console.print(
"\n[dim]Skipped agent installation (--skip-agents flag)[/dim]"
)
# 7. Hook installation (optional)
hooks_installed = False
if not skip_agents and agents_installed > 0:
console.print()
console.print(
"[bold cyan]Step 7/7:[/bold cyan] Claude Code hooks (optional)..."
)
console.print(
" Hooks automatically suggest relevant skills when you type prompts."
)
# Ask for confirmation (respect auto flag)
should_install_hooks = auto or click.confirm(
"\n Install Claude Code hooks for automatic skill hints?",
default=True,
)
if should_install_hooks:
try:
if _install_hooks(dry_run=False, force=False):
console.print(" β Hooks installed successfully")
hooks_installed = True
else:
console.print(
" [dim]Hooks not installed (already configured or Claude Code not found)[/dim]"
)
except Exception as e:
console.print(f" [yellow]β Hook installation failed: {e}[/yellow]")
logger.warning(f"Hook installation failed: {e}")
else:
console.print(" Skipped hook installation")
console.print(
" [dim]You can install later with: mcp-skillset install --with-hooks[/dim]"
)
console.print()
# Summary
if validation_ok:
console.print("[bold green]β Setup complete![/bold green]\n")
console.print("Next steps:")
if agents_installed > 0:
console.print(
" 1. [cyan]Restart your AI agent[/cyan] to load mcp-skillset"
)
console.print(" 2. [cyan]Explore skills:[/cyan] mcp-skillset demo")
console.print(
" 3. [cyan]Search skills:[/cyan] mcp-skillset search 'python testing'"
)
if hooks_installed:
console.print(
" 4. [cyan]Skills will be suggested automatically[/cyan] when you type prompts!"
)
else:
console.print(
" 4. [cyan]Enable auto-hints:[/cyan] mcp-skillset install --with-hooks"
)
else:
console.print(
" 1. [cyan]Install for agents:[/cyan] mcp-skillset install"
)
console.print(" 2. [cyan]Explore skills:[/cyan] mcp-skillset demo")
console.print(
" 3. [cyan]Search skills:[/cyan] mcp-skillset search 'python testing'"
)
console.print(
" 4. [cyan]Show skill:[/cyan] mcp-skillset show <skill-id>"
)
console.print()
console.print(
"[dim]π‘ Tip: Try 'mcp-skillset demo' to see example questions for each skill![/dim]"
)
else:
console.print(
"[bold yellow]β Setup completed with warnings[/bold yellow]\n"
)
console.print(
"Please check the errors above and run setup again if needed."
)
except KeyboardInterrupt:
console.print("\n[yellow]Setup cancelled by user[/yellow]")
raise SystemExit(1)
except Exception as e:
console.print(f"\n[red]Setup failed: {e}[/red]")
logger.exception("Setup failed")
raise SystemExit(1)