napistu 0.2.5.dev5__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.
Files changed (104) hide show
  1. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/PKG-INFO +1 -1
  2. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/setup.cfg +1 -1
  3. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/codebase.py +5 -13
  4. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/documentation.py +1 -1
  5. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/execution.py +3 -3
  6. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/health.py +2 -2
  7. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/server.py +1 -2
  8. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/tutorials.py +1 -1
  9. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu.egg-info/PKG-INFO +1 -1
  10. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu.egg-info/SOURCES.txt +1 -0
  11. napistu-0.2.5.dev7/src/tests/test_mcp_server.py +219 -0
  12. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/LICENSE +0 -0
  13. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/README.md +0 -0
  14. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/pyproject.toml +0 -0
  15. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/setup.py +0 -0
  16. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/__init__.py +0 -0
  17. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/__main__.py +0 -0
  18. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/consensus.py +0 -0
  19. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/constants.py +0 -0
  20. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/gcs/__init__.py +0 -0
  21. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/gcs/constants.py +0 -0
  22. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/gcs/downloads.py +0 -0
  23. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/gcs/utils.py +0 -0
  24. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/identifiers.py +0 -0
  25. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/indices.py +0 -0
  26. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/__init__.py +0 -0
  27. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/bigg.py +0 -0
  28. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/constants.py +0 -0
  29. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/cpr_edgelist.py +0 -0
  30. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/identifiers_etl.py +0 -0
  31. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/obo.py +0 -0
  32. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/psi_mi.py +0 -0
  33. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/reactome.py +0 -0
  34. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/sbml.py +0 -0
  35. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/string.py +0 -0
  36. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/trrust.py +0 -0
  37. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/ingestion/yeast.py +0 -0
  38. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/__init__.py +0 -0
  39. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/__main__.py +0 -0
  40. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/client.py +0 -0
  41. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/codebase_utils.py +0 -0
  42. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/constants.py +0 -0
  43. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/documentation_utils.py +0 -0
  44. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/profiles.py +0 -0
  45. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/tutorials_utils.py +0 -0
  46. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mcp/utils.py +0 -0
  47. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/mechanism_matching.py +0 -0
  48. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/modify/__init__.py +0 -0
  49. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/modify/constants.py +0 -0
  50. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/modify/curation.py +0 -0
  51. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/modify/gaps.py +0 -0
  52. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/modify/pathwayannot.py +0 -0
  53. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/modify/uncompartmentalize.py +0 -0
  54. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/network/__init__.py +0 -0
  55. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/network/constants.py +0 -0
  56. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/network/neighborhoods.py +0 -0
  57. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/network/net_create.py +0 -0
  58. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/network/net_propagation.py +0 -0
  59. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/network/net_utils.py +0 -0
  60. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/network/paths.py +0 -0
  61. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/network/precompute.py +0 -0
  62. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/rpy2/__init__.py +0 -0
  63. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/rpy2/callr.py +0 -0
  64. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/rpy2/constants.py +0 -0
  65. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/rpy2/netcontextr.py +0 -0
  66. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/rpy2/rids.py +0 -0
  67. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/sbml_dfs_core.py +0 -0
  68. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/sbml_dfs_utils.py +0 -0
  69. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/source.py +0 -0
  70. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu/utils.py +0 -0
  71. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu.egg-info/dependency_links.txt +0 -0
  72. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu.egg-info/entry_points.txt +0 -0
  73. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu.egg-info/requires.txt +0 -0
  74. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/napistu.egg-info/top_level.txt +0 -0
  75. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/__init__.py +0 -0
  76. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/conftest.py +0 -0
  77. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_consensus.py +0 -0
  78. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_constants.py +0 -0
  79. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_curation.py +0 -0
  80. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_data/__init__.py +0 -0
  81. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_edgelist.py +0 -0
  82. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_gaps.py +0 -0
  83. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_gcs.py +0 -0
  84. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_identifiers.py +0 -0
  85. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_igraph.py +0 -0
  86. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_indices.py +0 -0
  87. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_mcp_documentation_utils.py +0 -0
  88. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_mechanism_matching.py +0 -0
  89. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_net_propagation.py +0 -0
  90. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_net_utils.py +0 -0
  91. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_netcontextr.py +0 -0
  92. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_obo.py +0 -0
  93. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_pathwayannot.py +0 -0
  94. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_precomputed_distances.py +0 -0
  95. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_rpy2.py +0 -0
  96. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_sbml.py +0 -0
  97. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_sbml_dfs_core.py +0 -0
  98. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_sbml_dfs_utils.py +0 -0
  99. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_sbo.py +0 -0
  100. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_set_coverage.py +0 -0
  101. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_source.py +0 -0
  102. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_uncompartmentalize.py +0 -0
  103. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/test_utils.py +0 -0
  104. {napistu-0.2.5.dev5 → napistu-0.2.5.dev7}/src/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: napistu
3
- Version: 0.2.5.dev5
3
+ Version: 0.2.5.dev7
4
4
  Summary: Connecting high-dimensional data to curated pathways
5
5
  Home-page: https://github.com/napistu/napistu-py
6
6
  Author: Sean Hackett
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = napistu
3
- version = 0.2.5.dev5
3
+ version = 0.2.5.dev7
4
4
  description = Connecting high-dimensional data to curated pathways
5
5
  long_description = file: README.md
6
6
  long_description_content_type = text/markdown
@@ -45,7 +45,7 @@ async def initialize_components() -> bool:
45
45
 
46
46
  def register_components(mcp: FastMCP):
47
47
  """
48
- Register codebase exploration components with the MCP server.
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() -> Dict[str, Any]:
57
+ async def get_codebase_summary():
58
58
  """
59
- Get a summary of the Napistu codebase structure.
59
+ Get a summary of all available codebase information.
60
60
  """
61
61
  return {
62
62
  "modules": list(_codebase_cache["modules"].keys()),
63
- "top_level_classes": [
64
- class_name
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("search_documentation")
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-local://registry")
66
- async def get_registry_summary() -> Dict[str, Any]:
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-local://environment")
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("napistu://health/check")
39
- async def check_current_health() -> Dict[str, Any]:
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.
@@ -188,5 +188,4 @@ def start_mcp_server(
188
188
  logger.info("🚀 Starting MCP server...")
189
189
  logger.info(f"Using HTTP transport on http://{env_host}:{env_port}")
190
190
 
191
- # Simple, standard FastMCP run - no custom parameters
192
- mcp.run(transport="streamable-http", host=env_host, port=env_port)
191
+ mcp.run(transport="streamable-http")
@@ -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 get_tutorial_index() -> List[Dict[str, Any]]:
53
+ async def get_tutorials_index() -> List[Dict[str, Any]]:
54
54
  """
55
55
  Get the index of all available tutorials.
56
56
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: napistu
3
- Version: 0.2.5.dev5
3
+ Version: 0.2.5.dev7
4
4
  Summary: Connecting high-dimensional data to curated pathways
5
5
  Home-page: https://github.com/napistu/napistu-py
6
6
  Author: Sean Hackett
@@ -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