@arkheia/mcp-server 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,57 +1,36 @@
1
- {
2
- "name": "@arkheia/mcp-server",
3
- "version": "0.1.5",
4
- "mcpName": "io.github.arkheiaai/mcp-server",
5
- "description": "Arkheia MCP Server — Fabrication detection for LLM outputs. Detect hallucination in any model's output with a single tool call.",
6
- "bin": {
7
- "mcp-server": "bin/arkheia-mcp.js"
8
- },
9
- "scripts": {
10
- "start": "node bin/arkheia-mcp.js",
11
- "postinstall": "node scripts/setup.js",
12
- "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'"
13
- },
14
- "keywords": [
15
- "mcp",
16
- "mcp-server",
17
- "model-context-protocol",
18
- "ai-safety",
19
- "ai-governance",
20
- "fabrication-detection",
21
- "hallucination-detection",
22
- "llm-verification",
23
- "llm-grounding",
24
- "ai-agent",
25
- "agent-governance",
26
- "ai-trust",
27
- "ai-audit",
28
- "ai-compliance",
29
- "fact-checking",
30
- "claude",
31
- "gpt",
32
- "gemini",
33
- "llama",
34
- "anthropic",
35
- "openai",
36
- "cursor",
37
- "windsurf",
38
- "cline",
39
- "copilot"
40
- ],
41
- "author": "Arkheia AI <support@arkheia.ai>",
42
- "license": "MIT",
43
- "homepage": "https://arkheia.ai/mcp",
44
- "repository": {
45
- "type": "git",
46
- "url": "git+https://github.com/arkheiaai/arkheia-mcp.git"
47
- },
48
- "engines": {
49
- "node": ">=18.0.0"
50
- },
51
- "files": [
52
- "bin/",
53
- "scripts/",
54
- "python/",
55
- "README.md"
56
- ]
57
- }
1
+ {
2
+ "name": "@arkheia/mcp-server",
3
+ "version": "0.1.6",
4
+ "description": "Arkheia MCP Server — Fabrication detection for AI agents. Know when your AI is making things up.",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "mcp-server": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node dist/index.js",
12
+ "prepublishOnly": "npm run build",
13
+ "postinstall": "node scripts/setup.js"
14
+ },
15
+ "files": [
16
+ "dist/",
17
+ "scripts/",
18
+ "README.md"
19
+ ],
20
+ "keywords": ["mcp", "ai", "fabrication", "detection", "hallucination", "governance"],
21
+ "author": "Arkheia AI <dmurfet@arkheia.ai>",
22
+ "license": "MIT",
23
+ "engines": {
24
+ "node": ">=18.0.0"
25
+ },
26
+ "dependencies": {
27
+ "@modelcontextprotocol/sdk": "^1.12.0",
28
+ "sql.js": "^1.11.0",
29
+ "zod": "^3.23.8"
30
+ },
31
+ "devDependencies": {
32
+ "@types/sql.js": "^1.4.9",
33
+ "@types/node": "^20.14.10",
34
+ "typescript": "^5.5.3"
35
+ }
36
+ }
@@ -1,240 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Arkheia MCP Server — thin Node wrapper that spawns the Python MCP server.
4
- *
5
- * This wrapper exists so that MCP clients can install via:
6
- * npx @arkheia/mcp-server
7
- * npm install -g @arkheia/mcp-server
8
- *
9
- * It:
10
- * 1. Locates a Python 3.10+ interpreter
11
- * 2. Ensures mcp_server dependencies are installed (pip install)
12
- * 3. Spawns `python -m mcp_server.server` with stdio transport
13
- * 4. Forwards stdin/stdout/stderr (MCP uses stdio)
14
- *
15
- * Environment variables:
16
- * ARKHEIA_API_KEY — API key for hosted detection (required)
17
- * ARKHEIA_PROXY_URL — Local proxy URL (optional, for enterprise)
18
- * ARKHEIA_HOSTED_URL — Hosted API URL (default: https://arkheia-proxy-production.up.railway.app)
19
- */
20
-
21
- const { spawn, execSync } = require("child_process");
22
- const path = require("path");
23
- const fs = require("fs");
24
-
25
- const PYTHON_DIR = path.join(__dirname, "..", "python");
26
- const REQUIREMENTS = path.join(PYTHON_DIR, "requirements.txt");
27
- const VENV_DIR = path.join(
28
- process.env.HOME || process.env.USERPROFILE || "/tmp",
29
- ".arkheia",
30
- "venv"
31
- );
32
-
33
- function findPython() {
34
- // Try versioned interpreters first — on Homebrew, keg-only formulae like
35
- // python@3.12 only expose the versioned binary (python3.12), not python3.
36
- // Exclude 3.14: Homebrew's build has broken pyexpat on macOS as of Apr 2026.
37
- const candidates = ["python3.13", "python3.12", "python3.11", "python3", "python"];
38
- for (const cmd of candidates) {
39
- try {
40
- // Check version AND that pyexpat + ensurepip actually work.
41
- // Python 3.14 on macOS crashes on `import pyexpat` due to a missing
42
- // libexpat symbol — this import check catches it at discovery time.
43
- const output = execSync(
44
- `${cmd} -c "import sys,pyexpat,ensurepip; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`,
45
- { encoding: "utf-8", timeout: 10000, stdio: ["pipe", "pipe", "pipe"] }
46
- ).trim();
47
- const match = output.match(/^(\d+)\.(\d+)$/);
48
- if (match) {
49
- const major = parseInt(match[1]);
50
- const minor = parseInt(match[2]);
51
- if (major === 3 && minor >= 10 && minor <= 13) {
52
- return cmd;
53
- }
54
- }
55
- } catch {
56
- // Try next candidate
57
- }
58
- }
59
- return null;
60
- }
61
-
62
- function venvIsHealthy(venvPython) {
63
- if (!fs.existsSync(venvPython)) return false;
64
- try {
65
- execSync(`"${venvPython}" -m pip --version`, {
66
- encoding: "utf-8", timeout: 10000, stdio: ["pipe", "pipe", "pipe"],
67
- });
68
- return true;
69
- } catch {
70
- return false;
71
- }
72
- }
73
-
74
- function ensureVenv(python) {
75
- const venvPython =
76
- process.platform === "win32"
77
- ? path.join(VENV_DIR, "Scripts", "python.exe")
78
- : path.join(VENV_DIR, "bin", "python");
79
-
80
- if (!venvIsHealthy(venvPython)) {
81
- if (fs.existsSync(VENV_DIR)) {
82
- process.stderr.write("[arkheia] Existing venv is unhealthy (pip broken or missing). Recreating...\n");
83
- fs.rmSync(VENV_DIR, { recursive: true, force: true });
84
- }
85
- process.stderr.write("[arkheia] Creating virtual environment...\n");
86
- execSync(`${python} -m venv "${VENV_DIR}"`, { stdio: "inherit" });
87
- // Force-reinstall deps after venv recreation
88
- const marker = path.join(VENV_DIR, ".arkheia-deps-installed");
89
- if (fs.existsSync(marker)) fs.unlinkSync(marker);
90
- }
91
-
92
- return venvPython;
93
- }
94
-
95
- function installDeps(venvPython) {
96
- const marker = path.join(VENV_DIR, ".arkheia-deps-installed");
97
- if (fs.existsSync(marker)) {
98
- return; // Already installed
99
- }
100
-
101
- const logFile = path.join(ARKHEIA_HOME, "install.log");
102
- process.stderr.write("[arkheia] Installing Python dependencies (first run)...\n");
103
- const start = Date.now();
104
- try {
105
- const output = execSync(`"${venvPython}" -m pip install -r "${REQUIREMENTS}" 2>&1`, {
106
- encoding: "utf-8",
107
- timeout: 300000, // 5 min — slow networks exist
108
- });
109
- const elapsed = ((Date.now() - start) / 1000).toFixed(1);
110
- // Count installed packages from pip output
111
- const installed = (output.match(/Successfully installed/g) || []).length;
112
- process.stderr.write(`[arkheia] Dependencies installed in ${elapsed}s\n`);
113
- fs.writeFileSync(marker, new Date().toISOString());
114
- } catch (err) {
115
- const elapsed = ((Date.now() - start) / 1000).toFixed(1);
116
- // Save full pip output for debugging
117
- const pipOutput = err.stdout || err.stderr || err.message || "unknown error";
118
- fs.writeFileSync(logFile, pipOutput);
119
- process.stderr.write(
120
- `[arkheia] Dependency install failed after ${elapsed}s.\n` +
121
- `[arkheia] Full output saved to: ${logFile}\n` +
122
- `[arkheia] Try: "${venvPython}" -m pip install -r "${REQUIREMENTS}"\n`
123
- );
124
- throw err;
125
- }
126
- }
127
-
128
- function main() {
129
- // ── CRLF warning — env files with Windows line endings silently break API keys
130
- for (const k of ["ARKHEIA_API_KEY", "ARKHEIA_PROXY_URL", "ARKHEIA_HOSTED_URL"]) {
131
- const v = process.env[k];
132
- if (v && /[\r\n]/.test(v)) {
133
- process.stderr.write(
134
- `[arkheia] WARNING: ${k} contains whitespace/newline characters.\n` +
135
- `[arkheia] Your env file may have Windows (CRLF) line endings. Run 'dos2unix' on it.\n`
136
- );
137
- process.env[k] = v.trim(); // auto-fix for this run
138
- }
139
- }
140
-
141
- const python = findPython();
142
- if (!python) {
143
- process.stderr.write(
144
- "[arkheia] Error: Python 3.10–3.13 is required but not found.\n\n" +
145
- " macOS (Homebrew):\n" +
146
- " brew install python@3.12\n\n" +
147
- " NOTE: Homebrew's current default 'brew install python' installs 3.14,\n" +
148
- " which has a broken pyexpat link on macOS as of April 2026.\n" +
149
- " Use python@3.12 until Homebrew ships a fix.\n\n" +
150
- " After installing, verify with:\n" +
151
- " python3.12 -c \"import pyexpat, ensurepip\"\n\n" +
152
- " Other platforms: https://python.org\n"
153
- );
154
- process.exit(1);
155
- }
156
-
157
- // ── Load config from ~/.arkheia/config.json ──────────────────
158
- const configPath = path.join(
159
- process.env.HOME || process.env.USERPROFILE || "/tmp",
160
- ".arkheia",
161
- "config.json"
162
- );
163
- let arkheiaConfig = {};
164
- try {
165
- if (fs.existsSync(configPath)) {
166
- arkheiaConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
167
- process.stderr.write(`[arkheia] Loaded config from ${configPath}\n`);
168
- }
169
- } catch (err) {
170
- process.stderr.write(
171
- `[arkheia] Warning: Could not read ${configPath}: ${err.message}\n`
172
- );
173
- }
174
-
175
- // Inject API key from config if not already in env
176
- if (!process.env.ARKHEIA_API_KEY && arkheiaConfig.api_key) {
177
- process.env.ARKHEIA_API_KEY = arkheiaConfig.api_key;
178
- process.stderr.write("[arkheia] API key loaded from config.json\n");
179
- }
180
-
181
- // Inject hosted URL from config if not already in env
182
- if (!process.env.ARKHEIA_HOSTED_URL && arkheiaConfig.proxy_url) {
183
- process.env.ARKHEIA_HOSTED_URL = arkheiaConfig.proxy_url;
184
- process.stderr.write(`[arkheia] Hosted URL: ${arkheiaConfig.proxy_url}\n`);
185
- }
186
-
187
- // Check for API key
188
- if (!process.env.ARKHEIA_API_KEY) {
189
- process.stderr.write(
190
- "[arkheia] Warning: ARKHEIA_API_KEY not set.\n" +
191
- "Get a free API key at https://arkheia.ai/mcp\n" +
192
- "Then set: export ARKHEIA_API_KEY=ak_live_...\n\n"
193
- );
194
- }
195
-
196
- let venvPython;
197
- try {
198
- venvPython = ensureVenv(python);
199
- installDeps(venvPython);
200
- } catch (err) {
201
- process.stderr.write(
202
- `[arkheia] Error setting up Python environment: ${err.message}\n`
203
- );
204
- process.exit(1);
205
- }
206
-
207
- // Spawn the MCP server with stdio transport
208
- const serverDir = PYTHON_DIR;
209
- const child = spawn(
210
- venvPython,
211
- ["-m", "mcp_server.server"],
212
- {
213
- cwd: serverDir,
214
- stdio: ["pipe", "pipe", "inherit"], // stdin/stdout piped, stderr inherited
215
- env: {
216
- ...process.env,
217
- PYTHONPATH: serverDir,
218
- },
219
- }
220
- );
221
-
222
- // Forward stdio for MCP protocol
223
- process.stdin.pipe(child.stdin);
224
- child.stdout.pipe(process.stdout);
225
-
226
- child.on("error", (err) => {
227
- process.stderr.write(`[arkheia] Failed to start MCP server: ${err.message}\n`);
228
- process.exit(1);
229
- });
230
-
231
- child.on("exit", (code) => {
232
- process.exit(code || 0);
233
- });
234
-
235
- // Forward signals
236
- process.on("SIGINT", () => child.kill("SIGINT"));
237
- process.on("SIGTERM", () => child.kill("SIGTERM"));
238
- }
239
-
240
- main();
File without changes
@@ -1,4 +0,0 @@
1
- mcp>=1.26.0
2
- httpx>=0.27.1
3
- pydantic>=2.10.0
4
- pyyaml>=6.0