@arkheia/mcp-server 0.1.0
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/README.md +84 -0
- package/bin/arkheia-mcp.js +174 -0
- package/package.json +43 -0
- package/python/mcp_server/__init__.py +0 -0
- package/python/requirements.txt +4 -0
- package/scripts/build.js +33 -0
- package/scripts/setup.js +129 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Arkheia MCP Server — Fabrication Detection for LLMs
|
|
2
|
+
|
|
3
|
+
Detect fabrication (hallucination) in any LLM output.
|
|
4
|
+
Free tier included (1,500 detections/month).
|
|
5
|
+
|
|
6
|
+
## Quick Start
|
|
7
|
+
|
|
8
|
+
### 1. Clone and install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git clone https://github.com/arkheiaai/arkheia-mcp.git ~/.arkheia-mcp
|
|
12
|
+
cd ~/.arkheia-mcp
|
|
13
|
+
pip install -r requirements.txt
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 2. Get an API key (free)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
curl -X POST https://arkheia-proxy-production.up.railway.app/v1/provision \
|
|
20
|
+
-H "Content-Type: application/json" \
|
|
21
|
+
-d '{"email": "you@example.com"}'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 3. Add to Claude Desktop
|
|
25
|
+
|
|
26
|
+
Edit your config file:
|
|
27
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
28
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"arkheia": {
|
|
34
|
+
"command": "python",
|
|
35
|
+
"args": ["-m", "mcp_server.server"],
|
|
36
|
+
"cwd": "~/.arkheia-mcp",
|
|
37
|
+
"env": {
|
|
38
|
+
"PYTHONPATH": "~/.arkheia-mcp",
|
|
39
|
+
"ARKHEIA_API_KEY": "ak_live_YOUR_KEY_HERE"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
On Windows, replace `~/.arkheia-mcp` with the full path (e.g. `C:/Users/YourName/.arkheia-mcp`).
|
|
47
|
+
|
|
48
|
+
### 4. Restart Claude
|
|
49
|
+
|
|
50
|
+
The `arkheia_verify` and `arkheia_audit_log` tools will appear automatically.
|
|
51
|
+
|
|
52
|
+
## Tools
|
|
53
|
+
|
|
54
|
+
| Tool | Description |
|
|
55
|
+
|------|-------------|
|
|
56
|
+
| `arkheia_verify` | Score any model output for fabrication risk (LOW/MEDIUM/HIGH) |
|
|
57
|
+
| `arkheia_audit_log` | Review detection history |
|
|
58
|
+
| `run_grok` | Call xAI Grok + screen for fabrication |
|
|
59
|
+
| `run_gemini` | Call Google Gemini + screen for fabrication |
|
|
60
|
+
| `run_together` | Call Together AI (Kimi, DeepSeek) + screen |
|
|
61
|
+
| `run_ollama` | Call local Ollama model + screen |
|
|
62
|
+
| `memory_store` / `memory_retrieve` / `memory_relate` | Persistent knowledge graph |
|
|
63
|
+
|
|
64
|
+
## Pricing
|
|
65
|
+
|
|
66
|
+
- **Free:** 1,500 detections/month (no credit card)
|
|
67
|
+
- **Single Contributor:** $99/month (unlimited)
|
|
68
|
+
- **Professional:** $499/month (20 concurrent)
|
|
69
|
+
- **Team:** $1,999/month (50 concurrent)
|
|
70
|
+
|
|
71
|
+
## Requirements
|
|
72
|
+
|
|
73
|
+
- Python 3.10+
|
|
74
|
+
- Git
|
|
75
|
+
|
|
76
|
+
## Full Setup Guide
|
|
77
|
+
|
|
78
|
+
See [AGENTS.md](https://github.com/arkheiaai/arkheia-mcp/blob/master/AGENTS.md) for detailed instructions, troubleshooting, and environment variables.
|
|
79
|
+
|
|
80
|
+
## Links
|
|
81
|
+
|
|
82
|
+
- Website: https://arkheia.ai
|
|
83
|
+
- GitHub: https://github.com/arkheiaai/arkheia-mcp
|
|
84
|
+
- Support: support@arkheia.ai
|
|
@@ -0,0 +1,174 @@
|
|
|
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
|
+
const candidates = ["python3", "python"];
|
|
35
|
+
for (const cmd of candidates) {
|
|
36
|
+
try {
|
|
37
|
+
const version = execSync(`${cmd} --version 2>&1`, {
|
|
38
|
+
encoding: "utf-8",
|
|
39
|
+
timeout: 5000,
|
|
40
|
+
}).trim();
|
|
41
|
+
const match = version.match(/Python (\d+)\.(\d+)/);
|
|
42
|
+
if (match && parseInt(match[1]) >= 3 && parseInt(match[2]) >= 10) {
|
|
43
|
+
return cmd;
|
|
44
|
+
}
|
|
45
|
+
} catch {
|
|
46
|
+
// Try next candidate
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function ensureVenv(python) {
|
|
53
|
+
const venvPython =
|
|
54
|
+
process.platform === "win32"
|
|
55
|
+
? path.join(VENV_DIR, "Scripts", "python.exe")
|
|
56
|
+
: path.join(VENV_DIR, "bin", "python");
|
|
57
|
+
|
|
58
|
+
if (!fs.existsSync(venvPython)) {
|
|
59
|
+
process.stderr.write("[arkheia] Creating virtual environment...\n");
|
|
60
|
+
execSync(`${python} -m venv "${VENV_DIR}"`, { stdio: "inherit" });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return venvPython;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function installDeps(venvPython) {
|
|
67
|
+
const marker = path.join(VENV_DIR, ".arkheia-deps-installed");
|
|
68
|
+
if (fs.existsSync(marker)) {
|
|
69
|
+
return; // Already installed
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
process.stderr.write("[arkheia] Installing dependencies...\n");
|
|
73
|
+
execSync(`"${venvPython}" -m pip install --quiet -r "${REQUIREMENTS}"`, {
|
|
74
|
+
stdio: "inherit",
|
|
75
|
+
timeout: 120000,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
fs.writeFileSync(marker, new Date().toISOString());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function main() {
|
|
82
|
+
const python = findPython();
|
|
83
|
+
if (!python) {
|
|
84
|
+
process.stderr.write(
|
|
85
|
+
"[arkheia] Error: Python 3.10+ is required but not found.\n" +
|
|
86
|
+
"Install Python from https://python.org and try again.\n"
|
|
87
|
+
);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── Load config from ~/.arkheia/config.json ──────────────────
|
|
92
|
+
const configPath = path.join(
|
|
93
|
+
process.env.HOME || process.env.USERPROFILE || "/tmp",
|
|
94
|
+
".arkheia",
|
|
95
|
+
"config.json"
|
|
96
|
+
);
|
|
97
|
+
let arkheiaConfig = {};
|
|
98
|
+
try {
|
|
99
|
+
if (fs.existsSync(configPath)) {
|
|
100
|
+
arkheiaConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
101
|
+
process.stderr.write(`[arkheia] Loaded config from ${configPath}\n`);
|
|
102
|
+
}
|
|
103
|
+
} catch (err) {
|
|
104
|
+
process.stderr.write(
|
|
105
|
+
`[arkheia] Warning: Could not read ${configPath}: ${err.message}\n`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Inject API key from config if not already in env
|
|
110
|
+
if (!process.env.ARKHEIA_API_KEY && arkheiaConfig.api_key) {
|
|
111
|
+
process.env.ARKHEIA_API_KEY = arkheiaConfig.api_key;
|
|
112
|
+
process.stderr.write("[arkheia] API key loaded from config.json\n");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Inject hosted URL from config if not already in env
|
|
116
|
+
if (!process.env.ARKHEIA_HOSTED_URL && arkheiaConfig.proxy_url) {
|
|
117
|
+
process.env.ARKHEIA_HOSTED_URL = arkheiaConfig.proxy_url;
|
|
118
|
+
process.stderr.write(`[arkheia] Hosted URL: ${arkheiaConfig.proxy_url}\n`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Check for API key
|
|
122
|
+
if (!process.env.ARKHEIA_API_KEY) {
|
|
123
|
+
process.stderr.write(
|
|
124
|
+
"[arkheia] Warning: ARKHEIA_API_KEY not set.\n" +
|
|
125
|
+
"Get a free API key at https://arkheia.ai/mcp\n" +
|
|
126
|
+
"Then set: export ARKHEIA_API_KEY=ak_live_...\n\n"
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let venvPython;
|
|
131
|
+
try {
|
|
132
|
+
venvPython = ensureVenv(python);
|
|
133
|
+
installDeps(venvPython);
|
|
134
|
+
} catch (err) {
|
|
135
|
+
process.stderr.write(
|
|
136
|
+
`[arkheia] Error setting up Python environment: ${err.message}\n`
|
|
137
|
+
);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Spawn the MCP server with stdio transport
|
|
142
|
+
const serverDir = PYTHON_DIR;
|
|
143
|
+
const child = spawn(
|
|
144
|
+
venvPython,
|
|
145
|
+
["-m", "mcp_server.server"],
|
|
146
|
+
{
|
|
147
|
+
cwd: serverDir,
|
|
148
|
+
stdio: ["pipe", "pipe", "inherit"], // stdin/stdout piped, stderr inherited
|
|
149
|
+
env: {
|
|
150
|
+
...process.env,
|
|
151
|
+
PYTHONPATH: serverDir,
|
|
152
|
+
},
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// Forward stdio for MCP protocol
|
|
157
|
+
process.stdin.pipe(child.stdin);
|
|
158
|
+
child.stdout.pipe(process.stdout);
|
|
159
|
+
|
|
160
|
+
child.on("error", (err) => {
|
|
161
|
+
process.stderr.write(`[arkheia] Failed to start MCP server: ${err.message}\n`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
child.on("exit", (code) => {
|
|
166
|
+
process.exit(code || 0);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Forward signals
|
|
170
|
+
process.on("SIGINT", () => child.kill("SIGINT"));
|
|
171
|
+
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arkheia/mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Arkheia MCP Server — Fabrication detection for LLM outputs. Detect hallucination in any model's output with a single tool call.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"mcp-server": "bin/arkheia-mcp.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"start": "node bin/arkheia-mcp.js",
|
|
10
|
+
"postinstall": "node scripts/setup.js"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"mcp",
|
|
14
|
+
"ai",
|
|
15
|
+
"fabrication",
|
|
16
|
+
"hallucination",
|
|
17
|
+
"detection",
|
|
18
|
+
"llm",
|
|
19
|
+
"claude",
|
|
20
|
+
"gpt",
|
|
21
|
+
"gemini",
|
|
22
|
+
"governance",
|
|
23
|
+
"audit",
|
|
24
|
+
"grounding",
|
|
25
|
+
"verification"
|
|
26
|
+
],
|
|
27
|
+
"author": "Arkheia AI <support@arkheia.ai>",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"homepage": "https://arkheia.ai/mcp",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/arkheiaai/arkheia-mcp.git"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18.0.0"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"bin/",
|
|
39
|
+
"scripts/",
|
|
40
|
+
"python/",
|
|
41
|
+
"README.md"
|
|
42
|
+
]
|
|
43
|
+
}
|
|
File without changes
|
package/scripts/build.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Build script — copies Python MCP server source into npm package.
|
|
4
|
+
* Run before `npm publish`.
|
|
5
|
+
*
|
|
6
|
+
* Usage: node scripts/build.js
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
|
|
12
|
+
const SRC = path.resolve(__dirname, "..", "..", "mcp_server");
|
|
13
|
+
const DEST = path.resolve(__dirname, "..", "python", "mcp_server");
|
|
14
|
+
|
|
15
|
+
function copyDir(src, dest) {
|
|
16
|
+
if (!fs.existsSync(dest)) {
|
|
17
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
20
|
+
const srcPath = path.join(src, entry.name);
|
|
21
|
+
const destPath = path.join(dest, entry.name);
|
|
22
|
+
if (entry.name === "__pycache__" || entry.name === "tests") continue;
|
|
23
|
+
if (entry.isDirectory()) {
|
|
24
|
+
copyDir(srcPath, destPath);
|
|
25
|
+
} else if (entry.name.endsWith(".py")) {
|
|
26
|
+
fs.copyFileSync(srcPath, destPath);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log(`Copying ${SRC} -> ${DEST}`);
|
|
32
|
+
copyDir(SRC, DEST);
|
|
33
|
+
console.log("Build complete. Run `npm publish` from npm-wrapper/.");
|
package/scripts/setup.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Post-install script — verifies Python is available and prints setup instructions.
|
|
4
|
+
* Does NOT auto-install Python dependencies (that happens on first run).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { execSync } = require("child_process");
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
|
|
11
|
+
const ARKHEIA_DIR = path.join(
|
|
12
|
+
process.env.HOME || process.env.USERPROFILE || "/tmp",
|
|
13
|
+
".arkheia"
|
|
14
|
+
);
|
|
15
|
+
const CONFIG_FILE = path.join(ARKHEIA_DIR, "config.json");
|
|
16
|
+
|
|
17
|
+
function checkApiKey() {
|
|
18
|
+
// Check if config.json exists and has api_key
|
|
19
|
+
try {
|
|
20
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
21
|
+
const config = JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
|
|
22
|
+
if (config.api_key && config.api_key.length > 0) {
|
|
23
|
+
return config.api_key;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
// Corrupt config — treat as missing
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Check environment variable
|
|
31
|
+
if (process.env.ARKHEIA_API_KEY) {
|
|
32
|
+
// Save env-provided key to config for future runs
|
|
33
|
+
saveConfig(process.env.ARKHEIA_API_KEY);
|
|
34
|
+
return process.env.ARKHEIA_API_KEY;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function saveConfig(apiKey) {
|
|
41
|
+
try {
|
|
42
|
+
if (!fs.existsSync(ARKHEIA_DIR)) {
|
|
43
|
+
fs.mkdirSync(ARKHEIA_DIR, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
const config = {
|
|
46
|
+
api_key: apiKey,
|
|
47
|
+
proxy_url: "https://arkheia-proxy-production.up.railway.app",
|
|
48
|
+
provisioned_at: new Date().toISOString(),
|
|
49
|
+
};
|
|
50
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.error(` [arkheia] Warning: Could not save config: ${err.message}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function checkPython() {
|
|
57
|
+
const candidates = ["python3", "python"];
|
|
58
|
+
for (const cmd of candidates) {
|
|
59
|
+
try {
|
|
60
|
+
const version = execSync(`${cmd} --version 2>&1`, {
|
|
61
|
+
encoding: "utf-8",
|
|
62
|
+
timeout: 5000,
|
|
63
|
+
}).trim();
|
|
64
|
+
const match = version.match(/Python (\d+)\.(\d+)/);
|
|
65
|
+
if (match && parseInt(match[1]) >= 3 && parseInt(match[2]) >= 10) {
|
|
66
|
+
return { cmd, version };
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
// Try next
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const python = checkPython();
|
|
76
|
+
|
|
77
|
+
if (!python) {
|
|
78
|
+
console.log(`
|
|
79
|
+
============================================================
|
|
80
|
+
Arkheia MCP Server requires Python 3.10+
|
|
81
|
+
|
|
82
|
+
Install Python from: https://python.org
|
|
83
|
+
Then run: npx @arkheia/mcp-server
|
|
84
|
+
============================================================
|
|
85
|
+
`);
|
|
86
|
+
} else {
|
|
87
|
+
console.log(`
|
|
88
|
+
============================================================
|
|
89
|
+
Arkheia MCP Server installed successfully.
|
|
90
|
+
Python: ${python.version}
|
|
91
|
+
============================================================
|
|
92
|
+
`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ── API key provisioning check ──────────────────────────────────
|
|
96
|
+
const existingKey = checkApiKey();
|
|
97
|
+
|
|
98
|
+
if (existingKey) {
|
|
99
|
+
const maskedKey =
|
|
100
|
+
existingKey.substring(0, 8) + "..." + existingKey.substring(existingKey.length - 4);
|
|
101
|
+
console.log(`
|
|
102
|
+
============================================================
|
|
103
|
+
API key found: ${maskedKey}
|
|
104
|
+
Config: ${CONFIG_FILE}
|
|
105
|
+
============================================================
|
|
106
|
+
`);
|
|
107
|
+
} else {
|
|
108
|
+
console.log(`
|
|
109
|
+
============================================================
|
|
110
|
+
No Arkheia API key configured.
|
|
111
|
+
|
|
112
|
+
To enable hosted detection and encrypted profiles:
|
|
113
|
+
|
|
114
|
+
1. Get a free API key at: https://arkheia.ai/mcp
|
|
115
|
+
2. Set it in your environment:
|
|
116
|
+
export ARKHEIA_API_KEY=ak_live_...
|
|
117
|
+
|
|
118
|
+
Or save it directly to ${CONFIG_FILE}:
|
|
119
|
+
{
|
|
120
|
+
"api_key": "ak_live_...",
|
|
121
|
+
"proxy_url": "https://arkheia-proxy-production.up.railway.app",
|
|
122
|
+
"provisioned_at": "..."
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
The server will work without a key, but encrypted profiles
|
|
126
|
+
and hosted detection will be unavailable.
|
|
127
|
+
============================================================
|
|
128
|
+
`);
|
|
129
|
+
}
|