napistu 0.2.5.dev6__py3-none-any.whl → 0.3.1__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 (107) hide show
  1. napistu/__main__.py +126 -96
  2. napistu/constants.py +35 -41
  3. napistu/context/__init__.py +10 -0
  4. napistu/context/discretize.py +462 -0
  5. napistu/context/filtering.py +387 -0
  6. napistu/gcs/__init__.py +1 -1
  7. napistu/identifiers.py +74 -15
  8. napistu/indices.py +68 -0
  9. napistu/ingestion/__init__.py +1 -1
  10. napistu/ingestion/bigg.py +47 -62
  11. napistu/ingestion/constants.py +18 -133
  12. napistu/ingestion/gtex.py +113 -0
  13. napistu/ingestion/hpa.py +147 -0
  14. napistu/ingestion/sbml.py +0 -97
  15. napistu/ingestion/string.py +2 -2
  16. napistu/matching/__init__.py +10 -0
  17. napistu/matching/constants.py +18 -0
  18. napistu/matching/interactions.py +518 -0
  19. napistu/matching/mount.py +529 -0
  20. napistu/matching/species.py +510 -0
  21. napistu/mcp/__init__.py +7 -4
  22. napistu/mcp/__main__.py +128 -72
  23. napistu/mcp/client.py +16 -25
  24. napistu/mcp/codebase.py +201 -153
  25. napistu/mcp/component_base.py +170 -0
  26. napistu/mcp/config.py +223 -0
  27. napistu/mcp/constants.py +45 -2
  28. napistu/mcp/documentation.py +253 -136
  29. napistu/mcp/documentation_utils.py +13 -48
  30. napistu/mcp/execution.py +372 -305
  31. napistu/mcp/health.py +49 -67
  32. napistu/mcp/profiles.py +10 -6
  33. napistu/mcp/server.py +161 -80
  34. napistu/mcp/tutorials.py +139 -87
  35. napistu/modify/__init__.py +1 -1
  36. napistu/modify/gaps.py +1 -1
  37. napistu/network/__init__.py +1 -1
  38. napistu/network/constants.py +101 -34
  39. napistu/network/data_handling.py +388 -0
  40. napistu/network/ig_utils.py +351 -0
  41. napistu/network/napistu_graph_core.py +354 -0
  42. napistu/network/neighborhoods.py +40 -40
  43. napistu/network/net_create.py +373 -309
  44. napistu/network/net_propagation.py +47 -19
  45. napistu/network/{net_utils.py → ng_utils.py} +124 -272
  46. napistu/network/paths.py +67 -51
  47. napistu/network/precompute.py +11 -11
  48. napistu/ontologies/__init__.py +10 -0
  49. napistu/ontologies/constants.py +129 -0
  50. napistu/ontologies/dogma.py +243 -0
  51. napistu/ontologies/genodexito.py +649 -0
  52. napistu/ontologies/mygene.py +369 -0
  53. napistu/ontologies/renaming.py +198 -0
  54. napistu/rpy2/__init__.py +229 -86
  55. napistu/rpy2/callr.py +47 -77
  56. napistu/rpy2/constants.py +24 -23
  57. napistu/rpy2/rids.py +61 -648
  58. napistu/sbml_dfs_core.py +587 -222
  59. napistu/scverse/__init__.py +15 -0
  60. napistu/scverse/constants.py +28 -0
  61. napistu/scverse/loading.py +727 -0
  62. napistu/utils.py +118 -10
  63. {napistu-0.2.5.dev6.dist-info → napistu-0.3.1.dist-info}/METADATA +8 -3
  64. napistu-0.3.1.dist-info/RECORD +133 -0
  65. tests/conftest.py +22 -0
  66. tests/test_context_discretize.py +56 -0
  67. tests/test_context_filtering.py +267 -0
  68. tests/test_identifiers.py +100 -0
  69. tests/test_indices.py +65 -0
  70. tests/{test_edgelist.py → test_ingestion_napistu_edgelist.py} +2 -2
  71. tests/test_matching_interactions.py +108 -0
  72. tests/test_matching_mount.py +305 -0
  73. tests/test_matching_species.py +394 -0
  74. tests/test_mcp_config.py +193 -0
  75. tests/test_mcp_documentation_utils.py +12 -3
  76. tests/test_mcp_server.py +356 -0
  77. tests/test_network_data_handling.py +397 -0
  78. tests/test_network_ig_utils.py +23 -0
  79. tests/test_network_neighborhoods.py +19 -0
  80. tests/test_network_net_create.py +459 -0
  81. tests/test_network_ng_utils.py +30 -0
  82. tests/test_network_paths.py +56 -0
  83. tests/{test_precomputed_distances.py → test_network_precompute.py} +8 -6
  84. tests/test_ontologies_genodexito.py +58 -0
  85. tests/test_ontologies_mygene.py +39 -0
  86. tests/test_ontologies_renaming.py +110 -0
  87. tests/test_rpy2_callr.py +79 -0
  88. tests/test_rpy2_init.py +151 -0
  89. tests/test_sbml.py +0 -31
  90. tests/test_sbml_dfs_core.py +134 -10
  91. tests/test_scverse_loading.py +778 -0
  92. tests/test_set_coverage.py +2 -2
  93. tests/test_utils.py +121 -1
  94. napistu/mechanism_matching.py +0 -1353
  95. napistu/rpy2/netcontextr.py +0 -467
  96. napistu-0.2.5.dev6.dist-info/RECORD +0 -97
  97. tests/test_igraph.py +0 -367
  98. tests/test_mechanism_matching.py +0 -784
  99. tests/test_net_utils.py +0 -149
  100. tests/test_netcontextr.py +0 -105
  101. tests/test_rpy2.py +0 -61
  102. /napistu/ingestion/{cpr_edgelist.py → napistu_edgelist.py} +0 -0
  103. {napistu-0.2.5.dev6.dist-info → napistu-0.3.1.dist-info}/WHEEL +0 -0
  104. {napistu-0.2.5.dev6.dist-info → napistu-0.3.1.dist-info}/entry_points.txt +0 -0
  105. {napistu-0.2.5.dev6.dist-info → napistu-0.3.1.dist-info}/licenses/LICENSE +0 -0
  106. {napistu-0.2.5.dev6.dist-info → napistu-0.3.1.dist-info}/top_level.txt +0 -0
  107. /tests/{test_obo.py → test_ingestion_obo.py} +0 -0
napistu/mcp/config.py ADDED
@@ -0,0 +1,223 @@
1
+ from pydantic import BaseModel, Field, computed_field, validator
2
+ from typing import Optional
3
+ import click
4
+ from napistu.mcp.constants import MCP_DEFAULTS, MCP_PRODUCTION_URL
5
+
6
+
7
+ class MCPServerConfig(BaseModel):
8
+ """Server-side MCP configuration with validation."""
9
+
10
+ host: str = Field(description="Host to bind server to")
11
+ port: int = Field(ge=1, le=65535, description="Port to bind server to")
12
+ server_name: str = Field(description="Server name")
13
+
14
+ @validator("host")
15
+ def validate_host(cls, v):
16
+ """Basic host validation."""
17
+ if not v or v.isspace():
18
+ raise ValueError("Host cannot be empty")
19
+ return v.strip()
20
+
21
+ @computed_field
22
+ @property
23
+ def bind_address(self) -> str:
24
+ """Full address for server binding."""
25
+ return f"{self.host}:{self.port}"
26
+
27
+
28
+ class MCPClientConfig(BaseModel):
29
+ """Client-side MCP configuration with validation."""
30
+
31
+ host: str = Field(description="Target server host")
32
+ port: int = Field(ge=1, le=65535, description="Target server port")
33
+ use_https: bool = Field(description="Use HTTPS instead of HTTP")
34
+
35
+ @computed_field
36
+ @property
37
+ def base_url(self) -> str:
38
+ """Base URL for HTTP requests."""
39
+ protocol = "https" if self.use_https else "http"
40
+ return f"{protocol}://{self.host}:{self.port}"
41
+
42
+ @computed_field
43
+ @property
44
+ def mcp_url(self) -> str:
45
+ """Full MCP endpoint URL."""
46
+ return f"{self.base_url}{MCP_DEFAULTS.MCP_PATH}"
47
+
48
+
49
+ # Preset configurations - no overrides needed
50
+ def local_server_config() -> MCPServerConfig:
51
+ """Local development server configuration."""
52
+ return MCPServerConfig(
53
+ host=MCP_DEFAULTS.LOCAL_HOST,
54
+ port=MCP_DEFAULTS.LOCAL_PORT,
55
+ server_name=MCP_DEFAULTS.LOCAL_SERVER_NAME,
56
+ )
57
+
58
+
59
+ def production_server_config() -> MCPServerConfig:
60
+ """Production server configuration."""
61
+ return MCPServerConfig(
62
+ host=MCP_DEFAULTS.PRODUCTION_HOST,
63
+ port=MCP_DEFAULTS.PRODUCTION_PORT,
64
+ server_name=MCP_DEFAULTS.PRODUCTION_SERVER_NAME,
65
+ )
66
+
67
+
68
+ def local_client_config() -> MCPClientConfig:
69
+ """Local development client configuration."""
70
+ return MCPClientConfig(
71
+ host=MCP_DEFAULTS.LOCAL_HOST, port=MCP_DEFAULTS.LOCAL_PORT, use_https=False
72
+ )
73
+
74
+
75
+ def production_client_config() -> MCPClientConfig:
76
+ """Production client configuration."""
77
+ # Parse production URL to extract host
78
+ production_host = MCP_PRODUCTION_URL.replace("https://", "").split("/")[0]
79
+ return MCPClientConfig(
80
+ host=production_host, port=MCP_DEFAULTS.HTTPS_PORT, use_https=True
81
+ )
82
+
83
+
84
+ # Utility functions for CLI validation
85
+ def validate_server_config_flags(
86
+ local: bool,
87
+ production: bool,
88
+ host: Optional[str],
89
+ port: Optional[int],
90
+ server_name: Optional[str],
91
+ ) -> MCPServerConfig:
92
+ """
93
+ Validate server configuration flags and return appropriate config.
94
+
95
+ Raises click.BadParameter if incompatible flags are used.
96
+ """
97
+ # Check for mutually exclusive presets
98
+ if local and production:
99
+ raise click.BadParameter("Cannot use both --local and --production flags")
100
+
101
+ # Check for preset + manual config conflicts
102
+ preset_used = local or production
103
+ manual_config_used = any(
104
+ [host is not None, port is not None, server_name is not None]
105
+ )
106
+
107
+ if preset_used and manual_config_used:
108
+ preset_name = "local" if local else "production"
109
+ raise click.BadParameter(
110
+ f"Cannot use --{preset_name} with manual host/port/server-name configuration. "
111
+ f"Use either preset flags OR manual configuration, not both."
112
+ )
113
+
114
+ # Return appropriate config
115
+ if local:
116
+ return local_server_config()
117
+ elif production:
118
+ return production_server_config()
119
+ else:
120
+ # Manual configuration - all required
121
+ if not all([host, port, server_name]):
122
+ raise click.BadParameter(
123
+ "Manual configuration requires --host, --port, and --server-name"
124
+ )
125
+ return MCPServerConfig(host=host, port=port, server_name=server_name)
126
+
127
+
128
+ def validate_client_config_flags(
129
+ local: bool,
130
+ production: bool,
131
+ host: Optional[str],
132
+ port: Optional[int],
133
+ use_https: Optional[bool],
134
+ ) -> MCPClientConfig:
135
+ """
136
+ Validate client configuration flags and return appropriate config.
137
+
138
+ Raises click.BadParameter if incompatible flags are used.
139
+ """
140
+ # Check for mutually exclusive presets
141
+ if local and production:
142
+ raise click.BadParameter("Cannot use both --local and --production flags")
143
+
144
+ # Check for preset + manual config conflicts
145
+ preset_used = local or production
146
+ manual_config_used = any(
147
+ [host is not None, port is not None, use_https is not None]
148
+ )
149
+
150
+ if preset_used and manual_config_used:
151
+ preset_name = "local" if local else "production"
152
+ raise click.BadParameter(
153
+ f"Cannot use --{preset_name} with manual host/port/https configuration. "
154
+ f"Use either preset flags OR manual configuration, not both."
155
+ )
156
+
157
+ # Return appropriate config
158
+ if local:
159
+ return local_client_config()
160
+ elif production:
161
+ return production_client_config()
162
+ else:
163
+ # Manual configuration - all required
164
+ if not all([host is not None, port is not None, use_https is not None]):
165
+ raise click.BadParameter(
166
+ "Manual configuration requires --host, --port, and --https"
167
+ )
168
+ return MCPClientConfig(host=host, port=port, use_https=use_https)
169
+
170
+
171
+ # Click option decorators for reuse
172
+ def server_config_options(f):
173
+ """Decorator to add server configuration options to click commands."""
174
+ f = click.option(
175
+ "--production", is_flag=True, help="Use production server configuration"
176
+ )(f)
177
+ f = click.option(
178
+ "--local", is_flag=True, help="Use local development server configuration"
179
+ )(f)
180
+ f = click.option(
181
+ "--host",
182
+ type=str,
183
+ help="Host to bind server to (requires --port and --server-name)",
184
+ )(f)
185
+ f = click.option(
186
+ "--port",
187
+ type=int,
188
+ help="Port to bind server to (requires --host and --server-name)",
189
+ )(f)
190
+ f = click.option(
191
+ "--server-name", type=str, help="Server name (requires --host and --port)"
192
+ )(f)
193
+ return f
194
+
195
+
196
+ def client_config_options(f):
197
+ """Decorator to add client configuration options to click commands."""
198
+ f = click.option("--production", is_flag=True, help="Connect to production server")(
199
+ f
200
+ )
201
+ f = click.option(
202
+ "--local", is_flag=True, help="Connect to local development server"
203
+ )(f)
204
+ f = click.option(
205
+ "--host",
206
+ type=str,
207
+ default=None,
208
+ help="Server host (requires --port and --https)",
209
+ )(f)
210
+ f = click.option(
211
+ "--port",
212
+ type=int,
213
+ default=None,
214
+ help="Server port (requires --host and --https)",
215
+ )(f)
216
+ f = click.option(
217
+ "--https",
218
+ is_flag=True,
219
+ default=None,
220
+ flag_value=True,
221
+ help="Use HTTPS (requires --host and --port)",
222
+ )(f)
223
+ return f
napistu/mcp/constants.py CHANGED
@@ -31,6 +31,36 @@ TOOL_VARS = SimpleNamespace(
31
31
  SNIPPET="snippet",
32
32
  )
33
33
 
34
+ # MCP Server Configuration Constants
35
+ MCP_DEFAULTS = SimpleNamespace(
36
+ # Local development defaults
37
+ LOCAL_HOST="127.0.0.1",
38
+ LOCAL_PORT=8765,
39
+ # Production defaults
40
+ PRODUCTION_HOST="0.0.0.0",
41
+ PRODUCTION_PORT=8080,
42
+ # Server names
43
+ LOCAL_SERVER_NAME="napistu-local",
44
+ PRODUCTION_SERVER_NAME="napistu-production",
45
+ FULL_SERVER_NAME="napistu-full",
46
+ # Transport configuration
47
+ TRANSPORT="streamable-http",
48
+ MCP_PATH="/mcp",
49
+ # Standard protocol ports
50
+ HTTP_PORT=80,
51
+ HTTPS_PORT=443,
52
+ )
53
+
54
+ # Production server URL
55
+ MCP_PRODUCTION_URL = "https://napistu-mcp-server-844820030839.us-west1.run.app"
56
+
57
+ # Profile names (component configurations)
58
+ MCP_PROFILES = SimpleNamespace(
59
+ EXECUTION="execution", # execution only
60
+ DOCS="docs", # docs + codebase + tutorials
61
+ FULL="full", # all components
62
+ )
63
+
34
64
  READMES = {
35
65
  "napistu": "https://raw.githubusercontent.com/napistu/napistu/main/README.md",
36
66
  "napistu-py": "https://raw.githubusercontent.com/napistu/napistu-py/main/README.md",
@@ -38,7 +68,20 @@ READMES = {
38
68
  "napistu/tutorials": "https://raw.githubusercontent.com/napistu/napistu/main/tutorials/README.md",
39
69
  }
40
70
 
41
- WIKI_ROOT = "https://raw.githubusercontent.com/napistu/napistu/main/docs/wiki"
71
+ WIKI_PAGES = {
72
+ "Consensus",
73
+ "Data-Sources",
74
+ "Napistu-Graphs",
75
+ "Dev-Zone",
76
+ "Environment-Setup",
77
+ "Exploring-Molecular-Relationships-as-Networks",
78
+ "GitHub-Actions-napistu‐py",
79
+ "History",
80
+ "Model-Context-Protocol-(MCP)-server",
81
+ "Precomputed-distances",
82
+ "SBML",
83
+ "SBML-DFs",
84
+ }
42
85
 
43
86
  NAPISTU_PY_READTHEDOCS = "https://napistu.readthedocs.io/en/latest"
44
87
  NAPISTU_PY_READTHEDOCS_API = NAPISTU_PY_READTHEDOCS + "/api.html"
@@ -61,7 +104,7 @@ REPOS_WITH_WIKI = [PACKAGE_DEFS.GITHUB_PROJECT_REPO]
61
104
  TUTORIAL_URLS = {
62
105
  "adding_data_to_graphs": "https://raw.githubusercontent.com/napistu/napistu/refs/heads/main/tutorials/adding_data_to_graphs.ipynb",
63
106
  "downloading_pathway_data": "https://raw.githubusercontent.com/napistu/napistu/refs/heads/main/tutorials/downloading_pathway_data.ipynb",
64
- "formatting_sbml_dfs_as_cpr_graphs": "https://raw.githubusercontent.com/napistu/napistu/refs/heads/main/tutorials/formatting_sbml_dfs_as_cpr_graphs.ipynb",
107
+ "formatting_sbml_dfs_as_napistu_graphs": "https://raw.githubusercontent.com/napistu/napistu/refs/heads/main/tutorials/formatting_sbml_dfs_as_napistu_graphs.ipynb",
65
108
  "merging_models_into_a_consensus": "https://raw.githubusercontent.com/napistu/napistu/refs/heads/main/tutorials/merging_models_into_a_consensus.ipynb",
66
109
  "r_based_network_visualization": "https://raw.githubusercontent.com/napistu/napistu/refs/heads/main/tutorials/r_based_network_visualization.ipynb",
67
110
  "suggesting_mechanisms_with_networks": "https://raw.githubusercontent.com/napistu/napistu/refs/heads/main/tutorials/suggesting_mechanisms_with_networks.ipynb",