@vespermcp/mcp-server 1.2.21 → 1.2.22

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 (35) hide show
  1. package/README.md +49 -0
  2. package/build/cloud/adapters/supabase.js +49 -0
  3. package/build/cloud/storage-manager.js +6 -0
  4. package/build/export/exporter.js +22 -9
  5. package/build/gateway/unified-dataset-gateway.js +410 -0
  6. package/build/index.js +1587 -845
  7. package/build/ingestion/ingestor.js +7 -4
  8. package/build/install/install-service.js +11 -6
  9. package/build/lib/supabase.js +3 -0
  10. package/build/metadata/scraper.js +85 -14
  11. package/build/python/asset_downloader_engine.py +2 -0
  12. package/build/python/convert_engine.py +92 -0
  13. package/build/python/export_engine.py +45 -0
  14. package/build/python/kaggle_engine.py +77 -5
  15. package/build/python/normalize_engine.py +83 -0
  16. package/build/python/vesper/core/asset_downloader.py +5 -1
  17. package/build/search/engine.js +43 -5
  18. package/build/search/jit-orchestrator.js +18 -14
  19. package/build/search/query-intent.js +509 -0
  20. package/build/tools/formatter.js +6 -3
  21. package/build/utils/python-runtime.js +130 -0
  22. package/package.json +7 -5
  23. package/scripts/postinstall.cjs +87 -31
  24. package/scripts/wizard.cjs +601 -0
  25. package/scripts/wizard.js +306 -12
  26. package/src/python/__pycache__/config.cpython-312.pyc +0 -0
  27. package/src/python/__pycache__/kaggle_engine.cpython-312.pyc +0 -0
  28. package/src/python/asset_downloader_engine.py +2 -0
  29. package/src/python/convert_engine.py +92 -0
  30. package/src/python/export_engine.py +45 -0
  31. package/src/python/kaggle_engine.py +77 -5
  32. package/src/python/normalize_engine.py +83 -0
  33. package/src/python/requirements.txt +12 -0
  34. package/src/python/vesper/core/asset_downloader.py +5 -1
  35. package/wizard.cjs +3 -0
@@ -54,7 +54,7 @@ export function formatSearchResults(results) {
54
54
  results.forEach((ds, index) => {
55
55
  const relevanceScore = ds.relevance_score || 0;
56
56
  // Source badge and access level
57
- const openSources = ["huggingface", "uci", "github", "worldbank", "nasa"];
57
+ const openSources = ["huggingface", "openml", "s3", "uci", "github", "worldbank", "nasa"];
58
58
  const isOpen = openSources.includes(ds.source);
59
59
  const sourceLabel = ds.source.charAt(0).toUpperCase() + ds.source.slice(1);
60
60
  const accessBadge = isOpen ? "Open Access" : "Requires API Key";
@@ -131,7 +131,7 @@ export function formatDatasetInfo(ds) {
131
131
  output += `${ds.name}\n`;
132
132
  output += "═".repeat(80) + "\n\n";
133
133
  // Source and safety
134
- const openSources = ["huggingface", "uci", "github", "worldbank", "nasa"];
134
+ const openSources = ["huggingface", "openml", "s3", "uci", "github", "worldbank", "nasa"];
135
135
  const isOpen = openSources.includes(ds.source);
136
136
  const sourceLabel = ds.source.charAt(0).toUpperCase() + ds.source.slice(1);
137
137
  const accessBadge = isOpen ? "Open Access" : "Requires API Key";
@@ -149,7 +149,10 @@ export function formatDatasetInfo(ds) {
149
149
  output += `Safety: ${safetyIndicator}\n`;
150
150
  output += `ID: ${ds.id}\n\n`;
151
151
  if (!isOpen && ds.source === "kaggle") {
152
- output += `NOTE: This dataset requires a Kaggle API key (KAGGE_USERNAME/KAGGLE_KEY) to prepare.\n\n`;
152
+ output += `NOTE: This dataset uses the Kaggle connector. Vesper can access it through server-managed credentials when configured, otherwise a Kaggle key is still required.\n\n`;
153
+ }
154
+ if (!isOpen && ds.source === "dataworld") {
155
+ output += `NOTE: This dataset uses the data.world connector. Vesper can access it through a server-managed token when configured.\n\n`;
153
156
  }
154
157
  // Description
155
158
  if (ds.description) {
@@ -0,0 +1,130 @@
1
+ import { spawn } from "child_process";
2
+ import fs from "fs";
3
+ import os from "os";
4
+ import path from "path";
5
+ function getHomeDir(buildDir) {
6
+ return os.homedir() || process.env.HOME || process.env.USERPROFILE || buildDir;
7
+ }
8
+ export function getVesperDataRoot(buildDir = process.cwd()) {
9
+ return path.join(getHomeDir(buildDir), ".vesper");
10
+ }
11
+ export function getManagedPythonPath(buildDir = process.cwd()) {
12
+ const dataRoot = getVesperDataRoot(buildDir);
13
+ return process.platform === "win32"
14
+ ? path.join(dataRoot, ".venv", "Scripts", "python.exe")
15
+ : path.join(dataRoot, ".venv", "bin", "python");
16
+ }
17
+ function getFallbackPythonCommand() {
18
+ return process.platform === "win32" ? "py" : "python3";
19
+ }
20
+ export function resolvePythonCommand(buildDir = process.cwd()) {
21
+ const managedPython = getManagedPythonPath(buildDir);
22
+ if (fs.existsSync(managedPython)) {
23
+ return managedPython;
24
+ }
25
+ const envPython = process.env.VESPER_PYTHON;
26
+ if (envPython) {
27
+ return envPython;
28
+ }
29
+ const localCandidates = process.platform === "win32"
30
+ ? [
31
+ path.resolve(buildDir, ".venv", "Scripts", "python.exe"),
32
+ path.resolve(buildDir, "..", ".venv", "Scripts", "python.exe")
33
+ ]
34
+ : [
35
+ path.resolve(buildDir, ".venv", "bin", "python"),
36
+ path.resolve(buildDir, "..", ".venv", "bin", "python")
37
+ ];
38
+ for (const candidate of localCandidates) {
39
+ if (fs.existsSync(candidate)) {
40
+ return candidate;
41
+ }
42
+ }
43
+ return getFallbackPythonCommand();
44
+ }
45
+ function runPythonCommand(pythonPath, args, timeoutMs = 300000) {
46
+ return new Promise((resolve, reject) => {
47
+ const proc = spawn(pythonPath, args, {
48
+ env: {
49
+ ...process.env,
50
+ PYTHONIOENCODING: "utf-8",
51
+ },
52
+ });
53
+ let stdout = "";
54
+ let stderr = "";
55
+ const timer = setTimeout(() => {
56
+ proc.kill();
57
+ resolve({ code: 124, stdout, stderr: stderr || `Python command timed out after ${timeoutMs}ms` });
58
+ }, timeoutMs);
59
+ proc.stdout.on("data", (data) => {
60
+ stdout += data.toString();
61
+ });
62
+ proc.stderr.on("data", (data) => {
63
+ stderr += data.toString();
64
+ });
65
+ proc.on("close", (code) => {
66
+ clearTimeout(timer);
67
+ resolve({ code: code ?? 1, stdout, stderr });
68
+ });
69
+ proc.on("error", (error) => {
70
+ clearTimeout(timer);
71
+ reject(error);
72
+ });
73
+ });
74
+ }
75
+ async function createManagedPythonEnv(buildDir) {
76
+ const dataRoot = getVesperDataRoot(buildDir);
77
+ const venvDir = path.join(dataRoot, ".venv");
78
+ const managedPython = getManagedPythonPath(buildDir);
79
+ if (fs.existsSync(managedPython)) {
80
+ return managedPython;
81
+ }
82
+ fs.mkdirSync(dataRoot, { recursive: true });
83
+ const bootstrapAttempts = process.platform === "win32"
84
+ ? [
85
+ { command: "py", args: ["-3", "-m", "venv", venvDir] },
86
+ { command: "python", args: ["-m", "venv", venvDir] },
87
+ ]
88
+ : [
89
+ { command: "python3", args: ["-m", "venv", venvDir] },
90
+ { command: "python", args: ["-m", "venv", venvDir] },
91
+ ];
92
+ let lastError = "";
93
+ for (const attempt of bootstrapAttempts) {
94
+ try {
95
+ const result = await runPythonCommand(attempt.command, attempt.args, 180000);
96
+ if (result.code === 0 && fs.existsSync(managedPython)) {
97
+ await runPythonCommand(managedPython, ["-m", "pip", "install", "--disable-pip-version-check", "--upgrade", "pip"], 300000);
98
+ return managedPython;
99
+ }
100
+ lastError = (result.stderr || result.stdout || "Unknown venv creation error").trim();
101
+ }
102
+ catch (error) {
103
+ lastError = error?.message || String(error);
104
+ }
105
+ }
106
+ throw new Error(`Failed to create Vesper Python environment. ${lastError}`.trim());
107
+ }
108
+ export async function ensurePythonPackages(buildDir, requirements) {
109
+ const pythonPath = await createManagedPythonEnv(buildDir).catch(() => resolvePythonCommand(buildDir));
110
+ const missing = [];
111
+ for (const requirement of requirements) {
112
+ const check = await runPythonCommand(pythonPath, [
113
+ "-c",
114
+ `import importlib.util,sys; sys.exit(0 if importlib.util.find_spec(${JSON.stringify(requirement.module)}) else 1)`
115
+ ], 20000);
116
+ if (check.code !== 0) {
117
+ missing.push(requirement);
118
+ }
119
+ }
120
+ if (missing.length === 0) {
121
+ return pythonPath;
122
+ }
123
+ const packages = [...new Set(missing.map(requirement => requirement.packageName))];
124
+ const install = await runPythonCommand(pythonPath, ["-m", "pip", "install", "--disable-pip-version-check", ...packages], 600000);
125
+ if (install.code !== 0) {
126
+ const details = (install.stderr || install.stdout || "Unknown pip install error").trim();
127
+ throw new Error(`Failed to install Python packages (${packages.join(", ")}). ${details}`);
128
+ }
129
+ return pythonPath;
130
+ }
package/package.json CHANGED
@@ -1,17 +1,16 @@
1
1
  {
2
2
  "name": "@vespermcp/mcp-server",
3
- "version": "1.2.21",
3
+ "version": "1.2.22",
4
4
  "description": "AI-powered dataset discovery, quality analysis, and preparation MCP server with multimodal support (text, image, audio, video)",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
7
7
  "bin": {
8
- "mcp-server": "./build/index.js",
9
- "vespermcp": "./build/index.js",
10
- "vesper-wizard": "scripts/wizard.js"
8
+ "vesper-wizard": "wizard.cjs"
11
9
  },
12
10
  "files": [
13
11
  "build/**/*",
14
12
  "src/python/**/*",
13
+ "wizard.cjs",
15
14
  "scripts/**/*",
16
15
  "README.md",
17
16
  "LICENSE",
@@ -31,6 +30,7 @@
31
30
  "fuse": "node build/index.js fuse",
32
31
  "discover": "node build/index.js discover",
33
32
  "download": "node build/index.js download",
33
+ "export": "node build/index.js export",
34
34
  "config": "node build/index.js config",
35
35
  "test-fusion-engine": "py src/python/test_fusion_engine.py",
36
36
  "setup": "node build/index.js --setup",
@@ -59,7 +59,7 @@
59
59
  "license": "MIT",
60
60
  "repository": {
61
61
  "type": "git",
62
- "url": "https://github.com/vesper/mcp-server"
62
+ "url": "git+https://github.com/vesper/mcp-server.git"
63
63
  },
64
64
  "engines": {
65
65
  "node": ">=18.0.0",
@@ -68,6 +68,8 @@
68
68
  "dependencies": {
69
69
  "@huggingface/hub": "^2.7.1",
70
70
  "@modelcontextprotocol/sdk": "^1.25.2",
71
+ "@polar-sh/nextjs": "^0.9.4",
72
+ "@supabase/supabase-js": "^2.98.0",
71
73
  "@xenova/transformers": "^2.17.2",
72
74
  "adm-zip": "^0.5.16",
73
75
  "ajv": "^8.17.1",
@@ -2,13 +2,34 @@
2
2
 
3
3
  const { execSync } = require('child_process');
4
4
  const fs = require('fs');
5
+ const os = require('os');
5
6
  const path = require('path');
6
7
 
7
8
  console.log('\nšŸš€ Setting up Vesper MCP Server...\n');
8
9
 
10
+ function getPythonBootstrapCommand() {
11
+ const attempts = process.platform === 'win32'
12
+ ? ['py -3', 'python']
13
+ : ['python3', 'python'];
14
+
15
+ for (const command of attempts) {
16
+ try {
17
+ execSync(`${command} --version`, { stdio: 'pipe' });
18
+ return command;
19
+ } catch {
20
+ // try next command
21
+ }
22
+ }
23
+
24
+ return null;
25
+ }
26
+
9
27
  // 1. Check for Python
28
+ const pythonBootstrap = getPythonBootstrapCommand();
10
29
  try {
11
- execSync('python --version', { stdio: 'pipe' });
30
+ if (!pythonBootstrap) {
31
+ throw new Error('Python not found');
32
+ }
12
33
  console.log('āœ… Python found');
13
34
  } catch (e) {
14
35
  console.warn('āš ļø Python not found. Please install Python 3.8+ for full functionality.');
@@ -16,36 +37,15 @@ try {
16
37
  process.exit(0); // Don't fail installation
17
38
  }
18
39
 
19
- // 2. Install Python dependencies
20
- console.log('\nšŸ“¦ Installing Python dependencies...');
21
- const pythonPackages = [
22
- 'opencv-python',
23
- 'pillow',
24
- 'numpy',
25
- 'librosa',
26
- 'soundfile',
27
- 'aiohttp',
28
- 'aiofiles',
29
- 'datasets',
30
- 'webdataset',
31
- 'kaggle'
32
- ];
33
-
34
- try {
35
- execSync(`python -m pip install ${pythonPackages.join(' ')}`, {
36
- stdio: 'inherit',
37
- timeout: 120000 // 2 minutes timeout
38
- });
39
- console.log('āœ… Python dependencies installed');
40
- } catch (e) {
41
- console.warn('āš ļø Failed to install some Python dependencies.');
42
- console.warn(' You may need to install them manually:');
43
- console.warn(` pip install ${pythonPackages.join(' ')}\n`);
44
- }
45
-
46
- // 3. Create data directories
47
- const homeDir = process.env.HOME || process.env.USERPROFILE;
40
+ const homeDir = os.homedir() || process.env.HOME || process.env.USERPROFILE;
48
41
  const vesperDataDir = path.join(homeDir, '.vesper');
42
+ const managedVenvDir = path.join(vesperDataDir, '.venv');
43
+ const managedPython = process.platform === 'win32'
44
+ ? path.join(managedVenvDir, 'Scripts', 'python.exe')
45
+ : path.join(managedVenvDir, 'bin', 'python');
46
+ const requirementsPath = path.resolve(__dirname, '..', 'src', 'python', 'requirements.txt');
47
+
48
+ // 2. Create data directories
49
49
  const dirs = [
50
50
  vesperDataDir,
51
51
  path.join(vesperDataDir, 'data'),
@@ -62,7 +62,63 @@ dirs.forEach(dir => {
62
62
 
63
63
  console.log(`āœ… Data directories created at ${vesperDataDir}`);
64
64
 
65
- // 4. Auto-configure Claude Desktop (Best Effort)
65
+ // 3. Create a managed Vesper Python environment
66
+ console.log('\nšŸ Preparing managed Python environment...');
67
+ try {
68
+ if (!fs.existsSync(managedPython)) {
69
+ execSync(`${pythonBootstrap} -m venv "${managedVenvDir}"`, {
70
+ stdio: 'inherit',
71
+ timeout: 180000,
72
+ });
73
+ }
74
+ console.log(`āœ… Managed Python ready at ${managedVenvDir}`);
75
+ } catch (e) {
76
+ console.warn('āš ļø Failed to create the managed Vesper Python environment.');
77
+ console.warn(` Vesper will fall back to PATH Python and may need to self-heal at runtime. ${(e && e.message) || ''}`.trim());
78
+ }
79
+
80
+ // 4. Install Python dependencies into the managed environment
81
+ console.log('\nšŸ“¦ Installing Python dependencies...');
82
+ const pythonPackages = [
83
+ 'opencv-python',
84
+ 'pillow',
85
+ 'librosa',
86
+ 'soundfile',
87
+ 'pyarrow'
88
+ ];
89
+
90
+ try {
91
+ const targetPython = fs.existsSync(managedPython) ? `"${managedPython}"` : pythonBootstrap;
92
+ execSync(`${targetPython} -m pip install --disable-pip-version-check --upgrade pip`, {
93
+ stdio: 'inherit',
94
+ timeout: 180000,
95
+ });
96
+ execSync(`${targetPython} -m pip install --disable-pip-version-check -r "${requirementsPath}" ${pythonPackages.join(' ')}`, {
97
+ stdio: 'inherit',
98
+ timeout: 600000,
99
+ });
100
+ console.log('āœ… Python dependencies installed');
101
+ } catch (e) {
102
+ console.warn('āš ļø Failed to install some Python dependencies.');
103
+ console.warn(' You may need to install them manually into the Vesper runtime:');
104
+ console.warn(` ${fs.existsSync(managedPython) ? managedPython : pythonBootstrap} -m pip install -r "${requirementsPath}" ${pythonPackages.join(' ')}\n`);
105
+ }
106
+
107
+ // 5. Rebuild better-sqlite3 for current Node.js version
108
+ console.log('\nšŸ”§ Rebuilding native modules for current Node.js...');
109
+ try {
110
+ execSync('npm rebuild better-sqlite3', {
111
+ stdio: 'pipe',
112
+ timeout: 60000,
113
+ cwd: path.resolve(__dirname, '..')
114
+ });
115
+ console.log('āœ… Native modules rebuilt successfully');
116
+ } catch (e) {
117
+ console.warn('āš ļø Could not rebuild better-sqlite3: ' + (e.message || e));
118
+ console.warn(' If you see ERR_DLOPEN_FAILED, run: npm rebuild better-sqlite3');
119
+ }
120
+
121
+ // 6. Auto-configure Claude Desktop (Best Effort)
66
122
  console.log('\nāš™ļø Attempting to auto-configure Claude Desktop...');
67
123
 
68
124
  function getClaudeConfigPath() {