Compare commits
14 Commits
v5.0.0
...
7492cfad66
| Author | SHA1 | Date | |
|---|---|---|---|
| 7492cfad66 | |||
| 59db9ea0b0 | |||
| a21199d3db | |||
| 1abda1ca0f | |||
| bbb822db16 | |||
| 08e1dcb1f5 | |||
| 1b029d97b8 | |||
| 4ed3ed7e14 | |||
| c5232bd7bf | |||
| f9e23fd6eb | |||
| 457ed9c9ff | |||
| dadb4d3576 | |||
| ba771f100f | |||
| 2b9cb5defd |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -31,6 +31,8 @@ venv/
|
|||||||
ENV/
|
ENV/
|
||||||
env/
|
env/
|
||||||
.venv/
|
.venv/
|
||||||
|
.venv
|
||||||
|
**/.venv
|
||||||
|
|
||||||
# PyCharm
|
# PyCharm
|
||||||
.idea/
|
.idea/
|
||||||
|
|||||||
38
README.md
38
README.md
@@ -53,6 +53,19 @@ Analyze, optimize, and create CLAUDE.md configuration files for Claude Code proj
|
|||||||
|
|
||||||
**Commands:** `/config-analyze`, `/config-optimize`, `/config-init`
|
**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
|
### Productivity
|
||||||
|
|
||||||
#### [clarity-assist](./plugins/clarity-assist/README.md) *NEW in v3.0.0*
|
#### [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 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**
|
**pandas, PostgreSQL/PostGIS, and dbt Integration**
|
||||||
|
|
||||||
Comprehensive data engineering toolkit with persistent DataFrame storage.
|
Comprehensive data engineering toolkit with persistent DataFrame storage.
|
||||||
@@ -113,7 +126,7 @@ Comprehensive data engineering toolkit with persistent DataFrame storage.
|
|||||||
|
|
||||||
### Visualization
|
### 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**
|
**Dash Mantine Components Validation and Theming**
|
||||||
|
|
||||||
Visualization toolkit with version-locked component validation and design token 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 |
|
| Virtualization | Clusters, VMs, Interfaces |
|
||||||
| Extras | Tags, Custom Fields, Audit Log |
|
| 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.
|
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` |
|
| 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` |
|
| 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.
|
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` |
|
| 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` |
|
| 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
|
## Installation
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
@@ -278,6 +301,7 @@ After installing plugins, the `/plugin` command may show `(no content)` - this i
|
|||||||
| cmdb-assistant | `/cmdb-assistant:cmdb-search` |
|
| cmdb-assistant | `/cmdb-assistant:cmdb-search` |
|
||||||
| data-platform | `/data-platform:ingest` |
|
| data-platform | `/data-platform:ingest` |
|
||||||
| viz-platform | `/viz-platform:chart` |
|
| viz-platform | `/viz-platform:chart` |
|
||||||
|
| contract-validator | `/contract-validator:validate-contracts` |
|
||||||
|
|
||||||
## Repository Structure
|
## Repository Structure
|
||||||
|
|
||||||
@@ -289,14 +313,16 @@ leo-claude-mktplace/
|
|||||||
│ ├── gitea/ # Gitea MCP (issues, PRs, wiki)
|
│ ├── gitea/ # Gitea MCP (issues, PRs, wiki)
|
||||||
│ ├── netbox/ # NetBox MCP (CMDB)
|
│ ├── netbox/ # NetBox MCP (CMDB)
|
||||||
│ ├── data-platform/ # Data engineering (pandas, PostgreSQL, dbt)
|
│ ├── 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
|
├── plugins/ # All plugins
|
||||||
│ ├── projman/ # Sprint management
|
│ ├── projman/ # Sprint management
|
||||||
│ ├── git-flow/ # Git workflow automation
|
│ ├── git-flow/ # Git workflow automation
|
||||||
│ ├── pr-review/ # PR review
|
│ ├── pr-review/ # PR review
|
||||||
│ ├── clarity-assist/ # Prompt optimization
|
│ ├── clarity-assist/ # Prompt optimization
|
||||||
│ ├── data-platform/ # Data engineering
|
│ ├── data-platform/ # Data engineering
|
||||||
│ ├── viz-platform/ # Visualization (NEW)
|
│ ├── viz-platform/ # Visualization
|
||||||
|
│ ├── contract-validator/ # Cross-plugin validation (NEW)
|
||||||
│ ├── claude-config-maintainer/ # CLAUDE.md optimization
|
│ ├── claude-config-maintainer/ # CLAUDE.md optimization
|
||||||
│ ├── cmdb-assistant/ # NetBox CMDB integration
|
│ ├── cmdb-assistant/ # NetBox CMDB integration
|
||||||
│ ├── doc-guardian/ # Documentation drift detection
|
│ ├── doc-guardian/ # Documentation drift detection
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ class PandasTools:
|
|||||||
return {'error': f'DataFrame not found: {data_ref}'}
|
return {'error': f'DataFrame not found: {data_ref}'}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
filtered = df.query(condition)
|
filtered = df.query(condition).reset_index(drop=True)
|
||||||
result_name = name or f"{data_ref}_filtered"
|
result_name = name or f"{data_ref}_filtered"
|
||||||
return self._check_and_store(
|
return self._check_and_store(
|
||||||
filtered,
|
filtered,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ pip install -r requirements.txt
|
|||||||
|
|
||||||
| Command | Description |
|
| Command | Description |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
|
| `/initial-setup` | Interactive setup wizard |
|
||||||
| `/validate-contracts` | Full marketplace compatibility validation |
|
| `/validate-contracts` | Full marketplace compatibility validation |
|
||||||
| `/check-agent` | Validate single agent definition |
|
| `/check-agent` | Validate single agent definition |
|
||||||
| `/list-interfaces` | Show all plugin interfaces |
|
| `/list-interfaces` | Show all plugin interfaces |
|
||||||
|
|||||||
152
plugins/contract-validator/commands/initial-setup.md
Normal file
152
plugins/contract-validator/commands/initial-setup.md
Normal 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/`
|
||||||
@@ -5,13 +5,30 @@
|
|||||||
|
|
||||||
PREFIX="[projman]"
|
PREFIX="[projman]"
|
||||||
|
|
||||||
# Check if MCP venv exists
|
# Calculate paths
|
||||||
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$(dirname "$(realpath "$0")")")}"
|
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"
|
# Auto-repair MCP venvs (runs before other checks)
|
||||||
exit 0
|
# ============================================================================
|
||||||
|
|
||||||
|
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
|
fi
|
||||||
|
|
||||||
# Check git remote vs .env config (only if .env exists)
|
# Check git remote vs .env config (only if .env exists)
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# post-update.sh - Run after pulling updates
|
# post-update.sh - Run after pulling updates or marketplace sync
|
||||||
#
|
#
|
||||||
# Usage: ./scripts/post-update.sh
|
# Usage: ./scripts/post-update.sh
|
||||||
#
|
#
|
||||||
# This script:
|
# This script:
|
||||||
# 1. Updates Python dependencies for MCP servers
|
# 1. Restores MCP venv symlinks (instant if cache exists)
|
||||||
# 2. Validates configuration still works
|
# 2. Creates venvs in external cache if missing (first run only)
|
||||||
# 3. Reports any new manual steps from CHANGELOG
|
# 3. Shows recent changelog updates
|
||||||
#
|
#
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -19,42 +19,25 @@ REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
|||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
BLUE='\033[0;34m'
|
BLUE='\033[0;34m'
|
||||||
|
RED='\033[0;31m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||||
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
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"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
check_changelog() {
|
check_changelog() {
|
||||||
log_info "Checking CHANGELOG for recent updates..."
|
|
||||||
|
|
||||||
if [[ -f "$REPO_ROOT/CHANGELOG.md" ]]; then
|
if [[ -f "$REPO_ROOT/CHANGELOG.md" ]]; then
|
||||||
# Show the Unreleased section
|
local unreleased
|
||||||
echo ""
|
unreleased=$(sed -n '/## \[Unreleased\]/,/## \[/p' "$REPO_ROOT/CHANGELOG.md" | grep -E '^### ' | head -1 || true)
|
||||||
echo "Recent changes (from CHANGELOG.md):"
|
if [[ -n "$unreleased" ]]; then
|
||||||
echo "-----------------------------------"
|
echo ""
|
||||||
sed -n '/## \[Unreleased\]/,/## \[/p' "$REPO_ROOT/CHANGELOG.md" | head -30
|
log_info "Recent changes (from CHANGELOG.md):"
|
||||||
echo "-----------------------------------"
|
echo "-----------------------------------"
|
||||||
echo ""
|
sed -n '/## \[Unreleased\]/,/## \[/p' "$REPO_ROOT/CHANGELOG.md" | head -20
|
||||||
|
echo "-----------------------------------"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,23 +47,28 @@ main() {
|
|||||||
echo "=============================================="
|
echo "=============================================="
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Shared MCP servers at repository root (v3.0.0+)
|
# Run venv-repair.sh to restore symlinks to external cache
|
||||||
update_mcp_server "gitea"
|
# This is instant if cache exists, or does full setup on first run
|
||||||
update_mcp_server "netbox"
|
if [[ -x "$SCRIPT_DIR/venv-repair.sh" ]]; then
|
||||||
update_mcp_server "data-platform"
|
log_info "Restoring MCP venv symlinks..."
|
||||||
|
if "$SCRIPT_DIR/venv-repair.sh"; then
|
||||||
|
log_success "MCP venvs ready"
|
||||||
|
else
|
||||||
|
log_error "MCP venv setup failed"
|
||||||
|
log_warn "Run: $SCRIPT_DIR/setup-venvs.sh for full setup"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_error "venv-repair.sh not found at $SCRIPT_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
check_changelog
|
check_changelog
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
log_success "Post-update complete!"
|
log_success "Post-update complete!"
|
||||||
echo ""
|
echo ""
|
||||||
echo "If you see new features in the changelog that require"
|
echo "MCP servers will work immediately on next session start."
|
||||||
echo "configuration changes, update your ~/.config/claude/*.env files."
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
||||||
# Clear plugin cache to ensure fresh hooks are loaded
|
|
||||||
echo "Clearing plugin cache..."
|
|
||||||
rm -rf ~/.claude/plugins/cache/leo-claude-mktplace/
|
|
||||||
echo "Cache cleared"
|
|
||||||
|
|||||||
281
scripts/setup-venvs.sh
Executable file
281
scripts/setup-venvs.sh
Executable 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 "$@"
|
||||||
@@ -72,11 +72,16 @@ setup_shared_mcp() {
|
|||||||
log_success "$server_name venv created"
|
log_success "$server_name venv created"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Install/update dependencies
|
# Install/update dependencies and local package
|
||||||
if [[ -f "requirements.txt" ]]; then
|
if [[ -f "requirements.txt" ]]; then
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
pip install -q --upgrade pip
|
pip install -q --upgrade pip
|
||||||
pip install -q -r requirements.txt
|
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
|
deactivate
|
||||||
log_success "$server_name dependencies installed"
|
log_success "$server_name dependencies installed"
|
||||||
else
|
else
|
||||||
@@ -125,6 +130,24 @@ verify_symlinks() {
|
|||||||
log_error "data-platform symlink missing"
|
log_error "data-platform symlink missing"
|
||||||
log_todo "Run: ln -s ../../../mcp-servers/data-platform plugins/data-platform/mcp-servers/data-platform"
|
log_todo "Run: ln -s ../../../mcp-servers/data-platform plugins/data-platform/mcp-servers/data-platform"
|
||||||
fi
|
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 ---
|
# --- Section 3: Config File Templates ---
|
||||||
@@ -301,7 +324,7 @@ print_report() {
|
|||||||
# --- Main ---
|
# --- Main ---
|
||||||
main() {
|
main() {
|
||||||
echo "=============================================="
|
echo "=============================================="
|
||||||
echo " Leo Claude Marketplace Setup (v3.0.0)"
|
echo " Leo Claude Marketplace Setup (v5.0.0)"
|
||||||
echo "=============================================="
|
echo "=============================================="
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
@@ -309,6 +332,8 @@ main() {
|
|||||||
setup_shared_mcp "gitea"
|
setup_shared_mcp "gitea"
|
||||||
setup_shared_mcp "netbox"
|
setup_shared_mcp "netbox"
|
||||||
setup_shared_mcp "data-platform"
|
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 from plugins to shared MCP servers
|
||||||
verify_symlinks
|
verify_symlinks
|
||||||
|
|||||||
169
scripts/venv-repair.sh
Executable file
169
scripts/venv-repair.sh
Executable 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 "$@"
|
||||||
Reference in New Issue
Block a user