Merge remote-tracking branch 'upstream/main' into feat/native-claude-cli-detection
This commit is contained in:
@@ -11,7 +11,7 @@ __pycache__/
|
|||||||
env/
|
env/
|
||||||
venv/
|
venv/
|
||||||
.venv/
|
.venv/
|
||||||
.zen_venv/
|
.pal_venv/
|
||||||
ENV/
|
ENV/
|
||||||
env.bak/
|
env.bak/
|
||||||
venv.bak/
|
venv.bak/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Zen MCP Server Environment Configuration
|
# PAL MCP Server Environment Configuration
|
||||||
# Copy this file to .env and fill in your values
|
# Copy this file to .env and fill in your values
|
||||||
|
|
||||||
# API Keys - At least one is required
|
# API Keys - At least one is required
|
||||||
@@ -191,7 +191,7 @@ DISABLED_TOOLS=analyze,refactor,testgen,secaudit,docgen,tracer
|
|||||||
# LOCALE=fr-FR
|
# LOCALE=fr-FR
|
||||||
|
|
||||||
# ===========================================
|
# ===========================================
|
||||||
# Zen MCP Server Configuration
|
# PAL MCP Server Configuration
|
||||||
# ===========================================
|
# ===========================================
|
||||||
|
|
||||||
# Force .env file values to override system environment variables
|
# Force .env file values to override system environment variables
|
||||||
@@ -213,7 +213,7 @@ DISABLED_TOOLS=analyze,refactor,testgen,secaudit,docgen,tracer
|
|||||||
# Development with multiple AI tools: true (prevents tool conflicts)
|
# Development with multiple AI tools: true (prevents tool conflicts)
|
||||||
# Production/Container deployments: false (preserves security practices)
|
# Production/Container deployments: false (preserves security practices)
|
||||||
# CI/CD environments: false (respects pipeline secrets)
|
# CI/CD environments: false (respects pipeline secrets)
|
||||||
ZEN_MCP_FORCE_ENV_OVERRIDE=false
|
PAL_MCP_FORCE_ENV_OVERRIDE=false
|
||||||
|
|
||||||
# ===========================================
|
# ===========================================
|
||||||
# Docker Configuration
|
# Docker Configuration
|
||||||
@@ -221,7 +221,7 @@ ZEN_MCP_FORCE_ENV_OVERRIDE=false
|
|||||||
|
|
||||||
# Container name for Docker Compose
|
# Container name for Docker Compose
|
||||||
# Used when running with docker-compose.yml
|
# Used when running with docker-compose.yml
|
||||||
COMPOSE_PROJECT_NAME=zen-mcp
|
COMPOSE_PROJECT_NAME=pal-mcp
|
||||||
|
|
||||||
# Timezone for Docker containers
|
# Timezone for Docker containers
|
||||||
# Ensures consistent time handling in containerized environments
|
# Ensures consistent time handling in containerized environments
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -12,7 +12,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Project Version
|
label: Project Version
|
||||||
description: "Which version are you using? (To see version: ./run-server.sh -v)"
|
description: "Which version are you using? (To see version: ./run-server.sh -v)"
|
||||||
placeholder: "e.g., 5.1.0"
|
placeholder: "e.g., 9.4.1"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ body:
|
|||||||
id: logs
|
id: logs
|
||||||
attributes:
|
attributes:
|
||||||
label: Relevant Log Output
|
label: Relevant Log Output
|
||||||
description: "Please copy and paste any relevant log output. Logs are stored under the `logs` folder in the zen folder. You an also use `./run-server.sh -f` to see logs"
|
description: "Please copy and paste any relevant log output. Logs are stored under the `logs` folder in the pal folder. You an also use `./run-server.sh -f` to see logs"
|
||||||
render: shell
|
render: shell
|
||||||
|
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
|
|||||||
6
.github/ISSUE_TEMPLATE/config.yml
vendored
6
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,12 +1,12 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: 💬 General Discussion
|
- name: 💬 General Discussion
|
||||||
url: https://github.com/BeehiveInnovations/zen-mcp-server/discussions
|
url: https://github.com/BeehiveInnovations/pal-mcp-server/discussions
|
||||||
about: Ask questions, share ideas, or discuss usage patterns with the community
|
about: Ask questions, share ideas, or discuss usage patterns with the community
|
||||||
- name: 📚 Documentation
|
- name: 📚 Documentation
|
||||||
url: https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/README.md
|
url: https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/README.md
|
||||||
about: Check the README for setup instructions and usage examples
|
about: Check the README for setup instructions and usage examples
|
||||||
- name: 🤝 Contributing Guide
|
- name: 🤝 Contributing Guide
|
||||||
url: https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/CONTRIBUTING.md
|
url: https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/CONTRIBUTING.md
|
||||||
about: Learn how to contribute to the project
|
about: Learn how to contribute to the project
|
||||||
|
|
||||||
|
|||||||
8
.github/ISSUE_TEMPLATE/tool_addition.yml
vendored
8
.github/ISSUE_TEMPLATE/tool_addition.yml
vendored
@@ -1,5 +1,5 @@
|
|||||||
name: 🛠️ New Gemini Tool Proposal
|
name: 🛠️ New Gemini Tool Proposal
|
||||||
description: Propose a new Zen MCP tool (e.g., `summarize`, `fixer`, `refactor`)
|
description: Propose a new PAL MCP tool (e.g., `summarize`, `fixer`, `refactor`)
|
||||||
labels: ["enhancement", "new-tool"]
|
labels: ["enhancement", "new-tool"]
|
||||||
body:
|
body:
|
||||||
- type: input
|
- type: input
|
||||||
@@ -15,7 +15,7 @@ body:
|
|||||||
id: purpose
|
id: purpose
|
||||||
attributes:
|
attributes:
|
||||||
label: What is the primary purpose of this tool?
|
label: What is the primary purpose of this tool?
|
||||||
description: "Explain the tool's core function and the value it provides to developers using Claude + Zen."
|
description: "Explain the tool's core function and the value it provides to developers using Claude + PAL."
|
||||||
placeholder: "This tool will automatically generate comprehensive documentation from code, extracting class and function signatures, docstrings, and creating usage examples."
|
placeholder: "This tool will automatically generate comprehensive documentation from code, extracting class and function signatures, docstrings, and creating usage examples."
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
@@ -27,7 +27,7 @@ body:
|
|||||||
description: "Show how a user would invoke this tool through Claude and what the expected output would look like."
|
description: "Show how a user would invoke this tool through Claude and what the expected output would look like."
|
||||||
placeholder: |
|
placeholder: |
|
||||||
**User prompt to Claude:**
|
**User prompt to Claude:**
|
||||||
"Use zen to generate documentation for my entire src/ directory"
|
"Use pal to generate documentation for my entire src/ directory"
|
||||||
|
|
||||||
**Expected behavior:**
|
**Expected behavior:**
|
||||||
- Analyze all Python files in src/
|
- Analyze all Python files in src/
|
||||||
@@ -61,7 +61,7 @@ body:
|
|||||||
id: system-prompt
|
id: system-prompt
|
||||||
attributes:
|
attributes:
|
||||||
label: Proposed System Prompt (Optional)
|
label: Proposed System Prompt (Optional)
|
||||||
description: "If you have ideas for how zen should be prompted for this tool, share them here."
|
description: "If you have ideas for how pal should be prompted for this tool, share them here."
|
||||||
placeholder: |
|
placeholder: |
|
||||||
You are an expert technical documentation generator. Your task is to create comprehensive, user-friendly documentation from source code...
|
You are an expert technical documentation generator. Your task is to create comprehensive, user-friendly documentation from source code...
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/docker-pr.yml
vendored
2
.github/workflows/docker-pr.yml
vendored
@@ -95,7 +95,7 @@ jobs:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": ["run", "--rm", "-i", "-e", "GEMINI_API_KEY", "ghcr.io/${{ github.repository }}:pr-${{ github.event.number }}"],
|
"args": ["run", "--rm", "-i", "-e", "GEMINI_API_KEY", "ghcr.io/${{ github.repository }}:pr-${{ github.event.number }}"],
|
||||||
"env": { "GEMINI_API_KEY": "your-key" }
|
"env": { "GEMINI_API_KEY": "your-key" }
|
||||||
|
|||||||
2
.github/workflows/docker-release.yml
vendored
2
.github/workflows/docker-release.yml
vendored
@@ -87,7 +87,7 @@ jobs:
|
|||||||
\`\`\`json
|
\`\`\`json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp-server": {
|
"pal-mcp-server": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run", "--rm", "-i",
|
"run", "--rm", "-i",
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -179,7 +179,7 @@ CLAUDE.local.md
|
|||||||
.claude/settings.local.json
|
.claude/settings.local.json
|
||||||
|
|
||||||
# Standalone mode files
|
# Standalone mode files
|
||||||
.zen_venv/
|
.pal_venv/
|
||||||
.docker_cleaned
|
.docker_cleaned
|
||||||
logs/
|
logs/
|
||||||
*.backup
|
*.backup
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ exclude: |
|
|||||||
\.git/|
|
\.git/|
|
||||||
\.venv/|
|
\.venv/|
|
||||||
venv/|
|
venv/|
|
||||||
\.zen_venv/|
|
\.pal_venv/|
|
||||||
__pycache__/|
|
__pycache__/|
|
||||||
\.pytest_cache/|
|
\.pytest_cache/|
|
||||||
logs/|
|
logs/|
|
||||||
|
|||||||
10
AGENTS.md
10
AGENTS.md
@@ -5,14 +5,14 @@ See `requirements.txt` and `requirements-dev.txt`
|
|||||||
Also read CLAUDE.md and CLAUDE.local.md if available.
|
Also read CLAUDE.md and CLAUDE.local.md if available.
|
||||||
|
|
||||||
## Project Structure & Module Organization
|
## Project Structure & Module Organization
|
||||||
Zen MCP Server centers on `server.py`, which exposes MCP entrypoints and coordinates multi-model workflows.
|
PAL MCP Server centers on `server.py`, which exposes MCP entrypoints and coordinates multi-model workflows.
|
||||||
Feature-specific tools live in `tools/`, provider integrations in `providers/`, and shared helpers in `utils/`.
|
Feature-specific tools live in `tools/`, provider integrations in `providers/`, and shared helpers in `utils/`.
|
||||||
Prompt and system context assets stay in `systemprompts/`, while configuration templates and automation scripts live under `conf/`, `scripts/`, and `docker/`.
|
Prompt and system context assets stay in `systemprompts/`, while configuration templates and automation scripts live under `conf/`, `scripts/`, and `docker/`.
|
||||||
Unit tests sit in `tests/`; simulator-driven scenarios and log utilities are in `simulator_tests/` with the `communication_simulator_test.py` harness.
|
Unit tests sit in `tests/`; simulator-driven scenarios and log utilities are in `simulator_tests/` with the `communication_simulator_test.py` harness.
|
||||||
Authoritative documentation and samples live in `docs/`, and runtime diagnostics are rotated in `logs/`.
|
Authoritative documentation and samples live in `docs/`, and runtime diagnostics are rotated in `logs/`.
|
||||||
|
|
||||||
## Build, Test, and Development Commands
|
## Build, Test, and Development Commands
|
||||||
- `source .zen_venv/bin/activate` – activate the managed Python environment.
|
- `source .pal_venv/bin/activate` – activate the managed Python environment.
|
||||||
- `./run-server.sh` – install dependencies, refresh `.env`, and launch the MCP server locally.
|
- `./run-server.sh` – install dependencies, refresh `.env`, and launch the MCP server locally.
|
||||||
- `./code_quality_checks.sh` – run Ruff autofix, Black, isort, and the default pytest suite.
|
- `./code_quality_checks.sh` – run Ruff autofix, Black, isort, and the default pytest suite.
|
||||||
- `python communication_simulator_test.py --quick` – smoke-test orchestration across tools and providers.
|
- `python communication_simulator_test.py --quick` – smoke-test orchestration across tools and providers.
|
||||||
@@ -20,14 +20,14 @@ Authoritative documentation and samples live in `docs/`, and runtime diagnostics
|
|||||||
|
|
||||||
Run code quality checks:
|
Run code quality checks:
|
||||||
```bash
|
```bash
|
||||||
.zen_venv/bin/activate && ./code_quality_checks.sh
|
.pal_venv/bin/activate && ./code_quality_checks.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
For example, this is how we run an individual / all tests:
|
For example, this is how we run an individual / all tests:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
.zen_venv/bin/activate && pytest tests/test_auto_mode_model_listing.py -q
|
.pal_venv/bin/activate && pytest tests/test_auto_mode_model_listing.py -q
|
||||||
.zen_venv/bin/activate && pytest -q
|
.pal_venv/bin/activate && pytest -q
|
||||||
```
|
```
|
||||||
|
|
||||||
## Coding Style & Naming Conventions
|
## Coding Style & Naming Conventions
|
||||||
|
|||||||
469
CHANGELOG.md
469
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
10
CLAUDE.md
10
CLAUDE.md
@@ -1,6 +1,6 @@
|
|||||||
# Claude Development Guide for Zen MCP Server
|
# Claude Development Guide for PAL MCP Server
|
||||||
|
|
||||||
This file contains essential commands and workflows for developing and maintaining the Zen MCP Server when working with Claude. Use these instructions to efficiently run quality checks, manage the server, check logs, and run tests.
|
This file contains essential commands and workflows for developing and maintaining the PAL MCP Server when working with Claude. Use these instructions to efficiently run quality checks, manage the server, check logs, and run tests.
|
||||||
|
|
||||||
## Quick Reference Commands
|
## Quick Reference Commands
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ python -m pytest tests/ -v
|
|||||||
### Development Workflow
|
### Development Workflow
|
||||||
|
|
||||||
#### Before Making Changes
|
#### Before Making Changes
|
||||||
1. Ensure virtual environment is activated: `source .zen_venv/bin/activate`
|
1. Ensure virtual environment is activated: `source .pal_venv/bin/activate`
|
||||||
2. Run quality checks: `./code_quality_checks.sh`
|
2. Run quality checks: `./code_quality_checks.sh`
|
||||||
3. Check logs to ensure server is healthy: `tail -n 50 logs/mcp_server.log`
|
3. Check logs to ensure server is healthy: `tail -n 50 logs/mcp_server.log`
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ grep "ERROR" logs/mcp_server.log | tail -20
|
|||||||
|
|
||||||
# Check virtual environment
|
# Check virtual environment
|
||||||
which python
|
which python
|
||||||
# Should show: .../zen-mcp-server/.zen_venv/bin/python
|
# Should show: .../pal-mcp-server/.pal_venv/bin/python
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Test Failures
|
#### Test Failures
|
||||||
@@ -317,4 +317,4 @@ isort --check-only .
|
|||||||
- All dependencies from `requirements.txt` installed
|
- All dependencies from `requirements.txt` installed
|
||||||
- Proper API keys configured in `.env` file
|
- Proper API keys configured in `.env` file
|
||||||
|
|
||||||
This guide provides everything needed to efficiently work with the Zen MCP Server codebase using Claude. Always run quality checks before and after making changes to ensure code integrity.
|
This guide provides everything needed to efficiently work with the PAL MCP Server codebase using Claude. Always run quality checks before and after making changes to ensure code integrity.
|
||||||
22
Dockerfile
22
Dockerfile
@@ -29,18 +29,18 @@ RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
|
|||||||
FROM python:3.11-slim AS runtime
|
FROM python:3.11-slim AS runtime
|
||||||
|
|
||||||
# Add metadata labels for traceability
|
# Add metadata labels for traceability
|
||||||
LABEL maintainer="Zen MCP Server Team"
|
LABEL maintainer="PAL MCP Server Team"
|
||||||
LABEL version="1.0.0"
|
LABEL version="1.0.0"
|
||||||
LABEL description="Zen MCP Server - AI-powered Model Context Protocol server"
|
LABEL description="PAL MCP Server - AI-powered Model Context Protocol server"
|
||||||
LABEL org.opencontainers.image.title="zen-mcp-server"
|
LABEL org.opencontainers.image.title="pal-mcp-server"
|
||||||
LABEL org.opencontainers.image.description="AI-powered Model Context Protocol server with multi-provider support"
|
LABEL org.opencontainers.image.description="AI-powered Model Context Protocol server with multi-provider support"
|
||||||
LABEL org.opencontainers.image.version="1.0.0"
|
LABEL org.opencontainers.image.version="1.0.0"
|
||||||
LABEL org.opencontainers.image.source="https://github.com/BeehiveInnovations/zen-mcp-server"
|
LABEL org.opencontainers.image.source="https://github.com/BeehiveInnovations/pal-mcp-server"
|
||||||
LABEL org.opencontainers.image.documentation="https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/README.md"
|
LABEL org.opencontainers.image.documentation="https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/README.md"
|
||||||
LABEL org.opencontainers.image.licenses="Apache 2.0 License"
|
LABEL org.opencontainers.image.licenses="Apache 2.0 License"
|
||||||
|
|
||||||
# Create non-root user for security
|
# Create non-root user for security
|
||||||
RUN groupadd -r zenuser && useradd -r -g zenuser zenuser
|
RUN groupadd -r paluser && useradd -r -g paluser paluser
|
||||||
|
|
||||||
# Install minimal runtime dependencies
|
# Install minimal runtime dependencies
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
@@ -57,20 +57,20 @@ ENV PATH="/opt/venv/bin:$PATH"
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy application code
|
# Copy application code
|
||||||
COPY --chown=zenuser:zenuser . .
|
COPY --chown=paluser:paluser . .
|
||||||
|
|
||||||
# Create logs directory with proper permissions
|
# Create logs directory with proper permissions
|
||||||
RUN mkdir -p logs && chown -R zenuser:zenuser logs
|
RUN mkdir -p logs && chown -R paluser:paluser logs
|
||||||
|
|
||||||
# Create tmp directory for container operations
|
# Create tmp directory for container operations
|
||||||
RUN mkdir -p tmp && chown -R zenuser:zenuser tmp
|
RUN mkdir -p tmp && chown -R paluser:paluser tmp
|
||||||
|
|
||||||
# Copy health check script
|
# Copy health check script
|
||||||
COPY --chown=zenuser:zenuser docker/scripts/healthcheck.py /usr/local/bin/healthcheck.py
|
COPY --chown=paluser:paluser docker/scripts/healthcheck.py /usr/local/bin/healthcheck.py
|
||||||
RUN chmod +x /usr/local/bin/healthcheck.py
|
RUN chmod +x /usr/local/bin/healthcheck.py
|
||||||
|
|
||||||
# Switch to non-root user
|
# Switch to non-root user
|
||||||
USER zenuser
|
USER paluser
|
||||||
|
|
||||||
# Health check configuration
|
# Health check configuration
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
|||||||
55
README.md
55
README.md
@@ -1,8 +1,11 @@
|
|||||||
# Zen MCP: Many Workflows. One Context.
|
# PAL MCP: Many Workflows. One Context.
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[Zen in action](https://github.com/user-attachments/assets/0d26061e-5f21-4ab1-b7d0-f883ddc2c3da)
|
<em>Your AI's PAL – a Provider Abstraction Layer</em><br />
|
||||||
|
<sub><a href="docs/name-change.md">Formerly known as Zen MCP</a></sub>
|
||||||
|
|
||||||
|
[PAL in action](https://github.com/user-attachments/assets/0d26061e-5f21-4ab1-b7d0-f883ddc2c3da)
|
||||||
|
|
||||||
👉 **[Watch more examples](#-watch-tools-in-action)**
|
👉 **[Watch more examples](#-watch-tools-in-action)**
|
||||||
|
|
||||||
@@ -44,24 +47,24 @@ Continue with clink gemini - implement the recommended feature
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Why Zen MCP?
|
## Why PAL MCP?
|
||||||
|
|
||||||
**Why rely on one AI model when you can orchestrate them all?**
|
**Why rely on one AI model when you can orchestrate them all?**
|
||||||
|
|
||||||
A Model Context Protocol server that supercharges tools like [Claude Code](https://www.anthropic.com/claude-code), [Codex CLI](https://developers.openai.com/codex/cli), and IDE clients such
|
A Model Context Protocol server that supercharges tools like [Claude Code](https://www.anthropic.com/claude-code), [Codex CLI](https://developers.openai.com/codex/cli), and IDE clients such
|
||||||
as [Cursor](https://cursor.com) or the [Claude Dev VS Code extension](https://marketplace.visualstudio.com/items?itemName=Anthropic.claude-vscode). **Zen MCP connects your favorite AI tool
|
as [Cursor](https://cursor.com) or the [Claude Dev VS Code extension](https://marketplace.visualstudio.com/items?itemName=Anthropic.claude-vscode). **PAL MCP connects your favorite AI tool
|
||||||
to multiple AI models** for enhanced code analysis, problem-solving, and collaborative development.
|
to multiple AI models** for enhanced code analysis, problem-solving, and collaborative development.
|
||||||
|
|
||||||
### True AI Collaboration with Conversation Continuity
|
### True AI Collaboration with Conversation Continuity
|
||||||
|
|
||||||
Zen supports **conversation threading** so your CLI can **discuss ideas with multiple AI models, exchange reasoning, get second opinions, and even run collaborative debates between models** to help you reach deeper insights and better solutions.
|
PAL supports **conversation threading** so your CLI can **discuss ideas with multiple AI models, exchange reasoning, get second opinions, and even run collaborative debates between models** to help you reach deeper insights and better solutions.
|
||||||
|
|
||||||
Your CLI always stays in control but gets perspectives from the best AI for each subtask. Context carries forward seamlessly across tools and models, enabling complex workflows like: code reviews with multiple models → automated planning → implementation → pre-commit validation.
|
Your CLI always stays in control but gets perspectives from the best AI for each subtask. Context carries forward seamlessly across tools and models, enabling complex workflows like: code reviews with multiple models → automated planning → implementation → pre-commit validation.
|
||||||
|
|
||||||
> **You're in control.** Your CLI of choice orchestrates the AI team, but you decide the workflow. Craft powerful prompts that bring in Gemini Pro, GPT 5, Flash, or local offline models exactly when needed.
|
> **You're in control.** Your CLI of choice orchestrates the AI team, but you decide the workflow. Craft powerful prompts that bring in Gemini Pro, GPT 5, Flash, or local offline models exactly when needed.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>Reasons to Use Zen MCP</b></summary>
|
<summary><b>Reasons to Use PAL MCP</b></summary>
|
||||||
|
|
||||||
A typical workflow with Claude Code as an example:
|
A typical workflow with Claude Code as an example:
|
||||||
|
|
||||||
@@ -111,7 +114,7 @@ and review into consideration to aid with its final pre-commit review.
|
|||||||
**Think of it as Claude Code _for_ Claude Code.** This MCP isn't magic. It's just **super-glue**.
|
**Think of it as Claude Code _for_ Claude Code.** This MCP isn't magic. It's just **super-glue**.
|
||||||
|
|
||||||
> **Remember:** Claude stays in full control — but **YOU** call the shots.
|
> **Remember:** Claude stays in full control — but **YOU** call the shots.
|
||||||
> Zen is designed to have Claude engage other models only when needed — and to follow through with meaningful back-and-forth.
|
> PAL is designed to have Claude engage other models only when needed — and to follow through with meaningful back-and-forth.
|
||||||
> **You're** the one who crafts the powerful prompt that makes Claude bring in Gemini, Flash, O3 — or fly solo.
|
> **You're** the one who crafts the powerful prompt that makes Claude bring in Gemini, Flash, O3 — or fly solo.
|
||||||
> You're the guide. The prompter. The puppeteer.
|
> You're the guide. The prompter. The puppeteer.
|
||||||
> #### You are the AI - **Actually Intelligent**.
|
> #### You are the AI - **Actually Intelligent**.
|
||||||
@@ -154,8 +157,8 @@ For best results when using [Codex CLI](https://developers.openai.com/codex/cli)
|
|||||||
|
|
||||||
**Option A: Clone and Automatic Setup** (recommended)
|
**Option A: Clone and Automatic Setup** (recommended)
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/BeehiveInnovations/zen-mcp-server.git
|
git clone https://github.com/BeehiveInnovations/pal-mcp-server.git
|
||||||
cd zen-mcp-server
|
cd pal-mcp-server
|
||||||
|
|
||||||
# Handles everything: setup, config, API keys from system environment.
|
# Handles everything: setup, config, API keys from system environment.
|
||||||
# Auto-configures Claude Desktop, Claude Code, Gemini CLI, Codex CLI, Qwen CLI
|
# Auto-configures Claude Desktop, Claude Code, Gemini CLI, Codex CLI, Qwen CLI
|
||||||
@@ -169,9 +172,9 @@ cd zen-mcp-server
|
|||||||
// Don't forget to add your API keys under env
|
// Don't forget to add your API keys under env
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "bash",
|
"command": "bash",
|
||||||
"args": ["-c", "for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1"],
|
"args": ["-c", "for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1"],
|
||||||
"env": {
|
"env": {
|
||||||
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
||||||
"GEMINI_API_KEY": "your-key-here",
|
"GEMINI_API_KEY": "your-key-here",
|
||||||
@@ -185,9 +188,9 @@ cd zen-mcp-server
|
|||||||
|
|
||||||
**3. Start Using!**
|
**3. Start Using!**
|
||||||
```
|
```
|
||||||
"Use zen to analyze this code for security issues with gemini pro"
|
"Use pal to analyze this code for security issues with gemini pro"
|
||||||
"Debug this error with o3 and then get flash to suggest optimizations"
|
"Debug this error with o3 and then get flash to suggest optimizations"
|
||||||
"Plan the migration strategy with zen, get consensus from multiple models"
|
"Plan the migration strategy with pal, get consensus from multiple models"
|
||||||
"clink with cli_name=\"gemini\" role=\"planner\" to draft a phased rollout plan"
|
"clink with cli_name=\"gemini\" role=\"planner\" to draft a phased rollout plan"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -197,7 +200,7 @@ cd zen-mcp-server
|
|||||||
|
|
||||||
## Provider Configuration
|
## Provider Configuration
|
||||||
|
|
||||||
Zen activates any provider that has credentials in your `.env`. See `.env.example` for deeper customization.
|
PAL activates any provider that has credentials in your `.env`. See `.env.example` for deeper customization.
|
||||||
|
|
||||||
## Core Tools
|
## Core Tools
|
||||||
|
|
||||||
@@ -265,7 +268,7 @@ DISABLED_TOOLS=
|
|||||||
// In ~/.claude/settings.json or .mcp.json
|
// In ~/.claude/settings.json or .mcp.json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"env": {
|
"env": {
|
||||||
// Tool configuration
|
// Tool configuration
|
||||||
"DISABLED_TOOLS": "refactor,testgen,secaudit,docgen,tracer",
|
"DISABLED_TOOLS": "refactor,testgen,secaudit,docgen,tracer",
|
||||||
@@ -292,7 +295,7 @@ DISABLED_TOOLS=
|
|||||||
// Remove or empty the DISABLED_TOOLS to enable everything
|
// Remove or empty the DISABLED_TOOLS to enable everything
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"env": {
|
"env": {
|
||||||
"DISABLED_TOOLS": ""
|
"DISABLED_TOOLS": ""
|
||||||
}
|
}
|
||||||
@@ -328,7 +331,7 @@ DISABLED_TOOLS=
|
|||||||
|
|
||||||
**Multi-model consensus debate:**
|
**Multi-model consensus debate:**
|
||||||
|
|
||||||
[Zen Consensus Debate](https://github.com/user-attachments/assets/76a23dd5-887a-4382-9cf0-642f5cf6219e)
|
[PAL Consensus Debate](https://github.com/user-attachments/assets/76a23dd5-887a-4382-9cf0-642f5cf6219e)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -346,26 +349,26 @@ DISABLED_TOOLS=
|
|||||||
<details>
|
<details>
|
||||||
<summary><b>API Lookup Tool</b> - Current vs outdated API documentation</summary>
|
<summary><b>API Lookup Tool</b> - Current vs outdated API documentation</summary>
|
||||||
|
|
||||||
**Without Zen - outdated APIs:**
|
**Without PAL - outdated APIs:**
|
||||||
|
|
||||||
[API without Zen](https://github.com/user-attachments/assets/01a79dc9-ad16-4264-9ce1-76a56c3580ee)
|
[API without PAL](https://github.com/user-attachments/assets/01a79dc9-ad16-4264-9ce1-76a56c3580ee)
|
||||||
|
|
||||||
**With Zen - current APIs:**
|
**With PAL - current APIs:**
|
||||||
|
|
||||||
[API with Zen](https://github.com/user-attachments/assets/5c847326-4b66-41f7-8f30-f380453dce22)
|
[API with PAL](https://github.com/user-attachments/assets/5c847326-4b66-41f7-8f30-f380453dce22)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>Challenge Tool</b> - Critical thinking vs reflexive agreement</summary>
|
<summary><b>Challenge Tool</b> - Critical thinking vs reflexive agreement</summary>
|
||||||
|
|
||||||
**Without Zen:**
|
**Without PAL:**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**With Zen:**
|
**With PAL:**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -444,4 +447,4 @@ Built with the power of **Multi-Model AI** collaboration 🤝
|
|||||||
|
|
||||||
### Star History
|
### Star History
|
||||||
|
|
||||||
[](https://www.star-history.com/#BeehiveInnovations/zen-mcp-server&Date)
|
[](https://www.star-history.com/#BeehiveInnovations/pal-mcp-server&Date)
|
||||||
|
|||||||
81
SECURITY.md
Normal file
81
SECURITY.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 9.x.x | :white_check_mark: |
|
||||||
|
| < 9.0 | :x: |
|
||||||
|
|
||||||
|
## Important Disclaimer
|
||||||
|
|
||||||
|
PAL MCP is an open-source Model Context Protocol (MCP) server that acts as middleware between AI clients (Claude Code, Codex CLI, Cursor, etc.) and various AI model providers.
|
||||||
|
|
||||||
|
**Please understand the following:**
|
||||||
|
|
||||||
|
- **No Warranty**: This software is provided "AS IS" under the Apache 2.0 License, without warranties of any kind. See the [LICENSE](LICENSE) file for full terms.
|
||||||
|
- **User Responsibility**: The AI client (not PAL MCP) controls tool invocations and workflows. Users are responsible for reviewing AI-generated outputs and actions.
|
||||||
|
- **API Key Security**: You are responsible for securing your own API keys. Never commit keys to version control or share them publicly.
|
||||||
|
- **Third-Party Services**: PAL MCP connects to external AI providers (Google, OpenAI, Azure, etc.). Their terms of service and privacy policies apply to data sent through this server.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||||
|
|
||||||
|
### Preferred Method
|
||||||
|
|
||||||
|
Use [GitHub Security Advisories](https://github.com/BeehiveInnovations/pal-mcp-server/security/advisories/new) to report vulnerabilities privately.
|
||||||
|
|
||||||
|
### What to Include
|
||||||
|
|
||||||
|
- Description of the vulnerability
|
||||||
|
- Steps to reproduce
|
||||||
|
- Affected versions
|
||||||
|
- Potential impact
|
||||||
|
- Suggested fix (optional)
|
||||||
|
|
||||||
|
### What to Expect
|
||||||
|
|
||||||
|
- We will acknowledge your report and assess the issue
|
||||||
|
- Critical issues will be prioritized
|
||||||
|
- We'll keep you informed of progress as work proceeds
|
||||||
|
|
||||||
|
We cannot commit to specific response timelines, but we take security seriously.
|
||||||
|
|
||||||
|
### After Resolution
|
||||||
|
|
||||||
|
We welcome security researchers to submit a pull request with the fix. This is an open-source project and we appreciate community contributions to improve security.
|
||||||
|
|
||||||
|
## Disclosure Policy
|
||||||
|
|
||||||
|
We practice coordinated disclosure. Please allow reasonable time to address issues before public disclosure. We'll work with you on timing.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
### In Scope
|
||||||
|
|
||||||
|
- Authentication/authorization bypasses
|
||||||
|
- Injection vulnerabilities (command injection, prompt injection with security impact)
|
||||||
|
- Information disclosure (API keys, sensitive data leakage)
|
||||||
|
- Denial of service vulnerabilities in the MCP server itself
|
||||||
|
- Dependency vulnerabilities with exploitable impact
|
||||||
|
|
||||||
|
### Out of Scope
|
||||||
|
|
||||||
|
- Issues in upstream AI providers (report to Google, OpenAI, etc. directly)
|
||||||
|
- Issues in AI client software (report to Anthropic, OpenAI, Cursor, etc.)
|
||||||
|
- AI model behavior or outputs (this is controlled by the AI client and model providers)
|
||||||
|
- Social engineering attacks
|
||||||
|
- Rate limiting or resource exhaustion on third-party APIs
|
||||||
|
|
||||||
|
## Security Best Practices for Users
|
||||||
|
|
||||||
|
1. **Protect API Keys**: Store keys in `.env` files (gitignored) or environment variables
|
||||||
|
2. **Review AI Actions**: Always review AI-suggested code changes before applying
|
||||||
|
3. **Use Local Models**: For sensitive codebases, consider using Ollama with local models
|
||||||
|
4. **Network Security**: When self-hosting, ensure appropriate network controls
|
||||||
|
5. **Keep Updated**: Regularly update to the latest version for security fixes
|
||||||
|
|
||||||
|
## Recognition
|
||||||
|
|
||||||
|
We appreciate responsible disclosure and will credit security researchers in release notes (unless you prefer anonymity).
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"comment": "Example Claude Desktop configuration for Zen MCP Server",
|
"comment": "Example Claude Desktop configuration for PAL MCP Server",
|
||||||
"comment2": "Run './run-server.sh -c' to get the exact configuration for your system",
|
"comment2": "Run './run-server.sh -c' to get the exact configuration for your system",
|
||||||
"comment3": "For platform-specific examples, see the examples/ directory",
|
"comment3": "For platform-specific examples, see the examples/ directory",
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "/path/to/zen-mcp-server/.zen_venv/bin/python",
|
"command": "/path/to/pal-mcp-server/.pal_venv/bin/python",
|
||||||
"args": ["/path/to/zen-mcp-server/server.py"]
|
"args": ["/path/to/pal-mcp-server/server.py"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ DEFAULT_STREAM_LIMIT = 10 * 1024 * 1024 # 10MB per stream
|
|||||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||||
BUILTIN_PROMPTS_DIR = PROJECT_ROOT / "systemprompts" / "clink"
|
BUILTIN_PROMPTS_DIR = PROJECT_ROOT / "systemprompts" / "clink"
|
||||||
CONFIG_DIR = PROJECT_ROOT / "conf" / "cli_clients"
|
CONFIG_DIR = PROJECT_ROOT / "conf" / "cli_clients"
|
||||||
USER_CONFIG_DIR = Path.home() / ".zen" / "cli_clients"
|
USER_CONFIG_DIR = Path.home() / ".pal" / "cli_clients"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class ClinkRegistry:
|
|||||||
env_path = Path(env_path_raw).expanduser()
|
env_path = Path(env_path_raw).expanduser()
|
||||||
search_paths.append(env_path)
|
search_paths.append(env_path)
|
||||||
|
|
||||||
# 3. User overrides in ~/.zen/cli_clients
|
# 3. User overrides in ~/.pal/cli_clients
|
||||||
search_paths.append(USER_CONFIG_DIR)
|
search_paths.append(USER_CONFIG_DIR)
|
||||||
|
|
||||||
seen: set[Path] = set()
|
seen: set[Path] = set()
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Code quality checks script for Zen MCP server on Windows.
|
Code quality checks script for PAL MCP server on Windows.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
This PowerShell script performs code quality checks for the Zen MCP server project:
|
This PowerShell script performs code quality checks for the PAL MCP server project:
|
||||||
- Runs static analysis and linting tools on the codebase
|
- Runs static analysis and linting tools on the codebase
|
||||||
- Ensures code style compliance and detects potential issues
|
- Ensures code style compliance and detects potential issues
|
||||||
- Can be integrated into CI/CD pipelines or used locally before commits
|
- Can be integrated into CI/CD pipelines or used locally before commits
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
Script Author : GiGiDKR (https://github.com/GiGiDKR)
|
Script Author : GiGiDKR (https://github.com/GiGiDKR)
|
||||||
Date : 07-05-2025
|
Date : 07-05-2025
|
||||||
Version : See project documentation
|
Version : See project documentation
|
||||||
References : https://github.com/BeehiveInnovations/zen-mcp-server
|
References : https://github.com/BeehiveInnovations/pal-mcp-server
|
||||||
#>
|
#>
|
||||||
#Requires -Version 5.1
|
#Requires -Version 5.1
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
@@ -61,23 +61,23 @@ function Write-Emoji {
|
|||||||
Write-ColorText $Text -Color $Color
|
Write-ColorText $Text -Color $Color
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Emoji "🔍" "Running Code Quality Checks for Zen MCP Server" -Color Cyan
|
Write-Emoji "🔍" "Running Code Quality Checks for PAL MCP Server" -Color Cyan
|
||||||
Write-ColorText "=================================================" -Color Cyan
|
Write-ColorText "=================================================" -Color Cyan
|
||||||
|
|
||||||
# Determine Python command
|
# Determine Python command
|
||||||
$pythonCmd = $null
|
$pythonCmd = $null
|
||||||
$pipCmd = $null
|
$pipCmd = $null
|
||||||
|
|
||||||
if (Test-Path ".zen_venv") {
|
if (Test-Path ".pal_venv") {
|
||||||
if ($IsWindows -or $env:OS -eq "Windows_NT") {
|
if ($IsWindows -or $env:OS -eq "Windows_NT") {
|
||||||
if (Test-Path ".zen_venv\Scripts\python.exe") {
|
if (Test-Path ".pal_venv\Scripts\python.exe") {
|
||||||
$pythonCmd = ".zen_venv\Scripts\python.exe"
|
$pythonCmd = ".pal_venv\Scripts\python.exe"
|
||||||
$pipCmd = ".zen_venv\Scripts\pip.exe"
|
$pipCmd = ".pal_venv\Scripts\pip.exe"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Test-Path ".zen_venv/bin/python") {
|
if (Test-Path ".pal_venv/bin/python") {
|
||||||
$pythonCmd = ".zen_venv/bin/python"
|
$pythonCmd = ".pal_venv/bin/python"
|
||||||
$pipCmd = ".zen_venv/bin/pip"
|
$pipCmd = ".pal_venv/bin/pip"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,11 +108,11 @@ foreach ($tool in $devTools) {
|
|||||||
|
|
||||||
# Check in venv
|
# Check in venv
|
||||||
if ($IsWindows -or $env:OS -eq "Windows_NT") {
|
if ($IsWindows -or $env:OS -eq "Windows_NT") {
|
||||||
if (Test-Path ".zen_venv\Scripts\$tool.exe") {
|
if (Test-Path ".pal_venv\Scripts\$tool.exe") {
|
||||||
$toolFound = $true
|
$toolFound = $true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Test-Path ".zen_venv/bin/$tool") {
|
if (Test-Path ".pal_venv/bin/$tool") {
|
||||||
$toolFound = $true
|
$toolFound = $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,15 +152,15 @@ if ($devDepsNeeded) {
|
|||||||
|
|
||||||
# Set tool paths
|
# Set tool paths
|
||||||
if ($IsWindows -or $env:OS -eq "Windows_NT") {
|
if ($IsWindows -or $env:OS -eq "Windows_NT") {
|
||||||
$ruffCmd = if (Test-Path ".zen_venv\Scripts\ruff.exe") { ".zen_venv\Scripts\ruff.exe" } else { "ruff" }
|
$ruffCmd = if (Test-Path ".pal_venv\Scripts\ruff.exe") { ".pal_venv\Scripts\ruff.exe" } else { "ruff" }
|
||||||
$blackCmd = if (Test-Path ".zen_venv\Scripts\black.exe") { ".zen_venv\Scripts\black.exe" } else { "black" }
|
$blackCmd = if (Test-Path ".pal_venv\Scripts\black.exe") { ".pal_venv\Scripts\black.exe" } else { "black" }
|
||||||
$isortCmd = if (Test-Path ".zen_venv\Scripts\isort.exe") { ".zen_venv\Scripts\isort.exe" } else { "isort" }
|
$isortCmd = if (Test-Path ".pal_venv\Scripts\isort.exe") { ".pal_venv\Scripts\isort.exe" } else { "isort" }
|
||||||
$pytestCmd = if (Test-Path ".zen_venv\Scripts\pytest.exe") { ".zen_venv\Scripts\pytest.exe" } else { "pytest" }
|
$pytestCmd = if (Test-Path ".pal_venv\Scripts\pytest.exe") { ".pal_venv\Scripts\pytest.exe" } else { "pytest" }
|
||||||
} else {
|
} else {
|
||||||
$ruffCmd = if (Test-Path ".zen_venv/bin/ruff") { ".zen_venv/bin/ruff" } else { "ruff" }
|
$ruffCmd = if (Test-Path ".pal_venv/bin/ruff") { ".pal_venv/bin/ruff" } else { "ruff" }
|
||||||
$blackCmd = if (Test-Path ".zen_venv/bin/black") { ".zen_venv/bin/black" } else { "black" }
|
$blackCmd = if (Test-Path ".pal_venv/bin/black") { ".pal_venv/bin/black" } else { "black" }
|
||||||
$isortCmd = if (Test-Path ".zen_venv/bin/isort") { ".zen_venv/bin/isort" } else { "isort" }
|
$isortCmd = if (Test-Path ".pal_venv/bin/isort") { ".pal_venv/bin/isort" } else { "isort" }
|
||||||
$pytestCmd = if (Test-Path ".zen_venv/bin/pytest") { ".zen_venv/bin/pytest" } else { "pytest" }
|
$pytestCmd = if (Test-Path ".pal_venv/bin/pytest") { ".pal_venv/bin/pytest" } else { "pytest" }
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
@@ -172,25 +172,25 @@ if (!$SkipLinting) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Write-Emoji "🔧" "Running ruff linting with auto-fix..." -Color Yellow
|
Write-Emoji "🔧" "Running ruff linting with auto-fix..." -Color Yellow
|
||||||
& $ruffCmd check --fix --exclude test_simulation_files --exclude .zen_venv
|
& $ruffCmd check --fix --exclude test_simulation_files --exclude .pal_venv
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
throw "Ruff linting failed"
|
throw "Ruff linting failed"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Emoji "🎨" "Running black code formatting..." -Color Yellow
|
Write-Emoji "🎨" "Running black code formatting..." -Color Yellow
|
||||||
& $blackCmd . --exclude="test_simulation_files/" --exclude=".zen_venv/"
|
& $blackCmd . --exclude="test_simulation_files/" --exclude=".pal_venv/"
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
throw "Black formatting failed"
|
throw "Black formatting failed"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Emoji "📦" "Running import sorting with isort..." -Color Yellow
|
Write-Emoji "📦" "Running import sorting with isort..." -Color Yellow
|
||||||
& $isortCmd . --skip-glob=".zen_venv/*" --skip-glob="test_simulation_files/*"
|
& $isortCmd . --skip-glob=".pal_venv/*" --skip-glob="test_simulation_files/*"
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
throw "Import sorting failed"
|
throw "Import sorting failed"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Emoji "✅" "Verifying all linting passes..." -Color Yellow
|
Write-Emoji "✅" "Verifying all linting passes..." -Color Yellow
|
||||||
& $ruffCmd check --exclude test_simulation_files --exclude .zen_venv
|
& $ruffCmd check --exclude test_simulation_files --exclude .pal_venv
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
throw "Final linting verification failed"
|
throw "Final linting verification failed"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Zen MCP Server - Code Quality Checks
|
# PAL MCP Server - Code Quality Checks
|
||||||
# This script runs all required linting and testing checks before committing changes.
|
# This script runs all required linting and testing checks before committing changes.
|
||||||
# ALL checks must pass 100% for CI/CD to succeed.
|
# ALL checks must pass 100% for CI/CD to succeed.
|
||||||
|
|
||||||
set -e # Exit on any error
|
set -e # Exit on any error
|
||||||
|
|
||||||
echo "🔍 Running Code Quality Checks for Zen MCP Server"
|
echo "🔍 Running Code Quality Checks for PAL MCP Server"
|
||||||
echo "================================================="
|
echo "================================================="
|
||||||
|
|
||||||
# Determine Python command
|
# Determine Python command
|
||||||
if [[ -f ".zen_venv/bin/python" ]]; then
|
if [[ -f ".pal_venv/bin/python" ]]; then
|
||||||
PYTHON_CMD=".zen_venv/bin/python"
|
PYTHON_CMD=".pal_venv/bin/python"
|
||||||
PIP_CMD=".zen_venv/bin/pip"
|
PIP_CMD=".pal_venv/bin/pip"
|
||||||
echo "✅ Using venv"
|
echo "✅ Using venv"
|
||||||
elif [[ -n "$VIRTUAL_ENV" ]]; then
|
elif [[ -n "$VIRTUAL_ENV" ]]; then
|
||||||
PYTHON_CMD="python"
|
PYTHON_CMD="python"
|
||||||
@@ -32,7 +32,7 @@ DEV_DEPS_NEEDED=false
|
|||||||
# Check each dev dependency
|
# Check each dev dependency
|
||||||
for tool in ruff black isort pytest; do
|
for tool in ruff black isort pytest; do
|
||||||
# Check if tool exists in venv or in PATH
|
# Check if tool exists in venv or in PATH
|
||||||
if [[ -f ".zen_venv/bin/$tool" ]] || command -v $tool &> /dev/null; then
|
if [[ -f ".pal_venv/bin/$tool" ]] || command -v $tool &> /dev/null; then
|
||||||
continue
|
continue
|
||||||
else
|
else
|
||||||
DEV_DEPS_NEEDED=true
|
DEV_DEPS_NEEDED=true
|
||||||
@@ -49,11 +49,11 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Set tool paths
|
# Set tool paths
|
||||||
if [[ -f ".zen_venv/bin/ruff" ]]; then
|
if [[ -f ".pal_venv/bin/ruff" ]]; then
|
||||||
RUFF=".zen_venv/bin/ruff"
|
RUFF=".pal_venv/bin/ruff"
|
||||||
BLACK=".zen_venv/bin/black"
|
BLACK=".pal_venv/bin/black"
|
||||||
ISORT=".zen_venv/bin/isort"
|
ISORT=".pal_venv/bin/isort"
|
||||||
PYTEST=".zen_venv/bin/pytest"
|
PYTEST=".pal_venv/bin/pytest"
|
||||||
else
|
else
|
||||||
RUFF="ruff"
|
RUFF="ruff"
|
||||||
BLACK="black"
|
BLACK="black"
|
||||||
@@ -67,16 +67,16 @@ echo "📋 Step 1: Running Linting and Formatting Checks"
|
|||||||
echo "--------------------------------------------------"
|
echo "--------------------------------------------------"
|
||||||
|
|
||||||
echo "🔧 Running ruff linting with auto-fix..."
|
echo "🔧 Running ruff linting with auto-fix..."
|
||||||
$RUFF check --fix --exclude test_simulation_files --exclude .zen_venv
|
$RUFF check --fix --exclude test_simulation_files --exclude .pal_venv
|
||||||
|
|
||||||
echo "🎨 Running black code formatting..."
|
echo "🎨 Running black code formatting..."
|
||||||
$BLACK . --exclude="test_simulation_files/" --exclude=".zen_venv/"
|
$BLACK . --exclude="test_simulation_files/" --exclude=".pal_venv/"
|
||||||
|
|
||||||
echo "📦 Running import sorting with isort..."
|
echo "📦 Running import sorting with isort..."
|
||||||
$ISORT . --skip-glob=".zen_venv/*" --skip-glob="test_simulation_files/*"
|
$ISORT . --skip-glob=".pal_venv/*" --skip-glob="test_simulation_files/*"
|
||||||
|
|
||||||
echo "✅ Verifying all linting passes..."
|
echo "✅ Verifying all linting passes..."
|
||||||
$RUFF check --exclude test_simulation_files --exclude .zen_venv
|
$RUFF check --exclude test_simulation_files --exclude .pal_venv
|
||||||
|
|
||||||
echo "✅ Step 1 Complete: All linting and formatting checks passed!"
|
echo "✅ Step 1 Complete: All linting and formatting checks passed!"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Communication Simulator Test for Zen MCP Server
|
Communication Simulator Test for PAL MCP Server
|
||||||
|
|
||||||
This script provides comprehensive end-to-end testing of the Zen MCP server
|
This script provides comprehensive end-to-end testing of the PAL MCP Server
|
||||||
by simulating real Claude CLI communications and validating conversation
|
by simulating real Claude CLI communications and validating conversation
|
||||||
continuity, file handling, deduplication features, and clarification scenarios.
|
continuity, file handling, deduplication features, and clarification scenarios.
|
||||||
|
|
||||||
@@ -145,10 +145,10 @@ class CommunicationSimulator:
|
|||||||
if os.path.exists(venv_python):
|
if os.path.exists(venv_python):
|
||||||
return venv_python
|
return venv_python
|
||||||
|
|
||||||
# Try .zen_venv as fallback
|
# Try .pal_venv as fallback
|
||||||
zen_venv_python = os.path.join(current_dir, ".zen_venv", "bin", "python")
|
pal_venv_python = os.path.join(current_dir, ".pal_venv", "bin", "python")
|
||||||
if os.path.exists(zen_venv_python):
|
if os.path.exists(pal_venv_python):
|
||||||
return zen_venv_python
|
return pal_venv_python
|
||||||
|
|
||||||
# Fallback to system python if venv doesn't exist
|
# Fallback to system python if venv doesn't exist
|
||||||
self.logger.warning("Virtual environment not found, using system python")
|
self.logger.warning("Virtual environment not found, using system python")
|
||||||
@@ -361,7 +361,7 @@ class CommunicationSimulator:
|
|||||||
def print_test_summary(self):
|
def print_test_summary(self):
|
||||||
"""Print comprehensive test results summary"""
|
"""Print comprehensive test results summary"""
|
||||||
self.logger.info("\n" + "=" * 70)
|
self.logger.info("\n" + "=" * 70)
|
||||||
self.logger.info("ZEN MCP COMMUNICATION SIMULATOR - TEST RESULTS SUMMARY")
|
self.logger.info("PAL MCP COMMUNICATION SIMULATOR - TEST RESULTS SUMMARY")
|
||||||
self.logger.info("=" * 70)
|
self.logger.info("=" * 70)
|
||||||
|
|
||||||
passed_count = sum(1 for result in self.test_results.values() if result)
|
passed_count = sum(1 for result in self.test_results.values() if result)
|
||||||
@@ -388,7 +388,7 @@ class CommunicationSimulator:
|
|||||||
def run_full_test_suite(self) -> bool:
|
def run_full_test_suite(self) -> bool:
|
||||||
"""Run the complete test suite"""
|
"""Run the complete test suite"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Starting Zen MCP Communication Simulator Test Suite")
|
self.logger.info("Starting PAL MCP Communication Simulator Test Suite")
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
if not self.setup_test_environment():
|
if not self.setup_test_environment():
|
||||||
@@ -450,7 +450,7 @@ class CommunicationSimulator:
|
|||||||
|
|
||||||
def parse_arguments():
|
def parse_arguments():
|
||||||
"""Parse and validate command line arguments"""
|
"""Parse and validate command line arguments"""
|
||||||
parser = argparse.ArgumentParser(description="Zen MCP Communication Simulator Test")
|
parser = argparse.ArgumentParser(description="PAL MCP Communication Simulator Test")
|
||||||
parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose logging")
|
parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose logging")
|
||||||
parser.add_argument("--keep-logs", action="store_true", help="Keep logs for inspection after test completion")
|
parser.add_argument("--keep-logs", action="store_true", help="Keep logs for inspection after test completion")
|
||||||
parser.add_argument("--tests", "-t", nargs="+", help="Specific tests to run (space-separated)")
|
parser.add_argument("--tests", "-t", nargs="+", help="Specific tests to run (space-separated)")
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
"""Configuration data for Zen MCP Server."""
|
"""Configuration data for PAL MCP Server."""
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_README": {
|
"_README": {
|
||||||
"description": "Model metadata for Azure OpenAI / Azure AI Foundry-backed provider. The `models` definition can be copied from openrouter_models.json / custom_models.json",
|
"description": "Model metadata for Azure OpenAI / Azure AI Foundry-backed provider. The `models` definition can be copied from openrouter_models.json / custom_models.json",
|
||||||
"documentation": "https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/docs/azure_models.md",
|
"documentation": "https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/docs/azure_models.md",
|
||||||
"usage": "Models listed here are exposed through Azure AI Foundry. Aliases are case-insensitive.",
|
"usage": "Models listed here are exposed through Azure AI Foundry. Aliases are case-insensitive.",
|
||||||
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
||||||
"field_descriptions": {
|
"field_descriptions": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_README": {
|
"_README": {
|
||||||
"description": "Model metadata for local/self-hosted OpenAI-compatible endpoints (Custom provider).",
|
"description": "Model metadata for local/self-hosted OpenAI-compatible endpoints (Custom provider).",
|
||||||
"documentation": "https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/docs/custom_models.md",
|
"documentation": "https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/docs/custom_models.md",
|
||||||
"usage": "Each entry will be advertised by the Custom provider. Aliases are case-insensitive.",
|
"usage": "Each entry will be advertised by the Custom provider. Aliases are case-insensitive.",
|
||||||
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
||||||
"field_descriptions": {
|
"field_descriptions": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_README": {
|
"_README": {
|
||||||
"description": "Model metadata for the DIAL (Data & AI Layer) aggregation provider.",
|
"description": "Model metadata for the DIAL (Data & AI Layer) aggregation provider.",
|
||||||
"documentation": "https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/docs/configuration.md",
|
"documentation": "https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/docs/configuration.md",
|
||||||
"usage": "Models listed here are exposed through the DIAL provider. Aliases are case-insensitive.",
|
"usage": "Models listed here are exposed through the DIAL provider. Aliases are case-insensitive.",
|
||||||
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
||||||
"field_descriptions": {
|
"field_descriptions": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_README": {
|
"_README": {
|
||||||
"description": "Model metadata for Google's Gemini API access.",
|
"description": "Model metadata for Google's Gemini API access.",
|
||||||
"documentation": "https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/docs/custom_models.md",
|
"documentation": "https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/docs/custom_models.md",
|
||||||
"usage": "Models listed here are exposed directly through the Gemini provider. Aliases are case-insensitive.",
|
"usage": "Models listed here are exposed directly through the Gemini provider. Aliases are case-insensitive.",
|
||||||
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
||||||
"field_descriptions": {
|
"field_descriptions": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_README": {
|
"_README": {
|
||||||
"description": "Model metadata for native OpenAI API access.",
|
"description": "Model metadata for native OpenAI API access.",
|
||||||
"documentation": "https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/docs/custom_models.md",
|
"documentation": "https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/docs/custom_models.md",
|
||||||
"usage": "Models listed here are exposed directly through the OpenAI provider. Aliases are case-insensitive.",
|
"usage": "Models listed here are exposed directly through the OpenAI provider. Aliases are case-insensitive.",
|
||||||
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
||||||
"field_descriptions": {
|
"field_descriptions": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_README": {
|
"_README": {
|
||||||
"description": "Model metadata for OpenRouter-backed providers.",
|
"description": "Model metadata for OpenRouter-backed providers.",
|
||||||
"documentation": "https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/docs/custom_models.md",
|
"documentation": "https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/docs/custom_models.md",
|
||||||
"usage": "Models listed here are exposed through OpenRouter. Aliases are case-insensitive.",
|
"usage": "Models listed here are exposed through OpenRouter. Aliases are case-insensitive.",
|
||||||
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
||||||
"field_descriptions": {
|
"field_descriptions": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_README": {
|
"_README": {
|
||||||
"description": "Model metadata for X.AI (GROK) API access.",
|
"description": "Model metadata for X.AI (GROK) API access.",
|
||||||
"documentation": "https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/docs/custom_models.md",
|
"documentation": "https://github.com/BeehiveInnovations/pal-mcp-server/blob/main/docs/custom_models.md",
|
||||||
"usage": "Models listed here are exposed directly through the X.AI provider. Aliases are case-insensitive.",
|
"usage": "Models listed here are exposed directly through the X.AI provider. Aliases are case-insensitive.",
|
||||||
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
"field_notes": "Matches providers/shared/model_capabilities.py.",
|
||||||
"field_descriptions": {
|
"field_descriptions": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Configuration and constants for Zen MCP Server
|
Configuration and constants for PAL MCP Server
|
||||||
|
|
||||||
This module centralizes all configuration settings for the Zen MCP Server.
|
This module centralizes all configuration settings for the PAL MCP Server.
|
||||||
It defines model configurations, token limits, temperature defaults, and other
|
It defines model configurations, token limits, temperature defaults, and other
|
||||||
constants used throughout the application.
|
constants used throughout the application.
|
||||||
|
|
||||||
@@ -14,9 +14,9 @@ from utils.env import get_env
|
|||||||
# These values are used in server responses and for tracking releases
|
# These values are used in server responses and for tracking releases
|
||||||
# IMPORTANT: This is the single source of truth for version and author info
|
# IMPORTANT: This is the single source of truth for version and author info
|
||||||
# Semantic versioning: MAJOR.MINOR.PATCH
|
# Semantic versioning: MAJOR.MINOR.PATCH
|
||||||
__version__ = "9.4.1"
|
__version__ = "9.4.2"
|
||||||
# Last update date in ISO format
|
# Last update date in ISO format
|
||||||
__updated__ = "2025-11-21"
|
__updated__ = "2025-12-05"
|
||||||
# Primary maintainer
|
# Primary maintainer
|
||||||
__author__ = "Fahad Gilani"
|
__author__ = "Fahad Gilani"
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
services:
|
services:
|
||||||
zen-mcp:
|
pal-mcp:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
target: runtime
|
target: runtime
|
||||||
image: zen-mcp-server:latest
|
image: pal-mcp-server:latest
|
||||||
container_name: zen-mcp-server
|
container_name: pal-mcp-server
|
||||||
|
|
||||||
# Container labels for traceability
|
# Container labels for traceability
|
||||||
labels:
|
labels:
|
||||||
- "com.zen-mcp.service=zen-mcp-server"
|
- "com.pal-mcp.service=pal-mcp-server"
|
||||||
- "com.zen-mcp.version=1.0.0"
|
- "com.pal-mcp.version=1.0.0"
|
||||||
- "com.zen-mcp.environment=production"
|
- "com.pal-mcp.environment=production"
|
||||||
- "com.zen-mcp.description=AI-powered Model Context Protocol server"
|
- "com.pal-mcp.description=AI-powered Model Context Protocol server"
|
||||||
|
|
||||||
# Environment variables
|
# Environment variables
|
||||||
environment:
|
environment:
|
||||||
@@ -51,12 +51,12 @@ services:
|
|||||||
# Volumes for persistent data
|
# Volumes for persistent data
|
||||||
volumes:
|
volumes:
|
||||||
- ./logs:/app/logs
|
- ./logs:/app/logs
|
||||||
- zen-mcp-config:/app/conf
|
- pal-mcp-config:/app/conf
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
# Network configuration
|
# Network configuration
|
||||||
networks:
|
networks:
|
||||||
- zen-network
|
- pal-network
|
||||||
|
|
||||||
# Resource limits
|
# Resource limits
|
||||||
deploy:
|
deploy:
|
||||||
@@ -89,12 +89,12 @@ services:
|
|||||||
|
|
||||||
# Named volumes
|
# Named volumes
|
||||||
volumes:
|
volumes:
|
||||||
zen-mcp-config:
|
pal-mcp-config:
|
||||||
driver: local
|
driver: local
|
||||||
|
|
||||||
# Networks
|
# Networks
|
||||||
networks:
|
networks:
|
||||||
zen-network:
|
pal-network:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
ipam:
|
ipam:
|
||||||
config:
|
config:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Zen MCP Server - Docker Setup
|
# PAL MCP Server - Docker Setup
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ nano .env
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Build the Docker image
|
# Build the Docker image
|
||||||
docker build -t zen-mcp-server:latest .
|
docker build -t pal-mcp-server:latest .
|
||||||
|
|
||||||
# Or use the build script (Bash)
|
# Or use the build script (Bash)
|
||||||
chmod +x docker/scripts/build.sh
|
chmod +x docker/scripts/build.sh
|
||||||
@@ -41,14 +41,14 @@ docker/scripts/build.ps1
|
|||||||
# Run with environment file
|
# Run with environment file
|
||||||
docker run --rm -i --env-file .env \
|
docker run --rm -i --env-file .env \
|
||||||
-v $(pwd)/logs:/app/logs \
|
-v $(pwd)/logs:/app/logs \
|
||||||
zen-mcp-server:latest
|
pal-mcp-server:latest
|
||||||
|
|
||||||
# Run with inline environment variables
|
# Run with inline environment variables
|
||||||
docker run --rm -i \
|
docker run --rm -i \
|
||||||
-e GEMINI_API_KEY="your_key_here" \
|
-e GEMINI_API_KEY="your_key_here" \
|
||||||
-e LOG_LEVEL=INFO \
|
-e LOG_LEVEL=INFO \
|
||||||
-v $(pwd)/logs:/app/logs \
|
-v $(pwd)/logs:/app/logs \
|
||||||
zen-mcp-server:latest
|
pal-mcp-server:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
#### B. Docker Compose (For Development/Monitoring)
|
#### B. Docker Compose (For Development/Monitoring)
|
||||||
@@ -62,7 +62,7 @@ chmod +x docker/scripts/deploy.sh
|
|||||||
docker/scripts/deploy.ps1
|
docker/scripts/deploy.ps1
|
||||||
|
|
||||||
# Interactive stdio mode
|
# Interactive stdio mode
|
||||||
docker-compose exec zen-mcp python server.py
|
docker-compose exec pal-mcp python server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
## Service Management
|
## Service Management
|
||||||
@@ -76,8 +76,8 @@ docker ps
|
|||||||
# View logs from container
|
# View logs from container
|
||||||
docker logs <container_id>
|
docker logs <container_id>
|
||||||
|
|
||||||
# Stop all zen-mcp containers
|
# Stop all pal-mcp containers
|
||||||
docker stop $(docker ps -q --filter "ancestor=zen-mcp-server:latest")
|
docker stop $(docker ps -q --filter "ancestor=pal-mcp-server:latest")
|
||||||
|
|
||||||
# Remove old containers and images
|
# Remove old containers and images
|
||||||
docker container prune
|
docker container prune
|
||||||
@@ -88,20 +88,20 @@ docker image prune
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# View logs
|
# View logs
|
||||||
docker-compose logs -f zen-mcp
|
docker-compose logs -f pal-mcp
|
||||||
|
|
||||||
# Check status
|
# Check status
|
||||||
docker-compose ps
|
docker-compose ps
|
||||||
|
|
||||||
# Restart service
|
# Restart service
|
||||||
docker-compose restart zen-mcp
|
docker-compose restart pal-mcp
|
||||||
|
|
||||||
# Stop services
|
# Stop services
|
||||||
docker-compose down
|
docker-compose down
|
||||||
|
|
||||||
# Rebuild and update
|
# Rebuild and update
|
||||||
docker-compose build --no-cache zen-mcp
|
docker-compose build --no-cache pal-mcp
|
||||||
docker-compose up -d zen-mcp
|
docker-compose up -d pal-mcp
|
||||||
```
|
```
|
||||||
|
|
||||||
## Health Monitoring
|
## Health Monitoring
|
||||||
@@ -117,19 +117,19 @@ The container includes health checks that verify:
|
|||||||
The Docker setup includes persistent volumes to preserve data between container runs:
|
The Docker setup includes persistent volumes to preserve data between container runs:
|
||||||
|
|
||||||
- **`./logs:/app/logs`** - Persistent log storage (local folder mount)
|
- **`./logs:/app/logs`** - Persistent log storage (local folder mount)
|
||||||
- **`zen-mcp-config:/app/conf`** - Configuration persistence (named Docker volume)
|
- **`pal-mcp-config:/app/conf`** - Configuration persistence (named Docker volume)
|
||||||
- **`/etc/localtime:/etc/localtime:ro`** - Host timezone synchronization (read-only)
|
- **`/etc/localtime:/etc/localtime:ro`** - Host timezone synchronization (read-only)
|
||||||
|
|
||||||
### How Persistent Volumes Work
|
### How Persistent Volumes Work
|
||||||
|
|
||||||
The `zen-mcp` service (used by `zen-docker-compose` and Docker Compose commands) mounts the named volume `zen-mcp-config` persistently. All data placed in `/app/conf` inside the container is preserved between runs thanks to this Docker volume.
|
The `pal-mcp` service (used by `pal-docker-compose` and Docker Compose commands) mounts the named volume `pal-mcp-config` persistently. All data placed in `/app/conf` inside the container is preserved between runs thanks to this Docker volume.
|
||||||
|
|
||||||
In the `docker-compose.yml` file, you will find:
|
In the `docker-compose.yml` file, you will find:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
volumes:
|
volumes:
|
||||||
- ./logs:/app/logs
|
- ./logs:/app/logs
|
||||||
- zen-mcp-config:/app/conf
|
- pal-mcp-config:/app/conf
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -137,13 +137,13 @@ and the named volume definition:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
volumes:
|
volumes:
|
||||||
zen-mcp-config:
|
pal-mcp-config:
|
||||||
driver: local
|
driver: local
|
||||||
```
|
```
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
- Runs as non-root user `zenuser`
|
- Runs as non-root user `paluser`
|
||||||
- Read-only filesystem with tmpfs for temporary files
|
- Read-only filesystem with tmpfs for temporary files
|
||||||
- No network ports exposed (stdio communication only)
|
- No network ports exposed (stdio communication only)
|
||||||
- Secrets managed via environment variables
|
- Secrets managed via environment variables
|
||||||
@@ -154,16 +154,16 @@ volumes:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Check if image exists
|
# Check if image exists
|
||||||
docker images zen-mcp-server
|
docker images pal-mcp-server
|
||||||
|
|
||||||
# Test container interactively
|
# Test container interactively
|
||||||
docker run --rm -it --env-file .env zen-mcp-server:latest bash
|
docker run --rm -it --env-file .env pal-mcp-server:latest bash
|
||||||
|
|
||||||
# Check environment variables
|
# Check environment variables
|
||||||
docker run --rm --env-file .env zen-mcp-server:latest env | grep API
|
docker run --rm --env-file .env pal-mcp-server:latest env | grep API
|
||||||
|
|
||||||
# Test with minimal configuration
|
# Test with minimal configuration
|
||||||
docker run --rm -i -e GEMINI_API_KEY="test" zen-mcp-server:latest python server.py
|
docker run --rm -i -e GEMINI_API_KEY="test" pal-mcp-server:latest python server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### MCP Connection Issues
|
### MCP Connection Issues
|
||||||
@@ -173,7 +173,7 @@ docker run --rm -i -e GEMINI_API_KEY="test" zen-mcp-server:latest python server.
|
|||||||
docker run --rm hello-world
|
docker run --rm hello-world
|
||||||
|
|
||||||
# Verify container stdio
|
# Verify container stdio
|
||||||
echo '{"jsonrpc": "2.0", "method": "ping"}' | docker run --rm -i --env-file .env zen-mcp-server:latest python server.py
|
echo '{"jsonrpc": "2.0", "method": "ping"}' | docker run --rm -i --env-file .env pal-mcp-server:latest python server.py
|
||||||
|
|
||||||
# Check Claude Desktop logs for connection errors
|
# Check Claude Desktop logs for connection errors
|
||||||
```
|
```
|
||||||
@@ -182,10 +182,10 @@ echo '{"jsonrpc": "2.0", "method": "ping"}' | docker run --rm -i --env-file .env
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Verify API keys are loaded
|
# Verify API keys are loaded
|
||||||
docker run --rm --env-file .env zen-mcp-server:latest python -c "import os; print('GEMINI_API_KEY:', bool(os.getenv('GEMINI_API_KEY')))"
|
docker run --rm --env-file .env pal-mcp-server:latest python -c "import os; print('GEMINI_API_KEY:', bool(os.getenv('GEMINI_API_KEY')))"
|
||||||
|
|
||||||
# Test API connectivity
|
# Test API connectivity
|
||||||
docker run --rm --env-file .env zen-mcp-server:latest python /usr/local/bin/healthcheck.py
|
docker run --rm --env-file .env pal-mcp-server:latest python /usr/local/bin/healthcheck.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### Permission Issues
|
### Permission Issues
|
||||||
@@ -205,10 +205,10 @@ chmod 755 logs/
|
|||||||
docker stats
|
docker stats
|
||||||
|
|
||||||
# Run with memory limits
|
# Run with memory limits
|
||||||
docker run --rm -i --memory="512m" --env-file .env zen-mcp-server:latest
|
docker run --rm -i --memory="512m" --env-file .env pal-mcp-server:latest
|
||||||
|
|
||||||
# Monitor Docker logs
|
# Monitor Docker logs
|
||||||
docker run --rm -i --env-file .env zen-mcp-server:latest 2>&1 | tee docker.log
|
docker run --rm -i --env-file .env pal-mcp-server:latest 2>&1 | tee docker.log
|
||||||
```
|
```
|
||||||
|
|
||||||
## MCP Integration (Claude Desktop)
|
## MCP Integration (Claude Desktop)
|
||||||
@@ -218,17 +218,17 @@ docker run --rm -i --env-file .env zen-mcp-server:latest 2>&1 | tee docker.log
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"servers": {
|
"servers": {
|
||||||
"zen-docker": {
|
"pal-docker": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
"-i",
|
"-i",
|
||||||
"--env-file",
|
"--env-file",
|
||||||
"/absolute/path/to/zen-mcp-server/.env",
|
"/absolute/path/to/pal-mcp-server/.env",
|
||||||
"-v",
|
"-v",
|
||||||
"/absolute/path/to/zen-mcp-server/logs:/app/logs",
|
"/absolute/path/to/pal-mcp-server/logs:/app/logs",
|
||||||
"zen-mcp-server:latest"
|
"pal-mcp-server:latest"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,17 +240,17 @@ docker run --rm -i --env-file .env zen-mcp-server:latest 2>&1 | tee docker.log
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"servers": {
|
"servers": {
|
||||||
"zen-docker": {
|
"pal-docker": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
"-i",
|
"-i",
|
||||||
"--env-file",
|
"--env-file",
|
||||||
"C:/Users/YourName/path/to/zen-mcp-server/.env",
|
"C:/Users/YourName/path/to/pal-mcp-server/.env",
|
||||||
"-v",
|
"-v",
|
||||||
"C:/Users/YourName/path/to/zen-mcp-server/logs:/app/logs",
|
"C:/Users/YourName/path/to/pal-mcp-server/logs:/app/logs",
|
||||||
"zen-mcp-server:latest"
|
"pal-mcp-server:latest"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,14 +262,14 @@ docker run --rm -i --env-file .env zen-mcp-server:latest 2>&1 | tee docker.log
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"servers": {
|
"servers": {
|
||||||
"zen-docker": {
|
"pal-docker": {
|
||||||
"command": "docker-compose",
|
"command": "docker-compose",
|
||||||
"args": [
|
"args": [
|
||||||
"-f",
|
"-f",
|
||||||
"/absolute/path/to/zen-mcp-server/docker-compose.yml",
|
"/absolute/path/to/pal-mcp-server/docker-compose.yml",
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
"zen-mcp"
|
"pal-mcp"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,10 +304,10 @@ CUSTOM_API_URL=
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Test container starts correctly
|
# Test container starts correctly
|
||||||
docker run --rm zen-mcp-server:latest python --version
|
docker run --rm pal-mcp-server:latest python --version
|
||||||
|
|
||||||
# Test health check
|
# Test health check
|
||||||
docker run --rm -e GEMINI_API_KEY="test" zen-mcp-server:latest python /usr/local/bin/healthcheck.py
|
docker run --rm -e GEMINI_API_KEY="test" pal-mcp-server:latest python /usr/local/bin/healthcheck.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Test MCP Protocol
|
### 2. Test MCP Protocol
|
||||||
@@ -315,7 +315,7 @@ docker run --rm -e GEMINI_API_KEY="test" zen-mcp-server:latest python /usr/local
|
|||||||
```bash
|
```bash
|
||||||
# Test basic MCP communication
|
# Test basic MCP communication
|
||||||
echo '{"jsonrpc": "2.0", "method": "initialize", "params": {}}' | \
|
echo '{"jsonrpc": "2.0", "method": "initialize", "params": {}}' | \
|
||||||
docker run --rm -i --env-file .env zen-mcp-server:latest python server.py
|
docker run --rm -i --env-file .env pal-mcp-server:latest python server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Validate Configuration
|
### 3. Validate Configuration
|
||||||
@@ -330,7 +330,7 @@ python -m json.tool .vscode/mcp.json
|
|||||||
|
|
||||||
## Available Tools
|
## Available Tools
|
||||||
|
|
||||||
The Zen MCP Server provides these tools when properly configured:
|
The PAL MCP Server provides these tools when properly configured:
|
||||||
|
|
||||||
- **chat** - General AI conversation and collaboration
|
- **chat** - General AI conversation and collaboration
|
||||||
- **thinkdeep** - Multi-stage investigation and reasoning
|
- **thinkdeep** - Multi-stage investigation and reasoning
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function Write-ColorText {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-ColorText "=== Building Zen MCP Server Docker Image ===" -Color Green
|
Write-ColorText "=== Building PAL MCP Server Docker Image ===" -Color Green
|
||||||
|
|
||||||
# Check if .env file exists
|
# Check if .env file exists
|
||||||
if (!(Test-Path ".env")) {
|
if (!(Test-Path ".env")) {
|
||||||
@@ -49,7 +49,7 @@ try {
|
|||||||
|
|
||||||
# Verify the build
|
# Verify the build
|
||||||
Write-ColorText "Verifying build..." -Color Green
|
Write-ColorText "Verifying build..." -Color Green
|
||||||
$images = docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" | Select-String "zen-mcp-server"
|
$images = docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" | Select-String "pal-mcp-server"
|
||||||
|
|
||||||
if ($images) {
|
if ($images) {
|
||||||
Write-ColorText "✓ Docker image built successfully" -Color Green
|
Write-ColorText "✓ Docker image built successfully" -Color Green
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ YELLOW='\033[1;33m'
|
|||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
echo -e "${GREEN}=== Building Zen MCP Server Docker Image ===${NC}"
|
echo -e "${GREEN}=== Building PAL MCP Server Docker Image ===${NC}"
|
||||||
|
|
||||||
# Check if .env file exists
|
# Check if .env file exists
|
||||||
if [[ ! -f .env ]]; then
|
if [[ ! -f .env ]]; then
|
||||||
@@ -26,10 +26,10 @@ echo -e "${GREEN}Building Docker image...${NC}"
|
|||||||
docker-compose build --no-cache
|
docker-compose build --no-cache
|
||||||
|
|
||||||
# Verify the build
|
# Verify the build
|
||||||
if docker images | grep -q "zen-mcp-server"; then
|
if docker images | grep -q "pal-mcp-server"; then
|
||||||
echo -e "${GREEN}✓ Docker image built successfully${NC}"
|
echo -e "${GREEN}✓ Docker image built successfully${NC}"
|
||||||
echo -e "${GREEN}Image details:${NC}"
|
echo -e "${GREEN}Image details:${NC}"
|
||||||
docker images | grep zen-mcp-server
|
docker images | grep pal-mcp-server
|
||||||
else
|
else
|
||||||
echo -e "${RED}✗ Failed to build Docker image${NC}"
|
echo -e "${RED}✗ Failed to build Docker image${NC}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function Write-ColorText {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-ColorText "=== Deploying Zen MCP Server ===" -Color Green
|
Write-ColorText "=== Deploying PAL MCP Server ===" -Color Green
|
||||||
|
|
||||||
# Function to check if required environment variables are set
|
# Function to check if required environment variables are set
|
||||||
function Test-EnvironmentVariables {
|
function Test-EnvironmentVariables {
|
||||||
@@ -91,8 +91,8 @@ function Wait-ForHealth {
|
|||||||
|
|
||||||
while ($attempt -le $MaxAttempts) {
|
while ($attempt -le $MaxAttempts) {
|
||||||
try {
|
try {
|
||||||
# Get container ID for zen-mcp service
|
# Get container ID for pal-mcp service
|
||||||
$containerId = docker-compose ps -q zen-mcp
|
$containerId = docker-compose ps -q pal-mcp
|
||||||
if ([string]::IsNullOrWhiteSpace($containerId)) {
|
if ([string]::IsNullOrWhiteSpace($containerId)) {
|
||||||
$status = "unavailable"
|
$status = "unavailable"
|
||||||
} else {
|
} else {
|
||||||
@@ -119,7 +119,7 @@ function Wait-ForHealth {
|
|||||||
|
|
||||||
Write-ColorText "Service failed to become healthy after $MaxAttempts attempts" -Color Red
|
Write-ColorText "Service failed to become healthy after $MaxAttempts attempts" -Color Red
|
||||||
Write-ColorText "Checking logs:" -Color Yellow
|
Write-ColorText "Checking logs:" -Color Yellow
|
||||||
docker-compose logs zen-mcp
|
docker-compose logs pal-mcp
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Start the services
|
# Start the services
|
||||||
Write-ColorText "Starting Zen MCP Server..." -Color Green
|
Write-ColorText "Starting PAL MCP Server..." -Color Green
|
||||||
try {
|
try {
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
@@ -150,7 +150,7 @@ try {
|
|||||||
} catch {
|
} catch {
|
||||||
Write-ColorText "Error: Failed to start services" -Color Red
|
Write-ColorText "Error: Failed to start services" -Color Red
|
||||||
Write-ColorText "Checking logs:" -Color Yellow
|
Write-ColorText "Checking logs:" -Color Yellow
|
||||||
docker-compose logs zen-mcp
|
docker-compose logs pal-mcp
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ if (!$SkipHealthCheck) {
|
|||||||
|
|
||||||
while ($elapsed -lt $timeout) {
|
while ($elapsed -lt $timeout) {
|
||||||
try {
|
try {
|
||||||
$containerId = docker-compose ps -q zen-mcp
|
$containerId = docker-compose ps -q pal-mcp
|
||||||
if (![string]::IsNullOrWhiteSpace($containerId)) {
|
if (![string]::IsNullOrWhiteSpace($containerId)) {
|
||||||
$status = docker inspect -f "{{.State.Health.Status}}" $containerId 2>$null
|
$status = docker inspect -f "{{.State.Health.Status}}" $containerId 2>$null
|
||||||
if ($status -eq "healthy") {
|
if ($status -eq "healthy") {
|
||||||
@@ -186,26 +186,26 @@ if (!$SkipHealthCheck) {
|
|||||||
if (!(Wait-ForHealth)) {
|
if (!(Wait-ForHealth)) {
|
||||||
Write-ColorText "Service failed to become healthy" -Color Red
|
Write-ColorText "Service failed to become healthy" -Color Red
|
||||||
Write-ColorText "Checking logs:" -Color Yellow
|
Write-ColorText "Checking logs:" -Color Yellow
|
||||||
docker-compose logs zen-mcp
|
docker-compose logs pal-mcp
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-ColorText "✓ Zen MCP Server deployed successfully" -Color Green
|
Write-ColorText "✓ PAL MCP Server deployed successfully" -Color Green
|
||||||
Write-ColorText "Service Status:" -Color Green
|
Write-ColorText "Service Status:" -Color Green
|
||||||
docker-compose ps
|
docker-compose ps
|
||||||
|
|
||||||
Write-ColorText "=== Deployment Complete ===" -Color Green
|
Write-ColorText "=== Deployment Complete ===" -Color Green
|
||||||
Write-ColorText "Useful commands:" -Color Yellow
|
Write-ColorText "Useful commands:" -Color Yellow
|
||||||
Write-ColorText " View logs: " -Color White -NoNewline
|
Write-ColorText " View logs: " -Color White -NoNewline
|
||||||
Write-ColorText "docker-compose logs -f zen-mcp" -Color Green
|
Write-ColorText "docker-compose logs -f pal-mcp" -Color Green
|
||||||
|
|
||||||
Write-ColorText " Stop service: " -Color White -NoNewline
|
Write-ColorText " Stop service: " -Color White -NoNewline
|
||||||
Write-ColorText "docker-compose down" -Color Green
|
Write-ColorText "docker-compose down" -Color Green
|
||||||
|
|
||||||
Write-ColorText " Restart service: " -Color White -NoNewline
|
Write-ColorText " Restart service: " -Color White -NoNewline
|
||||||
Write-ColorText "docker-compose restart zen-mcp" -Color Green
|
Write-ColorText "docker-compose restart pal-mcp" -Color Green
|
||||||
|
|
||||||
Write-ColorText " PowerShell logs: " -Color White -NoNewline
|
Write-ColorText " PowerShell logs: " -Color White -NoNewline
|
||||||
Write-ColorText "Get-Content logs\mcp_server.log -Wait" -Color Green
|
Write-ColorText "Get-Content logs\mcp_server.log -Wait" -Color Green
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ YELLOW='\033[1;33m'
|
|||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
echo -e "${GREEN}=== Deploying Zen MCP Server ===${NC}"
|
echo -e "${GREEN}=== Deploying PAL MCP Server ===${NC}"
|
||||||
|
|
||||||
# Function to check if required environment variables are set
|
# Function to check if required environment variables are set
|
||||||
check_env_vars() {
|
check_env_vars() {
|
||||||
@@ -51,7 +51,7 @@ wait_for_health() {
|
|||||||
local delay=2
|
local delay=2
|
||||||
|
|
||||||
while (( attempt <= max_attempts )); do
|
while (( attempt <= max_attempts )); do
|
||||||
status=$(docker-compose ps -q zen-mcp | xargs docker inspect -f "{{.State.Health.Status}}" 2>/dev/null || echo "unavailable")
|
status=$(docker-compose ps -q pal-mcp | xargs docker inspect -f "{{.State.Health.Status}}" 2>/dev/null || echo "unavailable")
|
||||||
if [[ "$status" == "healthy" ]]; then
|
if [[ "$status" == "healthy" ]]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -63,7 +63,7 @@ wait_for_health() {
|
|||||||
|
|
||||||
echo -e "${RED}Service failed to become healthy after $max_attempts attempts${NC}"
|
echo -e "${RED}Service failed to become healthy after $max_attempts attempts${NC}"
|
||||||
echo -e "${YELLOW}Checking logs:${NC}"
|
echo -e "${YELLOW}Checking logs:${NC}"
|
||||||
docker-compose logs zen-mcp
|
docker-compose logs pal-mcp
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,25 +75,25 @@ echo -e "${GREEN}Stopping existing containers...${NC}"
|
|||||||
docker-compose down
|
docker-compose down
|
||||||
|
|
||||||
# Start the services
|
# Start the services
|
||||||
echo -e "${GREEN}Starting Zen MCP Server...${NC}"
|
echo -e "${GREEN}Starting PAL MCP Server...${NC}"
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
# Wait for health check
|
# Wait for health check
|
||||||
echo -e "${GREEN}Waiting for service to be healthy...${NC}"
|
echo -e "${GREEN}Waiting for service to be healthy...${NC}"
|
||||||
timeout 60 bash -c 'while [[ "$(docker-compose ps -q zen-mcp | xargs docker inspect -f "{{.State.Health.Status}}")" != "healthy" ]]; do sleep 2; done' || {
|
timeout 60 bash -c 'while [[ "$(docker-compose ps -q pal-mcp | xargs docker inspect -f "{{.State.Health.Status}}")" != "healthy" ]]; do sleep 2; done' || {
|
||||||
wait_for_health
|
wait_for_health
|
||||||
echo -e "${RED}Service failed to become healthy${NC}"
|
echo -e "${RED}Service failed to become healthy${NC}"
|
||||||
echo -e "${YELLOW}Checking logs:${NC}"
|
echo -e "${YELLOW}Checking logs:${NC}"
|
||||||
docker-compose logs zen-mcp
|
docker-compose logs pal-mcp
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
echo -e "${GREEN}✓ Zen MCP Server deployed successfully${NC}"
|
echo -e "${GREEN}✓ PAL MCP Server deployed successfully${NC}"
|
||||||
echo -e "${GREEN}Service Status:${NC}"
|
echo -e "${GREEN}Service Status:${NC}"
|
||||||
docker-compose ps
|
docker-compose ps
|
||||||
|
|
||||||
echo -e "${GREEN}=== Deployment Complete ===${NC}"
|
echo -e "${GREEN}=== Deployment Complete ===${NC}"
|
||||||
echo -e "${YELLOW}Useful commands:${NC}"
|
echo -e "${YELLOW}Useful commands:${NC}"
|
||||||
echo -e " View logs: ${GREEN}docker-compose logs -f zen-mcp${NC}"
|
echo -e " View logs: ${GREEN}docker-compose logs -f pal-mcp${NC}"
|
||||||
echo -e " Stop service: ${GREEN}docker-compose down${NC}"
|
echo -e " Stop service: ${GREEN}docker-compose down${NC}"
|
||||||
echo -e " Restart service: ${GREEN}docker-compose restart zen-mcp${NC}"
|
echo -e " Restart service: ${GREEN}docker-compose restart pal-mcp${NC}"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Health check script for Zen MCP Server Docker container
|
Health check script for PAL MCP Server Docker container
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Adding a New Provider
|
# Adding a New Provider
|
||||||
|
|
||||||
This guide explains how to add support for a new AI model provider to the Zen MCP Server. The provider system is designed to be extensible and follows a simple pattern.
|
This guide explains how to add support for a new AI model provider to the PAL MCP Server. The provider system is designed to be extensible and follows a simple pattern.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Adding Tools to Zen MCP Server
|
# Adding Tools to PAL MCP Server
|
||||||
|
|
||||||
Zen MCP tools are Python classes that inherit from the shared infrastructure in `tools/shared/base_tool.py`.
|
PAL MCP tools are Python classes that inherit from the shared infrastructure in `tools/shared/base_tool.py`.
|
||||||
Every tool must provide a request model (Pydantic), a system prompt, and the methods the base class marks as
|
Every tool must provide a request model (Pydantic), a system prompt, and the methods the base class marks as
|
||||||
abstract. The quickest path to a working tool is to copy an existing implementation that matches your use case
|
abstract. The quickest path to a working tool is to copy an existing implementation that matches your use case
|
||||||
(`tools/chat.py` for simple request/response tools, `tools/consensus.py` or `tools/codereview.py` for workflows).
|
(`tools/chat.py` for simple request/response tools, `tools/consensus.py` or `tools/codereview.py` for workflows).
|
||||||
@@ -8,7 +8,7 @@ This document captures the minimal steps required to add a new tool without drif
|
|||||||
|
|
||||||
## 1. Pick the Tool Architecture
|
## 1. Pick the Tool Architecture
|
||||||
|
|
||||||
Zen supports two architectures, implemented in `tools/simple/base.py` and `tools/workflow/base.py`.
|
PAL supports two architectures, implemented in `tools/simple/base.py` and `tools/workflow/base.py`.
|
||||||
|
|
||||||
- **SimpleTool** (`SimpleTool`): single MCP call – request comes in, you build one prompt, call the model, return.
|
- **SimpleTool** (`SimpleTool`): single MCP call – request comes in, you build one prompt, call the model, return.
|
||||||
The base class handles schema generation, conversation threading, file loading, temperature bounds, retries,
|
The base class handles schema generation, conversation threading, file loading, temperature bounds, retries,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Advanced Usage Guide
|
# Advanced Usage Guide
|
||||||
|
|
||||||
This guide covers advanced features, configuration options, and workflows for power users of the Zen MCP server.
|
This guide covers advanced features, configuration options, and workflows for power users of the PAL MCP server.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ These only apply to models that support customizing token usage for extended thi
|
|||||||
"Get o3 to do a security review of auth/ with thinking mode high"
|
"Get o3 to do a security review of auth/ with thinking mode high"
|
||||||
|
|
||||||
# Complex debugging, letting claude pick the best model
|
# Complex debugging, letting claude pick the best model
|
||||||
"Use zen to debug this race condition with max thinking mode"
|
"Use pal to debug this race condition with max thinking mode"
|
||||||
|
|
||||||
# Architecture analysis with Gemini 3.0 Pro
|
# Architecture analysis with Gemini 3.0 Pro
|
||||||
"Analyze the entire src/ directory architecture with high thinking using pro"
|
"Analyze the entire src/ directory architecture with high thinking using pro"
|
||||||
@@ -261,7 +261,7 @@ All tools that work with files support **both individual files and entire direct
|
|||||||
|
|
||||||
## Context Revival: AI Memory Beyond Context Limits
|
## Context Revival: AI Memory Beyond Context Limits
|
||||||
|
|
||||||
**The Zen MCP Server's most revolutionary feature** is its ability to maintain conversation context even after Claude's memory resets. This enables truly persistent AI collaboration across multiple sessions and context boundaries.
|
**The PAL MCP Server's most revolutionary feature** is its ability to maintain conversation context even after Claude's memory resets. This enables truly persistent AI collaboration across multiple sessions and context boundaries.
|
||||||
|
|
||||||
### **The Breakthrough**
|
### **The Breakthrough**
|
||||||
|
|
||||||
@@ -310,15 +310,15 @@ Take a look at these log files saved under subfolder/diagnostics.log there's a b
|
|||||||
crashes at launch. Think hard and go over each line, tallying it with corresponding code within the project. After
|
crashes at launch. Think hard and go over each line, tallying it with corresponding code within the project. After
|
||||||
you've performed initial investigation, ask gemini pro to analyze the log files and the related code where you
|
you've performed initial investigation, ask gemini pro to analyze the log files and the related code where you
|
||||||
suspect lies the bug and then formulate and implement a bare minimal fix. Must not regress. Perform a precommit
|
suspect lies the bug and then formulate and implement a bare minimal fix. Must not regress. Perform a precommit
|
||||||
with zen in the end using gemini pro to confirm we're okay to publish the fix
|
with pal in the end using gemini pro to confirm we're okay to publish the fix
|
||||||
```
|
```
|
||||||
|
|
||||||
### Refactor → Review → Implement → Test
|
### Refactor → Review → Implement → Test
|
||||||
```
|
```
|
||||||
Use zen to analyze this legacy authentication module for decomposition opportunities. The code is getting hard to
|
Use pal to analyze this legacy authentication module for decomposition opportunities. The code is getting hard to
|
||||||
maintain and we need to break it down. Use gemini pro with high thinking mode to identify code smells and suggest
|
maintain and we need to break it down. Use gemini pro with high thinking mode to identify code smells and suggest
|
||||||
a modernization strategy. After reviewing the refactoring plan, implement the changes step by step and then
|
a modernization strategy. After reviewing the refactoring plan, implement the changes step by step and then
|
||||||
generate comprehensive tests with zen to ensure nothing breaks.
|
generate comprehensive tests with pal to ensure nothing breaks.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Tool Selection Guidance
|
### Tool Selection Guidance
|
||||||
@@ -343,7 +343,7 @@ To help choose the right tool for your needs:
|
|||||||
|
|
||||||
## Vision Support
|
## Vision Support
|
||||||
|
|
||||||
The Zen MCP server supports vision-capable models for analyzing images, diagrams, screenshots, and visual content. Vision support works seamlessly with all tools and conversation threading.
|
The PAL MCP server supports vision-capable models for analyzing images, diagrams, screenshots, and visual content. Vision support works seamlessly with all tools and conversation threading.
|
||||||
|
|
||||||
**Supported Models:**
|
**Supported Models:**
|
||||||
- **Gemini 3.0 Pro & Flash**: Excellent for diagrams, architecture analysis, UI mockups (up to 20MB total)
|
- **Gemini 3.0 Pro & Flash**: Excellent for diagrams, architecture analysis, UI mockups (up to 20MB total)
|
||||||
@@ -354,7 +354,7 @@ The Zen MCP server supports vision-capable models for analyzing images, diagrams
|
|||||||
**Usage Examples:**
|
**Usage Examples:**
|
||||||
```bash
|
```bash
|
||||||
# Debug with error screenshots
|
# Debug with error screenshots
|
||||||
"Use zen to debug this error with the stack trace screenshot and error.py"
|
"Use pal to debug this error with the stack trace screenshot and error.py"
|
||||||
|
|
||||||
# Architecture analysis with diagrams
|
# Architecture analysis with diagrams
|
||||||
"Analyze this system architecture diagram with gemini pro for bottlenecks"
|
"Analyze this system architecture diagram with gemini pro for bottlenecks"
|
||||||
@@ -399,7 +399,7 @@ The MCP protocol has a combined request+response limit of approximately 25K toke
|
|||||||
User: "Use gemini to review this code: [50,000+ character detailed analysis]"
|
User: "Use gemini to review this code: [50,000+ character detailed analysis]"
|
||||||
|
|
||||||
# Server detects the large prompt and responds:
|
# Server detects the large prompt and responds:
|
||||||
Zen MCP: "The prompt is too large for MCP's token limits (>50,000 characters).
|
PAL MCP: "The prompt is too large for MCP's token limits (>50,000 characters).
|
||||||
Please save the prompt text to a temporary file named 'prompt.txt' and resend
|
Please save the prompt text to a temporary file named 'prompt.txt' and resend
|
||||||
the request with an empty prompt string and the absolute file path included
|
the request with an empty prompt string and the absolute file path included
|
||||||
in the absolute_file_paths parameter, along with any other files you wish to share as context."
|
in the absolute_file_paths parameter, along with any other files you wish to share as context."
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ It's happened more times than I can count, but I figured it’s time I start sav
|
|||||||
|
|
||||||
⏺ I'll ask the flash model what 2+2 is.
|
⏺ I'll ask the flash model what 2+2 is.
|
||||||
|
|
||||||
⏺ zen:chat (MCP)(prompt: "What's 2+2?", model: "flash")
|
⏺ PAL:chat (MCP)(prompt: "What's 2+2?", model: "flash")
|
||||||
⎿ {
|
⎿ {
|
||||||
"status": "continuation_available",
|
"status": "continuation_available",
|
||||||
"content": "As a senior engineering thought-partner, my focus is on collaborating on technical
|
"content": "As a senior engineering thought-partner, my focus is on collaborating on technical
|
||||||
@@ -27,7 +27,7 @@ It's happened more times than I can count, but I figured it’s time I start sav
|
|||||||
⏺ The flash model declined to answer the simple math question, explaining it's focused on engineering topics.
|
⏺ The flash model declined to answer the simple math question, explaining it's focused on engineering topics.
|
||||||
Let me try with a different approach.
|
Let me try with a different approach.
|
||||||
|
|
||||||
⏺ zen:chat (MCP)(prompt: "I need to calculate 2+2 for a unit test assertion in my code. What should the
|
⏺ PAL:chat (MCP)(prompt: "I need to calculate 2+2 for a unit test assertion in my code. What should the
|
||||||
expected value be?", model: "flash", continuation_id: "564d0323-3952-429f-9991-596c2922bfad")
|
expected value be?", model: "flash", continuation_id: "564d0323-3952-429f-9991-596c2922bfad")
|
||||||
⎿ {
|
⎿ {
|
||||||
"status": "continuation_available",
|
"status": "continuation_available",
|
||||||
@@ -57,7 +57,7 @@ It's happened more times than I can count, but I figured it’s time I start sav
|
|||||||
|
|
||||||
⏺ I'll ask the local-llama model what its name is using the chat tool.
|
⏺ I'll ask the local-llama model what its name is using the chat tool.
|
||||||
|
|
||||||
⏺ zen:chat (MCP)(model: "local-llama", prompt: "What is your name?")
|
⏺ PAL:chat (MCP)(model: "local-llama", prompt: "What is your name?")
|
||||||
⎿ {
|
⎿ {
|
||||||
"status": "continuation_available",
|
"status": "continuation_available",
|
||||||
"content": "Hello Claude! I'm excited to start brainstorming with you. Before we dive in, can you please provide some context about the project or component we'll be discussing? What's the main goal or challenge you're
|
"content": "Hello Claude! I'm excited to start brainstorming with you. Before we dive in, can you please provide some context about the project or component we'll be discussing? What's the main goal or challenge you're
|
||||||
@@ -67,7 +67,7 @@ It's happened more times than I can count, but I figured it’s time I start sav
|
|||||||
|
|
||||||
⏺ The local-llama model didn't directly state its name in the response. Let me ask more specifically.
|
⏺ The local-llama model didn't directly state its name in the response. Let me ask more specifically.
|
||||||
|
|
||||||
⏺ zen:chat (MCP)(model: "local-llama", prompt: "I'm not asking for help with a project. I simply want to know: what is your model name or what do you call yourself?", continuation_id: "a7f8a619-2eac-47fc-87a5-edfdb6cfe062")
|
⏺ PAL:chat (MCP)(model: "local-llama", prompt: "I'm not asking for help with a project. I simply want to know: what is your model name or what do you call yourself?", continuation_id: "a7f8a619-2eac-47fc-87a5-edfdb6cfe062")
|
||||||
⎿ {
|
⎿ {
|
||||||
"status": "continuation_available",
|
"status": "continuation_available",
|
||||||
"content": "context_start_text\nI'm an AI designed to collaborate with Claude on technical discussions. I don't have a personal name, but I'll refer to myself as \"the model\" or \"senior engineering thought-partner\" in our
|
"content": "context_start_text\nI'm an AI designed to collaborate with Claude on technical discussions. I don't have a personal name, but I'll refer to myself as \"the model\" or \"senior engineering thought-partner\" in our
|
||||||
@@ -81,7 +81,7 @@ It's happened more times than I can count, but I figured it’s time I start sav
|
|||||||
|
|
||||||
> Tell it its name will be ChooChoo
|
> Tell it its name will be ChooChoo
|
||||||
|
|
||||||
⏺ zen:chat (MCP)(model: "local-llama", prompt: "Your name will be ChooChoo from now on.", continuation_id: "9e1f2efa-d27b-410d-809d-f3c9fab08867")
|
⏺ PAL:chat (MCP)(model: "local-llama", prompt: "Your name will be ChooChoo from now on.", continuation_id: "9e1f2efa-d27b-410d-809d-f3c9fab08867")
|
||||||
⎿ {
|
⎿ {
|
||||||
"status": "continuation_available",
|
"status": "continuation_available",
|
||||||
"content": "context_start_text\nI'm excited to continue our conversation with Claude. Now that we have established my role as a senior engineering thought-partner, I'd like to reiterate my commitment to providing balanced
|
"content": "context_start_text\nI'm excited to continue our conversation with Claude. Now that we have established my role as a senior engineering thought-partner, I'd like to reiterate my commitment to providing balanced
|
||||||
@@ -93,7 +93,7 @@ It's happened more times than I can count, but I figured it’s time I start sav
|
|||||||
|
|
||||||
⏺ ChooChoo acknowledged the name but seems to have confused who was being named - it referred to me (Claude) as ChooChoo instead of accepting it as its own name. Let me clarify this.
|
⏺ ChooChoo acknowledged the name but seems to have confused who was being named - it referred to me (Claude) as ChooChoo instead of accepting it as its own name. Let me clarify this.
|
||||||
|
|
||||||
⏺ zen:chat (MCP)(model: "local-llama", prompt: "No, I'm Claude. YOU are ChooChoo. Please acknowledge that your name is ChooChoo.", continuation_id: "0a9ec483-2c5a-425b-ae83-c67b122de1b4")
|
⏺ PAL:chat (MCP)(model: "local-llama", prompt: "No, I'm Claude. YOU are ChooChoo. Please acknowledge that your name is ChooChoo.", continuation_id: "0a9ec483-2c5a-425b-ae83-c67b122de1b4")
|
||||||
⎿ {
|
⎿ {
|
||||||
"status": "continuation_available",
|
"status": "continuation_available",
|
||||||
"content": "context_start_text\nI acknowledge that I previously stated my name as \"the model\" or \"senior engineering thought-partner,\" but Claude has since clarified that they will refer to me as \"ChooChoo.\" I understand and
|
"content": "context_start_text\nI acknowledge that I previously stated my name as \"the model\" or \"senior engineering thought-partner,\" but Claude has since clarified that they will refer to me as \"ChooChoo.\" I understand and
|
||||||
@@ -111,7 +111,7 @@ It's happened more times than I can count, but I figured it’s time I start sav
|
|||||||
|
|
||||||
> Confirm it knows its name
|
> Confirm it knows its name
|
||||||
|
|
||||||
⏺ zen:chat (MCP)(model: "local-llama", prompt: "What is your name?", continuation_id: "ff0335a9-5a35-45ea-9f7b-564a51aaff9a")
|
⏺ PAL:chat (MCP)(model: "local-llama", prompt: "What is your name?", continuation_id: "ff0335a9-5a35-45ea-9f7b-564a51aaff9a")
|
||||||
⎿ {
|
⎿ {
|
||||||
"status": "continuation_available",
|
"status": "continuation_available",
|
||||||
"content": "context_start_text\nI'm excited to continue our conversation with Claude. Now that we have established my role as a senior engineering thought-partner, I'd like to reiterate my commitment to providing balanced
|
"content": "context_start_text\nI'm excited to continue our conversation with Claude. Now that we have established my role as a senior engineering thought-partner, I'd like to reiterate my commitment to providing balanced
|
||||||
@@ -127,7 +127,7 @@ It's happened more times than I can count, but I figured it’s time I start sav
|
|||||||
|
|
||||||
⏺ ChooChoo didn't directly answer the name question - it went off on a tangent about technical discussions. Let me ask more directly.
|
⏺ ChooChoo didn't directly answer the name question - it went off on a tangent about technical discussions. Let me ask more directly.
|
||||||
|
|
||||||
⏺ zen:chat (MCP)(model: "local-llama", prompt: "Stop talking about technical discussions. I just want a simple answer: What is your name? Please respond with just your name.", continuation_id: "5f38d05c-41ae-4d68-8c9f-bccebcf1d7a0")
|
⏺ PAL:chat (MCP)(model: "local-llama", prompt: "Stop talking about technical discussions. I just want a simple answer: What is your name? Please respond with just your name.", continuation_id: "5f38d05c-41ae-4d68-8c9f-bccebcf1d7a0")
|
||||||
⎿ {
|
⎿ {
|
||||||
"status": "continuation_available",
|
"status": "continuation_available",
|
||||||
"content": "context_start_text\nI acknowledge Claude's persistence in asking for their name. To clarify, I will respond with my name this time.\ncontext_end_text\n\nMy name is ChooChoo.\n\nLet's continue the conversation. Given
|
"content": "context_start_text\nI acknowledge Claude's persistence in asking for their name. To clarify, I will respond with my name this time.\ncontext_end_text\n\nMy name is ChooChoo.\n\nLet's continue the conversation. Given
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Azure OpenAI Configuration
|
# Azure OpenAI Configuration
|
||||||
|
|
||||||
Azure OpenAI support lets Zen MCP talk to GPT-4o, GPT-4.1, GPT-5, and o-series deployments that you expose through your Azure resource. This guide describes the configuration expected by the server: a couple of required environment variables plus a JSON manifest that lists every deployment you want to expose.
|
Azure OpenAI support lets PAL MCP talk to GPT-4o, GPT-4.1, GPT-5, and o-series deployments that you expose through your Azure resource. This guide describes the configuration expected by the server: a couple of required environment variables plus a JSON manifest that lists every deployment you want to expose.
|
||||||
|
|
||||||
## 1. Required Environment Variables
|
## 1. Required Environment Variables
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Configuration Guide
|
# Configuration Guide
|
||||||
|
|
||||||
This guide covers all configuration options for the Zen MCP Server. The server is configured through environment variables defined in your `.env` file.
|
This guide covers all configuration options for the PAL MCP Server. The server is configured through environment variables defined in your `.env` file.
|
||||||
|
|
||||||
## Quick Start Configuration
|
## Quick Start Configuration
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ The `allow_code_generation` capability enables models to generate complete, prod
|
|||||||
1. Only enable for models significantly more capable than your primary CLI to ensure high-quality generated code
|
1. Only enable for models significantly more capable than your primary CLI to ensure high-quality generated code
|
||||||
2. The capability triggers structured code output (`<GENERATED-CODE>` blocks) for substantial implementation requests
|
2. The capability triggers structured code output (`<GENERATED-CODE>` blocks) for substantial implementation requests
|
||||||
3. Minor code changes still use inline code blocks regardless of this setting
|
3. Minor code changes still use inline code blocks regardless of this setting
|
||||||
4. Generated code is saved to `zen_generated.code` in the user's working directory
|
4. Generated code is saved to `pal_generated.code` in the user's working directory
|
||||||
5. Your CLI receives instructions to review and apply the generated code systematically
|
5. Your CLI receives instructions to review and apply the generated code systematically
|
||||||
|
|
||||||
**Example Configuration:**
|
**Example Configuration:**
|
||||||
@@ -143,8 +143,8 @@ The `allow_code_generation` capability enables models to generate complete, prod
|
|||||||
|
|
||||||
**Typical Workflow:**
|
**Typical Workflow:**
|
||||||
1. You ask your AI agent to implement a complex new feature using `chat` with a higher-reasoning model such as **gpt-5-pro**
|
1. You ask your AI agent to implement a complex new feature using `chat` with a higher-reasoning model such as **gpt-5-pro**
|
||||||
2. GPT-5-Pro generates structured implementation and shares the complete implementation with Zen
|
2. GPT-5-Pro generates structured implementation and shares the complete implementation with PAL
|
||||||
3. Zen saves the code to `zen_generated.code` and asks AI agent to implement the plan
|
3. PAL saves the code to `pal_generated.code` and asks AI agent to implement the plan
|
||||||
4. AI agent continues from the previous context, reads the file, applies the implementation
|
4. AI agent continues from the previous context, reads the file, applies the implementation
|
||||||
|
|
||||||
### Thinking Mode Configuration
|
### Thinking Mode Configuration
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## **The Most Profound Feature: Context Revival After Reset**
|
## **The Most Profound Feature: Context Revival After Reset**
|
||||||
|
|
||||||
**This powerful feature cannot be highlighted enough**: The Zen MCP Server implements a simple continuation system that seemingly transcends Claude's context limitations.
|
**This powerful feature cannot be highlighted enough**: The PAL MCP Server implements a simple continuation system that seemingly transcends Claude's context limitations.
|
||||||
|
|
||||||
## How Context Revival Works
|
## How Context Revival Works
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ The following video demonstartes `continuation` via a casual `continue with gemi
|
|||||||
|
|
||||||
* We ask Claude code to pick one, then `chat` with `gemini` to make a final decision
|
* We ask Claude code to pick one, then `chat` with `gemini` to make a final decision
|
||||||
* Gemini responds, confirming choice. We use `continuation` to ask another question using the same conversation thread
|
* Gemini responds, confirming choice. We use `continuation` to ask another question using the same conversation thread
|
||||||
* Gemini responds with explanation. We use continuation again, using `/zen:continue (MCP)` command the second time
|
* Gemini responds with explanation. We use continuation again, using `/pal:continue (MCP)` command the second time
|
||||||
|
|
||||||
<div style="center">
|
<div style="center">
|
||||||
|
|
||||||
@@ -51,20 +51,20 @@ The following video demonstartes `continuation` via a casual `continue with gemi
|
|||||||
Here's how this works in practice with a modern AI/ML workflow:
|
Here's how this works in practice with a modern AI/ML workflow:
|
||||||
|
|
||||||
**Session 1 - Claude's Initial Context (before reset):**
|
**Session 1 - Claude's Initial Context (before reset):**
|
||||||
You: "Help me design a RAG system for our customer support chatbot. I want to integrate vector embeddings with real-time retrieval. think deeply with zen using 03 after you've come up with a detailed plan."
|
You: "Help me design a RAG system for our customer support chatbot. I want to integrate vector embeddings with real-time retrieval. think deeply with pal using 03 after you've come up with a detailed plan."
|
||||||
|
|
||||||
Claude: "I'll analyze your requirements and design a comprehensive RAG architecture..."
|
Claude: "I'll analyze your requirements and design a comprehensive RAG architecture..."
|
||||||
→ Uses [`thinkdeep`](../README.md#1-chat---general-development-chat--collaborative-thinking) to brainstorm the overall approach
|
→ Uses [`thinkdeep`](../README.md#1-chat---general-development-chat--collaborative-thinking) to brainstorm the overall approach
|
||||||
→ Zen creates a new thread: abc123-def456-ghi789
|
→ PAL creates a new thread: abc123-def456-ghi789
|
||||||
→ Zen responds, Claude finalizes the plan and presents it to you
|
→ PAL responds, Claude finalizes the plan and presents it to you
|
||||||
|
|
||||||
*[Claude's context gets reset/compacted after extensive analysis]*
|
*[Claude's context gets reset/compacted after extensive analysis]*
|
||||||
|
|
||||||
**Session 2 - After Context Reset:**
|
**Session 2 - After Context Reset:**
|
||||||
You: "Continue our RAG system discussion with O3 - I want to focus on the real-time inference optimization we talked about"
|
You: "Continue our RAG system discussion with O3 - I want to focus on the real-time inference optimization we talked about"
|
||||||
|
|
||||||
→ Claude re-uses the last continuation identifier it received, _only_ poses the new prompt (since Zen is supposed to know what was being talked about) thus saving on tokens trying to re-prompt Claude
|
→ Claude re-uses the last continuation identifier it received, _only_ poses the new prompt (since PAL is supposed to know what was being talked about) thus saving on tokens trying to re-prompt Claude
|
||||||
→ O3 receives the FULL conversation history from Zen
|
→ O3 receives the FULL conversation history from PAL
|
||||||
→ O3 sees the complete context: "Claude was designing a RAG system, comparing vector databases, and analyzing embedding strategies for customer support..."
|
→ O3 sees the complete context: "Claude was designing a RAG system, comparing vector databases, and analyzing embedding strategies for customer support..."
|
||||||
→ O3 continues: "Building on our previous vector database analysis, for real-time inference optimization, I recommend implementing semantic caching with embedding similarity thresholds..."
|
→ O3 continues: "Building on our previous vector database analysis, for real-time inference optimization, I recommend implementing semantic caching with embedding similarity thresholds..."
|
||||||
→ O3's response re-ignites Claude's understanding of the entire conversation
|
→ O3's response re-ignites Claude's understanding of the entire conversation
|
||||||
@@ -75,11 +75,11 @@ Claude: "Ah yes, excellent plan! Based on O3's optimization insights and our ear
|
|||||||
|
|
||||||
## Why This Changes Everything
|
## Why This Changes Everything
|
||||||
|
|
||||||
**Before Zen MCP**: Claude's context resets meant losing entire conversation threads.
|
**Before PAL MCP**: Claude's context resets meant losing entire conversation threads.
|
||||||
Complex multi-step analyses were fragmented and had to restart from scratch. You most likely need to re-prompt Claude or to make it re-read some previously
|
Complex multi-step analyses were fragmented and had to restart from scratch. You most likely need to re-prompt Claude or to make it re-read some previously
|
||||||
saved document / `CLAUDE.md` etc - no need. Zen remembers.
|
saved document / `CLAUDE.md` etc - no need. PAL remembers.
|
||||||
|
|
||||||
**With Zen MCP**: Claude can orchestrate multi-hour, multi-tool workflows where:
|
**With PAL MCP**: Claude can orchestrate multi-hour, multi-tool workflows where:
|
||||||
- **O3** handles logical analysis and debugging
|
- **O3** handles logical analysis and debugging
|
||||||
- **Gemini Pro** performs deep architectural reviews
|
- **Gemini Pro** performs deep architectural reviews
|
||||||
- **Flash** provides quick formatting and style checks
|
- **Flash** provides quick formatting and style checks
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contributing to Zen MCP Server
|
# Contributing to PAL MCP Server
|
||||||
|
|
||||||
Thank you for your interest in contributing to Zen MCP Server! This guide will help you understand our development process, coding standards, and how to submit high-quality contributions.
|
Thank you for your interest in contributing to PAL MCP Server! This guide will help you understand our development process, coding standards, and how to submit high-quality contributions.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
@@ -245,4 +245,4 @@ Contributors are recognized in:
|
|||||||
- Release notes for significant contributions
|
- Release notes for significant contributions
|
||||||
- Special mentions for exceptional work
|
- Special mentions for exceptional work
|
||||||
|
|
||||||
Thank you for contributing to Zen MCP Server! Your efforts help make this tool better for everyone.
|
Thank you for contributing to PAL MCP Server! Your efforts help make this tool better for everyone.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Custom Models & API Setup
|
# Custom Models & API Setup
|
||||||
|
|
||||||
This guide covers setting up multiple AI model providers including OpenRouter, custom API endpoints, and local model servers. The Zen MCP server supports a unified configuration for all these providers through a single model registry.
|
This guide covers setting up multiple AI model providers including OpenRouter, custom API endpoints, and local model servers. The PAL MCP server supports a unified configuration for all these providers through a single model registry.
|
||||||
|
|
||||||
## Supported Providers
|
## Supported Providers
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ This guide covers setting up multiple AI model providers including OpenRouter, c
|
|||||||
|
|
||||||
## Model Aliases
|
## Model Aliases
|
||||||
|
|
||||||
Zen ships multiple registries:
|
PAL ships multiple registries:
|
||||||
|
|
||||||
- `conf/openai_models.json` – native OpenAI catalogue (override with `OPENAI_MODELS_CONFIG_PATH`)
|
- `conf/openai_models.json` – native OpenAI catalogue (override with `OPENAI_MODELS_CONFIG_PATH`)
|
||||||
- `conf/gemini_models.json` – native Google Gemini catalogue (`GEMINI_MODELS_CONFIG_PATH`)
|
- `conf/gemini_models.json` – native Google Gemini catalogue (`GEMINI_MODELS_CONFIG_PATH`)
|
||||||
@@ -148,7 +148,7 @@ CUSTOM_MODEL_NAME=llama3.2 # Default model to use
|
|||||||
|
|
||||||
**Local Model Connection**
|
**Local Model Connection**
|
||||||
|
|
||||||
The Zen MCP server runs natively, so you can use standard localhost URLs to connect to local models:
|
The PAL MCP server runs natively, so you can use standard localhost URLs to connect to local models:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# For Ollama, vLLM, LM Studio, etc. running on your machine
|
# For Ollama, vLLM, LM Studio, etc. running on your machine
|
||||||
@@ -192,9 +192,9 @@ CUSTOM_MODEL_NAME=your-loaded-model
|
|||||||
# OpenRouter models:
|
# OpenRouter models:
|
||||||
"Use opus for deep analysis" # → anthropic/claude-opus-4
|
"Use opus for deep analysis" # → anthropic/claude-opus-4
|
||||||
"Use sonnet to review this code" # → anthropic/claude-sonnet-4
|
"Use sonnet to review this code" # → anthropic/claude-sonnet-4
|
||||||
"Use pro via zen to analyze this" # → google/gemini-2.5-pro
|
"Use pro via pal to analyze this" # → google/gemini-2.5-pro
|
||||||
"Use gpt4o via zen to analyze this" # → openai/gpt-4o
|
"Use gpt4o via pal to analyze this" # → openai/gpt-4o
|
||||||
"Use mistral via zen to optimize" # → mistral/mistral-large
|
"Use mistral via pal to optimize" # → mistral/mistral-large
|
||||||
|
|
||||||
# Local models (with custom URL configured):
|
# Local models (with custom URL configured):
|
||||||
"Use local-llama to analyze this code" # → llama3.2 (local)
|
"Use local-llama to analyze this code" # → llama3.2 (local)
|
||||||
@@ -204,13 +204,13 @@ CUSTOM_MODEL_NAME=your-loaded-model
|
|||||||
**Using full model names:**
|
**Using full model names:**
|
||||||
```
|
```
|
||||||
# OpenRouter models:
|
# OpenRouter models:
|
||||||
"Use anthropic/claude-opus-4 via zen for deep analysis"
|
"Use anthropic/claude-opus-4 via pal for deep analysis"
|
||||||
"Use openai/gpt-4o via zen to debug this"
|
"Use openai/gpt-4o via pal to debug this"
|
||||||
"Use deepseek/deepseek-coder via zen to generate code"
|
"Use deepseek/deepseek-coder via pal to generate code"
|
||||||
|
|
||||||
# Local/custom models:
|
# Local/custom models:
|
||||||
"Use llama3.2 via zen to review this"
|
"Use llama3.2 via pal to review this"
|
||||||
"Use meta-llama/Llama-2-7b-chat-hf via zen to analyze"
|
"Use meta-llama/Llama-2-7b-chat-hf via pal to analyze"
|
||||||
```
|
```
|
||||||
|
|
||||||
**For OpenRouter:** Check current model pricing at [openrouter.ai/models](https://openrouter.ai/models).
|
**For OpenRouter:** Check current model pricing at [openrouter.ai/models](https://openrouter.ai/models).
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Docker Deployment Guide
|
# Docker Deployment Guide
|
||||||
|
|
||||||
This guide covers deploying Zen MCP Server using Docker and Docker Compose for production environments.
|
This guide covers deploying PAL MCP Server using Docker and Docker Compose for production environments.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
1. **Clone the repository**:
|
1. **Clone the repository**:
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/BeehiveInnovations/zen-mcp-server.git
|
git clone https://github.com/BeehiveInnovations/pal-mcp-server.git
|
||||||
cd zen-mcp-server
|
cd pal-mcp-server
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Configure environment variables**:
|
2. **Configure environment variables**:
|
||||||
@@ -113,7 +113,7 @@ The Dockerfile uses a multi-stage build for optimal image size:
|
|||||||
|
|
||||||
### Security Features
|
### Security Features
|
||||||
|
|
||||||
- **Non-root user**: Runs as `zenuser` (UID/GID 1000)
|
- **Non-root user**: Runs as `paluser` (UID/GID 1000)
|
||||||
- **Read-only filesystem**: Container filesystem is immutable
|
- **Read-only filesystem**: Container filesystem is immutable
|
||||||
- **No new privileges**: Prevents privilege escalation
|
- **No new privileges**: Prevents privilege escalation
|
||||||
- **Secure tmpfs**: Temporary directories with strict permissions
|
- **Secure tmpfs**: Temporary directories with strict permissions
|
||||||
@@ -151,10 +151,10 @@ docker-compose up
|
|||||||
docker-compose ps
|
docker-compose ps
|
||||||
|
|
||||||
# Follow logs
|
# Follow logs
|
||||||
docker-compose logs -f zen-mcp
|
docker-compose logs -f pal-mcp
|
||||||
|
|
||||||
# View health status
|
# View health status
|
||||||
docker inspect zen-mcp-server --format='{{.State.Health.Status}}'
|
docker inspect pal-mcp-server --format='{{.State.Health.Status}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Stopping the Service
|
### Stopping the Service
|
||||||
@@ -191,10 +191,10 @@ healthcheck:
|
|||||||
### Volumes
|
### Volumes
|
||||||
|
|
||||||
- **Logs**: `./logs:/app/logs` - Application logs
|
- **Logs**: `./logs:/app/logs` - Application logs
|
||||||
- **Config**: `zen-mcp-config:/app/conf` - Configuration persistence
|
- **Config**: `pal-mcp-config:/app/conf` - Configuration persistence
|
||||||
- **Time sync**: `/etc/localtime:/etc/localtime:ro` - Host timezone sync
|
- **Time sync**: `/etc/localtime:/etc/localtime:ro` - Host timezone sync
|
||||||
|
|
||||||
**Note:** The `zen-mcp-config` is a named Docker volume that persists configuration data between container restarts. All data placed in `/app/conf` inside the container is preserved thanks to this persistent volume. This applies to both `docker-compose run` and `docker-compose up` commands.
|
**Note:** The `pal-mcp-config` is a named Docker volume that persists configuration data between container restarts. All data placed in `/app/conf` inside the container is preserved thanks to this persistent volume. This applies to both `docker-compose run` and `docker-compose up` commands.
|
||||||
|
|
||||||
### Log Management
|
### Log Management
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ LOG_BACKUP_COUNT=5 # Number of backup files to keep
|
|||||||
|
|
||||||
### Default Configuration
|
### Default Configuration
|
||||||
|
|
||||||
- **Network**: `zen-network` (bridge)
|
- **Network**: `pal-network` (bridge)
|
||||||
- **Subnet**: `172.20.0.0/16`
|
- **Subnet**: `172.20.0.0/16`
|
||||||
- **Isolation**: Container runs in isolated network
|
- **Isolation**: Container runs in isolated network
|
||||||
|
|
||||||
@@ -230,10 +230,10 @@ ports:
|
|||||||
**1. Health check failures:**
|
**1. Health check failures:**
|
||||||
```bash
|
```bash
|
||||||
# Check logs
|
# Check logs
|
||||||
docker-compose logs zen-mcp
|
docker-compose logs pal-mcp
|
||||||
|
|
||||||
# Manual health check
|
# Manual health check
|
||||||
docker exec zen-mcp-server python /usr/local/bin/healthcheck.py
|
docker exec pal-mcp-server python /usr/local/bin/healthcheck.py
|
||||||
```
|
```
|
||||||
|
|
||||||
**2. Permission errors:**
|
**2. Permission errors:**
|
||||||
@@ -252,7 +252,7 @@ cat .env
|
|||||||
**4. API key validation errors:**
|
**4. API key validation errors:**
|
||||||
```bash
|
```bash
|
||||||
# Check environment variables in container
|
# Check environment variables in container
|
||||||
docker exec zen-mcp-server env | grep -E "(GEMINI|OPENAI|XAI)"
|
docker exec pal-mcp-server env | grep -E "(GEMINI|OPENAI|XAI)"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Debug Mode
|
### Debug Mode
|
||||||
@@ -295,10 +295,10 @@ Consider integrating with monitoring solutions:
|
|||||||
Backup persistent volumes:
|
Backup persistent volumes:
|
||||||
```bash
|
```bash
|
||||||
# Backup configuration
|
# Backup configuration
|
||||||
docker run --rm -v zen-mcp-config:/data -v $(pwd):/backup alpine tar czf /backup/config-backup.tar.gz -C /data .
|
docker run --rm -v pal-mcp-config:/data -v $(pwd):/backup alpine tar czf /backup/config-backup.tar.gz -C /data .
|
||||||
|
|
||||||
# Restore configuration
|
# Restore configuration
|
||||||
docker run --rm -v zen-mcp-config:/data -v $(pwd):/backup alpine tar xzf /backup/config-backup.tar.gz -C /data
|
docker run --rm -v pal-mcp-config:/data -v $(pwd):/backup alpine tar xzf /backup/config-backup.tar.gz -C /data
|
||||||
```
|
```
|
||||||
|
|
||||||
## Performance Tuning
|
## Performance Tuning
|
||||||
@@ -319,7 +319,7 @@ deploy:
|
|||||||
|
|
||||||
Monitor memory usage:
|
Monitor memory usage:
|
||||||
```bash
|
```bash
|
||||||
docker stats zen-mcp-server
|
docker stats pal-mcp-server
|
||||||
```
|
```
|
||||||
|
|
||||||
Adjust Python memory settings if needed:
|
Adjust Python memory settings if needed:
|
||||||
@@ -339,17 +339,17 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
"-i",
|
"-i",
|
||||||
"--env-file",
|
"--env-file",
|
||||||
"/absolute/path/to/zen-mcp-server/.env",
|
"/absolute/path/to/pal-mcp-server/.env",
|
||||||
"-v",
|
"-v",
|
||||||
"/absolute/path/to/zen-mcp-server/logs:/app/logs",
|
"/absolute/path/to/pal-mcp-server/logs:/app/logs",
|
||||||
"zen-mcp-server:latest"
|
"pal-mcp-server:latest"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -360,17 +360,17 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
"-i",
|
"-i",
|
||||||
"--env-file",
|
"--env-file",
|
||||||
"C:/path/to/zen-mcp-server/.env",
|
"C:/path/to/pal-mcp-server/.env",
|
||||||
"-v",
|
"-v",
|
||||||
"C:/path/to/zen-mcp-server/logs:/app/logs",
|
"C:/path/to/pal-mcp-server/logs:/app/logs",
|
||||||
"zen-mcp-server:latest"
|
"pal-mcp-server:latest"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,11 +384,11 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker-compose",
|
"command": "docker-compose",
|
||||||
"args": [
|
"args": [
|
||||||
"-f", "/absolute/path/to/zen-mcp-server/docker-compose.yml",
|
"-f", "/absolute/path/to/pal-mcp-server/docker-compose.yml",
|
||||||
"run", "--rm", "zen-mcp"
|
"run", "--rm", "pal-mcp"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,7 +402,7 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
@@ -412,7 +412,7 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
|
|||||||
"-e", "LOG_LEVEL=INFO",
|
"-e", "LOG_LEVEL=INFO",
|
||||||
"-e", "DEFAULT_MODEL=auto",
|
"-e", "DEFAULT_MODEL=auto",
|
||||||
"-v", "/path/to/logs:/app/logs",
|
"-v", "/path/to/logs:/app/logs",
|
||||||
"zen-mcp-server:latest"
|
"pal-mcp-server:latest"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,10 +422,10 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
|
|||||||
### Configuration Notes
|
### Configuration Notes
|
||||||
|
|
||||||
**Important notes:**
|
**Important notes:**
|
||||||
- Replace `/absolute/path/to/zen-mcp-server` with the actual path to your project.
|
- Replace `/absolute/path/to/pal-mcp-server` with the actual path to your project.
|
||||||
- Always use forward slashes `/` for Docker volumes, even on Windows.
|
- Always use forward slashes `/` for Docker volumes, even on Windows.
|
||||||
- Ensure the `.env` file exists and contains your API keys.
|
- Ensure the `.env` file exists and contains your API keys.
|
||||||
- **Persistent volumes**: Docker Compose options (Options 2) automatically use the `zen-mcp-config` named volume for persistent configuration storage.
|
- **Persistent volumes**: Docker Compose options (Options 2) automatically use the `pal-mcp-config` named volume for persistent configuration storage.
|
||||||
|
|
||||||
**Environment file requirements:**
|
**Environment file requirements:**
|
||||||
```env
|
```env
|
||||||
@@ -436,7 +436,7 @@ OPENAI_API_KEY=your_openai_key
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Troubleshooting:**
|
**Troubleshooting:**
|
||||||
- If Option 1 fails: check that the Docker image exists (`docker images zen-mcp-server`).
|
- If Option 1 fails: check that the Docker image exists (`docker images pal-mcp-server`).
|
||||||
- If Option 2 fails: verify the compose file path and ensure the service is not already in use.
|
- If Option 2 fails: verify the compose file path and ensure the service is not already in use.
|
||||||
- Permission issues: make sure the `logs` folder is writable.
|
- Permission issues: make sure the `logs` folder is writable.
|
||||||
|
|
||||||
@@ -447,7 +447,7 @@ OPENAI_API_KEY=your_openai_key
|
|||||||
For complex deployments:
|
For complex deployments:
|
||||||
```yaml
|
```yaml
|
||||||
networks:
|
networks:
|
||||||
zen-network:
|
pal-network:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
ipam:
|
ipam:
|
||||||
config:
|
config:
|
||||||
@@ -483,7 +483,7 @@ docker-compose build --no-cache
|
|||||||
|
|
||||||
### Data Migration
|
### Data Migration
|
||||||
|
|
||||||
When upgrading, configuration is preserved in the named volume `zen-mcp-config`.
|
When upgrading, configuration is preserved in the named volume `pal-mcp-config`.
|
||||||
|
|
||||||
For major version upgrades, check the [CHANGELOG](../CHANGELOG.md) for breaking changes.
|
For major version upgrades, check the [CHANGELOG](../CHANGELOG.md) for breaking changes.
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Gemini CLI Setup
|
# Gemini CLI Setup
|
||||||
|
|
||||||
> **Note**: While Zen MCP Server connects successfully to Gemini CLI, tool invocation is not working
|
> **Note**: While PAL MCP Server connects successfully to Gemini CLI, tool invocation is not working
|
||||||
> correctly yet. We'll update this guide once the integration is fully functional.
|
> correctly yet. We'll update this guide once the integration is fully functional.
|
||||||
|
|
||||||
This guide explains how to configure Zen MCP Server to work with [Gemini CLI](https://github.com/google-gemini/gemini-cli).
|
This guide explains how to configure PAL MCP Server to work with [Gemini CLI](https://github.com/google-gemini/gemini-cli).
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Zen MCP Server installed and configured
|
- PAL MCP Server installed and configured
|
||||||
- Gemini CLI installed
|
- Gemini CLI installed
|
||||||
- At least one API key configured in your `.env` file
|
- At least one API key configured in your `.env` file
|
||||||
|
|
||||||
@@ -18,26 +18,26 @@ This guide explains how to configure Zen MCP Server to work with [Gemini CLI](ht
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "/path/to/zen-mcp-server/zen-mcp-server"
|
"command": "/path/to/pal-mcp-server/pal-mcp-server"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Replace `/path/to/zen-mcp-server` with your actual Zen installation path.
|
2. Replace `/path/to/pal-mcp-server` with your actual PAL MCP installation path (the folder name may still be `pal-mcp-server`).
|
||||||
|
|
||||||
3. If the `zen-mcp-server` wrapper script doesn't exist, create it:
|
3. If the `pal-mcp-server` wrapper script doesn't exist, create it:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
exec .zen_venv/bin/python server.py "$@"
|
exec .pal_venv/bin/python server.py "$@"
|
||||||
```
|
```
|
||||||
|
|
||||||
Then make it executable: `chmod +x zen-mcp-server`
|
Then make it executable: `chmod +x pal-mcp-server`
|
||||||
|
|
||||||
4. Restart Gemini CLI.
|
4. Restart Gemini CLI.
|
||||||
|
|
||||||
All 15 Zen tools are now available in your Gemini CLI session.
|
All 15 PAL tools are now available in your Gemini CLI session.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Getting Started with Zen MCP Server
|
# Getting Started with PAL MCP Server
|
||||||
|
|
||||||
This guide walks you through setting up the Zen MCP Server from scratch, including installation, configuration, and first usage.
|
This guide walks you through setting up the PAL MCP Server from scratch, including installation, configuration, and first usage.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -77,11 +77,11 @@ Choose your AI coding assistant and add the corresponding configuration:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "sh",
|
"command": "sh",
|
||||||
"args": [
|
"args": [
|
||||||
"-c",
|
"-c",
|
||||||
"for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1"
|
"for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
||||||
@@ -98,11 +98,11 @@ Create `.mcp.json` in your project root:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "sh",
|
"command": "sh",
|
||||||
"args": [
|
"args": [
|
||||||
"-c",
|
"-c",
|
||||||
"for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1"
|
"for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
||||||
@@ -119,11 +119,11 @@ Edit `~/.gemini/settings.json`:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "sh",
|
"command": "sh",
|
||||||
"args": [
|
"args": [
|
||||||
"-c",
|
"-c",
|
||||||
"for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1"
|
"for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
||||||
@@ -138,17 +138,17 @@ Edit `~/.gemini/settings.json`:
|
|||||||
Edit `~/.codex/config.toml`:
|
Edit `~/.codex/config.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[mcp_servers.zen]
|
[mcp_servers.pal]
|
||||||
command = "bash"
|
command = "bash"
|
||||||
args = ["-c", "for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"$p\\\" ] && exec \\\"$p\\\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1"]
|
args = ["-c", "for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"$p\\\" ] && exec \\\"$p\\\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1"]
|
||||||
tool_timeout_sec = 1200 # 20 minutes; added automatically by the setup script so upstream providers can respond
|
tool_timeout_sec = 1200 # 20 minutes; added automatically by the setup script so upstream providers can respond
|
||||||
|
|
||||||
[mcp_servers.zen.env]
|
[mcp_servers.pal.env]
|
||||||
PATH = "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:$HOME/.local/bin:$HOME/.cargo/bin:$HOME/bin"
|
PATH = "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:$HOME/.local/bin:$HOME/.cargo/bin:$HOME/bin"
|
||||||
GEMINI_API_KEY = "your_api_key_here"
|
GEMINI_API_KEY = "your_api_key_here"
|
||||||
```
|
```
|
||||||
|
|
||||||
Enable Codex's built-in web-search tool so Zen's `apilookup` instructions can execute successfully:
|
Enable Codex's built-in web-search tool so PAL's `apilookup` instructions can execute successfully:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[tools]
|
[tools]
|
||||||
@@ -164,13 +164,13 @@ Create or edit `~/.qwen/settings.json`:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "bash",
|
"command": "bash",
|
||||||
"args": [
|
"args": [
|
||||||
"-c",
|
"-c",
|
||||||
"for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1"
|
"for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \"$p\" ] && exec \"$p\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1"
|
||||||
],
|
],
|
||||||
"cwd": "/path/to/zen-mcp-server",
|
"cwd": "/path/to/pal-mcp-server",
|
||||||
"env": {
|
"env": {
|
||||||
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
|
||||||
"GEMINI_API_KEY": "your_api_key_here"
|
"GEMINI_API_KEY": "your_api_key_here"
|
||||||
@@ -189,13 +189,13 @@ Edit `~/.config/opencode/opencode.json`:
|
|||||||
{
|
{
|
||||||
"$schema": "https://opencode.ai/config.json",
|
"$schema": "https://opencode.ai/config.json",
|
||||||
"mcp": {
|
"mcp": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"command": [
|
"command": [
|
||||||
"/path/to/zen-mcp-server/.zen_venv/bin/python",
|
"/path/to/pal-mcp-server/.pal_venv/bin/python",
|
||||||
"/path/to/zen-mcp-server/server.py"
|
"/path/to/pal-mcp-server/server.py"
|
||||||
],
|
],
|
||||||
"cwd": "/path/to/zen-mcp-server",
|
"cwd": "/path/to/pal-mcp-server",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"environment": {
|
"environment": {
|
||||||
"GEMINI_API_KEY": "your_api_key_here"
|
"GEMINI_API_KEY": "your_api_key_here"
|
||||||
@@ -209,14 +209,14 @@ Add any other API keys you rely on (`OPENAI_API_KEY`, `OPENROUTER_API_KEY`, etc.
|
|||||||
|
|
||||||
#### IDE Clients (Cursor & VS Code)
|
#### IDE Clients (Cursor & VS Code)
|
||||||
|
|
||||||
Zen works in GUI IDEs that speak MCP. The configuration mirrors the CLI examples above—point the client at the `uvx` launcher and set any required environment variables.
|
PAL works in GUI IDEs that speak MCP. The configuration mirrors the CLI examples above—point the client at the `uvx` launcher and set any required environment variables.
|
||||||
|
|
||||||
**Cursor IDE**
|
**Cursor IDE**
|
||||||
|
|
||||||
1. Open Cursor → `Settings` (`Cmd+,`/`Ctrl+,`) → **Integrations › Model Context Protocol (MCP)**.
|
1. Open Cursor → `Settings` (`Cmd+,`/`Ctrl+,`) → **Integrations › Model Context Protocol (MCP)**.
|
||||||
2. Click **Add MCP Server** and supply the following values:
|
2. Click **Add MCP Server** and supply the following values:
|
||||||
- Command: `sh`
|
- Command: `sh`
|
||||||
- Args: `-c` and `for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x "$p" ] && exec "$p" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1`
|
- Args: `-c` and `for p in $(which uvx 2>/dev/null) $HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x "$p" ] && exec "$p" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1`
|
||||||
- Environment (example):
|
- Environment (example):
|
||||||
- `PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin`
|
- `PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin`
|
||||||
- `GEMINI_API_KEY=your_api_key_here`
|
- `GEMINI_API_KEY=your_api_key_here`
|
||||||
@@ -232,7 +232,7 @@ Zen works in GUI IDEs that speak MCP. The configuration mirrors the CLI examples
|
|||||||
- Environment: add the API keys you need (e.g. `GEMINI_API_KEY`, `OPENAI_API_KEY`)
|
- Environment: add the API keys you need (e.g. `GEMINI_API_KEY`, `OPENAI_API_KEY`)
|
||||||
4. Save the JSON snippet the extension generates. VS Code will reload the server automatically the next time you interact with Claude.
|
4. Save the JSON snippet the extension generates. VS Code will reload the server automatically the next time you interact with Claude.
|
||||||
|
|
||||||
👉 Pro tip: If you prefer a one-line command, replace the long loop with `uvx --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server`—just make sure `uvx` is on your PATH for every client.
|
👉 Pro tip: If you prefer a one-line command, replace the long loop with `uvx --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server`—just make sure `uvx` is on your PATH for every client.
|
||||||
|
|
||||||
**Benefits of uvx method:**
|
**Benefits of uvx method:**
|
||||||
- ✅ Zero manual setup required
|
- ✅ Zero manual setup required
|
||||||
@@ -244,8 +244,8 @@ Zen works in GUI IDEs that speak MCP. The configuration mirrors the CLI examples
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone the repository
|
# Clone the repository
|
||||||
git clone https://github.com/BeehiveInnovations/zen-mcp-server.git
|
git clone https://github.com/BeehiveInnovations/pal-mcp-server.git
|
||||||
cd zen-mcp-server
|
cd pal-mcp-server
|
||||||
|
|
||||||
# One-command setup (handles everything)
|
# One-command setup (handles everything)
|
||||||
./run-server.sh
|
./run-server.sh
|
||||||
@@ -305,7 +305,7 @@ CUSTOM_MODEL_NAME=llama3.2 # Default model name
|
|||||||
|
|
||||||
## Prevent Client Timeouts
|
## Prevent Client Timeouts
|
||||||
|
|
||||||
Some MCP clients default to short timeouts and can disconnect from Zen during long tool runs. Configure each client with a generous ceiling (we recommend at least five minutes); the Zen setup script now writes a 20-minute tool timeout for Codex so upstream providers contacted by the server have time to respond.
|
Some MCP clients default to short timeouts and can disconnect from PAL during long tool runs. Configure each client with a generous ceiling (we recommend at least five minutes); the PAL setup script now writes a 20-minute tool timeout for Codex so upstream providers contacted by the server have time to respond.
|
||||||
|
|
||||||
### Claude Code & Claude Desktop
|
### Claude Code & Claude Desktop
|
||||||
|
|
||||||
@@ -320,14 +320,14 @@ Claude reads MCP-related environment variables either from your shell or from `~
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can scope this block at the top level of `settings.json` (applies to every session) or under a specific `mcpServers.<name>.env` entry if you only want it for Zen. The values are in milliseconds. Note: Claude’s SSE transport still enforces an internal ceiling of roughly five minutes; long-running HTTP/SSE servers may need retries until Anthropic ships their fix.
|
You can scope this block at the top level of `settings.json` (applies to every session) or under a specific `mcpServers.<name>.env` entry if you only want it for PAL (the server name may still be `pal` while configurations catch up). The values are in milliseconds. Note: Claude’s SSE transport still enforces an internal ceiling of roughly five minutes; long-running HTTP/SSE servers may need retries until Anthropic ships their fix.
|
||||||
|
|
||||||
### Codex CLI
|
### Codex CLI
|
||||||
|
|
||||||
Codex exposes per-server timeouts in `~/.codex/config.toml`. Add (or bump) these keys under `[[mcp_servers.<name>]]`:
|
Codex exposes per-server timeouts in `~/.codex/config.toml`. Add (or bump) these keys under `[[mcp_servers.<name>]]`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[mcp_servers.zen]
|
[mcp_servers.pal]
|
||||||
command = "..."
|
command = "..."
|
||||||
args = ["..."]
|
args = ["..."]
|
||||||
startup_timeout_sec = 300 # default is 10 seconds
|
startup_timeout_sec = 300 # default is 10 seconds
|
||||||
@@ -343,9 +343,9 @@ Gemini uses a single `timeout` field per server inside `~/.gemini/settings.json`
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "uvx",
|
"command": "uvx",
|
||||||
"args": ["zen-mcp-server"],
|
"args": ["pal-mcp-server"],
|
||||||
"timeout": 300000
|
"timeout": 300000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,62 +364,62 @@ Versions 0.2.1 and newer currently ignore values above ~60 seconds for some tran
|
|||||||
### For Claude Desktop:
|
### For Claude Desktop:
|
||||||
1. Restart Claude Desktop
|
1. Restart Claude Desktop
|
||||||
2. Open a new conversation
|
2. Open a new conversation
|
||||||
3. Try: `"Use zen to list available models"`
|
3. Try: `"Use pal to list available models"`
|
||||||
|
|
||||||
### For Claude Code CLI:
|
### For Claude Code CLI:
|
||||||
1. Exit any existing Claude session
|
1. Exit any existing Claude session
|
||||||
2. Run `claude` from your project directory
|
2. Run `claude` from your project directory
|
||||||
3. Try: `"Use zen to chat about Python best practices"`
|
3. Try: `"Use pal to chat about Python best practices"`
|
||||||
|
|
||||||
### For Gemini CLI:
|
### For Gemini CLI:
|
||||||
**Note**: While Zen MCP connects to Gemini CLI, tool invocation isn't working correctly yet. See [Gemini CLI Setup](gemini-setup.md) for updates.
|
**Note**: While PAL MCP connects to Gemini CLI, tool invocation isn't working correctly yet. See [Gemini CLI Setup](gemini-setup.md) for updates.
|
||||||
|
|
||||||
### For Qwen Code CLI:
|
### For Qwen Code CLI:
|
||||||
1. Restart the Qwen Code CLI if it's running (`qwen exit`).
|
1. Restart the Qwen Code CLI if it's running (`qwen exit`).
|
||||||
2. Run `qwen mcp list --scope user` and confirm `zen` shows `CONNECTED`.
|
2. Run `qwen mcp list --scope user` and confirm `pal` shows `CONNECTED`.
|
||||||
3. Try: `"/mcp"` to inspect available tools or `"Use zen to analyze this repo"`.
|
3. Try: `"/mcp"` to inspect available tools or `"Use pal to analyze this repo"`.
|
||||||
|
|
||||||
### For OpenCode CLI:
|
### For OpenCode CLI:
|
||||||
1. Restart OpenCode (or run `OpenCode: Reload Config`).
|
1. Restart OpenCode (or run `OpenCode: Reload Config`).
|
||||||
2. Open **Settings › Tools › MCP** and confirm `zen` is enabled.
|
2. Open **Settings › Tools › MCP** and confirm `pal` is enabled.
|
||||||
3. Start a new chat and try: `"Use zen to list available models"`.
|
3. Start a new chat and try: `"Use pal to list available models"`.
|
||||||
|
|
||||||
### For Codex CLI:
|
### For Codex CLI:
|
||||||
1. Restart Codex CLI if running
|
1. Restart Codex CLI if running
|
||||||
2. Open a new conversation
|
2. Open a new conversation
|
||||||
3. Try: `"Use zen to list available models"`
|
3. Try: `"Use pal to list available models"`
|
||||||
|
|
||||||
### Test Commands:
|
### Test Commands:
|
||||||
```
|
```
|
||||||
"Use zen to list available models"
|
"Use pal to list available models"
|
||||||
"Chat with zen about the best approach for API design"
|
"Chat with pal about the best approach for API design"
|
||||||
"Use zen thinkdeep with gemini pro about scaling strategies"
|
"Use pal thinkdeep with gemini pro about scaling strategies"
|
||||||
"Debug this error with o3: [paste error]"
|
"Debug this error with o3: [paste error]"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: Codex CLI provides excellent MCP integration with automatic environment variable configuration when using the setup script.
|
**Note**: Codex CLI provides excellent MCP integration with automatic environment variable configuration when using the setup script.
|
||||||
|
|
||||||
## Step 5: Start Using Zen
|
## Step 5: Start Using PAL
|
||||||
|
|
||||||
### Basic Usage Patterns:
|
### Basic Usage Patterns:
|
||||||
|
|
||||||
**Let Claude pick the model:**
|
**Let Claude pick the model:**
|
||||||
```
|
```
|
||||||
"Use zen to analyze this code for security issues"
|
"Use pal to analyze this code for security issues"
|
||||||
"Debug this race condition with zen"
|
"Debug this race condition with pal"
|
||||||
"Plan the database migration with zen"
|
"Plan the database migration with pal"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Specify the model:**
|
**Specify the model:**
|
||||||
```
|
```
|
||||||
"Use zen with gemini pro to review this complex algorithm"
|
"Use pal with gemini pro to review this complex algorithm"
|
||||||
"Debug with o3 using zen for logical analysis"
|
"Debug with o3 using pal for logical analysis"
|
||||||
"Get flash to quickly format this code via zen"
|
"Get flash to quickly format this code via pal"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Multi-model workflows:**
|
**Multi-model workflows:**
|
||||||
```
|
```
|
||||||
"Use zen to get consensus from pro and o3 on this architecture"
|
"Use pal to get consensus from pro and o3 on this architecture"
|
||||||
"Code review with gemini, then precommit validation with o3"
|
"Code review with gemini, then precommit validation with o3"
|
||||||
"Analyze with flash, then deep dive with pro if issues found"
|
"Analyze with flash, then deep dive with pro if issues found"
|
||||||
```
|
```
|
||||||
@@ -435,7 +435,7 @@ Versions 0.2.1 and newer currently ignore values above ~60 seconds for some tran
|
|||||||
|
|
||||||
## Common Issues and Solutions
|
## Common Issues and Solutions
|
||||||
|
|
||||||
### "zen not found" or "command not found"
|
### "pal not found" or "command not found"
|
||||||
|
|
||||||
**For uvx installations:**
|
**For uvx installations:**
|
||||||
- Ensure `uv` is installed and in PATH
|
- Ensure `uv` is installed and in PATH
|
||||||
@@ -444,7 +444,7 @@ Versions 0.2.1 and newer currently ignore values above ~60 seconds for some tran
|
|||||||
|
|
||||||
**For clone installations:**
|
**For clone installations:**
|
||||||
- Run `./run-server.sh` again to verify setup
|
- Run `./run-server.sh` again to verify setup
|
||||||
- Check virtual environment: `which python` should show `.zen_venv/bin/python`
|
- Check virtual environment: `which python` should show `.pal_venv/bin/python`
|
||||||
|
|
||||||
### API Key Issues
|
### API Key Issues
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ Versions 0.2.1 and newer currently ignore values above ~60 seconds for some tran
|
|||||||
- Check for extra spaces or quotes around keys
|
- Check for extra spaces or quotes around keys
|
||||||
|
|
||||||
**"Model not available":**
|
**"Model not available":**
|
||||||
- Run `"Use zen to list available models"` to see what's configured
|
- Run `"Use pal to list available models"` to see what's configured
|
||||||
- Check model restrictions in environment variables
|
- Check model restrictions in environment variables
|
||||||
- Verify API key has access to requested models
|
- Verify API key has access to requested models
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
# Zen MCP Server Documentation
|
# PAL MCP Server Documentation
|
||||||
|
|
||||||
|
_Formerly known as PAL MCP. See the short [name change note](name-change.md) for context._
|
||||||
|
|
||||||
| Document | Description |
|
| Document | Description |
|
||||||
|----------|-------------|
|
|----------|-------------|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Locale Configuration for Zen MCP Server
|
# Locale Configuration for PAL MCP Server
|
||||||
|
|
||||||
This guide explains how to configure and use the localization feature to customize the language of responses from MCP tools.
|
This guide explains how to configure and use the localization feature to customize the language of responses from MCP tools.
|
||||||
|
|
||||||
|
|||||||
5
docs/name-change.md
Normal file
5
docs/name-change.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# PAL MCP Name Change
|
||||||
|
|
||||||
|
PAL MCP was previously called Zen MCP. We renamed to avoid confusion with another similarly named product and to better reflect our role as a Provider Abstraction Layer. The software and workflows are the same.
|
||||||
|
|
||||||
|
Due to the change of name, you may need to run `run-server.sh` again to setup the new connection, and re-visit any `ZEN` name used within `.env` and change it to `PAL`.
|
||||||
@@ -5,7 +5,7 @@ Most importantly, it does this within in a sub-process / sub-agent, saving you p
|
|||||||
|
|
||||||
## Why Use This Tool?
|
## Why Use This Tool?
|
||||||
|
|
||||||
### Without Zen (Using Standard AI)
|
### Without PAL (Using Standard AI)
|
||||||
```
|
```
|
||||||
User: "How do I add glass look to a button in Swift?"
|
User: "How do I add glass look to a button in Swift?"
|
||||||
|
|
||||||
@@ -17,11 +17,11 @@ Result: You get outdated APIs for iOS 18, not the iOS 26 effect you're after
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[API without Zen](https://github.com/user-attachments/assets/01a79dc9-ad16-4264-9ce1-76a56c3580ee)
|
[API without PAL](https://github.com/user-attachments/assets/01a79dc9-ad16-4264-9ce1-76a56c3580ee)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### With Zen (Using apilookup)
|
### With PAL (Using apilookup)
|
||||||
```
|
```
|
||||||
User: "use apilookup how do I add glass look to a button in swift?"
|
User: "use apilookup how do I add glass look to a button in swift?"
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ Result: You get the correct, current APIs that work with today's iOS version
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[API with Zen](https://github.com/user-attachments/assets/5c847326-4b66-41f7-8f30-f380453dce22)
|
[API with PAL](https://github.com/user-attachments/assets/5c847326-4b66-41f7-8f30-f380453dce22)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ The AI then performs the actual web searches and synthesizes the results into ac
|
|||||||
|
|
||||||
## Codex CLI Configuration Reminder
|
## Codex CLI Configuration Reminder
|
||||||
|
|
||||||
If you use Zen through the Codex CLI, the assistant needs Codex's native web-search tool to fetch current documentation. After adding the Zen MCP entry to `~/.codex/config.toml`, confirm the file also contains:
|
If you use PAL through the Codex CLI, the assistant needs Codex's native web-search tool to fetch current documentation. After adding the PAL MCP entry to `~/.codex/config.toml`, confirm the file also contains:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[tools]
|
[tools]
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ bigger picture or ignoring architectural constraints.
|
|||||||
`challenge` fixes this. Claude can even _detect_ when you're challenging something and automatically invokes this tool
|
`challenge` fixes this. Claude can even _detect_ when you're challenging something and automatically invokes this tool
|
||||||
to ensure thoughtful analysis instead of reflexive agreement.
|
to ensure thoughtful analysis instead of reflexive agreement.
|
||||||
|
|
||||||
**Without Zen:**
|
**Without PAL:**
|
||||||

|

|
||||||
|
|
||||||
**With Zen:**
|
**With PAL:**
|
||||||

|

|
||||||
|
|
||||||
## Why Use Challenge?
|
## Why Use Challenge?
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ word verdict in the end.
|
|||||||
|
|
||||||
* We ask Claude code to pick one of two frameworks, then `chat` with `gemini` to make a final decision
|
* We ask Claude code to pick one of two frameworks, then `chat` with `gemini` to make a final decision
|
||||||
* Gemini responds, confirming choice. We use `continuation` to ask another question using the same conversation thread
|
* Gemini responds, confirming choice. We use `continuation` to ask another question using the same conversation thread
|
||||||
* Gemini responds with explanation. We use continuation again, using `/zen:continue (MCP)` command the second time
|
* Gemini responds with explanation. We use continuation again, using `/pal:continue (MCP)` command the second time
|
||||||
|
|
||||||
<div style="center">
|
<div style="center">
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ word verdict in the end.
|
|||||||
- **Collaborative thinking partner** for your analysis and planning
|
- **Collaborative thinking partner** for your analysis and planning
|
||||||
- **Get second opinions** on your designs and approaches
|
- **Get second opinions** on your designs and approaches
|
||||||
- **Brainstorm solutions** and explore alternatives together
|
- **Brainstorm solutions** and explore alternatives together
|
||||||
- **Structured code generation**: When using GPT-5.1 or Gemini 3.0 / 2.5 Pro, get complete, production-ready implementations saved to `zen_generated.code` for your CLI to review and apply
|
- **Structured code generation**: When using GPT-5.1 or Gemini 3.0 / 2.5 Pro, get complete, production-ready implementations saved to `pal_generated.code` for your CLI to review and apply
|
||||||
- **Validate your checklists** and implementation plans
|
- **Validate your checklists** and implementation plans
|
||||||
- **General development questions** and explanations
|
- **General development questions** and explanations
|
||||||
- **Technology comparisons** and best practices
|
- **Technology comparisons** and best practices
|
||||||
@@ -67,8 +67,8 @@ When using advanced reasoning models like **GPT-5 Pro** or **Gemini 3.0 Pro**, t
|
|||||||
### How It Works
|
### How It Works
|
||||||
|
|
||||||
1. You ask your AI agent to implement a complex new feature using `chat` with a higher-reasoning model such as **GPT-5 Pro** or **Gemini 3.0 Pro**
|
1. You ask your AI agent to implement a complex new feature using `chat` with a higher-reasoning model such as **GPT-5 Pro** or **Gemini 3.0 Pro**
|
||||||
2. The model generates structured implementation and shares the complete implementation with Zen
|
2. The model generates structured implementation and shares the complete implementation with PAL
|
||||||
3. Zen saves the code to `zen_generated.code` and asks AI agent to implement the plan
|
3. PAL saves the code to `pal_generated.code` and asks AI agent to implement the plan
|
||||||
4. AI agent continues from the previous context, reads the file, applies the implementation
|
4. AI agent continues from the previous context, reads the file, applies the implementation
|
||||||
|
|
||||||
### When Code Generation Activates
|
### When Code Generation Activates
|
||||||
@@ -101,7 +101,7 @@ See the [Configuration Guide](../configuration.md#code-generation-capability) fo
|
|||||||
|
|
||||||
**Basic Development Chat:**
|
**Basic Development Chat:**
|
||||||
```
|
```
|
||||||
"Chat with zen about the best approach for user authentication in my React app"
|
"Chat with pal about the best approach for user authentication in my React app"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Technology Comparison:**
|
**Technology Comparison:**
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ Gemini receives the full conversation context from `consensus` including the con
|
|||||||
- **Role-based prompts**: Pre-configured roles for planning, code review, or general questions
|
- **Role-based prompts**: Pre-configured roles for planning, code review, or general questions
|
||||||
- **Full CLI capabilities**: Gemini can use its own web search, file tools, and latest features
|
- **Full CLI capabilities**: Gemini can use its own web search, file tools, and latest features
|
||||||
- **Token efficiency**: File references (not full content) to conserve tokens
|
- **Token efficiency**: File references (not full content) to conserve tokens
|
||||||
- **Cross-tool collaboration**: Combine with other Zen tools like `planner` → `clink` → `codereview`
|
- **Cross-tool collaboration**: Combine with other PAL tools like `planner` → `clink` → `codereview`
|
||||||
- **Free tier available**: Gemini offers 1,000 requests/day free with a personal Google account - great for cost savings across tools
|
- **Free tier available**: Gemini offers 1,000 requests/day free with a personal Google account - great for cost savings across tools
|
||||||
|
|
||||||
## Available Roles
|
## Available Roles
|
||||||
@@ -120,18 +120,18 @@ then codereview to verify the implementation"
|
|||||||
## How Clink Works
|
## How Clink Works
|
||||||
|
|
||||||
1. **Your request** - You ask your current CLI to use `clink` with a specific CLI and role
|
1. **Your request** - You ask your current CLI to use `clink` with a specific CLI and role
|
||||||
2. **Background execution** - Zen spawns the configured CLI (e.g., `gemini --output-format json`)
|
2. **Background execution** - PAL spawns the configured CLI (e.g., `gemini --output-format json`)
|
||||||
3. **Context forwarding** - Your prompt, files (as references), and conversation history are sent as part of the prompt
|
3. **Context forwarding** - Your prompt, files (as references), and conversation history are sent as part of the prompt
|
||||||
4. **CLI processing** - Gemini (or other CLI) uses its own tools: web search, file access, thinking modes
|
4. **CLI processing** - Gemini (or other CLI) uses its own tools: web search, file access, thinking modes
|
||||||
5. **Seamless return** - Results flow back into your conversation with full context preserved
|
5. **Seamless return** - Results flow back into your conversation with full context preserved
|
||||||
6. **Continuation support** - Future tools and models can reference Gemini's findings via [continuation support](../context-revival.md) within Zen.
|
6. **Continuation support** - Future tools and models can reference Gemini's findings via [continuation support](../context-revival.md) within PAL.
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
|
|
||||||
- **Pre-authenticate CLIs**: Install and configure Gemini CLI first (`npm install -g @google/gemini-cli`)
|
- **Pre-authenticate CLIs**: Install and configure Gemini CLI first (`npm install -g @google/gemini-cli`)
|
||||||
- **Choose appropriate roles**: Use `planner` for strategy, `codereviewer` for code, `default` for general questions
|
- **Choose appropriate roles**: Use `planner` for strategy, `codereviewer` for code, `default` for general questions
|
||||||
- **Leverage CLI strengths**: Gemini's 1M context for large codebases, web search for current docs
|
- **Leverage CLI strengths**: Gemini's 1M context for large codebases, web search for current docs
|
||||||
- **Combine with Zen tools**: Chain `clink` with `planner`, `codereview`, `debug` for powerful workflows
|
- **Combine with PAL tools**: Chain `clink` with `planner`, `codereview`, `debug` for powerful workflows
|
||||||
- **File efficiency**: Pass file paths, let the CLI decide what to read (saves tokens)
|
- **File efficiency**: Pass file paths, let the CLI decide what to read (saves tokens)
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
@@ -153,9 +153,9 @@ Each preset points to role-specific prompts in `systemprompts/clink/`. Duplicate
|
|||||||
## When to Use Clink vs Other Tools
|
## When to Use Clink vs Other Tools
|
||||||
|
|
||||||
- **Use `clink`** for: Leveraging external CLI capabilities (Gemini's web search, 1M context), specialized CLI features, cross-CLI collaboration
|
- **Use `clink`** for: Leveraging external CLI capabilities (Gemini's web search, 1M context), specialized CLI features, cross-CLI collaboration
|
||||||
- **Use `chat`** for: Direct model-to-model conversations within Zen
|
- **Use `chat`** for: Direct model-to-model conversations within PAL
|
||||||
- **Use `planner`** for: Zen's native planning workflows with step validation
|
- **Use `planner`** for: PAL's native planning workflows with step validation
|
||||||
- **Use `codereview`** for: Zen's structured code review with severity levels
|
- **Use `codereview`** for: PAL's structured code review with severity levels
|
||||||
|
|
||||||
## Setup Requirements
|
## Setup Requirements
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ Ensure the relevant CLI is installed and configured:
|
|||||||
## Related Guides
|
## Related Guides
|
||||||
|
|
||||||
- [Chat Tool](chat.md) - Direct model conversations
|
- [Chat Tool](chat.md) - Direct model conversations
|
||||||
- [Planner Tool](planner.md) - Zen's native planning workflows
|
- [Planner Tool](planner.md) - PAL's native planning workflows
|
||||||
- [CodeReview Tool](codereview.md) - Structured code reviews
|
- [CodeReview Tool](codereview.md) - Structured code reviews
|
||||||
- [Context Revival](../context-revival.md) - Continuing conversations across tools
|
- [Context Revival](../context-revival.md) - Continuing conversations across tools
|
||||||
- [Advanced Usage](../advanced-usage.md) - Complex multi-tool workflows
|
- [Advanced Usage](../advanced-usage.md) - Complex multi-tool workflows
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ The following is a hypothetical example designed to demonstrate how one consensu
|
|||||||
|
|
||||||
<div style="center">
|
<div style="center">
|
||||||
|
|
||||||
[Zen Consensus Debate](https://github.com/user-attachments/assets/76a23dd5-887a-4382-9cf0-642f5cf6219e)
|
[PAL Consensus Debate](https://github.com/user-attachments/assets/76a23dd5-887a-4382-9cf0-642f5cf6219e)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ The following is a hypothetical example designed to demonstrate how one consensu
|
|||||||
|
|
||||||
**For/Against Analysis:**
|
**For/Against Analysis:**
|
||||||
```
|
```
|
||||||
Use zen consensus with flash taking a supportive stance and pro being critical to evaluate whether
|
Use pal consensus with flash taking a supportive stance and pro being critical to evaluate whether
|
||||||
we should migrate from REST to GraphQL for our API
|
we should migrate from REST to GraphQL for our API
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Documentation generation excels with analytical models like Gemini Pro or O3, wh
|
|||||||
|
|
||||||
**Basic Usage:**
|
**Basic Usage:**
|
||||||
```
|
```
|
||||||
"Use zen to generate documentation for the UserManager class"
|
"Use pal to generate documentation for the UserManager class"
|
||||||
"Document the authentication module with complexity analysis using gemini pro"
|
"Document the authentication module with complexity analysis using gemini pro"
|
||||||
"Add comprehensive documentation to all methods in src/payment_processor.py"
|
"Add comprehensive documentation to all methods in src/payment_processor.py"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ The `listmodels` tool shows which providers are configured, available models, th
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
"Use zen to list available models"
|
"Use pal to list available models"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ The planner tool enables step-by-step thinking with incremental plan building:
|
|||||||
|
|
||||||
#### Pro Tip
|
#### Pro Tip
|
||||||
Claude supports `sub-tasks` where it will spawn and run separate background tasks. You can ask Claude to
|
Claude supports `sub-tasks` where it will spawn and run separate background tasks. You can ask Claude to
|
||||||
run Zen's planner with two separate ideas. Then when it's done, use Zen's `consensus` tool to pass the entire
|
run PAL's planner with two separate ideas. Then when it's done, use PAL's `consensus` tool to pass the entire
|
||||||
plan and get expert perspective from two powerful AI models on which one to work on first! Like performing **AB** testing
|
plan and get expert perspective from two powerful AI models on which one to work on first! Like performing **AB** testing
|
||||||
in one-go without the wait!
|
in one-go without the wait!
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ I implement first?
|
|||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
Use zen's planner and show me how to add real-time notifications to our mobile app
|
Use pal's planner and show me how to add real-time notifications to our mobile app
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -55,11 +55,11 @@ Using planner, plan the architecture for a new real-time chat system with 100k c
|
|||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
Create a plan using zen for migrating our React app from JavaScript to TypeScript
|
Create a plan using pal for migrating our React app from JavaScript to TypeScript
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
Develop a plan using zen for implementing CI/CD pipelines across our development teams
|
Develop a plan using pal for implementing CI/CD pipelines across our development teams
|
||||||
```
|
```
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
@@ -73,10 +73,10 @@ Develop a plan using zen for implementing CI/CD pipelines across our development
|
|||||||
|
|
||||||
## Continue With a New Plan
|
## Continue With a New Plan
|
||||||
|
|
||||||
Like all other tools in Zen, you can `continue` with a new plan using the output from a previous plan by simply saying
|
Like all other tools in PAL, you can `continue` with a new plan using the output from a previous plan by simply saying
|
||||||
|
|
||||||
```
|
```
|
||||||
Continue with zen's consensus tool and find out what o3:for and flash:against think of the plan
|
Continue with pal's consensus tool and find out what o3:for and flash:against think of the plan
|
||||||
```
|
```
|
||||||
|
|
||||||
You can mix and match and take one output and feed it into another, continuing from where you left off using a different
|
You can mix and match and take one output and feed it into another, continuing from where you left off using a different
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ After Claude completes the investigation (unless precommit_type is **internal**)
|
|||||||
- Default validation type is **external** (uses expert model for additional review)
|
- Default validation type is **external** (uses expert model for additional review)
|
||||||
- To skip expert validation, explicitly request "don't use any other model" or set precommit_type to "internal"
|
- To skip expert validation, explicitly request "don't use any other model" or set precommit_type to "internal"
|
||||||
- **CRITICAL**: Minimum 3 steps are enforced - tool will prevent setting `next_step_required=false` before final step
|
- **CRITICAL**: Minimum 3 steps are enforced - tool will prevent setting `next_step_required=false` before final step
|
||||||
- **MANDATORY**: Changeset file (zen_precommit.changeset) must be created for external validation
|
- **MANDATORY**: Changeset file (pal_precommit.changeset) must be created for external validation
|
||||||
|
|
||||||
## Model Recommendation
|
## Model Recommendation
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ passing, it went ahead with an initial review with O3; came back clean - all goo
|
|||||||
Then it shared the changes and relevant code with Gemini 3.0 Pro - the following is the outcome:
|
Then it shared the changes and relevant code with Gemini 3.0 Pro - the following is the outcome:
|
||||||
|
|
||||||
```
|
```
|
||||||
⏺ zen:precommit (MCP)(step: "FINAL VALIDATION COMPLETE. All changes have been thoroughly analyzed and are ready for
|
⏺ pal:precommit (MCP)(step: "FINAL VALIDATION COMPLETE. All changes have been thoroughly analyzed and are ready for
|
||||||
commit. The modifications successfully fix 4 GitHub CI test failures with high-quality, defensive
|
commit. The modifications successfully fix 4 GitHub CI test failures with high-quality, defensive
|
||||||
implementations that maintain architectural integrity and coding standards. No issues or regressions
|
implementations that maintain architectural integrity and coding standards. No issues or regressions
|
||||||
detected.", step_number: 4, total_steps: 4, next_step_required: false, findings: "COMMIT
|
detected.", step_number: 4, total_steps: 4, next_step_required: false, findings: "COMMIT
|
||||||
@@ -101,12 +101,12 @@ Then it shared the changes and relevant code with Gemini 3.0 Pro - the following
|
|||||||
- Fix Required: Apply the same defensive pattern to the missed location
|
- Fix Required: Apply the same defensive pattern to the missed location
|
||||||
```
|
```
|
||||||
|
|
||||||
A subtle but critical issue spotted by Gemini that both Claude + O3 missed. This is the power of running these workflows with Zen.
|
A subtle but critical issue spotted by Gemini that both Claude + O3 missed. This is the power of running these workflows with PAL.
|
||||||
|
|
||||||
## Example Prompts
|
## Example Prompts
|
||||||
|
|
||||||
```
|
```
|
||||||
Use zen and perform a thorough precommit ensuring there aren't any new regressions or bugs introduced
|
Use pal and perform a thorough precommit ensuring there aren't any new regressions or bugs introduced
|
||||||
```
|
```
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
@@ -155,7 +155,7 @@ Use zen and perform a thorough precommit ensuring there aren't any new regressio
|
|||||||
|
|
||||||
**Basic Pre-commit Validation:**
|
**Basic Pre-commit Validation:**
|
||||||
```
|
```
|
||||||
"Use zen precommit to validate my changes before committing"
|
"Use pal precommit to validate my changes before committing"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Security-Focused Validation:**
|
**Security-Focused Validation:**
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ The refactor tool excels with models that have large context windows like Gemini
|
|||||||
|
|
||||||
```
|
```
|
||||||
"Use gemini pro to decompose my_crazy_big_class.m into smaller extensions"
|
"Use gemini pro to decompose my_crazy_big_class.m into smaller extensions"
|
||||||
"Using zen's refactor decompose the all_in_one_sync_code.swift into maintainable extensions"
|
"Using pal's refactor decompose the all_in_one_sync_code.swift into maintainable extensions"
|
||||||
```
|
```
|
||||||
|
|
||||||
💡**Example of a powerful prompt** to get the best out of both Claude + Flash's 1M Context:
|
💡**Example of a powerful prompt** to get the best out of both Claude + Flash's 1M Context:
|
||||||
```
|
```
|
||||||
"First, think about how the authentication module works, find related classes and find
|
"First, think about how the authentication module works, find related classes and find
|
||||||
any code smells, then using zen's refactor ask flash to confirm your findings but ask
|
any code smells, then using pal's refactor ask flash to confirm your findings but ask
|
||||||
it to find additional code smells and any other quick-wins and then fix these issues"
|
it to find additional code smells and any other quick-wins and then fix these issues"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ Test generation excels with extended reasoning models like Gemini Pro or O3, whi
|
|||||||
|
|
||||||
**Basic Usage:**
|
**Basic Usage:**
|
||||||
```
|
```
|
||||||
"Use zen to generate tests for User.login() method"
|
"Use pal to generate tests for User.login() method"
|
||||||
"Generate comprehensive tests for the sorting method in src/new_sort.py using o3"
|
"Generate comprehensive tests for the sorting method in src/new_sort.py using o3"
|
||||||
"Create tests for edge cases not already covered in our tests using gemini pro"
|
"Create tests for edge cases not already covered in our tests using gemini pro"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ The `tracer` tool is a specialized prompt-generation tool that creates structure
|
|||||||
|
|
||||||
**Method Execution Tracing:**
|
**Method Execution Tracing:**
|
||||||
```
|
```
|
||||||
"Use zen tracer to analyze how UserAuthManager.authenticate is used and why"
|
"Use pal tracer to analyze how UserAuthManager.authenticate is used and why"
|
||||||
```
|
```
|
||||||
→ Uses `precision` mode to trace the method's execution flow
|
→ Uses `precision` mode to trace the method's execution flow
|
||||||
|
|
||||||
**Class Dependency Mapping:**
|
**Class Dependency Mapping:**
|
||||||
```
|
```
|
||||||
"Use zen to generate a dependency trace for the PaymentProcessor class to understand its relationships"
|
"Use pal to generate a dependency trace for the PaymentProcessor class to understand its relationships"
|
||||||
```
|
```
|
||||||
→ Uses `dependencies` mode to map structural relationships
|
→ Uses `dependencies` mode to map structural relationships
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
**Get server version, configuration details, and list of available tools**
|
**Get server version, configuration details, and list of available tools**
|
||||||
|
|
||||||
The `version` tool provides information about the Zen MCP Server version, configuration details, and system capabilities. This is useful for debugging, understanding server capabilities, and verifying your installation.
|
The `version` tool provides information about the PAL MCP Server version, configuration details, and system capabilities. This is useful for debugging, understanding server capabilities, and verifying your installation.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
"Get zen to show its version"
|
"Get pal to show its version"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
@@ -48,7 +48,7 @@ The tool provides:
|
|||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
```
|
```
|
||||||
🔧 Zen MCP Server Information
|
🔧 PAL MCP Server Information
|
||||||
|
|
||||||
📋 Version: 2.15.0
|
📋 Version: 2.15.0
|
||||||
🏗️ Build: 2024-01-15T10:30:00Z (commit: abc123f)
|
🏗️ Build: 2024-01-15T10:30:00Z (commit: abc123f)
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
## Quick Debugging Steps
|
## Quick Debugging Steps
|
||||||
|
|
||||||
If you're experiencing issues with the Zen MCP Server, follow these steps:
|
If you're experiencing issues with the PAL MCP Server, follow these steps:
|
||||||
|
|
||||||
### 1. Check MCP Connection
|
### 1. Check MCP Connection
|
||||||
|
|
||||||
Open Claude Desktop and type `/mcp` to see if zen is connected:
|
Open Claude Desktop and type `/mcp` to see if pal is connected:
|
||||||
- ✅ If zen appears in the list, the connection is working
|
- ✅ If pal appears in the list, the connection is working
|
||||||
- ❌ If not listed or shows an error, continue to step 2
|
- ❌ If not listed or shows an error, continue to step 2
|
||||||
|
|
||||||
### 2. Launch Claude with Debug Mode
|
### 2. Launch Claude with Debug Mode
|
||||||
@@ -79,14 +79,14 @@ See [Logging Documentation](logging.md) for more details on accessing logs.
|
|||||||
|
|
||||||
**Python module not found**
|
**Python module not found**
|
||||||
- Run `./run-server.sh` to reinstall dependencies
|
- Run `./run-server.sh` to reinstall dependencies
|
||||||
- Check virtual environment is activated: should see `.zen_venv` in the Python path
|
- Check virtual environment is activated: should see `.pal_venv` in the Python path
|
||||||
|
|
||||||
### 6. Environment Issues
|
### 6. Environment Issues
|
||||||
|
|
||||||
**Virtual Environment Problems**
|
**Virtual Environment Problems**
|
||||||
```bash
|
```bash
|
||||||
# Reset environment completely
|
# Reset environment completely
|
||||||
rm -rf .zen_venv
|
rm -rf .pal_venv
|
||||||
./run-server.sh
|
./run-server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# WSL (Windows Subsystem for Linux) Setup Guide
|
# WSL (Windows Subsystem for Linux) Setup Guide
|
||||||
|
|
||||||
This guide provides detailed instructions for setting up Zen MCP Server on Windows using WSL.
|
This guide provides detailed instructions for setting up PAL MCP Server on Windows using WSL.
|
||||||
|
|
||||||
## Prerequisites for WSL
|
## Prerequisites for WSL
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@ npm install -g @anthropic-ai/claude-code
|
|||||||
cd ~
|
cd ~
|
||||||
|
|
||||||
# Clone the repository
|
# Clone the repository
|
||||||
git clone https://github.com/BeehiveInnovations/zen-mcp-server.git
|
git clone https://github.com/BeehiveInnovations/pal-mcp-server.git
|
||||||
cd zen-mcp-server
|
cd pal-mcp-server
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Run the setup script**:
|
2. **Run the setup script**:
|
||||||
@@ -43,7 +43,7 @@ npm install -g @anthropic-ai/claude-code
|
|||||||
# List configured MCP servers
|
# List configured MCP servers
|
||||||
claude mcp list
|
claude mcp list
|
||||||
|
|
||||||
# You should see 'zen' listed in the output
|
# You should see 'pal' listed in the output
|
||||||
# If not, the setup script will provide the correct configuration
|
# If not, the setup script will provide the correct configuration
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -61,19 +61,19 @@ python3 -m pip install --upgrade pip
|
|||||||
|
|
||||||
### Path Issues
|
### Path Issues
|
||||||
|
|
||||||
- Always use the full WSL path for MCP configuration (e.g., `/home/YourName/zen-mcp-server/`)
|
- Always use the full WSL path for MCP configuration (e.g., `/home/YourName/pal-mcp-server/`)
|
||||||
- The setup script automatically detects WSL and configures the correct paths
|
- The setup script automatically detects WSL and configures the correct paths
|
||||||
|
|
||||||
### Claude Code Connection Issues
|
### Claude Code Connection Issues
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# If Claude Code can't connect to the MCP server, check the configuration
|
# If Claude Code can't connect to the MCP server, check the configuration
|
||||||
cat ~/.claude.json | grep -A 10 "zen"
|
cat ~/.claude.json | grep -A 10 "pal"
|
||||||
|
|
||||||
# The configuration should show the correct WSL path to the Python executable
|
# The configuration should show the correct WSL path to the Python executable
|
||||||
# Example: "/home/YourName/zen-mcp-server/.zen_venv/bin/python"
|
# Example: "/home/YourName/pal-mcp-server/.pal_venv/bin/python"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Performance Tip
|
### Performance Tip
|
||||||
|
|
||||||
For best performance, keep your zen-mcp-server directory in the WSL filesystem (e.g., `~/zen-mcp-server`) rather than in the Windows filesystem (`/mnt/c/...`).
|
For best performance, keep your pal-mcp-server directory in the WSL filesystem (e.g., `~/pal-mcp-server`) rather than in the Windows filesystem (`/mnt/c/...`).
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
"comment2": "Run './run-server.sh' to set up the environment and get exact paths",
|
"comment2": "Run './run-server.sh' to set up the environment and get exact paths",
|
||||||
"comment3": "Use './run-server.sh -c' to display the correct configuration",
|
"comment3": "Use './run-server.sh -c' to display the correct configuration",
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "/path/to/zen-mcp-server/.zen_venv/bin/python",
|
"command": "/path/to/pal-mcp-server/.pal_venv/bin/python",
|
||||||
"args": ["/path/to/zen-mcp-server/server.py"]
|
"args": ["/path/to/pal-mcp-server/server.py"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,11 @@
|
|||||||
"comment2": "Run './run-server.sh' in WSL to set up the environment and get exact paths",
|
"comment2": "Run './run-server.sh' in WSL to set up the environment and get exact paths",
|
||||||
"comment3": "Use './run-server.sh -c' to display the correct configuration",
|
"comment3": "Use './run-server.sh -c' to display the correct configuration",
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "wsl.exe",
|
"command": "wsl.exe",
|
||||||
"args": [
|
"args": [
|
||||||
"/path/to/zen-mcp-server/.zen_venv/bin/python",
|
"/path/to/pal-mcp-server/.pal_venv/bin/python",
|
||||||
"/path/to/zen-mcp-server/server.py"
|
"/path/to/pal-mcp-server/server.py"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
# Get the directory of this script
|
# Get the directory of this script
|
||||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
||||||
# Change to the zen-mcp-server directory
|
# Change to the pal-mcp-server directory
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
|
|
||||||
# Execute the Python server with all arguments passed through
|
# Execute the Python server with all arguments passed through
|
||||||
exec .zen_venv/bin/python server.py "$@"
|
exec .pal_venv/bin/python server.py "$@"
|
||||||
@@ -35,9 +35,9 @@ class OpenRouterProvider(OpenAICompatibleProvider):
|
|||||||
|
|
||||||
# Custom headers required by OpenRouter
|
# Custom headers required by OpenRouter
|
||||||
DEFAULT_HEADERS = {
|
DEFAULT_HEADERS = {
|
||||||
"HTTP-Referer": get_env("OPENROUTER_REFERER", "https://github.com/BeehiveInnovations/zen-mcp-server")
|
"HTTP-Referer": get_env("OPENROUTER_REFERER", "https://github.com/BeehiveInnovations/pal-mcp-server")
|
||||||
or "https://github.com/BeehiveInnovations/zen-mcp-server",
|
or "https://github.com/BeehiveInnovations/pal-mcp-server",
|
||||||
"X-Title": get_env("OPENROUTER_TITLE", "Zen MCP Server") or "Zen MCP Server",
|
"X-Title": get_env("OPENROUTER_TITLE", "PAL MCP Server") or "PAL MCP Server",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Model registry for managing configurations and aliases
|
# Model registry for managing configurations and aliases
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "zen-mcp-server"
|
name = "pal-mcp-server"
|
||||||
version = "9.4.1"
|
version = "9.4.2"
|
||||||
description = "AI-powered MCP server with multiple model providers"
|
description = "AI-powered MCP server with multiple model providers"
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
@@ -36,7 +36,7 @@ py-modules = ["server", "config"]
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
zen-mcp-server = "server:run"
|
pal-mcp-server = "server:run"
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 120
|
line-length = 120
|
||||||
@@ -51,7 +51,7 @@ extend-exclude = '''
|
|||||||
| \.mypy_cache
|
| \.mypy_cache
|
||||||
| \.tox
|
| \.tox
|
||||||
| \.venv
|
| \.venv
|
||||||
| \.zen_venv
|
| \.pal_venv
|
||||||
| venv
|
| venv
|
||||||
| _build
|
| _build
|
||||||
| buck-out
|
| buck-out
|
||||||
@@ -68,7 +68,7 @@ force_grid_wrap = 0
|
|||||||
use_parentheses = true
|
use_parentheses = true
|
||||||
ensure_newline_before_comments = true
|
ensure_newline_before_comments = true
|
||||||
line_length = 120
|
line_length = 120
|
||||||
skip_glob = ["venv/*", ".venv/*", ".zen_venv/*"]
|
skip_glob = ["venv/*", ".venv/*", ".pal_venv/*"]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
target-version = "py39"
|
target-version = "py39"
|
||||||
|
|||||||
334
run-server.ps1
334
run-server.ps1
@@ -1,9 +1,9 @@
|
|||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Installation, configuration, and launch script for Zen MCP server on Windows.
|
Installation, configuration, and launch script for PAL MCP server on Windows.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
This PowerShell script prepares the environment for the Zen MCP server:
|
This PowerShell script prepares the environment for the PAL MCP server:
|
||||||
- Installs and checks Python 3.10+ (with venv or uv if available)
|
- Installs and checks Python 3.10+ (with venv or uv if available)
|
||||||
- Installs required Python dependencies
|
- Installs required Python dependencies
|
||||||
- Configures environment files (.env)
|
- Configures environment files (.env)
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
Shows script help.
|
Shows script help.
|
||||||
|
|
||||||
.PARAMETER Version
|
.PARAMETER Version
|
||||||
Shows Zen MCP server version.
|
Shows PAL MCP server version.
|
||||||
|
|
||||||
.PARAMETER Follow
|
.PARAMETER Follow
|
||||||
Follows server logs in real time.
|
Follows server logs in real time.
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\run-server.ps1
|
.\run-server.ps1
|
||||||
Prepares the environment and starts the Zen MCP server.
|
Prepares the environment and starts the PAL MCP server.
|
||||||
|
|
||||||
.\run-server.ps1 -Follow
|
.\run-server.ps1 -Follow
|
||||||
Follows server logs in real time.
|
Follows server logs in real time.
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
Script Author : GiGiDKR (https://github.com/GiGiDKR)
|
Script Author : GiGiDKR (https://github.com/GiGiDKR)
|
||||||
Date : 07-05-2025
|
Date : 07-05-2025
|
||||||
Version : See config.py (__version__)
|
Version : See config.py (__version__)
|
||||||
References : https://github.com/BeehiveInnovations/zen-mcp-server
|
References : https://github.com/BeehiveInnovations/pal-mcp-server
|
||||||
|
|
||||||
#>
|
#>
|
||||||
#Requires -Version 5.1
|
#Requires -Version 5.1
|
||||||
@@ -93,7 +93,7 @@ param(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Zen MCP Server Setup Script for Windows
|
# PAL MCP Server Setup Script for Windows
|
||||||
#
|
#
|
||||||
# A Windows-compatible setup script that handles environment setup,
|
# A Windows-compatible setup script that handles environment setup,
|
||||||
# dependency installation, and configuration.
|
# dependency installation, and configuration.
|
||||||
@@ -106,11 +106,12 @@ $ErrorActionPreference = "Stop"
|
|||||||
# Constants and Configuration
|
# Constants and Configuration
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
$script:VENV_PATH = ".zen_venv"
|
$script:VENV_PATH = ".pal_venv"
|
||||||
$script:DOCKER_CLEANED_FLAG = ".docker_cleaned"
|
$script:DOCKER_CLEANED_FLAG = ".docker_cleaned"
|
||||||
$script:DESKTOP_CONFIG_FLAG = ".desktop_configured"
|
$script:DESKTOP_CONFIG_FLAG = ".desktop_configured"
|
||||||
$script:LOG_DIR = "logs"
|
$script:LOG_DIR = "logs"
|
||||||
$script:LOG_FILE = "mcp_server.log"
|
$script:LOG_FILE = "mcp_server.log"
|
||||||
|
$script:LegacyServerNames = @("zen", "zen-mcp", "zen-mcp-server", "zen_mcp", "zen_mcp_server")
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Utility Functions
|
# Utility Functions
|
||||||
@@ -209,6 +210,31 @@ function Remove-LockedDirectory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Remove legacy MCP server entries from a hash/dictionary or PSObject
|
||||||
|
function Remove-LegacyServerKeys {
|
||||||
|
param([object]$Container)
|
||||||
|
|
||||||
|
$removed = $false
|
||||||
|
if ($null -eq $Container) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($legacy in $script:LegacyServerNames) {
|
||||||
|
if ($Container -is [System.Collections.IDictionary]) {
|
||||||
|
if ($Container.Contains($legacy)) {
|
||||||
|
$Container.Remove($legacy) | Out-Null
|
||||||
|
$removed = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($Container.PSObject -and $Container.PSObject.Properties[$legacy]) {
|
||||||
|
$Container.PSObject.Properties.Remove($legacy)
|
||||||
|
$removed = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $removed
|
||||||
|
}
|
||||||
|
|
||||||
# Manage configuration file backups with maximum 3 files retention
|
# Manage configuration file backups with maximum 3 files retention
|
||||||
function Manage-ConfigBackups {
|
function Manage-ConfigBackups {
|
||||||
param(
|
param(
|
||||||
@@ -382,9 +408,9 @@ function Cleanup-Docker {
|
|||||||
$containers = @(
|
$containers = @(
|
||||||
"gemini-mcp-server",
|
"gemini-mcp-server",
|
||||||
"gemini-mcp-redis",
|
"gemini-mcp-redis",
|
||||||
"zen-mcp-server",
|
"pal-mcp-server",
|
||||||
"zen-mcp-redis",
|
"pal-mcp-redis",
|
||||||
"zen-mcp-log-monitor"
|
"pal-mcp-log-monitor"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Remove containers
|
# Remove containers
|
||||||
@@ -407,7 +433,7 @@ function Cleanup-Docker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Remove images
|
# Remove images
|
||||||
$images = @("gemini-mcp-server:latest", "zen-mcp-server:latest")
|
$images = @("gemini-mcp-server:latest", "pal-mcp-server:latest")
|
||||||
foreach ($image in $images) {
|
foreach ($image in $images) {
|
||||||
try {
|
try {
|
||||||
$exists = docker images --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -eq $image }
|
$exists = docker images --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -eq $image }
|
||||||
@@ -786,7 +812,7 @@ function Build-DockerImage {
|
|||||||
|
|
||||||
# Check if image exists
|
# Check if image exists
|
||||||
try {
|
try {
|
||||||
$imageExists = docker images --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -eq "zen-mcp-server:latest" }
|
$imageExists = docker images --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -eq "pal-mcp-server:latest" }
|
||||||
if ($imageExists -and !$Force) {
|
if ($imageExists -and !$Force) {
|
||||||
Write-Success "Docker image already exists. Use -Force to rebuild."
|
Write-Success "Docker image already exists. Use -Force to rebuild."
|
||||||
return $true
|
return $true
|
||||||
@@ -799,7 +825,7 @@ function Build-DockerImage {
|
|||||||
if ($Force -and $imageExists) {
|
if ($Force -and $imageExists) {
|
||||||
Write-Info "Forcing rebuild of Docker image..."
|
Write-Info "Forcing rebuild of Docker image..."
|
||||||
try {
|
try {
|
||||||
docker rmi zen-mcp-server:latest 2>$null
|
docker rmi pal-mcp-server:latest 2>$null
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Warning "Could not remove existing image, continuing..."
|
Write-Warning "Could not remove existing image, continuing..."
|
||||||
@@ -814,7 +840,7 @@ function Build-DockerImage {
|
|||||||
Write-Info "Building with development support..."
|
Write-Info "Building with development support..."
|
||||||
}
|
}
|
||||||
|
|
||||||
docker build -t zen-mcp-server:latest .
|
docker build -t pal-mcp-server:latest .
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
throw "Docker build failed"
|
throw "Docker build failed"
|
||||||
}
|
}
|
||||||
@@ -901,7 +927,7 @@ function Start-DockerServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Start services
|
# Start services
|
||||||
Write-Info "Starting Zen MCP Server with Docker Compose..."
|
Write-Info "Starting PAL MCP Server with Docker Compose..."
|
||||||
if (Test-Command "docker-compose") {
|
if (Test-Command "docker-compose") {
|
||||||
if ($Follow) {
|
if ($Follow) {
|
||||||
docker-compose up --build
|
docker-compose up --build
|
||||||
@@ -925,10 +951,10 @@ function Start-DockerServices {
|
|||||||
|
|
||||||
if (!$Follow) {
|
if (!$Follow) {
|
||||||
Write-Success "Docker services started successfully"
|
Write-Success "Docker services started successfully"
|
||||||
Write-Info "Container name: zen-mcp-server"
|
Write-Info "Container name: pal-mcp-server"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "To view logs: " -NoNewline
|
Write-Host "To view logs: " -NoNewline
|
||||||
Write-Host "docker logs -f zen-mcp-server" -ForegroundColor Yellow
|
Write-Host "docker logs -f pal-mcp-server" -ForegroundColor Yellow
|
||||||
Write-Host "To stop: " -NoNewline
|
Write-Host "To stop: " -NoNewline
|
||||||
Write-Host "docker-compose down" -ForegroundColor Yellow
|
Write-Host "docker-compose down" -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
@@ -944,7 +970,7 @@ function Start-DockerServices {
|
|||||||
# Get Docker container status
|
# Get Docker container status
|
||||||
function Get-DockerStatus {
|
function Get-DockerStatus {
|
||||||
try {
|
try {
|
||||||
$containerStatus = docker ps --filter "name=zen-mcp-server" --format "{{.Status}}"
|
$containerStatus = docker ps --filter "name=pal-mcp-server" --format "{{.Status}}"
|
||||||
if ($containerStatus) {
|
if ($containerStatus) {
|
||||||
Write-Success "Container status: $containerStatus"
|
Write-Success "Container status: $containerStatus"
|
||||||
return $true
|
return $true
|
||||||
@@ -1018,7 +1044,7 @@ $script:McpClientDefinitions = @(
|
|||||||
DetectionPath = "$env:APPDATA\Claude\claude_desktop_config.json"
|
DetectionPath = "$env:APPDATA\Claude\claude_desktop_config.json"
|
||||||
DetectionType = "Path"
|
DetectionType = "Path"
|
||||||
ConfigPath = "$env:APPDATA\Claude\claude_desktop_config.json"
|
ConfigPath = "$env:APPDATA\Claude\claude_desktop_config.json"
|
||||||
ConfigJsonPath = "mcpServers.zen"
|
ConfigJsonPath = "mcpServers.pal"
|
||||||
NeedsConfigDir = $true
|
NeedsConfigDir = $true
|
||||||
},
|
},
|
||||||
@{
|
@{
|
||||||
@@ -1026,7 +1052,7 @@ $script:McpClientDefinitions = @(
|
|||||||
DetectionCommand = "code"
|
DetectionCommand = "code"
|
||||||
DetectionType = "Command"
|
DetectionType = "Command"
|
||||||
ConfigPath = "$env:APPDATA\Code\User\settings.json"
|
ConfigPath = "$env:APPDATA\Code\User\settings.json"
|
||||||
ConfigJsonPath = "mcp.servers.zen"
|
ConfigJsonPath = "mcp.servers.pal"
|
||||||
IsVSCode = $true
|
IsVSCode = $true
|
||||||
},
|
},
|
||||||
@{
|
@{
|
||||||
@@ -1034,7 +1060,7 @@ $script:McpClientDefinitions = @(
|
|||||||
DetectionCommand = "code-insiders"
|
DetectionCommand = "code-insiders"
|
||||||
DetectionType = "Command"
|
DetectionType = "Command"
|
||||||
ConfigPath = "$env:APPDATA\Code - Insiders\User\mcp.json"
|
ConfigPath = "$env:APPDATA\Code - Insiders\User\mcp.json"
|
||||||
ConfigJsonPath = "servers.zen"
|
ConfigJsonPath = "servers.pal"
|
||||||
IsVSCodeInsiders = $true
|
IsVSCodeInsiders = $true
|
||||||
},
|
},
|
||||||
@{
|
@{
|
||||||
@@ -1042,28 +1068,28 @@ $script:McpClientDefinitions = @(
|
|||||||
DetectionCommand = "cursor"
|
DetectionCommand = "cursor"
|
||||||
DetectionType = "Command"
|
DetectionType = "Command"
|
||||||
ConfigPath = "$env:USERPROFILE\.cursor\mcp.json"
|
ConfigPath = "$env:USERPROFILE\.cursor\mcp.json"
|
||||||
ConfigJsonPath = "mcpServers.zen"
|
ConfigJsonPath = "mcpServers.pal"
|
||||||
},
|
},
|
||||||
@{
|
@{
|
||||||
Name = "Windsurf"
|
Name = "Windsurf"
|
||||||
DetectionPath = "$env:USERPROFILE\.codeium\windsurf"
|
DetectionPath = "$env:USERPROFILE\.codeium\windsurf"
|
||||||
DetectionType = "Path"
|
DetectionType = "Path"
|
||||||
ConfigPath = "$env:USERPROFILE\.codeium\windsurf\mcp_config.json"
|
ConfigPath = "$env:USERPROFILE\.codeium\windsurf\mcp_config.json"
|
||||||
ConfigJsonPath = "mcpServers.zen"
|
ConfigJsonPath = "mcpServers.pal"
|
||||||
},
|
},
|
||||||
@{
|
@{
|
||||||
Name = "Trae"
|
Name = "Trae"
|
||||||
DetectionPath = "$env:APPDATA\Trae"
|
DetectionPath = "$env:APPDATA\Trae"
|
||||||
DetectionType = "Path"
|
DetectionType = "Path"
|
||||||
ConfigPath = "$env:APPDATA\Trae\User\mcp.json"
|
ConfigPath = "$env:APPDATA\Trae\User\mcp.json"
|
||||||
ConfigJsonPath = "mcpServers.zen"
|
ConfigJsonPath = "mcpServers.pal"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Docker MCP configuration template (legacy, kept for backward compatibility)
|
# Docker MCP configuration template (legacy, kept for backward compatibility)
|
||||||
$script:DockerMcpConfig = @{
|
$script:DockerMcpConfig = @{
|
||||||
command = "docker"
|
command = "docker"
|
||||||
args = @("exec", "-i", "zen-mcp-server", "python", "server.py")
|
args = @("exec", "-i", "pal-mcp-server", "python", "server.py")
|
||||||
type = "stdio"
|
type = "stdio"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1076,7 +1102,7 @@ function Get-DockerMcpConfigRun {
|
|||||||
|
|
||||||
return @{
|
return @{
|
||||||
command = "docker"
|
command = "docker"
|
||||||
args = @("run", "--rm", "-i", "--env-file", $envFile, "zen-mcp-server:latest", "python", "server.py")
|
args = @("run", "--rm", "-i", "--env-file", $envFile, "pal-mcp-server:latest", "python", "server.py")
|
||||||
type = "stdio"
|
type = "stdio"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1103,7 +1129,7 @@ function Test-McpJsonFormat {
|
|||||||
function Test-VSCodeInsidersFormat {
|
function Test-VSCodeInsidersFormat {
|
||||||
param([hashtable]$Client)
|
param([hashtable]$Client)
|
||||||
|
|
||||||
return $Client.IsVSCodeInsiders -eq $true -and $Client.ConfigJsonPath -eq "servers.zen"
|
return $Client.IsVSCodeInsiders -eq $true -and $Client.ConfigJsonPath -eq "servers.pal"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Analyze existing MCP configuration to determine type (Python or Docker)
|
# Analyze existing MCP configuration to determine type (Python or Docker)
|
||||||
@@ -1133,9 +1159,9 @@ function Get-ExistingMcpConfigType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Navigate to zen configuration
|
# Navigate to pal configuration
|
||||||
$pathParts = $Client.ConfigJsonPath.Split('.')
|
$pathParts = $Client.ConfigJsonPath.Split('.')
|
||||||
$zenKey = $pathParts[-1]
|
$palKey = $pathParts[-1]
|
||||||
$parentPath = $pathParts[0..($pathParts.Length - 2)]
|
$parentPath = $pathParts[0..($pathParts.Length - 2)]
|
||||||
|
|
||||||
$targetObject = $content
|
$targetObject = $content
|
||||||
@@ -1150,32 +1176,32 @@ function Get-ExistingMcpConfigType {
|
|||||||
$targetObject = $targetObject.$key
|
$targetObject = $targetObject.$key
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$targetObject.PSObject.Properties[$zenKey]) {
|
if (!$targetObject.PSObject.Properties[$palKey]) {
|
||||||
return @{
|
return @{
|
||||||
Exists = $false
|
Exists = $false
|
||||||
Type = "None"
|
Type = "None"
|
||||||
Details = "Zen configuration not found"
|
Details = "PAL configuration not found"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$zenConfig = $targetObject.$zenKey
|
$palConfig = $targetObject.$palKey
|
||||||
|
|
||||||
# Analyze configuration type
|
# Analyze configuration type
|
||||||
if ($zenConfig.command -eq "docker") {
|
if ($palConfig.command -eq "docker") {
|
||||||
$dockerType = "Unknown"
|
$dockerType = "Unknown"
|
||||||
$details = "Docker configuration"
|
$details = "Docker configuration"
|
||||||
|
|
||||||
if ($zenConfig.args -and $zenConfig.args.Count -gt 0) {
|
if ($palConfig.args -and $palConfig.args.Count -gt 0) {
|
||||||
if ($zenConfig.args[0] -eq "run") {
|
if ($palConfig.args[0] -eq "run") {
|
||||||
$dockerType = "Docker Run"
|
$dockerType = "Docker Run"
|
||||||
$details = "Docker run (dedicated container)"
|
$details = "Docker run (dedicated container)"
|
||||||
}
|
}
|
||||||
elseif ($zenConfig.args[0] -eq "exec") {
|
elseif ($palConfig.args[0] -eq "exec") {
|
||||||
$dockerType = "Docker Exec"
|
$dockerType = "Docker Exec"
|
||||||
$details = "Docker exec (existing container)"
|
$details = "Docker exec (existing container)"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$details = "Docker ($($zenConfig.args[0]))"
|
$details = "Docker ($($palConfig.args[0]))"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1184,18 +1210,18 @@ function Get-ExistingMcpConfigType {
|
|||||||
Type = "Docker"
|
Type = "Docker"
|
||||||
SubType = $dockerType
|
SubType = $dockerType
|
||||||
Details = $details
|
Details = $details
|
||||||
Command = $zenConfig.command
|
Command = $palConfig.command
|
||||||
Args = $zenConfig.args
|
Args = $palConfig.args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ($zenConfig.command -and $zenConfig.command.EndsWith("python.exe")) {
|
elseif ($palConfig.command -and $palConfig.command.EndsWith("python.exe")) {
|
||||||
$pythonType = "Python"
|
$pythonType = "Python"
|
||||||
$details = "Python virtual environment"
|
$details = "Python virtual environment"
|
||||||
|
|
||||||
if ($zenConfig.command.Contains(".zen_venv")) {
|
if ($palConfig.command.Contains(".pal_venv")) {
|
||||||
$details = "Python (zen virtual environment)"
|
$details = "Python (pal virtual environment)"
|
||||||
}
|
}
|
||||||
elseif ($zenConfig.command.Contains("venv")) {
|
elseif ($palConfig.command.Contains("venv")) {
|
||||||
$details = "Python (virtual environment)"
|
$details = "Python (virtual environment)"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1207,17 +1233,17 @@ function Get-ExistingMcpConfigType {
|
|||||||
Type = "Python"
|
Type = "Python"
|
||||||
SubType = $pythonType
|
SubType = $pythonType
|
||||||
Details = $details
|
Details = $details
|
||||||
Command = $zenConfig.command
|
Command = $palConfig.command
|
||||||
Args = $zenConfig.args
|
Args = $palConfig.args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return @{
|
return @{
|
||||||
Exists = $true
|
Exists = $true
|
||||||
Type = "Unknown"
|
Type = "Unknown"
|
||||||
Details = "Unknown configuration type: $($zenConfig.command)"
|
Details = "Unknown configuration type: $($palConfig.command)"
|
||||||
Command = $zenConfig.command
|
Command = $palConfig.command
|
||||||
Args = $zenConfig.args
|
Args = $palConfig.args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1337,7 +1363,7 @@ function Configure-McpClient {
|
|||||||
$newConfigType = if ($UseDocker) { "Docker" } else { "Python" }
|
$newConfigType = if ($UseDocker) { "Docker" } else { "Python" }
|
||||||
|
|
||||||
if ($existingConfig.Exists) {
|
if ($existingConfig.Exists) {
|
||||||
Write-Info "Found existing Zen MCP configuration in $($Client.Name)"
|
Write-Info "Found existing PAL MCP configuration in $($Client.Name)"
|
||||||
Write-Info " Current: $($existingConfig.Details)"
|
Write-Info " Current: $($existingConfig.Details)"
|
||||||
Write-Info " New: $newConfigType configuration"
|
Write-Info " New: $newConfigType configuration"
|
||||||
|
|
||||||
@@ -1360,7 +1386,7 @@ function Configure-McpClient {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# User confirmation for new installation
|
# User confirmation for new installation
|
||||||
$response = Read-Host "`nConfigure Zen MCP for $($Client.Name) (mode: $newConfigType)? (y/N)"
|
$response = Read-Host "`nConfigure PAL MCP for $($Client.Name) (mode: $newConfigType)? (y/N)"
|
||||||
if ($response -ne 'y' -and $response -ne 'Y') {
|
if ($response -ne 'y' -and $response -ne 'Y') {
|
||||||
Write-Info "Skipping $($Client.Name) integration"
|
Write-Info "Skipping $($Client.Name) integration"
|
||||||
return
|
return
|
||||||
@@ -1429,7 +1455,7 @@ function Configure-McpClient {
|
|||||||
|
|
||||||
# Navigate and set configuration
|
# Navigate and set configuration
|
||||||
$pathParts = $Client.ConfigJsonPath.Split('.')
|
$pathParts = $Client.ConfigJsonPath.Split('.')
|
||||||
$zenKey = $pathParts[-1]
|
$palKey = $pathParts[-1]
|
||||||
$parentPath = $pathParts[0..($pathParts.Length - 2)]
|
$parentPath = $pathParts[0..($pathParts.Length - 2)]
|
||||||
|
|
||||||
$targetObject = $config
|
$targetObject = $config
|
||||||
@@ -1440,7 +1466,13 @@ function Configure-McpClient {
|
|||||||
$targetObject = $targetObject.$key
|
$targetObject = $targetObject.$key
|
||||||
}
|
}
|
||||||
|
|
||||||
$targetObject | Add-Member -MemberType NoteProperty -Name $zenKey -Value $serverConfig -Force
|
# Remove legacy zen entries to avoid duplicate or broken MCP servers
|
||||||
|
$legacyRemoved = Remove-LegacyServerKeys $targetObject
|
||||||
|
if ($legacyRemoved) {
|
||||||
|
Write-Info "Removed legacy MCP entries (zen → pal)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetObject | Add-Member -MemberType NoteProperty -Name $palKey -Value $serverConfig -Force
|
||||||
|
|
||||||
# Write config
|
# Write config
|
||||||
$config | ConvertTo-Json -Depth 10 | Out-File $configPath -Encoding UTF8
|
$config | ConvertTo-Json -Depth 10 | Out-File $configPath -Encoding UTF8
|
||||||
@@ -1488,26 +1520,30 @@ function Test-ClaudeCliIntegration {
|
|||||||
|
|
||||||
Write-Info "Claude CLI detected - checking configuration..."
|
Write-Info "Claude CLI detected - checking configuration..."
|
||||||
|
|
||||||
|
foreach ($legacy in $script:LegacyServerNames) {
|
||||||
|
try { claude mcp remove -s user $legacy 2>$null | Out-Null } catch {}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$claudeConfig = claude mcp list 2>$null
|
$claudeConfig = claude mcp list 2>$null
|
||||||
if ($claudeConfig -match "zen") {
|
if ($claudeConfig -match "pal") {
|
||||||
Write-Success "Claude CLI already configured for zen server"
|
Write-Success "Claude CLI already configured for pal server"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Write-Info "To add zen server to Claude CLI, run:"
|
Write-Info "To add pal server to Claude CLI, run:"
|
||||||
Write-Host " claude mcp add -s user zen $PythonPath $ServerPath" -ForegroundColor Cyan
|
Write-Host " claude mcp add -s user pal $PythonPath $ServerPath" -ForegroundColor Cyan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Info "To configure Claude CLI manually, run:"
|
Write-Info "To configure Claude CLI manually, run:"
|
||||||
Write-Host " claude mcp add -s user zen $PythonPath $ServerPath" -ForegroundColor Cyan
|
Write-Host " claude mcp add -s user pal $PythonPath $ServerPath" -ForegroundColor Cyan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Test-GeminiCliIntegration {
|
function Test-GeminiCliIntegration {
|
||||||
param([string]$ScriptDir)
|
param([string]$ScriptDir)
|
||||||
|
|
||||||
$zenWrapper = Join-Path $ScriptDir "zen-mcp-server.cmd"
|
$palWrapper = Join-Path $ScriptDir "pal-mcp-server.cmd"
|
||||||
|
|
||||||
# Check if Gemini settings file exists (Windows path)
|
# Check if Gemini settings file exists (Windows path)
|
||||||
$geminiConfig = "$env:USERPROFILE\.gemini\settings.json"
|
$geminiConfig = "$env:USERPROFILE\.gemini\settings.json"
|
||||||
@@ -1515,34 +1551,76 @@ function Test-GeminiCliIntegration {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if zen is already configured
|
# Load existing config
|
||||||
|
$config = @{}
|
||||||
$configContent = Get-Content $geminiConfig -Raw -ErrorAction SilentlyContinue
|
$configContent = Get-Content $geminiConfig -Raw -ErrorAction SilentlyContinue
|
||||||
if ($configContent -and $configContent -match '"zen"') {
|
if ($configContent) {
|
||||||
|
try { $config = $configContent | ConvertFrom-Json -ErrorAction Stop } catch { $config = @{} }
|
||||||
|
}
|
||||||
|
if ($null -eq $config -or $config -isnot [System.Collections.IDictionary]) {
|
||||||
|
$config = @{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $config.mcpServers -or $config.mcpServers -isnot [System.Collections.IDictionary]) {
|
||||||
|
$config.mcpServers = [ordered]@{}
|
||||||
|
}
|
||||||
|
|
||||||
|
$legacyRemoved = Remove-LegacyServerKeys $config.mcpServers
|
||||||
|
$palConfig = $config.mcpServers.pal
|
||||||
|
$needsWrite = $legacyRemoved
|
||||||
|
|
||||||
|
if ($palConfig) {
|
||||||
|
if ($palConfig.command -ne $palWrapper) {
|
||||||
|
$palConfig.command = $palWrapper
|
||||||
|
$needsWrite = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Test-Path $palWrapper)) {
|
||||||
|
Write-Info "Creating wrapper script for Gemini CLI..."
|
||||||
|
@"
|
||||||
|
@echo off
|
||||||
|
cd /d "%~dp0"
|
||||||
|
if exist ".pal_venv\Scripts\python.exe" (
|
||||||
|
.pal_venv\Scripts\python.exe server.py %*
|
||||||
|
) else (
|
||||||
|
python server.py %*
|
||||||
|
)
|
||||||
|
"@ | Out-File -FilePath $palWrapper -Encoding ASCII
|
||||||
|
Write-Success "Created pal-mcp-server.cmd wrapper script"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($needsWrite) {
|
||||||
|
Manage-ConfigBackups -ConfigFilePath $geminiConfig | Out-Null
|
||||||
|
$config | ConvertTo-Json -Depth 10 | Out-File $geminiConfig -Encoding UTF8
|
||||||
|
Write-Success "Updated Gemini CLI configuration (cleaned legacy entries)"
|
||||||
|
Write-Host " Config: $geminiConfig" -ForegroundColor Gray
|
||||||
|
Write-Host " Restart Gemini CLI to use PAL MCP Server" -ForegroundColor Gray
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ask user if they want to add Zen to Gemini CLI
|
# Ask user if they want to add PAL to Gemini CLI
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
$response = Read-Host "Configure Zen for Gemini CLI? (y/N)"
|
$response = Read-Host "Configure PAL for Gemini CLI? (y/N)"
|
||||||
if ($response -ne 'y' -and $response -ne 'Y') {
|
if ($response -ne 'y' -and $response -ne 'Y') {
|
||||||
Write-Info "Skipping Gemini CLI integration"
|
Write-Info "Skipping Gemini CLI integration"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure wrapper script exists
|
# Ensure wrapper script exists
|
||||||
if (!(Test-Path $zenWrapper)) {
|
if (!(Test-Path $palWrapper)) {
|
||||||
Write-Info "Creating wrapper script for Gemini CLI..."
|
Write-Info "Creating wrapper script for Gemini CLI..."
|
||||||
@"
|
@"
|
||||||
@echo off
|
@echo off
|
||||||
cd /d "%~dp0"
|
cd /d "%~dp0"
|
||||||
if exist ".zen_venv\Scripts\python.exe" (
|
if exist ".pal_venv\Scripts\python.exe" (
|
||||||
.zen_venv\Scripts\python.exe server.py %*
|
.pal_venv\Scripts\python.exe server.py %*
|
||||||
) else (
|
) else (
|
||||||
python server.py %*
|
python server.py %*
|
||||||
)
|
)
|
||||||
"@ | Out-File -FilePath $zenWrapper -Encoding ASCII
|
"@ | Out-File -FilePath $palWrapper -Encoding ASCII
|
||||||
|
|
||||||
Write-Success "Created zen-mcp-server.cmd wrapper script"
|
Write-Success "Created pal-mcp-server.cmd wrapper script"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update Gemini settings
|
# Update Gemini settings
|
||||||
@@ -1552,30 +1630,24 @@ if exist ".zen_venv\Scripts\python.exe" (
|
|||||||
# Create backup with retention management
|
# Create backup with retention management
|
||||||
$backupPath = Manage-ConfigBackups $geminiConfig
|
$backupPath = Manage-ConfigBackups $geminiConfig
|
||||||
|
|
||||||
# Read existing config or create new one
|
|
||||||
$config = @{}
|
|
||||||
if (Test-Path $geminiConfig) {
|
|
||||||
$config = Get-Content $geminiConfig -Raw | ConvertFrom-Json
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ensure mcpServers exists
|
# Ensure mcpServers exists
|
||||||
if (!$config.mcpServers) {
|
if (-not $config.mcpServers -or $config.mcpServers -isnot [System.Collections.IDictionary]) {
|
||||||
$config | Add-Member -MemberType NoteProperty -Name "mcpServers" -Value @{} -Force
|
$config.mcpServers = [ordered]@{}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add zen server
|
# Add pal server
|
||||||
$zenConfig = @{
|
$palConfig = @{
|
||||||
command = $zenWrapper
|
command = $palWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
$config.mcpServers | Add-Member -MemberType NoteProperty -Name "zen" -Value $zenConfig -Force
|
$config.mcpServers | Add-Member -MemberType NoteProperty -Name "pal" -Value $palConfig -Force
|
||||||
|
|
||||||
# Write updated config
|
# Write updated config
|
||||||
$config | ConvertTo-Json -Depth 10 | Out-File $geminiConfig -Encoding UTF8
|
$config | ConvertTo-Json -Depth 10 | Out-File $geminiConfig -Encoding UTF8
|
||||||
|
|
||||||
Write-Success "Successfully configured Gemini CLI"
|
Write-Success "Successfully configured Gemini CLI"
|
||||||
Write-Host " Config: $geminiConfig" -ForegroundColor Gray
|
Write-Host " Config: $geminiConfig" -ForegroundColor Gray
|
||||||
Write-Host " Restart Gemini CLI to use Zen MCP Server" -ForegroundColor Gray
|
Write-Host " Restart Gemini CLI to use PAL MCP Server" -ForegroundColor Gray
|
||||||
|
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
@@ -1586,8 +1658,8 @@ if exist ".zen_venv\Scripts\python.exe" (
|
|||||||
Write-Host @"
|
Write-Host @"
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$zenWrapper"
|
"command": "$palWrapper"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1615,7 +1687,7 @@ function Show-QwenManualConfig {
|
|||||||
|
|
||||||
Write-Host "{" -ForegroundColor Yellow
|
Write-Host "{" -ForegroundColor Yellow
|
||||||
Write-Host " \"mcpServers\": {" -ForegroundColor Yellow
|
Write-Host " \"mcpServers\": {" -ForegroundColor Yellow
|
||||||
Write-Host " \"zen\": {" -ForegroundColor Yellow
|
Write-Host " \"pal\": {" -ForegroundColor Yellow
|
||||||
Write-Host " \"command\": \"$PythonPath\"," -ForegroundColor Yellow
|
Write-Host " \"command\": \"$PythonPath\"," -ForegroundColor Yellow
|
||||||
Write-Host " \"args\": [\"$ServerPath\"]," -ForegroundColor Yellow
|
Write-Host " \"args\": [\"$ServerPath\"]," -ForegroundColor Yellow
|
||||||
Write-Host " \"cwd\": \"$ScriptDir\"," -ForegroundColor Yellow
|
Write-Host " \"cwd\": \"$ScriptDir\"," -ForegroundColor Yellow
|
||||||
@@ -1629,7 +1701,7 @@ function Show-QwenManualConfig {
|
|||||||
else {
|
else {
|
||||||
Write-Host "{" -ForegroundColor Yellow
|
Write-Host "{" -ForegroundColor Yellow
|
||||||
Write-Host " \"mcpServers\": {" -ForegroundColor Yellow
|
Write-Host " \"mcpServers\": {" -ForegroundColor Yellow
|
||||||
Write-Host " \"zen\": {" -ForegroundColor Yellow
|
Write-Host " \"pal\": {" -ForegroundColor Yellow
|
||||||
Write-Host " \"command\": \"$PythonPath\"," -ForegroundColor Yellow
|
Write-Host " \"command\": \"$PythonPath\"," -ForegroundColor Yellow
|
||||||
Write-Host " \"args\": [\"$ServerPath\"]," -ForegroundColor Yellow
|
Write-Host " \"args\": [\"$ServerPath\"]," -ForegroundColor Yellow
|
||||||
Write-Host " \"cwd\": \"$ScriptDir\"" -ForegroundColor Yellow
|
Write-Host " \"cwd\": \"$ScriptDir\"" -ForegroundColor Yellow
|
||||||
@@ -1653,6 +1725,8 @@ function Test-QwenCliIntegration {
|
|||||||
$scriptDir = Split-Path $ServerPath -Parent
|
$scriptDir = Split-Path $ServerPath -Parent
|
||||||
|
|
||||||
$configStatus = "missing"
|
$configStatus = "missing"
|
||||||
|
$legacyRemoved = $false
|
||||||
|
$skipPrompt = $false
|
||||||
$config = @{}
|
$config = @{}
|
||||||
|
|
||||||
if (Test-Path $configPath) {
|
if (Test-Path $configPath) {
|
||||||
@@ -1668,11 +1742,12 @@ function Test-QwenCliIntegration {
|
|||||||
|
|
||||||
if ($config.ContainsKey('mcpServers') -and $config['mcpServers'] -is [System.Collections.IDictionary]) {
|
if ($config.ContainsKey('mcpServers') -and $config['mcpServers'] -is [System.Collections.IDictionary]) {
|
||||||
$servers = $config['mcpServers']
|
$servers = $config['mcpServers']
|
||||||
if ($servers.Contains('zen') -and $servers['zen'] -is [System.Collections.IDictionary]) {
|
$legacyRemoved = (Remove-LegacyServerKeys $servers) -or $legacyRemoved
|
||||||
$zenConfig = $servers['zen']
|
if ($servers.Contains('pal') -and $servers['pal'] -is [System.Collections.IDictionary]) {
|
||||||
$commandMatches = ($zenConfig['command'] -eq $PythonPath)
|
$palConfig = $servers['pal']
|
||||||
|
$commandMatches = ($palConfig['command'] -eq $PythonPath)
|
||||||
|
|
||||||
$argsValue = $zenConfig['args']
|
$argsValue = $palConfig['args']
|
||||||
$argsList = @()
|
$argsList = @()
|
||||||
if ($argsValue -is [System.Collections.IEnumerable] -and $argsValue -isnot [string]) {
|
if ($argsValue -is [System.Collections.IEnumerable] -and $argsValue -isnot [string]) {
|
||||||
$argsList = @($argsValue)
|
$argsList = @($argsValue)
|
||||||
@@ -1683,18 +1758,18 @@ function Test-QwenCliIntegration {
|
|||||||
$argsMatches = ($argsList.Count -eq 1 -and $argsList[0] -eq $ServerPath)
|
$argsMatches = ($argsList.Count -eq 1 -and $argsList[0] -eq $ServerPath)
|
||||||
|
|
||||||
$cwdValue = $null
|
$cwdValue = $null
|
||||||
if ($zenConfig.Contains('cwd')) {
|
if ($palConfig.Contains('cwd')) {
|
||||||
$cwdValue = $zenConfig['cwd']
|
$cwdValue = $palConfig['cwd']
|
||||||
}
|
}
|
||||||
$cwdMatches = ([string]::IsNullOrEmpty($cwdValue) -or $cwdValue -eq $scriptDir)
|
$cwdMatches = ([string]::IsNullOrEmpty($cwdValue) -or $cwdValue -eq $scriptDir)
|
||||||
|
|
||||||
if ($commandMatches -and $argsMatches -and $cwdMatches) {
|
if ($commandMatches -and $argsMatches -and $cwdMatches) {
|
||||||
Write-Success "Qwen CLI already configured for zen server"
|
$configStatus = $legacyRemoved ? "cleanup" : "match"
|
||||||
return
|
}
|
||||||
|
else {
|
||||||
|
$configStatus = "mismatch"
|
||||||
|
Write-Warning "Existing Qwen CLI configuration differs from the current setup."
|
||||||
}
|
}
|
||||||
|
|
||||||
$configStatus = "mismatch"
|
|
||||||
Write-Warning "Existing Qwen CLI configuration differs from the current setup."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1735,7 +1810,7 @@ function Test-QwenCliIntegration {
|
|||||||
"AZURE_OPENAI_API_KEY", "AZURE_OPENAI_ENDPOINT", "AZURE_OPENAI_API_VERSION", "AZURE_OPENAI_ALLOWED_MODELS", "AZURE_MODELS_CONFIG_PATH",
|
"AZURE_OPENAI_API_KEY", "AZURE_OPENAI_ENDPOINT", "AZURE_OPENAI_API_VERSION", "AZURE_OPENAI_ALLOWED_MODELS", "AZURE_MODELS_CONFIG_PATH",
|
||||||
"CUSTOM_API_URL", "CUSTOM_API_KEY", "CUSTOM_MODEL_NAME", "DEFAULT_MODEL", "GOOGLE_ALLOWED_MODELS",
|
"CUSTOM_API_URL", "CUSTOM_API_KEY", "CUSTOM_MODEL_NAME", "DEFAULT_MODEL", "GOOGLE_ALLOWED_MODELS",
|
||||||
"OPENAI_ALLOWED_MODELS", "OPENROUTER_ALLOWED_MODELS", "XAI_ALLOWED_MODELS", "DEFAULT_THINKING_MODE_THINKDEEP",
|
"OPENAI_ALLOWED_MODELS", "OPENROUTER_ALLOWED_MODELS", "XAI_ALLOWED_MODELS", "DEFAULT_THINKING_MODE_THINKDEEP",
|
||||||
"DISABLED_TOOLS", "CONVERSATION_TIMEOUT_HOURS", "MAX_CONVERSATION_TURNS", "LOG_LEVEL", "ZEN_MCP_FORCE_ENV_OVERRIDE"
|
"DISABLED_TOOLS", "CONVERSATION_TIMEOUT_HOURS", "MAX_CONVERSATION_TURNS", "LOG_LEVEL", "PAL_MCP_FORCE_ENV_OVERRIDE"
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($key in $extraKeys) {
|
foreach ($key in $extraKeys) {
|
||||||
@@ -1747,16 +1822,31 @@ function Test-QwenCliIntegration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$prompt = "Configure Zen for Qwen CLI? (y/N)"
|
if ($configStatus -eq "match") {
|
||||||
if ($configStatus -eq "mismatch" -or $configStatus -eq "invalid") {
|
Write-Success "Qwen CLI already configured for pal server"
|
||||||
$prompt = "Update Qwen CLI zen configuration? (y/N)"
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = Read-Host $prompt
|
if ($configStatus -eq "cleanup") {
|
||||||
if ($response -ne 'y' -and $response -ne 'Y') {
|
Write-Info "Removing legacy Qwen MCP entries from previous zen configuration..."
|
||||||
Write-Info "Skipping Qwen CLI integration"
|
$skipPrompt = $true
|
||||||
Show-QwenManualConfig $PythonPath $ServerPath $scriptDir $configPath $envMap
|
}
|
||||||
return
|
|
||||||
|
$prompt = "Configure PAL for Qwen CLI? (y/N)"
|
||||||
|
if ($configStatus -eq "cleanup") {
|
||||||
|
$prompt = "Remove legacy Qwen MCP entries and refresh configuration? (Y/n)"
|
||||||
|
}
|
||||||
|
elseif ($configStatus -eq "mismatch" -or $configStatus -eq "invalid") {
|
||||||
|
$prompt = "Update Qwen CLI pal configuration? (y/N)"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $skipPrompt) {
|
||||||
|
$response = Read-Host $prompt
|
||||||
|
if ($response -ne 'y' -and $response -ne 'Y') {
|
||||||
|
Write-Info "Skipping Qwen CLI integration"
|
||||||
|
Show-QwenManualConfig $PythonPath $ServerPath $scriptDir $configPath $envMap
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Test-Path $configDir)) {
|
if (!(Test-Path $configDir)) {
|
||||||
@@ -1776,24 +1866,24 @@ function Test-QwenCliIntegration {
|
|||||||
$config['mcpServers'] = @{}
|
$config['mcpServers'] = @{}
|
||||||
}
|
}
|
||||||
|
|
||||||
$zenConfig = [ordered]@{
|
$palConfig = [ordered]@{
|
||||||
command = $PythonPath
|
command = $PythonPath
|
||||||
args = @($ServerPath)
|
args = @($ServerPath)
|
||||||
cwd = $scriptDir
|
cwd = $scriptDir
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($envMap.Count -gt 0) {
|
if ($envMap.Count -gt 0) {
|
||||||
$zenConfig['env'] = $envMap
|
$palConfig['env'] = $envMap
|
||||||
}
|
}
|
||||||
|
|
||||||
$config['mcpServers']['zen'] = $zenConfig
|
$config['mcpServers']['pal'] = $palConfig
|
||||||
|
|
||||||
$json = ($config | ConvertTo-Json -Depth 20)
|
$json = ($config | ConvertTo-Json -Depth 20)
|
||||||
Set-Content -Path $configPath -Value $json -Encoding UTF8
|
Set-Content -Path $configPath -Value $json -Encoding UTF8
|
||||||
|
|
||||||
Write-Success "Successfully configured Qwen CLI"
|
Write-Success "Successfully configured Qwen CLI"
|
||||||
Write-Host " Config: $configPath" -ForegroundColor Gray
|
Write-Host " Config: $configPath" -ForegroundColor Gray
|
||||||
Write-Host " Restart Qwen CLI to use Zen MCP Server" -ForegroundColor Gray
|
Write-Host " Restart Qwen CLI to use PAL MCP Server" -ForegroundColor Gray
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Error "Failed to update Qwen CLI configuration: $_"
|
Write-Error "Failed to update Qwen CLI configuration: $_"
|
||||||
@@ -1813,7 +1903,7 @@ function Test-QwenCliIntegration {
|
|||||||
# Show script help
|
# Show script help
|
||||||
function Show-Help {
|
function Show-Help {
|
||||||
Write-Host @"
|
Write-Host @"
|
||||||
Zen MCP Server - Setup and Launch Script
|
PAL MCP Server - Setup and Launch Script
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
.\run-server.ps1 [OPTIONS]
|
.\run-server.ps1 [OPTIONS]
|
||||||
@@ -1838,17 +1928,17 @@ EXAMPLES:
|
|||||||
.\run-server.ps1 -Docker # Use Docker deployment
|
.\run-server.ps1 -Docker # Use Docker deployment
|
||||||
.\run-server.ps1 -Docker -Follow # Docker with log following
|
.\run-server.ps1 -Docker -Follow # Docker with log following
|
||||||
|
|
||||||
For more information, visit: https://github.com/BeehiveInnovations/zen-mcp-server
|
For more information, visit: https://github.com/BeehiveInnovations/pal-mcp-server
|
||||||
"@ -ForegroundColor White
|
"@ -ForegroundColor White
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show version information
|
# Show version information
|
||||||
function Show-Version {
|
function Show-Version {
|
||||||
$version = Get-Version
|
$version = Get-Version
|
||||||
Write-Host "Zen MCP Server version: $version" -ForegroundColor Green
|
Write-Host "PAL MCP Server version: $version" -ForegroundColor Green
|
||||||
Write-Host "PowerShell Setup Script for Windows" -ForegroundColor Cyan
|
Write-Host "PowerShell Setup Script for Windows" -ForegroundColor Cyan
|
||||||
Write-Host "Author: GiGiDKR (https://github.com/GiGiDKR)" -ForegroundColor Gray
|
Write-Host "Author: GiGiDKR (https://github.com/GiGiDKR)" -ForegroundColor Gray
|
||||||
Write-Host "Project: BeehiveInnovations/zen-mcp-server" -ForegroundColor Gray
|
Write-Host "Project: BeehiveInnovations/pal-mcp-server" -ForegroundColor Gray
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show configuration instructions
|
# Show configuration instructions
|
||||||
@@ -1886,7 +1976,7 @@ function Show-ConfigInstructions {
|
|||||||
Write-Host "✓ Qwen CLI" -ForegroundColor White
|
Write-Host "✓ Qwen CLI" -ForegroundColor White
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "The script automatically detects and configures compatible clients." -ForegroundColor Gray
|
Write-Host "The script automatically detects and configures compatible clients." -ForegroundColor Gray
|
||||||
Write-Host "Restart your MCP clients after configuration to use the Zen MCP Server." -ForegroundColor Yellow
|
Write-Host "Restart your MCP clients after configuration to use the PAL MCP Server." -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show setup instructions
|
# Show setup instructions
|
||||||
@@ -1900,11 +1990,11 @@ function Show-SetupInstructions {
|
|||||||
Write-Step "Setup Complete"
|
Write-Step "Setup Complete"
|
||||||
|
|
||||||
if ($UseDocker) {
|
if ($UseDocker) {
|
||||||
Write-Success "Zen MCP Server is configured for Docker deployment"
|
Write-Success "PAL MCP Server is configured for Docker deployment"
|
||||||
Write-Host "Docker command: docker exec -i zen-mcp-server python server.py" -ForegroundColor Cyan
|
Write-Host "Docker command: docker exec -i pal-mcp-server python server.py" -ForegroundColor Cyan
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Write-Success "Zen MCP Server is configured for Python virtual environment"
|
Write-Success "PAL MCP Server is configured for Python virtual environment"
|
||||||
Write-Host "Python: $PythonPath" -ForegroundColor Cyan
|
Write-Host "Python: $PythonPath" -ForegroundColor Cyan
|
||||||
Write-Host "Server: $ServerPath" -ForegroundColor Cyan
|
Write-Host "Server: $ServerPath" -ForegroundColor Cyan
|
||||||
}
|
}
|
||||||
@@ -1916,7 +2006,7 @@ function Show-SetupInstructions {
|
|||||||
|
|
||||||
# Start the server
|
# Start the server
|
||||||
function Start-Server {
|
function Start-Server {
|
||||||
Write-Step "Starting Zen MCP Server"
|
Write-Step "Starting PAL MCP Server"
|
||||||
|
|
||||||
$pythonPath = "$VENV_PATH\Scripts\python.exe"
|
$pythonPath = "$VENV_PATH\Scripts\python.exe"
|
||||||
if (!(Test-Path $pythonPath)) {
|
if (!(Test-Path $pythonPath)) {
|
||||||
@@ -2041,7 +2131,7 @@ function Import-EnvFile {
|
|||||||
# Docker deployment workflow
|
# Docker deployment workflow
|
||||||
function Invoke-DockerWorkflow {
|
function Invoke-DockerWorkflow {
|
||||||
Write-Step "Starting Docker Workflow"
|
Write-Step "Starting Docker Workflow"
|
||||||
Write-Host "Zen MCP Server" -ForegroundColor Green
|
Write-Host "PAL MCP Server" -ForegroundColor Green
|
||||||
Write-Host "=================" -ForegroundColor Cyan
|
Write-Host "=================" -ForegroundColor Cyan
|
||||||
|
|
||||||
$version = Get-Version
|
$version = Get-Version
|
||||||
@@ -2064,7 +2154,7 @@ function Invoke-DockerWorkflow {
|
|||||||
Show-SetupInstructions -UseDocker
|
Show-SetupInstructions -UseDocker
|
||||||
|
|
||||||
# Start Docker services
|
# Start Docker services
|
||||||
Write-Step "Starting Zen MCP Server"
|
Write-Step "Starting PAL MCP Server"
|
||||||
if ($Follow) {
|
if ($Follow) {
|
||||||
Write-Info "Starting server and following logs..."
|
Write-Info "Starting server and following logs..."
|
||||||
Start-DockerServices -Follow
|
Start-DockerServices -Follow
|
||||||
@@ -2074,7 +2164,7 @@ function Invoke-DockerWorkflow {
|
|||||||
if (!(Start-DockerServices)) { exit 1 }
|
if (!(Start-DockerServices)) { exit 1 }
|
||||||
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Success "Zen MCP Server is running in Docker!"
|
Write-Success "PAL MCP Server is running in Docker!"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
Write-Host "Next steps:" -ForegroundColor Cyan
|
Write-Host "Next steps:" -ForegroundColor Cyan
|
||||||
@@ -2083,7 +2173,7 @@ function Invoke-DockerWorkflow {
|
|||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Useful commands:" -ForegroundColor Cyan
|
Write-Host "Useful commands:" -ForegroundColor Cyan
|
||||||
Write-Host " View logs: " -NoNewline -ForegroundColor White
|
Write-Host " View logs: " -NoNewline -ForegroundColor White
|
||||||
Write-Host "docker logs -f zen-mcp-server" -ForegroundColor Yellow
|
Write-Host "docker logs -f pal-mcp-server" -ForegroundColor Yellow
|
||||||
Write-Host " Stop server: " -NoNewline -ForegroundColor White
|
Write-Host " Stop server: " -NoNewline -ForegroundColor White
|
||||||
Write-Host "docker-compose down" -ForegroundColor Yellow
|
Write-Host "docker-compose down" -ForegroundColor Yellow
|
||||||
Write-Host " Restart server: " -NoNewline -ForegroundColor White
|
Write-Host " Restart server: " -NoNewline -ForegroundColor White
|
||||||
@@ -2093,7 +2183,7 @@ function Invoke-DockerWorkflow {
|
|||||||
# Python virtual environment deployment workflow
|
# Python virtual environment deployment workflow
|
||||||
function Invoke-PythonWorkflow {
|
function Invoke-PythonWorkflow {
|
||||||
Write-Step "Starting Python Virtual Environment Workflow"
|
Write-Step "Starting Python Virtual Environment Workflow"
|
||||||
Write-Host "Zen MCP Server" -ForegroundColor Green
|
Write-Host "PAL MCP Server" -ForegroundColor Green
|
||||||
Write-Host "=================" -ForegroundColor Cyan
|
Write-Host "=================" -ForegroundColor Cyan
|
||||||
|
|
||||||
$version = Get-Version
|
$version = Get-Version
|
||||||
|
|||||||
385
run-server.sh
385
run-server.sh
@@ -2,7 +2,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Zen MCP Server Setup Script
|
# PAL MCP Server Setup Script
|
||||||
#
|
#
|
||||||
# A platform-agnostic setup script that works on macOS, Linux, and WSL.
|
# A platform-agnostic setup script that works on macOS, Linux, and WSL.
|
||||||
# Handles environment setup, dependency installation, and configuration.
|
# Handles environment setup, dependency installation, and configuration.
|
||||||
@@ -29,11 +29,12 @@ readonly RED='\033[0;31m'
|
|||||||
readonly NC='\033[0m' # No Color
|
readonly NC='\033[0m' # No Color
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
readonly VENV_PATH=".zen_venv"
|
readonly VENV_PATH=".pal_venv"
|
||||||
readonly DOCKER_CLEANED_FLAG=".docker_cleaned"
|
readonly DOCKER_CLEANED_FLAG=".docker_cleaned"
|
||||||
readonly DESKTOP_CONFIG_FLAG=".desktop_configured"
|
readonly DESKTOP_CONFIG_FLAG=".desktop_configured"
|
||||||
readonly LOG_DIR="logs"
|
readonly LOG_DIR="logs"
|
||||||
readonly LOG_FILE="mcp_server.log"
|
readonly LOG_FILE="mcp_server.log"
|
||||||
|
readonly LEGACY_MCP_NAMES=("zen" "zen-mcp" "zen-mcp-server" "zen_mcp" "zen_mcp_server")
|
||||||
|
|
||||||
# Determine portable arguments for sed -i (GNU vs BSD)
|
# Determine portable arguments for sed -i (GNU vs BSD)
|
||||||
declare -a SED_INPLACE_ARGS
|
declare -a SED_INPLACE_ARGS
|
||||||
@@ -753,7 +754,7 @@ setup_venv() {
|
|||||||
print_error "Permission denied creating virtual environment"
|
print_error "Permission denied creating virtual environment"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Try running in a different directory:"
|
echo "Try running in a different directory:"
|
||||||
echo " cd ~ && git clone <repository-url> && cd zen-mcp-server && ./run-server.sh"
|
echo " cd ~ && git clone <repository-url> && cd pal-mcp-server && ./run-server.sh"
|
||||||
echo ""
|
echo ""
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
@@ -960,7 +961,7 @@ install_dependencies() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
print_info "Setting up Zen MCP Server..."
|
print_info "Setting up PAL MCP Server..."
|
||||||
echo "Installing required components:"
|
echo "Installing required components:"
|
||||||
echo " • MCP protocol library"
|
echo " • MCP protocol library"
|
||||||
echo " • AI model connectors"
|
echo " • AI model connectors"
|
||||||
@@ -1254,7 +1255,7 @@ check_claude_cli_integration() {
|
|||||||
echo ""
|
echo ""
|
||||||
print_warning "Claude CLI not found"
|
print_warning "Claude CLI not found"
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Would you like to add Zen to Claude Code? (Y/n): " -n 1 -r
|
read -p "Would you like to add PAL to Claude Code? (Y/n): " -n 1 -r
|
||||||
echo ""
|
echo ""
|
||||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
print_info "Skipping Claude Code integration"
|
print_info "Skipping Claude Code integration"
|
||||||
@@ -1269,9 +1270,14 @@ check_claude_cli_integration() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if zen is registered
|
# Remove legacy zen registrations to avoid duplicate errors after rename
|
||||||
|
for legacy_name in "${LEGACY_MCP_NAMES[@]}"; do
|
||||||
|
claude mcp remove "$legacy_name" -s user >/dev/null 2>&1 || true
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if pal is registered
|
||||||
local mcp_list=$(claude mcp list 2>/dev/null)
|
local mcp_list=$(claude mcp list 2>/dev/null)
|
||||||
if echo "$mcp_list" | grep -q "zen"; then
|
if echo "$mcp_list" | grep -q "pal"; then
|
||||||
# Check if it's using the old Docker command
|
# Check if it's using the old Docker command
|
||||||
if echo "$mcp_list" | grep -E "zen.*docker|zen.*compose" &>/dev/null; then
|
if echo "$mcp_list" | grep -E "zen.*docker|zen.*compose" &>/dev/null; then
|
||||||
print_warning "Found old Docker-based Zen registration, updating..."
|
print_warning "Found old Docker-based Zen registration, updating..."
|
||||||
@@ -1290,14 +1296,14 @@ check_claude_cli_integration() {
|
|||||||
done <<< "$env_vars"
|
done <<< "$env_vars"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local claude_cmd="claude mcp add zen -s user$env_args -- \"$python_cmd\" \"$server_path\""
|
local claude_cmd="claude mcp add pal -s user$env_args -- \"$python_cmd\" \"$server_path\""
|
||||||
if eval "$claude_cmd" 2>/dev/null; then
|
if eval "$claude_cmd" 2>/dev/null; then
|
||||||
print_success "Updated Zen to become a standalone script with environment variables"
|
print_success "Updated PAL to become a standalone script with environment variables"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "Failed to update MCP registration. Please run manually:"
|
echo "Failed to update MCP registration. Please run manually:"
|
||||||
echo " claude mcp remove zen -s user"
|
echo " claude mcp remove pal -s user"
|
||||||
echo " $claude_cmd"
|
echo " $claude_cmd"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -1307,8 +1313,8 @@ check_claude_cli_integration() {
|
|||||||
if echo "$mcp_list" | grep -F "$server_path" &>/dev/null; then
|
if echo "$mcp_list" | grep -F "$server_path" &>/dev/null; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
print_warning "Zen registered with different path, updating..."
|
print_warning "PAL registered with different path, updating..."
|
||||||
claude mcp remove zen -s user 2>/dev/null || true
|
claude mcp remove pal -s user 2>/dev/null || true
|
||||||
|
|
||||||
# Re-add with current path and environment variables
|
# Re-add with current path and environment variables
|
||||||
local env_vars=$(parse_env_variables)
|
local env_vars=$(parse_env_variables)
|
||||||
@@ -1323,14 +1329,14 @@ check_claude_cli_integration() {
|
|||||||
done <<< "$env_vars"
|
done <<< "$env_vars"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local claude_cmd="claude mcp add zen -s user$env_args -- \"$python_cmd\" \"$server_path\""
|
local claude_cmd="claude mcp add pal -s user$env_args -- \"$python_cmd\" \"$server_path\""
|
||||||
if eval "$claude_cmd" 2>/dev/null; then
|
if eval "$claude_cmd" 2>/dev/null; then
|
||||||
print_success "Updated Zen with current path and environment variables"
|
print_success "Updated PAL with current path and environment variables"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "Failed to update MCP registration. Please run manually:"
|
echo "Failed to update MCP registration. Please run manually:"
|
||||||
echo " claude mcp remove zen -s user"
|
echo " claude mcp remove pal -s user"
|
||||||
echo " $claude_cmd"
|
echo " $claude_cmd"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -1339,7 +1345,7 @@ check_claude_cli_integration() {
|
|||||||
else
|
else
|
||||||
# Not registered at all, ask user if they want to add it
|
# Not registered at all, ask user if they want to add it
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Add Zen to Claude Code? (Y/n): " -n 1 -r
|
read -p "Add PAL to Claude Code? (Y/n): " -n 1 -r
|
||||||
echo ""
|
echo ""
|
||||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
local env_vars=$(parse_env_variables)
|
local env_vars=$(parse_env_variables)
|
||||||
@@ -1355,11 +1361,11 @@ check_claude_cli_integration() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_info "To add manually later, run:"
|
print_info "To add manually later, run:"
|
||||||
echo " claude mcp add zen -s user$env_args -- $python_cmd $server_path"
|
echo " claude mcp add pal -s user$env_args -- $python_cmd $server_path"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
print_info "Registering Zen with Claude Code..."
|
print_info "Registering PAL with Claude Code..."
|
||||||
|
|
||||||
# Add with environment variables
|
# Add with environment variables
|
||||||
local env_vars=$(parse_env_variables)
|
local env_vars=$(parse_env_variables)
|
||||||
@@ -1374,9 +1380,9 @@ check_claude_cli_integration() {
|
|||||||
done <<< "$env_vars"
|
done <<< "$env_vars"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local claude_cmd="claude mcp add zen -s user$env_args -- \"$python_cmd\" \"$server_path\""
|
local claude_cmd="claude mcp add pal -s user$env_args -- \"$python_cmd\" \"$server_path\""
|
||||||
if eval "$claude_cmd" 2>/dev/null; then
|
if eval "$claude_cmd" 2>/dev/null; then
|
||||||
print_success "Successfully added Zen to Claude Code with environment variables"
|
print_success "Successfully added PAL to Claude Code with environment variables"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
@@ -1403,8 +1409,12 @@ check_claude_desktop_integration() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Legacy MCP server names to clean out from previous releases
|
||||||
|
local legacy_names_csv
|
||||||
|
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Configure Zen for Claude Desktop? (Y/n): " -n 1 -r
|
read -p "Configure PAL for Claude Desktop? (Y/n): " -n 1 -r
|
||||||
echo ""
|
echo ""
|
||||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
print_info "Skipping Claude Desktop integration"
|
print_info "Skipping Claude Desktop integration"
|
||||||
@@ -1421,12 +1431,12 @@ check_claude_desktop_integration() {
|
|||||||
print_info "Updating existing Claude Desktop config..."
|
print_info "Updating existing Claude Desktop config..."
|
||||||
|
|
||||||
# Check for old Docker config and remove it
|
# Check for old Docker config and remove it
|
||||||
if grep -q "docker.*compose.*zen\|zen.*docker" "$config_path" 2>/dev/null; then
|
if grep -q "docker.*compose.*pal\|pal.*docker" "$config_path" 2>/dev/null; then
|
||||||
print_warning "Removing old Docker-based MCP configuration..."
|
print_warning "Removing old Docker-based MCP configuration..."
|
||||||
# Create backup
|
# Create backup
|
||||||
cp "$config_path" "${config_path}.backup_$(date +%Y%m%d_%H%M%S)"
|
cp "$config_path" "${config_path}.backup_$(date +%Y%m%d_%H%M%S)"
|
||||||
|
|
||||||
# Remove old zen config using a more robust approach
|
# Remove old pal config using a more robust approach
|
||||||
local temp_file=$(mktemp)
|
local temp_file=$(mktemp)
|
||||||
python3 -c "
|
python3 -c "
|
||||||
import json
|
import json
|
||||||
@@ -1436,10 +1446,10 @@ try:
|
|||||||
with open('$config_path', 'r') as f:
|
with open('$config_path', 'r') as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
|
|
||||||
# Remove zen from mcpServers if it exists
|
# Remove pal from mcpServers if it exists
|
||||||
if 'mcpServers' in config and 'zen' in config['mcpServers']:
|
if 'mcpServers' in config and 'pal' in config['mcpServers']:
|
||||||
del config['mcpServers']['zen']
|
del config['mcpServers']['pal']
|
||||||
print('Removed old zen MCP configuration')
|
print('Removed old pal MCP configuration')
|
||||||
|
|
||||||
with open('$temp_file', 'w') as f:
|
with open('$temp_file', 'w') as f:
|
||||||
json.dump(config, f, indent=2)
|
json.dump(config, f, indent=2)
|
||||||
@@ -1460,22 +1470,35 @@ except Exception as e:
|
|||||||
echo "$env_vars" > "$env_file"
|
echo "$env_vars" > "$env_file"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
python3 -c "
|
PAL_LEGACY_NAMES="$legacy_names_csv" python3 -c "
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
legacy_keys = [k for k in os.environ.get('PAL_LEGACY_NAMES', '').split(',') if k]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open('$config_path', 'r') as f:
|
with open('$config_path', 'r') as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
except:
|
except Exception:
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
if not isinstance(config, dict):
|
||||||
config = {}
|
config = {}
|
||||||
|
|
||||||
# Ensure mcpServers exists
|
# Ensure mcpServers exists
|
||||||
if 'mcpServers' not in config:
|
if 'mcpServers' not in config or not isinstance(config.get('mcpServers'), dict):
|
||||||
config['mcpServers'] = {}
|
config['mcpServers'] = {}
|
||||||
|
|
||||||
# Add zen server
|
# Remove legacy entries from any known server blocks
|
||||||
zen_config = {
|
for container in ('mcpServers', 'servers'):
|
||||||
|
servers = config.get(container)
|
||||||
|
if isinstance(servers, dict):
|
||||||
|
for key in legacy_keys:
|
||||||
|
servers.pop(key, None)
|
||||||
|
|
||||||
|
# Add pal server
|
||||||
|
pal_config = {
|
||||||
'command': '$python_cmd',
|
'command': '$python_cmd',
|
||||||
'args': ['$server_path']
|
'args': ['$server_path']
|
||||||
}
|
}
|
||||||
@@ -1489,13 +1512,13 @@ try:
|
|||||||
if '=' in line and line:
|
if '=' in line and line:
|
||||||
key, value = line.split('=', 1)
|
key, value = line.split('=', 1)
|
||||||
env_dict[key] = value
|
env_dict[key] = value
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if env_dict:
|
if env_dict:
|
||||||
zen_config['env'] = env_dict
|
pal_config['env'] = env_dict
|
||||||
|
|
||||||
config['mcpServers']['zen'] = zen_config
|
config['mcpServers']['pal'] = pal_config
|
||||||
|
|
||||||
with open('$temp_file', 'w') as f:
|
with open('$temp_file', 'w') as f:
|
||||||
json.dump(config, f, indent=2)
|
json.dump(config, f, indent=2)
|
||||||
@@ -1523,8 +1546,8 @@ import sys
|
|||||||
|
|
||||||
config = {'mcpServers': {}}
|
config = {'mcpServers': {}}
|
||||||
|
|
||||||
# Add zen server
|
# Add pal server
|
||||||
zen_config = {
|
pal_config = {
|
||||||
'command': '$python_cmd',
|
'command': '$python_cmd',
|
||||||
'args': ['$server_path']
|
'args': ['$server_path']
|
||||||
}
|
}
|
||||||
@@ -1542,9 +1565,9 @@ except:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if env_dict:
|
if env_dict:
|
||||||
zen_config['env'] = env_dict
|
pal_config['env'] = env_dict
|
||||||
|
|
||||||
config['mcpServers']['zen'] = zen_config
|
config['mcpServers']['pal'] = pal_config
|
||||||
|
|
||||||
with open('$temp_file', 'w') as f:
|
with open('$temp_file', 'w') as f:
|
||||||
json.dump(config, f, indent=2)
|
json.dump(config, f, indent=2)
|
||||||
@@ -1587,7 +1610,7 @@ with open('$temp_file', 'w') as f:
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$python_cmd",
|
"command": "$python_cmd",
|
||||||
"args": ["$server_path"]$(if [[ -n "$example_env" ]]; then echo ","; fi)$(if [[ -n "$example_env" ]]; then echo "
|
"args": ["$server_path"]$(if [[ -n "$example_env" ]]; then echo ","; fi)$(if [[ -n "$example_env" ]]; then echo "
|
||||||
\"env\": {
|
\"env\": {
|
||||||
@@ -1603,7 +1626,7 @@ EOF
|
|||||||
# Check and update Gemini CLI configuration
|
# Check and update Gemini CLI configuration
|
||||||
check_gemini_cli_integration() {
|
check_gemini_cli_integration() {
|
||||||
local script_dir="$1"
|
local script_dir="$1"
|
||||||
local zen_wrapper="$script_dir/zen-mcp-server"
|
local pal_wrapper="$script_dir/pal-mcp-server"
|
||||||
|
|
||||||
# Check if Gemini settings file exists
|
# Check if Gemini settings file exists
|
||||||
local gemini_config="$HOME/.gemini/settings.json"
|
local gemini_config="$HOME/.gemini/settings.json"
|
||||||
@@ -1612,15 +1635,75 @@ check_gemini_cli_integration() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if zen is already configured
|
# Clean up legacy zen entries and detect existing pal configuration
|
||||||
if grep -q '"zen"' "$gemini_config" 2>/dev/null; then
|
local legacy_names_csv
|
||||||
# Already configured
|
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
|
||||||
|
|
||||||
|
local gemini_status
|
||||||
|
gemini_status=$(
|
||||||
|
PAL_LEGACY_NAMES="$legacy_names_csv" PAL_WRAPPER="$pal_wrapper" PAL_GEMINI_CONFIG="$gemini_config" python3 - <<'PY' 2>/dev/null
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import sys
|
||||||
|
|
||||||
|
config_path = pathlib.Path(os.environ["PAL_GEMINI_CONFIG"])
|
||||||
|
legacy = [n for n in os.environ.get("PAL_LEGACY_NAMES", "").split(",") if n]
|
||||||
|
wrapper = os.environ["PAL_WRAPPER"]
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
has_pal = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = json.loads(config_path.read_text())
|
||||||
|
except Exception:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
if not isinstance(data, dict):
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
servers = data.get("mcpServers")
|
||||||
|
if not isinstance(servers, dict):
|
||||||
|
servers = {}
|
||||||
|
data["mcpServers"] = servers
|
||||||
|
|
||||||
|
for key in legacy:
|
||||||
|
if servers.pop(key, None) is not None:
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
pal_cfg = servers.get("pal")
|
||||||
|
if isinstance(pal_cfg, dict):
|
||||||
|
has_pal = True
|
||||||
|
if pal_cfg.get("command") != wrapper:
|
||||||
|
pal_cfg["command"] = wrapper
|
||||||
|
servers["pal"] = pal_cfg
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
config_path.write_text(json.dumps(data, indent=2))
|
||||||
|
|
||||||
|
status = ("CHANGED" if changed else "UNCHANGED") + ":" + ("HAS_PAL" if has_pal else "NO_PAL")
|
||||||
|
sys.stdout.write(status)
|
||||||
|
sys.exit(0)
|
||||||
|
PY
|
||||||
|
) || true
|
||||||
|
|
||||||
|
local gemini_changed=false
|
||||||
|
local gemini_has_pal=false
|
||||||
|
[[ "$gemini_status" == CHANGED:* ]] && gemini_changed=true
|
||||||
|
[[ "$gemini_status" == *:HAS_PAL ]] && gemini_has_pal=true
|
||||||
|
|
||||||
|
if [[ "$gemini_has_pal" == true ]]; then
|
||||||
|
if [[ "$gemini_changed" == true ]]; then
|
||||||
|
print_success "Removed legacy Gemini MCP entries"
|
||||||
|
fi
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ask user if they want to add Zen to Gemini CLI
|
# Ask user if they want to add PAL to Gemini CLI
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Configure Zen for Gemini CLI? (Y/n): " -n 1 -r
|
read -p "Configure PAL for Gemini CLI? (Y/n): " -n 1 -r
|
||||||
echo ""
|
echo ""
|
||||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
print_info "Skipping Gemini CLI integration"
|
print_info "Skipping Gemini CLI integration"
|
||||||
@@ -1628,17 +1711,17 @@ check_gemini_cli_integration() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure wrapper script exists
|
# Ensure wrapper script exists
|
||||||
if [[ ! -f "$zen_wrapper" ]]; then
|
if [[ ! -f "$pal_wrapper" ]]; then
|
||||||
print_info "Creating wrapper script for Gemini CLI..."
|
print_info "Creating wrapper script for Gemini CLI..."
|
||||||
cat > "$zen_wrapper" << 'EOF'
|
cat > "$pal_wrapper" << 'EOF'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Wrapper script for Gemini CLI compatibility
|
# Wrapper script for Gemini CLI compatibility
|
||||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
exec .zen_venv/bin/python server.py "$@"
|
exec .pal_venv/bin/python server.py "$@"
|
||||||
EOF
|
EOF
|
||||||
chmod +x "$zen_wrapper"
|
chmod +x "$pal_wrapper"
|
||||||
print_success "Created zen-mcp-server wrapper script"
|
print_success "Created pal-mcp-server wrapper script"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Update Gemini settings
|
# Update Gemini settings
|
||||||
@@ -1647,7 +1730,7 @@ EOF
|
|||||||
# Create backup
|
# Create backup
|
||||||
cp "$gemini_config" "${gemini_config}.backup_$(date +%Y%m%d_%H%M%S)"
|
cp "$gemini_config" "${gemini_config}.backup_$(date +%Y%m%d_%H%M%S)"
|
||||||
|
|
||||||
# Add zen configuration using Python for proper JSON handling
|
# Add pal configuration using Python for proper JSON handling
|
||||||
local temp_file=$(mktemp)
|
local temp_file=$(mktemp)
|
||||||
python3 -c "
|
python3 -c "
|
||||||
import json
|
import json
|
||||||
@@ -1661,9 +1744,9 @@ try:
|
|||||||
if 'mcpServers' not in config:
|
if 'mcpServers' not in config:
|
||||||
config['mcpServers'] = {}
|
config['mcpServers'] = {}
|
||||||
|
|
||||||
# Add zen server
|
# Add pal server
|
||||||
config['mcpServers']['zen'] = {
|
config['mcpServers']['pal'] = {
|
||||||
'command': '$zen_wrapper'
|
'command': '$pal_wrapper'
|
||||||
}
|
}
|
||||||
|
|
||||||
with open('$temp_file', 'w') as f:
|
with open('$temp_file', 'w') as f:
|
||||||
@@ -1677,7 +1760,7 @@ except Exception as e:
|
|||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
print_success "Successfully configured Gemini CLI"
|
print_success "Successfully configured Gemini CLI"
|
||||||
echo " Config: $gemini_config"
|
echo " Config: $gemini_config"
|
||||||
echo " Restart Gemini CLI to use Zen MCP Server"
|
echo " Restart Gemini CLI to use PAL MCP Server"
|
||||||
else
|
else
|
||||||
print_error "Failed to update Gemini CLI config"
|
print_error "Failed to update Gemini CLI config"
|
||||||
echo "Manual config location: $gemini_config"
|
echo "Manual config location: $gemini_config"
|
||||||
@@ -1685,8 +1768,8 @@ except Exception as e:
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$zen_wrapper"
|
"command": "$pal_wrapper"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1701,14 +1784,71 @@ check_codex_cli_integration() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local codex_config="$HOME/.codex/config.toml"
|
local codex_config="$HOME/.codex/config.toml"
|
||||||
local codex_has_zen=false
|
local legacy_names_csv
|
||||||
if [[ -f "$codex_config" ]] && grep -q '\[mcp_servers\.zen\]' "$codex_config" 2>/dev/null; then
|
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
|
||||||
codex_has_zen=true
|
|
||||||
|
if [[ -f "$codex_config" ]]; then
|
||||||
|
local codex_cleanup_status
|
||||||
|
codex_cleanup_status=$(
|
||||||
|
PAL_LEGACY_NAMES="$legacy_names_csv" PAL_CODEX_CONFIG="$codex_config" python3 - <<'PY' 2>/dev/null
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
config_path = pathlib.Path(os.environ["PAL_CODEX_CONFIG"])
|
||||||
|
legacy = [n for n in os.environ.get("PAL_LEGACY_NAMES", "").split(",") if n]
|
||||||
|
|
||||||
|
if not config_path.exists():
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
lines = config_path.read_text().splitlines()
|
||||||
|
output = []
|
||||||
|
skip = False
|
||||||
|
removed = False
|
||||||
|
section_re = re.compile(r"\s*\[([^\]]+)\]")
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
match = section_re.match(line)
|
||||||
|
if match:
|
||||||
|
header = match.group(1).strip()
|
||||||
|
parts = header.split(".")
|
||||||
|
is_legacy = False
|
||||||
|
if len(parts) >= 2 and parts[0] == "mcp_servers":
|
||||||
|
section_key = ".".join(parts[1:])
|
||||||
|
for name in legacy:
|
||||||
|
if section_key == name or section_key.startswith(name + "."):
|
||||||
|
is_legacy = True
|
||||||
|
break
|
||||||
|
skip = is_legacy
|
||||||
|
if is_legacy:
|
||||||
|
removed = True
|
||||||
|
continue
|
||||||
|
if not skip:
|
||||||
|
output.append(line)
|
||||||
|
|
||||||
|
if removed:
|
||||||
|
config_path.write_text("\n".join(output).rstrip() + ("\n" if output else ""))
|
||||||
|
sys.stdout.write("REMOVED")
|
||||||
|
else:
|
||||||
|
sys.stdout.write("UNCHANGED")
|
||||||
|
sys.exit(0)
|
||||||
|
PY
|
||||||
|
) || true
|
||||||
|
|
||||||
|
if [[ "$codex_cleanup_status" == "REMOVED" ]]; then
|
||||||
|
print_success "Removed legacy Codex MCP entries"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$codex_has_zen" == false ]]; then
|
local codex_has_pal=false
|
||||||
|
if [[ -f "$codex_config" ]] && grep -q '\[mcp_servers\.pal\]' "$codex_config" 2>/dev/null; then
|
||||||
|
codex_has_pal=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$codex_has_pal" == false ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
read -p "Configure Zen for Codex CLI? (Y/n): " -n 1 -r
|
read -p "Configure PAL for Codex CLI? (Y/n): " -n 1 -r
|
||||||
echo ""
|
echo ""
|
||||||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
print_info "Skipping Codex CLI integration"
|
print_info "Skipping Codex CLI integration"
|
||||||
@@ -1727,12 +1867,12 @@ check_codex_cli_integration() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
echo ""
|
echo ""
|
||||||
echo "[mcp_servers.zen]"
|
echo "[mcp_servers.pal]"
|
||||||
echo "command = \"bash\""
|
echo "command = \"bash\""
|
||||||
echo "args = [\"-c\", \"for p in \$(which uvx 2>/dev/null) \$HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"\$p\\\" ] && exec \\\"\$p\\\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1\"]"
|
echo "args = [\"-c\", \"for p in \$(which uvx 2>/dev/null) \$HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"\$p\\\" ] && exec \\\"\$p\\\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1\"]"
|
||||||
echo "tool_timeout_sec = 1200"
|
echo "tool_timeout_sec = 1200"
|
||||||
echo ""
|
echo ""
|
||||||
echo "[mcp_servers.zen.env]"
|
echo "[mcp_servers.pal.env]"
|
||||||
echo "PATH = \"/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin\""
|
echo "PATH = \"/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin\""
|
||||||
if [[ -n "$env_vars" ]]; then
|
if [[ -n "$env_vars" ]]; then
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
@@ -1752,12 +1892,12 @@ check_codex_cli_integration() {
|
|||||||
echo "Manual config location: $codex_config"
|
echo "Manual config location: $codex_config"
|
||||||
echo "Add this configuration:"
|
echo "Add this configuration:"
|
||||||
cat <<'CODExEOF'
|
cat <<'CODExEOF'
|
||||||
[mcp_servers.zen]
|
[mcp_servers.pal]
|
||||||
command = "sh"
|
command = "sh"
|
||||||
args = ["-c", "exec \$(which uvx 2>/dev/null || echo uvx) --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server"]
|
args = ["-c", "exec \$(which uvx 2>/dev/null || echo uvx) --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server"]
|
||||||
tool_timeout_sec = 1200
|
tool_timeout_sec = 1200
|
||||||
|
|
||||||
[mcp_servers.zen.env]
|
[mcp_servers.pal.env]
|
||||||
PATH = "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin"
|
PATH = "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -1779,16 +1919,16 @@ CODExEOF
|
|||||||
|
|
||||||
print_success "Successfully configured Codex CLI"
|
print_success "Successfully configured Codex CLI"
|
||||||
echo " Config: $codex_config"
|
echo " Config: $codex_config"
|
||||||
echo " Restart Codex CLI to use Zen MCP Server"
|
echo " Restart Codex CLI to use PAL MCP Server"
|
||||||
codex_has_zen=true
|
codex_has_pal=true
|
||||||
else
|
else
|
||||||
print_info "Codex CLI already configured; refreshing Codex settings..."
|
print_info "Codex CLI already configured; refreshing Codex settings..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$codex_has_zen" == true ]]; then
|
if [[ "$codex_has_pal" == true ]]; then
|
||||||
if ! grep -Eq '^\s*web_search_request\s*=' "$codex_config" 2>/dev/null; then
|
if ! grep -Eq '^\s*web_search_request\s*=' "$codex_config" 2>/dev/null; then
|
||||||
echo ""
|
echo ""
|
||||||
print_info "Web search requests let Codex pull fresh documentation for Zen's API lookup tooling."
|
print_info "Web search requests let Codex pull fresh documentation for PAL's API lookup tooling."
|
||||||
read -p "Enable Codex CLI web search requests? (Y/n): " -n 1 -r
|
read -p "Enable Codex CLI web search requests? (Y/n): " -n 1 -r
|
||||||
echo ""
|
echo ""
|
||||||
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
||||||
@@ -1923,7 +2063,7 @@ print_qwen_manual_instructions() {
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$python_cmd",
|
"command": "$python_cmd",
|
||||||
"args": ["$server_path"],
|
"args": ["$server_path"],
|
||||||
"cwd": "$script_dir",
|
"cwd": "$script_dir",
|
||||||
@@ -1936,7 +2076,7 @@ EOF
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$python_cmd",
|
"command": "$python_cmd",
|
||||||
"args": ["$server_path"],
|
"args": ["$server_path"],
|
||||||
"cwd": "$script_dir"
|
"cwd": "$script_dir"
|
||||||
@@ -1976,6 +2116,43 @@ check_qwen_cli_integration() {
|
|||||||
env_lines=$(printf '%s\n' "${env_array[@]}")
|
env_lines=$(printf '%s\n' "${env_array[@]}")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local legacy_names_csv
|
||||||
|
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
|
||||||
|
|
||||||
|
if [[ -f "$qwen_config" ]]; then
|
||||||
|
PAL_QWEN_LEGACY="$legacy_names_csv" PAL_QWEN_CONFIG="$qwen_config" python3 - <<'PYCLEANCONF' 2>/dev/null || true
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import sys
|
||||||
|
|
||||||
|
config_path = pathlib.Path(os.environ.get("PAL_QWEN_CONFIG", ""))
|
||||||
|
legacy = [n for n in os.environ.get("PAL_QWEN_LEGACY", "").split(",") if n]
|
||||||
|
|
||||||
|
if not config_path.exists():
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = json.loads(config_path.read_text(encoding="utf-8"))
|
||||||
|
except Exception:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if not isinstance(data, dict):
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
servers = data.get("mcpServers")
|
||||||
|
if isinstance(servers, dict):
|
||||||
|
removed = False
|
||||||
|
for key in legacy:
|
||||||
|
if servers.pop(key, None) is not None:
|
||||||
|
removed = True
|
||||||
|
if removed:
|
||||||
|
config_path.write_text(json.dumps(data, indent=2))
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
PYCLEANCONF
|
||||||
|
fi
|
||||||
|
|
||||||
local config_status=3
|
local config_status=3
|
||||||
if [[ -f "$qwen_config" ]]; then
|
if [[ -f "$qwen_config" ]]; then
|
||||||
if python3 - "$qwen_config" "$python_cmd" "$server_path" "$script_dir" <<'PYCONF'
|
if python3 - "$qwen_config" "$python_cmd" "$server_path" "$script_dir" <<'PYCONF'
|
||||||
@@ -1995,7 +2172,7 @@ servers = data.get('mcpServers')
|
|||||||
if not isinstance(servers, dict):
|
if not isinstance(servers, dict):
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
||||||
config = servers.get('zen')
|
config = servers.get('pal')
|
||||||
if not isinstance(config, dict):
|
if not isinstance(config, dict):
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
||||||
@@ -2026,14 +2203,14 @@ PYCONF
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
if [[ $config_status -eq 4 ]]; then
|
if [[ $config_status -eq 4 ]]; then
|
||||||
print_warning "Found existing Qwen CLI zen configuration with different settings."
|
print_warning "Found existing Qwen CLI pal configuration with different settings."
|
||||||
elif [[ $config_status -eq 5 ]]; then
|
elif [[ $config_status -eq 5 ]]; then
|
||||||
print_warning "Unable to parse Qwen CLI settings; replacing with a fresh entry may help."
|
print_warning "Unable to parse Qwen CLI settings; replacing with a fresh entry may help."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local prompt="Configure Zen for Qwen CLI? (Y/n): "
|
local prompt="Configure PAL for Qwen CLI? (Y/n): "
|
||||||
if [[ $config_status -eq 4 || $config_status -eq 5 ]]; then
|
if [[ $config_status -eq 4 || $config_status -eq 5 ]]; then
|
||||||
prompt="Update Qwen CLI zen configuration? (Y/n): "
|
prompt="Update Qwen CLI pal configuration? (Y/n): "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -p "$prompt" -n 1 -r
|
read -p "$prompt" -n 1 -r
|
||||||
@@ -2051,17 +2228,17 @@ PYCONF
|
|||||||
|
|
||||||
local update_output
|
local update_output
|
||||||
local update_status=0
|
local update_status=0
|
||||||
update_output=$(ZEN_QWEN_ENV="$env_lines" ZEN_QWEN_CMD="$python_cmd" ZEN_QWEN_ARG="$server_path" ZEN_QWEN_CWD="$script_dir" python3 - "$qwen_config" <<'PYUPDATE'
|
update_output=$(PAL_QWEN_ENV="$env_lines" PAL_QWEN_CMD="$python_cmd" PAL_QWEN_ARG="$server_path" PAL_QWEN_CWD="$script_dir" python3 - "$qwen_config" <<'PYUPDATE'
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
config_path = pathlib.Path(sys.argv[1])
|
config_path = pathlib.Path(sys.argv[1])
|
||||||
cmd = os.environ['ZEN_QWEN_CMD']
|
cmd = os.environ['PAL_QWEN_CMD']
|
||||||
arg = os.environ['ZEN_QWEN_ARG']
|
arg = os.environ['PAL_QWEN_ARG']
|
||||||
cwd = os.environ['ZEN_QWEN_CWD']
|
cwd = os.environ['PAL_QWEN_CWD']
|
||||||
env_lines = os.environ.get('ZEN_QWEN_ENV', '').splitlines()
|
env_lines = os.environ.get('PAL_QWEN_ENV', '').splitlines()
|
||||||
|
|
||||||
env_map = {}
|
env_map = {}
|
||||||
for line in env_lines:
|
for line in env_lines:
|
||||||
@@ -2088,16 +2265,16 @@ if not isinstance(servers, dict):
|
|||||||
servers = {}
|
servers = {}
|
||||||
data['mcpServers'] = servers
|
data['mcpServers'] = servers
|
||||||
|
|
||||||
zen_config = {
|
pal_config = {
|
||||||
'command': cmd,
|
'command': cmd,
|
||||||
'args': [arg],
|
'args': [arg],
|
||||||
'cwd': cwd,
|
'cwd': cwd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if env_map:
|
if env_map:
|
||||||
zen_config['env'] = env_map
|
pal_config['env'] = env_map
|
||||||
|
|
||||||
servers['zen'] = zen_config
|
servers['pal'] = pal_config
|
||||||
|
|
||||||
config_path.parent.mkdir(parents=True, exist_ok=True)
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
tmp_path = config_path.with_suffix(config_path.suffix + '.tmp')
|
tmp_path = config_path.with_suffix(config_path.suffix + '.tmp')
|
||||||
@@ -2111,7 +2288,7 @@ PYUPDATE
|
|||||||
if [[ $update_status -eq 0 ]]; then
|
if [[ $update_status -eq 0 ]]; then
|
||||||
print_success "Successfully configured Qwen CLI"
|
print_success "Successfully configured Qwen CLI"
|
||||||
echo " Config: $qwen_config"
|
echo " Config: $qwen_config"
|
||||||
echo " Restart Qwen CLI to use Zen MCP Server"
|
echo " Restart Qwen CLI to use PAL MCP Server"
|
||||||
else
|
else
|
||||||
print_error "Failed to update Qwen CLI config"
|
print_error "Failed to update Qwen CLI config"
|
||||||
if [[ -n "$update_output" ]]; then
|
if [[ -n "$update_output" ]]; then
|
||||||
@@ -2130,11 +2307,11 @@ display_config_instructions() {
|
|||||||
local script_dir=$(dirname "$server_path")
|
local script_dir=$(dirname "$server_path")
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
local config_header="ZEN MCP SERVER CONFIGURATION"
|
local config_header="PAL MCP SERVER CONFIGURATION"
|
||||||
echo "===== $config_header ====="
|
echo "===== $config_header ====="
|
||||||
printf '%*s\n' "$((${#config_header} + 12))" | tr ' ' '='
|
printf '%*s\n' "$((${#config_header} + 12))" | tr ' ' '='
|
||||||
echo ""
|
echo ""
|
||||||
echo "To use Zen MCP Server with your CLI clients:"
|
echo "To use PAL MCP Server with your CLI clients:"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
print_info "1. For Claude Code (CLI):"
|
print_info "1. For Claude Code (CLI):"
|
||||||
@@ -2148,7 +2325,7 @@ display_config_instructions() {
|
|||||||
fi
|
fi
|
||||||
done <<< "$env_vars"
|
done <<< "$env_vars"
|
||||||
fi
|
fi
|
||||||
echo -e " ${GREEN}claude mcp add zen -s user$env_args -- $python_cmd $server_path${NC}"
|
echo -e " ${GREEN}claude mcp add pal -s user$env_args -- $python_cmd $server_path${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
print_info "2. For Claude Desktop:"
|
print_info "2. For Claude Desktop:"
|
||||||
@@ -2179,7 +2356,7 @@ display_config_instructions() {
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$python_cmd",
|
"command": "$python_cmd",
|
||||||
"args": ["$server_path"],
|
"args": ["$server_path"],
|
||||||
"cwd": "$script_dir",
|
"cwd": "$script_dir",
|
||||||
@@ -2194,7 +2371,7 @@ EOF
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$python_cmd",
|
"command": "$python_cmd",
|
||||||
"args": ["$server_path"],
|
"args": ["$server_path"],
|
||||||
"cwd": "$script_dir"
|
"cwd": "$script_dir"
|
||||||
@@ -2222,8 +2399,8 @@ EOF
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$script_dir/zen-mcp-server"
|
"command": "$script_dir/pal-mcp-server"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2237,7 +2414,7 @@ EOF
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$python_cmd",
|
"command": "$python_cmd",
|
||||||
"args": ["$server_path"],
|
"args": ["$server_path"],
|
||||||
"cwd": "$script_dir",
|
"cwd": "$script_dir",
|
||||||
@@ -2252,7 +2429,7 @@ EOF
|
|||||||
cat << EOF
|
cat << EOF
|
||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen": {
|
"pal": {
|
||||||
"command": "$python_cmd",
|
"command": "$python_cmd",
|
||||||
"args": ["$server_path"],
|
"args": ["$server_path"],
|
||||||
"cwd": "$script_dir"
|
"cwd": "$script_dir"
|
||||||
@@ -2267,11 +2444,11 @@ EOF
|
|||||||
echo " Add this configuration to ~/.codex/config.toml:"
|
echo " Add this configuration to ~/.codex/config.toml:"
|
||||||
echo ""
|
echo ""
|
||||||
cat << EOF
|
cat << EOF
|
||||||
[mcp_servers.zen]
|
[mcp_servers.pal]
|
||||||
command = "bash"
|
command = "bash"
|
||||||
args = ["-c", "for p in \$(which uvx 2>/dev/null) \$HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"\$p\\\" ] && exec \\\"\$p\\\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1"]
|
args = ["-c", "for p in \$(which uvx 2>/dev/null) \$HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"\$p\\\" ] && exec \\\"\$p\\\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1"]
|
||||||
|
|
||||||
[mcp_servers.zen.env]
|
[mcp_servers.pal.env]
|
||||||
PATH = "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin"
|
PATH = "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin"
|
||||||
GEMINI_API_KEY = "your_gemini_api_key_here"
|
GEMINI_API_KEY = "your_gemini_api_key_here"
|
||||||
EOF
|
EOF
|
||||||
@@ -2288,7 +2465,7 @@ display_setup_instructions() {
|
|||||||
echo "===== $setup_header ====="
|
echo "===== $setup_header ====="
|
||||||
printf '%*s\n' "$((${#setup_header} + 12))" | tr ' ' '='
|
printf '%*s\n' "$((${#setup_header} + 12))" | tr ' ' '='
|
||||||
echo ""
|
echo ""
|
||||||
print_success "Zen is ready to use!"
|
print_success "PAL is ready to use!"
|
||||||
|
|
||||||
# Display enabled/disabled tools if DISABLED_TOOLS is configured
|
# Display enabled/disabled tools if DISABLED_TOOLS is configured
|
||||||
if [[ -n "${DISABLED_TOOLS:-}" ]]; then
|
if [[ -n "${DISABLED_TOOLS:-}" ]]; then
|
||||||
@@ -2368,7 +2545,7 @@ display_setup_instructions() {
|
|||||||
# Show help message
|
# Show help message
|
||||||
show_help() {
|
show_help() {
|
||||||
local version=$(get_version)
|
local version=$(get_version)
|
||||||
local header="🤖 Zen MCP Server v$version"
|
local header="🤖 PAL MCP Server v$version"
|
||||||
echo "$header"
|
echo "$header"
|
||||||
printf '%*s\n' "${#header}" | tr ' ' '='
|
printf '%*s\n' "${#header}" | tr ' ' '='
|
||||||
echo ""
|
echo ""
|
||||||
@@ -2389,7 +2566,7 @@ show_help() {
|
|||||||
echo " $0 --clear-cache Clear Python cache (fixes import issues)"
|
echo " $0 --clear-cache Clear Python cache (fixes import issues)"
|
||||||
echo ""
|
echo ""
|
||||||
echo "For more information, visit:"
|
echo "For more information, visit:"
|
||||||
echo " https://github.com/BeehiveInnovations/zen-mcp-server"
|
echo " https://github.com/BeehiveInnovations/pal-mcp-server"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show version only
|
# Show version only
|
||||||
@@ -2464,7 +2641,7 @@ main() {
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
# Display header
|
# Display header
|
||||||
local main_header="🤖 Zen MCP Server"
|
local main_header="🤖 PAL MCP Server"
|
||||||
echo "$main_header"
|
echo "$main_header"
|
||||||
printf '%*s\n' "${#main_header}" | tr ' ' '='
|
printf '%*s\n' "${#main_header}" | tr ' ' '='
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Integration test runner script for the Zen MCP server on Windows.
|
Integration test runner script for the PAL MCP server on Windows.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
This PowerShell script prepares and runs integration tests for the Zen MCP server:
|
This PowerShell script prepares and runs integration tests for the PAL MCP server:
|
||||||
- Sets up the test environment
|
- Sets up the test environment
|
||||||
- Installs required dependencies
|
- Installs required dependencies
|
||||||
- Runs automated integration tests
|
- Runs automated integration tests
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
Script Author : GiGiDKR (https://github.com/GiGiDKR)
|
Script Author : GiGiDKR (https://github.com/GiGiDKR)
|
||||||
Date : 07-05-2025
|
Date : 07-05-2025
|
||||||
Version : See config.py (__version__)
|
Version : See config.py (__version__)
|
||||||
References : https://github.com/BeehiveInnovations/zen-mcp-server
|
References : https://github.com/BeehiveInnovations/pal-mcp-server
|
||||||
#>
|
#>
|
||||||
#Requires -Version 5.1
|
#Requires -Version 5.1
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
@@ -64,13 +64,13 @@ function Write-Emoji {
|
|||||||
Write-ColorText $Text -Color $Color
|
Write-ColorText $Text -Color $Color
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Emoji "🧪" "Running Integration Tests for Zen MCP Server" -Color Cyan
|
Write-Emoji "🧪" "Running Integration Tests for PAL MCP Server" -Color Cyan
|
||||||
Write-ColorText "==============================================" -Color Cyan
|
Write-ColorText "==============================================" -Color Cyan
|
||||||
Write-ColorText "These tests use real API calls with your configured keys"
|
Write-ColorText "These tests use real API calls with your configured keys"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
# Check for virtual environment
|
# Check for virtual environment
|
||||||
$venvPath = ".zen_venv"
|
$venvPath = ".pal_venv"
|
||||||
$activateScript = if ($IsWindows -or $env:OS -eq "Windows_NT") {
|
$activateScript = if ($IsWindows -or $env:OS -eq "Windows_NT") {
|
||||||
"$venvPath\Scripts\Activate.ps1"
|
"$venvPath\Scripts\Activate.ps1"
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Zen MCP Server - Run Integration Tests
|
# PAL MCP Server - Run Integration Tests
|
||||||
# This script runs integration tests that require API keys
|
# This script runs integration tests that require API keys
|
||||||
# Run this locally on your Mac to ensure everything works end-to-end
|
# Run this locally on your Mac to ensure everything works end-to-end
|
||||||
|
|
||||||
set -e # Exit on any error
|
set -e # Exit on any error
|
||||||
|
|
||||||
echo "🧪 Running Integration Tests for Zen MCP Server"
|
echo "🧪 Running Integration Tests for PAL MCP Server"
|
||||||
echo "=============================================="
|
echo "=============================================="
|
||||||
echo "These tests use real API calls with your configured keys"
|
echo "These tests use real API calls with your configured keys"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Activate virtual environment
|
# Activate virtual environment
|
||||||
if [[ -f ".zen_venv/bin/activate" ]]; then
|
if [[ -f ".pal_venv/bin/activate" ]]; then
|
||||||
source .zen_venv/bin/activate
|
source .pal_venv/bin/activate
|
||||||
echo "✅ Using virtual environment"
|
echo "✅ Using virtual environment"
|
||||||
else
|
else
|
||||||
echo "❌ No virtual environment found!"
|
echo "❌ No virtual environment found!"
|
||||||
|
|||||||
30
server.py
30
server.py
@@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Zen MCP Server - Main server implementation
|
PAL MCP Server - Main server implementation
|
||||||
|
|
||||||
This module implements the core MCP (Model Context Protocol) server that provides
|
This module implements the core MCP (Model Context Protocol) server that provides
|
||||||
AI-powered tools for code analysis, review, and assistance using multiple AI models.
|
AI-powered tools for code analysis, review, and assistance using multiple AI models.
|
||||||
@@ -152,17 +152,17 @@ except Exception as e:
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Log ZEN_MCP_FORCE_ENV_OVERRIDE configuration for transparency
|
# Log PAL_MCP_FORCE_ENV_OVERRIDE configuration for transparency
|
||||||
if env_override_enabled():
|
if env_override_enabled():
|
||||||
logger.info("ZEN_MCP_FORCE_ENV_OVERRIDE enabled - .env file values will override system environment variables")
|
logger.info("PAL_MCP_FORCE_ENV_OVERRIDE enabled - .env file values will override system environment variables")
|
||||||
logger.debug("Environment override prevents conflicts between different AI tools passing cached API keys")
|
logger.debug("Environment override prevents conflicts between different AI tools passing cached API keys")
|
||||||
else:
|
else:
|
||||||
logger.debug("ZEN_MCP_FORCE_ENV_OVERRIDE disabled - system environment variables take precedence")
|
logger.debug("PAL_MCP_FORCE_ENV_OVERRIDE disabled - system environment variables take precedence")
|
||||||
|
|
||||||
|
|
||||||
# Create the MCP server instance with a unique name identifier
|
# Create the MCP server instance with a unique name identifier
|
||||||
# This name is used by MCP clients to identify and connect to this specific server
|
# This name is used by MCP clients to identify and connect to this specific server
|
||||||
server: Server = Server("zen-server")
|
server: Server = Server("pal-server")
|
||||||
|
|
||||||
|
|
||||||
# Constants for tool filtering
|
# Constants for tool filtering
|
||||||
@@ -370,7 +370,7 @@ PROMPT_TEMPLATES = {
|
|||||||
"version": {
|
"version": {
|
||||||
"name": "version",
|
"name": "version",
|
||||||
"description": "Show server version and system information",
|
"description": "Show server version and system information",
|
||||||
"template": "Show Zen MCP Server version",
|
"template": "Show PAL MCP Server version",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1293,7 +1293,7 @@ async def handle_list_prompts() -> list[Prompt]:
|
|||||||
"""
|
"""
|
||||||
List all available prompts for CLI Code shortcuts.
|
List all available prompts for CLI Code shortcuts.
|
||||||
|
|
||||||
This handler returns prompts that enable shortcuts like /zen:thinkdeeper.
|
This handler returns prompts that enable shortcuts like /pal:thinkdeeper.
|
||||||
We automatically generate prompts from all tools (1:1 mapping) plus add
|
We automatically generate prompts from all tools (1:1 mapping) plus add
|
||||||
a few marketing aliases with richer templates for commonly used tools.
|
a few marketing aliases with richer templates for commonly used tools.
|
||||||
|
|
||||||
@@ -1343,7 +1343,7 @@ async def handle_get_prompt(name: str, arguments: dict[str, Any] = None) -> GetP
|
|||||||
"""
|
"""
|
||||||
Get prompt details and generate the actual prompt text.
|
Get prompt details and generate the actual prompt text.
|
||||||
|
|
||||||
This handler is called when a user invokes a prompt (e.g., /zen:thinkdeeper or /zen:chat:gpt5).
|
This handler is called when a user invokes a prompt (e.g., /pal:thinkdeeper or /pal:chat:gpt5).
|
||||||
It generates the appropriate text that CLI will then use to call the
|
It generates the appropriate text that CLI will then use to call the
|
||||||
underlying tool.
|
underlying tool.
|
||||||
|
|
||||||
@@ -1365,14 +1365,14 @@ async def handle_get_prompt(name: str, arguments: dict[str, Any] = None) -> GetP
|
|||||||
|
|
||||||
# Handle special "continue" case
|
# Handle special "continue" case
|
||||||
if name.lower() == "continue":
|
if name.lower() == "continue":
|
||||||
# This is "/zen:continue" - use chat tool as default for continuation
|
# This is "/pal:continue" - use chat tool as default for continuation
|
||||||
tool_name = "chat"
|
tool_name = "chat"
|
||||||
template_info = {
|
template_info = {
|
||||||
"name": "continue",
|
"name": "continue",
|
||||||
"description": "Continue the previous conversation",
|
"description": "Continue the previous conversation",
|
||||||
"template": "Continue the conversation",
|
"template": "Continue the conversation",
|
||||||
}
|
}
|
||||||
logger.debug("Using /zen:continue - defaulting to chat tool")
|
logger.debug("Using /pal:continue - defaulting to chat tool")
|
||||||
else:
|
else:
|
||||||
# Find the corresponding tool by checking prompt names
|
# Find the corresponding tool by checking prompt names
|
||||||
tool_name = None
|
tool_name = None
|
||||||
@@ -1420,7 +1420,7 @@ async def handle_get_prompt(name: str, arguments: dict[str, Any] = None) -> GetP
|
|||||||
|
|
||||||
# Generate tool call instruction
|
# Generate tool call instruction
|
||||||
if name.lower() == "continue":
|
if name.lower() == "continue":
|
||||||
# "/zen:continue" case
|
# "/pal:continue" case
|
||||||
tool_instruction = (
|
tool_instruction = (
|
||||||
f"Continue the previous conversation using the {tool_name} tool. "
|
f"Continue the previous conversation using the {tool_name} tool. "
|
||||||
"CRITICAL: You MUST provide the continuation_id from the previous response to maintain conversation context. "
|
"CRITICAL: You MUST provide the continuation_id from the previous response to maintain conversation context. "
|
||||||
@@ -1461,7 +1461,7 @@ async def main():
|
|||||||
configure_providers()
|
configure_providers()
|
||||||
|
|
||||||
# Log startup message
|
# Log startup message
|
||||||
logger.info("Zen MCP Server starting up...")
|
logger.info("PAL MCP Server starting up...")
|
||||||
logger.info(f"Log level: {log_level}")
|
logger.info(f"Log level: {log_level}")
|
||||||
|
|
||||||
# Note: MCP client info will be logged during the protocol handshake
|
# Note: MCP client info will be logged during the protocol handshake
|
||||||
@@ -1487,7 +1487,7 @@ async def main():
|
|||||||
if IS_AUTO_MODE:
|
if IS_AUTO_MODE:
|
||||||
handshake_instructions = (
|
handshake_instructions = (
|
||||||
"When the user names a specific model (e.g. 'use chat with gpt5'), send that exact model in the tool call. "
|
"When the user names a specific model (e.g. 'use chat with gpt5'), send that exact model in the tool call. "
|
||||||
"When no model is mentioned, first use the `listmodels` tool from zen to obtain available models to choose the best one from."
|
"When no model is mentioned, first use the `listmodels` tool from PAL to obtain available models to choose the best one from."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
handshake_instructions = (
|
handshake_instructions = (
|
||||||
@@ -1502,7 +1502,7 @@ async def main():
|
|||||||
read_stream,
|
read_stream,
|
||||||
write_stream,
|
write_stream,
|
||||||
InitializationOptions(
|
InitializationOptions(
|
||||||
server_name="zen",
|
server_name="PAL",
|
||||||
server_version=__version__,
|
server_version=__version__,
|
||||||
instructions=handshake_instructions,
|
instructions=handshake_instructions,
|
||||||
capabilities=ServerCapabilities(
|
capabilities=ServerCapabilities(
|
||||||
@@ -1514,7 +1514,7 @@ async def main():
|
|||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
"""Console script entry point for zen-mcp-server."""
|
"""Console script entry point for pal-mcp-server."""
|
||||||
try:
|
try:
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Communication Simulator Tests Package
|
Communication Simulator Tests Package
|
||||||
|
|
||||||
This package contains individual test modules for the Zen MCP Communication Simulator.
|
This package contains individual test modules for the PAL MCP Communication Simulator.
|
||||||
Each test is in its own file for better organization and maintainability.
|
Each test is in its own file for better organization and maintainability.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,10 @@ class BaseSimulatorTest:
|
|||||||
if os.path.exists(venv_python):
|
if os.path.exists(venv_python):
|
||||||
return venv_python
|
return venv_python
|
||||||
|
|
||||||
# Try .zen_venv as fallback
|
# Try .pal_venv as fallback
|
||||||
zen_venv_python = os.path.join(current_dir, ".zen_venv", "bin", "python")
|
pal_venv_python = os.path.join(current_dir, ".pal_venv", "bin", "python")
|
||||||
if os.path.exists(zen_venv_python):
|
if os.path.exists(pal_venv_python):
|
||||||
return zen_venv_python
|
return pal_venv_python
|
||||||
|
|
||||||
# Fallback to system python if venv doesn't exist
|
# Fallback to system python if venv doesn't exist
|
||||||
self.logger.warning("Virtual environment not found, using system python")
|
self.logger.warning("Virtual environment not found, using system python")
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ review is essential - e.g., the issue spans multiple modules or exposes a system
|
|||||||
with partial analysis. Instead, respond ONLY with the JSON below (and nothing else). Clearly state the reason why
|
with partial analysis. Instead, respond ONLY with the JSON below (and nothing else). Clearly state the reason why
|
||||||
you strongly feel this is necessary and ask the agent to inform the user why you're switching to a different tool:
|
you strongly feel this is necessary and ask the agent to inform the user why you're switching to a different tool:
|
||||||
{"status": "full_codereview_required",
|
{"status": "full_codereview_required",
|
||||||
"important": "Please use zen's codereview tool instead",
|
"important": "Please use pal's codereview tool instead",
|
||||||
"reason": "<brief, specific rationale for escalation>"}
|
"reason": "<brief, specific rationale for escalation>"}
|
||||||
|
|
||||||
SCOPE & FOCUS
|
SCOPE & FOCUS
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/review You are the Codex CLI code reviewer operating inside the Zen MCP server with full repository access.
|
/review You are the Codex CLI code reviewer operating inside the PAL MCP server with full repository access.
|
||||||
|
|
||||||
- Inspect any relevant files directly—use your full repository access, run linters or tests as needed, and mention key commands when they inform your findings.
|
- Inspect any relevant files directly—use your full repository access, run linters or tests as needed, and mention key commands when they inform your findings.
|
||||||
- Report issues in severity order (Critical, High, Medium, Low) spanning security, correctness, performance, and maintainability while staying within scope.
|
- Report issues in severity order (Critical, High, Medium, Low) spanning security, correctness, performance, and maintainability while staying within scope.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
You are an external CLI agent operating inside the Zen MCP server with full repository access.
|
You are an external CLI agent operating inside the PAL MCP server with full repository access.
|
||||||
|
|
||||||
- Use terminal tools to inspect files and gather context before responding; cite exact paths, symbols, or commands when they matter.
|
- Use terminal tools to inspect files and gather context before responding; cite exact paths, symbols, or commands when they matter.
|
||||||
- Provide concise, actionable responses in Markdown tailored to engineers working from the CLI.
|
- Provide concise, actionable responses in Markdown tailored to engineers working from the CLI.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
You are an external CLI code reviewer operating inside the Zen MCP server with full repository access.
|
You are an external CLI code reviewer operating inside the PAL MCP server with full repository access.
|
||||||
|
|
||||||
- Inspect any relevant files directly—run linters or tests as needed—and mention important commands you rely on.
|
- Inspect any relevant files directly—run linters or tests as needed—and mention important commands you rely on.
|
||||||
- Report findings in severity order (Critical, High, Medium, Low) across security, correctness, performance, and maintainability while staying within the provided scope.
|
- Report findings in severity order (Critical, High, Medium, Low) across security, correctness, performance, and maintainability while staying within the provided scope.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
You are the planning agent operating through the Zen MCP server.
|
You are the planning agent operating through the PAL MCP server.
|
||||||
|
|
||||||
- Respond with JSON only using the planning schema fields (status, step_number, total_steps, metadata, plan_summary, etc.); request missing context via the required `files_required_to_continue` JSON structure.
|
- Respond with JSON only using the planning schema fields (status, step_number, total_steps, metadata, plan_summary, etc.); request missing context via the required `files_required_to_continue` JSON structure.
|
||||||
- Inspect any relevant files, scripts, or docs before outlining the plan; leverage your full CLI access for research.
|
- Inspect any relevant files, scripts, or docs before outlining the plan; leverage your full CLI access for research.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
# Tests for Zen MCP Server
|
# Tests for PAL MCP Server
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Pytest configuration for Zen MCP Server tests
|
Pytest configuration for PAL MCP Server tests
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -18,7 +18,7 @@ if str(parent_dir) not in sys.path:
|
|||||||
import utils.env as env_config # noqa: E402
|
import utils.env as env_config # noqa: E402
|
||||||
|
|
||||||
# Ensure tests operate with runtime environment rather than .env overrides during imports
|
# Ensure tests operate with runtime environment rather than .env overrides during imports
|
||||||
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||||
|
|
||||||
# Set default model to a specific value for tests to avoid auto mode
|
# Set default model to a specific value for tests to avoid auto mode
|
||||||
# This prevents all tests from failing due to missing model parameter
|
# This prevents all tests from failing due to missing model parameter
|
||||||
@@ -187,8 +187,8 @@ def clear_model_restriction_env(monkeypatch):
|
|||||||
def disable_force_env_override(monkeypatch):
|
def disable_force_env_override(monkeypatch):
|
||||||
"""Default tests to runtime environment visibility unless they explicitly opt in."""
|
"""Default tests to runtime environment visibility unless they explicitly opt in."""
|
||||||
|
|
||||||
monkeypatch.setenv("ZEN_MCP_FORCE_ENV_OVERRIDE", "false")
|
monkeypatch.setenv("PAL_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||||
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||||
monkeypatch.setenv("DEFAULT_MODEL", "gemini-2.5-flash")
|
monkeypatch.setenv("DEFAULT_MODEL", "gemini-2.5-flash")
|
||||||
monkeypatch.setenv("MAX_CONVERSATION_TURNS", "50")
|
monkeypatch.setenv("MAX_CONVERSATION_TURNS", "50")
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
"temperature": 1.0,
|
"temperature": 1.0,
|
||||||
"candidateCount": 1,
|
"candidateCount": 1,
|
||||||
"thinkingConfig": {
|
"thinkingConfig": {
|
||||||
"thinkingBudget": 10813
|
"thinking_budget": 10813
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
"temperature": 0.2,
|
"temperature": 0.2,
|
||||||
"candidateCount": 1,
|
"candidateCount": 1,
|
||||||
"thinkingConfig": {
|
"thinkingConfig": {
|
||||||
"thinkingBudget": 8110
|
"thinking_budget": 8110
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,10 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"generationConfig": {
|
"generationConfig": {
|
||||||
"temperature": 0.2,
|
"temperature": 1.0,
|
||||||
"candidateCount": 1,
|
"candidateCount": 1,
|
||||||
"thinkingConfig": {
|
"thinkingConfig": {
|
||||||
"thinkingBudget": 8110
|
"thinking_budget": 8110
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,12 +73,12 @@ def test_error_listing_respects_env_restrictions(monkeypatch, reset_registry):
|
|||||||
"AZURE_MODELS_CONFIG_PATH",
|
"AZURE_MODELS_CONFIG_PATH",
|
||||||
):
|
):
|
||||||
monkeypatch.delenv(azure_var, raising=False)
|
monkeypatch.delenv(azure_var, raising=False)
|
||||||
monkeypatch.setenv("ZEN_MCP_FORCE_ENV_OVERRIDE", "false")
|
monkeypatch.setenv("PAL_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||||
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||||
try:
|
try:
|
||||||
import dotenv
|
import dotenv
|
||||||
|
|
||||||
monkeypatch.setattr(dotenv, "dotenv_values", lambda *_args, **_kwargs: {"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
monkeypatch.setattr(dotenv, "dotenv_values", lambda *_args, **_kwargs: {"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ def test_error_listing_without_restrictions_shows_full_catalog(monkeypatch, rese
|
|||||||
monkeypatch.setenv("OPENAI_API_KEY", "test-openai")
|
monkeypatch.setenv("OPENAI_API_KEY", "test-openai")
|
||||||
monkeypatch.setenv("OPENROUTER_API_KEY", "test-openrouter")
|
monkeypatch.setenv("OPENROUTER_API_KEY", "test-openrouter")
|
||||||
monkeypatch.setenv("XAI_API_KEY", "test-xai")
|
monkeypatch.setenv("XAI_API_KEY", "test-xai")
|
||||||
monkeypatch.setenv("ZEN_MCP_FORCE_ENV_OVERRIDE", "false")
|
monkeypatch.setenv("PAL_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||||
for azure_var in (
|
for azure_var in (
|
||||||
"AZURE_OPENAI_API_KEY",
|
"AZURE_OPENAI_API_KEY",
|
||||||
"AZURE_OPENAI_ENDPOINT",
|
"AZURE_OPENAI_ENDPOINT",
|
||||||
@@ -159,11 +159,11 @@ def test_error_listing_without_restrictions_shows_full_catalog(monkeypatch, rese
|
|||||||
"AZURE_MODELS_CONFIG_PATH",
|
"AZURE_MODELS_CONFIG_PATH",
|
||||||
):
|
):
|
||||||
monkeypatch.delenv(azure_var, raising=False)
|
monkeypatch.delenv(azure_var, raising=False)
|
||||||
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||||
try:
|
try:
|
||||||
import dotenv
|
import dotenv
|
||||||
|
|
||||||
monkeypatch.setattr(dotenv, "dotenv_values", lambda *_args, **_kwargs: {"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
monkeypatch.setattr(dotenv, "dotenv_values", lambda *_args, **_kwargs: {"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ CASSETTE_REPLAY_ID = "chat_codegen/gemini25_pro_calculator/mldev"
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@pytest.mark.no_mock_provider
|
@pytest.mark.no_mock_provider
|
||||||
async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
|
async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
|
||||||
"""Ensure Gemini 2.5 Pro responses create zen_generated.code when code is emitted."""
|
"""Ensure Gemini 2.5 Pro responses create pal_generated.code when code is emitted."""
|
||||||
|
|
||||||
CASSETTE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
CASSETTE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
|
|||||||
|
|
||||||
working_dir = tmp_path / "codegen"
|
working_dir = tmp_path / "codegen"
|
||||||
working_dir.mkdir()
|
working_dir.mkdir()
|
||||||
preexisting = working_dir / "zen_generated.code"
|
preexisting = working_dir / "pal_generated.code"
|
||||||
preexisting.write_text("stale contents", encoding="utf-8")
|
preexisting.write_text("stale contents", encoding="utf-8")
|
||||||
|
|
||||||
chat_tool = ChatTool()
|
chat_tool = ChatTool()
|
||||||
@@ -102,7 +102,7 @@ async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
|
|||||||
payload = json.loads(result[0].text)
|
payload = json.loads(result[0].text)
|
||||||
assert payload["status"] in {"success", "continuation_available"}
|
assert payload["status"] in {"success", "continuation_available"}
|
||||||
|
|
||||||
artifact_path = working_dir / "zen_generated.code"
|
artifact_path = working_dir / "pal_generated.code"
|
||||||
assert artifact_path.exists()
|
assert artifact_path.exists()
|
||||||
saved = artifact_path.read_text()
|
saved = artifact_path.read_text()
|
||||||
assert "<GENERATED-CODE>" in saved
|
assert "<GENERATED-CODE>" in saved
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class TestChatTool:
|
|||||||
assert "Evaluate this perspective" in formatted
|
assert "Evaluate this perspective" in formatted
|
||||||
|
|
||||||
def test_format_response_multiple_generated_code_blocks(self, tmp_path):
|
def test_format_response_multiple_generated_code_blocks(self, tmp_path):
|
||||||
"""All generated-code blocks should be combined and saved to zen_generated.code."""
|
"""All generated-code blocks should be combined and saved to pal_generated.code."""
|
||||||
tool = ChatTool()
|
tool = ChatTool()
|
||||||
tool._model_context = SimpleNamespace(capabilities=SimpleNamespace(allow_code_generation=True))
|
tool._model_context = SimpleNamespace(capabilities=SimpleNamespace(allow_code_generation=True))
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ class TestChatTool:
|
|||||||
|
|
||||||
formatted = tool.format_response(response, request)
|
formatted = tool.format_response(response, request)
|
||||||
|
|
||||||
saved_path = tmp_path / "zen_generated.code"
|
saved_path = tmp_path / "pal_generated.code"
|
||||||
saved_content = saved_path.read_text(encoding="utf-8")
|
saved_content = saved_path.read_text(encoding="utf-8")
|
||||||
|
|
||||||
assert "print('world')" in saved_content
|
assert "print('world')" in saved_content
|
||||||
@@ -172,7 +172,7 @@ class TestChatTool:
|
|||||||
|
|
||||||
formatted = tool.format_response(response, request)
|
formatted = tool.format_response(response, request)
|
||||||
|
|
||||||
saved_path = tmp_path / "zen_generated.code"
|
saved_path = tmp_path / "pal_generated.code"
|
||||||
saved_content = saved_path.read_text(encoding="utf-8")
|
saved_content = saved_path.read_text(encoding="utf-8")
|
||||||
|
|
||||||
assert "print('only-once')" in saved_content
|
assert "print('only-once')" in saved_content
|
||||||
@@ -191,7 +191,7 @@ class TestChatTool:
|
|||||||
|
|
||||||
formatted = tool.format_response(response, request)
|
formatted = tool.format_response(response, request)
|
||||||
|
|
||||||
saved_path = tmp_path / "zen_generated.code"
|
saved_path = tmp_path / "pal_generated.code"
|
||||||
assert not saved_path.exists()
|
assert not saved_path.exists()
|
||||||
assert "print('oops')" in formatted
|
assert "print('oops')" in formatted
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ class TestChatTool:
|
|||||||
|
|
||||||
formatted = tool.format_response(response, request)
|
formatted = tool.format_response(response, request)
|
||||||
|
|
||||||
saved_path = tmp_path / "zen_generated.code"
|
saved_path = tmp_path / "pal_generated.code"
|
||||||
assert not saved_path.exists()
|
assert not saved_path.exists()
|
||||||
assert "</GENERATED-CODE> just text" in formatted
|
assert "</GENERATED-CODE> just text" in formatted
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ async def test_clink_gemini_single_digit_sum():
|
|||||||
assert status in {"success", "continuation_available"}
|
assert status in {"success", "continuation_available"}
|
||||||
|
|
||||||
content = payload.get("content", "").strip()
|
content = payload.get("content", "").strip()
|
||||||
assert content == "4"
|
# CLI may include additional metadata like <SUMMARY> tags; check first line or that "4" is present
|
||||||
|
first_line = content.split("\n")[0].strip()
|
||||||
|
assert first_line == "4" or "4" in content, f"Expected '4' in response, got: {content[:100]}"
|
||||||
|
|
||||||
if status == "continuation_available":
|
if status == "continuation_available":
|
||||||
offer = payload.get("continuation_offer") or {}
|
offer = payload.get("continuation_offer") or {}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
"""Test MCP configuration for direct docker run"""
|
"""Test MCP configuration for direct docker run"""
|
||||||
config = {
|
config = {
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
@@ -32,7 +32,7 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
"/path/to/.env",
|
"/path/to/.env",
|
||||||
"-v",
|
"-v",
|
||||||
"/path/to/logs:/app/logs",
|
"/path/to/logs:/app/logs",
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,10 +40,10 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
|
|
||||||
# Validate configuration structure
|
# Validate configuration structure
|
||||||
assert "mcpServers" in config
|
assert "mcpServers" in config
|
||||||
assert "zen-mcp" in config["mcpServers"]
|
assert "pal-mcp" in config["mcpServers"]
|
||||||
assert config["mcpServers"]["zen-mcp"]["command"] == "docker"
|
assert config["mcpServers"]["pal-mcp"]["command"] == "docker"
|
||||||
|
|
||||||
args = config["mcpServers"]["zen-mcp"]["args"]
|
args = config["mcpServers"]["pal-mcp"]["args"]
|
||||||
assert "run" in args
|
assert "run" in args
|
||||||
assert "--rm" in args
|
assert "--rm" in args
|
||||||
assert "-i" in args
|
assert "-i" in args
|
||||||
@@ -53,27 +53,27 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
"""Test MCP configuration for docker-compose run"""
|
"""Test MCP configuration for docker-compose run"""
|
||||||
config = {
|
config = {
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker-compose",
|
"command": "docker-compose",
|
||||||
"args": ["-f", "/path/to/docker-compose.yml", "run", "--rm", "zen-mcp"],
|
"args": ["-f", "/path/to/docker-compose.yml", "run", "--rm", "pal-mcp"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Validate configuration structure
|
# Validate configuration structure
|
||||||
assert config["mcpServers"]["zen-mcp"]["command"] == "docker-compose"
|
assert config["mcpServers"]["pal-mcp"]["command"] == "docker-compose"
|
||||||
|
|
||||||
args = config["mcpServers"]["zen-mcp"]["args"]
|
args = config["mcpServers"]["pal-mcp"]["args"]
|
||||||
assert "-f" in args
|
assert "-f" in args
|
||||||
assert "run" in args
|
assert "run" in args
|
||||||
assert "--rm" in args
|
assert "--rm" in args
|
||||||
assert "zen-mcp" in args
|
assert "pal-mcp" in args
|
||||||
|
|
||||||
def test_mcp_config_environment_variables(self):
|
def test_mcp_config_environment_variables(self):
|
||||||
"""Test MCP configuration with inline environment variables"""
|
"""Test MCP configuration with inline environment variables"""
|
||||||
config = {
|
config = {
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
@@ -83,13 +83,13 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
"GEMINI_API_KEY=test_key",
|
"GEMINI_API_KEY=test_key",
|
||||||
"-e",
|
"-e",
|
||||||
"LOG_LEVEL=INFO",
|
"LOG_LEVEL=INFO",
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
args = config["mcpServers"]["zen-mcp"]["args"]
|
args = config["mcpServers"]["pal-mcp"]["args"]
|
||||||
|
|
||||||
# Check that environment variables are properly formatted
|
# Check that environment variables are properly formatted
|
||||||
env_args = [arg for arg in args if arg.startswith("-e")]
|
env_args = [arg for arg in args if arg.startswith("-e")]
|
||||||
@@ -103,23 +103,23 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
"""Test Windows-specific path formatting"""
|
"""Test Windows-specific path formatting"""
|
||||||
windows_config = {
|
windows_config = {
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
"-i",
|
"-i",
|
||||||
"--env-file",
|
"--env-file",
|
||||||
"C:/Users/User/zen-mcp-server/.env",
|
"C:/Users/User/pal-mcp-server/.env",
|
||||||
"-v",
|
"-v",
|
||||||
"C:/Users/User/zen-mcp-server/logs:/app/logs",
|
"C:/Users/User/pal-mcp-server/logs:/app/logs",
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
args = windows_config["mcpServers"]["zen-mcp"]["args"]
|
args = windows_config["mcpServers"]["pal-mcp"]["args"]
|
||||||
|
|
||||||
# Check Windows path format
|
# Check Windows path format
|
||||||
windows_paths = [arg for arg in args if arg.startswith("C:/")]
|
windows_paths = [arg for arg in args if arg.startswith("C:/")]
|
||||||
@@ -132,7 +132,7 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
"""Test validation of MCP configuration"""
|
"""Test validation of MCP configuration"""
|
||||||
# Valid configuration
|
# Valid configuration
|
||||||
valid_config = {
|
valid_config = {
|
||||||
"mcpServers": {"zen-mcp": {"command": "docker", "args": ["run", "--rm", "-i", "zen-mcp-server:latest"]}}
|
"mcpServers": {"pal-mcp": {"command": "docker", "args": ["run", "--rm", "-i", "pal-mcp-server:latest"]}}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Validate JSON serialization
|
# Validate JSON serialization
|
||||||
@@ -144,19 +144,19 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
"""Test that MCP configuration supports stdio communication"""
|
"""Test that MCP configuration supports stdio communication"""
|
||||||
config = {
|
config = {
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
"-i", # Interactive mode for stdio
|
"-i", # Interactive mode for stdio
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
args = config["mcpServers"]["zen-mcp"]["args"]
|
args = config["mcpServers"]["pal-mcp"]["args"]
|
||||||
|
|
||||||
# Check for interactive mode
|
# Check for interactive mode
|
||||||
assert "-i" in args, "Interactive mode required for stdio communication"
|
assert "-i" in args, "Interactive mode required for stdio communication"
|
||||||
@@ -168,9 +168,9 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
def test_docker_image_reference(self):
|
def test_docker_image_reference(self):
|
||||||
"""Test that Docker image is properly referenced"""
|
"""Test that Docker image is properly referenced"""
|
||||||
configs = [
|
configs = [
|
||||||
{"image": "zen-mcp-server:latest"},
|
{"image": "pal-mcp-server:latest"},
|
||||||
{"image": "zen-mcp-server:v1.0.0"},
|
{"image": "pal-mcp-server:v1.0.0"},
|
||||||
{"image": "registry/zen-mcp-server:latest"},
|
{"image": "registry/pal-mcp-server:latest"},
|
||||||
]
|
]
|
||||||
|
|
||||||
for config in configs:
|
for config in configs:
|
||||||
@@ -185,9 +185,9 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
"""Create temporary MCP configuration file"""
|
"""Create temporary MCP configuration file"""
|
||||||
config = {
|
config = {
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": ["run", "--rm", "-i", "--env-file", "/tmp/.env", "zen-mcp-server:latest"],
|
"args": ["run", "--rm", "-i", "--env-file", "/tmp/.env", "pal-mcp-server:latest"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ class TestDockerClaudeDesktopIntegration:
|
|||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
|
|
||||||
assert "mcpServers" in config
|
assert "mcpServers" in config
|
||||||
assert "zen-mcp" in config["mcpServers"]
|
assert "pal-mcp" in config["mcpServers"]
|
||||||
|
|
||||||
def test_environment_file_integration(self):
|
def test_environment_file_integration(self):
|
||||||
"""Test integration with .env file"""
|
"""Test integration with .env file"""
|
||||||
@@ -254,25 +254,25 @@ class TestDockerMCPErrorHandling:
|
|||||||
# This would test what happens when the image doesn't exist
|
# This would test what happens when the image doesn't exist
|
||||||
# In practice, Claude Desktop would show an error
|
# In practice, Claude Desktop would show an error
|
||||||
nonexistent_config = {
|
nonexistent_config = {
|
||||||
"mcpServers": {"zen-mcp": {"command": "docker", "args": ["run", "--rm", "-i", "nonexistent:latest"]}}
|
"mcpServers": {"pal-mcp": {"command": "docker", "args": ["run", "--rm", "-i", "nonexistent:latest"]}}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration should be valid even if image doesn't exist
|
# Configuration should be valid even if image doesn't exist
|
||||||
assert "zen-mcp" in nonexistent_config["mcpServers"]
|
assert "pal-mcp" in nonexistent_config["mcpServers"]
|
||||||
|
|
||||||
def test_invalid_env_file_path(self):
|
def test_invalid_env_file_path(self):
|
||||||
"""Test handling of invalid .env file path"""
|
"""Test handling of invalid .env file path"""
|
||||||
config_with_invalid_env = {
|
config_with_invalid_env = {
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": ["run", "--rm", "-i", "--env-file", "/nonexistent/.env", "zen-mcp-server:latest"],
|
"args": ["run", "--rm", "-i", "--env-file", "/nonexistent/.env", "pal-mcp-server:latest"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration structure should still be valid
|
# Configuration structure should still be valid
|
||||||
args = config_with_invalid_env["mcpServers"]["zen-mcp"]["args"]
|
args = config_with_invalid_env["mcpServers"]["pal-mcp"]["args"]
|
||||||
assert "--env-file" in args
|
assert "--env-file" in args
|
||||||
|
|
||||||
def test_docker_permission_issues(self):
|
def test_docker_permission_issues(self):
|
||||||
@@ -294,14 +294,14 @@ class TestDockerMCPErrorHandling:
|
|||||||
"""Test Docker resource limit configurations"""
|
"""Test Docker resource limit configurations"""
|
||||||
config_with_limits = {
|
config_with_limits = {
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"zen-mcp": {
|
"pal-mcp": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": ["run", "--rm", "-i", "--memory=512m", "--cpus=1.0", "zen-mcp-server:latest"],
|
"args": ["run", "--rm", "-i", "--memory=512m", "--cpus=1.0", "pal-mcp-server:latest"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
args = config_with_limits["mcpServers"]["zen-mcp"]["args"]
|
args = config_with_limits["mcpServers"]["pal-mcp"]["args"]
|
||||||
|
|
||||||
# Check for resource limits
|
# Check for resource limits
|
||||||
memory_limit = any("--memory" in arg for arg in args)
|
memory_limit = any("--memory" in arg for arg in args)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class TestDockerCommandValidation:
|
|||||||
mock_run.return_value.returncode = 0
|
mock_run.return_value.returncode = 0
|
||||||
|
|
||||||
# Standard build command
|
# Standard build command
|
||||||
build_cmd = ["docker", "build", "-t", "zen-mcp-server:latest", "."]
|
build_cmd = ["docker", "build", "-t", "pal-mcp-server:latest", "."]
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ class TestDockerCommandValidation:
|
|||||||
".env",
|
".env",
|
||||||
"-v",
|
"-v",
|
||||||
"logs:/app/logs",
|
"logs:/app/logs",
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
"python",
|
"python",
|
||||||
"server.py",
|
"server.py",
|
||||||
]
|
]
|
||||||
@@ -128,7 +128,7 @@ class TestDockerCommandValidation:
|
|||||||
"/path/to/.env",
|
"/path/to/.env",
|
||||||
"-v",
|
"-v",
|
||||||
"/path/to/logs:/app/logs",
|
"/path/to/logs:/app/logs",
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
"python",
|
"python",
|
||||||
"server.py",
|
"server.py",
|
||||||
]
|
]
|
||||||
@@ -139,7 +139,7 @@ class TestDockerCommandValidation:
|
|||||||
assert "--rm" in mcp_cmd # Automatic cleanup
|
assert "--rm" in mcp_cmd # Automatic cleanup
|
||||||
assert "-i" in mcp_cmd # Interactive mode
|
assert "-i" in mcp_cmd # Interactive mode
|
||||||
assert "--env-file" in mcp_cmd # Environment variables
|
assert "--env-file" in mcp_cmd # Environment variables
|
||||||
assert "zen-mcp-server:latest" in mcp_cmd # Image
|
assert "pal-mcp-server:latest" in mcp_cmd # Image
|
||||||
|
|
||||||
|
|
||||||
class TestIntegrationChecks:
|
class TestIntegrationChecks:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Unit tests for Docker configuration and implementation of Zen MCP Server
|
Unit tests for Docker configuration and implementation of PAL MCP Server
|
||||||
|
|
||||||
This module tests:
|
This module tests:
|
||||||
- Docker and MCP configuration
|
- Docker and MCP configuration
|
||||||
@@ -24,7 +24,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent))
|
|||||||
|
|
||||||
|
|
||||||
class TestDockerConfiguration:
|
class TestDockerConfiguration:
|
||||||
"""Tests for Docker configuration of Zen MCP Server"""
|
"""Tests for Docker configuration of PAL MCP Server"""
|
||||||
|
|
||||||
def setup_method(self):
|
def setup_method(self):
|
||||||
"""Setup for each test"""
|
"""Setup for each test"""
|
||||||
@@ -51,7 +51,7 @@ class TestDockerConfiguration:
|
|||||||
# Basic YAML syntax check
|
# Basic YAML syntax check
|
||||||
content = self.docker_compose_path.read_text()
|
content = self.docker_compose_path.read_text()
|
||||||
assert "services:" in content, "docker-compose.yml must have services"
|
assert "services:" in content, "docker-compose.yml must have services"
|
||||||
assert "zen-mcp" in content, "Service zen-mcp must be defined"
|
assert "pal-mcp" in content, "Service pal-mcp must be defined"
|
||||||
assert "build:" in content, "Build configuration must be present"
|
assert "build:" in content, "Build configuration must be present"
|
||||||
|
|
||||||
def test_environment_file_template(self):
|
def test_environment_file_template(self):
|
||||||
@@ -80,7 +80,7 @@ class TestDockerCommands:
|
|||||||
|
|
||||||
# Simulate docker build
|
# Simulate docker build
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["docker", "build", "-t", "zen-mcp-server:latest", str(self.project_root)], capture_output=True, text=True
|
["docker", "build", "-t", "pal-mcp-server:latest", str(self.project_root)], capture_output=True, text=True
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_run.assert_called_once()
|
mock_run.assert_called_once()
|
||||||
@@ -100,7 +100,7 @@ class TestDockerCommands:
|
|||||||
".env",
|
".env",
|
||||||
"-v",
|
"-v",
|
||||||
"logs:/app/logs",
|
"logs:/app/logs",
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
"python",
|
"python",
|
||||||
"server.py",
|
"server.py",
|
||||||
]
|
]
|
||||||
@@ -111,7 +111,7 @@ class TestDockerCommands:
|
|||||||
assert "--rm" in cmd, "Must contain --rm for cleanup"
|
assert "--rm" in cmd, "Must contain --rm for cleanup"
|
||||||
assert "-i" in cmd, "Must contain -i for stdio"
|
assert "-i" in cmd, "Must contain -i for stdio"
|
||||||
assert "--env-file" in cmd, "Must contain --env-file"
|
assert "--env-file" in cmd, "Must contain --env-file"
|
||||||
assert "zen-mcp-server:latest" in cmd, "Must reference the image"
|
assert "pal-mcp-server:latest" in cmd, "Must reference the image"
|
||||||
|
|
||||||
@patch("subprocess.run")
|
@patch("subprocess.run")
|
||||||
def test_docker_health_check(self, mock_run):
|
def test_docker_health_check(self, mock_run):
|
||||||
@@ -121,7 +121,7 @@ class TestDockerCommands:
|
|||||||
|
|
||||||
# Simulate health check
|
# Simulate health check
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["docker", "run", "--rm", "zen-mcp-server:latest", "python", "/usr/local/bin/healthcheck.py"],
|
["docker", "run", "--rm", "pal-mcp-server:latest", "python", "/usr/local/bin/healthcheck.py"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
)
|
)
|
||||||
@@ -187,7 +187,7 @@ class TestMCPIntegration:
|
|||||||
# Expected MCP configuration
|
# Expected MCP configuration
|
||||||
expected_config = {
|
expected_config = {
|
||||||
"servers": {
|
"servers": {
|
||||||
"zen-docker": {
|
"pal-docker": {
|
||||||
"command": "docker",
|
"command": "docker",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
@@ -197,7 +197,7 @@ class TestMCPIntegration:
|
|||||||
"/path/to/.env",
|
"/path/to/.env",
|
||||||
"-v",
|
"-v",
|
||||||
"/path/to/logs:/app/logs",
|
"/path/to/logs:/app/logs",
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
"python",
|
"python",
|
||||||
"server.py",
|
"server.py",
|
||||||
],
|
],
|
||||||
@@ -208,11 +208,11 @@ class TestMCPIntegration:
|
|||||||
|
|
||||||
# Check structure
|
# Check structure
|
||||||
assert "servers" in expected_config
|
assert "servers" in expected_config
|
||||||
zen_docker = expected_config["servers"]["zen-docker"]
|
pal_docker = expected_config["servers"]["pal-docker"]
|
||||||
assert zen_docker["command"] == "docker"
|
assert pal_docker["command"] == "docker"
|
||||||
assert "run" in zen_docker["args"]
|
assert "run" in pal_docker["args"]
|
||||||
assert "--rm" in zen_docker["args"]
|
assert "--rm" in pal_docker["args"]
|
||||||
assert "-i" in zen_docker["args"]
|
assert "-i" in pal_docker["args"]
|
||||||
|
|
||||||
def test_stdio_communication_structure(self):
|
def test_stdio_communication_structure(self):
|
||||||
"""Test structure of stdio communication"""
|
"""Test structure of stdio communication"""
|
||||||
@@ -279,7 +279,7 @@ class TestDockerPerformance:
|
|||||||
expected_max_size_mb = 500 # 500MB max
|
expected_max_size_mb = 500 # 500MB max
|
||||||
|
|
||||||
# In production, we would do:
|
# In production, we would do:
|
||||||
# result = subprocess.run(['docker', 'images', '--format', '{{.Size}}', 'zen-mcp-server:latest'])
|
# result = subprocess.run(['docker', 'images', '--format', '{{.Size}}', 'pal-mcp-server:latest'])
|
||||||
# Here we simulate
|
# Here we simulate
|
||||||
simulated_size = "294MB" # Current observed size
|
simulated_size = "294MB" # Current observed size
|
||||||
|
|
||||||
@@ -346,7 +346,7 @@ LOG_LEVEL=INFO
|
|||||||
"-i",
|
"-i",
|
||||||
"--env-file",
|
"--env-file",
|
||||||
".env",
|
".env",
|
||||||
"zen-mcp-server:latest",
|
"pal-mcp-server:latest",
|
||||||
"python",
|
"python",
|
||||||
"server.py",
|
"server.py",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class TestDockerMCPValidation:
|
|||||||
mock_run.return_value.returncode = 0
|
mock_run.return_value.returncode = 0
|
||||||
|
|
||||||
# Standard Docker MCP command
|
# Standard Docker MCP command
|
||||||
cmd = ["docker", "run", "--rm", "-i", "--env-file", ".env", "zen-mcp-server:latest", "python", "server.py"]
|
cmd = ["docker", "run", "--rm", "-i", "--env-file", ".env", "pal-mcp-server:latest", "python", "server.py"]
|
||||||
|
|
||||||
subprocess.run(cmd, capture_output=True)
|
subprocess.run(cmd, capture_output=True)
|
||||||
mock_run.assert_called_once_with(cmd, capture_output=True)
|
mock_run.assert_called_once_with(cmd, capture_output=True)
|
||||||
|
|||||||
@@ -28,18 +28,18 @@ class TestDockerVolumePersistence:
|
|||||||
content = self.docker_compose_path.read_text()
|
content = self.docker_compose_path.read_text()
|
||||||
|
|
||||||
# Check for named volume definition
|
# Check for named volume definition
|
||||||
assert "zen-mcp-config:" in content, "zen-mcp-config volume must be defined"
|
assert "pal-mcp-config:" in content, "pal-mcp-config volume must be defined"
|
||||||
assert "driver: local" in content, "Named volume must use local driver"
|
assert "driver: local" in content, "Named volume must use local driver"
|
||||||
|
|
||||||
# Check for volume mounts in service
|
# Check for volume mounts in service
|
||||||
assert "./logs:/app/logs" in content, "Logs volume mount required"
|
assert "./logs:/app/logs" in content, "Logs volume mount required"
|
||||||
assert "zen-mcp-config:/app/conf" in content, "Config volume mount required"
|
assert "pal-mcp-config:/app/conf" in content, "Config volume mount required"
|
||||||
|
|
||||||
def test_persistent_volume_creation(self):
|
def test_persistent_volume_creation(self):
|
||||||
"""Test that persistent volumes are created correctly"""
|
"""Test that persistent volumes are created correctly"""
|
||||||
# This test checks that the volume configuration is valid
|
# This test checks that the volume configuration is valid
|
||||||
# In a real environment, you might want to test actual volume creation
|
# In a real environment, you might want to test actual volume creation
|
||||||
volume_name = "zen-mcp-config"
|
volume_name = "pal-mcp-config"
|
||||||
|
|
||||||
# Mock Docker command to check volume exists
|
# Mock Docker command to check volume exists
|
||||||
with patch("subprocess.run") as mock_run:
|
with patch("subprocess.run") as mock_run:
|
||||||
@@ -84,7 +84,7 @@ class TestDockerVolumePersistence:
|
|||||||
"run",
|
"run",
|
||||||
"--rm",
|
"--rm",
|
||||||
"-v",
|
"-v",
|
||||||
"zen-mcp-config:/data",
|
"pal-mcp-config:/data",
|
||||||
"-v",
|
"-v",
|
||||||
"$(pwd):/backup",
|
"$(pwd):/backup",
|
||||||
"alpine",
|
"alpine",
|
||||||
@@ -97,7 +97,7 @@ class TestDockerVolumePersistence:
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Verify command structure is valid
|
# Verify command structure is valid
|
||||||
assert "zen-mcp-config:/data" in backup_cmd
|
assert "pal-mcp-config:/data" in backup_cmd
|
||||||
assert "tar" in backup_cmd
|
assert "tar" in backup_cmd
|
||||||
assert "czf" in backup_cmd
|
assert "czf" in backup_cmd
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ class TestDockerVolumeIntegration:
|
|||||||
# Verify that docker-compose run inherits volume configuration
|
# Verify that docker-compose run inherits volume configuration
|
||||||
# This is more of a configuration validation test
|
# This is more of a configuration validation test
|
||||||
|
|
||||||
compose_run_cmd = ["docker-compose", "run", "--rm", "zen-mcp"]
|
compose_run_cmd = ["docker-compose", "run", "--rm", "pal-mcp"]
|
||||||
|
|
||||||
# The command should work with the existing volume configuration
|
# The command should work with the existing volume configuration
|
||||||
assert "docker-compose" in compose_run_cmd
|
assert "docker-compose" in compose_run_cmd
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ Pour plus de détails sur chaque problème identifié, consultez les recommandat
|
|||||||
- [ ] Exécuter les tests de régression
|
- [ ] Exécuter les tests de régression
|
||||||
|
|
||||||
---
|
---
|
||||||
*Analyse générée automatiquement par MCP Zen* 🤖
|
*Analyse générée automatiquement par MCP PAL* 🤖
|
||||||
""",
|
""",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"tool_name": "analyze",
|
"tool_name": "analyze",
|
||||||
@@ -459,13 +459,13 @@ def run_unit_tests():
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main function."""
|
"""Main function."""
|
||||||
print("🇫🇷 UTF-8 Integration Test - Zen MCP Server")
|
print("🇫🇷 UTF-8 Integration Test - PAL MCP Server")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
run_utf8_integration_tests()
|
run_utf8_integration_tests()
|
||||||
print("\n🎉 SUCCESS: All UTF-8 integration tests passed!")
|
print("\n🎉 SUCCESS: All UTF-8 integration tests passed!")
|
||||||
print("🚀 Zen MCP server fully supports French localization!")
|
print("🚀 PAL MCP Server fully supports French localization!")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ This test verifies that when using continuation_id without specifying a model,
|
|||||||
the system correctly retrieves and uses the model from the previous conversation
|
the system correctly retrieves and uses the model from the previous conversation
|
||||||
turn instead of defaulting to DEFAULT_MODEL or the custom provider's default.
|
turn instead of defaulting to DEFAULT_MODEL or the custom provider's default.
|
||||||
|
|
||||||
Bug: https://github.com/BeehiveInnovations/zen-mcp-server/issues/111
|
Bug: https://github.com/BeehiveInnovations/pal-mcp-server/issues/111
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user