@arkheia/mcp-server
Advanced tools
+92
-59
@@ -25,55 +25,31 @@ #!/usr/bin/env node | ||
| const ARKHEIA_HOME = path.join( | ||
| const PYTHON_DIR = path.join(__dirname, "..", "python"); | ||
| const REQUIREMENTS = path.join(PYTHON_DIR, "requirements.txt"); | ||
| const VENV_DIR = path.join( | ||
| process.env.HOME || process.env.USERPROFILE || "/tmp", | ||
| ".arkheia" | ||
| ".arkheia", | ||
| "venv" | ||
| ); | ||
| const REPO_DIR = path.join(ARKHEIA_HOME, "mcp"); | ||
| const BUNDLED_PYTHON_DIR = path.join(__dirname, "..", "python"); | ||
| const VENV_DIR = path.join(ARKHEIA_HOME, "venv"); | ||
| // Determine the real Python source: cloned repo > bundled package | ||
| function getServerDir() { | ||
| // If repo already cloned, use it | ||
| if (fs.existsSync(path.join(REPO_DIR, "mcp_server", "server.py"))) { | ||
| return REPO_DIR; | ||
| } | ||
| // If bundled package has the server code, use it | ||
| if (fs.existsSync(path.join(BUNDLED_PYTHON_DIR, "mcp_server", "server.py"))) { | ||
| return BUNDLED_PYTHON_DIR; | ||
| } | ||
| // Neither exists — clone the repo | ||
| process.stderr.write("[arkheia] Server code not found. Cloning from GitHub...\n"); | ||
| try { | ||
| if (!fs.existsSync(ARKHEIA_HOME)) fs.mkdirSync(ARKHEIA_HOME, { recursive: true }); | ||
| execSync(`git clone --depth 1 https://github.com/arkheiaai/arkheia-mcp.git "${REPO_DIR}"`, { | ||
| stdio: "inherit", | ||
| timeout: 60000, | ||
| }); | ||
| process.stderr.write("[arkheia] Repository cloned successfully.\n"); | ||
| return REPO_DIR; | ||
| } catch (err) { | ||
| process.stderr.write( | ||
| `[arkheia] Error: Could not clone repository: ${err.message}\n` + | ||
| "Manual install: git clone https://github.com/arkheiaai/arkheia-mcp.git ~/.arkheia/mcp\n" | ||
| ); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| const PYTHON_DIR = getServerDir(); | ||
| const REQUIREMENTS = fs.existsSync(path.join(PYTHON_DIR, "mcp_server", "requirements.txt")) | ||
| ? path.join(PYTHON_DIR, "mcp_server", "requirements.txt") | ||
| : path.join(PYTHON_DIR, "requirements.txt"); | ||
| function findPython() { | ||
| const candidates = ["python3", "python"]; | ||
| // Try versioned interpreters first — on Homebrew, keg-only formulae like | ||
| // python@3.12 only expose the versioned binary (python3.12), not python3. | ||
| // Exclude 3.14: Homebrew's build has broken pyexpat on macOS as of Apr 2026. | ||
| const candidates = ["python3.13", "python3.12", "python3.11", "python3", "python"]; | ||
| for (const cmd of candidates) { | ||
| try { | ||
| const version = execSync(`${cmd} --version 2>&1`, { | ||
| encoding: "utf-8", | ||
| timeout: 5000, | ||
| }).trim(); | ||
| const match = version.match(/Python (\d+)\.(\d+)/); | ||
| if (match && parseInt(match[1]) >= 3 && parseInt(match[2]) >= 10) { | ||
| return cmd; | ||
| // Check version AND that pyexpat + ensurepip actually work. | ||
| // Python 3.14 on macOS crashes on `import pyexpat` due to a missing | ||
| // libexpat symbol — this import check catches it at discovery time. | ||
| const output = execSync( | ||
| `${cmd} -c "import sys,pyexpat,ensurepip; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, | ||
| { encoding: "utf-8", timeout: 10000, stdio: ["pipe", "pipe", "pipe"] } | ||
| ).trim(); | ||
| const match = output.match(/^(\d+)\.(\d+)$/); | ||
| if (match) { | ||
| const major = parseInt(match[1]); | ||
| const minor = parseInt(match[2]); | ||
| if (major === 3 && minor >= 10 && minor <= 13) { | ||
| return cmd; | ||
| } | ||
| } | ||
@@ -87,2 +63,14 @@ } catch { | ||
| function venvIsHealthy(venvPython) { | ||
| if (!fs.existsSync(venvPython)) return false; | ||
| try { | ||
| execSync(`"${venvPython}" -m pip --version`, { | ||
| encoding: "utf-8", timeout: 10000, stdio: ["pipe", "pipe", "pipe"], | ||
| }); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| function ensureVenv(python) { | ||
@@ -94,5 +82,12 @@ const venvPython = | ||
| if (!fs.existsSync(venvPython)) { | ||
| if (!venvIsHealthy(venvPython)) { | ||
| if (fs.existsSync(VENV_DIR)) { | ||
| process.stderr.write("[arkheia] Existing venv is unhealthy (pip broken or missing). Recreating...\n"); | ||
| fs.rmSync(VENV_DIR, { recursive: true, force: true }); | ||
| } | ||
| process.stderr.write("[arkheia] Creating virtual environment...\n"); | ||
| execSync(`${python} -m venv "${VENV_DIR}"`, { stdio: "inherit" }); | ||
| // Force-reinstall deps after venv recreation | ||
| const marker = path.join(VENV_DIR, ".arkheia-deps-installed"); | ||
| if (fs.existsSync(marker)) fs.unlinkSync(marker); | ||
| } | ||
@@ -109,17 +104,54 @@ | ||
| process.stderr.write("[arkheia] Installing dependencies...\n"); | ||
| execSync(`"${venvPython}" -m pip install --quiet -r "${REQUIREMENTS}"`, { | ||
| stdio: "inherit", | ||
| timeout: 120000, | ||
| }); | ||
| fs.writeFileSync(marker, new Date().toISOString()); | ||
| const logFile = path.join(ARKHEIA_HOME, "install.log"); | ||
| process.stderr.write("[arkheia] Installing Python dependencies (first run)...\n"); | ||
| const start = Date.now(); | ||
| try { | ||
| const output = execSync(`"${venvPython}" -m pip install -r "${REQUIREMENTS}" 2>&1`, { | ||
| encoding: "utf-8", | ||
| timeout: 300000, // 5 min — slow networks exist | ||
| }); | ||
| const elapsed = ((Date.now() - start) / 1000).toFixed(1); | ||
| // Count installed packages from pip output | ||
| const installed = (output.match(/Successfully installed/g) || []).length; | ||
| process.stderr.write(`[arkheia] Dependencies installed in ${elapsed}s\n`); | ||
| fs.writeFileSync(marker, new Date().toISOString()); | ||
| } catch (err) { | ||
| const elapsed = ((Date.now() - start) / 1000).toFixed(1); | ||
| // Save full pip output for debugging | ||
| const pipOutput = err.stdout || err.stderr || err.message || "unknown error"; | ||
| fs.writeFileSync(logFile, pipOutput); | ||
| process.stderr.write( | ||
| `[arkheia] Dependency install failed after ${elapsed}s.\n` + | ||
| `[arkheia] Full output saved to: ${logFile}\n` + | ||
| `[arkheia] Try: "${venvPython}" -m pip install -r "${REQUIREMENTS}"\n` | ||
| ); | ||
| throw err; | ||
| } | ||
| } | ||
| function main() { | ||
| // ── CRLF warning — env files with Windows line endings silently break API keys | ||
| for (const k of ["ARKHEIA_API_KEY", "ARKHEIA_PROXY_URL", "ARKHEIA_HOSTED_URL"]) { | ||
| const v = process.env[k]; | ||
| if (v && /[\r\n]/.test(v)) { | ||
| process.stderr.write( | ||
| `[arkheia] WARNING: ${k} contains whitespace/newline characters.\n` + | ||
| `[arkheia] Your env file may have Windows (CRLF) line endings. Run 'dos2unix' on it.\n` | ||
| ); | ||
| process.env[k] = v.trim(); // auto-fix for this run | ||
| } | ||
| } | ||
| const python = findPython(); | ||
| if (!python) { | ||
| process.stderr.write( | ||
| "[arkheia] Error: Python 3.10+ is required but not found.\n" + | ||
| "Install Python from https://python.org and try again.\n" | ||
| "[arkheia] Error: Python 3.10–3.13 is required but not found.\n\n" + | ||
| " macOS (Homebrew):\n" + | ||
| " brew install python@3.12\n\n" + | ||
| " NOTE: Homebrew's current default 'brew install python' installs 3.14,\n" + | ||
| " which has a broken pyexpat link on macOS as of April 2026.\n" + | ||
| " Use python@3.12 until Homebrew ships a fix.\n\n" + | ||
| " After installing, verify with:\n" + | ||
| " python3.12 -c \"import pyexpat, ensurepip\"\n\n" + | ||
| " Other platforms: https://python.org\n" | ||
| ); | ||
@@ -180,2 +212,3 @@ process.exit(1); | ||
| // Spawn the MCP server with stdio transport | ||
| const serverDir = PYTHON_DIR; | ||
| const child = spawn( | ||
@@ -185,7 +218,7 @@ venvPython, | ||
| { | ||
| cwd: PYTHON_DIR, | ||
| cwd: serverDir, | ||
| stdio: ["pipe", "pipe", "inherit"], // stdin/stdout piped, stderr inherited | ||
| env: { | ||
| ...process.env, | ||
| PYTHONPATH: PYTHON_DIR, | ||
| PYTHONPATH: serverDir, | ||
| }, | ||
@@ -192,0 +225,0 @@ } |
+3
-2
| { | ||
| "name": "@arkheia/mcp-server", | ||
| "version": "0.1.4", | ||
| "version": "0.1.5", | ||
| "mcpName": "io.github.arkheiaai/mcp-server", | ||
@@ -11,3 +11,4 @@ "description": "Arkheia MCP Server — Fabrication detection for LLM outputs. Detect hallucination in any model's output with a single tool call.", | ||
| "start": "node bin/arkheia-mcp.js", | ||
| "postinstall": "node scripts/setup.js" | ||
| "postinstall": "node scripts/setup.js", | ||
| "release": "npm version patch --no-git-tag-version && npm publish --access public && node -e \"const{execSync}=require('child_process');const p=require('./package.json');const s=JSON.parse(require('fs').readFileSync('server.json','utf8'));s.version=p.version;s.packages[0].version=p.version;require('fs').writeFileSync('server.json',JSON.stringify(s,null,2));execSync('mcp-publisher publish',{stdio:'inherit'})\" && echo 'Published to npm + MCP registry'" | ||
| }, | ||
@@ -14,0 +15,0 @@ "keywords": [ |
+109
-21
@@ -9,9 +9,22 @@ # Arkheia MCP Server — Fabrication Detection for AI Agents | ||
| ## Quick Start | ||
| ## Prerequisites | ||
| ``` | ||
| Requires: | ||
| - Node 18+ | ||
| - Python 3.10–3.13 with working pyexpat | ||
| macOS note: Homebrew's current `brew install python` installs 3.14, | ||
| which has a broken pyexpat link. Use `brew install python@3.12` until | ||
| Homebrew ships a fix. Verify with: | ||
| python3.12 -c "import pyexpat, ensurepip" | ||
| ``` | ||
| ## Install | ||
| ```bash | ||
| npx @arkheia/mcp-server | ||
| npm install -g @arkheia/mcp-server | ||
| ``` | ||
| Get a free API key: | ||
| Get a free API key at [arkheia.ai/mcp/account](https://arkheia.ai/mcp/account), or via the CLI: | ||
@@ -24,26 +37,76 @@ ```bash | ||
| Add to your agent config (Claude Code, Claude Desktop, Cursor, or any MCP-compatible tool): | ||
| Set your key: | ||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "arkheia": { | ||
| "command": "python", | ||
| "args": ["-m", "mcp_server.server"], | ||
| "cwd": "~/.arkheia/mcp", | ||
| "env": { | ||
| "PYTHONPATH": "~/.arkheia/mcp", | ||
| "ARKHEIA_API_KEY": "ak_live_your_key_here" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ```bash | ||
| export ARKHEIA_API_KEY="ak_live_..." | ||
| ``` | ||
| Restart your agent. Then ask it: | ||
| ## Register with your CLI | ||
| > "Use arkheia_verify to check this response: The Kafka 4.1 ConsumerLease API introduces a lease-based partition ownership model." | ||
| Each AI CLI has a slightly different `mcp add` command. Use the one that matches your tool. All assume you've installed globally with `npm install -g`. | ||
| It should flag this as **HIGH** risk — because the Kafka 4.1 ConsumerLease API doesn't exist. | ||
| ### Claude Code | ||
| ```bash | ||
| claude mcp add arkheia -s user \ | ||
| -e ARKHEIA_API_KEY="$ARKHEIA_API_KEY" \ | ||
| -- mcp-server | ||
| ``` | ||
| Config lands in: `~/.claude.json` under `mcpServers.arkheia` | ||
| ### Codex | ||
| ```bash | ||
| codex mcp add arkheia \ | ||
| --env ARKHEIA_API_KEY="$ARKHEIA_API_KEY" \ | ||
| -- mcp-server | ||
| ``` | ||
| Config lands in: `~/.codex/config.toml` under `[mcp_servers.arkheia.env]` | ||
| Note: `codex login --api-key` is deprecated. Use `printenv OPENAI_API_KEY | codex login --with-api-key` instead. | ||
| ### Gemini | ||
| ```bash | ||
| gemini mcp add -s user \ | ||
| -e ARKHEIA_API_KEY="$ARKHEIA_API_KEY" \ | ||
| arkheia mcp-server | ||
| ``` | ||
| Config lands in: `~/.gemini/settings.json` under `mcpServers.arkheia` | ||
| **Gotcha:** `gemini mcp list` only shows project-scope servers. If you registered with `-s user`, verify by reading `~/.gemini/settings.json` directly. | ||
| **Gotcha:** Don't use `npx -y @arkheia/mcp-server` with Gemini — the `-y` flag gets eaten by Gemini's yargs parser as `--yolo`. Use the globally-installed `mcp-server` binary directly. | ||
| ### Grok | ||
| ```bash | ||
| grok mcp add arkheia \ | ||
| -t stdio \ | ||
| -c mcp-server \ | ||
| -e ARKHEIA_API_KEY="$ARKHEIA_API_KEY" | ||
| ``` | ||
| Config lands in: `~/.grok/settings.json` under `mcpServers.arkheia` (note: env is nested under `transport`, unlike other CLIs) | ||
| ## Verify it works | ||
| ```bash | ||
| # Claude Code — live connection test | ||
| claude mcp list | ||
| # Codex — shows 'enabled' (not a live check) | ||
| codex mcp list | ||
| # Grok — best: spawns the server and lists all 9 tools | ||
| grok mcp test arkheia | ||
| # Gemini — no built-in test; start a session and try the tool | ||
| ``` | ||
| **Important:** MCP registrations are not hot-reloaded. Restart your CLI session after running `mcp add`. | ||
| ## What You Get | ||
@@ -59,2 +122,5 @@ | ||
| | `run_together` | Call Together AI (Kimi, DeepSeek) + screen | | ||
| | `memory_store` | Persistent knowledge graph — upsert entity | | ||
| | `memory_retrieve` | Knowledge graph lookup | | ||
| | `memory_relate` | Create relationship between entities | | ||
@@ -74,2 +140,23 @@ ## 35+ Model Profiles | ||
| Manage your account at [arkheia.ai/mcp/account](https://arkheia.ai/mcp/account). | ||
| ## Where API keys are stored | ||
| | CLI | Config file | Key location | | ||
| |-----|-------------|-------------| | ||
| | Claude Code | `~/.claude.json` | `mcpServers.arkheia.env.ARKHEIA_API_KEY` | | ||
| | Codex | `~/.codex/config.toml` | `[mcp_servers.arkheia.env]` section | | ||
| | Gemini | `~/.gemini/settings.json` | `mcpServers.arkheia.env.ARKHEIA_API_KEY` | | ||
| | Grok | `~/.grok/settings.json` | `mcpServers.arkheia.transport.env.ARKHEIA_API_KEY` | | ||
| ## Troubleshooting | ||
| **"Python 3.10+ is required but not found"** — Install Python 3.12: `brew install python@3.12` (macOS) or download from [python.org](https://python.org). | ||
| **"No module named pip"** — Your Python installation has broken pip (common with Python 3.14 on macOS). Delete `~/.arkheia/venv` and switch to Python 3.12: `brew install python@3.12`. | ||
| **Server registered but tools not showing** — Restart your CLI session. MCP registrations are not hot-reloaded. | ||
| **API key rejected** — Check for trailing whitespace or `\r` characters. If your env file was created on Windows, run `dos2unix` on it. The server will warn about this on startup. | ||
| ## Full Documentation | ||
@@ -93,2 +180,3 @@ | ||
| - Website: https://arkheia.ai | ||
| - MCP Account: https://arkheia.ai/mcp/account | ||
| - GitHub: https://github.com/arkheiaai/arkheia-mcp |
+35
-13
@@ -57,12 +57,23 @@ #!/usr/bin/env node | ||
| function checkPython() { | ||
| const candidates = ["python3", "python"]; | ||
| // Try versioned interpreters first — on Homebrew, keg-only formulae like | ||
| // python@3.12 only expose python3.12, not python3. | ||
| const candidates = ["python3.13", "python3.12", "python3.11", "python3", "python"]; | ||
| for (const cmd of candidates) { | ||
| try { | ||
| const version = execSync(`${cmd} --version 2>&1`, { | ||
| encoding: "utf-8", | ||
| timeout: 5000, | ||
| }).trim(); | ||
| const match = version.match(/Python (\d+)\.(\d+)/); | ||
| if (match && parseInt(match[1]) >= 3 && parseInt(match[2]) >= 10) { | ||
| return { cmd, version }; | ||
| // Verify version AND that pyexpat + ensurepip work. | ||
| // Python 3.14 on macOS has broken pyexpat (missing libexpat symbol). | ||
| const output = execSync( | ||
| `${cmd} -c "import sys,pyexpat,ensurepip; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, | ||
| { encoding: "utf-8", timeout: 10000, stdio: ["pipe", "pipe", "pipe"] } | ||
| ).trim(); | ||
| const match = output.match(/^(\d+)\.(\d+)$/); | ||
| if (match) { | ||
| const major = parseInt(match[1]); | ||
| const minor = parseInt(match[2]); | ||
| if (major === 3 && minor >= 10 && minor <= 13) { | ||
| const version = execSync(`${cmd} --version 2>&1`, { | ||
| encoding: "utf-8", timeout: 5000, | ||
| }).trim(); | ||
| return { cmd, version }; | ||
| } | ||
| } | ||
@@ -79,10 +90,21 @@ } catch { | ||
| if (!python) { | ||
| console.log(` | ||
| console.error(` | ||
| ============================================================ | ||
| Arkheia MCP Server requires Python 3.10+ | ||
| ERROR: Arkheia MCP Server requires Python 3.10–3.13 | ||
| with working pyexpat and ensurepip. | ||
| Install Python from: https://python.org | ||
| Then run: npx @arkheia/mcp-server | ||
| macOS (Homebrew): | ||
| brew install python@3.12 | ||
| NOTE: Homebrew's current default 'brew install python' | ||
| installs 3.14, which has a broken pyexpat link on macOS | ||
| as of April 2026. Use python@3.12 until Homebrew ships a fix. | ||
| After installing, verify with: | ||
| python3.12 -c "import pyexpat, ensurepip" | ||
| Other platforms: https://python.org | ||
| ============================================================ | ||
| `); | ||
| process.exit(1); | ||
| } else { | ||
@@ -92,3 +114,3 @@ console.log(` | ||
| Arkheia MCP Server installed successfully. | ||
| Python: ${python.version} | ||
| Python: ${python.version} (${python.cmd}) | ||
| ============================================================ | ||
@@ -95,0 +117,0 @@ `); |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
22055
42.75%379
16.26%178
97.78%22
10%