Merge remote-tracking branch 'upstream/main' into fix/path-traversal-security

This commit is contained in:
谢栋梁
2025-12-07 00:07:59 +08:00
122 changed files with 1439 additions and 1059 deletions

View File

@@ -11,7 +11,7 @@ __pycache__/
env/
venv/
.venv/
.zen_venv/
.pal_venv/
ENV/
env.bak/
venv.bak/

View File

@@ -1,4 +1,4 @@
# Zen MCP Server Environment Configuration
# PAL MCP Server Environment Configuration
# Copy this file to .env and fill in your values
# API Keys - At least one is required
@@ -191,7 +191,7 @@ DISABLED_TOOLS=analyze,refactor,testgen,secaudit,docgen,tracer
# LOCALE=fr-FR
# ===========================================
# Zen MCP Server Configuration
# PAL MCP Server Configuration
# ===========================================
# 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)
# Production/Container deployments: false (preserves security practices)
# CI/CD environments: false (respects pipeline secrets)
ZEN_MCP_FORCE_ENV_OVERRIDE=false
PAL_MCP_FORCE_ENV_OVERRIDE=false
# ===========================================
# Docker Configuration
@@ -221,7 +221,7 @@ ZEN_MCP_FORCE_ENV_OVERRIDE=false
# Container name for Docker Compose
# Used when running with docker-compose.yml
COMPOSE_PROJECT_NAME=zen-mcp
COMPOSE_PROJECT_NAME=pal-mcp
# Timezone for Docker containers
# Ensures consistent time handling in containerized environments

View File

@@ -12,7 +12,7 @@ body:
attributes:
label: Project Version
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:
required: true
@@ -29,7 +29,7 @@ body:
id: logs
attributes:
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
- type: dropdown

View File

@@ -1,12 +1,12 @@
blank_issues_enabled: false
contact_links:
- 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
- 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
- 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

View File

@@ -1,5 +1,5 @@
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"]
body:
- type: input
@@ -15,7 +15,7 @@ body:
id: purpose
attributes:
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."
validations:
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."
placeholder: |
**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:**
- Analyze all Python files in src/
@@ -61,7 +61,7 @@ body:
id: system-prompt
attributes:
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: |
You are an expert technical documentation generator. Your task is to create comprehensive, user-friendly documentation from source code...

View File

@@ -95,7 +95,7 @@ jobs:
```json
{
"mcpServers": {
"zen": {
"pal": {
"command": "docker",
"args": ["run", "--rm", "-i", "-e", "GEMINI_API_KEY", "ghcr.io/${{ github.repository }}:pr-${{ github.event.number }}"],
"env": { "GEMINI_API_KEY": "your-key" }

View File

@@ -87,7 +87,7 @@ jobs:
\`\`\`json
{
"mcpServers": {
"zen-mcp-server": {
"pal-mcp-server": {
"command": "docker",
"args": [
"run", "--rm", "-i",

2
.gitignore vendored
View File

@@ -179,7 +179,7 @@ CLAUDE.local.md
.claude/settings.local.json
# Standalone mode files
.zen_venv/
.pal_venv/
.docker_cleaned
logs/
*.backup

View File

@@ -28,7 +28,7 @@ exclude: |
\.git/|
\.venv/|
venv/|
\.zen_venv/|
\.pal_venv/|
__pycache__/|
\.pytest_cache/|
logs/|

View File

@@ -5,14 +5,14 @@ See `requirements.txt` and `requirements-dev.txt`
Also read CLAUDE.md and CLAUDE.local.md if available.
## 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/`.
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.
Authoritative documentation and samples live in `docs/`, and runtime diagnostics are rotated in `logs/`.
## 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.
- `./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.
@@ -20,14 +20,14 @@ Authoritative documentation and samples live in `docs/`, and runtime diagnostics
Run code quality checks:
```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:
```bash
.zen_venv/bin/activate && pytest tests/test_auto_mode_model_listing.py -q
.zen_venv/bin/activate && pytest -q
.pal_venv/bin/activate && pytest tests/test_auto_mode_model_listing.py -q
.pal_venv/bin/activate && pytest -q
```
## Coding Style & Naming Conventions

File diff suppressed because it is too large Load Diff

View File

@@ -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
@@ -237,7 +237,7 @@ python -m pytest tests/ -v
### Development Workflow
#### 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`
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
which python
# Should show: .../zen-mcp-server/.zen_venv/bin/python
# Should show: .../pal-mcp-server/.pal_venv/bin/python
```
#### Test Failures
@@ -317,4 +317,4 @@ isort --check-only .
- All dependencies from `requirements.txt` installed
- 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.

View File

@@ -29,18 +29,18 @@ RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
FROM python:3.11-slim AS runtime
# Add metadata labels for traceability
LABEL maintainer="Zen MCP Server Team"
LABEL maintainer="PAL MCP Server Team"
LABEL version="1.0.0"
LABEL description="Zen MCP Server - AI-powered Model Context Protocol server"
LABEL org.opencontainers.image.title="zen-mcp-server"
LABEL description="PAL MCP Server - AI-powered Model Context Protocol 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.version="1.0.0"
LABEL org.opencontainers.image.source="https://github.com/BeehiveInnovations/zen-mcp-server"
LABEL org.opencontainers.image.documentation="https://github.com/BeehiveInnovations/zen-mcp-server/blob/main/README.md"
LABEL org.opencontainers.image.source="https://github.com/BeehiveInnovations/pal-mcp-server"
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"
# 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
RUN apt-get update && apt-get install -y \
@@ -57,20 +57,20 @@ ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
# Copy application code
COPY --chown=zenuser:zenuser . .
COPY --chown=paluser:paluser . .
# 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
RUN mkdir -p tmp && chown -R zenuser:zenuser tmp
RUN mkdir -p tmp && chown -R paluser:paluser tmp
# 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
# Switch to non-root user
USER zenuser
USER paluser
# Health check configuration
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \

View File

@@ -1,8 +1,11 @@
# Zen MCP: Many Workflows. One Context.
# PAL MCP: Many Workflows. One Context.
<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)**
@@ -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?**
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.
### 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.
> **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>
<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:
@@ -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**.
> **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 guide. The prompter. The puppeteer.
> #### 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)
```bash
git clone https://github.com/BeehiveInnovations/zen-mcp-server.git
cd zen-mcp-server
git clone https://github.com/BeehiveInnovations/pal-mcp-server.git
cd pal-mcp-server
# Handles everything: setup, config, API keys from system environment.
# 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
{
"mcpServers": {
"zen": {
"pal": {
"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": {
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
"GEMINI_API_KEY": "your-key-here",
@@ -185,9 +188,9 @@ cd zen-mcp-server
**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"
"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"
```
@@ -197,7 +200,7 @@ cd zen-mcp-server
## 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
@@ -265,7 +268,7 @@ DISABLED_TOOLS=
// In ~/.claude/settings.json or .mcp.json
{
"mcpServers": {
"zen": {
"pal": {
"env": {
// Tool configuration
"DISABLED_TOOLS": "refactor,testgen,secaudit,docgen,tracer",
@@ -292,7 +295,7 @@ DISABLED_TOOLS=
// Remove or empty the DISABLED_TOOLS to enable everything
{
"mcpServers": {
"zen": {
"pal": {
"env": {
"DISABLED_TOOLS": ""
}
@@ -328,7 +331,7 @@ DISABLED_TOOLS=
**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>
@@ -346,26 +349,26 @@ DISABLED_TOOLS=
<details>
<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>
<summary><b>Challenge Tool</b> - Critical thinking vs reflexive agreement</summary>
**Without Zen:**
**Without PAL:**
![without_zen@2x](https://github.com/user-attachments/assets/64f3c9fb-7ca9-4876-b687-25e847edfd87)
![without_pal@2x](https://github.com/user-attachments/assets/64f3c9fb-7ca9-4876-b687-25e847edfd87)
**With Zen:**
**With PAL:**
![with_zen@2x](https://github.com/user-attachments/assets/9d72f444-ba53-4ab1-83e5-250062c6ee70)
![with_pal@2x](https://github.com/user-attachments/assets/9d72f444-ba53-4ab1-83e5-250062c6ee70)
</details>
@@ -444,4 +447,4 @@ Built with the power of **Multi-Model AI** collaboration 🤝
### Star History
[![Star History Chart](https://api.star-history.com/svg?repos=BeehiveInnovations/zen-mcp-server&type=Date)](https://www.star-history.com/#BeehiveInnovations/zen-mcp-server&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=BeehiveInnovations/pal-mcp-server&type=Date)](https://www.star-history.com/#BeehiveInnovations/pal-mcp-server&Date)

81
SECURITY.md Normal file
View 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).

View File

@@ -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",
"comment3": "For platform-specific examples, see the examples/ directory",
"mcpServers": {
"zen": {
"command": "/path/to/zen-mcp-server/.zen_venv/bin/python",
"args": ["/path/to/zen-mcp-server/server.py"]
"pal": {
"command": "/path/to/pal-mcp-server/.pal_venv/bin/python",
"args": ["/path/to/pal-mcp-server/server.py"]
}
}
}

View File

@@ -11,7 +11,7 @@ DEFAULT_STREAM_LIMIT = 10 * 1024 * 1024 # 10MB per stream
PROJECT_ROOT = Path(__file__).resolve().parent.parent
BUILTIN_PROMPTS_DIR = PROJECT_ROOT / "systemprompts" / "clink"
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)

View File

@@ -102,7 +102,7 @@ class ClinkRegistry:
env_path = Path(env_path_raw).expanduser()
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)
seen: set[Path] = set()

View File

@@ -1,9 +1,9 @@
<#
.SYNOPSIS
Code quality checks script for Zen MCP server on Windows.
Code quality checks script for PAL MCP server on Windows.
.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
- Ensures code style compliance and detects potential issues
- Can be integrated into CI/CD pipelines or used locally before commits
@@ -26,7 +26,7 @@
Script Author : GiGiDKR (https://github.com/GiGiDKR)
Date : 07-05-2025
Version : See project documentation
References : https://github.com/BeehiveInnovations/zen-mcp-server
References : https://github.com/BeehiveInnovations/pal-mcp-server
#>
#Requires -Version 5.1
[CmdletBinding()]
@@ -61,23 +61,23 @@ function Write-Emoji {
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
# Determine Python command
$pythonCmd = $null
$pipCmd = $null
if (Test-Path ".zen_venv") {
if (Test-Path ".pal_venv") {
if ($IsWindows -or $env:OS -eq "Windows_NT") {
if (Test-Path ".zen_venv\Scripts\python.exe") {
$pythonCmd = ".zen_venv\Scripts\python.exe"
$pipCmd = ".zen_venv\Scripts\pip.exe"
if (Test-Path ".pal_venv\Scripts\python.exe") {
$pythonCmd = ".pal_venv\Scripts\python.exe"
$pipCmd = ".pal_venv\Scripts\pip.exe"
}
} else {
if (Test-Path ".zen_venv/bin/python") {
$pythonCmd = ".zen_venv/bin/python"
$pipCmd = ".zen_venv/bin/pip"
if (Test-Path ".pal_venv/bin/python") {
$pythonCmd = ".pal_venv/bin/python"
$pipCmd = ".pal_venv/bin/pip"
}
}
@@ -108,11 +108,11 @@ foreach ($tool in $devTools) {
# Check in venv
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
}
} else {
if (Test-Path ".zen_venv/bin/$tool") {
if (Test-Path ".pal_venv/bin/$tool") {
$toolFound = $true
}
}
@@ -152,15 +152,15 @@ if ($devDepsNeeded) {
# Set tool paths
if ($IsWindows -or $env:OS -eq "Windows_NT") {
$ruffCmd = if (Test-Path ".zen_venv\Scripts\ruff.exe") { ".zen_venv\Scripts\ruff.exe" } else { "ruff" }
$blackCmd = if (Test-Path ".zen_venv\Scripts\black.exe") { ".zen_venv\Scripts\black.exe" } else { "black" }
$isortCmd = if (Test-Path ".zen_venv\Scripts\isort.exe") { ".zen_venv\Scripts\isort.exe" } else { "isort" }
$pytestCmd = if (Test-Path ".zen_venv\Scripts\pytest.exe") { ".zen_venv\Scripts\pytest.exe" } else { "pytest" }
$ruffCmd = if (Test-Path ".pal_venv\Scripts\ruff.exe") { ".pal_venv\Scripts\ruff.exe" } else { "ruff" }
$blackCmd = if (Test-Path ".pal_venv\Scripts\black.exe") { ".pal_venv\Scripts\black.exe" } else { "black" }
$isortCmd = if (Test-Path ".pal_venv\Scripts\isort.exe") { ".pal_venv\Scripts\isort.exe" } else { "isort" }
$pytestCmd = if (Test-Path ".pal_venv\Scripts\pytest.exe") { ".pal_venv\Scripts\pytest.exe" } else { "pytest" }
} else {
$ruffCmd = if (Test-Path ".zen_venv/bin/ruff") { ".zen_venv/bin/ruff" } else { "ruff" }
$blackCmd = if (Test-Path ".zen_venv/bin/black") { ".zen_venv/bin/black" } else { "black" }
$isortCmd = if (Test-Path ".zen_venv/bin/isort") { ".zen_venv/bin/isort" } else { "isort" }
$pytestCmd = if (Test-Path ".zen_venv/bin/pytest") { ".zen_venv/bin/pytest" } else { "pytest" }
$ruffCmd = if (Test-Path ".pal_venv/bin/ruff") { ".pal_venv/bin/ruff" } else { "ruff" }
$blackCmd = if (Test-Path ".pal_venv/bin/black") { ".pal_venv/bin/black" } else { "black" }
$isortCmd = if (Test-Path ".pal_venv/bin/isort") { ".pal_venv/bin/isort" } else { "isort" }
$pytestCmd = if (Test-Path ".pal_venv/bin/pytest") { ".pal_venv/bin/pytest" } else { "pytest" }
}
Write-Host ""
@@ -172,25 +172,25 @@ if (!$SkipLinting) {
try {
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) {
throw "Ruff linting failed"
}
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) {
throw "Black formatting failed"
}
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) {
throw "Import sorting failed"
}
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) {
throw "Final linting verification failed"
}

View File

@@ -1,18 +1,18 @@
#!/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.
# ALL checks must pass 100% for CI/CD to succeed.
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 "================================================="
# Determine Python command
if [[ -f ".zen_venv/bin/python" ]]; then
PYTHON_CMD=".zen_venv/bin/python"
PIP_CMD=".zen_venv/bin/pip"
if [[ -f ".pal_venv/bin/python" ]]; then
PYTHON_CMD=".pal_venv/bin/python"
PIP_CMD=".pal_venv/bin/pip"
echo "✅ Using venv"
elif [[ -n "$VIRTUAL_ENV" ]]; then
PYTHON_CMD="python"
@@ -32,7 +32,7 @@ DEV_DEPS_NEEDED=false
# Check each dev dependency
for tool in ruff black isort pytest; do
# 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
else
DEV_DEPS_NEEDED=true
@@ -49,11 +49,11 @@ else
fi
# Set tool paths
if [[ -f ".zen_venv/bin/ruff" ]]; then
RUFF=".zen_venv/bin/ruff"
BLACK=".zen_venv/bin/black"
ISORT=".zen_venv/bin/isort"
PYTEST=".zen_venv/bin/pytest"
if [[ -f ".pal_venv/bin/ruff" ]]; then
RUFF=".pal_venv/bin/ruff"
BLACK=".pal_venv/bin/black"
ISORT=".pal_venv/bin/isort"
PYTEST=".pal_venv/bin/pytest"
else
RUFF="ruff"
BLACK="black"
@@ -67,16 +67,16 @@ echo "📋 Step 1: Running Linting and Formatting Checks"
echo "--------------------------------------------------"
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..."
$BLACK . --exclude="test_simulation_files/" --exclude=".zen_venv/"
$BLACK . --exclude="test_simulation_files/" --exclude=".pal_venv/"
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..."
$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 ""

View File

@@ -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
continuity, file handling, deduplication features, and clarification scenarios.
@@ -145,10 +145,10 @@ class CommunicationSimulator:
if os.path.exists(venv_python):
return venv_python
# Try .zen_venv as fallback
zen_venv_python = os.path.join(current_dir, ".zen_venv", "bin", "python")
if os.path.exists(zen_venv_python):
return zen_venv_python
# Try .pal_venv as fallback
pal_venv_python = os.path.join(current_dir, ".pal_venv", "bin", "python")
if os.path.exists(pal_venv_python):
return pal_venv_python
# Fallback to system python if venv doesn't exist
self.logger.warning("Virtual environment not found, using system python")
@@ -361,7 +361,7 @@ class CommunicationSimulator:
def print_test_summary(self):
"""Print comprehensive test results summary"""
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)
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:
"""Run the complete test suite"""
try:
self.logger.info("Starting Zen MCP Communication Simulator Test Suite")
self.logger.info("Starting PAL MCP Communication Simulator Test Suite")
# Setup
if not self.setup_test_environment():
@@ -450,7 +450,7 @@ class CommunicationSimulator:
def parse_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("--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)")

View File

@@ -1 +1 @@
"""Configuration data for Zen MCP Server."""
"""Configuration data for PAL MCP Server."""

View File

@@ -1,7 +1,7 @@
{
"_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",
"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.",
"field_notes": "Matches providers/shared/model_capabilities.py.",
"field_descriptions": {

View File

@@ -1,7 +1,7 @@
{
"_README": {
"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.",
"field_notes": "Matches providers/shared/model_capabilities.py.",
"field_descriptions": {

View File

@@ -1,7 +1,7 @@
{
"_README": {
"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.",
"field_notes": "Matches providers/shared/model_capabilities.py.",
"field_descriptions": {

View File

@@ -1,7 +1,7 @@
{
"_README": {
"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.",
"field_notes": "Matches providers/shared/model_capabilities.py.",
"field_descriptions": {

View File

@@ -1,7 +1,7 @@
{
"_README": {
"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.",
"field_notes": "Matches providers/shared/model_capabilities.py.",
"field_descriptions": {

View File

@@ -1,7 +1,7 @@
{
"_README": {
"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.",
"field_notes": "Matches providers/shared/model_capabilities.py.",
"field_descriptions": {

View File

@@ -1,7 +1,7 @@
{
"_README": {
"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.",
"field_notes": "Matches providers/shared/model_capabilities.py.",
"field_descriptions": {

View File

@@ -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
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
# IMPORTANT: This is the single source of truth for version and author info
# Semantic versioning: MAJOR.MINOR.PATCH
__version__ = "9.4.1"
__version__ = "9.4.2"
# Last update date in ISO format
__updated__ = "2025-11-21"
__updated__ = "2025-12-05"
# Primary maintainer
__author__ = "Fahad Gilani"

View File

@@ -1,18 +1,18 @@
services:
zen-mcp:
pal-mcp:
build:
context: .
dockerfile: Dockerfile
target: runtime
image: zen-mcp-server:latest
container_name: zen-mcp-server
image: pal-mcp-server:latest
container_name: pal-mcp-server
# Container labels for traceability
labels:
- "com.zen-mcp.service=zen-mcp-server"
- "com.zen-mcp.version=1.0.0"
- "com.zen-mcp.environment=production"
- "com.zen-mcp.description=AI-powered Model Context Protocol server"
- "com.pal-mcp.service=pal-mcp-server"
- "com.pal-mcp.version=1.0.0"
- "com.pal-mcp.environment=production"
- "com.pal-mcp.description=AI-powered Model Context Protocol server"
# Environment variables
environment:
@@ -51,12 +51,12 @@ services:
# Volumes for persistent data
volumes:
- ./logs:/app/logs
- zen-mcp-config:/app/conf
- pal-mcp-config:/app/conf
- /etc/localtime:/etc/localtime:ro
# Network configuration
networks:
- zen-network
- pal-network
# Resource limits
deploy:
@@ -89,12 +89,12 @@ services:
# Named volumes
volumes:
zen-mcp-config:
pal-mcp-config:
driver: local
# Networks
networks:
zen-network:
pal-network:
driver: bridge
ipam:
config:

View File

@@ -1,4 +1,4 @@
# Zen MCP Server - Docker Setup
# PAL MCP Server - Docker Setup
## Quick Start
@@ -22,7 +22,7 @@ nano .env
```bash
# Build the Docker image
docker build -t zen-mcp-server:latest .
docker build -t pal-mcp-server:latest .
# Or use the build script (Bash)
chmod +x docker/scripts/build.sh
@@ -41,14 +41,14 @@ docker/scripts/build.ps1
# Run with environment file
docker run --rm -i --env-file .env \
-v $(pwd)/logs:/app/logs \
zen-mcp-server:latest
pal-mcp-server:latest
# Run with inline environment variables
docker run --rm -i \
-e GEMINI_API_KEY="your_key_here" \
-e LOG_LEVEL=INFO \
-v $(pwd)/logs:/app/logs \
zen-mcp-server:latest
pal-mcp-server:latest
```
#### B. Docker Compose (For Development/Monitoring)
@@ -62,7 +62,7 @@ chmod +x docker/scripts/deploy.sh
docker/scripts/deploy.ps1
# Interactive stdio mode
docker-compose exec zen-mcp python server.py
docker-compose exec pal-mcp python server.py
```
## Service Management
@@ -76,8 +76,8 @@ docker ps
# View logs from container
docker logs <container_id>
# Stop all zen-mcp containers
docker stop $(docker ps -q --filter "ancestor=zen-mcp-server:latest")
# Stop all pal-mcp containers
docker stop $(docker ps -q --filter "ancestor=pal-mcp-server:latest")
# Remove old containers and images
docker container prune
@@ -88,20 +88,20 @@ docker image prune
```bash
# View logs
docker-compose logs -f zen-mcp
docker-compose logs -f pal-mcp
# Check status
docker-compose ps
# Restart service
docker-compose restart zen-mcp
docker-compose restart pal-mcp
# Stop services
docker-compose down
# Rebuild and update
docker-compose build --no-cache zen-mcp
docker-compose up -d zen-mcp
docker-compose build --no-cache pal-mcp
docker-compose up -d pal-mcp
```
## 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:
- **`./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)
### 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:
```yaml
volumes:
- ./logs:/app/logs
- zen-mcp-config:/app/conf
- pal-mcp-config:/app/conf
- /etc/localtime:/etc/localtime:ro
```
@@ -137,13 +137,13 @@ and the named volume definition:
```yaml
volumes:
zen-mcp-config:
pal-mcp-config:
driver: local
```
## Security
- Runs as non-root user `zenuser`
- Runs as non-root user `paluser`
- Read-only filesystem with tmpfs for temporary files
- No network ports exposed (stdio communication only)
- Secrets managed via environment variables
@@ -154,16 +154,16 @@ volumes:
```bash
# Check if image exists
docker images zen-mcp-server
docker images pal-mcp-server
# 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
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
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
@@ -173,7 +173,7 @@ docker run --rm -i -e GEMINI_API_KEY="test" zen-mcp-server:latest python server.
docker run --rm hello-world
# 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
```
@@ -182,10 +182,10 @@ echo '{"jsonrpc": "2.0", "method": "ping"}' | docker run --rm -i --env-file .env
```bash
# 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
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
@@ -205,10 +205,10 @@ chmod 755 logs/
docker stats
# 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
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)
@@ -218,17 +218,17 @@ docker run --rm -i --env-file .env zen-mcp-server:latest 2>&1 | tee docker.log
```json
{
"servers": {
"zen-docker": {
"pal-docker": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--env-file",
"/absolute/path/to/zen-mcp-server/.env",
"/absolute/path/to/pal-mcp-server/.env",
"-v",
"/absolute/path/to/zen-mcp-server/logs:/app/logs",
"zen-mcp-server:latest"
"/absolute/path/to/pal-mcp-server/logs:/app/logs",
"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
{
"servers": {
"zen-docker": {
"pal-docker": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--env-file",
"C:/Users/YourName/path/to/zen-mcp-server/.env",
"C:/Users/YourName/path/to/pal-mcp-server/.env",
"-v",
"C:/Users/YourName/path/to/zen-mcp-server/logs:/app/logs",
"zen-mcp-server:latest"
"C:/Users/YourName/path/to/pal-mcp-server/logs:/app/logs",
"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
{
"servers": {
"zen-docker": {
"pal-docker": {
"command": "docker-compose",
"args": [
"-f",
"/absolute/path/to/zen-mcp-server/docker-compose.yml",
"/absolute/path/to/pal-mcp-server/docker-compose.yml",
"run",
"--rm",
"zen-mcp"
"pal-mcp"
]
}
}
@@ -304,10 +304,10 @@ CUSTOM_API_URL=
```bash
# 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
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
@@ -315,7 +315,7 @@ docker run --rm -e GEMINI_API_KEY="test" zen-mcp-server:latest python /usr/local
```bash
# Test basic MCP communication
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
@@ -330,7 +330,7 @@ python -m json.tool .vscode/mcp.json
## 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
- **thinkdeep** - Multi-stage investigation and reasoning

View File

@@ -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
if (!(Test-Path ".env")) {
@@ -49,7 +49,7 @@ try {
# Verify the build
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) {
Write-ColorText "✓ Docker image built successfully" -Color Green

View File

@@ -7,7 +7,7 @@ YELLOW='\033[1;33m'
RED='\033[0;31m'
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
if [[ ! -f .env ]]; then
@@ -26,10 +26,10 @@ echo -e "${GREEN}Building Docker image...${NC}"
docker-compose build --no-cache
# 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}Image details:${NC}"
docker images | grep zen-mcp-server
docker images | grep pal-mcp-server
else
echo -e "${RED}✗ Failed to build Docker image${NC}"
exit 1

View File

@@ -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 Test-EnvironmentVariables {
@@ -91,8 +91,8 @@ function Wait-ForHealth {
while ($attempt -le $MaxAttempts) {
try {
# Get container ID for zen-mcp service
$containerId = docker-compose ps -q zen-mcp
# Get container ID for pal-mcp service
$containerId = docker-compose ps -q pal-mcp
if ([string]::IsNullOrWhiteSpace($containerId)) {
$status = "unavailable"
} else {
@@ -119,7 +119,7 @@ function Wait-ForHealth {
Write-ColorText "Service failed to become healthy after $MaxAttempts attempts" -Color Red
Write-ColorText "Checking logs:" -Color Yellow
docker-compose logs zen-mcp
docker-compose logs pal-mcp
return $false
}
@@ -141,7 +141,7 @@ try {
}
# Start the services
Write-ColorText "Starting Zen MCP Server..." -Color Green
Write-ColorText "Starting PAL MCP Server..." -Color Green
try {
docker-compose up -d
if ($LASTEXITCODE -ne 0) {
@@ -150,7 +150,7 @@ try {
} catch {
Write-ColorText "Error: Failed to start services" -Color Red
Write-ColorText "Checking logs:" -Color Yellow
docker-compose logs zen-mcp
docker-compose logs pal-mcp
exit 1
}
@@ -165,7 +165,7 @@ if (!$SkipHealthCheck) {
while ($elapsed -lt $timeout) {
try {
$containerId = docker-compose ps -q zen-mcp
$containerId = docker-compose ps -q pal-mcp
if (![string]::IsNullOrWhiteSpace($containerId)) {
$status = docker inspect -f "{{.State.Health.Status}}" $containerId 2>$null
if ($status -eq "healthy") {
@@ -186,26 +186,26 @@ if (!$SkipHealthCheck) {
if (!(Wait-ForHealth)) {
Write-ColorText "Service failed to become healthy" -Color Red
Write-ColorText "Checking logs:" -Color Yellow
docker-compose logs zen-mcp
docker-compose logs pal-mcp
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
docker-compose ps
Write-ColorText "=== Deployment Complete ===" -Color Green
Write-ColorText "Useful commands:" -Color Yellow
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 "docker-compose down" -Color Green
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 "Get-Content logs\mcp_server.log -Wait" -Color Green

View File

@@ -7,7 +7,7 @@ YELLOW='\033[1;33m'
RED='\033[0;31m'
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
check_env_vars() {
@@ -51,7 +51,7 @@ wait_for_health() {
local delay=2
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
return 0
fi
@@ -63,7 +63,7 @@ wait_for_health() {
echo -e "${RED}Service failed to become healthy after $max_attempts attempts${NC}"
echo -e "${YELLOW}Checking logs:${NC}"
docker-compose logs zen-mcp
docker-compose logs pal-mcp
exit 1
}
@@ -75,25 +75,25 @@ echo -e "${GREEN}Stopping existing containers...${NC}"
docker-compose down
# Start the services
echo -e "${GREEN}Starting Zen MCP Server...${NC}"
echo -e "${GREEN}Starting PAL MCP Server...${NC}"
docker-compose up -d
# Wait for health check
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
echo -e "${RED}Service failed to become healthy${NC}"
echo -e "${YELLOW}Checking logs:${NC}"
docker-compose logs zen-mcp
docker-compose logs pal-mcp
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}"
docker-compose ps
echo -e "${GREEN}=== Deployment Complete ===${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 " Restart service: ${GREEN}docker-compose restart zen-mcp${NC}"
echo -e " Restart service: ${GREEN}docker-compose restart pal-mcp${NC}"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""
Health check script for Zen MCP Server Docker container
Health check script for PAL MCP Server Docker container
"""
import os

View File

@@ -1,6 +1,6 @@
# 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

View File

@@ -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
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).
@@ -8,7 +8,7 @@ This document captures the minimal steps required to add a new tool without drif
## 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.
The base class handles schema generation, conversation threading, file loading, temperature bounds, retries,

View File

@@ -1,6 +1,6 @@
# 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
@@ -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"
# 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
"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
**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**
@@ -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
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
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
```
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
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
@@ -343,7 +343,7 @@ To help choose the right tool for your needs:
## 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:**
- **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:**
```bash
# 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
"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]"
# 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
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."

View File

@@ -12,7 +12,7 @@ It's happened more times than I can count, but I figured its time I start sav
⏺ 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",
"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 its time I start sav
⏺ The flash model declined to answer the simple math question, explaining it's focused on engineering topics.
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")
⎿ {
"status": "continuation_available",
@@ -57,7 +57,7 @@ It's happened more times than I can count, but I figured its time I start sav
⏺ 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",
"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 its time I start sav
⏺ 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",
"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 its time I start sav
> 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",
"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 its 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.
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",
"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 its time I start sav
> 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",
"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 its 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.
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",
"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

View File

@@ -1,6 +1,6 @@
# 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

View File

@@ -1,6 +1,6 @@
# 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
@@ -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
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
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
**Example Configuration:**
@@ -143,8 +143,8 @@ The `allow_code_generation` capability enables models to generate complete, prod
**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**
2. GPT-5-Pro generates structured implementation and shares the complete implementation with Zen
3. Zen saves the code to `zen_generated.code` and asks AI agent to implement the plan
2. GPT-5-Pro generates structured implementation and shares the complete implementation with PAL
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
### Thinking Mode Configuration

View File

@@ -2,7 +2,7 @@
## **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
@@ -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
* 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">
@@ -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:
**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..."
→ Uses [`thinkdeep`](../README.md#1-chat---general-development-chat--collaborative-thinking) to brainstorm the overall approach
Zen creates a new thread: abc123-def456-ghi789
Zen responds, Claude finalizes the plan and presents it to you
PAL creates a new thread: abc123-def456-ghi789
PAL responds, Claude finalizes the plan and presents it to you
*[Claude's context gets reset/compacted after extensive analysis]*
**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"
→ 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
→ O3 receives the FULL conversation history from Zen
→ 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 PAL
→ 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'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
**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
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
- **Gemini Pro** performs deep architectural reviews
- **Flash** provides quick formatting and style checks

View File

@@ -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
@@ -245,4 +245,4 @@ Contributors are recognized in:
- Release notes for significant contributions
- 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.

View File

@@ -1,6 +1,6 @@
# 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
@@ -35,7 +35,7 @@ This guide covers setting up multiple AI model providers including OpenRouter, c
## Model Aliases
Zen ships multiple registries:
PAL ships multiple registries:
- `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`)
@@ -148,7 +148,7 @@ CUSTOM_MODEL_NAME=llama3.2 # Default model to use
**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
# For Ollama, vLLM, LM Studio, etc. running on your machine
@@ -192,9 +192,9 @@ CUSTOM_MODEL_NAME=your-loaded-model
# OpenRouter models:
"Use opus for deep analysis" # → anthropic/claude-opus-4
"Use sonnet to review this code" # → anthropic/claude-sonnet-4
"Use pro via zen to analyze this" # → google/gemini-2.5-pro
"Use gpt4o via zen to analyze this" # → openai/gpt-4o
"Use mistral via zen to optimize" # → mistral/mistral-large
"Use pro via pal to analyze this" # → google/gemini-2.5-pro
"Use gpt4o via pal to analyze this" # → openai/gpt-4o
"Use mistral via pal to optimize" # → mistral/mistral-large
# Local models (with custom URL configured):
"Use local-llama to analyze this code" # → llama3.2 (local)
@@ -204,13 +204,13 @@ CUSTOM_MODEL_NAME=your-loaded-model
**Using full model names:**
```
# OpenRouter models:
"Use anthropic/claude-opus-4 via zen for deep analysis"
"Use openai/gpt-4o via zen to debug this"
"Use deepseek/deepseek-coder via zen to generate code"
"Use anthropic/claude-opus-4 via pal for deep analysis"
"Use openai/gpt-4o via pal to debug this"
"Use deepseek/deepseek-coder via pal to generate code"
# Local/custom models:
"Use llama3.2 via zen to review this"
"Use meta-llama/Llama-2-7b-chat-hf via zen to analyze"
"Use llama3.2 via pal to review this"
"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).

View File

@@ -1,13 +1,13 @@
# 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
1. **Clone the repository**:
```bash
git clone https://github.com/BeehiveInnovations/zen-mcp-server.git
cd zen-mcp-server
git clone https://github.com/BeehiveInnovations/pal-mcp-server.git
cd pal-mcp-server
```
2. **Configure environment variables**:
@@ -113,7 +113,7 @@ The Dockerfile uses a multi-stage build for optimal image size:
### 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
- **No new privileges**: Prevents privilege escalation
- **Secure tmpfs**: Temporary directories with strict permissions
@@ -151,10 +151,10 @@ docker-compose up
docker-compose ps
# Follow logs
docker-compose logs -f zen-mcp
docker-compose logs -f pal-mcp
# View health status
docker inspect zen-mcp-server --format='{{.State.Health.Status}}'
docker inspect pal-mcp-server --format='{{.State.Health.Status}}'
```
### Stopping the Service
@@ -191,10 +191,10 @@ healthcheck:
### Volumes
- **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
**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
@@ -209,7 +209,7 @@ LOG_BACKUP_COUNT=5 # Number of backup files to keep
### Default Configuration
- **Network**: `zen-network` (bridge)
- **Network**: `pal-network` (bridge)
- **Subnet**: `172.20.0.0/16`
- **Isolation**: Container runs in isolated network
@@ -230,10 +230,10 @@ ports:
**1. Health check failures:**
```bash
# Check logs
docker-compose logs zen-mcp
docker-compose logs pal-mcp
# 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:**
@@ -252,7 +252,7 @@ cat .env
**4. API key validation errors:**
```bash
# 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
@@ -295,10 +295,10 @@ Consider integrating with monitoring solutions:
Backup persistent volumes:
```bash
# 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
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
@@ -319,7 +319,7 @@ deploy:
Monitor memory usage:
```bash
docker stats zen-mcp-server
docker stats pal-mcp-server
```
Adjust Python memory settings if needed:
@@ -339,17 +339,17 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
```json
{
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--env-file",
"/absolute/path/to/zen-mcp-server/.env",
"/absolute/path/to/pal-mcp-server/.env",
"-v",
"/absolute/path/to/zen-mcp-server/logs:/app/logs",
"zen-mcp-server:latest"
"/absolute/path/to/pal-mcp-server/logs:/app/logs",
"pal-mcp-server:latest"
]
}
}
@@ -360,17 +360,17 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
```json
{
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--env-file",
"C:/path/to/zen-mcp-server/.env",
"C:/path/to/pal-mcp-server/.env",
"-v",
"C:/path/to/zen-mcp-server/logs:/app/logs",
"zen-mcp-server:latest"
"C:/path/to/pal-mcp-server/logs:/app/logs",
"pal-mcp-server:latest"
]
}
}
@@ -384,11 +384,11 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
```json
{
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"command": "docker-compose",
"args": [
"-f", "/absolute/path/to/zen-mcp-server/docker-compose.yml",
"run", "--rm", "zen-mcp"
"-f", "/absolute/path/to/pal-mcp-server/docker-compose.yml",
"run", "--rm", "pal-mcp"
]
}
}
@@ -402,7 +402,7 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
```json
{
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"command": "docker",
"args": [
"run",
@@ -412,7 +412,7 @@ Configure Claude Desktop to use the containerized server. **Choose one of the co
"-e", "LOG_LEVEL=INFO",
"-e", "DEFAULT_MODEL=auto",
"-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
**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.
- 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:**
```env
@@ -436,7 +436,7 @@ OPENAI_API_KEY=your_openai_key
```
**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.
- Permission issues: make sure the `logs` folder is writable.
@@ -447,7 +447,7 @@ OPENAI_API_KEY=your_openai_key
For complex deployments:
```yaml
networks:
zen-network:
pal-network:
driver: bridge
ipam:
config:
@@ -483,7 +483,7 @@ docker-compose build --no-cache
### 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.

View File

@@ -1,13 +1,13 @@
# 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.
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
- Zen MCP Server installed and configured
- PAL MCP Server installed and configured
- Gemini CLI installed
- 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
{
"mcpServers": {
"zen": {
"command": "/path/to/zen-mcp-server/zen-mcp-server"
"pal": {
"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
#!/bin/bash
DIR="$(cd "$(dirname "$0")" && pwd)"
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.
All 15 Zen tools are now available in your Gemini CLI session.
All 15 PAL tools are now available in your Gemini CLI session.

View File

@@ -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
@@ -77,11 +77,11 @@ Choose your AI coding assistant and add the corresponding configuration:
```json
{
"mcpServers": {
"zen": {
"pal": {
"command": "sh",
"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"
"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": {
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
@@ -98,11 +98,11 @@ Create `.mcp.json` in your project root:
```json
{
"mcpServers": {
"zen": {
"pal": {
"command": "sh",
"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"
"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": {
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
@@ -119,11 +119,11 @@ Edit `~/.gemini/settings.json`:
```json
{
"mcpServers": {
"zen": {
"pal": {
"command": "sh",
"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"
"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": {
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
@@ -138,17 +138,17 @@ Edit `~/.gemini/settings.json`:
Edit `~/.codex/config.toml`:
```toml
[mcp_servers.zen]
[mcp_servers.pal]
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
[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"
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
[tools]
@@ -164,13 +164,13 @@ Create or edit `~/.qwen/settings.json`:
```json
{
"mcpServers": {
"zen": {
"pal": {
"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"
"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": {
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin",
"GEMINI_API_KEY": "your_api_key_here"
@@ -189,13 +189,13 @@ Edit `~/.config/opencode/opencode.json`:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"zen": {
"pal": {
"type": "local",
"command": [
"/path/to/zen-mcp-server/.zen_venv/bin/python",
"/path/to/zen-mcp-server/server.py"
"/path/to/pal-mcp-server/.pal_venv/bin/python",
"/path/to/pal-mcp-server/server.py"
],
"cwd": "/path/to/zen-mcp-server",
"cwd": "/path/to/pal-mcp-server",
"enabled": true,
"environment": {
"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)
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**
1. Open Cursor → `Settings` (`Cmd+,`/`Ctrl+,`) → **Integrations Model Context Protocol (MCP)**.
2. Click **Add MCP Server** and supply the following values:
- 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):
- `PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:~/.local/bin`
- `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`)
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:**
- ✅ Zero manual setup required
@@ -244,8 +244,8 @@ Zen works in GUI IDEs that speak MCP. The configuration mirrors the CLI examples
```bash
# Clone the repository
git clone https://github.com/BeehiveInnovations/zen-mcp-server.git
cd zen-mcp-server
git clone https://github.com/BeehiveInnovations/pal-mcp-server.git
cd pal-mcp-server
# One-command setup (handles everything)
./run-server.sh
@@ -305,7 +305,7 @@ CUSTOM_MODEL_NAME=llama3.2 # Default model name
## 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
@@ -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: Claudes 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: Claudes 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 exposes per-server timeouts in `~/.codex/config.toml`. Add (or bump) these keys under `[[mcp_servers.<name>]]`:
```toml
[mcp_servers.zen]
[mcp_servers.pal]
command = "..."
args = ["..."]
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
{
"mcpServers": {
"zen": {
"pal": {
"command": "uvx",
"args": ["zen-mcp-server"],
"args": ["pal-mcp-server"],
"timeout": 300000
}
}
@@ -364,62 +364,62 @@ Versions 0.2.1 and newer currently ignore values above ~60 seconds for some tran
### For Claude Desktop:
1. Restart Claude Desktop
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:
1. Exit any existing Claude session
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:
**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:
1. Restart the Qwen Code CLI if it's running (`qwen exit`).
2. Run `qwen mcp list --scope user` and confirm `zen` shows `CONNECTED`.
3. Try: `"/mcp"` to inspect available tools or `"Use zen to analyze this repo"`.
2. Run `qwen mcp list --scope user` and confirm `pal` shows `CONNECTED`.
3. Try: `"/mcp"` to inspect available tools or `"Use pal to analyze this repo"`.
### For OpenCode CLI:
1. Restart OpenCode (or run `OpenCode: Reload Config`).
2. Open **Settings Tools MCP** and confirm `zen` is enabled.
3. Start a new chat and try: `"Use zen to list available models"`.
2. Open **Settings Tools MCP** and confirm `pal` is enabled.
3. Start a new chat and try: `"Use pal to list available models"`.
### For Codex CLI:
1. Restart Codex CLI if running
2. Open a new conversation
3. Try: `"Use zen to list available models"`
3. Try: `"Use pal to list available models"`
### Test Commands:
```
"Use zen to list available models"
"Chat with zen about the best approach for API design"
"Use zen thinkdeep with gemini pro about scaling strategies"
"Use pal to list available models"
"Chat with pal about the best approach for API design"
"Use pal thinkdeep with gemini pro about scaling strategies"
"Debug this error with o3: [paste error]"
```
**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:
**Let Claude pick the model:**
```
"Use zen to analyze this code for security issues"
"Debug this race condition with zen"
"Plan the database migration with zen"
"Use pal to analyze this code for security issues"
"Debug this race condition with pal"
"Plan the database migration with pal"
```
**Specify the model:**
```
"Use zen with gemini pro to review this complex algorithm"
"Debug with o3 using zen for logical analysis"
"Get flash to quickly format this code via zen"
"Use pal with gemini pro to review this complex algorithm"
"Debug with o3 using pal for logical analysis"
"Get flash to quickly format this code via pal"
```
**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"
"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
### "zen not found" or "command not found"
### "pal not found" or "command not found"
**For uvx installations:**
- 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:**
- 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
@@ -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
**"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
- Verify API key has access to requested models

View File

@@ -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 |
|----------|-------------|

View File

@@ -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.

5
docs/name-change.md Normal file
View 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`.

View File

@@ -5,7 +5,7 @@ Most importantly, it does this within in a sub-process / sub-agent, saving you p
## 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?"
@@ -17,11 +17,11 @@ Result: You get outdated APIs for iOS 18, not the iOS 26 effect you're after
<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>
### With Zen (Using apilookup)
### With PAL (Using apilookup)
```
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">
[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>
@@ -110,7 +110,7 @@ The AI then performs the actual web searches and synthesizes the results into ac
## 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
[tools]

View File

@@ -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
to ensure thoughtful analysis instead of reflexive agreement.
**Without Zen:**
![without_zen@2x](https://github.com/user-attachments/assets/64f3c9fb-7ca9-4876-b687-25e847edfd87)
**Without PAL:**
![without_pal@2x](https://github.com/user-attachments/assets/64f3c9fb-7ca9-4876-b687-25e847edfd87)
**With Zen:**
![with_zen@2x](https://github.com/user-attachments/assets/9d72f444-ba53-4ab1-83e5-250062c6ee70)
**With PAL:**
![with_pal@2x](https://github.com/user-attachments/assets/9d72f444-ba53-4ab1-83e5-250062c6ee70)
## Why Use Challenge?

View File

@@ -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
* 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">
@@ -39,7 +39,7 @@ word verdict in the end.
- **Collaborative thinking partner** for your analysis and planning
- **Get second opinions** on your designs and approaches
- **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
- **General development questions** and explanations
- **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
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
3. Zen saves the code to `zen_generated.code` and asks AI agent to implement the plan
2. The model generates structured implementation and shares the complete implementation with PAL
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
### When Code Generation Activates
@@ -101,7 +101,7 @@ See the [Configuration Guide](../configuration.md#code-generation-capability) fo
**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:**

View File

@@ -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
- **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
- **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
## Available Roles
@@ -120,18 +120,18 @@ then codereview to verify the implementation"
## How Clink Works
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
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
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
- **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
- **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)
## Configuration
@@ -153,9 +153,9 @@ Each preset points to role-specific prompts in `systemprompts/clink/`. Duplicate
## 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 `chat`** for: Direct model-to-model conversations within Zen
- **Use `planner`** for: Zen's native planning workflows with step validation
- **Use `codereview`** for: Zen's structured code review with severity levels
- **Use `chat`** for: Direct model-to-model conversations within PAL
- **Use `planner`** for: PAL's native planning workflows with step validation
- **Use `codereview`** for: PAL's structured code review with severity levels
## Setup Requirements
@@ -168,7 +168,7 @@ Ensure the relevant CLI is installed and configured:
## Related Guides
- [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
- [Context Revival](../context-revival.md) - Continuing conversations across tools
- [Advanced Usage](../advanced-usage.md) - Complex multi-tool workflows

View File

@@ -27,7 +27,7 @@ The following is a hypothetical example designed to demonstrate how one consensu
<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>
@@ -35,7 +35,7 @@ The following is a hypothetical example designed to demonstrate how one consensu
**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
```

View File

@@ -32,7 +32,7 @@ Documentation generation excels with analytical models like Gemini Pro or O3, wh
**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"
"Add comprehensive documentation to all methods in src/payment_processor.py"
```

View File

@@ -7,7 +7,7 @@ The `listmodels` tool shows which providers are configured, available models, th
## Usage
```
"Use zen to list available models"
"Use pal to list available models"
```
## Key Features

View File

@@ -19,7 +19,7 @@ The planner tool enables step-by-step thinking with incremental plan building:
#### Pro Tip
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
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
@@ -73,10 +73,10 @@ Develop a plan using zen for implementing CI/CD pipelines across our development
## 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

View File

@@ -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)
- 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
- **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
@@ -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:
```
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
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
@@ -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
```
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
```
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
@@ -155,7 +155,7 @@ Use zen and perform a thorough precommit ensuring there aren't any new regressio
**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:**

View File

@@ -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"
"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:
```
"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"
```

View File

@@ -35,7 +35,7 @@ Test generation excels with extended reasoning models like Gemini Pro or O3, whi
**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"
"Create tests for edge cases not already covered in our tests using gemini pro"
```

View File

@@ -36,13 +36,13 @@ The `tracer` tool is a specialized prompt-generation tool that creates structure
**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
**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

View File

@@ -2,12 +2,12 @@
**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
```
"Get zen to show its version"
"Get pal to show its version"
```
## Key Features
@@ -48,7 +48,7 @@ The tool provides:
## Example Output
```
🔧 Zen MCP Server Information
🔧 PAL MCP Server Information
📋 Version: 2.15.0
🏗️ Build: 2024-01-15T10:30:00Z (commit: abc123f)

View File

@@ -2,12 +2,12 @@
## 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
Open Claude Desktop and type `/mcp` to see if zen is connected:
- ✅ If zen appears in the list, the connection is working
Open Claude Desktop and type `/mcp` to see if pal is connected:
- ✅ If pal appears in the list, the connection is working
- ❌ If not listed or shows an error, continue to step 2
### 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**
- 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
**Virtual Environment Problems**
```bash
# Reset environment completely
rm -rf .zen_venv
rm -rf .pal_venv
./run-server.sh
```

View File

@@ -1,6 +1,6 @@
# 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
@@ -27,8 +27,8 @@ npm install -g @anthropic-ai/claude-code
cd ~
# Clone the repository
git clone https://github.com/BeehiveInnovations/zen-mcp-server.git
cd zen-mcp-server
git clone https://github.com/BeehiveInnovations/pal-mcp-server.git
cd pal-mcp-server
```
2. **Run the setup script**:
@@ -43,7 +43,7 @@ npm install -g @anthropic-ai/claude-code
# List configured MCP servers
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
```
@@ -61,19 +61,19 @@ python3 -m pip install --upgrade pip
### 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
### Claude Code Connection Issues
```bash
# 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
# Example: "/home/YourName/zen-mcp-server/.zen_venv/bin/python"
# Example: "/home/YourName/pal-mcp-server/.pal_venv/bin/python"
```
### 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/...`).

View File

@@ -3,9 +3,9 @@
"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",
"mcpServers": {
"zen": {
"command": "/path/to/zen-mcp-server/.zen_venv/bin/python",
"args": ["/path/to/zen-mcp-server/server.py"]
"pal": {
"command": "/path/to/pal-mcp-server/.pal_venv/bin/python",
"args": ["/path/to/pal-mcp-server/server.py"]
}
}
}

View File

@@ -3,11 +3,11 @@
"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",
"mcpServers": {
"zen": {
"pal": {
"command": "wsl.exe",
"args": [
"/path/to/zen-mcp-server/.zen_venv/bin/python",
"/path/to/zen-mcp-server/server.py"
"/path/to/pal-mcp-server/.pal_venv/bin/python",
"/path/to/pal-mcp-server/server.py"
]
}
}

View File

@@ -4,8 +4,8 @@
# Get the directory of this script
DIR="$(cd "$(dirname "$0")" && pwd)"
# Change to the zen-mcp-server directory
# Change to the pal-mcp-server directory
cd "$DIR"
# Execute the Python server with all arguments passed through
exec .zen_venv/bin/python server.py "$@"
exec .pal_venv/bin/python server.py "$@"

View File

@@ -35,9 +35,9 @@ class OpenRouterProvider(OpenAICompatibleProvider):
# Custom headers required by OpenRouter
DEFAULT_HEADERS = {
"HTTP-Referer": get_env("OPENROUTER_REFERER", "https://github.com/BeehiveInnovations/zen-mcp-server")
or "https://github.com/BeehiveInnovations/zen-mcp-server",
"X-Title": get_env("OPENROUTER_TITLE", "Zen MCP Server") or "Zen MCP Server",
"HTTP-Referer": get_env("OPENROUTER_REFERER", "https://github.com/BeehiveInnovations/pal-mcp-server")
or "https://github.com/BeehiveInnovations/pal-mcp-server",
"X-Title": get_env("OPENROUTER_TITLE", "PAL MCP Server") or "PAL MCP Server",
}
# Model registry for managing configurations and aliases

View File

@@ -1,6 +1,6 @@
[project]
name = "zen-mcp-server"
version = "9.4.1"
name = "pal-mcp-server"
version = "9.4.2"
description = "AI-powered MCP server with multiple model providers"
requires-python = ">=3.9"
dependencies = [
@@ -36,7 +36,7 @@ py-modules = ["server", "config"]
]
[project.scripts]
zen-mcp-server = "server:run"
pal-mcp-server = "server:run"
[tool.black]
line-length = 120
@@ -51,7 +51,7 @@ extend-exclude = '''
| \.mypy_cache
| \.tox
| \.venv
| \.zen_venv
| \.pal_venv
| venv
| _build
| buck-out
@@ -68,7 +68,7 @@ force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true
line_length = 120
skip_glob = ["venv/*", ".venv/*", ".zen_venv/*"]
skip_glob = ["venv/*", ".venv/*", ".pal_venv/*"]
[tool.ruff]
target-version = "py39"

View File

@@ -1,9 +1,9 @@
<#
.SYNOPSIS
Installation, configuration, and launch script for Zen MCP server on Windows.
Installation, configuration, and launch script for PAL MCP server on Windows.
.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 required Python dependencies
- Configures environment files (.env)
@@ -17,7 +17,7 @@
Shows script help.
.PARAMETER Version
Shows Zen MCP server version.
Shows PAL MCP server version.
.PARAMETER Follow
Follows server logs in real time.
@@ -48,7 +48,7 @@
.EXAMPLE
.\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
Follows server logs in real time.
@@ -73,7 +73,7 @@
Script Author : GiGiDKR (https://github.com/GiGiDKR)
Date : 07-05-2025
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
@@ -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,
# dependency installation, and configuration.
@@ -106,11 +106,12 @@ $ErrorActionPreference = "Stop"
# Constants and Configuration
# ----------------------------------------------------------------------------
$script:VENV_PATH = ".zen_venv"
$script:VENV_PATH = ".pal_venv"
$script:DOCKER_CLEANED_FLAG = ".docker_cleaned"
$script:DESKTOP_CONFIG_FLAG = ".desktop_configured"
$script:LOG_DIR = "logs"
$script:LOG_FILE = "mcp_server.log"
$script:LegacyServerNames = @("zen", "zen-mcp", "zen-mcp-server", "zen_mcp", "zen_mcp_server")
# ----------------------------------------------------------------------------
# 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
function Manage-ConfigBackups {
param(
@@ -382,9 +408,9 @@ function Cleanup-Docker {
$containers = @(
"gemini-mcp-server",
"gemini-mcp-redis",
"zen-mcp-server",
"zen-mcp-redis",
"zen-mcp-log-monitor"
"pal-mcp-server",
"pal-mcp-redis",
"pal-mcp-log-monitor"
)
# Remove containers
@@ -407,7 +433,7 @@ function Cleanup-Docker {
}
# Remove images
$images = @("gemini-mcp-server:latest", "zen-mcp-server:latest")
$images = @("gemini-mcp-server:latest", "pal-mcp-server:latest")
foreach ($image in $images) {
try {
$exists = docker images --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -eq $image }
@@ -786,7 +812,7 @@ function Build-DockerImage {
# Check if image exists
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) {
Write-Success "Docker image already exists. Use -Force to rebuild."
return $true
@@ -799,7 +825,7 @@ function Build-DockerImage {
if ($Force -and $imageExists) {
Write-Info "Forcing rebuild of Docker image..."
try {
docker rmi zen-mcp-server:latest 2>$null
docker rmi pal-mcp-server:latest 2>$null
}
catch {
Write-Warning "Could not remove existing image, continuing..."
@@ -814,7 +840,7 @@ function Build-DockerImage {
Write-Info "Building with development support..."
}
docker build -t zen-mcp-server:latest .
docker build -t pal-mcp-server:latest .
if ($LASTEXITCODE -ne 0) {
throw "Docker build failed"
}
@@ -901,7 +927,7 @@ function Start-DockerServices {
}
# 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 ($Follow) {
docker-compose up --build
@@ -925,10 +951,10 @@ function Start-DockerServices {
if (!$Follow) {
Write-Success "Docker services started successfully"
Write-Info "Container name: zen-mcp-server"
Write-Info "Container name: pal-mcp-server"
Write-Host ""
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 "docker-compose down" -ForegroundColor Yellow
}
@@ -944,7 +970,7 @@ function Start-DockerServices {
# Get Docker container status
function Get-DockerStatus {
try {
$containerStatus = docker ps --filter "name=zen-mcp-server" --format "{{.Status}}"
$containerStatus = docker ps --filter "name=pal-mcp-server" --format "{{.Status}}"
if ($containerStatus) {
Write-Success "Container status: $containerStatus"
return $true
@@ -1018,7 +1044,7 @@ $script:McpClientDefinitions = @(
DetectionPath = "$env:APPDATA\Claude\claude_desktop_config.json"
DetectionType = "Path"
ConfigPath = "$env:APPDATA\Claude\claude_desktop_config.json"
ConfigJsonPath = "mcpServers.zen"
ConfigJsonPath = "mcpServers.pal"
NeedsConfigDir = $true
},
@{
@@ -1026,7 +1052,7 @@ $script:McpClientDefinitions = @(
DetectionCommand = "code"
DetectionType = "Command"
ConfigPath = "$env:APPDATA\Code\User\settings.json"
ConfigJsonPath = "mcp.servers.zen"
ConfigJsonPath = "mcp.servers.pal"
IsVSCode = $true
},
@{
@@ -1034,7 +1060,7 @@ $script:McpClientDefinitions = @(
DetectionCommand = "code-insiders"
DetectionType = "Command"
ConfigPath = "$env:APPDATA\Code - Insiders\User\mcp.json"
ConfigJsonPath = "servers.zen"
ConfigJsonPath = "servers.pal"
IsVSCodeInsiders = $true
},
@{
@@ -1042,28 +1068,28 @@ $script:McpClientDefinitions = @(
DetectionCommand = "cursor"
DetectionType = "Command"
ConfigPath = "$env:USERPROFILE\.cursor\mcp.json"
ConfigJsonPath = "mcpServers.zen"
ConfigJsonPath = "mcpServers.pal"
},
@{
Name = "Windsurf"
DetectionPath = "$env:USERPROFILE\.codeium\windsurf"
DetectionType = "Path"
ConfigPath = "$env:USERPROFILE\.codeium\windsurf\mcp_config.json"
ConfigJsonPath = "mcpServers.zen"
ConfigJsonPath = "mcpServers.pal"
},
@{
Name = "Trae"
DetectionPath = "$env:APPDATA\Trae"
DetectionType = "Path"
ConfigPath = "$env:APPDATA\Trae\User\mcp.json"
ConfigJsonPath = "mcpServers.zen"
ConfigJsonPath = "mcpServers.pal"
}
)
# Docker MCP configuration template (legacy, kept for backward compatibility)
$script:DockerMcpConfig = @{
command = "docker"
args = @("exec", "-i", "zen-mcp-server", "python", "server.py")
args = @("exec", "-i", "pal-mcp-server", "python", "server.py")
type = "stdio"
}
@@ -1076,7 +1102,7 @@ function Get-DockerMcpConfigRun {
return @{
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"
}
}
@@ -1103,7 +1129,7 @@ function Test-McpJsonFormat {
function Test-VSCodeInsidersFormat {
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)
@@ -1133,9 +1159,9 @@ function Get-ExistingMcpConfigType {
}
}
# Navigate to zen configuration
# Navigate to pal configuration
$pathParts = $Client.ConfigJsonPath.Split('.')
$zenKey = $pathParts[-1]
$palKey = $pathParts[-1]
$parentPath = $pathParts[0..($pathParts.Length - 2)]
$targetObject = $content
@@ -1150,32 +1176,32 @@ function Get-ExistingMcpConfigType {
$targetObject = $targetObject.$key
}
if (!$targetObject.PSObject.Properties[$zenKey]) {
if (!$targetObject.PSObject.Properties[$palKey]) {
return @{
Exists = $false
Type = "None"
Details = "Zen configuration not found"
Details = "PAL configuration not found"
}
}
$zenConfig = $targetObject.$zenKey
$palConfig = $targetObject.$palKey
# Analyze configuration type
if ($zenConfig.command -eq "docker") {
if ($palConfig.command -eq "docker") {
$dockerType = "Unknown"
$details = "Docker configuration"
if ($zenConfig.args -and $zenConfig.args.Count -gt 0) {
if ($zenConfig.args[0] -eq "run") {
if ($palConfig.args -and $palConfig.args.Count -gt 0) {
if ($palConfig.args[0] -eq "run") {
$dockerType = "Docker Run"
$details = "Docker run (dedicated container)"
}
elseif ($zenConfig.args[0] -eq "exec") {
elseif ($palConfig.args[0] -eq "exec") {
$dockerType = "Docker Exec"
$details = "Docker exec (existing container)"
}
else {
$details = "Docker ($($zenConfig.args[0]))"
$details = "Docker ($($palConfig.args[0]))"
}
}
@@ -1184,18 +1210,18 @@ function Get-ExistingMcpConfigType {
Type = "Docker"
SubType = $dockerType
Details = $details
Command = $zenConfig.command
Args = $zenConfig.args
Command = $palConfig.command
Args = $palConfig.args
}
}
elseif ($zenConfig.command -and $zenConfig.command.EndsWith("python.exe")) {
elseif ($palConfig.command -and $palConfig.command.EndsWith("python.exe")) {
$pythonType = "Python"
$details = "Python virtual environment"
if ($zenConfig.command.Contains(".zen_venv")) {
$details = "Python (zen virtual environment)"
if ($palConfig.command.Contains(".pal_venv")) {
$details = "Python (pal virtual environment)"
}
elseif ($zenConfig.command.Contains("venv")) {
elseif ($palConfig.command.Contains("venv")) {
$details = "Python (virtual environment)"
}
else {
@@ -1207,17 +1233,17 @@ function Get-ExistingMcpConfigType {
Type = "Python"
SubType = $pythonType
Details = $details
Command = $zenConfig.command
Args = $zenConfig.args
Command = $palConfig.command
Args = $palConfig.args
}
}
else {
return @{
Exists = $true
Type = "Unknown"
Details = "Unknown configuration type: $($zenConfig.command)"
Command = $zenConfig.command
Args = $zenConfig.args
Details = "Unknown configuration type: $($palConfig.command)"
Command = $palConfig.command
Args = $palConfig.args
}
}
@@ -1337,7 +1363,7 @@ function Configure-McpClient {
$newConfigType = if ($UseDocker) { "Docker" } else { "Python" }
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 " New: $newConfigType configuration"
@@ -1360,7 +1386,7 @@ function Configure-McpClient {
}
else {
# 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') {
Write-Info "Skipping $($Client.Name) integration"
return
@@ -1429,7 +1455,7 @@ function Configure-McpClient {
# Navigate and set configuration
$pathParts = $Client.ConfigJsonPath.Split('.')
$zenKey = $pathParts[-1]
$palKey = $pathParts[-1]
$parentPath = $pathParts[0..($pathParts.Length - 2)]
$targetObject = $config
@@ -1440,7 +1466,13 @@ function Configure-McpClient {
$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
$config | ConvertTo-Json -Depth 10 | Out-File $configPath -Encoding UTF8
@@ -1488,26 +1520,30 @@ function Test-ClaudeCliIntegration {
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 {
$claudeConfig = claude mcp list 2>$null
if ($claudeConfig -match "zen") {
Write-Success "Claude CLI already configured for zen server"
if ($claudeConfig -match "pal") {
Write-Success "Claude CLI already configured for pal server"
}
else {
Write-Info "To add zen server to Claude CLI, run:"
Write-Host " claude mcp add -s user zen $PythonPath $ServerPath" -ForegroundColor Cyan
Write-Info "To add pal server to Claude CLI, run:"
Write-Host " claude mcp add -s user pal $PythonPath $ServerPath" -ForegroundColor Cyan
}
}
catch {
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 {
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)
$geminiConfig = "$env:USERPROFILE\.gemini\settings.json"
@@ -1515,34 +1551,76 @@ function Test-GeminiCliIntegration {
return
}
# Check if zen is already configured
# Load existing config
$config = @{}
$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
}
# Ask user if they want to add Zen to Gemini CLI
# Ask user if they want to add PAL to Gemini CLI
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') {
Write-Info "Skipping Gemini CLI integration"
return
}
# Ensure wrapper script exists
if (!(Test-Path $zenWrapper)) {
if (!(Test-Path $palWrapper)) {
Write-Info "Creating wrapper script for Gemini CLI..."
@"
@echo off
cd /d "%~dp0"
if exist ".zen_venv\Scripts\python.exe" (
.zen_venv\Scripts\python.exe server.py %*
if exist ".pal_venv\Scripts\python.exe" (
.pal_venv\Scripts\python.exe server.py %*
) else (
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
@@ -1552,30 +1630,24 @@ if exist ".zen_venv\Scripts\python.exe" (
# Create backup with retention management
$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
if (!$config.mcpServers) {
$config | Add-Member -MemberType NoteProperty -Name "mcpServers" -Value @{} -Force
if (-not $config.mcpServers -or $config.mcpServers -isnot [System.Collections.IDictionary]) {
$config.mcpServers = [ordered]@{}
}
# Add zen server
$zenConfig = @{
command = $zenWrapper
# Add pal server
$palConfig = @{
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
$config | ConvertTo-Json -Depth 10 | Out-File $geminiConfig -Encoding UTF8
Write-Success "Successfully configured Gemini CLI"
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 {
@@ -1586,8 +1658,8 @@ if exist ".zen_venv\Scripts\python.exe" (
Write-Host @"
{
"mcpServers": {
"zen": {
"command": "$zenWrapper"
"pal": {
"command": "$palWrapper"
}
}
}
@@ -1615,7 +1687,7 @@ function Show-QwenManualConfig {
Write-Host "{" -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 " \"args\": [\"$ServerPath\"]," -ForegroundColor Yellow
Write-Host " \"cwd\": \"$ScriptDir\"," -ForegroundColor Yellow
@@ -1629,7 +1701,7 @@ function Show-QwenManualConfig {
else {
Write-Host "{" -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 " \"args\": [\"$ServerPath\"]," -ForegroundColor Yellow
Write-Host " \"cwd\": \"$ScriptDir\"" -ForegroundColor Yellow
@@ -1653,6 +1725,8 @@ function Test-QwenCliIntegration {
$scriptDir = Split-Path $ServerPath -Parent
$configStatus = "missing"
$legacyRemoved = $false
$skipPrompt = $false
$config = @{}
if (Test-Path $configPath) {
@@ -1668,11 +1742,12 @@ function Test-QwenCliIntegration {
if ($config.ContainsKey('mcpServers') -and $config['mcpServers'] -is [System.Collections.IDictionary]) {
$servers = $config['mcpServers']
if ($servers.Contains('zen') -and $servers['zen'] -is [System.Collections.IDictionary]) {
$zenConfig = $servers['zen']
$commandMatches = ($zenConfig['command'] -eq $PythonPath)
$legacyRemoved = (Remove-LegacyServerKeys $servers) -or $legacyRemoved
if ($servers.Contains('pal') -and $servers['pal'] -is [System.Collections.IDictionary]) {
$palConfig = $servers['pal']
$commandMatches = ($palConfig['command'] -eq $PythonPath)
$argsValue = $zenConfig['args']
$argsValue = $palConfig['args']
$argsList = @()
if ($argsValue -is [System.Collections.IEnumerable] -and $argsValue -isnot [string]) {
$argsList = @($argsValue)
@@ -1683,21 +1758,21 @@ function Test-QwenCliIntegration {
$argsMatches = ($argsList.Count -eq 1 -and $argsList[0] -eq $ServerPath)
$cwdValue = $null
if ($zenConfig.Contains('cwd')) {
$cwdValue = $zenConfig['cwd']
if ($palConfig.Contains('cwd')) {
$cwdValue = $palConfig['cwd']
}
$cwdMatches = ([string]::IsNullOrEmpty($cwdValue) -or $cwdValue -eq $scriptDir)
if ($commandMatches -and $argsMatches -and $cwdMatches) {
Write-Success "Qwen CLI already configured for zen server"
return
$configStatus = $legacyRemoved ? "cleanup" : "match"
}
else {
$configStatus = "mismatch"
Write-Warning "Existing Qwen CLI configuration differs from the current setup."
}
}
}
}
catch {
$configStatus = "invalid"
Write-Warning "Unable to parse Qwen CLI settings at $configPath ($_)."
@@ -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",
"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",
"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) {
@@ -1747,17 +1822,32 @@ function Test-QwenCliIntegration {
}
}
$prompt = "Configure Zen for Qwen CLI? (y/N)"
if ($configStatus -eq "mismatch" -or $configStatus -eq "invalid") {
$prompt = "Update Qwen CLI zen configuration? (y/N)"
if ($configStatus -eq "match") {
Write-Success "Qwen CLI already configured for pal server"
return
}
if ($configStatus -eq "cleanup") {
Write-Info "Removing legacy Qwen MCP entries from previous zen configuration..."
$skipPrompt = $true
}
$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)) {
New-Item -ItemType Directory -Path $configDir -Force | Out-Null
@@ -1776,24 +1866,24 @@ function Test-QwenCliIntegration {
$config['mcpServers'] = @{}
}
$zenConfig = [ordered]@{
$palConfig = [ordered]@{
command = $PythonPath
args = @($ServerPath)
cwd = $scriptDir
}
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)
Set-Content -Path $configPath -Value $json -Encoding UTF8
Write-Success "Successfully configured Qwen CLI"
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 {
Write-Error "Failed to update Qwen CLI configuration: $_"
@@ -1813,7 +1903,7 @@ function Test-QwenCliIntegration {
# Show script help
function Show-Help {
Write-Host @"
Zen MCP Server - Setup and Launch Script
PAL MCP Server - Setup and Launch Script
USAGE:
.\run-server.ps1 [OPTIONS]
@@ -1838,17 +1928,17 @@ EXAMPLES:
.\run-server.ps1 -Docker # Use Docker deployment
.\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
}
# Show version information
function Show-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 "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
@@ -1886,7 +1976,7 @@ function Show-ConfigInstructions {
Write-Host "✓ Qwen CLI" -ForegroundColor White
Write-Host ""
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
@@ -1900,11 +1990,11 @@ function Show-SetupInstructions {
Write-Step "Setup Complete"
if ($UseDocker) {
Write-Success "Zen MCP Server is configured for Docker deployment"
Write-Host "Docker command: docker exec -i zen-mcp-server python server.py" -ForegroundColor Cyan
Write-Success "PAL MCP Server is configured for Docker deployment"
Write-Host "Docker command: docker exec -i pal-mcp-server python server.py" -ForegroundColor Cyan
}
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 "Server: $ServerPath" -ForegroundColor Cyan
}
@@ -1916,7 +2006,7 @@ function Show-SetupInstructions {
# Start the server
function Start-Server {
Write-Step "Starting Zen MCP Server"
Write-Step "Starting PAL MCP Server"
$pythonPath = "$VENV_PATH\Scripts\python.exe"
if (!(Test-Path $pythonPath)) {
@@ -2041,7 +2131,7 @@ function Import-EnvFile {
# Docker deployment workflow
function Invoke-DockerWorkflow {
Write-Step "Starting Docker Workflow"
Write-Host "Zen MCP Server" -ForegroundColor Green
Write-Host "PAL MCP Server" -ForegroundColor Green
Write-Host "=================" -ForegroundColor Cyan
$version = Get-Version
@@ -2064,7 +2154,7 @@ function Invoke-DockerWorkflow {
Show-SetupInstructions -UseDocker
# Start Docker services
Write-Step "Starting Zen MCP Server"
Write-Step "Starting PAL MCP Server"
if ($Follow) {
Write-Info "Starting server and following logs..."
Start-DockerServices -Follow
@@ -2074,7 +2164,7 @@ function Invoke-DockerWorkflow {
if (!(Start-DockerServices)) { exit 1 }
Write-Host ""
Write-Success "Zen MCP Server is running in Docker!"
Write-Success "PAL MCP Server is running in Docker!"
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Cyan
@@ -2083,7 +2173,7 @@ function Invoke-DockerWorkflow {
Write-Host ""
Write-Host "Useful commands:" -ForegroundColor Cyan
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 "docker-compose down" -ForegroundColor Yellow
Write-Host " Restart server: " -NoNewline -ForegroundColor White
@@ -2093,7 +2183,7 @@ function Invoke-DockerWorkflow {
# Python virtual environment deployment workflow
function Invoke-PythonWorkflow {
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
$version = Get-Version

View File

@@ -2,7 +2,7 @@
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.
# Handles environment setup, dependency installation, and configuration.
@@ -29,11 +29,12 @@ readonly RED='\033[0;31m'
readonly NC='\033[0m' # No Color
# Configuration
readonly VENV_PATH=".zen_venv"
readonly VENV_PATH=".pal_venv"
readonly DOCKER_CLEANED_FLAG=".docker_cleaned"
readonly DESKTOP_CONFIG_FLAG=".desktop_configured"
readonly LOG_DIR="logs"
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)
declare -a SED_INPLACE_ARGS
@@ -753,7 +754,7 @@ setup_venv() {
print_error "Permission denied creating virtual environment"
echo ""
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 ""
exit 1
else
@@ -960,7 +961,7 @@ install_dependencies() {
fi
echo ""
print_info "Setting up Zen MCP Server..."
print_info "Setting up PAL MCP Server..."
echo "Installing required components:"
echo " • MCP protocol library"
echo " • AI model connectors"
@@ -1234,7 +1235,7 @@ check_claude_cli_integration() {
echo ""
print_warning "Claude CLI not found"
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 ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_info "Skipping Claude Code integration"
@@ -1249,9 +1250,14 @@ check_claude_cli_integration() {
return 1
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)
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
if echo "$mcp_list" | grep -E "zen.*docker|zen.*compose" &>/dev/null; then
print_warning "Found old Docker-based Zen registration, updating..."
@@ -1270,14 +1276,14 @@ check_claude_cli_integration() {
done <<< "$env_vars"
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
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
else
echo ""
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"
return 1
fi
@@ -1287,8 +1293,8 @@ check_claude_cli_integration() {
if echo "$mcp_list" | grep -F "$server_path" &>/dev/null; then
return 0
else
print_warning "Zen registered with different path, updating..."
claude mcp remove zen -s user 2>/dev/null || true
print_warning "PAL registered with different path, updating..."
claude mcp remove pal -s user 2>/dev/null || true
# Re-add with current path and environment variables
local env_vars=$(parse_env_variables)
@@ -1303,14 +1309,14 @@ check_claude_cli_integration() {
done <<< "$env_vars"
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
print_success "Updated Zen with current path and environment variables"
print_success "Updated PAL with current path and environment variables"
return 0
else
echo ""
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"
return 1
fi
@@ -1319,7 +1325,7 @@ check_claude_cli_integration() {
else
# Not registered at all, ask user if they want to add it
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 ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
local env_vars=$(parse_env_variables)
@@ -1335,11 +1341,11 @@ check_claude_cli_integration() {
fi
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
fi
print_info "Registering Zen with Claude Code..."
print_info "Registering PAL with Claude Code..."
# Add with environment variables
local env_vars=$(parse_env_variables)
@@ -1354,9 +1360,9 @@ check_claude_cli_integration() {
done <<< "$env_vars"
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
print_success "Successfully added Zen to Claude Code with environment variables"
print_success "Successfully added PAL to Claude Code with environment variables"
return 0
else
echo ""
@@ -1383,8 +1389,12 @@ check_claude_desktop_integration() {
return 0
fi
# Legacy MCP server names to clean out from previous releases
local legacy_names_csv
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
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 ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_info "Skipping Claude Desktop integration"
@@ -1401,12 +1411,12 @@ check_claude_desktop_integration() {
print_info "Updating existing Claude Desktop config..."
# 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..."
# Create backup
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)
python3 -c "
import json
@@ -1416,10 +1426,10 @@ try:
with open('$config_path', 'r') as f:
config = json.load(f)
# Remove zen from mcpServers if it exists
if 'mcpServers' in config and 'zen' in config['mcpServers']:
del config['mcpServers']['zen']
print('Removed old zen MCP configuration')
# Remove pal from mcpServers if it exists
if 'mcpServers' in config and 'pal' in config['mcpServers']:
del config['mcpServers']['pal']
print('Removed old pal MCP configuration')
with open('$temp_file', 'w') as f:
json.dump(config, f, indent=2)
@@ -1440,22 +1450,35 @@ except Exception as e:
echo "$env_vars" > "$env_file"
fi
python3 -c "
PAL_LEGACY_NAMES="$legacy_names_csv" python3 -c "
import json
import os
import sys
legacy_keys = [k for k in os.environ.get('PAL_LEGACY_NAMES', '').split(',') if k]
try:
with open('$config_path', 'r') as f:
config = json.load(f)
except:
except Exception:
config = {}
if not isinstance(config, dict):
config = {}
# Ensure mcpServers exists
if 'mcpServers' not in config:
if 'mcpServers' not in config or not isinstance(config.get('mcpServers'), dict):
config['mcpServers'] = {}
# Add zen server
zen_config = {
# Remove legacy entries from any known server blocks
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',
'args': ['$server_path']
}
@@ -1469,13 +1492,13 @@ try:
if '=' in line and line:
key, value = line.split('=', 1)
env_dict[key] = value
except:
except Exception:
pass
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:
json.dump(config, f, indent=2)
@@ -1503,8 +1526,8 @@ import sys
config = {'mcpServers': {}}
# Add zen server
zen_config = {
# Add pal server
pal_config = {
'command': '$python_cmd',
'args': ['$server_path']
}
@@ -1522,9 +1545,9 @@ except:
pass
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:
json.dump(config, f, indent=2)
@@ -1567,7 +1590,7 @@ with open('$temp_file', 'w') as f:
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"]$(if [[ -n "$example_env" ]]; then echo ","; fi)$(if [[ -n "$example_env" ]]; then echo "
\"env\": {
@@ -1583,7 +1606,7 @@ EOF
# Check and update Gemini CLI configuration
check_gemini_cli_integration() {
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
local gemini_config="$HOME/.gemini/settings.json"
@@ -1592,15 +1615,75 @@ check_gemini_cli_integration() {
return 0
fi
# Check if zen is already configured
if grep -q '"zen"' "$gemini_config" 2>/dev/null; then
# Already configured
# Clean up legacy zen entries and detect existing pal configuration
local legacy_names_csv
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
fi
# Ask user if they want to add Zen to Gemini CLI
# Ask user if they want to add PAL to Gemini CLI
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 ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_info "Skipping Gemini CLI integration"
@@ -1608,17 +1691,17 @@ check_gemini_cli_integration() {
fi
# Ensure wrapper script exists
if [[ ! -f "$zen_wrapper" ]]; then
if [[ ! -f "$pal_wrapper" ]]; then
print_info "Creating wrapper script for Gemini CLI..."
cat > "$zen_wrapper" << 'EOF'
cat > "$pal_wrapper" << 'EOF'
#!/bin/bash
# Wrapper script for Gemini CLI compatibility
DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$DIR"
exec .zen_venv/bin/python server.py "$@"
exec .pal_venv/bin/python server.py "$@"
EOF
chmod +x "$zen_wrapper"
print_success "Created zen-mcp-server wrapper script"
chmod +x "$pal_wrapper"
print_success "Created pal-mcp-server wrapper script"
fi
# Update Gemini settings
@@ -1627,7 +1710,7 @@ EOF
# Create backup
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)
python3 -c "
import json
@@ -1641,9 +1724,9 @@ try:
if 'mcpServers' not in config:
config['mcpServers'] = {}
# Add zen server
config['mcpServers']['zen'] = {
'command': '$zen_wrapper'
# Add pal server
config['mcpServers']['pal'] = {
'command': '$pal_wrapper'
}
with open('$temp_file', 'w') as f:
@@ -1657,7 +1740,7 @@ except Exception as e:
if [[ $? -eq 0 ]]; then
print_success "Successfully configured Gemini CLI"
echo " Config: $gemini_config"
echo " Restart Gemini CLI to use Zen MCP Server"
echo " Restart Gemini CLI to use PAL MCP Server"
else
print_error "Failed to update Gemini CLI config"
echo "Manual config location: $gemini_config"
@@ -1665,8 +1748,8 @@ except Exception as e:
cat << EOF
{
"mcpServers": {
"zen": {
"command": "$zen_wrapper"
"pal": {
"command": "$pal_wrapper"
}
}
}
@@ -1681,14 +1764,71 @@ check_codex_cli_integration() {
fi
local codex_config="$HOME/.codex/config.toml"
local codex_has_zen=false
if [[ -f "$codex_config" ]] && grep -q '\[mcp_servers\.zen\]' "$codex_config" 2>/dev/null; then
codex_has_zen=true
local legacy_names_csv
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
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
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 ""
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 ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_info "Skipping Codex CLI integration"
@@ -1707,12 +1847,12 @@ check_codex_cli_integration() {
{
echo ""
echo "[mcp_servers.zen]"
echo "[mcp_servers.pal]"
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 ""
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\""
if [[ -n "$env_vars" ]]; then
while IFS= read -r line; do
@@ -1732,12 +1872,12 @@ check_codex_cli_integration() {
echo "Manual config location: $codex_config"
echo "Add this configuration:"
cat <<'CODExEOF'
[mcp_servers.zen]
[mcp_servers.pal]
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
[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"
[features]
@@ -1759,16 +1899,16 @@ CODExEOF
print_success "Successfully configured Codex CLI"
echo " Config: $codex_config"
echo " Restart Codex CLI to use Zen MCP Server"
codex_has_zen=true
echo " Restart Codex CLI to use PAL MCP Server"
codex_has_pal=true
else
print_info "Codex CLI already configured; refreshing Codex settings..."
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
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
echo ""
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
@@ -1903,7 +2043,7 @@ print_qwen_manual_instructions() {
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir",
@@ -1916,7 +2056,7 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir"
@@ -1956,6 +2096,43 @@ check_qwen_cli_integration() {
env_lines=$(printf '%s\n' "${env_array[@]}")
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
if [[ -f "$qwen_config" ]]; then
if python3 - "$qwen_config" "$python_cmd" "$server_path" "$script_dir" <<'PYCONF'
@@ -1975,7 +2152,7 @@ servers = data.get('mcpServers')
if not isinstance(servers, dict):
sys.exit(3)
config = servers.get('zen')
config = servers.get('pal')
if not isinstance(config, dict):
sys.exit(3)
@@ -2006,14 +2183,14 @@ PYCONF
echo ""
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
print_warning "Unable to parse Qwen CLI settings; replacing with a fresh entry may help."
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
prompt="Update Qwen CLI zen configuration? (Y/n): "
prompt="Update Qwen CLI pal configuration? (Y/n): "
fi
read -p "$prompt" -n 1 -r
@@ -2031,17 +2208,17 @@ PYCONF
local update_output
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 os
import pathlib
import sys
config_path = pathlib.Path(sys.argv[1])
cmd = os.environ['ZEN_QWEN_CMD']
arg = os.environ['ZEN_QWEN_ARG']
cwd = os.environ['ZEN_QWEN_CWD']
env_lines = os.environ.get('ZEN_QWEN_ENV', '').splitlines()
cmd = os.environ['PAL_QWEN_CMD']
arg = os.environ['PAL_QWEN_ARG']
cwd = os.environ['PAL_QWEN_CWD']
env_lines = os.environ.get('PAL_QWEN_ENV', '').splitlines()
env_map = {}
for line in env_lines:
@@ -2068,16 +2245,16 @@ if not isinstance(servers, dict):
servers = {}
data['mcpServers'] = servers
zen_config = {
pal_config = {
'command': cmd,
'args': [arg],
'cwd': cwd,
}
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)
tmp_path = config_path.with_suffix(config_path.suffix + '.tmp')
@@ -2091,7 +2268,7 @@ PYUPDATE
if [[ $update_status -eq 0 ]]; then
print_success "Successfully configured Qwen CLI"
echo " Config: $qwen_config"
echo " Restart Qwen CLI to use Zen MCP Server"
echo " Restart Qwen CLI to use PAL MCP Server"
else
print_error "Failed to update Qwen CLI config"
if [[ -n "$update_output" ]]; then
@@ -2110,11 +2287,11 @@ display_config_instructions() {
local script_dir=$(dirname "$server_path")
echo ""
local config_header="ZEN MCP SERVER CONFIGURATION"
local config_header="PAL MCP SERVER CONFIGURATION"
echo "===== $config_header ====="
printf '%*s\n' "$((${#config_header} + 12))" | tr ' ' '='
echo ""
echo "To use Zen MCP Server with your CLI clients:"
echo "To use PAL MCP Server with your CLI clients:"
echo ""
print_info "1. For Claude Code (CLI):"
@@ -2128,7 +2305,7 @@ display_config_instructions() {
fi
done <<< "$env_vars"
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 ""
print_info "2. For Claude Desktop:"
@@ -2159,7 +2336,7 @@ display_config_instructions() {
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir",
@@ -2174,7 +2351,7 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir"
@@ -2202,8 +2379,8 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"command": "$script_dir/zen-mcp-server"
"pal": {
"command": "$script_dir/pal-mcp-server"
}
}
}
@@ -2217,7 +2394,7 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir",
@@ -2232,7 +2409,7 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir"
@@ -2247,11 +2424,11 @@ EOF
echo " Add this configuration to ~/.codex/config.toml:"
echo ""
cat << EOF
[mcp_servers.zen]
[mcp_servers.pal]
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"
GEMINI_API_KEY = "your_gemini_api_key_here"
EOF
@@ -2268,7 +2445,7 @@ display_setup_instructions() {
echo "===== $setup_header ====="
printf '%*s\n' "$((${#setup_header} + 12))" | tr ' ' '='
echo ""
print_success "Zen is ready to use!"
print_success "PAL is ready to use!"
# Display enabled/disabled tools if DISABLED_TOOLS is configured
if [[ -n "${DISABLED_TOOLS:-}" ]]; then
@@ -2348,7 +2525,7 @@ display_setup_instructions() {
# Show help message
show_help() {
local version=$(get_version)
local header="🤖 Zen MCP Server v$version"
local header="🤖 PAL MCP Server v$version"
echo "$header"
printf '%*s\n' "${#header}" | tr ' ' '='
echo ""
@@ -2369,7 +2546,7 @@ show_help() {
echo " $0 --clear-cache Clear Python cache (fixes import issues)"
echo ""
echo "For more information, visit:"
echo " https://github.com/BeehiveInnovations/zen-mcp-server"
echo " https://github.com/BeehiveInnovations/pal-mcp-server"
}
# Show version only
@@ -2444,7 +2621,7 @@ main() {
esac
# Display header
local main_header="🤖 Zen MCP Server"
local main_header="🤖 PAL MCP Server"
echo "$main_header"
printf '%*s\n' "${#main_header}" | tr ' ' '='

View File

@@ -1,9 +1,9 @@
<#
.SYNOPSIS
Integration test runner script for the Zen MCP server on Windows.
Integration test runner script for the PAL MCP server on Windows.
.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
- Installs required dependencies
- Runs automated integration tests
@@ -25,7 +25,7 @@
Script Author : GiGiDKR (https://github.com/GiGiDKR)
Date : 07-05-2025
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
[CmdletBinding()]
@@ -64,13 +64,13 @@ function Write-Emoji {
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 "These tests use real API calls with your configured keys"
Write-Host ""
# Check for virtual environment
$venvPath = ".zen_venv"
$venvPath = ".pal_venv"
$activateScript = if ($IsWindows -or $env:OS -eq "Windows_NT") {
"$venvPath\Scripts\Activate.ps1"
} else {

View File

@@ -1,19 +1,19 @@
#!/bin/bash
# Zen MCP Server - Run Integration Tests
# PAL MCP Server - Run Integration Tests
# This script runs integration tests that require API keys
# Run this locally on your Mac to ensure everything works end-to-end
set -e # Exit on any error
echo "🧪 Running Integration Tests for Zen MCP Server"
echo "🧪 Running Integration Tests for PAL MCP Server"
echo "=============================================="
echo "These tests use real API calls with your configured keys"
echo ""
# Activate virtual environment
if [[ -f ".zen_venv/bin/activate" ]]; then
source .zen_venv/bin/activate
if [[ -f ".pal_venv/bin/activate" ]]; then
source .pal_venv/bin/activate
echo "✅ Using virtual environment"
else
echo "❌ No virtual environment found!"

View File

@@ -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
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__)
# Log ZEN_MCP_FORCE_ENV_OVERRIDE configuration for transparency
# Log PAL_MCP_FORCE_ENV_OVERRIDE configuration for transparency
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")
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
# 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
@@ -370,7 +370,7 @@ PROMPT_TEMPLATES = {
"version": {
"name": "version",
"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.
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
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.
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
underlying tool.
@@ -1365,14 +1365,14 @@ async def handle_get_prompt(name: str, arguments: dict[str, Any] = None) -> GetP
# Handle special "continue" case
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"
template_info = {
"name": "continue",
"description": "Continue the previous conversation",
"template": "Continue the conversation",
}
logger.debug("Using /zen:continue - defaulting to chat tool")
logger.debug("Using /pal:continue - defaulting to chat tool")
else:
# Find the corresponding tool by checking prompt names
tool_name = None
@@ -1420,7 +1420,7 @@ async def handle_get_prompt(name: str, arguments: dict[str, Any] = None) -> GetP
# Generate tool call instruction
if name.lower() == "continue":
# "/zen:continue" case
# "/pal:continue" case
tool_instruction = (
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. "
@@ -1461,7 +1461,7 @@ async def main():
configure_providers()
# Log startup message
logger.info("Zen MCP Server starting up...")
logger.info("PAL MCP Server starting up...")
logger.info(f"Log level: {log_level}")
# Note: MCP client info will be logged during the protocol handshake
@@ -1487,7 +1487,7 @@ async def main():
if IS_AUTO_MODE:
handshake_instructions = (
"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:
handshake_instructions = (
@@ -1502,7 +1502,7 @@ async def main():
read_stream,
write_stream,
InitializationOptions(
server_name="zen",
server_name="PAL",
server_version=__version__,
instructions=handshake_instructions,
capabilities=ServerCapabilities(
@@ -1514,7 +1514,7 @@ async def main():
def run():
"""Console script entry point for zen-mcp-server."""
"""Console script entry point for pal-mcp-server."""
try:
asyncio.run(main())
except KeyboardInterrupt:

View File

@@ -1,7 +1,7 @@
"""
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.
"""

View File

@@ -43,10 +43,10 @@ class BaseSimulatorTest:
if os.path.exists(venv_python):
return venv_python
# Try .zen_venv as fallback
zen_venv_python = os.path.join(current_dir, ".zen_venv", "bin", "python")
if os.path.exists(zen_venv_python):
return zen_venv_python
# Try .pal_venv as fallback
pal_venv_python = os.path.join(current_dir, ".pal_venv", "bin", "python")
if os.path.exists(pal_venv_python):
return pal_venv_python
# Fallback to system python if venv doesn't exist
self.logger.warning("Virtual environment not found, using system python")

View File

@@ -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
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",
"important": "Please use zen's codereview tool instead",
"important": "Please use pal's codereview tool instead",
"reason": "<brief, specific rationale for escalation>"}
SCOPE & FOCUS

View File

@@ -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.
- Report issues in severity order (Critical, High, Medium, Low) spanning security, correctness, performance, and maintainability while staying within scope.

View File

@@ -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.
- Provide concise, actionable responses in Markdown tailored to engineers working from the CLI.

View File

@@ -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.
- Report findings in severity order (Critical, High, Medium, Low) across security, correctness, performance, and maintainability while staying within the provided scope.

View File

@@ -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.
- Inspect any relevant files, scripts, or docs before outlining the plan; leverage your full CLI access for research.

View File

@@ -1 +1 @@
# Tests for Zen MCP Server
# Tests for PAL MCP Server

View File

@@ -1,5 +1,5 @@
"""
Pytest configuration for Zen MCP Server tests
Pytest configuration for PAL MCP Server tests
"""
import asyncio
@@ -18,7 +18,7 @@ if str(parent_dir) not in sys.path:
import utils.env as env_config # noqa: E402
# 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
# 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):
"""Default tests to runtime environment visibility unless they explicitly opt in."""
monkeypatch.setenv("ZEN_MCP_FORCE_ENV_OVERRIDE", "false")
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
monkeypatch.setenv("PAL_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("MAX_CONVERSATION_TURNS", "50")

View File

@@ -26,7 +26,7 @@
"temperature": 1.0,
"candidateCount": 1,
"thinkingConfig": {
"thinkingBudget": 10813
"thinking_budget": 10813
}
}
}

View File

@@ -26,7 +26,7 @@
"temperature": 0.2,
"candidateCount": 1,
"thinkingConfig": {
"thinkingBudget": 8110
"thinking_budget": 8110
}
}
}

View File

@@ -23,10 +23,10 @@
}
],
"generationConfig": {
"temperature": 0.2,
"temperature": 1.0,
"candidateCount": 1,
"thinkingConfig": {
"thinkingBudget": 8110
"thinking_budget": 8110
}
}
}

View File

@@ -73,12 +73,12 @@ def test_error_listing_respects_env_restrictions(monkeypatch, reset_registry):
"AZURE_MODELS_CONFIG_PATH",
):
monkeypatch.delenv(azure_var, raising=False)
monkeypatch.setenv("ZEN_MCP_FORCE_ENV_OVERRIDE", "false")
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
monkeypatch.setenv("PAL_MCP_FORCE_ENV_OVERRIDE", "false")
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
try:
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:
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("OPENROUTER_API_KEY", "test-openrouter")
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 (
"AZURE_OPENAI_API_KEY",
"AZURE_OPENAI_ENDPOINT",
@@ -159,11 +159,11 @@ def test_error_listing_without_restrictions_shows_full_catalog(monkeypatch, rese
"AZURE_MODELS_CONFIG_PATH",
):
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:
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:
pass

View File

@@ -33,7 +33,7 @@ CASSETTE_REPLAY_ID = "chat_codegen/gemini25_pro_calculator/mldev"
@pytest.mark.asyncio
@pytest.mark.no_mock_provider
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)
@@ -65,7 +65,7 @@ async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
working_dir = tmp_path / "codegen"
working_dir.mkdir()
preexisting = working_dir / "zen_generated.code"
preexisting = working_dir / "pal_generated.code"
preexisting.write_text("stale contents", encoding="utf-8")
chat_tool = ChatTool()
@@ -102,7 +102,7 @@ async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
payload = json.loads(result[0].text)
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()
saved = artifact_path.read_text()
assert "<GENERATED-CODE>" in saved

View File

@@ -133,7 +133,7 @@ class TestChatTool:
assert "Evaluate this perspective" in formatted
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._model_context = SimpleNamespace(capabilities=SimpleNamespace(allow_code_generation=True))
@@ -148,7 +148,7 @@ class TestChatTool:
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")
assert "print('world')" in saved_content
@@ -172,7 +172,7 @@ class TestChatTool:
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")
assert "print('only-once')" in saved_content
@@ -191,7 +191,7 @@ class TestChatTool:
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 "print('oops')" in formatted
@@ -206,7 +206,7 @@ class TestChatTool:
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 "</GENERATED-CODE> just text" in formatted

View File

@@ -35,7 +35,9 @@ async def test_clink_gemini_single_digit_sum():
assert status in {"success", "continuation_available"}
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":
offer = payload.get("continuation_offer") or {}

View File

@@ -22,7 +22,7 @@ class TestDockerClaudeDesktopIntegration:
"""Test MCP configuration for direct docker run"""
config = {
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"command": "docker",
"args": [
"run",
@@ -32,7 +32,7 @@ class TestDockerClaudeDesktopIntegration:
"/path/to/.env",
"-v",
"/path/to/logs:/app/logs",
"zen-mcp-server:latest",
"pal-mcp-server:latest",
],
}
}
@@ -40,10 +40,10 @@ class TestDockerClaudeDesktopIntegration:
# Validate configuration structure
assert "mcpServers" in config
assert "zen-mcp" in config["mcpServers"]
assert config["mcpServers"]["zen-mcp"]["command"] == "docker"
assert "pal-mcp" in config["mcpServers"]
assert config["mcpServers"]["pal-mcp"]["command"] == "docker"
args = config["mcpServers"]["zen-mcp"]["args"]
args = config["mcpServers"]["pal-mcp"]["args"]
assert "run" in args
assert "--rm" in args
assert "-i" in args
@@ -53,27 +53,27 @@ class TestDockerClaudeDesktopIntegration:
"""Test MCP configuration for docker-compose run"""
config = {
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"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
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 "run" in args
assert "--rm" in args
assert "zen-mcp" in args
assert "pal-mcp" in args
def test_mcp_config_environment_variables(self):
"""Test MCP configuration with inline environment variables"""
config = {
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"command": "docker",
"args": [
"run",
@@ -83,13 +83,13 @@ class TestDockerClaudeDesktopIntegration:
"GEMINI_API_KEY=test_key",
"-e",
"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
env_args = [arg for arg in args if arg.startswith("-e")]
@@ -103,23 +103,23 @@ class TestDockerClaudeDesktopIntegration:
"""Test Windows-specific path formatting"""
windows_config = {
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--env-file",
"C:/Users/User/zen-mcp-server/.env",
"C:/Users/User/pal-mcp-server/.env",
"-v",
"C:/Users/User/zen-mcp-server/logs:/app/logs",
"zen-mcp-server:latest",
"C:/Users/User/pal-mcp-server/logs:/app/logs",
"pal-mcp-server:latest",
],
}
}
}
args = windows_config["mcpServers"]["zen-mcp"]["args"]
args = windows_config["mcpServers"]["pal-mcp"]["args"]
# Check Windows path format
windows_paths = [arg for arg in args if arg.startswith("C:/")]
@@ -132,7 +132,7 @@ class TestDockerClaudeDesktopIntegration:
"""Test validation of MCP configuration"""
# Valid configuration
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
@@ -144,19 +144,19 @@ class TestDockerClaudeDesktopIntegration:
"""Test that MCP configuration supports stdio communication"""
config = {
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"command": "docker",
"args": [
"run",
"--rm",
"-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
assert "-i" in args, "Interactive mode required for stdio communication"
@@ -168,9 +168,9 @@ class TestDockerClaudeDesktopIntegration:
def test_docker_image_reference(self):
"""Test that Docker image is properly referenced"""
configs = [
{"image": "zen-mcp-server:latest"},
{"image": "zen-mcp-server:v1.0.0"},
{"image": "registry/zen-mcp-server:latest"},
{"image": "pal-mcp-server:latest"},
{"image": "pal-mcp-server:v1.0.0"},
{"image": "registry/pal-mcp-server:latest"},
]
for config in configs:
@@ -185,9 +185,9 @@ class TestDockerClaudeDesktopIntegration:
"""Create temporary MCP configuration file"""
config = {
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"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)
assert "mcpServers" in config
assert "zen-mcp" in config["mcpServers"]
assert "pal-mcp" in config["mcpServers"]
def test_environment_file_integration(self):
"""Test integration with .env file"""
@@ -254,25 +254,25 @@ class TestDockerMCPErrorHandling:
# This would test what happens when the image doesn't exist
# In practice, Claude Desktop would show an error
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
assert "zen-mcp" in nonexistent_config["mcpServers"]
assert "pal-mcp" in nonexistent_config["mcpServers"]
def test_invalid_env_file_path(self):
"""Test handling of invalid .env file path"""
config_with_invalid_env = {
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"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
args = config_with_invalid_env["mcpServers"]["zen-mcp"]["args"]
args = config_with_invalid_env["mcpServers"]["pal-mcp"]["args"]
assert "--env-file" in args
def test_docker_permission_issues(self):
@@ -294,14 +294,14 @@ class TestDockerMCPErrorHandling:
"""Test Docker resource limit configurations"""
config_with_limits = {
"mcpServers": {
"zen-mcp": {
"pal-mcp": {
"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
memory_limit = any("--memory" in arg for arg in args)

View File

@@ -83,7 +83,7 @@ class TestDockerCommandValidation:
mock_run.return_value.returncode = 0
# Standard build command
build_cmd = ["docker", "build", "-t", "zen-mcp-server:latest", "."]
build_cmd = ["docker", "build", "-t", "pal-mcp-server:latest", "."]
import subprocess
@@ -105,7 +105,7 @@ class TestDockerCommandValidation:
".env",
"-v",
"logs:/app/logs",
"zen-mcp-server:latest",
"pal-mcp-server:latest",
"python",
"server.py",
]
@@ -128,7 +128,7 @@ class TestDockerCommandValidation:
"/path/to/.env",
"-v",
"/path/to/logs:/app/logs",
"zen-mcp-server:latest",
"pal-mcp-server:latest",
"python",
"server.py",
]
@@ -139,7 +139,7 @@ class TestDockerCommandValidation:
assert "--rm" in mcp_cmd # Automatic cleanup
assert "-i" in mcp_cmd # Interactive mode
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:

View File

@@ -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:
- Docker and MCP configuration
@@ -24,7 +24,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent))
class TestDockerConfiguration:
"""Tests for Docker configuration of Zen MCP Server"""
"""Tests for Docker configuration of PAL MCP Server"""
def setup_method(self):
"""Setup for each test"""
@@ -51,7 +51,7 @@ class TestDockerConfiguration:
# Basic YAML syntax check
content = self.docker_compose_path.read_text()
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"
def test_environment_file_template(self):
@@ -80,7 +80,7 @@ class TestDockerCommands:
# Simulate docker build
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()
@@ -100,7 +100,7 @@ class TestDockerCommands:
".env",
"-v",
"logs:/app/logs",
"zen-mcp-server:latest",
"pal-mcp-server:latest",
"python",
"server.py",
]
@@ -111,7 +111,7 @@ class TestDockerCommands:
assert "--rm" in cmd, "Must contain --rm for cleanup"
assert "-i" in cmd, "Must contain -i for stdio"
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")
def test_docker_health_check(self, mock_run):
@@ -121,7 +121,7 @@ class TestDockerCommands:
# Simulate health check
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,
text=True,
)
@@ -187,7 +187,7 @@ class TestMCPIntegration:
# Expected MCP configuration
expected_config = {
"servers": {
"zen-docker": {
"pal-docker": {
"command": "docker",
"args": [
"run",
@@ -197,7 +197,7 @@ class TestMCPIntegration:
"/path/to/.env",
"-v",
"/path/to/logs:/app/logs",
"zen-mcp-server:latest",
"pal-mcp-server:latest",
"python",
"server.py",
],
@@ -208,11 +208,11 @@ class TestMCPIntegration:
# Check structure
assert "servers" in expected_config
zen_docker = expected_config["servers"]["zen-docker"]
assert zen_docker["command"] == "docker"
assert "run" in zen_docker["args"]
assert "--rm" in zen_docker["args"]
assert "-i" in zen_docker["args"]
pal_docker = expected_config["servers"]["pal-docker"]
assert pal_docker["command"] == "docker"
assert "run" in pal_docker["args"]
assert "--rm" in pal_docker["args"]
assert "-i" in pal_docker["args"]
def test_stdio_communication_structure(self):
"""Test structure of stdio communication"""
@@ -279,7 +279,7 @@ class TestDockerPerformance:
expected_max_size_mb = 500 # 500MB max
# 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
simulated_size = "294MB" # Current observed size
@@ -346,7 +346,7 @@ LOG_LEVEL=INFO
"-i",
"--env-file",
".env",
"zen-mcp-server:latest",
"pal-mcp-server:latest",
"python",
"server.py",
]

View File

@@ -39,7 +39,7 @@ class TestDockerMCPValidation:
mock_run.return_value.returncode = 0
# 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)
mock_run.assert_called_once_with(cmd, capture_output=True)

View File

@@ -28,18 +28,18 @@ class TestDockerVolumePersistence:
content = self.docker_compose_path.read_text()
# 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"
# Check for volume mounts in service
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):
"""Test that persistent volumes are created correctly"""
# This test checks that the volume configuration is valid
# 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
with patch("subprocess.run") as mock_run:
@@ -84,7 +84,7 @@ class TestDockerVolumePersistence:
"run",
"--rm",
"-v",
"zen-mcp-config:/data",
"pal-mcp-config:/data",
"-v",
"$(pwd):/backup",
"alpine",
@@ -97,7 +97,7 @@ class TestDockerVolumePersistence:
]
# 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 "czf" in backup_cmd
@@ -139,7 +139,7 @@ class TestDockerVolumeIntegration:
# Verify that docker-compose run inherits volume configuration
# 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
assert "docker-compose" in compose_run_cmd

View File

@@ -335,7 +335,7 @@ Pour plus de détails sur chaque problème identifié, consultez les recommandat
- [ ] 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": {
"tool_name": "analyze",
@@ -459,13 +459,13 @@ def run_unit_tests():
def main():
"""Main function."""
print("🇫🇷 UTF-8 Integration Test - Zen MCP Server")
print("🇫🇷 UTF-8 Integration Test - PAL MCP Server")
print("=" * 60)
try:
run_utf8_integration_tests()
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
except AssertionError as e:

View File

@@ -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
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

Some files were not shown because too many files have changed in this diff Show More