nia-mcp-server 1.0.18__tar.gz → 1.0.21__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.

Files changed (22) hide show
  1. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/PKG-INFO +1 -1
  2. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/pyproject.toml +1 -1
  3. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/__init__.py +1 -1
  4. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/api_client.py +137 -8
  5. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/server.py +1194 -403
  6. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/.gitignore +0 -0
  7. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/ARCHITECTURE.md +0 -0
  8. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/LICENSE +0 -0
  9. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/README.md +0 -0
  10. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/nia_analytics.log +0 -0
  11. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/nia_mcp_server.log +0 -0
  12. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/__main__.py +0 -0
  13. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/assets/rules/claude_rules.md +0 -0
  14. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/assets/rules/cursor_rules.md +0 -0
  15. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/assets/rules/nia_rules.md +0 -0
  16. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/assets/rules/vscode_rules.md +0 -0
  17. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/assets/rules/windsurf_rules.md +0 -0
  18. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/cli.py +0 -0
  19. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/profiles.py +0 -0
  20. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/project_init.py +0 -0
  21. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/rule_transformer.py +0 -0
  22. {nia_mcp_server-1.0.18 → nia_mcp_server-1.0.21}/src/nia_mcp_server/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nia-mcp-server
3
- Version: 1.0.18
3
+ Version: 1.0.21
4
4
  Summary: Nia Knowledge Agent
5
5
  Project-URL: Homepage, https://trynia.ai
6
6
  Project-URL: Documentation, https://docs.trynia.ai
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "nia-mcp-server"
7
- version = "1.0.18"
7
+ version = "1.0.21"
8
8
  description = "Nia Knowledge Agent"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -2,4 +2,4 @@
2
2
  NIA MCP Server - Proxy server for NIA Knowledge Agent
3
3
  """
4
4
 
5
- __version__ = "1.0.18"
5
+ __version__ = "1.0.21"
@@ -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.0",
31
+ "User-Agent": "nia-mcp-server/1.0.21",
32
32
  "Content-Type": "application/json"
33
33
  },
34
34
  timeout=720.0 # 12 minute timeout for deep research operations
@@ -552,15 +552,23 @@ class NIAApiClient:
552
552
  for repo in repositories:
553
553
  repo_list.append({"repository": repo})
554
554
 
555
- # Build data source list
555
+ # Build data source list
556
556
  source_list = []
557
557
  if data_sources:
558
- for source_id in data_sources:
559
- # Handle both list of IDs and list of dicts
560
- if isinstance(source_id, dict):
561
- source_list.append(source_id)
558
+ for source in data_sources:
559
+ # Handle flexible identifier formats:
560
+ # 1. String directly (display_name, URL, or source_id) - NEW
561
+ # 2. Dict with "source_id" (backwards compatible)
562
+ # 3. Dict with "identifier" (new format)
563
+ if isinstance(source, str):
564
+ # Pass string directly - backend will resolve it
565
+ source_list.append(source)
566
+ elif isinstance(source, dict):
567
+ # Keep dict format as-is (backwards compatible)
568
+ source_list.append(source)
562
569
  else:
563
- source_list.append({"source_id": source_id})
570
+ # Convert other types to string
571
+ source_list.append(str(source))
564
572
 
565
573
  # Validate at least one source
566
574
  if not repo_list and not source_list:
@@ -758,4 +766,125 @@ class NIAApiClient:
758
766
  except httpx.HTTPStatusError as e:
759
767
  raise self._handle_api_error(e)
760
768
  except Exception as e:
761
- raise APIError(f"Failed to check local filesystem status: {str(e)}")
769
+ raise APIError(f"Failed to check local filesystem status: {str(e)}")
770
+
771
+ # ========================================================================
772
+ # CHROMA PACKAGE SEARCH METHODS
773
+ # ========================================================================
774
+
775
+ async def package_search_grep(
776
+ self,
777
+ registry: str,
778
+ package_name: str,
779
+ pattern: str,
780
+ version: Optional[str] = None,
781
+ language: Optional[str] = None,
782
+ filename_sha256: Optional[str] = None,
783
+ a: Optional[int] = None,
784
+ b: Optional[int] = None,
785
+ c: Optional[int] = None,
786
+ head_limit: Optional[int] = None,
787
+ output_mode: str = "content"
788
+ ) -> Dict[str, Any]:
789
+ """Execute grep search on package source code via Chroma."""
790
+ try:
791
+ payload = {
792
+ "registry": registry,
793
+ "package_name": package_name,
794
+ "pattern": pattern,
795
+ "version": version,
796
+ "language": language,
797
+ "filename_sha256": filename_sha256,
798
+ "a": a,
799
+ "b": b,
800
+ "c": c,
801
+ "head_limit": head_limit,
802
+ "output_mode": output_mode
803
+ }
804
+
805
+ # Remove None values
806
+ payload = {k: v for k, v in payload.items() if v is not None}
807
+
808
+ response = await self.client.post(
809
+ f"{self.base_url}/v2/package-search/grep",
810
+ json=payload
811
+ )
812
+ response.raise_for_status()
813
+ return response.json()
814
+
815
+ except httpx.HTTPStatusError as e:
816
+ raise self._handle_api_error(e)
817
+ except Exception as e:
818
+ raise APIError(f"Failed to search package with grep: {str(e)}")
819
+
820
+ async def package_search_hybrid(
821
+ self,
822
+ registry: str,
823
+ package_name: str,
824
+ semantic_queries: List[str],
825
+ version: Optional[str] = None,
826
+ filename_sha256: Optional[str] = None,
827
+ pattern: Optional[str] = None,
828
+ language: Optional[str] = None
829
+ ) -> Dict[str, Any]:
830
+ """Execute hybrid semantic search on package source code via Chroma."""
831
+ try:
832
+ payload = {
833
+ "registry": registry,
834
+ "package_name": package_name,
835
+ "semantic_queries": semantic_queries,
836
+ "version": version,
837
+ "filename_sha256": filename_sha256,
838
+ "pattern": pattern,
839
+ "language": language
840
+ }
841
+
842
+ # Remove None values
843
+ payload = {k: v for k, v in payload.items() if v is not None}
844
+
845
+ response = await self.client.post(
846
+ f"{self.base_url}/v2/package-search/hybrid",
847
+ json=payload
848
+ )
849
+ response.raise_for_status()
850
+ return response.json()
851
+
852
+ except httpx.HTTPStatusError as e:
853
+ raise self._handle_api_error(e)
854
+ except Exception as e:
855
+ raise APIError(f"Failed to search package with hybrid search: {str(e)}")
856
+
857
+ async def package_search_read_file(
858
+ self,
859
+ registry: str,
860
+ package_name: str,
861
+ filename_sha256: str,
862
+ start_line: int,
863
+ end_line: int,
864
+ version: Optional[str] = None
865
+ ) -> Dict[str, Any]:
866
+ """Read specific lines from a package file via Chroma."""
867
+ try:
868
+ payload = {
869
+ "registry": registry,
870
+ "package_name": package_name,
871
+ "filename_sha256": filename_sha256,
872
+ "start_line": start_line,
873
+ "end_line": end_line,
874
+ "version": version
875
+ }
876
+
877
+ # Remove None values
878
+ payload = {k: v for k, v in payload.items() if v is not None}
879
+
880
+ response = await self.client.post(
881
+ f"{self.base_url}/v2/package-search/read-file",
882
+ json=payload
883
+ )
884
+ response.raise_for_status()
885
+ return response.json()
886
+
887
+ except httpx.HTTPStatusError as e:
888
+ raise self._handle_api_error(e)
889
+ except Exception as e:
890
+ raise APIError(f"Failed to read package file: {str(e)}")