nia-mcp-server 1.0.24__py3-none-any.whl → 1.0.26__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.

@@ -3,4 +3,4 @@ NIA MCP Server - Proxy server for NIA Knowledge Agent
3
3
  """
4
4
 
5
5
 
6
- __version__ = "1.0.24"
6
+ __version__ = "1.0.26"
@@ -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.24",
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(
nia_mcp_server/server.py CHANGED
@@ -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. Don't just use keywords or unstrctured query, make a comprehensive question to get the best results possible.
161
- repositories: List of repositories to search (owner/repo or owner/repo/tree/branch if indexed differently before).
162
- - "owner/repo" - Search entire repository (e.g., "facebook/react")
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 (e.g., "550e8400-e29b-41d4-a716-446655440000") - RECOMMENDED
340
- - Display names (e.g., "Vercel AI SDK - Core")
341
- - URLs (e.g., "https://sdk.vercel.ai/docs")
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 (e.g., ["/docs/*", "/guide/*"])
640
- exclude_patterns: Optional list of URL patterns to exclude from crawling (e.g., ["/blog/*", "/changelog/*"])
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 repository: Repository in owner/repo format (e.g., "facebook/react")
848
- - For documentation: UUID preferred, also supports display name or URL (e.g., "550e8400-e29b-41d4-a716-446655440000", "Vercel AI SDK - Core", or "https://docs.trynia.ai/")
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 repository: Repository in owner/repo format (e.g., "facebook/react")
919
- - For documentation: UUID preferred, also supports display name or URL (e.g., "550e8400-e29b-41d4-a716-446655440000", "Vercel AI SDK - Core", or "https://docs.trynia.ai/")
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 repository: Repository in owner/repo format (e.g., "facebook/react")
982
- - For documentation: Source ID (UUID format only) - use list_resources to get the UUID
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 AI-powered search.
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 to
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 NIA's AI capabilities?**\n"
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" (e.g., "facebook/react:src/React.js")
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. Valid
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}, if unsure check the GitHub URL for the package and use {org}/{repo} from that URL.
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 "py_pi".
2493
- version: Optionally, the specific version of the package whose source code to search.
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. This
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. Valid
2620
- options: "Rust", "Go", "Python", "JavaScript", "JSX", "TypeScript", "TSX", "HTML", "Markdown",
2621
- "YAML", "Bash", "SQL", "JSON", "Text", "Dockerfile", "HCL", "Protobuf", "Make", "Toml", "Jupyter Notebook"
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 "py_pi".
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: Optionally, the specific version of the package whose source code to search.
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}, if unsure check the GitHub URL for the package and use {org}/{repo} from that URL.
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 "py_pi".
2600
+ "crates_io", "golang_proxy", "npm", "py_pi", or "ruby_gems".
2762
2601
  start_line: 1-based inclusive start line to read
2763
- version: Optionally, the specific version of the package whose source code to search.
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 to the Nia development team.
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 (1-200 characters)
2956
- summary: Brief summary of the conversation (10-1000 characters)
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", "claude-code", "windsurf")
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
@@ -3220,7 +3020,8 @@ async def retrieve_context(context_id: str) -> List[TextContent]:
3220
3020
  response += f"\n📝 **Summary:**\n{context['summary']}\n\n"
3221
3021
 
3222
3022
  # Add NIA References - CRITICAL for context handoffs
3223
- nia_references = context.get('nia_references', {})
3023
+ # Use 'or {}' to handle cases where nia_references is None (not just missing)
3024
+ nia_references = context.get('nia_references') or {}
3224
3025
  if nia_references:
3225
3026
  response += "🧠 **NIA RESOURCES USED - RECOMMENDED ACTIONS:**\n"
3226
3027
 
@@ -3260,7 +3061,8 @@ async def retrieve_context(context_id: str) -> List[TextContent]:
3260
3061
  response += f"**📋 NIA Session Summary:** {session_summary}\n\n"
3261
3062
 
3262
3063
  # Add Edited Files - CRITICAL for code handoffs
3263
- edited_files = context.get('edited_files', [])
3064
+ # Use 'or []' to handle cases where edited_files is None (not just missing)
3065
+ edited_files = context.get('edited_files') or []
3264
3066
  if edited_files:
3265
3067
  response += "📝 **FILES MODIFIED - READ THESE TO GET UP TO SPEED:**\n"
3266
3068
  for file_info in edited_files:
@@ -3288,7 +3090,8 @@ async def retrieve_context(context_id: str) -> List[TextContent]:
3288
3090
  response += "\n"
3289
3091
 
3290
3092
  # Add metadata if available
3291
- metadata = context.get('metadata', {})
3093
+ # Use 'or {}' to handle cases where metadata is None (not just missing)
3094
+ metadata = context.get('metadata') or {}
3292
3095
  if metadata:
3293
3096
  response += f"📊 **Additional Metadata:**\n"
3294
3097
  for key, value in metadata.items():
@@ -3330,9 +3133,6 @@ async def search_contexts(
3330
3133
  """
3331
3134
  Search conversation contexts by content, title, or summary.
3332
3135
 
3333
- Perfect for finding relevant contexts when you remember part of the
3334
- conversation but not the exact context ID.
3335
-
3336
3136
  Args:
3337
3137
  query: Search query to match against title, summary, content, and tags
3338
3138
  limit: Maximum number of results to return (1-100, default: 20)
@@ -3341,11 +3141,6 @@ async def search_contexts(
3341
3141
 
3342
3142
  Returns:
3343
3143
  Search results with matching contexts
3344
-
3345
- Examples:
3346
- - search_contexts("streaming AI SDK")
3347
- - search_contexts("authentication", tags="security,implementation")
3348
- - search_contexts("database", agent_source="cursor")
3349
3144
  """
3350
3145
  try:
3351
3146
  # Validate parameters
@@ -3447,13 +3242,6 @@ async def update_context(
3447
3242
 
3448
3243
  Returns:
3449
3244
  Confirmation of successful update
3450
-
3451
- Example:
3452
- update_context(
3453
- context_id="550e8400-e29b-41d4-a716-446655440000",
3454
- title="Updated: Streaming AI SDK Implementation",
3455
- tags=["streaming", "ai-sdk", "completed"]
3456
- )
3457
3245
  """
3458
3246
  try:
3459
3247
  if not context_id or not context_id.strip():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nia-mcp-server
3
- Version: 1.0.24
3
+ Version: 1.0.26
4
4
  Summary: Nia Knowledge Agent
5
5
  Project-URL: Homepage, https://trynia.ai
6
6
  Project-URL: Documentation, https://docs.trynia.ai
@@ -1,19 +1,19 @@
1
- nia_mcp_server/__init__.py,sha256=VOORKLeNTKA2FspOIRTpNpZQPszzLz8RVGVzrInPjew,87
1
+ nia_mcp_server/__init__.py,sha256=SQJaSosesKSvvInnz8O1NOnCdxEoEJ3WyjMX-BBwDCo,87
2
2
  nia_mcp_server/__main__.py,sha256=YQSpFtDeKp18r8mKr084cHnRFV4416_EKCu9FTM8_ik,394
3
- nia_mcp_server/api_client.py,sha256=Flk54a3E73TCZmrChwq-sdBaDRxaEtcMC3p2APOHg_0,41546
3
+ nia_mcp_server/api_client.py,sha256=UhR64YMjIXDYFXCGnna64fa5PvFrDLgM-Xb5_RX1LXA,44348
4
4
  nia_mcp_server/cli.py,sha256=32VSPNIocXtDgVBDZNZsxvj3kytBn54_a1pIE84vOdY,1834
5
5
  nia_mcp_server/profiles.py,sha256=2DD8PFRr5Ij4IK4sPUz0mH8aKjkrEtkKLC1R0iki2bA,7221
6
6
  nia_mcp_server/project_init.py,sha256=T0-ziJhofL4L8APwnM43BLhxtlmOHaYH-V9PF2yXLw4,7138
7
7
  nia_mcp_server/rule_transformer.py,sha256=wCxoQ1Kl_rI9mUFnh9kG5iCXYU4QInrmFQOReZfAFVo,11000
8
- nia_mcp_server/server.py,sha256=oDV-HZCyLlsPpAXU6IwMLDR9YjfduB1AsVDLQLRDoxU,156315
8
+ nia_mcp_server/server.py,sha256=Loq-9MJxHIKNcSUO3MMKT5aoYuUinXiHWvStD4ClU4E,145460
9
9
  nia_mcp_server/setup.py,sha256=nJXVY8NHGtWROtoH8DW-3uOgyuPs4F9dW0cNhcbCLrM,5355
10
10
  nia_mcp_server/assets/rules/claude_rules.md,sha256=HNL5GJMUbFxSpNbIAJUQWqAywjMl4lf530I1in69aNY,7380
11
11
  nia_mcp_server/assets/rules/cursor_rules.md,sha256=hd6lhzNrK1ULQUYIEVeOnyKnuLKq4hmwZPbMqGUI1Lk,1720
12
12
  nia_mcp_server/assets/rules/nia_rules.md,sha256=l6sx000uqoczoHYqOPp4hnNgyfpnhvO9NyT0fVx5nU0,8059
13
13
  nia_mcp_server/assets/rules/vscode_rules.md,sha256=fqn4aJO_bhftaCGkVoquruQHf3EaREQJQWHXq6a4FOk,6967
14
14
  nia_mcp_server/assets/rules/windsurf_rules.md,sha256=PzU2as5gaiVsV6PAzg8T_-GR7VCyRQGMjAHcSzYF_ms,3354
15
- nia_mcp_server-1.0.24.dist-info/METADATA,sha256=HTPMQsCgZ4qkwpwk0P9inx85JSnCGewM3_yO_JIqCUc,1324
16
- nia_mcp_server-1.0.24.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
- nia_mcp_server-1.0.24.dist-info/entry_points.txt,sha256=V74FQEp48pfWxPCl7B9mihtqvIJNVjCSbRfCz4ww77I,64
18
- nia_mcp_server-1.0.24.dist-info/licenses/LICENSE,sha256=IrdVKi3bsiB2MTLM26MltBRpwyNi-8P6Cy0EnmAN76A,1557
19
- nia_mcp_server-1.0.24.dist-info/RECORD,,
15
+ nia_mcp_server-1.0.26.dist-info/METADATA,sha256=FsQTbduDPN-naPmWBbfUdT8jgtpiLlehJssgvwoNxW8,1324
16
+ nia_mcp_server-1.0.26.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ nia_mcp_server-1.0.26.dist-info/entry_points.txt,sha256=V74FQEp48pfWxPCl7B9mihtqvIJNVjCSbRfCz4ww77I,64
18
+ nia_mcp_server-1.0.26.dist-info/licenses/LICENSE,sha256=IrdVKi3bsiB2MTLM26MltBRpwyNi-8P6Cy0EnmAN76A,1557
19
+ nia_mcp_server-1.0.26.dist-info/RECORD,,