@vespermcp/mcp-server 1.2.8 → 1.2.10

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.
@@ -155,12 +155,7 @@ def _get_from_env(name: str) -> Optional[str]:
155
155
 
156
156
 
157
157
  def get_key(name: str) -> Optional[str]:
158
- # 1) env vars (highest priority)
159
- env_val = _get_from_env(name)
160
- if env_val:
161
- return env_val
162
-
163
- # 2) keyring (secure)
158
+ # 1) keyring (secure)
164
159
  if HAS_KEYRING:
165
160
  try:
166
161
  val = keyring.get_password(SERVICE_NAME, name)
@@ -169,14 +164,21 @@ def get_key(name: str) -> Optional[str]:
169
164
  except Exception:
170
165
  pass
171
166
 
172
- # 3) encrypted fallback config.toml
167
+ # 2) encrypted fallback config.toml
173
168
  fallback = _read_fallback_toml()
174
169
  enc = fallback.get(name)
175
- if not enc:
176
- return None
177
- secret = _get_or_create_local_secret()
178
- method = fallback.get("__method__", "fernet" if HAS_FERNET else "xor")
179
- return _decrypt_value(enc, method, secret)
170
+ if enc:
171
+ secret = _get_or_create_local_secret()
172
+ method = fallback.get("__method__", "fernet" if HAS_FERNET else "xor")
173
+ dec = _decrypt_value(enc, method, secret)
174
+ if dec:
175
+ return dec
176
+
177
+ # 3) env vars (fallback only)
178
+ env_val = _get_from_env(name)
179
+ if env_val:
180
+ return env_val
181
+ return None
180
182
 
181
183
 
182
184
  def set_key(name: str, value: str) -> Dict[str, str]:
@@ -20,14 +20,13 @@ def _ensure_auth() -> Dict[str, Any]:
20
20
  }
21
21
 
22
22
  # Priority:
23
- # 1) Existing env vars
24
- # 2) secure local store (keyring or ~/.vesper/config.toml)
23
+ # 1) secure local store (keyring or ~/.vesper/config.toml)
24
+ # 2) existing env vars
25
25
  # 3) ~/.kaggle/kaggle.json handled by KaggleApi.authenticate()
26
- if not os.getenv("KAGGLE_USERNAME") or not os.getenv("KAGGLE_KEY"):
27
- keys = get_all()
28
- if keys.get("kaggle_username") and keys.get("kaggle_key"):
29
- os.environ["KAGGLE_USERNAME"] = keys["kaggle_username"]
30
- os.environ["KAGGLE_KEY"] = keys["kaggle_key"]
26
+ keys = get_all()
27
+ if keys.get("kaggle_username") and keys.get("kaggle_key"):
28
+ os.environ["KAGGLE_USERNAME"] = keys["kaggle_username"]
29
+ os.environ["KAGGLE_KEY"] = keys["kaggle_key"]
31
30
 
32
31
  api = KaggleApi()
33
32
  try:
@@ -60,6 +60,42 @@ class AssetDownloader:
60
60
  if asyncio.iscoroutine(maybe):
61
61
  await maybe
62
62
 
63
+ @staticmethod
64
+ def _hydrate_kaggle_credentials() -> None:
65
+ try:
66
+ from config import get_all # type: ignore
67
+ keys = get_all() or {}
68
+ except Exception:
69
+ keys = {}
70
+
71
+ username = keys.get("kaggle_username") or os.getenv("KAGGLE_USERNAME")
72
+ key = keys.get("kaggle_key") or os.getenv("KAGGLE_KEY")
73
+
74
+ if username:
75
+ os.environ["KAGGLE_USERNAME"] = str(username)
76
+ if key:
77
+ os.environ["KAGGLE_KEY"] = str(key)
78
+
79
+ username = os.getenv("KAGGLE_USERNAME")
80
+ key = os.getenv("KAGGLE_KEY")
81
+ if not username or not key:
82
+ return
83
+
84
+ kaggle_dir = Path.home() / ".kaggle"
85
+ kaggle_file = kaggle_dir / "kaggle.json"
86
+ try:
87
+ kaggle_dir.mkdir(parents=True, exist_ok=True)
88
+ kaggle_file.write_text(
89
+ json.dumps({"username": username, "key": key}, ensure_ascii=False),
90
+ encoding="utf-8",
91
+ )
92
+ try:
93
+ os.chmod(kaggle_file, 0o600)
94
+ except Exception:
95
+ pass
96
+ except Exception:
97
+ pass
98
+
63
99
  @staticmethod
64
100
  def find_image_column(dataset: Any) -> Optional[str]:
65
101
  features = getattr(dataset, "features", None)
@@ -240,8 +276,17 @@ class AssetDownloader:
240
276
 
241
277
  await self._emit("start", {"source": "kaggle", "dataset": kaggle_ref})
242
278
 
279
+ self._hydrate_kaggle_credentials()
280
+
243
281
  api = KaggleApi()
244
- api.authenticate()
282
+ try:
283
+ api.authenticate()
284
+ except Exception as e:
285
+ raise RuntimeError(
286
+ "Kaggle authentication failed. Run 'configure_kaggle' or 'configure_keys' with "
287
+ "kaggle_username and kaggle_key, then retry. "
288
+ f"Details: {e}"
289
+ )
245
290
 
246
291
  tmp_dir = Path(tempfile.mkdtemp(prefix="vesper_kaggle_assets_"))
247
292
  downloaded = 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vespermcp/mcp-server",
3
- "version": "1.2.8",
3
+ "version": "1.2.10",
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",
@@ -155,12 +155,7 @@ def _get_from_env(name: str) -> Optional[str]:
155
155
 
156
156
 
157
157
  def get_key(name: str) -> Optional[str]:
158
- # 1) env vars (highest priority)
159
- env_val = _get_from_env(name)
160
- if env_val:
161
- return env_val
162
-
163
- # 2) keyring (secure)
158
+ # 1) keyring (secure)
164
159
  if HAS_KEYRING:
165
160
  try:
166
161
  val = keyring.get_password(SERVICE_NAME, name)
@@ -169,14 +164,21 @@ def get_key(name: str) -> Optional[str]:
169
164
  except Exception:
170
165
  pass
171
166
 
172
- # 3) encrypted fallback config.toml
167
+ # 2) encrypted fallback config.toml
173
168
  fallback = _read_fallback_toml()
174
169
  enc = fallback.get(name)
175
- if not enc:
176
- return None
177
- secret = _get_or_create_local_secret()
178
- method = fallback.get("__method__", "fernet" if HAS_FERNET else "xor")
179
- return _decrypt_value(enc, method, secret)
170
+ if enc:
171
+ secret = _get_or_create_local_secret()
172
+ method = fallback.get("__method__", "fernet" if HAS_FERNET else "xor")
173
+ dec = _decrypt_value(enc, method, secret)
174
+ if dec:
175
+ return dec
176
+
177
+ # 3) env vars (fallback only)
178
+ env_val = _get_from_env(name)
179
+ if env_val:
180
+ return env_val
181
+ return None
180
182
 
181
183
 
182
184
  def set_key(name: str, value: str) -> Dict[str, str]:
@@ -20,14 +20,13 @@ def _ensure_auth() -> Dict[str, Any]:
20
20
  }
21
21
 
22
22
  # Priority:
23
- # 1) Existing env vars
24
- # 2) secure local store (keyring or ~/.vesper/config.toml)
23
+ # 1) secure local store (keyring or ~/.vesper/config.toml)
24
+ # 2) existing env vars
25
25
  # 3) ~/.kaggle/kaggle.json handled by KaggleApi.authenticate()
26
- if not os.getenv("KAGGLE_USERNAME") or not os.getenv("KAGGLE_KEY"):
27
- keys = get_all()
28
- if keys.get("kaggle_username") and keys.get("kaggle_key"):
29
- os.environ["KAGGLE_USERNAME"] = keys["kaggle_username"]
30
- os.environ["KAGGLE_KEY"] = keys["kaggle_key"]
26
+ keys = get_all()
27
+ if keys.get("kaggle_username") and keys.get("kaggle_key"):
28
+ os.environ["KAGGLE_USERNAME"] = keys["kaggle_username"]
29
+ os.environ["KAGGLE_KEY"] = keys["kaggle_key"]
31
30
 
32
31
  api = KaggleApi()
33
32
  try:
@@ -60,6 +60,42 @@ class AssetDownloader:
60
60
  if asyncio.iscoroutine(maybe):
61
61
  await maybe
62
62
 
63
+ @staticmethod
64
+ def _hydrate_kaggle_credentials() -> None:
65
+ try:
66
+ from config import get_all # type: ignore
67
+ keys = get_all() or {}
68
+ except Exception:
69
+ keys = {}
70
+
71
+ username = keys.get("kaggle_username") or os.getenv("KAGGLE_USERNAME")
72
+ key = keys.get("kaggle_key") or os.getenv("KAGGLE_KEY")
73
+
74
+ if username:
75
+ os.environ["KAGGLE_USERNAME"] = str(username)
76
+ if key:
77
+ os.environ["KAGGLE_KEY"] = str(key)
78
+
79
+ username = os.getenv("KAGGLE_USERNAME")
80
+ key = os.getenv("KAGGLE_KEY")
81
+ if not username or not key:
82
+ return
83
+
84
+ kaggle_dir = Path.home() / ".kaggle"
85
+ kaggle_file = kaggle_dir / "kaggle.json"
86
+ try:
87
+ kaggle_dir.mkdir(parents=True, exist_ok=True)
88
+ kaggle_file.write_text(
89
+ json.dumps({"username": username, "key": key}, ensure_ascii=False),
90
+ encoding="utf-8",
91
+ )
92
+ try:
93
+ os.chmod(kaggle_file, 0o600)
94
+ except Exception:
95
+ pass
96
+ except Exception:
97
+ pass
98
+
63
99
  @staticmethod
64
100
  def find_image_column(dataset: Any) -> Optional[str]:
65
101
  features = getattr(dataset, "features", None)
@@ -240,8 +276,17 @@ class AssetDownloader:
240
276
 
241
277
  await self._emit("start", {"source": "kaggle", "dataset": kaggle_ref})
242
278
 
279
+ self._hydrate_kaggle_credentials()
280
+
243
281
  api = KaggleApi()
244
- api.authenticate()
282
+ try:
283
+ api.authenticate()
284
+ except Exception as e:
285
+ raise RuntimeError(
286
+ "Kaggle authentication failed. Run 'configure_kaggle' or 'configure_keys' with "
287
+ "kaggle_username and kaggle_key, then retry. "
288
+ f"Details: {e}"
289
+ )
245
290
 
246
291
  tmp_dir = Path(tempfile.mkdtemp(prefix="vesper_kaggle_assets_"))
247
292
  downloaded = 0