napistu 0.2.5.dev6__tar.gz → 0.2.5.dev7__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.
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/PKG-INFO +1 -1
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/setup.cfg +1 -1
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/codebase.py +5 -13
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/documentation.py +1 -1
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/execution.py +3 -3
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/health.py +2 -2
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/tutorials.py +1 -1
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu.egg-info/PKG-INFO +1 -1
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu.egg-info/SOURCES.txt +1 -0
- napistu-0.2.5.dev7/src/tests/test_mcp_server.py +219 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/LICENSE +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/README.md +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/pyproject.toml +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/setup.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/__main__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/consensus.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/constants.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/gcs/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/gcs/constants.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/gcs/downloads.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/gcs/utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/identifiers.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/indices.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/bigg.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/constants.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/cpr_edgelist.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/identifiers_etl.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/obo.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/psi_mi.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/reactome.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/sbml.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/string.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/trrust.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/ingestion/yeast.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/__main__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/client.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/codebase_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/constants.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/documentation_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/profiles.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/server.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/tutorials_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mcp/utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/mechanism_matching.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/modify/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/modify/constants.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/modify/curation.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/modify/gaps.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/modify/pathwayannot.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/modify/uncompartmentalize.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/network/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/network/constants.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/network/neighborhoods.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/network/net_create.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/network/net_propagation.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/network/net_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/network/paths.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/network/precompute.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/rpy2/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/rpy2/callr.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/rpy2/constants.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/rpy2/netcontextr.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/rpy2/rids.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/sbml_dfs_core.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/sbml_dfs_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/source.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu/utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu.egg-info/dependency_links.txt +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu.egg-info/entry_points.txt +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu.egg-info/requires.txt +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/napistu.egg-info/top_level.txt +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/conftest.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_consensus.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_constants.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_curation.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_data/__init__.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_edgelist.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_gaps.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_gcs.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_identifiers.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_igraph.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_indices.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_mcp_documentation_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_mechanism_matching.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_net_propagation.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_net_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_netcontextr.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_obo.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_pathwayannot.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_precomputed_distances.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_rpy2.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_sbml.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_sbml_dfs_core.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_sbml_dfs_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_sbo.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_set_coverage.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_source.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_uncompartmentalize.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/test_utils.py +0 -0
- {napistu-0.2.5.dev6 → napistu-0.2.5.dev7}/src/tests/utils.py +0 -0
@@ -45,7 +45,7 @@ async def initialize_components() -> bool:
|
|
45
45
|
|
46
46
|
def register_components(mcp: FastMCP):
|
47
47
|
"""
|
48
|
-
Register codebase
|
48
|
+
Register codebase components with the MCP server.
|
49
49
|
|
50
50
|
Args:
|
51
51
|
mcp: FastMCP server instance
|
@@ -54,22 +54,14 @@ def register_components(mcp: FastMCP):
|
|
54
54
|
|
55
55
|
# Register resources
|
56
56
|
@mcp.resource("napistu://codebase/summary")
|
57
|
-
async def get_codebase_summary()
|
57
|
+
async def get_codebase_summary():
|
58
58
|
"""
|
59
|
-
Get a summary of
|
59
|
+
Get a summary of all available codebase information.
|
60
60
|
"""
|
61
61
|
return {
|
62
62
|
"modules": list(_codebase_cache["modules"].keys()),
|
63
|
-
"
|
64
|
-
|
65
|
-
for class_name, info in _codebase_cache["classes"].items()
|
66
|
-
if "." not in class_name # Only include top-level classes
|
67
|
-
],
|
68
|
-
"top_level_functions": [
|
69
|
-
func_name
|
70
|
-
for func_name, info in _codebase_cache["functions"].items()
|
71
|
-
if "." not in func_name # Only include top-level functions
|
72
|
-
],
|
63
|
+
"classes": list(_codebase_cache["classes"].keys()),
|
64
|
+
"functions": list(_codebase_cache["functions"].keys()),
|
73
65
|
}
|
74
66
|
|
75
67
|
@mcp.resource("napistu://codebase/modules/{module_name}")
|
@@ -136,7 +136,7 @@ def register_components(mcp: FastMCP):
|
|
136
136
|
return await documentation_utils.get_issue(repo, number)
|
137
137
|
|
138
138
|
# Register tools
|
139
|
-
@mcp.tool(
|
139
|
+
@mcp.tool()
|
140
140
|
async def search_documentation(query: str):
|
141
141
|
"""
|
142
142
|
Search all documentation for a specific query.
|
@@ -62,8 +62,8 @@ def register_components(mcp, session_context=None, object_registry=None):
|
|
62
62
|
_session_context["napistu"] = napistu
|
63
63
|
|
64
64
|
# Register resources
|
65
|
-
@mcp.resource("napistu
|
66
|
-
async def
|
65
|
+
@mcp.resource("napistu://execution/registry")
|
66
|
+
async def get_registry():
|
67
67
|
"""
|
68
68
|
Get a summary of all objects registered with the server.
|
69
69
|
"""
|
@@ -75,7 +75,7 @@ def register_components(mcp, session_context=None, object_registry=None):
|
|
75
75
|
},
|
76
76
|
}
|
77
77
|
|
78
|
-
@mcp.resource("napistu
|
78
|
+
@mcp.resource("napistu://execution/environment")
|
79
79
|
async def get_environment_info() -> Dict[str, Any]:
|
80
80
|
"""
|
81
81
|
Get information about the local Python environment.
|
@@ -35,8 +35,8 @@ def register_components(mcp: FastMCP) -> None:
|
|
35
35
|
"""
|
36
36
|
return _health_cache
|
37
37
|
|
38
|
-
@mcp.tool(
|
39
|
-
async def
|
38
|
+
@mcp.tool()
|
39
|
+
async def check_health() -> Dict[str, Any]:
|
40
40
|
"""
|
41
41
|
Tool to actively check current component health.
|
42
42
|
This performs real-time checks and updates the cached status.
|
@@ -50,7 +50,7 @@ def register_components(mcp: FastMCP) -> None:
|
|
50
50
|
|
51
51
|
# Register resources
|
52
52
|
@mcp.resource("napistu://tutorials/index")
|
53
|
-
async def
|
53
|
+
async def get_tutorials_index() -> List[Dict[str, Any]]:
|
54
54
|
"""
|
55
55
|
Get the index of all available tutorials.
|
56
56
|
|
@@ -82,6 +82,7 @@ src/tests/test_identifiers.py
|
|
82
82
|
src/tests/test_igraph.py
|
83
83
|
src/tests/test_indices.py
|
84
84
|
src/tests/test_mcp_documentation_utils.py
|
85
|
+
src/tests/test_mcp_server.py
|
85
86
|
src/tests/test_mechanism_matching.py
|
86
87
|
src/tests/test_net_propagation.py
|
87
88
|
src/tests/test_net_utils.py
|
@@ -0,0 +1,219 @@
|
|
1
|
+
"""
|
2
|
+
Tests to validate MCP tool and resource naming conventions.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import re
|
6
|
+
from typing import List, Tuple
|
7
|
+
from fastmcp import FastMCP
|
8
|
+
|
9
|
+
from napistu.mcp import (
|
10
|
+
documentation,
|
11
|
+
codebase,
|
12
|
+
tutorials,
|
13
|
+
execution,
|
14
|
+
health,
|
15
|
+
)
|
16
|
+
|
17
|
+
# Regex patterns for validation
|
18
|
+
VALID_RESOURCE_PATH = re.compile(
|
19
|
+
r"^napistu://[a-zA-Z][a-zA-Z0-9_]*(?:/[a-zA-Z0-9_{}.-]+)*$"
|
20
|
+
)
|
21
|
+
VALID_TOOL_NAME = re.compile(r"^[a-zA-Z][a-zA-Z0-9_]*$")
|
22
|
+
|
23
|
+
|
24
|
+
def collect_resources_and_tools(mcp: FastMCP) -> Tuple[List[str], List[str]]:
|
25
|
+
"""
|
26
|
+
Collect all registered resource paths and tool names from an MCP server instance.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
mcp: FastMCP server instance
|
30
|
+
|
31
|
+
Returns:
|
32
|
+
Tuple of (resource_paths, tool_names)
|
33
|
+
"""
|
34
|
+
# Get all registered resources and tools
|
35
|
+
resources = mcp._resource_manager.get_resources()
|
36
|
+
tool_names = mcp._tool_manager.get_tools()
|
37
|
+
|
38
|
+
# Extract resource paths from the resource objects
|
39
|
+
resource_paths = []
|
40
|
+
|
41
|
+
# Add all resources (including parameterized ones)
|
42
|
+
for resource in resources.values():
|
43
|
+
resource_paths.append(str(resource.uri))
|
44
|
+
|
45
|
+
return resource_paths, tool_names
|
46
|
+
|
47
|
+
|
48
|
+
def test_documentation_naming():
|
49
|
+
"""Test that documentation component uses valid names."""
|
50
|
+
mcp = FastMCP("test")
|
51
|
+
documentation.register_components(mcp)
|
52
|
+
|
53
|
+
resource_paths, tool_names = collect_resources_and_tools(mcp)
|
54
|
+
|
55
|
+
# Check resource paths
|
56
|
+
for path in resource_paths:
|
57
|
+
assert VALID_RESOURCE_PATH.match(path), f"Invalid resource path: {path}"
|
58
|
+
|
59
|
+
# Check tool names
|
60
|
+
for name in tool_names:
|
61
|
+
assert VALID_TOOL_NAME.match(name), f"Invalid tool name: {name}"
|
62
|
+
|
63
|
+
|
64
|
+
def test_codebase_naming():
|
65
|
+
"""Test that codebase component uses valid names."""
|
66
|
+
mcp = FastMCP("test")
|
67
|
+
codebase.register_components(mcp)
|
68
|
+
|
69
|
+
resource_paths, tool_names = collect_resources_and_tools(mcp)
|
70
|
+
|
71
|
+
# Check resource paths
|
72
|
+
for path in resource_paths:
|
73
|
+
assert VALID_RESOURCE_PATH.match(path), f"Invalid resource path: {path}"
|
74
|
+
|
75
|
+
# Check tool names
|
76
|
+
for name in tool_names:
|
77
|
+
assert VALID_TOOL_NAME.match(name), f"Invalid tool name: {name}"
|
78
|
+
|
79
|
+
|
80
|
+
def test_tutorials_naming():
|
81
|
+
"""Test that tutorials component uses valid names."""
|
82
|
+
mcp = FastMCP("test")
|
83
|
+
tutorials.register_components(mcp)
|
84
|
+
|
85
|
+
resource_paths, tool_names = collect_resources_and_tools(mcp)
|
86
|
+
|
87
|
+
# Check resource paths
|
88
|
+
for path in resource_paths:
|
89
|
+
assert VALID_RESOURCE_PATH.match(path), f"Invalid resource path: {path}"
|
90
|
+
|
91
|
+
# Check tool names
|
92
|
+
for name in tool_names:
|
93
|
+
assert VALID_TOOL_NAME.match(name), f"Invalid tool name: {name}"
|
94
|
+
|
95
|
+
|
96
|
+
def test_execution_naming():
|
97
|
+
"""Test that execution component uses valid names."""
|
98
|
+
mcp = FastMCP("test")
|
99
|
+
execution.register_components(mcp)
|
100
|
+
|
101
|
+
resource_paths, tool_names = collect_resources_and_tools(mcp)
|
102
|
+
|
103
|
+
# Check resource paths
|
104
|
+
for path in resource_paths:
|
105
|
+
assert VALID_RESOURCE_PATH.match(path), f"Invalid resource path: {path}"
|
106
|
+
|
107
|
+
# Check tool names
|
108
|
+
for name in tool_names:
|
109
|
+
assert VALID_TOOL_NAME.match(name), f"Invalid tool name: {name}"
|
110
|
+
|
111
|
+
|
112
|
+
def test_health_naming():
|
113
|
+
"""Test that health component uses valid names."""
|
114
|
+
mcp = FastMCP("test")
|
115
|
+
health.register_components(mcp)
|
116
|
+
|
117
|
+
resource_paths, tool_names = collect_resources_and_tools(mcp)
|
118
|
+
|
119
|
+
# Check resource paths
|
120
|
+
for path in resource_paths:
|
121
|
+
assert VALID_RESOURCE_PATH.match(path), f"Invalid resource path: {path}"
|
122
|
+
|
123
|
+
# Check tool names
|
124
|
+
for name in tool_names:
|
125
|
+
assert VALID_TOOL_NAME.match(name), f"Invalid tool name: {name}"
|
126
|
+
|
127
|
+
|
128
|
+
def test_all_components_naming():
|
129
|
+
"""Test that all components together use valid names without conflicts."""
|
130
|
+
mcp = FastMCP("test")
|
131
|
+
|
132
|
+
# Register all components
|
133
|
+
documentation.register_components(mcp)
|
134
|
+
codebase.register_components(mcp)
|
135
|
+
tutorials.register_components(mcp)
|
136
|
+
execution.register_components(mcp)
|
137
|
+
health.register_components(mcp)
|
138
|
+
|
139
|
+
resource_paths, tool_names = collect_resources_and_tools(mcp)
|
140
|
+
|
141
|
+
# Check for duplicate resource paths
|
142
|
+
path_counts = {}
|
143
|
+
for path in resource_paths:
|
144
|
+
assert VALID_RESOURCE_PATH.match(path), f"Invalid resource path: {path}"
|
145
|
+
path_counts[path] = path_counts.get(path, 0) + 1
|
146
|
+
assert path_counts[path] == 1, f"Duplicate resource path: {path}"
|
147
|
+
|
148
|
+
# Check for duplicate tool names
|
149
|
+
name_counts = {}
|
150
|
+
for name in tool_names:
|
151
|
+
assert VALID_TOOL_NAME.match(name), f"Invalid tool name: {name}"
|
152
|
+
name_counts[name] = name_counts.get(name, 0) + 1
|
153
|
+
assert name_counts[name] == 1, f"Duplicate tool name: {name}"
|
154
|
+
|
155
|
+
|
156
|
+
def test_expected_resources_exist():
|
157
|
+
"""Test that all expected resources are registered."""
|
158
|
+
mcp = FastMCP("test")
|
159
|
+
|
160
|
+
# Register all components
|
161
|
+
documentation.register_components(mcp)
|
162
|
+
codebase.register_components(mcp)
|
163
|
+
tutorials.register_components(mcp)
|
164
|
+
execution.register_components(mcp)
|
165
|
+
health.register_components(mcp)
|
166
|
+
|
167
|
+
resource_paths, _ = collect_resources_and_tools(mcp)
|
168
|
+
|
169
|
+
# Debug: Print all registered resources
|
170
|
+
print("\nRegistered resources:")
|
171
|
+
for path in sorted(resource_paths):
|
172
|
+
print(f" {path}")
|
173
|
+
print()
|
174
|
+
|
175
|
+
# List of expected base resources (no templates)
|
176
|
+
expected_resources = {
|
177
|
+
"napistu://documentation/summary",
|
178
|
+
"napistu://codebase/summary",
|
179
|
+
"napistu://tutorials/index",
|
180
|
+
"napistu://execution/registry",
|
181
|
+
"napistu://execution/environment",
|
182
|
+
"napistu://health",
|
183
|
+
}
|
184
|
+
|
185
|
+
# Check that each expected resource exists
|
186
|
+
for resource in expected_resources:
|
187
|
+
assert resource in resource_paths, f"Missing expected resource: {resource}"
|
188
|
+
|
189
|
+
|
190
|
+
def test_expected_tools_exist():
|
191
|
+
"""Test that all expected tools are registered."""
|
192
|
+
mcp = FastMCP("test")
|
193
|
+
|
194
|
+
# Register all components
|
195
|
+
documentation.register_components(mcp)
|
196
|
+
codebase.register_components(mcp)
|
197
|
+
tutorials.register_components(mcp)
|
198
|
+
execution.register_components(mcp)
|
199
|
+
health.register_components(mcp)
|
200
|
+
|
201
|
+
_, tool_names = collect_resources_and_tools(mcp)
|
202
|
+
|
203
|
+
# List of expected tools
|
204
|
+
expected_tools = {
|
205
|
+
"search_documentation",
|
206
|
+
"search_codebase",
|
207
|
+
"get_function_documentation",
|
208
|
+
"get_class_documentation",
|
209
|
+
"search_tutorials",
|
210
|
+
"list_registry",
|
211
|
+
"describe_object",
|
212
|
+
"execute_function",
|
213
|
+
"search_paths",
|
214
|
+
"check_health",
|
215
|
+
}
|
216
|
+
|
217
|
+
# Check that all expected tools exist
|
218
|
+
for tool in expected_tools:
|
219
|
+
assert tool in tool_names, f"Missing expected tool: {tool}"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|