12 Commits

Author SHA1 Message Date
a21199d3db Merge pull request 'fix(mcp): persistent venv cache survives marketplace updates' (#211) from fix/persistent-venv-cache into development
Reviewed-on: #211
2026-01-27 16:49:19 +00:00
1abda1ca0f fix(mcp): persistent venv cache survives marketplace updates
Problem:
- Venvs in marketplace directory got deleted on every update
- Users had to manually run setup.sh and wait for full pip install
- This caused MCP servers to fail until manually fixed

Solution:
- Store venvs in external cache (~/.cache/claude-mcp-venvs/)
- Auto-repair symlinks via SessionStart hook (instant operation)
- Only run pip install on first use or when requirements change

Architecture:
  Cache (runtime) → Marketplaces → External venv cache

  The chain of symlinks ensures all three locations work:
  1. ~/.claude/plugins/cache/.../mcp-servers/* (runtime)
  2. ~/.claude/plugins/marketplaces/.../mcp-servers/* (install)
  3. ~/.cache/claude-mcp-venvs/* (persistent venvs)

Performance:
- First install: ~2-3 min (unchanged)
- After marketplace update: 0.03 sec (was 2-3 min)

Files:
- scripts/venv-repair.sh: Fast symlink restoration for hooks
- scripts/setup-venvs.sh: Full setup with external cache
- plugins/projman/hooks/startup-check.sh: Auto-repair on session start
- .gitignore: Ignore .venv symlinks

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 11:48:13 -05:00
bbb822db16 Merge pull request 'fix(post-update): create missing venvs instead of just warning' (#209) from fix/post-update-create-venvs into development
Reviewed-on: #209
2026-01-27 15:51:39 +00:00
08e1dcb1f5 fix(post-update): create missing venvs instead of just warning
Previously post-update.sh would only warn when venvs were missing,
requiring a separate setup.sh run. Now it automatically creates
missing venvs and installs dependencies including editable packages.

Also added viz-platform and contract-validator to the update list.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 10:41:04 -05:00
1b029d97b8 Merge pull request 'fix/data-platform-filter-index' (#207) from fix/data-platform-filter-index into development
Reviewed-on: #207
2026-01-26 22:27:19 +00:00
4ed3ed7e14 fix(data-platform): reset index after filter to prevent extra column
The filter tool was adding an __index_level_0__ column to results
because pandas query() preserves the original index, which gets
converted to a column when storing the DataFrame.

Added .reset_index(drop=True) after query() to drop the preserved
index and create a clean sequential index.

Fixes #203

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 17:25:37 -05:00
c5232bd7bf Merge pull request 'development' (#202) from development into main
Reviewed-on: #202
2026-01-26 21:49:08 +00:00
f9e23fd6eb Merge pull request 'fix/setup-editable-install' (#201) from fix/setup-editable-install into development
Reviewed-on: #201
2026-01-26 21:48:50 +00:00
457ed9c9ff fix(setup): install MCP packages in editable mode for viz-platform and contract-validator
The setup script only installed requirements.txt dependencies but not the
local package itself, causing MCP servers to fail with ModuleNotFoundError.

Changes:
- Add `pip install -e .` for servers with pyproject.toml
- Add viz-platform and contract-validator to MCP server setup
- Add symlink verification for new plugins
- Update version banner to v5.0.0

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 16:44:11 -05:00
dadb4d3576 Merge pull request 'Merge development into main: contract-validator setup docs' (#200) from development into main 2026-01-26 20:57:23 +00:00
ba771f100f Merge pull request 'docs: add contract-validator initial-setup and update version tags' (#199) from docs/contract-validator-setup into development 2026-01-26 20:57:09 +00:00
2b9cb5defd docs: add contract-validator initial-setup and update version tags
- Add /initial-setup command for contract-validator plugin
- Add contract-validator section to README.md (NEW in v5.0.0)
- Update data-platform version tag: *NEW* -> *NEW in v4.0.0*
- Update viz-platform version tag: *NEW* -> *NEW in v4.0.0*
- Add Contract Validator MCP Server section to README.md
- Add contract-validator to test commands table and repo structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 15:55:17 -05:00
10 changed files with 723 additions and 26 deletions

2
.gitignore vendored
View File

@@ -31,6 +31,8 @@ venv/
ENV/
env/
.venv/
.venv
**/.venv
# PyCharm
.idea/

View File

@@ -53,6 +53,19 @@ Analyze, optimize, and create CLAUDE.md configuration files for Claude Code proj
**Commands:** `/config-analyze`, `/config-optimize`, `/config-init`
#### [contract-validator](./plugins/contract-validator/README.md) *NEW in v5.0.0*
**Cross-Plugin Compatibility Validation**
Validate plugin marketplaces for command conflicts, tool overlaps, and broken agent references.
- Interface parsing from plugin README.md files
- Agent extraction from CLAUDE.md definitions
- Pairwise compatibility checks between all plugins
- Data flow validation for agent sequences
- Markdown or JSON reports with actionable suggestions
**Commands:** `/validate-contracts`, `/check-agent`, `/list-interfaces`, `/initial-setup`
### Productivity
#### [clarity-assist](./plugins/clarity-assist/README.md) *NEW in v3.0.0*
@@ -98,7 +111,7 @@ Full CRUD operations for network infrastructure management directly from Claude
### Data Engineering
#### [data-platform](./plugins/data-platform/README.md) *NEW*
#### [data-platform](./plugins/data-platform/README.md) *NEW in v4.0.0*
**pandas, PostgreSQL/PostGIS, and dbt Integration**
Comprehensive data engineering toolkit with persistent DataFrame storage.
@@ -113,7 +126,7 @@ Comprehensive data engineering toolkit with persistent DataFrame storage.
### Visualization
#### [viz-platform](./plugins/viz-platform/README.md) *NEW*
#### [viz-platform](./plugins/viz-platform/README.md) *NEW in v4.0.0*
**Dash Mantine Components Validation and Theming**
Visualization toolkit with version-locked component validation and design token theming.
@@ -157,7 +170,7 @@ Comprehensive NetBox REST API integration for infrastructure management.
| Virtualization | Clusters, VMs, Interfaces |
| Extras | Tags, Custom Fields, Audit Log |
### Data Platform MCP Server (shared) *NEW*
### Data Platform MCP Server (shared) *NEW in v4.0.0*
pandas, PostgreSQL/PostGIS, and dbt integration for data engineering.
@@ -168,7 +181,7 @@ pandas, PostgreSQL/PostGIS, and dbt integration for data engineering.
| PostGIS | `st_tables`, `st_geometry_type`, `st_srid`, `st_extent` |
| dbt | `dbt_parse`, `dbt_run`, `dbt_test`, `dbt_build`, `dbt_compile`, `dbt_ls`, `dbt_docs_generate`, `dbt_lineage` |
### Viz Platform MCP Server (shared) *NEW*
### Viz Platform MCP Server (shared) *NEW in v4.0.0*
Dash Mantine Components validation and visualization tools.
@@ -180,6 +193,16 @@ Dash Mantine Components validation and visualization tools.
| Theme | `theme_create`, `theme_extend`, `theme_validate`, `theme_export_css`, `theme_list`, `theme_activate` |
| Page | `page_create`, `page_add_navbar`, `page_set_auth`, `page_list`, `page_get_app_config` |
### Contract Validator MCP Server (shared) *NEW in v5.0.0*
Cross-plugin compatibility validation tools.
| Category | Tools |
|----------|-------|
| Parse | `parse_plugin_interface`, `parse_claude_md_agents` |
| Validation | `validate_compatibility`, `validate_agent_refs`, `validate_data_flow` |
| Report | `generate_compatibility_report`, `list_issues` |
## Installation
### Prerequisites
@@ -278,6 +301,7 @@ After installing plugins, the `/plugin` command may show `(no content)` - this i
| cmdb-assistant | `/cmdb-assistant:cmdb-search` |
| data-platform | `/data-platform:ingest` |
| viz-platform | `/viz-platform:chart` |
| contract-validator | `/contract-validator:validate-contracts` |
## Repository Structure
@@ -289,14 +313,16 @@ leo-claude-mktplace/
│ ├── gitea/ # Gitea MCP (issues, PRs, wiki)
│ ├── netbox/ # NetBox MCP (CMDB)
│ ├── data-platform/ # Data engineering (pandas, PostgreSQL, dbt)
── viz-platform/ # Visualization (DMC, Plotly, theming)
── viz-platform/ # Visualization (DMC, Plotly, theming)
│ └── contract-validator/ # Cross-plugin validation (v5.0.0)
├── plugins/ # All plugins
│ ├── projman/ # Sprint management
│ ├── git-flow/ # Git workflow automation
│ ├── pr-review/ # PR review
│ ├── clarity-assist/ # Prompt optimization
│ ├── data-platform/ # Data engineering
│ ├── viz-platform/ # Visualization (NEW)
│ ├── viz-platform/ # Visualization
│ ├── contract-validator/ # Cross-plugin validation (NEW)
│ ├── claude-config-maintainer/ # CLAUDE.md optimization
│ ├── cmdb-assistant/ # NetBox CMDB integration
│ ├── doc-guardian/ # Documentation drift detection

View File

@@ -330,7 +330,7 @@ class PandasTools:
return {'error': f'DataFrame not found: {data_ref}'}
try:
filtered = df.query(condition)
filtered = df.query(condition).reset_index(drop=True)
result_name = name or f"{data_ref}_filtered"
return self._check_and_store(
filtered,

View File

@@ -40,6 +40,7 @@ pip install -r requirements.txt
| Command | Description |
|---------|-------------|
| `/initial-setup` | Interactive setup wizard |
| `/validate-contracts` | Full marketplace compatibility validation |
| `/check-agent` | Validate single agent definition |
| `/list-interfaces` | Show all plugin interfaces |

View File

@@ -0,0 +1,152 @@
---
description: Interactive setup wizard for contract-validator plugin - verifies MCP server and shows capabilities
---
# Contract-Validator Setup Wizard
This command sets up the contract-validator plugin for cross-plugin compatibility validation.
## Important Context
- **This command uses Bash, Read, Write, and AskUserQuestion tools** - NOT MCP tools
- **MCP tools won't work until after setup + session restart**
- **No external credentials required** - this plugin validates local files only
---
## Phase 1: Environment Validation
### Step 1.1: Check Python Version
```bash
python3 --version
```
Requires Python 3.10+. If below, stop setup and inform user:
```
Python 3.10 or higher is required. Please install it and run /initial-setup again.
```
---
## Phase 2: MCP Server Setup
### Step 2.1: Locate Contract-Validator MCP Server
```bash
# If running from installed marketplace
ls -la ~/.claude/plugins/marketplaces/leo-claude-mktplace/mcp-servers/contract-validator/ 2>/dev/null || echo "NOT_FOUND_INSTALLED"
# If running from source
ls -la ~/claude-plugins-work/mcp-servers/contract-validator/ 2>/dev/null || echo "NOT_FOUND_SOURCE"
```
Determine which path exists and use that as the MCP server path.
### Step 2.2: Check Virtual Environment
```bash
ls -la /path/to/mcp-servers/contract-validator/.venv/bin/python 2>/dev/null && echo "VENV_EXISTS" || echo "VENV_MISSING"
```
### Step 2.3: Create Virtual Environment (if missing)
```bash
cd /path/to/mcp-servers/contract-validator && python3 -m venv .venv && source .venv/bin/activate && pip install --upgrade pip && pip install -r requirements.txt && deactivate
```
**If pip install fails:**
- Show the error to the user
- Suggest: "Check your internet connection and try again."
---
## Phase 3: Validation
### Step 3.1: Verify MCP Server
```bash
cd /path/to/mcp-servers/contract-validator && .venv/bin/python -c "from mcp_server.server import ContractValidatorMCPServer; print('MCP Server OK')"
```
If this fails, check the error and report it to the user.
### Step 3.2: Summary
Display:
```
╔════════════════════════════════════════════════════════════════╗
║ CONTRACT-VALIDATOR SETUP COMPLETE ║
╠════════════════════════════════════════════════════════════════╣
║ MCP Server: ✓ Ready ║
║ Parse Tools: ✓ Available (2 tools) ║
║ Validation Tools: ✓ Available (3 tools) ║
║ Report Tools: ✓ Available (2 tools) ║
╚════════════════════════════════════════════════════════════════╝
```
### Step 3.3: Session Restart Notice
---
**Session Restart Required**
Restart your Claude Code session for MCP tools to become available.
**After restart, you can:**
- Run `/validate-contracts` to check all plugins for compatibility issues
- Run `/check-agent` to validate a single agent definition
- Run `/list-interfaces` to see all plugin commands and tools
---
## Available Tools
| Category | Tools | Description |
|----------|-------|-------------|
| Parse | `parse_plugin_interface`, `parse_claude_md_agents` | Extract interfaces from README.md and agents from CLAUDE.md |
| Validation | `validate_compatibility`, `validate_agent_refs`, `validate_data_flow` | Check conflicts, tool references, and data flows |
| Report | `generate_compatibility_report`, `list_issues` | Generate reports and filter issues |
---
## Available Commands
| Command | Description |
|---------|-------------|
| `/validate-contracts` | Full marketplace compatibility validation |
| `/check-agent` | Validate single agent definition |
| `/list-interfaces` | Show all plugin interfaces |
---
## Use Cases
### 1. Pre-Release Validation
Run `/validate-contracts` before releasing a new marketplace version to catch:
- Command name conflicts between plugins
- Missing tool references in agents
- Broken data flows
### 2. Agent Development
Run `/check-agent` when creating or modifying agents to verify:
- All referenced tools exist
- Data flows are valid
- No undeclared dependencies
### 3. Plugin Audit
Run `/list-interfaces` to get a complete view of:
- All commands across plugins
- All tools available
- Potential overlap areas
---
## No Configuration Required
This plugin doesn't require any configuration files. It reads plugin manifests and README files directly from the filesystem.
**Paths it scans:**
- Marketplace: `~/.claude/plugins/marketplaces/leo-claude-mktplace/plugins/`
- Source (if available): `~/claude-plugins-work/plugins/`

View File

@@ -5,13 +5,30 @@
PREFIX="[projman]"
# Check if MCP venv exists
# Calculate paths
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$(dirname "$(realpath "$0")")")}"
VENV_PATH="$PLUGIN_ROOT/mcp-servers/gitea/.venv/bin/python"
# Marketplace root is 2 levels up from plugin root (plugins/projman -> .)
MARKETPLACE_ROOT="$(dirname "$(dirname "$PLUGIN_ROOT")")"
VENV_REPAIR_SCRIPT="$MARKETPLACE_ROOT/scripts/venv-repair.sh"
if [[ ! -f "$VENV_PATH" ]]; then
echo "$PREFIX MCP venvs missing - run setup.sh from installed marketplace"
exit 0
# ============================================================================
# Auto-repair MCP venvs (runs before other checks)
# ============================================================================
if [[ -x "$VENV_REPAIR_SCRIPT" ]]; then
# Run venv repair - this creates symlinks to cached venvs
# Only outputs messages if something needed fixing
"$VENV_REPAIR_SCRIPT" 2>/dev/null || {
echo "$PREFIX MCP venv setup failed - run: cd $MARKETPLACE_ROOT && ./scripts/setup-venvs.sh"
exit 0
}
else
# Fallback: just check if venv exists
VENV_PATH="$PLUGIN_ROOT/mcp-servers/gitea/.venv/bin/python"
if [[ ! -f "$VENV_PATH" ]]; then
echo "$PREFIX MCP venvs missing - run setup.sh from installed marketplace"
exit 0
fi
fi
# Check git remote vs .env config (only if .env exists)

View File

@@ -29,19 +29,41 @@ update_mcp_server() {
local server_name="$1"
local server_path="$REPO_ROOT/mcp-servers/$server_name"
log_info "Updating $server_name dependencies..."
if [[ -d "$server_path/.venv" ]] && [[ -f "$server_path/requirements.txt" ]]; then
cd "$server_path"
source .venv/bin/activate
pip install -q --upgrade pip
pip install -q -r requirements.txt
deactivate
cd "$REPO_ROOT"
log_success "$server_name dependencies updated"
else
log_warn "$server_name not fully set up - run ./scripts/setup.sh first"
if [[ ! -d "$server_path" ]]; then
log_warn "$server_name directory not found at $server_path - skipping"
return 0
fi
if [[ ! -f "$server_path/requirements.txt" ]]; then
log_warn "$server_name has no requirements.txt - skipping"
return 0
fi
cd "$server_path"
# Create venv if missing
if [[ ! -d ".venv" ]]; then
log_info "Creating $server_name venv (was missing)..."
python3 -m venv .venv
log_success "$server_name venv created"
else
log_info "Updating $server_name dependencies..."
fi
# Install/update dependencies
source .venv/bin/activate
pip install -q --upgrade pip
pip install -q -r requirements.txt
# Install local package in editable mode if pyproject.toml exists
if [[ -f "pyproject.toml" ]]; then
pip install -q -e .
log_success "$server_name package installed (editable mode)"
fi
deactivate
cd "$REPO_ROOT"
log_success "$server_name ready"
}
check_changelog() {
@@ -68,6 +90,8 @@ main() {
update_mcp_server "gitea"
update_mcp_server "netbox"
update_mcp_server "data-platform"
update_mcp_server "viz-platform"
update_mcp_server "contract-validator"
check_changelog

281
scripts/setup-venvs.sh Executable file
View File

@@ -0,0 +1,281 @@
#!/usr/bin/env bash
#
# setup-venvs.sh - Smart MCP server venv management with external cache
#
# This script manages Python virtual environments for MCP servers in a
# PERSISTENT location outside the marketplace directory, so they survive
# marketplace updates.
#
# Features:
# - Stores venvs in ~/.cache/claude-mcp-venvs/ (survives updates)
# - Incremental installs (only missing packages)
# - Hash-based change detection (skip if requirements unchanged)
# - Can be called from SessionStart hooks safely
#
# Usage:
# ./scripts/setup-venvs.sh # Full setup
# ./scripts/setup-venvs.sh --check # Check only, no install
# ./scripts/setup-venvs.sh --quick # Skip if hash unchanged
# ./scripts/setup-venvs.sh gitea # Setup specific server only
#
set -euo pipefail
# ============================================================================
# Configuration
# ============================================================================
# Persistent venv location (outside marketplace)
VENV_CACHE_DIR="${HOME}/.cache/claude-mcp-venvs/leo-claude-mktplace"
# Script and repo paths
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
# MCP servers to manage
MCP_SERVERS=(gitea netbox data-platform viz-platform contract-validator)
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Flags
CHECK_ONLY=false
QUICK_MODE=false
SPECIFIC_SERVER=""
# ============================================================================
# Argument Parsing
# ============================================================================
while [[ $# -gt 0 ]]; do
case $1 in
--check)
CHECK_ONLY=true
shift
;;
--quick)
QUICK_MODE=true
shift
;;
-h|--help)
echo "Usage: $0 [OPTIONS] [SERVER]"
echo ""
echo "Options:"
echo " --check Check venv status without installing"
echo " --quick Skip servers with unchanged requirements"
echo " -h,--help Show this help"
echo ""
echo "Servers: ${MCP_SERVERS[*]}"
exit 0
;;
*)
SPECIFIC_SERVER="$1"
shift
;;
esac
done
# ============================================================================
# Helper Functions
# ============================================================================
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_ok() { echo -e "${GREEN}[OK]${NC} $1"; }
log_skip() { echo -e "${YELLOW}[SKIP]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
# Calculate hash of requirements file(s)
requirements_hash() {
local server_path="$1"
local hash_input=""
if [[ -f "$server_path/requirements.txt" ]]; then
hash_input+=$(cat "$server_path/requirements.txt")
fi
if [[ -f "$server_path/pyproject.toml" ]]; then
hash_input+=$(cat "$server_path/pyproject.toml")
fi
echo "$hash_input" | sha256sum | cut -d' ' -f1
}
# Check if requirements changed since last install
requirements_changed() {
local server_name="$1"
local server_path="$2"
local hash_file="$VENV_CACHE_DIR/$server_name/.requirements_hash"
local current_hash
current_hash=$(requirements_hash "$server_path")
if [[ -f "$hash_file" ]]; then
local stored_hash
stored_hash=$(cat "$hash_file")
if [[ "$current_hash" == "$stored_hash" ]]; then
return 1 # Not changed
fi
fi
return 0 # Changed or no hash file
}
# Save requirements hash after successful install
save_requirements_hash() {
local server_name="$1"
local server_path="$2"
local hash_file="$VENV_CACHE_DIR/$server_name/.requirements_hash"
requirements_hash "$server_path" > "$hash_file"
}
# ============================================================================
# Main Setup Function
# ============================================================================
setup_server() {
local server_name="$1"
local server_path="$REPO_ROOT/mcp-servers/$server_name"
local venv_path="$VENV_CACHE_DIR/$server_name/.venv"
# Verify server exists in repo
if [[ ! -d "$server_path" ]]; then
log_error "$server_name: source directory not found at $server_path"
return 1
fi
# Check-only mode
if [[ "$CHECK_ONLY" == true ]]; then
if [[ -f "$venv_path/bin/python" ]]; then
log_ok "$server_name: venv exists"
else
log_error "$server_name: venv MISSING"
return 1
fi
return 0
fi
# Quick mode: skip if requirements unchanged
if [[ "$QUICK_MODE" == true ]] && [[ -f "$venv_path/bin/python" ]]; then
if ! requirements_changed "$server_name" "$server_path"; then
log_skip "$server_name: requirements unchanged"
return 0
fi
fi
log_info "$server_name: setting up venv..."
# Create cache directory
mkdir -p "$VENV_CACHE_DIR/$server_name"
# Create venv if missing
if [[ ! -d "$venv_path" ]]; then
python3 -m venv "$venv_path"
log_ok "$server_name: venv created"
fi
# Activate and install
# shellcheck disable=SC1091
source "$venv_path/bin/activate"
# Upgrade pip quietly
pip install -q --upgrade pip
# Install requirements (incremental - pip handles already-installed)
if [[ -f "$server_path/requirements.txt" ]]; then
pip install -q -r "$server_path/requirements.txt"
fi
# Install local package in editable mode if pyproject.toml exists
if [[ -f "$server_path/pyproject.toml" ]]; then
pip install -q -e "$server_path"
log_ok "$server_name: package installed (editable)"
fi
deactivate
# Save hash for quick mode
save_requirements_hash "$server_name" "$server_path"
log_ok "$server_name: ready"
}
# ============================================================================
# Create Symlinks (for backward compatibility)
# ============================================================================
create_symlinks() {
log_info "Creating symlinks for backward compatibility..."
for server_name in "${MCP_SERVERS[@]}"; do
local server_path="$REPO_ROOT/mcp-servers/$server_name"
local venv_path="$VENV_CACHE_DIR/$server_name/.venv"
local link_path="$server_path/.venv"
# Skip if source doesn't exist
[[ ! -d "$server_path" ]] && continue
# Skip if venv not in cache
[[ ! -d "$venv_path" ]] && continue
# Remove existing venv or symlink
if [[ -L "$link_path" ]]; then
rm "$link_path"
elif [[ -d "$link_path" ]]; then
log_warn "$server_name: removing old venv directory (now using cache)"
rm -rf "$link_path"
fi
# Create symlink
ln -s "$venv_path" "$link_path"
log_ok "$server_name: symlink created"
done
}
# ============================================================================
# Main
# ============================================================================
main() {
echo "=============================================="
echo " MCP Server Venv Manager"
echo "=============================================="
echo "Cache: $VENV_CACHE_DIR"
echo ""
local failed=0
if [[ -n "$SPECIFIC_SERVER" ]]; then
# Setup specific server
if setup_server "$SPECIFIC_SERVER"; then
: # success
else
failed=1
fi
else
# Setup all servers
for server in "${MCP_SERVERS[@]}"; do
if ! setup_server "$server"; then
((failed++)) || true
fi
done
fi
# Create symlinks for backward compatibility
if [[ "$CHECK_ONLY" != true ]]; then
create_symlinks
fi
echo ""
if [[ $failed -eq 0 ]]; then
log_ok "All MCP servers ready"
else
log_error "$failed server(s) failed"
return 1
fi
}
main "$@"

View File

@@ -72,11 +72,16 @@ setup_shared_mcp() {
log_success "$server_name venv created"
fi
# Install/update dependencies
# Install/update dependencies and local package
if [[ -f "requirements.txt" ]]; then
source .venv/bin/activate
pip install -q --upgrade pip
pip install -q -r requirements.txt
# Install local package in editable mode (required for MCP server to work)
if [[ -f "pyproject.toml" ]]; then
pip install -q -e .
log_success "$server_name package installed (editable mode)"
fi
deactivate
log_success "$server_name dependencies installed"
else
@@ -125,6 +130,24 @@ verify_symlinks() {
log_error "data-platform symlink missing"
log_todo "Run: ln -s ../../../mcp-servers/data-platform plugins/data-platform/mcp-servers/data-platform"
fi
# Check viz-platform -> viz-platform symlink
local vizplatform_link="$REPO_ROOT/plugins/viz-platform/mcp-servers/viz-platform"
if [[ -L "$vizplatform_link" ]]; then
log_success "viz-platform symlink exists"
else
log_error "viz-platform symlink missing"
log_todo "Run: ln -s ../../../mcp-servers/viz-platform plugins/viz-platform/mcp-servers/viz-platform"
fi
# Check contract-validator -> contract-validator symlink
local contractvalidator_link="$REPO_ROOT/plugins/contract-validator/mcp-servers/contract-validator"
if [[ -L "$contractvalidator_link" ]]; then
log_success "contract-validator symlink exists"
else
log_error "contract-validator symlink missing"
log_todo "Run: ln -s ../../../mcp-servers/contract-validator plugins/contract-validator/mcp-servers/contract-validator"
fi
}
# --- Section 3: Config File Templates ---
@@ -301,7 +324,7 @@ print_report() {
# --- Main ---
main() {
echo "=============================================="
echo " Leo Claude Marketplace Setup (v3.0.0)"
echo " Leo Claude Marketplace Setup (v5.0.0)"
echo "=============================================="
echo ""
@@ -309,6 +332,8 @@ main() {
setup_shared_mcp "gitea"
setup_shared_mcp "netbox"
setup_shared_mcp "data-platform"
setup_shared_mcp "viz-platform"
setup_shared_mcp "contract-validator"
# Verify symlinks from plugins to shared MCP servers
verify_symlinks

169
scripts/venv-repair.sh Executable file
View File

@@ -0,0 +1,169 @@
#!/usr/bin/env bash
#
# venv-repair.sh - Fast MCP venv auto-repair for SessionStart hooks
#
# This script is designed to run at session start. It:
# 1. Checks if venvs exist in external cache (~/.cache/claude-mcp-venvs/)
# 2. Creates symlinks from marketplace to cache (instant operation)
# 3. Only runs pip install if cache is missing (first install)
#
# Output format: All messages prefixed with [mcp-venv] for hook display
#
# Usage:
# ./scripts/venv-repair.sh # Auto-repair (default)
# ./scripts/venv-repair.sh --silent # Silent mode (no output unless error)
#
set -euo pipefail
# ============================================================================
# Configuration
# ============================================================================
PREFIX="[mcp-venv]"
VENV_CACHE_DIR="${HOME}/.cache/claude-mcp-venvs/leo-claude-mktplace"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
# MCP servers
MCP_SERVERS=(gitea netbox data-platform viz-platform contract-validator)
# Parse args
SILENT=false
[[ "${1:-}" == "--silent" ]] && SILENT=true
log() {
[[ "$SILENT" == true ]] && return
echo "$PREFIX $1"
}
log_error() {
echo "$PREFIX ERROR: $1" >&2
}
# ============================================================================
# Check if all venvs exist in cache
# ============================================================================
cache_complete() {
for server in "${MCP_SERVERS[@]}"; do
local venv_python="$VENV_CACHE_DIR/$server/.venv/bin/python"
[[ ! -f "$venv_python" ]] && return 1
done
return 0
}
# ============================================================================
# Create symlinks from marketplace to cache
# ============================================================================
create_symlink() {
local server_name="$1"
local server_path="$REPO_ROOT/mcp-servers/$server_name"
local venv_cache="$VENV_CACHE_DIR/$server_name/.venv"
local venv_link="$server_path/.venv"
# Skip if server doesn't exist
[[ ! -d "$server_path" ]] && return 0
# Skip if cache doesn't exist
[[ ! -d "$venv_cache" ]] && return 1
# Already correct symlink?
if [[ -L "$venv_link" ]]; then
local target
target=$(readlink "$venv_link")
[[ "$target" == "$venv_cache" ]] && return 0
rm "$venv_link"
elif [[ -d "$venv_link" ]]; then
# Old venv directory exists - back it up or remove
rm -rf "$venv_link"
fi
# Create symlink
ln -s "$venv_cache" "$venv_link"
return 0
}
create_all_symlinks() {
local created=0
for server in "${MCP_SERVERS[@]}"; do
if create_symlink "$server"; then
((created++)) || true
fi
done
[[ $created -gt 0 ]] && log "Restored $created venv symlinks"
}
# ============================================================================
# Full setup (only if cache missing)
# ============================================================================
setup_server() {
local server_name="$1"
local server_path="$REPO_ROOT/mcp-servers/$server_name"
local venv_path="$VENV_CACHE_DIR/$server_name/.venv"
[[ ! -d "$server_path" ]] && return 0
mkdir -p "$VENV_CACHE_DIR/$server_name"
# Create venv
if [[ ! -d "$venv_path" ]]; then
python3 -m venv "$venv_path"
fi
# Install dependencies
# shellcheck disable=SC1091
source "$venv_path/bin/activate"
pip install -q --upgrade pip
if [[ -f "$server_path/requirements.txt" ]]; then
pip install -q -r "$server_path/requirements.txt"
fi
if [[ -f "$server_path/pyproject.toml" ]]; then
pip install -q -e "$server_path"
fi
deactivate
# Save hash for future quick checks
local hash_file="$VENV_CACHE_DIR/$server_name/.requirements_hash"
{
if [[ -f "$server_path/requirements.txt" ]]; then
cat "$server_path/requirements.txt"
fi
if [[ -f "$server_path/pyproject.toml" ]]; then
cat "$server_path/pyproject.toml"
fi
echo "" # Ensure non-empty input for sha256sum
} | sha256sum | cut -d' ' -f1 > "$hash_file"
}
full_setup() {
log "First run - setting up MCP venvs (this only happens once)..."
for server in "${MCP_SERVERS[@]}"; do
log " Setting up $server..."
setup_server "$server"
done
log "Setup complete. Future sessions will be instant."
}
# ============================================================================
# Main
# ============================================================================
main() {
# Fast path: cache exists, just ensure symlinks
if cache_complete; then
create_all_symlinks
exit 0
fi
# Slow path: need to create venvs (first install)
full_setup
create_all_symlinks
}
main "$@"