diff --git a/packages/vestige-mcp-npm/.gitignore b/packages/vestige-mcp-npm/.gitignore new file mode 100644 index 0000000..7c5d56c --- /dev/null +++ b/packages/vestige-mcp-npm/.gitignore @@ -0,0 +1,7 @@ +# Downloaded binaries (installed via postinstall) +bin/vestige +bin/vestige.exe +bin/vestige-mcp +bin/vestige-mcp.exe +bin/*.tar.gz +bin/*.zip diff --git a/packages/vestige-mcp-npm/README.md b/packages/vestige-mcp-npm/README.md index c484041..f567ce0 100644 --- a/packages/vestige-mcp-npm/README.md +++ b/packages/vestige-mcp-npm/README.md @@ -10,6 +10,29 @@ Built on 130 years of cognitive science research, Vestige provides biologically- npm install -g @vestige/mcp ``` +This automatically downloads the correct binary for your platform (macOS, Linux, Windows) from GitHub releases. + +### What gets installed + +| Command | Description | +|---------|-------------| +| `vestige-mcp` | MCP server for Claude integration | +| `vestige` | CLI for stats, health checks, and maintenance | + +### Verify installation + +```bash +vestige health +``` + +## Usage with Claude Code + +```bash +claude mcp add vestige vestige-mcp -s user +``` + +Then restart Claude. + ## Usage with Claude Desktop Add to your Claude Desktop configuration: @@ -21,30 +44,48 @@ Add to your Claude Desktop configuration: { "mcpServers": { "vestige": { - "command": "vestige-mcp", - "args": ["--project", "."] + "command": "vestige-mcp" } } } ``` +## CLI Commands + +```bash +vestige stats # Memory statistics +vestige stats --states # Cognitive state distribution +vestige health # System health check +vestige consolidate # Run memory maintenance cycle +``` + ## Features - **FSRS-6 Algorithm**: State-of-the-art spaced repetition for optimal memory retention - **Dual-Strength Memory**: Bjork & Bjork (1992) - Storage + Retrieval strength model -- **Sleep Consolidation**: Bio-inspired memory optimization cycles -- **Semantic Search**: Local embeddings for intelligent memory retrieval -- **Local-First**: All data stays on your machine +- **Synaptic Tagging**: Memories become important retroactively (Frey & Morris 1997) +- **Semantic Search**: Local embeddings via nomic-embed-text-v1.5 (768 dimensions) +- **Local-First**: All data stays on your machine - no cloud, no API costs -## MCP Tools +## Storage & Memory -| Tool | Description | -|------|-------------| -| `remember` | Store a new memory with importance scoring | -| `recall` | Retrieve memories by semantic similarity | -| `search` | Full-text search across all memories | -| `consolidate` | Trigger memory consolidation (sleep cycle) | -| `get_context` | Get relevant context for current project | +Vestige uses SQLite for storage. Your memories are stored on **disk**, not in RAM. + +- **Database limit**: 216TB (SQLite theoretical max) +- **RAM usage**: ~64MB cache (configurable) +- **Typical usage**: 1 million memories ≈ 1-2GB on disk + +You'll never run out of space. A heavy user creating 100 memories/day would use ~1.5GB after 10 years. + +## Embeddings + +On first use, Vestige downloads the nomic-embed-text-v1.5 model (~130MB). This is a one-time download and all subsequent operations are fully offline. + +The model is stored in `.fastembed_cache/` in your working directory, or you can set a global location: + +```bash +export FASTEMBED_CACHE_PATH="$HOME/.fastembed_cache" +``` ## Environment Variables @@ -52,6 +93,36 @@ Add to your Claude Desktop configuration: |----------|-------------|---------| | `VESTIGE_DATA_DIR` | Data storage directory | `~/.vestige` | | `VESTIGE_LOG_LEVEL` | Log verbosity | `info` | +| `FASTEMBED_CACHE_PATH` | Embeddings model location | `./.fastembed_cache` | + +## Troubleshooting + +### "Could not attach to MCP server vestige" + +1. Verify binary exists: `which vestige-mcp` +2. Test directly: `vestige-mcp` (should wait for stdio input) +3. Check Claude logs: `~/Library/Logs/Claude/` (macOS) + +### "vestige: command not found" + +Reinstall the package: +```bash +npm install -g @vestige/mcp +``` + +### Embeddings not downloading + +The model downloads on first `ingest` or `search` operation. If Claude can't connect to the MCP server, no memory operations happen and no model downloads. + +Fix the MCP connection first, then the model will download automatically. + +## Supported Platforms + +| Platform | Architecture | +|----------|--------------| +| macOS | ARM64 (Apple Silicon) | +| Linux | x86_64 | +| Windows | x86_64 | ## License diff --git a/packages/vestige-mcp-npm/bin/vestige-mcp.js b/packages/vestige-mcp-npm/bin/vestige-mcp.js index 04c1177..9165dad 100755 --- a/packages/vestige-mcp-npm/bin/vestige-mcp.js +++ b/packages/vestige-mcp-npm/bin/vestige-mcp.js @@ -2,18 +2,30 @@ const { spawn } = require('child_process'); const path = require('path'); +const fs = require('fs'); const os = require('os'); const platform = os.platform(); -const arch = os.arch(); - const binaryName = platform === 'win32' ? 'vestige-mcp.exe' : 'vestige-mcp'; -const binaryPath = path.join(__dirname, '..', 'bin', binaryName); +const binaryPath = path.join(__dirname, binaryName); + +if (!fs.existsSync(binaryPath)) { + console.error('Error: vestige-mcp binary not found.'); + console.error(`Expected at: ${binaryPath}`); + console.error(''); + console.error('Try reinstalling: npm install -g @vestige/mcp'); + process.exit(1); +} const child = spawn(binaryPath, process.argv.slice(2), { stdio: 'inherit', }); +child.on('error', (err) => { + console.error('Failed to start vestige-mcp:', err.message); + process.exit(1); +}); + child.on('exit', (code) => { process.exit(code ?? 0); }); diff --git a/packages/vestige-mcp-npm/bin/vestige.js b/packages/vestige-mcp-npm/bin/vestige.js new file mode 100755 index 0000000..443f4a0 --- /dev/null +++ b/packages/vestige-mcp-npm/bin/vestige.js @@ -0,0 +1,31 @@ +#!/usr/bin/env node + +const { spawn } = require('child_process'); +const path = require('path'); +const fs = require('fs'); +const os = require('os'); + +const platform = os.platform(); +const binaryName = platform === 'win32' ? 'vestige.exe' : 'vestige'; +const binaryPath = path.join(__dirname, binaryName); + +if (!fs.existsSync(binaryPath)) { + console.error('Error: vestige CLI binary not found.'); + console.error(`Expected at: ${binaryPath}`); + console.error(''); + console.error('Try reinstalling: npm install -g @vestige/mcp'); + process.exit(1); +} + +const child = spawn(binaryPath, process.argv.slice(2), { + stdio: 'inherit', +}); + +child.on('error', (err) => { + console.error('Failed to start vestige:', err.message); + process.exit(1); +}); + +child.on('exit', (code) => { + process.exit(code ?? 0); +}); diff --git a/packages/vestige-mcp-npm/package.json b/packages/vestige-mcp-npm/package.json index 37ec915..eef19d9 100644 --- a/packages/vestige-mcp-npm/package.json +++ b/packages/vestige-mcp-npm/package.json @@ -1,9 +1,10 @@ { "name": "@vestige/mcp", - "version": "0.1.0", + "version": "1.1.0", "description": "Vestige MCP Server - AI Memory System for Claude and other assistants", "bin": { - "vestige-mcp": "./bin/vestige-mcp.js" + "vestige-mcp": "./bin/vestige-mcp.js", + "vestige": "./bin/vestige.js" }, "scripts": { "postinstall": "node scripts/postinstall.js" diff --git a/packages/vestige-mcp-npm/scripts/postinstall.js b/packages/vestige-mcp-npm/scripts/postinstall.js index 31a48ee..4c301ad 100644 --- a/packages/vestige-mcp-npm/scripts/postinstall.js +++ b/packages/vestige-mcp-npm/scripts/postinstall.js @@ -1,3 +1,5 @@ +#!/usr/bin/env node + const https = require('https'); const fs = require('fs'); const path = require('path'); @@ -24,18 +26,148 @@ const archStr = ARCH_MAP[ARCH]; if (!platformStr || !archStr) { console.error(`Unsupported platform: ${PLATFORM}-${ARCH}`); + console.error('Supported: darwin/linux/win32 on x64/arm64'); process.exit(1); } -const binaryName = PLATFORM === 'win32' ? 'vestige-mcp.exe' : 'vestige-mcp'; -const targetDir = path.join(__dirname, '..', 'bin'); -const targetPath = path.join(targetDir, binaryName); +const target = `${archStr}-${platformStr}`; +const isWindows = PLATFORM === 'win32'; +const archiveExt = isWindows ? 'zip' : 'tar.gz'; +const archiveName = `vestige-mcp-${target}.${archiveExt}`; +const downloadUrl = `https://github.com/samvallad33/vestige/releases/download/v${VERSION}/${archiveName}`; -// For now, just create a placeholder - real binaries come from GitHub releases -console.log(`Vestige MCP v${VERSION} installed for ${archStr}-${platformStr}`); -console.log(`Binary location: ${targetPath}`); +const targetDir = path.join(__dirname, '..', 'bin'); +const archivePath = path.join(targetDir, archiveName); + +console.log(`Installing Vestige MCP v${VERSION} for ${target}...`); // Ensure bin directory exists if (!fs.existsSync(targetDir)) { fs.mkdirSync(targetDir, { recursive: true }); } + +/** + * Download a file following redirects (GitHub releases use redirects) + */ +function download(url, dest) { + return new Promise((resolve, reject) => { + const file = fs.createWriteStream(dest); + + const request = (currentUrl) => { + https.get(currentUrl, (response) => { + // Handle redirects (GitHub uses 302) + if (response.statusCode === 301 || response.statusCode === 302) { + const redirectUrl = response.headers.location; + if (!redirectUrl) { + reject(new Error('Redirect without location header')); + return; + } + request(redirectUrl); + return; + } + + if (response.statusCode !== 200) { + reject(new Error(`Download failed: HTTP ${response.statusCode}`)); + return; + } + + response.pipe(file); + file.on('finish', () => { + file.close(); + resolve(); + }); + }).on('error', (err) => { + fs.unlink(dest, () => {}); // Delete partial file + reject(err); + }); + }; + + request(url); + }); +} + +/** + * Extract archive based on platform + */ +function extract(archivePath, destDir) { + if (isWindows) { + // Use PowerShell to extract zip on Windows + execSync( + `powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${destDir}' -Force"`, + { stdio: 'inherit' } + ); + } else { + // Use tar on Unix + execSync(`tar -xzf "${archivePath}" -C "${destDir}"`, { stdio: 'inherit' }); + } +} + +/** + * Make binaries executable (Unix only) + */ +function makeExecutable(binDir) { + if (isWindows) return; + + const binaries = ['vestige-mcp', 'vestige']; + for (const bin of binaries) { + const binPath = path.join(binDir, bin); + if (fs.existsSync(binPath)) { + fs.chmodSync(binPath, 0o755); + } + } +} + +async function main() { + try { + // Download + console.log(`Downloading from ${downloadUrl}...`); + await download(downloadUrl, archivePath); + console.log('Download complete.'); + + // Extract + console.log('Extracting binaries...'); + extract(archivePath, targetDir); + + // Cleanup archive + fs.unlinkSync(archivePath); + + // Make executable + makeExecutable(targetDir); + + // Verify installation + const mcpBinary = path.join(targetDir, isWindows ? 'vestige-mcp.exe' : 'vestige-mcp'); + const cliBinary = path.join(targetDir, isWindows ? 'vestige.exe' : 'vestige'); + + if (!fs.existsSync(mcpBinary)) { + throw new Error('vestige-mcp binary not found after extraction'); + } + + console.log(''); + console.log('Vestige MCP installed successfully!'); + console.log(''); + console.log('Binaries installed:'); + console.log(` - vestige-mcp: ${mcpBinary}`); + if (fs.existsSync(cliBinary)) { + console.log(` - vestige: ${cliBinary}`); + } + console.log(''); + console.log('Next steps:'); + console.log(' 1. Add to Claude: claude mcp add vestige vestige-mcp -s user'); + console.log(' 2. Restart Claude'); + console.log(' 3. Test with: "remember that my favorite color is blue"'); + console.log(''); + + } catch (err) { + console.error(''); + console.error('Installation failed:', err.message); + console.error(''); + console.error('Manual installation:'); + console.error(` 1. Download: ${downloadUrl}`); + console.error(` 2. Extract to: ${targetDir}`); + console.error(' 3. Ensure binaries are executable (chmod +x on Unix)'); + console.error(''); + process.exit(1); + } +} + +main();