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

@@ -2,4 +2,4 @@
2
2
  NIA MCP Server - Proxy server for NIA Knowledge Agent
3
3
  """
4
4
 
5
- __version__ = "1.0.16"
5
+ __version__ = "1.0.17"
@@ -176,7 +176,10 @@ class NIAApiClient:
176
176
  # Regular repo URL - extract owner/repo
177
177
  parts = clean_url.rstrip('/').split('/')
178
178
  if len(parts) >= 2:
179
- repo_name = parts[-1].rstrip('.git') # Remove .git suffix
179
+ repo_name = parts[-1]
180
+ # Remove .git suffix if present
181
+ if repo_name.endswith('.git'):
182
+ repo_name = repo_name[:-4]
180
183
  repository_path = f"{parts[-2]}/{repo_name}"
181
184
  else:
182
185
  repository_path = repo_url
@@ -685,4 +688,74 @@ class NIAApiClient:
685
688
  except httpx.HTTPStatusError as e:
686
689
  raise self._handle_api_error(e)
687
690
  except Exception as e:
688
- raise APIError(f"Failed to get source content: {str(e)}")
691
+ raise APIError(f"Failed to get source content: {str(e)}")
692
+
693
+ async def index_local_filesystem(
694
+ self,
695
+ directory_path: str,
696
+ inclusion_patterns: List[str] = None,
697
+ exclusion_patterns: List[str] = None,
698
+ max_file_size_mb: int = 50
699
+ ) -> Dict[str, Any]:
700
+ """Index a local filesystem directory."""
701
+ try:
702
+ payload = {
703
+ "directory_path": directory_path,
704
+ "inclusion_patterns": inclusion_patterns or [],
705
+ "exclusion_patterns": exclusion_patterns or [],
706
+ "max_file_size_mb": max_file_size_mb
707
+ }
708
+
709
+ response = await self.client.post(
710
+ f"{self.base_url}/v2/local-filesystem",
711
+ json=payload
712
+ )
713
+ response.raise_for_status()
714
+ return response.json()
715
+
716
+ except httpx.HTTPStatusError as e:
717
+ raise self._handle_api_error(e)
718
+ except Exception as e:
719
+ raise APIError(f"Failed to index local filesystem: {str(e)}")
720
+
721
+ async def scan_local_filesystem(
722
+ self,
723
+ directory_path: str,
724
+ inclusion_patterns: List[str] = None,
725
+ exclusion_patterns: List[str] = None,
726
+ max_file_size_mb: int = 50
727
+ ) -> Dict[str, Any]:
728
+ """Scan a local filesystem directory to preview what would be indexed."""
729
+ try:
730
+ payload = {
731
+ "directory_path": directory_path,
732
+ "inclusion_patterns": inclusion_patterns or [],
733
+ "exclusion_patterns": exclusion_patterns or [],
734
+ "max_file_size_mb": max_file_size_mb
735
+ }
736
+
737
+ response = await self.client.post(
738
+ f"{self.base_url}/v2/local-filesystem/scan",
739
+ json=payload
740
+ )
741
+ response.raise_for_status()
742
+ return response.json()
743
+
744
+ except httpx.HTTPStatusError as e:
745
+ raise self._handle_api_error(e)
746
+ except Exception as e:
747
+ raise APIError(f"Failed to scan local filesystem: {str(e)}")
748
+
749
+ async def check_local_filesystem_status(self, source_id: str) -> Dict[str, Any]:
750
+ """Check the indexing status of a local filesystem source."""
751
+ try:
752
+ response = await self.client.get(
753
+ f"{self.base_url}/v2/local-filesystem/{source_id}"
754
+ )
755
+ response.raise_for_status()
756
+ return response.json()
757
+
758
+ except httpx.HTTPStatusError as e:
759
+ raise self._handle_api_error(e)
760
+ except Exception as e:
761
+ raise APIError(f"Failed to check local filesystem status: {str(e)}")
nia_mcp_server/server.py CHANGED
@@ -1622,6 +1622,408 @@ async def read_source_content(
1622
1622
  text=f"❌ Error reading source content: {str(e)}"
1623
1623
  )]
1624
1624
 
1625
+ @mcp.tool()
1626
+ async def index_local_filesystem(
1627
+ directory_path: str,
1628
+ inclusion_patterns: Optional[List[str]] = None,
1629
+ exclusion_patterns: Optional[List[str]] = None,
1630
+ max_file_size_mb: int = 50
1631
+ ) -> List[TextContent]:
1632
+ """
1633
+ Index a local filesystem directory for intelligent search.
1634
+
1635
+ Args:
1636
+ directory_path: Absolute path to the directory to index
1637
+ inclusion_patterns: Optional list of patterns to include (e.g., ["ext:.py", "dir:src"])
1638
+ exclusion_patterns: Optional list of patterns to exclude (e.g., ["dir:node_modules", "ext:.log"])
1639
+ max_file_size_mb: Maximum file size in MB to process (default: 50)
1640
+
1641
+ Returns:
1642
+ Status of the indexing operation
1643
+
1644
+ Important:
1645
+ - Path must be absolute (e.g., /Users/username/projects/myproject)
1646
+ - When indexing starts, use check_local_filesystem_status tool to monitor progress
1647
+ """
1648
+ try:
1649
+ # Validate absolute path
1650
+ if not os.path.isabs(directory_path):
1651
+ return [TextContent(
1652
+ type="text",
1653
+ text=f"❌ Error: directory_path must be an absolute path. Got: {directory_path}\n\n"
1654
+ f"Example: /Users/username/projects/myproject"
1655
+ )]
1656
+
1657
+ client = await ensure_api_client()
1658
+
1659
+ # Start indexing
1660
+ logger.info(f"Starting to index local directory: {directory_path}")
1661
+ result = await client.index_local_filesystem(
1662
+ directory_path=directory_path,
1663
+ inclusion_patterns=inclusion_patterns or [],
1664
+ exclusion_patterns=exclusion_patterns or [],
1665
+ max_file_size_mb=max_file_size_mb
1666
+ )
1667
+
1668
+ if result.get("success"):
1669
+ source_id = result["data"]["source_id"]
1670
+ status_url = result["data"]["status_url"]
1671
+
1672
+ return [TextContent(
1673
+ type="text",
1674
+ text=(
1675
+ f"✅ Successfully started indexing local directory!\n\n"
1676
+ f"📁 **Directory:** `{directory_path}`\n"
1677
+ f"🆔 **Source ID:** `{source_id}`\n"
1678
+ f"📊 **Status:** Processing\n\n"
1679
+ f"**What happens next:**\n"
1680
+ f"• NIA is scanning and indexing your files in the background\n"
1681
+ f"• This process typically takes a few minutes depending on directory size\n"
1682
+ f"• Use `check_local_filesystem_status` with source ID `{source_id}` to monitor progress\n"
1683
+ f"• Once indexed, use `search_codebase` or `search_documentation` to search your files\n\n"
1684
+ f"📌 **Tip:** You can check the status at any time or visit [app.trynia.ai](https://app.trynia.ai) to monitor progress."
1685
+ )
1686
+ )]
1687
+ else:
1688
+ return [TextContent(
1689
+ type="text",
1690
+ text=f"❌ Failed to start indexing: {result.get('detail', 'Unknown error')}"
1691
+ )]
1692
+
1693
+ except APIError as e:
1694
+ logger.error(f"API error indexing local filesystem: {e}")
1695
+ return [TextContent(
1696
+ type="text",
1697
+ text=f"❌ API Error: {str(e)}\n\nStatus Code: {e.status_code}\nDetails: {e.detail}"
1698
+ )]
1699
+ except Exception as e:
1700
+ logger.error(f"Unexpected error indexing local filesystem: {e}")
1701
+ return [TextContent(
1702
+ type="text",
1703
+ text=f"❌ Error: An unexpected error occurred while indexing the directory: {str(e)}"
1704
+ )]
1705
+
1706
+ @mcp.tool()
1707
+ async def scan_local_filesystem(
1708
+ directory_path: str,
1709
+ inclusion_patterns: Optional[List[str]] = None,
1710
+ exclusion_patterns: Optional[List[str]] = None,
1711
+ max_file_size_mb: int = 50
1712
+ ) -> List[TextContent]:
1713
+ """
1714
+ Scan a local filesystem directory to preview what files would be indexed.
1715
+
1716
+ This tool helps you understand what files will be processed before actually indexing.
1717
+
1718
+ Args:
1719
+ directory_path: Absolute path to the directory to scan
1720
+ inclusion_patterns: Optional list of patterns to include (e.g., ["ext:.py", "dir:src"])
1721
+ exclusion_patterns: Optional list of patterns to exclude (e.g., ["dir:node_modules", "ext:.log"])
1722
+ max_file_size_mb: Maximum file size in MB to process (default: 50)
1723
+
1724
+ Returns:
1725
+ Summary of files that would be indexed including count, size, and file types
1726
+ """
1727
+ try:
1728
+ # Validate absolute path
1729
+ if not os.path.isabs(directory_path):
1730
+ return [TextContent(
1731
+ type="text",
1732
+ text=f"❌ Error: directory_path must be an absolute path. Got: {directory_path}\n\n"
1733
+ f"Example: /Users/username/projects/myproject"
1734
+ )]
1735
+
1736
+ client = await ensure_api_client()
1737
+
1738
+ logger.info(f"Scanning local directory: {directory_path}")
1739
+ result = await client.scan_local_filesystem(
1740
+ directory_path=directory_path,
1741
+ inclusion_patterns=inclusion_patterns or [],
1742
+ exclusion_patterns=exclusion_patterns or [],
1743
+ max_file_size_mb=max_file_size_mb
1744
+ )
1745
+
1746
+ # Format the scan results
1747
+ total_files = result.get("total_files", 0)
1748
+ total_size_mb = result.get("total_size_mb", 0)
1749
+ file_types = result.get("file_types", {})
1750
+ files = result.get("files", [])
1751
+ truncated = result.get("truncated", False)
1752
+
1753
+ response = f"📊 **Local Directory Scan Results**\n\n"
1754
+ response += f"📁 **Directory:** `{directory_path}`\n"
1755
+ response += f"📄 **Total Files:** {total_files:,}\n"
1756
+ response += f"💾 **Total Size:** {total_size_mb:.2f} MB\n\n"
1757
+
1758
+ if file_types:
1759
+ response += "**File Types:**\n"
1760
+ # Sort by count descending
1761
+ sorted_types = sorted(file_types.items(), key=lambda x: x[1], reverse=True)
1762
+ for ext, count in sorted_types[:10]: # Show top 10
1763
+ response += f"• `{ext}`: {count:,} files\n"
1764
+ if len(sorted_types) > 10:
1765
+ response += f"• ... and {len(sorted_types) - 10} more types\n"
1766
+ response += "\n"
1767
+
1768
+ if files:
1769
+ response += f"**Largest Files (showing {min(len(files), 10)}):**\n"
1770
+ for i, file_info in enumerate(files[:10]):
1771
+ size_mb = file_info["size"] / (1024 * 1024)
1772
+ response += f"{i+1}. `{file_info['path']}` ({size_mb:.2f} MB)\n"
1773
+
1774
+ if truncated:
1775
+ response += f"\n*Note: Showing first 100 files out of {total_files:,} total*\n"
1776
+
1777
+ if inclusion_patterns:
1778
+ response += f"\n**Inclusion Patterns:** {', '.join(f'`{p}`' for p in inclusion_patterns)}\n"
1779
+ if exclusion_patterns:
1780
+ response += f"**Exclusion Patterns:** {', '.join(f'`{p}`' for p in exclusion_patterns)}\n"
1781
+
1782
+ response += "\n💡 **Next Step:** Use `index_local_filesystem` to index these files."
1783
+
1784
+ return [TextContent(type="text", text=response)]
1785
+
1786
+ except APIError as e:
1787
+ logger.error(f"API error scanning local filesystem: {e}")
1788
+ return [TextContent(
1789
+ type="text",
1790
+ text=f"❌ API Error: {str(e)}\n\nStatus Code: {e.status_code}\nDetails: {e.detail}"
1791
+ )]
1792
+ except Exception as e:
1793
+ logger.error(f"Unexpected error scanning local filesystem: {e}")
1794
+ return [TextContent(
1795
+ type="text",
1796
+ text=f"❌ Error: An unexpected error occurred while scanning: {str(e)}"
1797
+ )]
1798
+
1799
+ @mcp.tool()
1800
+ async def check_local_filesystem_status(source_id: str) -> List[TextContent]:
1801
+ """
1802
+ Check the indexing status of a local filesystem source.
1803
+
1804
+ Args:
1805
+ source_id: The source ID returned when indexing was started
1806
+
1807
+ Returns:
1808
+ Current status of the local filesystem indexing
1809
+ """
1810
+ try:
1811
+ client = await ensure_api_client()
1812
+ status = await client.check_local_filesystem_status(source_id)
1813
+
1814
+ # Format status response
1815
+ status_text = status.get("status", "unknown")
1816
+ progress = status.get("progress", 0)
1817
+ message = status.get("message", "")
1818
+ error = status.get("error")
1819
+ directory_path = status.get("directory_path", "Unknown")
1820
+ page_count = status.get("page_count", 0) # Number of files
1821
+ chunk_count = status.get("chunk_count", 0)
1822
+
1823
+ # Status emoji
1824
+ status_emoji = {
1825
+ "pending": "⏳",
1826
+ "processing": "🔄",
1827
+ "completed": "✅",
1828
+ "failed": "❌",
1829
+ "error": "❌"
1830
+ }.get(status_text, "❓")
1831
+
1832
+ response = f"{status_emoji} **Local Filesystem Status**\n\n"
1833
+ response += f"🆔 **Source ID:** `{source_id}`\n"
1834
+ response += f"📁 **Directory:** `{directory_path}`\n"
1835
+ response += f"📊 **Status:** {status_text.capitalize()}\n"
1836
+
1837
+ if progress > 0:
1838
+ response += f"📈 **Progress:** {progress}%\n"
1839
+
1840
+ if message:
1841
+ response += f"💬 **Message:** {message}\n"
1842
+
1843
+ if status_text == "completed":
1844
+ response += f"\n✨ **Indexing Complete!**\n"
1845
+ response += f"• **Files Indexed:** {page_count:,}\n"
1846
+ response += f"• **Chunks Created:** {chunk_count:,}\n"
1847
+ response += f"\nYou can now search this directory using `search_codebase` or the unified search!"
1848
+ elif status_text in ["failed", "error"]:
1849
+ response += f"\n❌ **Indexing Failed**\n"
1850
+ if error:
1851
+ response += f"**Error:** {error}\n"
1852
+ response += "\nPlease check your directory path and try again."
1853
+ elif status_text == "processing":
1854
+ response += f"\n🔄 Indexing is in progress...\n"
1855
+ response += "Check back in a few moments or monitor at [app.trynia.ai](https://app.trynia.ai)"
1856
+
1857
+ return [TextContent(type="text", text=response)]
1858
+
1859
+ except APIError as e:
1860
+ logger.error(f"API error checking local filesystem status: {e}")
1861
+ if e.status_code == 404:
1862
+ return [TextContent(
1863
+ type="text",
1864
+ text=f"❌ Source ID `{source_id}` not found. Please check the ID and try again."
1865
+ )]
1866
+ return [TextContent(
1867
+ type="text",
1868
+ text=f"❌ API Error: {str(e)}\n\nStatus Code: {e.status_code}\nDetails: {e.detail}"
1869
+ )]
1870
+ except Exception as e:
1871
+ logger.error(f"Unexpected error checking local filesystem status: {e}")
1872
+ return [TextContent(
1873
+ type="text",
1874
+ text=f"❌ Error: An unexpected error occurred: {str(e)}"
1875
+ )]
1876
+
1877
+ @mcp.tool()
1878
+ async def search_local_filesystem(
1879
+ source_id: str,
1880
+ query: str,
1881
+ include_sources: bool = True
1882
+ ) -> List[TextContent]:
1883
+ """
1884
+ Search an indexed local filesystem directory using its source ID.
1885
+
1886
+ To search local files:
1887
+ 1. First index a directory using `index_local_filesystem` - this will return a source_id
1888
+ 2. Use that source_id with this tool to search the indexed content
1889
+
1890
+ Args:
1891
+ source_id: The source ID returned when the directory was indexed (required)
1892
+ query: Your search query in natural language (required)
1893
+ include_sources: Whether to include source code snippets in results (default: True)
1894
+
1895
+ Returns:
1896
+ Search results with relevant file snippets and explanations
1897
+
1898
+ Example:
1899
+ # After indexing returns source_id "abc123-def456"
1900
+ search_local_filesystem(
1901
+ source_id="abc123-def456",
1902
+ query="configuration settings"
1903
+ )
1904
+
1905
+ Note: To find your source IDs, use `list_documentation` and look for
1906
+ sources with source_type="local_filesystem"
1907
+ """
1908
+ try:
1909
+ # Validate inputs
1910
+ if not source_id:
1911
+ return [TextContent(
1912
+ type="text",
1913
+ text="❌ Error: 'source_id' parameter is required. Use the ID returned from index_local_filesystem."
1914
+ )]
1915
+
1916
+ if not query:
1917
+ return [TextContent(
1918
+ type="text",
1919
+ text="❌ Error: 'query' parameter is required"
1920
+ )]
1921
+
1922
+ client = await ensure_api_client()
1923
+
1924
+ # Check if the source exists and is ready
1925
+ logger.info(f"Checking status of source {source_id}")
1926
+ try:
1927
+ status = await client.get_data_source_status(source_id)
1928
+ if not status:
1929
+ return [TextContent(
1930
+ type="text",
1931
+ text=f"❌ Source ID '{source_id}' not found. Please check the ID and try again."
1932
+ )]
1933
+
1934
+ source_status = status.get("status", "unknown")
1935
+ if source_status == "processing":
1936
+ progress = status.get("progress", 0)
1937
+ return [TextContent(
1938
+ type="text",
1939
+ text=f"⏳ This source is still being indexed ({progress}% complete).\n\n"
1940
+ f"Use `check_local_filesystem_status(\"{source_id}\")` to check progress."
1941
+ )]
1942
+ elif source_status == "failed":
1943
+ error = status.get("error", "Unknown error")
1944
+ return [TextContent(
1945
+ type="text",
1946
+ text=f"❌ This source failed to index.\n\nError: {error}"
1947
+ )]
1948
+ elif source_status != "completed":
1949
+ return [TextContent(
1950
+ type="text",
1951
+ text=f"❌ Source is not ready for search. Status: {source_status}"
1952
+ )]
1953
+ except Exception as e:
1954
+ logger.warning(f"Could not check source status: {e}")
1955
+ # Continue anyway in case it's just a status check issue
1956
+
1957
+ # Perform the search
1958
+ logger.info(f"Searching local filesystem source {source_id} with query: {query}")
1959
+
1960
+ # Use the unified query endpoint with data_sources parameter
1961
+ result = client.query_unified(
1962
+ messages=[{"role": "user", "content": query}],
1963
+ data_sources=[source_id],
1964
+ include_sources=include_sources,
1965
+ stream=False
1966
+ )
1967
+
1968
+ # Parse the response
1969
+ response_text = ""
1970
+ async for chunk in result:
1971
+ data = json.loads(chunk)
1972
+ if "content" in data:
1973
+ response_text = data["content"]
1974
+ sources = data.get("sources", [])
1975
+ break
1976
+
1977
+ # Format the response nicely for local filesystem results
1978
+ if response_text:
1979
+ # Extract the local filesystem results section if present
1980
+ if "**Local filesystem results" in response_text:
1981
+ # Keep the original response
1982
+ formatted_response = response_text
1983
+ else:
1984
+ # Create our own formatted response
1985
+ formatted_response = f"🔍 **Search Results for Local Directory**\n"
1986
+ formatted_response += f"🔎 Query: \"{query}\"\n\n"
1987
+ formatted_response += response_text
1988
+
1989
+ # Add sources if available and requested
1990
+ if include_sources and sources:
1991
+ formatted_response += "\n\n**📄 Source Details:**\n"
1992
+ for i, source in enumerate(sources[:5], 1):
1993
+ metadata = source.get("metadata", {})
1994
+ file_path = metadata.get("file_path", "Unknown file")
1995
+ formatted_response += f"\n{i}. `{file_path}`\n"
1996
+
1997
+ # Add snippet of content
1998
+ content = source.get("content", "")
1999
+ if content:
2000
+ # Truncate to reasonable length
2001
+ lines = content.split('\n')[:10]
2002
+ snippet = '\n'.join(lines)
2003
+ if len(lines) > 10:
2004
+ snippet += "\n..."
2005
+ formatted_response += f"```\n{snippet}\n```\n"
2006
+
2007
+ return [TextContent(type="text", text=formatted_response)]
2008
+ else:
2009
+ return [TextContent(
2010
+ type="text",
2011
+ text=f"No results found for query: \"{query}\" in the indexed directory."
2012
+ )]
2013
+
2014
+ except APIError as e:
2015
+ logger.error(f"API error searching local filesystem: {e}")
2016
+ return [TextContent(
2017
+ type="text",
2018
+ text=f"❌ API Error: {str(e)}\n\nStatus Code: {e.status_code}\nDetails: {e.detail}"
2019
+ )]
2020
+ except Exception as e:
2021
+ logger.error(f"Unexpected error searching local filesystem: {e}")
2022
+ return [TextContent(
2023
+ type="text",
2024
+ text=f"❌ Error: An unexpected error occurred: {str(e)}"
2025
+ )]
2026
+
1625
2027
  @mcp.tool()
1626
2028
  async def visualize_codebase(
1627
2029
  repository: str
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nia-mcp-server
3
- Version: 1.0.16
3
+ Version: 1.0.17
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=o1sbmg9E91Ai4_OVbf6uHc4n-0QzsJZpfCxhON3U7Zk,85
1
+ nia_mcp_server/__init__.py,sha256=Vey2MprReAMtBucCOwDlS0ZmshGrAJ0IJ1RV6BTFT50,85
2
2
  nia_mcp_server/__main__.py,sha256=YQSpFtDeKp18r8mKr084cHnRFV4416_EKCu9FTM8_ik,394
3
- nia_mcp_server/api_client.py,sha256=KlzGDebSZEMC4ikrk5dtX6HWJwKU5iUU0zRqM0AyvP0,27646
3
+ nia_mcp_server/api_client.py,sha256=L9xf7rz6i2aPKKLfYOwj8Fs0_SYqJHHZgTki0y3UtcY,30415
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=IgScr-xiiVuRo8UqQgCMzxjAFT8SHssktaGChCaaj5I,77855
8
+ nia_mcp_server/server.py,sha256=hdn81qwTR_zPvOsO4wnIs7jI3HzYHvmzgKKs9QX_7-Y,94731
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.16.dist-info/METADATA,sha256=zXKq6Nlrklk02Fr_BXDB8SrS85FnsKtE1x8sVqqtrWg,1324
16
- nia_mcp_server-1.0.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
- nia_mcp_server-1.0.16.dist-info/entry_points.txt,sha256=V74FQEp48pfWxPCl7B9mihtqvIJNVjCSbRfCz4ww77I,64
18
- nia_mcp_server-1.0.16.dist-info/licenses/LICENSE,sha256=IrdVKi3bsiB2MTLM26MltBRpwyNi-8P6Cy0EnmAN76A,1557
19
- nia_mcp_server-1.0.16.dist-info/RECORD,,
15
+ nia_mcp_server-1.0.17.dist-info/METADATA,sha256=FRAGfMUlSLv3AOkry3a6Blb0LffzGze_R9nfnJq54R4,1324
16
+ nia_mcp_server-1.0.17.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ nia_mcp_server-1.0.17.dist-info/entry_points.txt,sha256=V74FQEp48pfWxPCl7B9mihtqvIJNVjCSbRfCz4ww77I,64
18
+ nia_mcp_server-1.0.17.dist-info/licenses/LICENSE,sha256=IrdVKi3bsiB2MTLM26MltBRpwyNi-8P6Cy0EnmAN76A,1557
19
+ nia_mcp_server-1.0.17.dist-info/RECORD,,