nia-mcp-server 1.0.18__py3-none-any.whl → 1.0.20__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nia-mcp-server might be problematic. Click here for more details.
- nia_mcp_server/__init__.py +1 -1
- nia_mcp_server/api_client.py +137 -8
- nia_mcp_server/server.py +1196 -403
- {nia_mcp_server-1.0.18.dist-info → nia_mcp_server-1.0.20.dist-info}/METADATA +1 -1
- {nia_mcp_server-1.0.18.dist-info → nia_mcp_server-1.0.20.dist-info}/RECORD +8 -8
- {nia_mcp_server-1.0.18.dist-info → nia_mcp_server-1.0.20.dist-info}/WHEEL +0 -0
- {nia_mcp_server-1.0.18.dist-info → nia_mcp_server-1.0.20.dist-info}/entry_points.txt +0 -0
- {nia_mcp_server-1.0.18.dist-info → nia_mcp_server-1.0.20.dist-info}/licenses/LICENSE +0 -0
nia_mcp_server/__init__.py
CHANGED
nia_mcp_server/api_client.py
CHANGED
|
@@ -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.20",
|
|
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
|
|
559
|
-
# Handle
|
|
560
|
-
|
|
561
|
-
|
|
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
|
-
|
|
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)}")
|