nia-mcp-server 1.0.25__tar.gz → 1.0.26__tar.gz
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-1.0.25 → nia_mcp_server-1.0.26}/PKG-INFO +1 -1
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/pyproject.toml +1 -1
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/__init__.py +1 -1
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/api_client.py +75 -2
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/server.py +202 -417
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/.gitignore +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/ARCHITECTURE.md +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/LICENSE +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/README.md +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/nia_analytics.log +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/nia_mcp_server.log +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/__main__.py +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/claude_rules.md +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/cursor_rules.md +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/nia_rules.md +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/vscode_rules.md +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/windsurf_rules.md +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/cli.py +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/profiles.py +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/project_init.py +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/rule_transformer.py +0 -0
- {nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/setup.py +0 -0
|
@@ -28,7 +28,7 @@ class NIAApiClient:
|
|
|
28
28
|
self.client = httpx.AsyncClient(
|
|
29
29
|
headers={
|
|
30
30
|
"Authorization": f"Bearer {api_key}",
|
|
31
|
-
"User-Agent": "nia-mcp-server/1.0.
|
|
31
|
+
"User-Agent": "nia-mcp-server/1.0.26",
|
|
32
32
|
"Content-Type": "application/json"
|
|
33
33
|
},
|
|
34
34
|
timeout=720.0 # 12 minute timeout for deep research operations
|
|
@@ -432,7 +432,80 @@ class NIAApiClient:
|
|
|
432
432
|
except Exception as e:
|
|
433
433
|
logger.error(f"Failed to rename repository: {e}")
|
|
434
434
|
raise APIError(f"Failed to rename repository: {str(e)}")
|
|
435
|
-
|
|
435
|
+
|
|
436
|
+
async def get_repository_hierarchy(
|
|
437
|
+
self,
|
|
438
|
+
owner_repo: str,
|
|
439
|
+
include_classes: bool = True,
|
|
440
|
+
include_methods: bool = False,
|
|
441
|
+
include_tree: bool = False
|
|
442
|
+
) -> Dict[str, Any]:
|
|
443
|
+
"""Get the file hierarchy for a repository."""
|
|
444
|
+
try:
|
|
445
|
+
# Check if this looks like owner/repo format (contains /)
|
|
446
|
+
if '/' in owner_repo:
|
|
447
|
+
# First, get the repository ID
|
|
448
|
+
status = await self.get_repository_status(owner_repo)
|
|
449
|
+
if not status:
|
|
450
|
+
raise APIError(f"Repository {owner_repo} not found", 404)
|
|
451
|
+
|
|
452
|
+
# Extract the repository ID from status
|
|
453
|
+
repo_id = status.get("repository_id") or status.get("id")
|
|
454
|
+
if not repo_id:
|
|
455
|
+
# Try to get it from list as fallback
|
|
456
|
+
repos = await self.list_repositories()
|
|
457
|
+
for repo in repos:
|
|
458
|
+
if repo.get("repository") == owner_repo:
|
|
459
|
+
repo_id = repo.get("repository_id") or repo.get("id")
|
|
460
|
+
break
|
|
461
|
+
|
|
462
|
+
if not repo_id:
|
|
463
|
+
raise APIError(f"No repository ID found for {owner_repo}", 404)
|
|
464
|
+
|
|
465
|
+
# Get hierarchy using the ID
|
|
466
|
+
params = {
|
|
467
|
+
"include_classes": include_classes,
|
|
468
|
+
"include_methods": include_methods
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
headers = {}
|
|
472
|
+
if include_tree:
|
|
473
|
+
headers["X-Include-Tree"] = "true"
|
|
474
|
+
|
|
475
|
+
response = await self.client.get(
|
|
476
|
+
f"{self.base_url}/v2/repositories/{repo_id}/hierarchy",
|
|
477
|
+
params=params,
|
|
478
|
+
headers=headers
|
|
479
|
+
)
|
|
480
|
+
response.raise_for_status()
|
|
481
|
+
return response.json()
|
|
482
|
+
else:
|
|
483
|
+
# Assume it's already a repository ID
|
|
484
|
+
params = {
|
|
485
|
+
"include_classes": include_classes,
|
|
486
|
+
"include_methods": include_methods
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
headers = {}
|
|
490
|
+
if include_tree:
|
|
491
|
+
headers["X-Include-Tree"] = "true"
|
|
492
|
+
|
|
493
|
+
response = await self.client.get(
|
|
494
|
+
f"{self.base_url}/v2/repositories/{owner_repo}/hierarchy",
|
|
495
|
+
params=params,
|
|
496
|
+
headers=headers
|
|
497
|
+
)
|
|
498
|
+
response.raise_for_status()
|
|
499
|
+
return response.json()
|
|
500
|
+
|
|
501
|
+
except httpx.HTTPStatusError as e:
|
|
502
|
+
raise self._handle_api_error(e)
|
|
503
|
+
except APIError:
|
|
504
|
+
raise
|
|
505
|
+
except Exception as e:
|
|
506
|
+
logger.error(f"Failed to get repository hierarchy: {e}")
|
|
507
|
+
raise APIError(f"Failed to get repository hierarchy: {str(e)}")
|
|
508
|
+
|
|
436
509
|
# Data Source methods
|
|
437
510
|
|
|
438
511
|
async def create_data_source(
|
|
@@ -80,15 +80,10 @@ async def index_repository(
|
|
|
80
80
|
branch: Optional[str] = None
|
|
81
81
|
) -> List[TextContent]:
|
|
82
82
|
"""
|
|
83
|
-
Index a GitHub repository for intelligent code search.
|
|
84
|
-
|
|
85
83
|
Args:
|
|
86
84
|
repo_url: GitHub repository URL (e.g., https://github.com/owner/repo or https://github.com/owner/repo/tree/branch)
|
|
87
85
|
branch: Branch to index (optional, defaults to main branch)
|
|
88
|
-
|
|
89
|
-
Returns:
|
|
90
|
-
Status of the indexing operation
|
|
91
|
-
|
|
86
|
+
|
|
92
87
|
Important:
|
|
93
88
|
- When started indexing, prompt users to either use check_repository_status tool or go to app.trynia.ai to check the status.
|
|
94
89
|
"""
|
|
@@ -157,31 +152,12 @@ async def search_codebase(
|
|
|
157
152
|
Search indexed repositories using natural language.
|
|
158
153
|
|
|
159
154
|
Args:
|
|
160
|
-
query: Natural language search query.
|
|
161
|
-
repositories: List of repositories to search (owner/repo or owner/repo/tree/branch
|
|
162
|
-
|
|
163
|
-
- "owner/repo/tree/branch/folder" - Search specific folder indexed separately
|
|
164
|
-
(e.g., "PostHog/posthog/tree/master/docs")
|
|
165
|
-
Use the EXACT format shown in list_repositories output for folder-indexed repos.
|
|
166
|
-
If not specified, searches all indexed repos.
|
|
167
|
-
include_sources: Whether to include source code in results
|
|
155
|
+
query: Natural language search query.
|
|
156
|
+
repositories: List of repositories to search (owner/repo or owner/repo/tree/branch).
|
|
157
|
+
include_sources: default to True.
|
|
168
158
|
|
|
169
159
|
Returns:
|
|
170
160
|
Search results with relevant code snippets and explanations
|
|
171
|
-
|
|
172
|
-
Examples:
|
|
173
|
-
# Search all indexed repositories
|
|
174
|
-
search_codebase("How does authentication work?")
|
|
175
|
-
|
|
176
|
-
# Search specific repository
|
|
177
|
-
search_codebase("How to create custom hooks?", ["facebook/react"])
|
|
178
|
-
|
|
179
|
-
# Search folder-indexed repository (use exact format from list_repositories)
|
|
180
|
-
search_codebase("What is Flox?", ["PostHog/posthog/tree/master/docs"])
|
|
181
|
-
|
|
182
|
-
Important:
|
|
183
|
-
- If you want to search a specific folder, use the EXACT repository path shown above
|
|
184
|
-
- Example: `search_codebase(\"query\", [\"owner/repo/tree/branch/folder\"])`
|
|
185
161
|
"""
|
|
186
162
|
try:
|
|
187
163
|
client = await ensure_api_client()
|
|
@@ -336,18 +312,11 @@ async def search_documentation(
|
|
|
336
312
|
Args:
|
|
337
313
|
query: Natural language search query. Don't just use keywords or unstrctured query, make a comprehensive question to get the best results possible.
|
|
338
314
|
sources: List of documentation identifiers to search. Preferred format is UUID, but also supports:
|
|
339
|
-
- Source UUIDs
|
|
340
|
-
- Display names
|
|
341
|
-
- URLs
|
|
342
|
-
include_sources: Whether to include source references in results
|
|
343
|
-
|
|
344
|
-
Returns:
|
|
345
|
-
Search results with relevant documentation excerpts
|
|
346
|
-
|
|
315
|
+
- Source UUIDs - RECOMMENDED
|
|
316
|
+
- Display names
|
|
317
|
+
- URLs
|
|
347
318
|
Important:
|
|
348
319
|
- UUIDs are the preferred identifier format for best performance
|
|
349
|
-
- Use `list_documentation` tool to see available sources and their UUIDs
|
|
350
|
-
- Display names and URLs are also supported for convenience
|
|
351
320
|
"""
|
|
352
321
|
try:
|
|
353
322
|
client = await ensure_api_client()
|
|
@@ -474,9 +443,7 @@ async def search_documentation(
|
|
|
474
443
|
|
|
475
444
|
# @mcp.tool()
|
|
476
445
|
# async def list_repositories() -> List[TextContent]:
|
|
477
|
-
"""
|
|
478
|
-
List all indexed repositories.
|
|
479
|
-
|
|
446
|
+
"""
|
|
480
447
|
Returns:
|
|
481
448
|
List of indexed repositories with their status
|
|
482
449
|
"""
|
|
@@ -563,9 +530,6 @@ async def search_documentation(
|
|
|
563
530
|
|
|
564
531
|
Args:
|
|
565
532
|
repository: Repository in owner/repo format
|
|
566
|
-
|
|
567
|
-
Returns:
|
|
568
|
-
Current status of the repository
|
|
569
533
|
"""
|
|
570
534
|
try:
|
|
571
535
|
client = await ensure_api_client()
|
|
@@ -636,25 +600,8 @@ async def index_documentation(
|
|
|
636
600
|
|
|
637
601
|
Args:
|
|
638
602
|
url: URL of the documentation site to index
|
|
639
|
-
url_patterns: Optional list of URL patterns to include in crawling
|
|
640
|
-
exclude_patterns: Optional list of URL patterns to exclude from crawling
|
|
641
|
-
max_age: Maximum age of cached content in seconds (for fast scraping mode)
|
|
642
|
-
only_main_content: Extract only main content (removes navigation, ads, etc.)
|
|
643
|
-
wait_for: Time to wait for page to load in milliseconds (defaults to backend setting)
|
|
644
|
-
include_screenshot: Whether to capture full page screenshots (defaults to backend setting)
|
|
645
|
-
check_llms_txt: Check for llms.txt file for curated documentation URLs (default: True)
|
|
646
|
-
llms_txt_strategy: How to use llms.txt if found:
|
|
647
|
-
- "prefer": Start with llms.txt URLs, then crawl additional pages if under limit
|
|
648
|
-
- "only": Only index URLs listed in llms.txt
|
|
649
|
-
- "ignore": Skip llms.txt check (traditional behavior)
|
|
650
|
-
|
|
651
|
-
Returns:
|
|
652
|
-
Status of the indexing operation
|
|
653
|
-
|
|
654
|
-
Important:
|
|
655
|
-
- When started indexing, prompt users to either use check_documentation_status tool or go to app.trynia.ai to check the status.
|
|
656
|
-
- By default, crawls the entire domain (up to 10,000 pages)
|
|
657
|
-
- Use exclude_patterns to filter out unwanted sections like blogs, changelogs, etc.
|
|
603
|
+
url_patterns: Optional list of URL patterns to include in crawling
|
|
604
|
+
exclude_patterns: Optional list of URL patterns to exclude from crawling
|
|
658
605
|
"""
|
|
659
606
|
try:
|
|
660
607
|
client = await ensure_api_client()
|
|
@@ -708,8 +655,6 @@ async def index_documentation(
|
|
|
708
655
|
# @mcp.tool()
|
|
709
656
|
# async def list_documentation() -> List[TextContent]:
|
|
710
657
|
"""
|
|
711
|
-
List all indexed documentation sources.
|
|
712
|
-
|
|
713
658
|
Returns:
|
|
714
659
|
List of indexed documentation with their status
|
|
715
660
|
"""
|
|
@@ -767,8 +712,6 @@ async def index_documentation(
|
|
|
767
712
|
# @mcp.tool()
|
|
768
713
|
# async def check_documentation_status(source_id: str) -> List[TextContent]:
|
|
769
714
|
"""
|
|
770
|
-
Check the indexing status of a documentation source.
|
|
771
|
-
|
|
772
715
|
Args:
|
|
773
716
|
source_id: Documentation source ID
|
|
774
717
|
|
|
@@ -844,17 +787,8 @@ async def rename_resource(
|
|
|
844
787
|
Args:
|
|
845
788
|
resource_type: Type of resource - "repository" or "documentation"
|
|
846
789
|
identifier:
|
|
847
|
-
- For
|
|
848
|
-
- For
|
|
849
|
-
new_name: New display name for the resource (1-100 characters)
|
|
850
|
-
|
|
851
|
-
Returns:
|
|
852
|
-
Confirmation of rename operation
|
|
853
|
-
|
|
854
|
-
Examples:
|
|
855
|
-
- rename_resource("repository", "facebook/react", "React Framework")
|
|
856
|
-
- rename_resource("documentation", "550e8400-e29b-41d4-a716-446655440000", "Python Official Docs")
|
|
857
|
-
- rename_resource("documentation", "https://docs.trynia.ai/", "NIA Documentation")
|
|
790
|
+
- For repos: Repository in owner/repo format (e.g., "facebook/react")
|
|
791
|
+
- For docs: UUID preferred, also supports display name or URL
|
|
858
792
|
"""
|
|
859
793
|
try:
|
|
860
794
|
# Validate resource type
|
|
@@ -915,16 +849,8 @@ async def delete_resource(
|
|
|
915
849
|
Args:
|
|
916
850
|
resource_type: Type of resource - "repository" or "documentation"
|
|
917
851
|
identifier:
|
|
918
|
-
- For
|
|
919
|
-
- For
|
|
920
|
-
|
|
921
|
-
Returns:
|
|
922
|
-
Confirmation of deletion
|
|
923
|
-
|
|
924
|
-
Examples:
|
|
925
|
-
- delete_resource("repository", "facebook/react")
|
|
926
|
-
- delete_resource("documentation", "550e8400-e29b-41d4-a716-446655440000")
|
|
927
|
-
- delete_resource("documentation", "https://docs.trynia.ai/")
|
|
852
|
+
- For repos: Repository in owner/repo format (e.g., "facebook/react")
|
|
853
|
+
- For docs: UUID preferred, also supports display name or URL
|
|
928
854
|
"""
|
|
929
855
|
try:
|
|
930
856
|
# Validate resource type
|
|
@@ -978,19 +904,8 @@ async def check_resource_status(
|
|
|
978
904
|
Args:
|
|
979
905
|
resource_type: Type of resource - "repository" or "documentation"
|
|
980
906
|
identifier:
|
|
981
|
-
- For
|
|
982
|
-
- For
|
|
983
|
-
|
|
984
|
-
Returns:
|
|
985
|
-
Current status of the resource
|
|
986
|
-
|
|
987
|
-
Examples:
|
|
988
|
-
- check_resource_status("repository", "facebook/react")
|
|
989
|
-
- check_resource_status("documentation", "550e8400-e29b-41d4-a716-446655440000")
|
|
990
|
-
|
|
991
|
-
Note:
|
|
992
|
-
- Documentation status checking requires UUID identifiers only
|
|
993
|
-
- Use list_resources("documentation") to find the UUID for a documentation source
|
|
907
|
+
- For repos: Repository in owner/repo format
|
|
908
|
+
- For docs: Source ID (UUID format only)
|
|
994
909
|
"""
|
|
995
910
|
try:
|
|
996
911
|
# Validate resource type
|
|
@@ -1093,11 +1008,6 @@ async def list_resources(
|
|
|
1093
1008
|
|
|
1094
1009
|
Returns:
|
|
1095
1010
|
List of indexed resources with their status
|
|
1096
|
-
|
|
1097
|
-
Examples:
|
|
1098
|
-
- list_resources() - List all resources
|
|
1099
|
-
- list_resources("repository") - List only repositories
|
|
1100
|
-
- list_resources("documentation") - List only documentation
|
|
1101
1011
|
"""
|
|
1102
1012
|
try:
|
|
1103
1013
|
# Validate resource type if provided
|
|
@@ -1219,9 +1129,6 @@ async def list_resources(
|
|
|
1219
1129
|
|
|
1220
1130
|
Args:
|
|
1221
1131
|
source_id: Documentation source ID to delete
|
|
1222
|
-
|
|
1223
|
-
Returns:
|
|
1224
|
-
Confirmation of deletion
|
|
1225
1132
|
"""
|
|
1226
1133
|
try:
|
|
1227
1134
|
client = await ensure_api_client()
|
|
@@ -1258,9 +1165,6 @@ async def list_resources(
|
|
|
1258
1165
|
|
|
1259
1166
|
Args:
|
|
1260
1167
|
repository: Repository in owner/repo format
|
|
1261
|
-
|
|
1262
|
-
Returns:
|
|
1263
|
-
Confirmation of deletion
|
|
1264
1168
|
"""
|
|
1265
1169
|
try:
|
|
1266
1170
|
client = await ensure_api_client()
|
|
@@ -1298,9 +1202,6 @@ async def list_resources(
|
|
|
1298
1202
|
Args:
|
|
1299
1203
|
repository: Repository in owner/repo format
|
|
1300
1204
|
new_name: New display name for the repository (1-100 characters)
|
|
1301
|
-
|
|
1302
|
-
Returns:
|
|
1303
|
-
Confirmation of rename operation
|
|
1304
1205
|
"""
|
|
1305
1206
|
try:
|
|
1306
1207
|
# Validate name length
|
|
@@ -1345,9 +1246,6 @@ async def list_resources(
|
|
|
1345
1246
|
Args:
|
|
1346
1247
|
source_id: Documentation source ID
|
|
1347
1248
|
new_name: New display name for the documentation (1-100 characters)
|
|
1348
|
-
|
|
1349
|
-
Returns:
|
|
1350
|
-
Confirmation of rename operation
|
|
1351
1249
|
"""
|
|
1352
1250
|
try:
|
|
1353
1251
|
# Validate name length
|
|
@@ -1393,30 +1291,14 @@ async def nia_web_search(
|
|
|
1393
1291
|
find_similar_to: Optional[str] = None
|
|
1394
1292
|
) -> List[TextContent]:
|
|
1395
1293
|
"""
|
|
1396
|
-
Search repositories, documentation, and other content using
|
|
1397
|
-
Returns results formatted to guide next actions.
|
|
1398
|
-
|
|
1399
|
-
USE THIS TOOL WHEN:
|
|
1400
|
-
- Finding specific repos/docs/content ("find X library", "trending Y frameworks")
|
|
1401
|
-
- Looking for examples or implementations
|
|
1402
|
-
- Searching for what's available on a topic
|
|
1403
|
-
- Simple, direct searches that need quick results
|
|
1404
|
-
- Finding similar content to a known URL
|
|
1405
|
-
|
|
1406
|
-
DON'T USE THIS FOR:
|
|
1407
|
-
- Comparative analysis (use nia_deep_research_agent instead)
|
|
1408
|
-
- Complex multi-faceted questions (use nia_deep_research_agent instead)
|
|
1409
|
-
- Questions requiring synthesis of multiple sources (use nia_deep_research_agent instead)
|
|
1294
|
+
Search repositories, documentation, and other content using web search.
|
|
1410
1295
|
|
|
1411
1296
|
Args:
|
|
1412
1297
|
query: Natural language search query (e.g., "best RAG implementations", "trending rust web frameworks")
|
|
1413
1298
|
num_results: Number of results to return (default: 5, max: 10)
|
|
1414
1299
|
category: Filter by category: "github", "company", "research paper", "news", "tweet", "pdf"
|
|
1415
1300
|
days_back: Only show results from the last N days (for trending content)
|
|
1416
|
-
find_similar_to: URL to find similar content
|
|
1417
|
-
|
|
1418
|
-
Returns:
|
|
1419
|
-
Search results with actionable next steps
|
|
1301
|
+
find_similar_to: URL to find similar content
|
|
1420
1302
|
"""
|
|
1421
1303
|
try:
|
|
1422
1304
|
client = await ensure_api_client()
|
|
@@ -1516,13 +1398,7 @@ async def nia_web_search(
|
|
|
1516
1398
|
|
|
1517
1399
|
# Add prominent call-to-action if we found indexable content
|
|
1518
1400
|
if github_repos or documentation:
|
|
1519
|
-
response_text += "\n## 🎯 **Ready to unlock
|
|
1520
|
-
response_text += "The repositories and documentation above can be indexed for:\n"
|
|
1521
|
-
response_text += "- 🤖 AI-powered code understanding and search\n"
|
|
1522
|
-
response_text += "- 💡 Instant answers to technical questions\n"
|
|
1523
|
-
response_text += "- 🔍 Deep architectural insights\n"
|
|
1524
|
-
response_text += "- 📚 Smart documentation Q&A\n\n"
|
|
1525
|
-
response_text += "**Just copy and paste the index commands above!**\n"
|
|
1401
|
+
response_text += "\n## 🎯 **Ready to unlock nia's tools**\n"
|
|
1526
1402
|
|
|
1527
1403
|
# Add search metadata
|
|
1528
1404
|
response_text += f"\n---\n"
|
|
@@ -1562,27 +1438,6 @@ async def nia_deep_research_agent(
|
|
|
1562
1438
|
) -> List[TextContent]:
|
|
1563
1439
|
"""
|
|
1564
1440
|
Perform deep, multi-step research on a topic using advanced AI research capabilities.
|
|
1565
|
-
Best for complex questions that need comprehensive analysis. Don't just use keywords or unstrctured query, make a comprehensive question to get the best results possible.
|
|
1566
|
-
|
|
1567
|
-
USE THIS TOOL WHEN:
|
|
1568
|
-
- Comparing multiple options ("compare X vs Y vs Z")
|
|
1569
|
-
- Analyzing pros and cons
|
|
1570
|
-
- Questions with "best", "top", "which is better"
|
|
1571
|
-
- Needing structured analysis or synthesis
|
|
1572
|
-
- Complex questions requiring multiple sources
|
|
1573
|
-
- Questions about trends, patterns, or developments
|
|
1574
|
-
- Requests for comprehensive overviews
|
|
1575
|
-
|
|
1576
|
-
DON'T USE THIS FOR:
|
|
1577
|
-
- Simple lookups (use nia_web_search instead)
|
|
1578
|
-
- Finding a specific known item (use nia_web_search instead)
|
|
1579
|
-
- Quick searches for repos/docs (use nia_web_search instead)
|
|
1580
|
-
|
|
1581
|
-
COMPLEXITY INDICATORS:
|
|
1582
|
-
- Words like: compare, analyze, evaluate, pros/cons, trade-offs
|
|
1583
|
-
- Multiple criteria mentioned
|
|
1584
|
-
- Asking for recommendations based on context
|
|
1585
|
-
- Needing structured output (tables, lists, comparisons)
|
|
1586
1441
|
|
|
1587
1442
|
Args:
|
|
1588
1443
|
query: Research question (e.g., "Compare top 3 RAG frameworks with pros/cons")
|
|
@@ -1732,162 +1587,6 @@ async def nia_deep_research_agent(
|
|
|
1732
1587
|
"Try simplifying your question or using the regular nia_web_search tool."
|
|
1733
1588
|
)]
|
|
1734
1589
|
|
|
1735
|
-
@mcp.tool()
|
|
1736
|
-
async def initialize_project(
|
|
1737
|
-
project_root: str,
|
|
1738
|
-
profiles: Optional[List[str]] = None
|
|
1739
|
-
) -> List[TextContent]:
|
|
1740
|
-
"""
|
|
1741
|
-
Initialize a NIA-enabled project with IDE-specific rules and configurations.
|
|
1742
|
-
|
|
1743
|
-
This tool sets up your project with NIA integration, creating configuration files
|
|
1744
|
-
and rules tailored to your IDE or editor. It enables AI assistants to better
|
|
1745
|
-
understand and work with NIA's knowledge search capabilities.
|
|
1746
|
-
|
|
1747
|
-
Args:
|
|
1748
|
-
project_root: Absolute path to the project root directory
|
|
1749
|
-
profiles: List of IDE profiles to set up (default: ["cursor"]).
|
|
1750
|
-
Options: cursor, vscode, claude, windsurf, cline, codex, zed, jetbrains, neovim, sublime
|
|
1751
|
-
|
|
1752
|
-
Returns:
|
|
1753
|
-
Status of the initialization with created files and next steps
|
|
1754
|
-
|
|
1755
|
-
Examples:
|
|
1756
|
-
- Basic: initialize_project("/path/to/project")
|
|
1757
|
-
- Multiple IDEs: initialize_project("/path/to/project", profiles=["cursor", "vscode"])
|
|
1758
|
-
- Specific IDE: initialize_project("/path/to/project", profiles=["windsurf"])
|
|
1759
|
-
"""
|
|
1760
|
-
try:
|
|
1761
|
-
# Validate project root
|
|
1762
|
-
project_path = Path(project_root)
|
|
1763
|
-
if not project_path.is_absolute():
|
|
1764
|
-
return [TextContent(
|
|
1765
|
-
type="text",
|
|
1766
|
-
text=f"❌ Error: project_root must be an absolute path. Got: {project_root}"
|
|
1767
|
-
)]
|
|
1768
|
-
|
|
1769
|
-
# Default to cursor profile if none specified
|
|
1770
|
-
if profiles is None:
|
|
1771
|
-
profiles = ["cursor"]
|
|
1772
|
-
|
|
1773
|
-
# Validate profiles
|
|
1774
|
-
supported = get_supported_profiles()
|
|
1775
|
-
invalid_profiles = [p for p in profiles if p not in supported]
|
|
1776
|
-
if invalid_profiles:
|
|
1777
|
-
return [TextContent(
|
|
1778
|
-
type="text",
|
|
1779
|
-
text=f"❌ Unknown profiles: {', '.join(invalid_profiles)}\n\n"
|
|
1780
|
-
f"Supported profiles: {', '.join(supported)}"
|
|
1781
|
-
)]
|
|
1782
|
-
|
|
1783
|
-
logger.info(f"Initializing NIA project at {project_root} with profiles: {profiles}")
|
|
1784
|
-
|
|
1785
|
-
# Initialize the project
|
|
1786
|
-
result = initialize_nia_project(
|
|
1787
|
-
project_root=project_root,
|
|
1788
|
-
profiles=profiles
|
|
1789
|
-
)
|
|
1790
|
-
|
|
1791
|
-
if not result.get("success"):
|
|
1792
|
-
return [TextContent(
|
|
1793
|
-
type="text",
|
|
1794
|
-
text=f"❌ Failed to initialize project: {result.get('error', 'Unknown error')}"
|
|
1795
|
-
)]
|
|
1796
|
-
|
|
1797
|
-
# Format success response
|
|
1798
|
-
response_lines = [
|
|
1799
|
-
f"✅ Successfully initialized NIA project at: {project_root}",
|
|
1800
|
-
"",
|
|
1801
|
-
"## 📁 Created Files:",
|
|
1802
|
-
]
|
|
1803
|
-
|
|
1804
|
-
for file in result.get("files_created", []):
|
|
1805
|
-
response_lines.append(f"- {file}")
|
|
1806
|
-
|
|
1807
|
-
if result.get("profiles_initialized"):
|
|
1808
|
-
response_lines.extend([
|
|
1809
|
-
"",
|
|
1810
|
-
"## 🎨 Initialized Profiles:",
|
|
1811
|
-
])
|
|
1812
|
-
for profile in result["profiles_initialized"]:
|
|
1813
|
-
response_lines.append(f"- {profile}")
|
|
1814
|
-
|
|
1815
|
-
if result.get("warnings"):
|
|
1816
|
-
response_lines.extend([
|
|
1817
|
-
"",
|
|
1818
|
-
"## ⚠️ Warnings:",
|
|
1819
|
-
])
|
|
1820
|
-
for warning in result["warnings"]:
|
|
1821
|
-
response_lines.append(f"- {warning}")
|
|
1822
|
-
|
|
1823
|
-
if result.get("next_steps"):
|
|
1824
|
-
response_lines.extend([
|
|
1825
|
-
"",
|
|
1826
|
-
"## 🚀 Next Steps:",
|
|
1827
|
-
])
|
|
1828
|
-
for i, step in enumerate(result["next_steps"], 1):
|
|
1829
|
-
response_lines.append(f"{i}. {step}")
|
|
1830
|
-
|
|
1831
|
-
# Add profile-specific instructions
|
|
1832
|
-
response_lines.extend([
|
|
1833
|
-
"",
|
|
1834
|
-
"## 💡 Quick Start:",
|
|
1835
|
-
])
|
|
1836
|
-
|
|
1837
|
-
if "cursor" in profiles:
|
|
1838
|
-
response_lines.extend([
|
|
1839
|
-
"**For Cursor:**",
|
|
1840
|
-
"1. Restart Cursor to load the NIA MCP server",
|
|
1841
|
-
"2. Run `list_repositories` to verify connection",
|
|
1842
|
-
"3. Start indexing with `index_repository https://github.com/owner/repo`",
|
|
1843
|
-
""
|
|
1844
|
-
])
|
|
1845
|
-
|
|
1846
|
-
if "vscode" in profiles:
|
|
1847
|
-
response_lines.extend([
|
|
1848
|
-
"**For VSCode:**",
|
|
1849
|
-
"1. Reload the VSCode window (Cmd/Ctrl+R)",
|
|
1850
|
-
"2. Open command palette (Cmd/Ctrl+Shift+P)",
|
|
1851
|
-
"3. Run 'NIA: Index Repository' task",
|
|
1852
|
-
""
|
|
1853
|
-
])
|
|
1854
|
-
|
|
1855
|
-
if "claude" in profiles:
|
|
1856
|
-
response_lines.extend([
|
|
1857
|
-
"**For Claude Desktop:**",
|
|
1858
|
-
"1. The .claude directory has been created",
|
|
1859
|
-
"2. Claude will now understand NIA commands",
|
|
1860
|
-
"3. Try: 'Search for authentication patterns'",
|
|
1861
|
-
""
|
|
1862
|
-
])
|
|
1863
|
-
|
|
1864
|
-
# Add general tips
|
|
1865
|
-
response_lines.extend([
|
|
1866
|
-
"## 📚 Tips:",
|
|
1867
|
-
"- Use natural language for searches: 'How does X work?'",
|
|
1868
|
-
"- Index repositories before searching them",
|
|
1869
|
-
"- Use `nia_web_search` to discover new repositories",
|
|
1870
|
-
"- Check `list_repositories` to see what's already indexed",
|
|
1871
|
-
"",
|
|
1872
|
-
"Ready to supercharge your development with AI-powered code search! 🚀"
|
|
1873
|
-
])
|
|
1874
|
-
|
|
1875
|
-
return [TextContent(
|
|
1876
|
-
type="text",
|
|
1877
|
-
text="\n".join(response_lines)
|
|
1878
|
-
)]
|
|
1879
|
-
|
|
1880
|
-
except Exception as e:
|
|
1881
|
-
logger.error(f"Error in initialize_project tool: {e}")
|
|
1882
|
-
return [TextContent(
|
|
1883
|
-
type="text",
|
|
1884
|
-
text=f"❌ Error initializing project: {str(e)}\n\n"
|
|
1885
|
-
"Please check:\n"
|
|
1886
|
-
"- The project_root path is correct and accessible\n"
|
|
1887
|
-
"- You have write permissions to the directory\n"
|
|
1888
|
-
"- The NIA MCP server is properly installed"
|
|
1889
|
-
)]
|
|
1890
|
-
|
|
1891
1590
|
@mcp.tool()
|
|
1892
1591
|
async def read_source_content(
|
|
1893
1592
|
source_type: str,
|
|
@@ -1897,22 +1596,15 @@ async def read_source_content(
|
|
|
1897
1596
|
"""
|
|
1898
1597
|
Read the full content of a specific source file or document.
|
|
1899
1598
|
|
|
1900
|
-
This tool allows AI to fetch complete content from sources identified during search,
|
|
1901
|
-
enabling deeper analysis when the truncated search results are insufficient.
|
|
1902
|
-
|
|
1903
1599
|
Args:
|
|
1904
1600
|
source_type: Type of source - "repository" or "documentation"
|
|
1905
1601
|
source_identifier:
|
|
1906
|
-
- For repository: "owner/repo:path/to/file.py"
|
|
1602
|
+
- For repository: "owner/repo:path/to/file.py"
|
|
1907
1603
|
- For documentation: The source URL or document ID
|
|
1908
1604
|
metadata: Optional metadata from search results to help locate the source
|
|
1909
1605
|
|
|
1910
1606
|
Returns:
|
|
1911
1607
|
Full content of the requested source with metadata
|
|
1912
|
-
|
|
1913
|
-
Examples:
|
|
1914
|
-
- read_source_content("repository", "langchain-ai/langchain:libs/core/langchain_core/runnables/base.py")
|
|
1915
|
-
- read_source_content("documentation", "https://docs.python.org/3/library/asyncio.html")
|
|
1916
1608
|
"""
|
|
1917
1609
|
try:
|
|
1918
1610
|
client = await ensure_api_client()
|
|
@@ -2016,6 +1708,170 @@ async def read_source_content(
|
|
|
2016
1708
|
text=f"❌ Error reading source content: {str(e)}"
|
|
2017
1709
|
)]
|
|
2018
1710
|
|
|
1711
|
+
@mcp.tool()
|
|
1712
|
+
async def get_repository_hierarchy(
|
|
1713
|
+
repository: str,
|
|
1714
|
+
include_classes: bool = True,
|
|
1715
|
+
include_methods: bool = False,
|
|
1716
|
+
include_tree: bool = False
|
|
1717
|
+
) -> List[TextContent]:
|
|
1718
|
+
"""
|
|
1719
|
+
Get the file hierarchy for an indexed repository.
|
|
1720
|
+
|
|
1721
|
+
Args:
|
|
1722
|
+
repository: Repository identifier in owner/repo format (e.g., "facebook/react")
|
|
1723
|
+
include_classes: Whether to include class names in the hierarchy (default: True)
|
|
1724
|
+
include_methods: Whether to include method names in the hierarchy (default: False)
|
|
1725
|
+
include_tree: Whether to include the full tree structure (default: False)
|
|
1726
|
+
|
|
1727
|
+
Returns:
|
|
1728
|
+
Repository file hierarchy with statistics and structural information
|
|
1729
|
+
"""
|
|
1730
|
+
try:
|
|
1731
|
+
client = await ensure_api_client()
|
|
1732
|
+
|
|
1733
|
+
logger.info(f"Getting repository hierarchy for: {repository}")
|
|
1734
|
+
|
|
1735
|
+
# Get the hierarchy data
|
|
1736
|
+
result = await client.get_repository_hierarchy(
|
|
1737
|
+
owner_repo=repository,
|
|
1738
|
+
include_classes=include_classes,
|
|
1739
|
+
include_methods=include_methods,
|
|
1740
|
+
include_tree=include_tree
|
|
1741
|
+
)
|
|
1742
|
+
|
|
1743
|
+
# Format the response
|
|
1744
|
+
response_lines = []
|
|
1745
|
+
|
|
1746
|
+
# Header
|
|
1747
|
+
response_lines.extend([
|
|
1748
|
+
f"# 🏗️ Repository File Hierarchy: {repository}",
|
|
1749
|
+
"",
|
|
1750
|
+
f"**Repository ID:** {result.get('repository_id', 'Unknown')}",
|
|
1751
|
+
f"**Generated:** {result.get('generated_at', 'Unknown')}",
|
|
1752
|
+
""
|
|
1753
|
+
])
|
|
1754
|
+
|
|
1755
|
+
# Options used
|
|
1756
|
+
options = result.get("options", {})
|
|
1757
|
+
response_lines.extend([
|
|
1758
|
+
"**Options:**",
|
|
1759
|
+
f"- Include Classes: {'✅' if options.get('include_classes', include_classes) else '❌'}",
|
|
1760
|
+
f"- Include Methods: {'✅' if options.get('include_methods', include_methods) else '❌'}",
|
|
1761
|
+
f"- Include Tree: {'✅' if include_tree else '❌'}",
|
|
1762
|
+
""
|
|
1763
|
+
])
|
|
1764
|
+
|
|
1765
|
+
# Statistics
|
|
1766
|
+
stats = result.get("stats", {})
|
|
1767
|
+
if stats:
|
|
1768
|
+
response_lines.extend([
|
|
1769
|
+
"## 📊 Statistics",
|
|
1770
|
+
""
|
|
1771
|
+
])
|
|
1772
|
+
|
|
1773
|
+
if stats.get("total_files"):
|
|
1774
|
+
response_lines.append(f"📄 **Total Files:** {stats['total_files']:,}")
|
|
1775
|
+
if stats.get("total_directories"):
|
|
1776
|
+
response_lines.append(f"📁 **Total Directories:** {stats['total_directories']:,}")
|
|
1777
|
+
if stats.get("total_classes"):
|
|
1778
|
+
response_lines.append(f"🏷️ **Total Classes:** {stats['total_classes']:,}")
|
|
1779
|
+
if stats.get("total_methods"):
|
|
1780
|
+
response_lines.append(f"⚙️ **Total Methods:** {stats['total_methods']:,}")
|
|
1781
|
+
|
|
1782
|
+
# File types breakdown
|
|
1783
|
+
if stats.get("file_types"):
|
|
1784
|
+
response_lines.extend([
|
|
1785
|
+
"",
|
|
1786
|
+
"**File Types:**"
|
|
1787
|
+
])
|
|
1788
|
+
file_types = stats["file_types"]
|
|
1789
|
+
# Sort by count descending
|
|
1790
|
+
sorted_types = sorted(file_types.items(), key=lambda x: x[1], reverse=True)
|
|
1791
|
+
for ext, count in sorted_types[:10]: # Show top 10
|
|
1792
|
+
response_lines.append(f"- `{ext}`: {count:,} files")
|
|
1793
|
+
if len(sorted_types) > 10:
|
|
1794
|
+
response_lines.append(f"- ... and {len(sorted_types) - 10} more types")
|
|
1795
|
+
|
|
1796
|
+
response_lines.append("")
|
|
1797
|
+
|
|
1798
|
+
# Hierarchy text
|
|
1799
|
+
hierarchy_text = result.get("hierarchy_text", "")
|
|
1800
|
+
if hierarchy_text:
|
|
1801
|
+
response_lines.extend([
|
|
1802
|
+
"## 🌳 File Hierarchy",
|
|
1803
|
+
"",
|
|
1804
|
+
"```",
|
|
1805
|
+
hierarchy_text,
|
|
1806
|
+
"```",
|
|
1807
|
+
""
|
|
1808
|
+
])
|
|
1809
|
+
|
|
1810
|
+
# Tree structure if requested and available
|
|
1811
|
+
if include_tree and result.get("hierarchy_tree"):
|
|
1812
|
+
response_lines.extend([
|
|
1813
|
+
"## 🗂️ Detailed Tree Structure",
|
|
1814
|
+
"",
|
|
1815
|
+
"```json",
|
|
1816
|
+
json.dumps(result["hierarchy_tree"], indent=2),
|
|
1817
|
+
"```",
|
|
1818
|
+
""
|
|
1819
|
+
])
|
|
1820
|
+
|
|
1821
|
+
# Usage tips
|
|
1822
|
+
response_lines.extend([
|
|
1823
|
+
"## 💡 Usage Tips",
|
|
1824
|
+
"",
|
|
1825
|
+
"- Use this hierarchy to understand the codebase structure before searching",
|
|
1826
|
+
"- Include methods for detailed function discovery",
|
|
1827
|
+
"- Use `search_codebase` with specific file paths found here",
|
|
1828
|
+
"- Reference file paths when using `read_source_content`"
|
|
1829
|
+
])
|
|
1830
|
+
|
|
1831
|
+
return [TextContent(type="text", text="\n".join(response_lines))]
|
|
1832
|
+
|
|
1833
|
+
except APIError as e:
|
|
1834
|
+
logger.error(f"API Error getting repository hierarchy: {e}")
|
|
1835
|
+
|
|
1836
|
+
if e.status_code == 404:
|
|
1837
|
+
return [TextContent(
|
|
1838
|
+
type="text",
|
|
1839
|
+
text=f"❌ Repository '{repository}' not found. Please check:\n\n"
|
|
1840
|
+
"1. The repository name is correct (owner/repo format)\n"
|
|
1841
|
+
"2. The repository has been indexed\n"
|
|
1842
|
+
"3. You have access to this repository\n\n"
|
|
1843
|
+
"Use `list_repositories` to see available repositories."
|
|
1844
|
+
)]
|
|
1845
|
+
elif e.status_code == 400:
|
|
1846
|
+
return [TextContent(
|
|
1847
|
+
type="text",
|
|
1848
|
+
text=f"❌ Repository not ready: {e.detail}\n\n"
|
|
1849
|
+
f"The repository may still be indexing. Use `check_resource_status(\"repository\", \"{repository}\")` to check status."
|
|
1850
|
+
)]
|
|
1851
|
+
elif e.status_code == 403 or "free tier limit" in str(e).lower():
|
|
1852
|
+
if e.detail and "3 free indexing operations" in e.detail:
|
|
1853
|
+
return [TextContent(
|
|
1854
|
+
type="text",
|
|
1855
|
+
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited access."
|
|
1856
|
+
)]
|
|
1857
|
+
else:
|
|
1858
|
+
return [TextContent(
|
|
1859
|
+
type="text",
|
|
1860
|
+
text=f"❌ {str(e)}\n\n💡 Tip: You've reached the free tier limit. Upgrade to Pro for unlimited access."
|
|
1861
|
+
)]
|
|
1862
|
+
else:
|
|
1863
|
+
return [TextContent(type="text", text=f"❌ {str(e)}")]
|
|
1864
|
+
except Exception as e:
|
|
1865
|
+
logger.error(f"Unexpected error getting repository hierarchy: {e}")
|
|
1866
|
+
return [TextContent(
|
|
1867
|
+
type="text",
|
|
1868
|
+
text=f"❌ Error getting repository hierarchy: {str(e)}\n\n"
|
|
1869
|
+
"Please check that:\n"
|
|
1870
|
+
"- The repository identifier is correct\n"
|
|
1871
|
+
"- The repository is fully indexed\n"
|
|
1872
|
+
"- Your API connection is working"
|
|
1873
|
+
)]
|
|
1874
|
+
|
|
2019
1875
|
# @mcp.tool()
|
|
2020
1876
|
# async def index_local_filesystem(
|
|
2021
1877
|
# directory_path: str,
|
|
@@ -2432,6 +2288,7 @@ async def read_source_content(
|
|
|
2432
2288
|
# - npm: Node.js packages from NPM registry
|
|
2433
2289
|
# - crates_io: Rust packages from crates.io
|
|
2434
2290
|
# - golang_proxy: Go modules from Go proxy
|
|
2291
|
+
# - ruby_gems: Ruby gems from RubyGems.org
|
|
2435
2292
|
#
|
|
2436
2293
|
# Authentication:
|
|
2437
2294
|
# - Requires CHROMA_API_KEY environment variable
|
|
@@ -2467,8 +2324,6 @@ async def nia_package_search_grep(
|
|
|
2467
2324
|
Required Args: "registry", "package_name", "pattern" Optional Args: "version", "language",
|
|
2468
2325
|
"filename_sha256", "a", "b", "c", "head_limit", "output_mode"
|
|
2469
2326
|
|
|
2470
|
-
Best for: Deterministic code search, finding specific code patterns, or exploring code structure.
|
|
2471
|
-
|
|
2472
2327
|
Parameters:
|
|
2473
2328
|
a: The number of lines after a grep match to include
|
|
2474
2329
|
b: The number of lines before a grep match to include
|
|
@@ -2476,23 +2331,19 @@ async def nia_package_search_grep(
|
|
|
2476
2331
|
filename_sha256: The sha256 hash of the file to filter for
|
|
2477
2332
|
head_limit: Limits number of results returned. If the number of results returned is less than the
|
|
2478
2333
|
head limit, all results have been returned.
|
|
2479
|
-
language: The languages to filter for. If not provided, all languages will be searched.
|
|
2480
|
-
options: "Rust", "Go", "Python", "JavaScript", "JSX", "TypeScript", "TSX", "HTML", "Markdown",
|
|
2481
|
-
"YAML", "Bash", "SQL", "JSON", "Text", "Dockerfile", "HCL", "Protobuf", "Make", "Toml", "Jupyter Notebook"
|
|
2334
|
+
language: The languages to filter for. If not provided, all languages will be searched.
|
|
2482
2335
|
output_mode: Controls the shape of the grep output. Accepted values:
|
|
2483
2336
|
"content" (default): return content snippets with line ranges
|
|
2484
2337
|
"files_with_matches": return unique files (path and sha256) that match
|
|
2485
2338
|
"count": return files with the count of matches per file
|
|
2486
2339
|
package_name: The name of the requested package. Pass the name as it appears in the package
|
|
2487
2340
|
manager. For Go packages, use the GitHub organization and repository name in the format
|
|
2488
|
-
{org}/{repo}
|
|
2341
|
+
{org}/{repo}
|
|
2489
2342
|
pattern: The regex pattern for exact text matching in the codebase. Must be a valid regex.
|
|
2490
2343
|
Example: "func\\s+\\(get_repository\\|getRepository\\)\\s*\\(.*?\\)\\s\\{"
|
|
2491
2344
|
registry: The name of the registry containing the requested package. Must be one of:
|
|
2492
|
-
"crates_io", "golang_proxy", "npm", or "
|
|
2493
|
-
version:
|
|
2494
|
-
If provided, must be in semver format: {major}.{minor}.{patch}. Otherwise, the latest indexed
|
|
2495
|
-
version of the package available will be used.
|
|
2345
|
+
"crates_io", "golang_proxy", "npm", "py_pi", or "ruby_gems".
|
|
2346
|
+
version: Optional
|
|
2496
2347
|
"""
|
|
2497
2348
|
try:
|
|
2498
2349
|
# Use API client for backend routing
|
|
@@ -2604,33 +2455,24 @@ async def nia_package_search_hybrid(
|
|
|
2604
2455
|
language: Optional[str] = None
|
|
2605
2456
|
) -> List[TextContent]:
|
|
2606
2457
|
"""
|
|
2607
|
-
Searches package source code using semantic understanding AND optionally regex patterns.
|
|
2608
|
-
allows for hybrid search, allowing for prefiltering with regex, and semantic ranking.
|
|
2458
|
+
Searches package source code using semantic understanding AND optionally regex patterns.
|
|
2609
2459
|
|
|
2610
2460
|
Required Args: "registry", "package_name", "semantic_queries"
|
|
2611
2461
|
|
|
2612
2462
|
Optional Args: "version", "filename_sha256", "pattern", "language"
|
|
2613
2463
|
|
|
2614
|
-
Best for: Understanding how packages implement specific features, finding usage patterns, or
|
|
2615
|
-
exploring code structure.
|
|
2616
|
-
|
|
2617
2464
|
Parameters:
|
|
2618
2465
|
filename_sha256: The sha256 hash of the file to filter for
|
|
2619
|
-
language: The languages to filter for. If not provided, all languages will be searched.
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
package_name: The name of the requested package. Pass the name as it appears in the package
|
|
2623
|
-
manager. For Go packages, use the GitHub organization and repository name in the format
|
|
2624
|
-
{org}/{repo}, if unsure check the GitHub URL for the package and use {org}/{repo} from that URL.
|
|
2466
|
+
language: The languages to filter for. If not provided, all languages will be searched.
|
|
2467
|
+
package_name: The name of the requested package. Pass the name as it appears in the package manager. For Go packages, use the GitHub organization and repository name in the format
|
|
2468
|
+
{org}/{repo}
|
|
2625
2469
|
pattern: The regex pattern for exact text matching in the codebase. Must be a valid regex.
|
|
2626
2470
|
Example: "func\\s+\\(get_repository\\|getRepository\\)\\s*\\(.*?\\)\\s\\{"
|
|
2627
2471
|
registry: The name of the registry containing the requested package. Must be one of:
|
|
2628
|
-
"crates_io", "golang_proxy", "npm", or "
|
|
2472
|
+
"crates_io", "golang_proxy", "npm", "py_pi", or "ruby_gems".
|
|
2629
2473
|
semantic_queries: Array of 1-5 plain English questions about the codebase. Example: ["how is
|
|
2630
2474
|
argmax implemented in numpy?", "what testing patterns does axum use?"]
|
|
2631
|
-
version:
|
|
2632
|
-
If provided, must be in semver format: {major}.{minor}.{patch}. Otherwise, the latest indexed
|
|
2633
|
-
version of the package available will be used.
|
|
2475
|
+
version: Optional
|
|
2634
2476
|
"""
|
|
2635
2477
|
try:
|
|
2636
2478
|
# Use API client for backend routing
|
|
@@ -2748,21 +2590,16 @@ async def nia_package_search_read_file(
|
|
|
2748
2590
|
Required Args: "registry", "package_name", "filename_sha256", "start_line", "end_line" Optional Args:
|
|
2749
2591
|
"version"
|
|
2750
2592
|
|
|
2751
|
-
Best for: Inspecting exact code snippets when you already know the file and line numbers. Max 200
|
|
2752
|
-
lines.
|
|
2753
|
-
|
|
2754
2593
|
Parameters:
|
|
2755
2594
|
end_line: 1-based inclusive end line to read
|
|
2756
2595
|
filename_sha256: The sha256 hash of the file to filter for
|
|
2757
2596
|
package_name: The name of the requested package. Pass the name as it appears in the package
|
|
2758
2597
|
manager. For Go packages, use the GitHub organization and repository name in the format
|
|
2759
|
-
{org}/{repo}
|
|
2598
|
+
{org}/{repo}
|
|
2760
2599
|
registry: The name of the registry containing the requested package. Must be one of:
|
|
2761
|
-
"crates_io", "golang_proxy", "npm", or "
|
|
2600
|
+
"crates_io", "golang_proxy", "npm", "py_pi", or "ruby_gems".
|
|
2762
2601
|
start_line: 1-based inclusive start line to read
|
|
2763
|
-
version:
|
|
2764
|
-
If provided, must be in semver format: {major}.{minor}.{patch}. Otherwise, the latest indexed
|
|
2765
|
-
version of the package available will be used.
|
|
2602
|
+
version: Optional
|
|
2766
2603
|
"""
|
|
2767
2604
|
try:
|
|
2768
2605
|
# Validate line range
|
|
@@ -2833,24 +2670,11 @@ async def nia_bug_report(
|
|
|
2833
2670
|
additional_context: Optional[str] = None
|
|
2834
2671
|
) -> List[TextContent]:
|
|
2835
2672
|
"""
|
|
2836
|
-
Submit a bug report or feature request
|
|
2837
|
-
|
|
2838
|
-
This tool allows users to report bugs, request features, or provide feedback
|
|
2839
|
-
directly to the development team. Reports are sent via email and Slack for
|
|
2840
|
-
immediate attention.
|
|
2841
|
-
|
|
2673
|
+
Submit a bug report or feature request.
|
|
2842
2674
|
Args:
|
|
2843
2675
|
description: Detailed description of the bug or feature request (10-5000 characters)
|
|
2844
2676
|
bug_type: Type of report - "bug", "feature-request", "improvement", or "other" (default: "bug")
|
|
2845
2677
|
additional_context: Optional additional context, steps to reproduce, or related information
|
|
2846
|
-
|
|
2847
|
-
Returns:
|
|
2848
|
-
Confirmation of successful submission with reference ID
|
|
2849
|
-
|
|
2850
|
-
Examples:
|
|
2851
|
-
- nia_bug_report("The search is not returning any results for my repository")
|
|
2852
|
-
- nia_bug_report("Add support for searching within specific file types", "feature-request")
|
|
2853
|
-
- nia_bug_report("Repository indexing fails with large repos", "bug", "Happens with repos over 1GB")
|
|
2854
2678
|
"""
|
|
2855
2679
|
try:
|
|
2856
2680
|
client = await ensure_api_client()
|
|
@@ -2947,15 +2771,11 @@ async def save_context(
|
|
|
2947
2771
|
"""
|
|
2948
2772
|
Save a conversation context for cross-agent sharing.
|
|
2949
2773
|
|
|
2950
|
-
This tool enables agents to save conversation contexts that can be shared
|
|
2951
|
-
with other AI agents, creating seamless handoffs between different coding
|
|
2952
|
-
environments (e.g., Cursor → Claude Code).
|
|
2953
|
-
|
|
2954
2774
|
Args:
|
|
2955
|
-
title: A descriptive title for the context
|
|
2956
|
-
summary: Brief summary of the conversation
|
|
2775
|
+
title: A descriptive title for the context
|
|
2776
|
+
summary: Brief summary of the conversation
|
|
2957
2777
|
content: Full conversation context - the agent should compact the conversation history but keep all important parts togethers, as well as code snippets. No excuses.
|
|
2958
|
-
agent_source: Which agent is creating this context (e.g., "cursor"
|
|
2778
|
+
agent_source: Which agent is creating this context (e.g., "cursor")
|
|
2959
2779
|
tags: Optional list of searchable tags
|
|
2960
2780
|
metadata: Optional metadata like file paths, repositories discussed, etc.
|
|
2961
2781
|
nia_references: Structured data about NIA resources used during conversation
|
|
@@ -2969,20 +2789,6 @@ async def save_context(
|
|
|
2969
2789
|
|
|
2970
2790
|
Returns:
|
|
2971
2791
|
Confirmation of successful context save with context ID
|
|
2972
|
-
|
|
2973
|
-
Example:
|
|
2974
|
-
save_context(
|
|
2975
|
-
title="Streaming AI SDK Implementation",
|
|
2976
|
-
summary="Planning conversation about implementing streaming responses with AI SDK",
|
|
2977
|
-
content="User asked about implementing streaming... [agent should include conversation]",
|
|
2978
|
-
agent_source="cursor",
|
|
2979
|
-
tags=["streaming", "ai-sdk", "implementation"],
|
|
2980
|
-
nia_references={
|
|
2981
|
-
"indexed_resources": [{"identifier": "vercel/ai", "resource_type": "repository", "purpose": "Reference for streaming implementation"}],
|
|
2982
|
-
"search_queries": [{"query": "streaming API", "query_type": "documentation", "key_findings": "Found useChat hook with streaming"}]
|
|
2983
|
-
},
|
|
2984
|
-
edited_files=[{"file_path": "src/chat.ts", "operation": "created", "changes_description": "Added streaming chat component"}]
|
|
2985
|
-
)
|
|
2986
2792
|
"""
|
|
2987
2793
|
try:
|
|
2988
2794
|
# Validate input parameters
|
|
@@ -3061,12 +2867,6 @@ async def list_contexts(
|
|
|
3061
2867
|
|
|
3062
2868
|
Returns:
|
|
3063
2869
|
List of conversation contexts with pagination info
|
|
3064
|
-
|
|
3065
|
-
Examples:
|
|
3066
|
-
- list_contexts() - List recent 20 contexts
|
|
3067
|
-
- list_contexts(limit=50) - List recent 50 contexts
|
|
3068
|
-
- list_contexts(tags="streaming,ai-sdk") - Filter by tags
|
|
3069
|
-
- list_contexts(agent_source="cursor") - Only contexts from Cursor
|
|
3070
2870
|
"""
|
|
3071
2871
|
try:
|
|
3072
2872
|
# Validate parameters
|
|
@@ -3333,9 +3133,6 @@ async def search_contexts(
|
|
|
3333
3133
|
"""
|
|
3334
3134
|
Search conversation contexts by content, title, or summary.
|
|
3335
3135
|
|
|
3336
|
-
Perfect for finding relevant contexts when you remember part of the
|
|
3337
|
-
conversation but not the exact context ID.
|
|
3338
|
-
|
|
3339
3136
|
Args:
|
|
3340
3137
|
query: Search query to match against title, summary, content, and tags
|
|
3341
3138
|
limit: Maximum number of results to return (1-100, default: 20)
|
|
@@ -3344,11 +3141,6 @@ async def search_contexts(
|
|
|
3344
3141
|
|
|
3345
3142
|
Returns:
|
|
3346
3143
|
Search results with matching contexts
|
|
3347
|
-
|
|
3348
|
-
Examples:
|
|
3349
|
-
- search_contexts("streaming AI SDK")
|
|
3350
|
-
- search_contexts("authentication", tags="security,implementation")
|
|
3351
|
-
- search_contexts("database", agent_source="cursor")
|
|
3352
3144
|
"""
|
|
3353
3145
|
try:
|
|
3354
3146
|
# Validate parameters
|
|
@@ -3450,13 +3242,6 @@ async def update_context(
|
|
|
3450
3242
|
|
|
3451
3243
|
Returns:
|
|
3452
3244
|
Confirmation of successful update
|
|
3453
|
-
|
|
3454
|
-
Example:
|
|
3455
|
-
update_context(
|
|
3456
|
-
context_id="550e8400-e29b-41d4-a716-446655440000",
|
|
3457
|
-
title="Updated: Streaming AI SDK Implementation",
|
|
3458
|
-
tags=["streaming", "ai-sdk", "completed"]
|
|
3459
|
-
)
|
|
3460
3245
|
"""
|
|
3461
3246
|
try:
|
|
3462
3247
|
if not context_id or not context_id.strip():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/claude_rules.md
RENAMED
|
File without changes
|
{nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/cursor_rules.md
RENAMED
|
File without changes
|
{nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/nia_rules.md
RENAMED
|
File without changes
|
{nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/vscode_rules.md
RENAMED
|
File without changes
|
{nia_mcp_server-1.0.25 → nia_mcp_server-1.0.26}/src/nia_mcp_server/assets/rules/windsurf_rules.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|