napistu 0.2.5.dev7__py3-none-any.whl → 0.3.1.dev1__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.
Files changed (108) hide show
  1. napistu/__init__.py +1 -3
  2. napistu/__main__.py +126 -96
  3. napistu/constants.py +35 -41
  4. napistu/context/__init__.py +10 -0
  5. napistu/context/discretize.py +462 -0
  6. napistu/context/filtering.py +387 -0
  7. napistu/gcs/__init__.py +1 -1
  8. napistu/identifiers.py +74 -15
  9. napistu/indices.py +68 -0
  10. napistu/ingestion/__init__.py +1 -1
  11. napistu/ingestion/bigg.py +47 -62
  12. napistu/ingestion/constants.py +18 -133
  13. napistu/ingestion/gtex.py +113 -0
  14. napistu/ingestion/hpa.py +147 -0
  15. napistu/ingestion/sbml.py +0 -97
  16. napistu/ingestion/string.py +2 -2
  17. napistu/matching/__init__.py +10 -0
  18. napistu/matching/constants.py +18 -0
  19. napistu/matching/interactions.py +518 -0
  20. napistu/matching/mount.py +529 -0
  21. napistu/matching/species.py +510 -0
  22. napistu/mcp/__init__.py +7 -4
  23. napistu/mcp/__main__.py +128 -72
  24. napistu/mcp/client.py +16 -25
  25. napistu/mcp/codebase.py +201 -145
  26. napistu/mcp/component_base.py +170 -0
  27. napistu/mcp/config.py +223 -0
  28. napistu/mcp/constants.py +45 -2
  29. napistu/mcp/documentation.py +253 -136
  30. napistu/mcp/documentation_utils.py +13 -48
  31. napistu/mcp/execution.py +372 -305
  32. napistu/mcp/health.py +47 -65
  33. napistu/mcp/profiles.py +10 -6
  34. napistu/mcp/server.py +161 -80
  35. napistu/mcp/tutorials.py +139 -87
  36. napistu/modify/__init__.py +1 -1
  37. napistu/modify/gaps.py +1 -1
  38. napistu/network/__init__.py +1 -1
  39. napistu/network/constants.py +101 -34
  40. napistu/network/data_handling.py +388 -0
  41. napistu/network/ig_utils.py +351 -0
  42. napistu/network/napistu_graph_core.py +354 -0
  43. napistu/network/neighborhoods.py +40 -40
  44. napistu/network/net_create.py +373 -309
  45. napistu/network/net_propagation.py +47 -19
  46. napistu/network/{net_utils.py → ng_utils.py} +124 -272
  47. napistu/network/paths.py +67 -51
  48. napistu/network/precompute.py +11 -11
  49. napistu/ontologies/__init__.py +10 -0
  50. napistu/ontologies/constants.py +129 -0
  51. napistu/ontologies/dogma.py +243 -0
  52. napistu/ontologies/genodexito.py +649 -0
  53. napistu/ontologies/mygene.py +369 -0
  54. napistu/ontologies/renaming.py +198 -0
  55. napistu/rpy2/__init__.py +229 -86
  56. napistu/rpy2/callr.py +47 -77
  57. napistu/rpy2/constants.py +24 -23
  58. napistu/rpy2/rids.py +61 -648
  59. napistu/sbml_dfs_core.py +587 -222
  60. napistu/scverse/__init__.py +15 -0
  61. napistu/scverse/constants.py +28 -0
  62. napistu/scverse/loading.py +727 -0
  63. napistu/utils.py +118 -10
  64. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/METADATA +8 -3
  65. napistu-0.3.1.dev1.dist-info/RECORD +133 -0
  66. tests/conftest.py +22 -0
  67. tests/test_context_discretize.py +56 -0
  68. tests/test_context_filtering.py +267 -0
  69. tests/test_identifiers.py +100 -0
  70. tests/test_indices.py +65 -0
  71. tests/{test_edgelist.py → test_ingestion_napistu_edgelist.py} +2 -2
  72. tests/test_matching_interactions.py +108 -0
  73. tests/test_matching_mount.py +305 -0
  74. tests/test_matching_species.py +394 -0
  75. tests/test_mcp_config.py +193 -0
  76. tests/test_mcp_documentation_utils.py +12 -3
  77. tests/test_mcp_server.py +156 -19
  78. tests/test_network_data_handling.py +397 -0
  79. tests/test_network_ig_utils.py +23 -0
  80. tests/test_network_neighborhoods.py +19 -0
  81. tests/test_network_net_create.py +459 -0
  82. tests/test_network_ng_utils.py +30 -0
  83. tests/test_network_paths.py +56 -0
  84. tests/{test_precomputed_distances.py → test_network_precompute.py} +8 -6
  85. tests/test_ontologies_genodexito.py +58 -0
  86. tests/test_ontologies_mygene.py +39 -0
  87. tests/test_ontologies_renaming.py +110 -0
  88. tests/test_rpy2_callr.py +79 -0
  89. tests/test_rpy2_init.py +151 -0
  90. tests/test_sbml.py +0 -31
  91. tests/test_sbml_dfs_core.py +134 -10
  92. tests/test_scverse_loading.py +778 -0
  93. tests/test_set_coverage.py +2 -2
  94. tests/test_utils.py +121 -1
  95. napistu/mechanism_matching.py +0 -1353
  96. napistu/rpy2/netcontextr.py +0 -467
  97. napistu-0.2.5.dev7.dist-info/RECORD +0 -98
  98. tests/test_igraph.py +0 -367
  99. tests/test_mechanism_matching.py +0 -784
  100. tests/test_net_utils.py +0 -149
  101. tests/test_netcontextr.py +0 -105
  102. tests/test_rpy2.py +0 -61
  103. /napistu/ingestion/{cpr_edgelist.py → napistu_edgelist.py} +0 -0
  104. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/WHEEL +0 -0
  105. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/entry_points.txt +0 -0
  106. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/licenses/LICENSE +0 -0
  107. {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/top_level.txt +0 -0
  108. /tests/{test_obo.py → test_ingestion_obo.py} +0 -0
napistu/mcp/health.py CHANGED
@@ -131,99 +131,81 @@ async def initialize_components() -> bool:
131
131
  return False
132
132
 
133
133
 
134
- def _check_component_health(
135
- component_name: str, module_name: str, cache_attr: str
136
- ) -> Dict[str, str]:
134
+ def _check_component_health(component_name: str, module_path: str) -> Dict[str, Any]:
137
135
  """
138
- Check the health of a single MCP component by verifying its cache is initialized and contains data.
136
+ Check the health of a single MCP component using the component class pattern.
139
137
 
140
138
  Parameters
141
139
  ----------
142
140
  component_name : str
143
- Name of the component (for importing)
144
- module_name : str
145
- Full module path for importing
146
- cache_attr : str
147
- Name of the cache/context attribute to check
141
+ Name of the component (for logging)
142
+ module_path : str
143
+ Full module path for importing the component
148
144
 
149
145
  Returns
150
146
  -------
151
- Dict[str, str]
152
- Dictionary containing component health status:
153
- - status : str
154
- One of: 'healthy', 'inactive', or 'unavailable'
155
- - error : str, optional
156
- Error message if status is 'unavailable'
147
+ Dict[str, Any]
148
+ Dictionary containing component health status from the component's state
157
149
  """
158
150
  try:
159
- module = __import__(module_name, fromlist=[component_name])
160
- cache = getattr(module, cache_attr, None)
161
- logger.info(
162
- f"Checking {component_name} health - Cache exists: {cache is not None}"
163
- )
164
-
165
- # Component specific checks for actual data
166
- if cache:
167
- if component_name == "documentation":
168
- # Check if any documentation section has content
169
- has_data = any(bool(section) for section in cache.values())
170
- logger.info(f"Documentation sections: {list(cache.keys())}")
171
- elif component_name == "codebase":
172
- # Check if any codebase section has content
173
- has_data = any(bool(section) for section in cache.values())
174
- logger.info(f"Codebase sections: {list(cache.keys())}")
175
- elif component_name == "tutorials":
176
- # Check if tutorials section has content
177
- has_data = bool(cache.get("tutorials", {}))
178
- logger.info(f"Tutorials cache: {bool(cache.get('tutorials', {}))}")
179
- elif component_name == "execution":
180
- # Check if session context has more than just napistu module
181
- has_data = len(cache) > 0
182
- logger.info(f"Execution context: {list(cache.keys())}")
183
- else:
184
- has_data = bool(cache)
185
-
186
- if has_data:
187
- logger.info(f"{component_name} is healthy")
188
- return {"status": "healthy"}
189
-
190
- logger.info(f"{component_name} is inactive")
191
- return {"status": "inactive"}
151
+ # Import the component module
152
+ module = __import__(module_path, fromlist=[component_name])
153
+
154
+ # Use the new component class pattern
155
+ if hasattr(module, "get_component"):
156
+ try:
157
+ component = module.get_component()
158
+ state = component.get_state()
159
+ health_status = state.get_health_status()
160
+ logger.info(f"{component_name} health: {health_status}")
161
+ return health_status
162
+ except RuntimeError as e:
163
+ # Handle execution component that might not be created yet
164
+ if "not created" in str(e):
165
+ logger.warning(f"{component_name} not initialized yet")
166
+ return {
167
+ "status": "initializing",
168
+ "message": "Component not created",
169
+ }
170
+ else:
171
+ raise
172
+ else:
173
+ # Component doesn't follow the new pattern
174
+ logger.warning(f"{component_name} doesn't use component class pattern")
175
+ return {"status": "unknown", "message": "Component using legacy pattern"}
176
+
177
+ except ImportError as e:
178
+ logger.error(f"Could not import {component_name}: {str(e)}")
179
+ return {"status": "unavailable", "error": f"Import failed: {str(e)}"}
192
180
  except Exception as e:
193
- logger.error(f"{component_name} check failed: {str(e)}")
181
+ logger.error(f"{component_name} health check failed: {str(e)}")
194
182
  return {"status": "unavailable", "error": str(e)}
195
183
 
196
184
 
197
185
  async def _check_components() -> Dict[str, Dict[str, Any]]:
198
186
  """
199
- Check the health of individual MCP components by verifying their caches.
187
+ Check the health of individual MCP components using their component classes.
200
188
 
201
189
  Returns
202
190
  -------
203
191
  Dict[str, Dict[str, Any]]
204
- Dictionary mapping component names to their health status:
205
- - {component_name} : Dict[str, str]
206
- Health status for each component, containing:
207
- - status : str
208
- One of: 'healthy', 'inactive', or 'unavailable'
209
- - error : str, optional
210
- Error message if status is 'unavailable'
192
+ Dictionary mapping component names to their health status
211
193
  """
212
- # Define component configurations - cache vars that indicate initialization
194
+ # Define component configurations
213
195
  component_configs = {
214
- "documentation": ("napistu.mcp.documentation", "_docs_cache"),
215
- "codebase": ("napistu.mcp.codebase", "_codebase_cache"),
216
- "tutorials": ("napistu.mcp.tutorials", "_tutorial_cache"),
217
- "execution": ("napistu.mcp.execution", "_session_context"),
196
+ "documentation": "napistu.mcp.documentation",
197
+ "codebase": "napistu.mcp.codebase",
198
+ "tutorials": "napistu.mcp.tutorials",
199
+ "execution": "napistu.mcp.execution",
218
200
  }
219
201
 
220
202
  logger.info("Starting component health checks...")
221
203
  logger.info(f"Checking components: {list(component_configs.keys())}")
222
204
 
223
- # Check each component's cache
205
+ # Check each component using their state objects
224
206
  results = {
225
- name: _check_component_health(name, module_path, cache_attr)
226
- for name, (module_path, cache_attr) in component_configs.items()
207
+ name: _check_component_health(name, module_path)
208
+ for name, module_path in component_configs.items()
227
209
  }
228
210
 
229
211
  logger.info(f"Health check results: {results}")
napistu/mcp/profiles.py CHANGED
@@ -1,5 +1,7 @@
1
1
  from typing import Dict, Any
2
2
 
3
+ from napistu.mcp.constants import MCP_PROFILES
4
+
3
5
 
4
6
  class ServerProfile:
5
7
  """Base profile for MCP server configuration."""
@@ -31,9 +33,11 @@ class ServerProfile:
31
33
 
32
34
 
33
35
  # Pre-defined profiles
34
- LOCAL_PROFILE = ServerProfile(server_name="napistu-local", enable_execution=True)
36
+ EXECUTION_PROFILE = ServerProfile(
37
+ server_name="napistu-execution", enable_execution=True
38
+ )
35
39
 
36
- REMOTE_PROFILE = ServerProfile(
40
+ DOCS_PROFILE = ServerProfile(
37
41
  server_name="napistu-docs",
38
42
  enable_documentation=True,
39
43
  enable_codebase=True,
@@ -54,16 +58,16 @@ def get_profile(profile_name: str, **overrides) -> ServerProfile:
54
58
  Get a predefined profile with optional overrides.
55
59
 
56
60
  Args:
57
- profile_name: Name of the profile ('local', 'remote', or 'full')
61
+ profile_name: Name of the profile ('execution', 'docs', or 'full')
58
62
  **overrides: Configuration overrides
59
63
 
60
64
  Returns:
61
65
  ServerProfile instance
62
66
  """
63
67
  profiles = {
64
- "local": LOCAL_PROFILE,
65
- "remote": REMOTE_PROFILE,
66
- "full": FULL_PROFILE,
68
+ MCP_PROFILES.EXECUTION: EXECUTION_PROFILE,
69
+ MCP_PROFILES.DOCS: DOCS_PROFILE,
70
+ MCP_PROFILES.FULL: FULL_PROFILE,
67
71
  }
68
72
 
69
73
  if profile_name not in profiles:
napistu/mcp/server.py CHANGED
@@ -1,11 +1,9 @@
1
- # src/napistu/mcp/server.py
2
1
  """
3
2
  Core MCP server implementation for Napistu.
4
3
  """
5
4
 
6
5
  import asyncio
7
6
  import logging
8
- import os
9
7
 
10
8
  from mcp.server import FastMCP
11
9
 
@@ -16,20 +14,60 @@ from napistu.mcp import tutorials
16
14
  from napistu.mcp import health
17
15
 
18
16
  from napistu.mcp.profiles import ServerProfile, get_profile
17
+ from napistu.mcp.constants import MCP_DEFAULTS
18
+ from napistu.mcp.config import MCPServerConfig
19
19
 
20
20
  logger = logging.getLogger(__name__)
21
21
 
22
22
 
23
- def create_server(profile: ServerProfile, **kwargs) -> FastMCP:
23
+ def _register_component(
24
+ name: str, module, config_key: str, config: dict, mcp: FastMCP, **kwargs
25
+ ) -> None:
26
+ """
27
+ Register a single component with the MCP server.
28
+
29
+ Parameters
30
+ ----------
31
+ name : str
32
+ Component name for logging
33
+ module : module
34
+ Component module with get_component() function or create_component() for execution
35
+ config_key : str
36
+ Configuration key to check if component is enabled
37
+ config : dict
38
+ Server configuration
39
+ mcp : FastMCP
40
+ FastMCP server instance
41
+ **kwargs : dict
42
+ Additional arguments for component creation (used by execution component)
43
+ """
44
+ if not config.get(config_key, False):
45
+ return # Skip disabled components
46
+
47
+ logger.info(f"Registering {name} components")
48
+
49
+ if name == "execution":
50
+ # Special handling for execution component which needs session context
51
+ component = module.create_component(
52
+ session_context=kwargs.get("session_context"),
53
+ object_registry=kwargs.get("object_registry"),
54
+ )
55
+ else:
56
+ component = module.get_component()
57
+
58
+ component.register(mcp)
59
+
60
+
61
+ def create_server(profile: ServerProfile, server_config: MCPServerConfig) -> FastMCP:
24
62
  """
25
- Create an MCP server based on a profile configuration.
63
+ Create an MCP server based on a profile configuration and server config.
26
64
 
27
65
  Parameters
28
66
  ----------
29
67
  profile : ServerProfile
30
- Server profile to use. All configuration must be set in the profile.
31
- **kwargs
32
- Additional arguments to pass to the FastMCP constructor such as host and port.
68
+ Server profile to use. All configuration must be set in the profile. (Valid profiles: 'execution', 'docs', 'full')
69
+ server_config : MCPServerConfig
70
+ Server configuration with validated host, port, and server name.
33
71
 
34
72
  Returns
35
73
  -------
@@ -39,26 +77,30 @@ def create_server(profile: ServerProfile, **kwargs) -> FastMCP:
39
77
 
40
78
  config = profile.get_config()
41
79
 
42
- # Create the server with FastMCP-specific parameters
43
- # Pass all kwargs directly to the FastMCP constructor
44
- mcp = FastMCP(config["server_name"], **kwargs)
45
-
46
- if config["enable_documentation"]:
47
- logger.info("Registering documentation components")
48
- documentation.register_components(mcp)
49
- if config["enable_codebase"]:
50
- logger.info("Registering codebase components")
51
- codebase.register_components(mcp)
52
- if config["enable_execution"]:
53
- logger.info("Registering execution components")
54
- execution.register_components(
80
+ # Create the server with validated configuration
81
+ mcp = FastMCP(
82
+ server_config.server_name, host=server_config.host, port=server_config.port
83
+ )
84
+
85
+ # Define component configurations
86
+ component_configs = [
87
+ ("documentation", documentation, "enable_documentation"),
88
+ ("codebase", codebase, "enable_codebase"),
89
+ ("tutorials", tutorials, "enable_tutorials"),
90
+ ("execution", execution, "enable_execution"),
91
+ ]
92
+
93
+ # Register all components
94
+ for name, module, config_key in component_configs:
95
+ _register_component(
96
+ name,
97
+ module,
98
+ config_key,
99
+ config,
55
100
  mcp,
56
- session_context=config["session_context"],
57
- object_registry=config["object_registry"],
101
+ session_context=config.get("session_context"),
102
+ object_registry=config.get("object_registry"),
58
103
  )
59
- if config["enable_tutorials"]:
60
- logger.info("Registering tutorials components")
61
- tutorials.register_components(mcp)
62
104
 
63
105
  # Always register health components
64
106
  health.register_components(mcp)
@@ -67,9 +109,44 @@ def create_server(profile: ServerProfile, **kwargs) -> FastMCP:
67
109
  return mcp
68
110
 
69
111
 
112
+ async def _initialize_component(
113
+ name: str, module, config_key: str, config: dict
114
+ ) -> bool:
115
+ """
116
+ Initialize a single component with error handling.
117
+
118
+ Parameters
119
+ ----------
120
+ name : str
121
+ Component name for logging
122
+ module : module
123
+ Component module with get_component() function
124
+ config_key : str
125
+ Configuration key to check if component is enabled
126
+ config : dict
127
+ Server configuration
128
+
129
+ Returns
130
+ -------
131
+ bool
132
+ True if initialization successful
133
+ """
134
+ if not config.get(config_key, False):
135
+ return True # Skip disabled components
136
+
137
+ logger.info(f"Initializing {name} components")
138
+ try:
139
+ component = module.get_component()
140
+ result = await component.safe_initialize()
141
+ return result
142
+ except Exception as e:
143
+ logger.error(f"❌ {name.title()} components failed to initialize: {e}")
144
+ return False
145
+
146
+
70
147
  async def initialize_components(profile: ServerProfile) -> None:
71
148
  """
72
- Asynchronously initialize all enabled components for the MCP server, using the provided ServerProfile.
149
+ Asynchronously initialize all enabled components for the MCP server.
73
150
 
74
151
  Parameters
75
152
  ----------
@@ -82,51 +159,61 @@ async def initialize_components(profile: ServerProfile) -> None:
82
159
  """
83
160
  config = profile.get_config()
84
161
 
85
- if config["enable_documentation"]:
86
- logger.info("Initializing documentation components")
87
- await documentation.initialize_components()
88
- if config["enable_codebase"]:
89
- logger.info("Initializing codebase components")
90
- await codebase.initialize_components()
91
- if config["enable_tutorials"]:
92
- logger.info("Initializing tutorials components")
93
- await tutorials.initialize_components()
94
- if config["enable_execution"]:
95
- logger.info("Initializing execution components")
96
- await execution.initialize_components()
162
+ # Define component configurations
163
+ component_configs = [
164
+ ("documentation", documentation, "enable_documentation"),
165
+ ("codebase", codebase, "enable_codebase"),
166
+ ("tutorials", tutorials, "enable_tutorials"),
167
+ ("execution", execution, "enable_execution"),
168
+ ]
169
+
170
+ # Initialize all components
171
+ initialization_results = {}
172
+
173
+ for name, module, config_key in component_configs:
174
+ result = await _initialize_component(name, module, config_key, config)
175
+ initialization_results[name] = result
97
176
 
98
177
  # Initialize health components last since they monitor the other components
99
178
  logger.info("Initializing health components")
100
- await health.initialize_components()
179
+ try:
180
+ result = await health.initialize_components()
181
+ initialization_results["health"] = result
182
+ if result:
183
+ logger.info("✅ Health components initialized successfully")
184
+ else:
185
+ logger.warning("⚠️ Health components initialized with issues")
186
+ except Exception as e:
187
+ logger.error(f"❌ Health components failed to initialize: {e}")
188
+ initialization_results["health"] = False
189
+
190
+ # Summary of initialization
191
+ successful = sum(1 for success in initialization_results.values() if success)
192
+ total = len(initialization_results)
193
+ logger.info(
194
+ f"Component initialization complete: {successful}/{total} components successful"
195
+ )
101
196
 
197
+ if successful == 0:
198
+ logger.error(
199
+ "❌ All components failed to initialize - server may not function correctly"
200
+ )
201
+ elif successful < total:
202
+ logger.warning(
203
+ "⚠️ Some components failed to initialize - server running in degraded mode"
204
+ )
102
205
 
103
- def start_mcp_server(
104
- profile_name: str = "remote",
105
- host: str = "0.0.0.0",
106
- port: int = 8080,
107
- server_name: str | None = None,
108
- ) -> None:
206
+
207
+ def start_mcp_server(profile_name: str, server_config: MCPServerConfig) -> None:
109
208
  """
110
209
  Start MCP server - main entry point for server startup.
111
210
 
112
- The server will be started with HTTP transport on the specified host and port.
113
- Environment variables can override the default configuration:
114
- - MCP_PROFILE: Server profile to use
115
- - HOST: Host to bind to
116
- - PORT: Port to bind to
117
- - MCP_SERVER_NAME: Name of the MCP server
118
-
119
211
  Parameters
120
212
  ----------
121
- profile_name : str, optional
122
- Server profile to use ('local', 'remote', 'full'). Defaults to 'remote'.
123
- host : str, optional
124
- Host address to bind the server to. Defaults to '0.0.0.0'.
125
- port : int, optional
126
- Port number to listen on. Defaults to 8080.
127
- server_name : str | None, optional
128
- Custom name for the MCP server. If None, will be generated from profile name.
129
- Defaults to None.
213
+ profile_name : str
214
+ Server profile to use ('local', 'remote', 'full').
215
+ server_config : MCPServerConfig
216
+ Validated server configuration.
130
217
 
131
218
  Returns
132
219
  -------
@@ -143,20 +230,12 @@ def start_mcp_server(
143
230
  logging.basicConfig(level=logging.INFO)
144
231
  logger = logging.getLogger("napistu")
145
232
 
146
- # Get configuration from environment variables (for Cloud Run)
147
- env_profile = os.getenv("MCP_PROFILE", profile_name)
148
- env_host = os.getenv("HOST", host)
149
- env_port = int(os.getenv("PORT", port))
150
- env_server_name = os.getenv(
151
- "MCP_SERVER_NAME", server_name or f"napistu-{env_profile}"
152
- )
153
-
154
233
  logger.info("Starting Napistu MCP Server")
155
- logger.info(f" Profile: {env_profile}")
156
- logger.info(f" Host: {env_host}")
157
- logger.info(f" Port: {env_port}")
158
- logger.info(f" Server Name: {env_server_name}")
159
- logger.info(" Transport: streamable-http")
234
+ logger.info(f" Profile: {profile_name}")
235
+ logger.info(f" Host: {server_config.host}")
236
+ logger.info(f" Port: {server_config.port}")
237
+ logger.info(f" Server Name: {server_config.server_name}")
238
+ logger.info(f" Transport: {MCP_DEFAULTS.TRANSPORT}")
160
239
 
161
240
  # Create session context for execution components
162
241
  session_context = {}
@@ -164,14 +243,14 @@ def start_mcp_server(
164
243
 
165
244
  # Get profile with configuration
166
245
  profile: ServerProfile = get_profile(
167
- env_profile,
246
+ profile_name,
168
247
  session_context=session_context,
169
248
  object_registry=object_registry,
170
- server_name=env_server_name,
249
+ server_name=server_config.server_name,
171
250
  )
172
251
 
173
- # Create server with Cloud Run proxy settings
174
- mcp = create_server(profile, host=env_host, port=env_port)
252
+ # Create server with validated configuration
253
+ mcp = create_server(profile, server_config)
175
254
 
176
255
  # Initialize components first (separate async call)
177
256
  async def init_components():
@@ -186,6 +265,8 @@ def start_mcp_server(
186
265
  logger.info(f"Server settings: {mcp.settings}")
187
266
 
188
267
  logger.info("🚀 Starting MCP server...")
189
- logger.info(f"Using HTTP transport on http://{env_host}:{env_port}")
268
+ logger.info(
269
+ f"Using {MCP_DEFAULTS.TRANSPORT} transport on http://{server_config.host}:{server_config.port}"
270
+ )
190
271
 
191
- mcp.run(transport="streamable-http")
272
+ mcp.run(transport=MCP_DEFAULTS.TRANSPORT)