aikoql-mcp 0.1.3

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.
Files changed (2) hide show
  1. package/package.json +31 -0
  2. package/run.js +121 -0
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "aikoql-mcp",
3
+ "version": "0.1.3",
4
+ "description": "Aikoql — The Agent-First Knowledge Database. Single binary, zero deps. 59 MCP tools.",
5
+ "license": "Apache-2.0",
6
+ "author": {
7
+ "name": "Anckur Singh",
8
+ "url": "https://github.com/anckursingh"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/anckursingh/aikoql.git"
13
+ },
14
+ "homepage": "https://github.com/anckursingh/aikoql",
15
+ "keywords": [
16
+ "aikoql",
17
+ "knowledge-graph",
18
+ "knowledge-database",
19
+ "mcp",
20
+ "mcp-server",
21
+ "ai-agents",
22
+ "context-compiler",
23
+ "claude-code"
24
+ ],
25
+ "bin": {
26
+ "aikoql-mcp": "./run.js"
27
+ },
28
+ "files": [
29
+ "run.js"
30
+ ]
31
+ }
package/run.js ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ // Aikoql — download + verify + run the platform binary from GitHub Releases.
3
+ const { execSync, spawn } = require('child_process');
4
+ const path = require('path');
5
+ const fs = require('fs');
6
+ const crypto = require('crypto');
7
+
8
+ const BIN_DIR = path.join(__dirname, 'bin');
9
+ const exe = process.platform === 'win32' ? 'aikoql.exe' : 'aikoql';
10
+ const binPath = path.join(BIN_DIR, exe);
11
+
12
+ const PLATFORM_MAP = {
13
+ 'win32-x64': 'aikoql-mcp.exe',
14
+ 'linux-x64': 'aikoql-mcp-linux',
15
+ 'darwin-x64': 'aikoql-mcp-macos',
16
+ 'darwin-arm64': 'aikoql-mcp-macos-arm64',
17
+ };
18
+
19
+ function fail(msg) {
20
+ console.error(`aikoql: ${msg}\nBuild from source: cargo install aikoql-mcp`);
21
+ process.exit(1);
22
+ }
23
+
24
+ function download() {
25
+ const platform = `${process.platform}-${process.arch}`;
26
+ const file = PLATFORM_MAP[platform];
27
+ if (!file) {
28
+ fail(`no prebuilt binary for ${platform}.`);
29
+ }
30
+
31
+ const base = `https://github.com/anckursingh/aikoql/releases/latest/download`;
32
+ const binUrl = `${base}/${file}`;
33
+ const chkUrl = `${base}/${file}.sha256`;
34
+
35
+ console.error(`aikoql: downloading ${file}...`);
36
+
37
+ fs.mkdirSync(BIN_DIR, { recursive: true });
38
+
39
+ const tmpPath = binPath + '.tmp';
40
+ const clean = () => { try { fs.unlinkSync(tmpPath); } catch (_) {} };
41
+
42
+ // ── Download binary ──────────────────────────────────────────
43
+ try {
44
+ clean();
45
+ if (process.platform === 'win32') {
46
+ execSync(`powershell -c "$ProgressPreference='SilentlyContinue'; Invoke-WebRequest -Uri '${binUrl}' -OutFile '${tmpPath}'"`, { stdio: 'inherit' });
47
+ } else {
48
+ execSync(`curl -fsSL '${binUrl}' -o '${tmpPath}' && chmod +x '${tmpPath}'`, { stdio: 'inherit' });
49
+ }
50
+ } catch (_) {
51
+ clean();
52
+ fail('download failed.');
53
+ }
54
+
55
+ // ── Size sanity check ────────────────────────────────────────
56
+ try {
57
+ const stat = fs.statSync(tmpPath);
58
+ if (stat.size < 1_000_000) {
59
+ throw new Error(`file too small (${stat.size} bytes), likely corrupted`);
60
+ }
61
+ } catch (e) {
62
+ clean();
63
+ fail(e.message);
64
+ }
65
+
66
+ // ── SHA-256 verification ─────────────────────────────────────
67
+ console.error('aikoql: verifying checksum...');
68
+ try {
69
+ const checksumUrl = chkUrl;
70
+ let expected;
71
+ if (process.platform === 'win32') {
72
+ expected = execSync(`powershell -c "$ProgressPreference='SilentlyContinue'; (Invoke-WebRequest -Uri '${checksumUrl}').Content.Trim()"`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
73
+ } else {
74
+ expected = execSync(`curl -fsSL '${checksumUrl}'`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
75
+ }
76
+
77
+ const actual = crypto.createHash('sha256').update(fs.readFileSync(tmpPath)).digest('hex');
78
+
79
+ // The .sha256 file may be "<hash> <filename>" or just "<hash>"
80
+ const expectedHash = expected.split(/\s+/)[0].toLowerCase();
81
+ if (expectedHash !== actual) {
82
+ throw new Error(`checksum mismatch\n expected: ${expectedHash}\n actual: ${actual}`);
83
+ }
84
+ console.error(`aikoql: checksum OK (${actual.substring(0, 12)}...)`);
85
+ } catch (e) {
86
+ clean();
87
+ if (e.message.includes('checksum mismatch')) {
88
+ fail(e.message);
89
+ }
90
+ fail(`checksum verification failed — unable to fetch or verify integrity.`);
91
+ }
92
+
93
+ fs.renameSync(tmpPath, binPath);
94
+ if (process.platform !== 'win32') {
95
+ try { fs.chmodSync(binPath, 0o755); } catch (_) {}
96
+ }
97
+ }
98
+
99
+ if (!fs.existsSync(binPath)) {
100
+ download();
101
+ }
102
+
103
+ if (!fs.existsSync(binPath)) {
104
+ fail('binary not found after download.');
105
+ }
106
+
107
+ // Forward all args to the binary via long-lived spawn (MCP needs persistent stdio)
108
+ const args = process.argv.slice(2);
109
+ const child = spawn(binPath, args, { stdio: 'inherit' });
110
+
111
+ child.on('exit', (code, signal) => {
112
+ if (signal) {
113
+ process.exit(128 + (signal === 'SIGTERM' ? 15 : 9));
114
+ }
115
+ process.exit(code || 0);
116
+ });
117
+
118
+ // Forward parent signals to child
119
+ ['SIGTERM', 'SIGINT', 'SIGHUP'].forEach(sig => {
120
+ process.on(sig, () => child.kill(sig));
121
+ });