nia-mcp-server 1.0.25__py3-none-any.whl → 1.0.42__py3-none-any.whl

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.

Potentially problematic release.


This version of nia-mcp-server might be problematic. Click here for more details.

nia_mcp_server/setup.py CHANGED
@@ -5,49 +5,210 @@ import os
5
5
  import json
6
6
  import platform
7
7
  import shutil
8
+ import subprocess
8
9
  from pathlib import Path
9
- from typing import Dict, Optional, Any
10
+ from typing import Dict, Optional, Any, List
10
11
 
12
+ # Remote MCP endpoint
13
+ REMOTE_MCP_URL = "https://apigcp.trynia.ai/mcp"
14
+ NIA_API_URL = "https://apigcp.trynia.ai/"
11
15
 
12
- def find_mcp_config_path(ide: str = "cursor") -> Path:
16
+ # All supported IDEs
17
+ SUPPORTED_IDES = [
18
+ "cursor", "claude-code", "claude-desktop", "vscode", "windsurf", "continue",
19
+ "cline", "codex", "antigravity", "trae", "amp", "zed", "augment", "roo-code",
20
+ "kilo-code", "gemini-cli", "opencode", "jetbrains", "kiro", "lm-studio",
21
+ "visual-studio", "crush", "bolt-ai", "rovo-dev", "zencoder", "qodo-gen",
22
+ "qwen-coder", "perplexity", "warp", "copilot-agent", "copilot-cli",
23
+ "amazon-q", "factory"
24
+ ]
25
+
26
+ # IDEs that support remote mode
27
+ REMOTE_SUPPORTED_IDES = [
28
+ "cursor", "vscode", "windsurf", "cline", "antigravity", "trae", "continue",
29
+ "roo-code", "kilo-code", "gemini-cli", "opencode", "qodo-gen", "qwen-coder",
30
+ "visual-studio", "crush", "copilot-agent", "copilot-cli", "factory",
31
+ "rovo-dev", "claude-code", "amp"
32
+ ]
33
+
34
+ # IDEs that require CLI-based setup
35
+ CLI_BASED_IDES = ["claude-code", "codex", "amp", "factory"]
36
+
37
+
38
+ def find_mcp_config_path(ide: str = "cursor") -> Optional[Path]:
13
39
  """
14
40
  Find the MCP configuration file path based on OS and IDE.
15
-
41
+
16
42
  Args:
17
- ide: IDE to configure (cursor, vscode, continue)
18
-
43
+ ide: IDE to configure
44
+
19
45
  Returns:
20
- Path to the MCP configuration file
46
+ Path to the MCP configuration file, or None for CLI-based IDEs
21
47
  """
22
48
  system = platform.system()
23
49
  home = Path.home()
24
-
25
- if ide == "cursor":
26
- if system == "Darwin": # macOS
27
- return home / ".cursor" / "mcp.json"
28
- elif system == "Windows":
29
- appdata = os.environ.get("APPDATA", home / "AppData" / "Roaming")
30
- return Path(appdata) / "Cursor" / "mcp.json"
31
- else: # Linux and others
32
- return home / ".config" / "cursor" / "mcp.json"
33
-
34
- elif ide == "vscode":
35
- # VS Code uses different config locations
36
- if system == "Darwin":
37
- return home / "Library" / "Application Support" / "Code" / "User" / "mcp.json"
38
- elif system == "Windows":
39
- appdata = os.environ.get("APPDATA", home / "AppData" / "Roaming")
40
- return Path(appdata) / "Code" / "User" / "mcp.json"
41
- else:
42
- return home / ".config" / "Code" / "User" / "mcp.json"
43
-
44
- elif ide == "continue":
45
- # Continue.dev uses .continue directory
46
- return home / ".continue" / "config.json"
47
-
48
- else:
50
+
51
+ # CLI-based IDEs don't have a config file path
52
+ if ide in CLI_BASED_IDES:
53
+ return None
54
+
55
+ config_paths = {
56
+ # Standard MCP config IDEs
57
+ "cursor": {
58
+ "Darwin": home / ".cursor" / "mcp.json",
59
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "Cursor" / "mcp.json",
60
+ "Linux": home / ".config" / "cursor" / "mcp.json",
61
+ },
62
+ "vscode": {
63
+ "Darwin": home / ".vscode" / "mcp.json",
64
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "Code" / "User" / "mcp.json",
65
+ "Linux": home / ".config" / "Code" / "User" / "mcp.json",
66
+ },
67
+ "windsurf": {
68
+ "Darwin": home / ".codeium" / "windsurf" / "mcp_config.json",
69
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "Windsurf" / "mcp_config.json",
70
+ "Linux": home / ".codeium" / "windsurf" / "mcp_config.json",
71
+ },
72
+ "continue": {
73
+ "Darwin": home / ".continue" / "config.json",
74
+ "Windows": home / ".continue" / "config.json",
75
+ "Linux": home / ".continue" / "config.json",
76
+ },
77
+ "cline": {
78
+ "Darwin": home / "Library" / "Application Support" / "Code" / "User" / "globalStorage" / "saoudrizwan.claude-dev" / "settings" / "cline_mcp_settings.json",
79
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "Code" / "User" / "globalStorage" / "saoudrizwan.claude-dev" / "settings" / "cline_mcp_settings.json",
80
+ "Linux": home / ".config" / "Code" / "User" / "globalStorage" / "saoudrizwan.claude-dev" / "settings" / "cline_mcp_settings.json",
81
+ },
82
+ "antigravity": {
83
+ "Darwin": home / ".gemini" / "antigravity" / "mcp_config.json",
84
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "Gemini" / "Antigravity" / "mcp_config.json",
85
+ "Linux": home / ".config" / "gemini" / "antigravity" / "mcp_config.json",
86
+ },
87
+ "trae": {
88
+ "Darwin": home / "Library" / "Application Support" / "Trae" / "User" / "mcp.json",
89
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "Trae" / "User" / "mcp.json",
90
+ "Linux": home / ".config" / "trae" / "mcp.json",
91
+ },
92
+ "gemini-cli": {
93
+ "Darwin": home / ".gemini" / "settings.json",
94
+ "Windows": home / ".gemini" / "settings.json",
95
+ "Linux": home / ".gemini" / "settings.json",
96
+ },
97
+ "qwen-coder": {
98
+ "Darwin": home / ".qwen" / "settings.json",
99
+ "Windows": home / ".qwen" / "settings.json",
100
+ "Linux": home / ".qwen" / "settings.json",
101
+ },
102
+ "claude-desktop": {
103
+ "Darwin": home / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json",
104
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "Claude" / "claude_desktop_config.json",
105
+ "Linux": home / ".config" / "claude" / "claude_desktop_config.json",
106
+ },
107
+ "zed": {
108
+ "Darwin": home / ".config" / "zed" / "settings.json",
109
+ "Windows": home / ".config" / "zed" / "settings.json",
110
+ "Linux": home / ".config" / "zed" / "settings.json",
111
+ },
112
+ "roo-code": {
113
+ "Darwin": home / ".roo-code" / "mcp.json",
114
+ "Windows": home / ".roo-code" / "mcp.json",
115
+ "Linux": home / ".roo-code" / "mcp.json",
116
+ },
117
+ "kilo-code": {
118
+ "Darwin": home / ".kilocode" / "mcp.json",
119
+ "Windows": home / ".kilocode" / "mcp.json",
120
+ "Linux": home / ".kilocode" / "mcp.json",
121
+ },
122
+ "opencode": {
123
+ "Darwin": home / ".opencode" / "config.json",
124
+ "Windows": home / ".opencode" / "config.json",
125
+ "Linux": home / ".opencode" / "config.json",
126
+ },
127
+ "jetbrains": {
128
+ "Darwin": home / ".jetbrains" / "mcp.json",
129
+ "Windows": home / ".jetbrains" / "mcp.json",
130
+ "Linux": home / ".jetbrains" / "mcp.json",
131
+ },
132
+ "kiro": {
133
+ "Darwin": home / ".kiro" / "mcp.json",
134
+ "Windows": home / ".kiro" / "mcp.json",
135
+ "Linux": home / ".kiro" / "mcp.json",
136
+ },
137
+ "lm-studio": {
138
+ "Darwin": home / ".lmstudio" / "mcp.json",
139
+ "Windows": home / ".lmstudio" / "mcp.json",
140
+ "Linux": home / ".lmstudio" / "mcp.json",
141
+ },
142
+ "visual-studio": {
143
+ "Darwin": home / ".vs" / "mcp.json",
144
+ "Windows": home / ".vs" / "mcp.json",
145
+ "Linux": home / ".vs" / "mcp.json",
146
+ },
147
+ "crush": {
148
+ "Darwin": home / ".crush" / "config.json",
149
+ "Windows": home / ".crush" / "config.json",
150
+ "Linux": home / ".crush" / "config.json",
151
+ },
152
+ "bolt-ai": {
153
+ "Darwin": home / "Library" / "Application Support" / "BoltAI" / "mcp.json",
154
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "BoltAI" / "mcp.json",
155
+ "Linux": home / ".config" / "bolt-ai" / "mcp.json",
156
+ },
157
+ "augment": {
158
+ "Darwin": home / ".augment" / "settings.json",
159
+ "Windows": home / ".augment" / "settings.json",
160
+ "Linux": home / ".augment" / "settings.json",
161
+ },
162
+ "qodo-gen": {
163
+ "Darwin": home / ".qodo" / "mcp.json",
164
+ "Windows": home / ".qodo" / "mcp.json",
165
+ "Linux": home / ".qodo" / "mcp.json",
166
+ },
167
+ "perplexity": {
168
+ "Darwin": home / "Library" / "Application Support" / "Perplexity" / "mcp.json",
169
+ "Windows": Path(os.environ.get("APPDATA", home / "AppData" / "Roaming")) / "Perplexity" / "mcp.json",
170
+ "Linux": home / ".config" / "perplexity" / "mcp.json",
171
+ },
172
+ "warp": {
173
+ "Darwin": home / ".warp" / "mcp.json",
174
+ "Windows": home / ".warp" / "mcp.json",
175
+ "Linux": home / ".warp" / "mcp.json",
176
+ },
177
+ "copilot-cli": {
178
+ "Darwin": home / ".copilot" / "mcp-config.json",
179
+ "Windows": home / ".copilot" / "mcp-config.json",
180
+ "Linux": home / ".copilot" / "mcp-config.json",
181
+ },
182
+ "copilot-agent": {
183
+ # This is typically in the repo, not home
184
+ "Darwin": Path(".github") / "copilot-mcp.json",
185
+ "Windows": Path(".github") / "copilot-mcp.json",
186
+ "Linux": Path(".github") / "copilot-mcp.json",
187
+ },
188
+ "amazon-q": {
189
+ "Darwin": home / ".aws" / "amazonq" / "mcp.json",
190
+ "Windows": home / ".aws" / "amazonq" / "mcp.json",
191
+ "Linux": home / ".aws" / "amazonq" / "mcp.json",
192
+ },
193
+ "rovo-dev": {
194
+ "Darwin": home / ".rovo" / "mcp.json",
195
+ "Windows": home / ".rovo" / "mcp.json",
196
+ "Linux": home / ".rovo" / "mcp.json",
197
+ },
198
+ "zencoder": {
199
+ # Zencoder uses UI-based setup
200
+ "Darwin": None,
201
+ "Windows": None,
202
+ "Linux": None,
203
+ },
204
+ }
205
+
206
+ if ide not in config_paths:
49
207
  raise ValueError(f"Unsupported IDE: {ide}")
50
208
 
209
+ ide_paths = config_paths[ide]
210
+ return ide_paths.get(system, ide_paths.get("Linux"))
211
+
51
212
 
52
213
  def backup_config(config_path: Path) -> Optional[Path]:
53
214
  """
@@ -59,7 +220,7 @@ def backup_config(config_path: Path) -> Optional[Path]:
59
220
  Returns:
60
221
  Path to the backup file if created, None otherwise
61
222
  """
62
- if config_path.exists():
223
+ if config_path and config_path.exists():
63
224
  backup_path = config_path.with_suffix(".json.backup")
64
225
  # If backup already exists, add timestamp
65
226
  if backup_path.exists():
@@ -72,106 +233,459 @@ def backup_config(config_path: Path) -> Optional[Path]:
72
233
  return None
73
234
 
74
235
 
75
- def create_nia_config(api_key: str) -> Dict[str, Any]:
236
+ def create_local_nia_config(api_key: str, ide: str = "cursor") -> Dict[str, Any]:
76
237
  """
77
- Create NIA MCP server configuration.
78
-
238
+ Create local NIA MCP server configuration.
239
+
79
240
  Args:
80
241
  api_key: NIA API key
81
-
242
+ ide: IDE to configure (affects config format)
243
+
82
244
  Returns:
83
- Dictionary with NIA server configuration
245
+ Dictionary with local NIA server configuration
84
246
  """
85
- return {
247
+ base_local = {
86
248
  "command": "pipx",
87
- "args": ["run", "nia-mcp-server"],
249
+ "args": ["run", "--no-cache", "nia-mcp-server"],
88
250
  "env": {
89
251
  "NIA_API_KEY": api_key,
90
- "NIA_API_URL": "https://apigcp.trynia.ai/"
252
+ "NIA_API_URL": NIA_API_URL
91
253
  }
92
254
  }
93
255
 
256
+ # IDE-specific variations
257
+ if ide == "cline":
258
+ return {
259
+ **base_local,
260
+ "alwaysAllow": [
261
+ "index", "search", "manage_resource", "regex_search",
262
+ "get_github_file_tree", "nia_web_search", "nia_deep_research_agent",
263
+ "read_source_content", "doc_tree", "doc_ls", "doc_read", "doc_grep", "context"
264
+ ],
265
+ "disabled": False
266
+ }
267
+ elif ide in ["vscode", "visual-studio"]:
268
+ return {
269
+ "type": "stdio",
270
+ **base_local
271
+ }
272
+ elif ide == "opencode":
273
+ return {
274
+ "type": "local",
275
+ "command": ["pipx", "run", "--no-cache", "nia-mcp-server"],
276
+ "env": {
277
+ "NIA_API_KEY": api_key,
278
+ "NIA_API_URL": NIA_API_URL
279
+ },
280
+ "enabled": True
281
+ }
282
+ elif ide == "crush":
283
+ return {
284
+ "type": "stdio",
285
+ **base_local
286
+ }
287
+ elif ide in ["copilot-agent", "copilot-cli"]:
288
+ return {
289
+ "type": "stdio" if ide == "copilot-agent" else "local",
290
+ **base_local,
291
+ "tools": ["index", "search", "manage_resource", "nia_web_search", "nia_deep_research_agent"]
292
+ }
293
+ elif ide == "zed":
294
+ return {
295
+ "source": "custom",
296
+ "command": "pipx",
297
+ "args": ["run", "--no-cache", "nia-mcp-server"],
298
+ "env": {
299
+ "NIA_API_KEY": api_key,
300
+ "NIA_API_URL": NIA_API_URL
301
+ }
302
+ }
303
+ elif ide == "warp":
304
+ return {
305
+ **base_local,
306
+ "working_directory": None,
307
+ "start_on_launch": True
308
+ }
309
+ elif ide == "kilo-code":
310
+ return {
311
+ **base_local,
312
+ "alwaysAllow": [],
313
+ "disabled": False
314
+ }
315
+
316
+ return base_local
317
+
94
318
 
95
- def update_mcp_config(config_path: Path, api_key: str) -> bool:
319
+ def create_remote_nia_config(api_key: str, ide: str = "cursor") -> Dict[str, Any]:
96
320
  """
97
- Update or create MCP configuration file with NIA server.
321
+ Create remote NIA MCP server configuration (HTTP transport).
322
+
323
+ Args:
324
+ api_key: NIA API key
325
+ ide: IDE to configure (affects config format)
326
+
327
+ Returns:
328
+ Dictionary with remote NIA server configuration
329
+ """
330
+ base_remote = {
331
+ "url": REMOTE_MCP_URL,
332
+ "headers": {
333
+ "Authorization": f"Bearer {api_key}"
334
+ }
335
+ }
336
+
337
+ # IDE-specific variations
338
+ if ide == "windsurf":
339
+ return {
340
+ "serverUrl": REMOTE_MCP_URL,
341
+ "headers": {
342
+ "Authorization": f"Bearer {api_key}"
343
+ }
344
+ }
345
+ elif ide in ["vscode", "visual-studio"]:
346
+ return {
347
+ "type": "http",
348
+ "url": REMOTE_MCP_URL,
349
+ "headers": {
350
+ "Authorization": f"Bearer {api_key}"
351
+ }
352
+ }
353
+ elif ide == "cline":
354
+ return {
355
+ "url": REMOTE_MCP_URL,
356
+ "type": "streamableHttp",
357
+ "headers": {
358
+ "Authorization": f"Bearer {api_key}"
359
+ },
360
+ "alwaysAllow": [
361
+ "index", "search", "manage_resource", "regex_search",
362
+ "get_github_file_tree", "nia_web_search", "nia_deep_research_agent",
363
+ "read_source_content", "doc_tree", "doc_ls", "doc_read", "doc_grep", "context"
364
+ ],
365
+ "disabled": False
366
+ }
367
+ elif ide == "roo-code":
368
+ return {
369
+ "type": "streamable-http",
370
+ "url": REMOTE_MCP_URL,
371
+ "headers": {
372
+ "Authorization": f"Bearer {api_key}"
373
+ }
374
+ }
375
+ elif ide == "kilo-code":
376
+ return {
377
+ "type": "streamable-http",
378
+ "url": REMOTE_MCP_URL,
379
+ "headers": {
380
+ "Authorization": f"Bearer {api_key}"
381
+ },
382
+ "alwaysAllow": [],
383
+ "disabled": False
384
+ }
385
+ elif ide in ["gemini-cli", "qwen-coder"]:
386
+ return {
387
+ "httpUrl": REMOTE_MCP_URL,
388
+ "headers": {
389
+ "Authorization": f"Bearer {api_key}",
390
+ "Accept": "application/json, text/event-stream"
391
+ }
392
+ }
393
+ elif ide == "opencode":
394
+ return {
395
+ "type": "remote",
396
+ "url": REMOTE_MCP_URL,
397
+ "headers": {
398
+ "Authorization": f"Bearer {api_key}"
399
+ },
400
+ "enabled": True
401
+ }
402
+ elif ide == "crush":
403
+ return {
404
+ "type": "http",
405
+ "url": REMOTE_MCP_URL,
406
+ "headers": {
407
+ "Authorization": f"Bearer {api_key}"
408
+ }
409
+ }
410
+ elif ide in ["copilot-agent", "copilot-cli"]:
411
+ return {
412
+ "type": "http",
413
+ "url": REMOTE_MCP_URL,
414
+ "headers": {
415
+ "Authorization": f"Bearer {api_key}"
416
+ },
417
+ "tools": ["index", "search", "manage_resource", "nia_web_search", "nia_deep_research_agent"]
418
+ }
98
419
 
420
+ # Default for cursor, antigravity, trae, qodo-gen, etc.
421
+ return base_remote
422
+
423
+
424
+ def create_nia_config(api_key: str, ide: str = "cursor", remote: bool = False) -> Dict[str, Any]:
425
+ """
426
+ Create NIA MCP server configuration.
427
+
428
+ Args:
429
+ api_key: NIA API key
430
+ ide: IDE to configure (affects config format)
431
+ remote: If True, create remote HTTP config instead of local
432
+
433
+ Returns:
434
+ Dictionary with NIA server configuration
435
+ """
436
+ if remote:
437
+ return create_remote_nia_config(api_key, ide)
438
+ return create_local_nia_config(api_key, ide)
439
+
440
+
441
+ def update_mcp_config(config_path: Path, api_key: str, ide: str = "cursor", remote: bool = False) -> bool:
442
+ """
443
+ Update or create MCP configuration file with NIA server.
444
+
99
445
  Args:
100
446
  config_path: Path to the MCP configuration file
101
447
  api_key: NIA API key
102
-
448
+ ide: IDE to configure
449
+ remote: If True, use remote HTTP config
450
+
103
451
  Returns:
104
452
  True if successful, False otherwise
105
453
  """
106
454
  try:
107
455
  # Ensure directory exists
108
456
  config_path.parent.mkdir(parents=True, exist_ok=True)
109
-
457
+
110
458
  # Load existing config or create new one
111
459
  if config_path.exists():
112
- with open(config_path, 'r') as f:
113
- config = json.load(f)
460
+ try:
461
+ with open(config_path, 'r') as f:
462
+ content = f.read().strip()
463
+ config = json.loads(content) if content else {}
464
+ except (json.JSONDecodeError, ValueError):
465
+ config = {}
114
466
  else:
115
467
  config = {}
116
-
117
- # Ensure mcpServers section exists
118
- if "mcpServers" not in config:
119
- config["mcpServers"] = {}
120
-
121
- # Add or update NIA server configuration
122
- config["mcpServers"]["nia"] = create_nia_config(api_key)
123
-
468
+
469
+ nia_config = create_nia_config(api_key, ide, remote)
470
+
471
+ # Handle different config structures based on IDE
472
+ if ide == "continue":
473
+ if "experimental" not in config:
474
+ config["experimental"] = {}
475
+ if "modelContextProtocolServer" not in config["experimental"]:
476
+ config["experimental"]["modelContextProtocolServer"] = {}
477
+
478
+ if remote:
479
+ config["experimental"]["modelContextProtocolServer"]["transport"] = {
480
+ "type": "http",
481
+ "url": REMOTE_MCP_URL,
482
+ "headers": {
483
+ "Authorization": f"Bearer {api_key}"
484
+ }
485
+ }
486
+ else:
487
+ config["experimental"]["modelContextProtocolServer"]["transport"] = {
488
+ "type": "stdio",
489
+ "command": "pipx",
490
+ "args": ["run", "--no-cache", "nia-mcp-server"],
491
+ "env": {
492
+ "NIA_API_KEY": api_key,
493
+ "NIA_API_URL": NIA_API_URL
494
+ }
495
+ }
496
+ elif ide in ["vscode", "visual-studio"]:
497
+ if "servers" not in config:
498
+ config["servers"] = {}
499
+ config["servers"]["nia"] = nia_config
500
+ elif ide == "zed":
501
+ if "context_servers" not in config:
502
+ config["context_servers"] = {}
503
+ config["context_servers"]["Nia"] = nia_config
504
+ elif ide == "augment":
505
+ if "augment.advanced" not in config:
506
+ config["augment.advanced"] = {}
507
+ if "mcpServers" not in config["augment.advanced"]:
508
+ config["augment.advanced"]["mcpServers"] = []
509
+ # Remove existing nia config if present
510
+ config["augment.advanced"]["mcpServers"] = [
511
+ s for s in config["augment.advanced"]["mcpServers"]
512
+ if s.get("name") != "nia"
513
+ ]
514
+ config["augment.advanced"]["mcpServers"].append({
515
+ "name": "nia",
516
+ **nia_config
517
+ })
518
+ elif ide == "opencode":
519
+ if "mcp" not in config:
520
+ config["mcp"] = {}
521
+ config["mcp"]["nia"] = nia_config
522
+ elif ide == "crush":
523
+ if "$schema" not in config:
524
+ config["$schema"] = "https://charm.land/crush.json"
525
+ if "mcp" not in config:
526
+ config["mcp"] = {}
527
+ config["mcp"]["nia"] = nia_config
528
+ else:
529
+ # Standard mcpServers structure for cursor, windsurf, cline, etc.
530
+ if "mcpServers" not in config:
531
+ config["mcpServers"] = {}
532
+ config["mcpServers"]["nia"] = nia_config
533
+
124
534
  # Write updated configuration
125
535
  with open(config_path, 'w') as f:
126
536
  json.dump(config, f, indent=2)
127
-
537
+
128
538
  return True
129
-
539
+
130
540
  except Exception as e:
131
541
  print(f"❌ Error updating configuration: {e}")
132
542
  return False
133
543
 
134
544
 
135
- def setup_mcp_config(api_key: str, ide: str = "cursor") -> bool:
545
+ def setup_command_based_ide(api_key: str, ide: str, remote: bool = False) -> bool:
546
+ """
547
+ Setup NIA MCP Server for command-based IDEs (claude-code, codex, amp, factory).
548
+
549
+ Args:
550
+ api_key: NIA API key
551
+ ide: IDE to configure
552
+ remote: If True, use remote config
553
+
554
+ Returns:
555
+ True if successful, False otherwise
556
+ """
557
+ if ide == "claude-code":
558
+ if remote:
559
+ cmd = [
560
+ "claude", "mcp", "add", "--transport", "http", "nia",
561
+ REMOTE_MCP_URL,
562
+ "--header", f"Authorization: Bearer {api_key}"
563
+ ]
564
+ else:
565
+ cmd = [
566
+ "claude", "mcp", "add", "nia", "--scope", "user",
567
+ "-e", f"NIA_API_KEY={api_key}",
568
+ "-e", f"NIA_API_URL={NIA_API_URL}",
569
+ "--", "pipx", "run", "--no-cache", "nia-mcp-server"
570
+ ]
571
+ ide_name = "Claude Code"
572
+ elif ide == "codex":
573
+ if remote:
574
+ print("❌ Codex does not support remote MCP. Please use local mode.")
575
+ return False
576
+ cmd = [
577
+ "codex", "mcp", "add", "nia",
578
+ "--env", f"NIA_API_KEY={api_key}",
579
+ "--env", f"NIA_API_URL={NIA_API_URL}",
580
+ "--", "pipx", "run", "--no-cache", "nia-mcp-server"
581
+ ]
582
+ ide_name = "Codex"
583
+ elif ide == "amp":
584
+ if remote:
585
+ cmd = [
586
+ "amp", "mcp", "add", "nia",
587
+ "--header", f"Authorization=Bearer {api_key}",
588
+ REMOTE_MCP_URL
589
+ ]
590
+ else:
591
+ print("❌ Amp only supports remote MCP. Please use --remote flag.")
592
+ return False
593
+ ide_name = "Amp"
594
+ elif ide == "factory":
595
+ if remote:
596
+ cmd = [
597
+ "droid", "mcp", "add", "nia",
598
+ REMOTE_MCP_URL,
599
+ "--type", "http",
600
+ "--header", f"Authorization: Bearer {api_key}"
601
+ ]
602
+ else:
603
+ cmd = [
604
+ "droid", "mcp", "add", "nia",
605
+ "pipx run --no-cache nia-mcp-server",
606
+ "--env", f"NIA_API_KEY={api_key}",
607
+ "--env", f"NIA_API_URL={NIA_API_URL}"
608
+ ]
609
+ ide_name = "Factory"
610
+ else:
611
+ print(f"❌ Unsupported command-based IDE: {ide}")
612
+ return False
613
+
614
+ try:
615
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
616
+ print(f"\n✅ Setup complete!")
617
+ return True
618
+
619
+ except subprocess.CalledProcessError as e:
620
+ print(f"\n❌ Setup failed with error: {e}")
621
+ if e.stderr:
622
+ print(f"Error details: {e.stderr}")
623
+ return False
624
+ except FileNotFoundError:
625
+ print(f"\n❌ {ide_name} CLI not found. Please ensure {ide_name} is installed and in your PATH.")
626
+ return False
627
+
628
+
629
+ def setup_mcp_config(api_key: str, ide: str = "cursor", remote: bool = False) -> bool:
136
630
  """
137
631
  Main setup function to configure NIA MCP Server.
138
-
632
+
139
633
  Args:
140
634
  api_key: NIA API key
141
635
  ide: IDE to configure
142
-
636
+ remote: If True, use remote HTTP config (no local installation needed)
637
+
143
638
  Returns:
144
639
  True if successful, False otherwise
145
640
  """
146
- print(f"\n🚀 Setting up NIA MCP Server for {ide.title()}...\n")
147
-
148
- # Find config path
641
+ # Check remote support
642
+ if remote and ide not in REMOTE_SUPPORTED_IDES:
643
+ print(f"⚠️ {ide} does not support remote MCP mode.")
644
+ print(f" Falling back to local installation...")
645
+ remote = False
646
+
647
+ # Handle command-based IDEs differently
648
+ if ide in CLI_BASED_IDES:
649
+ return setup_command_based_ide(api_key, ide, remote)
650
+
651
+ # Handle IDEs that require manual UI setup
652
+ if ide == "zencoder":
653
+ print(f"\n📋 Zencoder requires manual setup via UI:")
654
+ print(" 1. Go to: Zencoder menu (…) → Agent tools → Add custom MCP")
655
+ print(" 2. Add this configuration:")
656
+ print(json.dumps({
657
+ "command": "pipx",
658
+ "args": ["run", "--no-cache", "nia-mcp-server"],
659
+ "env": {
660
+ "NIA_API_KEY": api_key,
661
+ "NIA_API_URL": NIA_API_URL
662
+ }
663
+ }, indent=2))
664
+ return True
665
+
666
+ # For file-based configuration IDEs
149
667
  config_path = find_mcp_config_path(ide)
150
- print(f"📍 Configuration path: {config_path}")
151
668
 
669
+ if config_path is None:
670
+ print(f"❌ Could not determine config path for {ide}")
671
+ return False
672
+
152
673
  # Backup existing config
153
674
  backup_path = backup_config(config_path)
154
675
  if backup_path:
155
676
  print(f"📦 Backed up existing config to: {backup_path}")
156
-
677
+
157
678
  # Update configuration
158
- if update_mcp_config(config_path, api_key):
159
- print(f"\n✅ NIA MCP Server setup complete!")
160
- print(f"\n📝 Configuration written to: {config_path}")
161
- print(f"🔑 API Key: {api_key[:10]}...")
162
-
163
- print("\n📌 Next steps:")
164
- print(f" 1. Restart {ide.title()} to load the NIA MCP server")
165
- print(f" 2. Test with: \"Claude, list my repositories\"")
166
- print(f" 3. Get started: \"Claude, index https://github.com/owner/repo\"")
167
-
168
- print("\n💡 Learn more:")
169
- print(" - Documentation: https://docs.trynia.ai")
170
- print(" - Get help: https://discord.gg/BBSwUMrrfn")
171
-
679
+ if update_mcp_config(config_path, api_key, ide, remote):
680
+ mode_str = "Remote MCP" if remote else "Local MCP"
681
+ print(f"\n {mode_str} setup complete!")
682
+ print(f"📝 Configuration written to: {config_path}")
683
+ if remote:
684
+ print(f"🌐 Connected to: {REMOTE_MCP_URL}")
685
+ print(f"\n💡 No local installation required - your IDE connects directly to NIA's servers.")
172
686
  return True
173
687
  else:
174
688
  print(f"\n❌ Setup failed. Please check the error messages above.")
175
689
  if backup_path:
176
690
  print(f" Your original config is safe at: {backup_path}")
177
- return False
691
+ return False