scmcp-shared 0.3.6__py3-none-any.whl → 0.3.7__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.
scmcp_shared/server/pl.py CHANGED
@@ -3,6 +3,7 @@ import inspect
3
3
  from functools import partial
4
4
  import scanpy as sc
5
5
  from fastmcp import FastMCP, Context
6
+ from fastmcp.tools.tool import Tool
6
7
  from fastmcp.exceptions import ToolError
7
8
  from ..schema.pl import *
8
9
  from ..schema import AdataInfo
@@ -24,7 +25,7 @@ class ScanpyPlottingMCP(BaseMCP):
24
25
  super().__init__("ScanpyMCP-PL-Server", include_tools, exclude_tools, AdataInfo)
25
26
 
26
27
  def _tool_pca(self):
27
- def _pca(request: PCAModel, adinfo: self.AdataInfo=self.AdataInfo()):
28
+ def _pca(request: PCAParams, adinfo: self.AdataInfo=self.AdataInfo()):
28
29
  """Scatter plot in PCA coordinates. default figure for PCA plot"""
29
30
  try:
30
31
  if (res := forward_request("pl_pca", request, adinfo)) is not None:
@@ -39,10 +40,10 @@ class ScanpyPlottingMCP(BaseMCP):
39
40
  raise ToolError(e.__context__)
40
41
  else:
41
42
  raise ToolError(e)
42
- return _pca
43
+ return Tool.from_function(_pca, name="pca")
43
44
 
44
45
  def _tool_diffmap(self):
45
- def _diffmap(request: DiffusionMapModel, adinfo: self.AdataInfo=self.AdataInfo()):
46
+ def _diffmap(request: DiffusionMapParams, adinfo: self.AdataInfo=self.AdataInfo()):
46
47
  """Plot diffusion map embedding of cells."""
47
48
  try:
48
49
  if (res := forward_request("pl_diffmap", request, adinfo)) is not None:
@@ -57,10 +58,10 @@ class ScanpyPlottingMCP(BaseMCP):
57
58
  raise ToolError(e.__context__)
58
59
  else:
59
60
  raise ToolError(e)
60
- return _diffmap
61
+ return Tool.from_function(_diffmap, name="diffmap")
61
62
 
62
63
  def _tool_violin(self):
63
- def _violin(request: ViolinModel, adinfo: self.AdataInfo=self.AdataInfo()):
64
+ def _violin(request: ViolinParams, adinfo: self.AdataInfo=self.AdataInfo()):
64
65
  """Plot violin plot of one or more variables."""
65
66
  try:
66
67
  if (res := forward_request("pl_violin", request, adinfo)) is not None:
@@ -77,10 +78,10 @@ class ScanpyPlottingMCP(BaseMCP):
77
78
  raise ToolError(e.__context__)
78
79
  else:
79
80
  raise ToolError(e)
80
- return _violin
81
+ return Tool.from_function(_violin, name="violin")
81
82
 
82
83
  def _tool_stacked_violin(self):
83
- def _stacked_violin(request: StackedViolinModel, adinfo: self.AdataInfo=self.AdataInfo()):
84
+ def _stacked_violin(request: StackedViolinParams, adinfo: self.AdataInfo=self.AdataInfo()):
84
85
  """Plot stacked violin plots. Makes a compact image composed of individual violin plots stacked on top of each other."""
85
86
  try:
86
87
  if (res := forward_request("pl_stacked_violin", request, adinfo)) is not None:
@@ -95,10 +96,10 @@ class ScanpyPlottingMCP(BaseMCP):
95
96
  raise ToolError(e.__context__)
96
97
  else:
97
98
  raise ToolError(e)
98
- return _stacked_violin
99
+ return Tool.from_function(_stacked_violin, name="stacked_violin")
99
100
 
100
101
  def _tool_heatmap(self):
101
- async def _heatmap(request: HeatmapModel, adinfo: self.AdataInfo=self.AdataInfo()):
102
+ async def _heatmap(request: HeatmapParams, adinfo: self.AdataInfo=self.AdataInfo()):
102
103
  """Heatmap of the expression values of genes."""
103
104
  try:
104
105
  if (res := forward_request("pl_heatmap", request, adinfo)) is not None:
@@ -113,10 +114,10 @@ class ScanpyPlottingMCP(BaseMCP):
113
114
  raise ToolError(e.__context__)
114
115
  else:
115
116
  raise ToolError(e)
116
- return _heatmap
117
+ return Tool.from_function(_heatmap, name="heatmap")
117
118
 
118
119
  def _tool_dotplot(self):
119
- def _dotplot(request: DotplotModel, adinfo: self.AdataInfo=self.AdataInfo()):
120
+ def _dotplot(request: DotplotParams, adinfo: self.AdataInfo=self.AdataInfo()):
120
121
  """Plot dot plot of expression values per gene for each group."""
121
122
  try:
122
123
  if (res := forward_request("pl_dotplot", request, adinfo)) is not None:
@@ -131,10 +132,10 @@ class ScanpyPlottingMCP(BaseMCP):
131
132
  raise ToolError(e.__context__)
132
133
  else:
133
134
  raise ToolError(e)
134
- return _dotplot
135
+ return Tool.from_function(_dotplot, name="dotplot")
135
136
 
136
137
  def _tool_matrixplot(self):
137
- def _matrixplot(request: MatrixplotModel, adinfo: self.AdataInfo=self.AdataInfo()):
138
+ def _matrixplot(request: MatrixplotParams, adinfo: self.AdataInfo=self.AdataInfo()):
138
139
  """matrixplot, Create a heatmap of the mean expression values per group of each var_names."""
139
140
  try:
140
141
  if (res := forward_request("pl_matrixplot", request, adinfo)) is not None:
@@ -149,10 +150,10 @@ class ScanpyPlottingMCP(BaseMCP):
149
150
  raise ToolError(e.__context__)
150
151
  else:
151
152
  raise ToolError(e)
152
- return _matrixplot
153
+ return Tool.from_function(_matrixplot, name="matrixplot")
153
154
 
154
155
  def _tool_tracksplot(self):
155
- def _tracksplot(request: TracksplotModel, adinfo: self.AdataInfo=self.AdataInfo()):
156
+ def _tracksplot(request: TracksplotParams, adinfo: self.AdataInfo=self.AdataInfo()):
156
157
  """tracksplot, compact plot of expression of a list of genes."""
157
158
  try:
158
159
  if (res := forward_request("pl_tracksplot", request, adinfo)) is not None:
@@ -167,10 +168,10 @@ class ScanpyPlottingMCP(BaseMCP):
167
168
  raise ToolError(e.__context__)
168
169
  else:
169
170
  raise ToolError(e)
170
- return _tracksplot
171
+ return Tool.from_function(_tracksplot, name="tracksplot")
171
172
 
172
173
  def _tool_scatter(self):
173
- def _scatter(request: EnhancedScatterModel, adinfo: self.AdataInfo=self.AdataInfo()):
174
+ def _scatter(request: EnhancedScatterParams, adinfo: self.AdataInfo=self.AdataInfo()):
174
175
  """Plot a scatter plot of two variables, Scatter plot along observations or variables axes."""
175
176
  try:
176
177
  if (res := forward_request("pl_scatter", request, adinfo)) is not None:
@@ -185,10 +186,10 @@ class ScanpyPlottingMCP(BaseMCP):
185
186
  raise ToolError(e.__context__)
186
187
  else:
187
188
  raise ToolError(e)
188
- return _scatter
189
+ return Tool.from_function(_scatter, name="scatter")
189
190
 
190
191
  def _tool_embedding(self):
191
- def _embedding(request: EmbeddingModel, adinfo: self.AdataInfo=self.AdataInfo()):
192
+ def _embedding(request: EmbeddingParams, adinfo: self.AdataInfo=self.AdataInfo()):
192
193
  """Scatter plot for user specified embedding basis (e.g. umap, tsne, etc)."""
193
194
  try:
194
195
  if (res := forward_request("pl_embedding", request, adinfo)) is not None:
@@ -203,10 +204,10 @@ class ScanpyPlottingMCP(BaseMCP):
203
204
  raise ToolError(e.__context__)
204
205
  else:
205
206
  raise ToolError(e)
206
- return _embedding
207
+ return Tool.from_function(_embedding, name="embedding")
207
208
 
208
209
  def _tool_embedding_density(self):
209
- def _embedding_density(request: EmbeddingDensityModel, adinfo: self.AdataInfo=self.AdataInfo()):
210
+ def _embedding_density(request: EmbeddingDensityParams, adinfo: self.AdataInfo=self.AdataInfo()):
210
211
  """Plot the density of cells in an embedding."""
211
212
  try:
212
213
  if (res := forward_request("pl_embedding_density", request, adinfo)) is not None:
@@ -221,10 +222,10 @@ class ScanpyPlottingMCP(BaseMCP):
221
222
  raise ToolError(e.__context__)
222
223
  else:
223
224
  raise ToolError(e)
224
- return _embedding_density
225
+ return Tool.from_function(_embedding_density, name="embedding_density")
225
226
 
226
227
  def _tool_rank_genes_groups(self):
227
- def _rank_genes_groups(request: RankGenesGroupsModel, adinfo: self.AdataInfo=self.AdataInfo()):
228
+ def _rank_genes_groups(request: RankGenesGroupsParams, adinfo: self.AdataInfo=self.AdataInfo()):
228
229
  """Plot ranking of genes based on differential expression."""
229
230
  try:
230
231
  if (res := forward_request("pl_rank_genes_groups", request, adinfo)) is not None:
@@ -239,10 +240,10 @@ class ScanpyPlottingMCP(BaseMCP):
239
240
  raise ToolError(e.__context__)
240
241
  else:
241
242
  raise ToolError(e)
242
- return _rank_genes_groups
243
+ return Tool.from_function(_rank_genes_groups, name="rank_genes_groups")
243
244
 
244
245
  def _tool_rank_genes_groups_dotplot(self):
245
- def _rank_genes_groups_dotplot(request: RankGenesGroupsDotplotModel, adinfo: self.AdataInfo=self.AdataInfo()):
246
+ def _rank_genes_groups_dotplot(request: RankGenesGroupsDotplotParams, adinfo: self.AdataInfo=self.AdataInfo()):
246
247
  """Plot ranking of genes(DEGs) using dotplot visualization. Defualt plot DEGs for rank_genes_groups tool"""
247
248
  try:
248
249
  if (res := forward_request("pl_rank_genes_groups_dotplot", request, adinfo)) is not None:
@@ -257,10 +258,10 @@ class ScanpyPlottingMCP(BaseMCP):
257
258
  raise ToolError(e.__context__)
258
259
  else:
259
260
  raise ToolError(e)
260
- return _rank_genes_groups_dotplot
261
+ return Tool.from_function(_rank_genes_groups_dotplot, name="rank_genes_groups_dotplot")
261
262
 
262
263
  def _tool_clustermap(self):
263
- def _clustermap(request: ClusterMapModel, adinfo: self.AdataInfo=self.AdataInfo()):
264
+ def _clustermap(request: ClusterMapParams, adinfo: self.AdataInfo=self.AdataInfo()):
264
265
  """Plot hierarchical clustering of cells and genes."""
265
266
  try:
266
267
  if (res := forward_request("pl_clustermap", request, adinfo)) is not None:
@@ -275,10 +276,10 @@ class ScanpyPlottingMCP(BaseMCP):
275
276
  raise ToolError(e.__context__)
276
277
  else:
277
278
  raise ToolError(e)
278
- return _clustermap
279
+ return Tool.from_function(_clustermap, name="clustermap")
279
280
 
280
281
  def _tool_highly_variable_genes(self):
281
- def _highly_variable_genes(request: HighlyVariableGenesModel, adinfo: self.AdataInfo=self.AdataInfo()):
282
+ def _highly_variable_genes(request: HighlyVariableGenesParams, adinfo: self.AdataInfo=self.AdataInfo()):
282
283
  """plot highly variable genes; Plot dispersions or normalized variance versus means for genes."""
283
284
  try:
284
285
  if (res := forward_request("pl_highly_variable_genes", request, adinfo)) is not None:
@@ -293,10 +294,10 @@ class ScanpyPlottingMCP(BaseMCP):
293
294
  raise ToolError(e.__context__)
294
295
  else:
295
296
  raise ToolError(e)
296
- return _highly_variable_genes
297
+ return Tool.from_function(_highly_variable_genes, name="highly_variable_genes")
297
298
 
298
299
  def _tool_pca_variance_ratio(self):
299
- def _pca_variance_ratio(request: PCAVarianceRatioModel, adinfo: self.AdataInfo=self.AdataInfo()):
300
+ def _pca_variance_ratio(request: PCAVarianceRatioParams, adinfo: self.AdataInfo=self.AdataInfo()):
300
301
  """Plot the PCA variance ratio to visualize explained variance."""
301
302
  try:
302
303
  if (res := forward_request("pl_pca_variance_ratio", request, adinfo)) is not None:
@@ -311,5 +312,5 @@ class ScanpyPlottingMCP(BaseMCP):
311
312
  raise ToolError(e.__context__)
312
313
  else:
313
314
  raise ToolError(e)
314
- return _pca_variance_ratio
315
+ return Tool.from_function(_pca_variance_ratio, name="pca_variance_ratio")
315
316
 
scmcp_shared/server/pp.py CHANGED
@@ -2,6 +2,7 @@ import os
2
2
  import inspect
3
3
  import scanpy as sc
4
4
  from fastmcp import FastMCP, Context
5
+ from fastmcp.tools.tool import Tool
5
6
  from fastmcp.exceptions import ToolError
6
7
  from ..schema.pp import *
7
8
  from ..schema import AdataInfo
@@ -22,7 +23,7 @@ class ScanpyPreprocessingMCP(BaseMCP):
22
23
  super().__init__("ScanpyMCP-PP-Server", include_tools, exclude_tools, AdataInfo)
23
24
 
24
25
  def _tool_subset_cells(self):
25
- def _subset_cells(request: SubsetCellModel, adinfo: self.AdataInfo=self.AdataInfo()):
26
+ def _subset_cells(request: SubsetCellParams, adinfo: self.AdataInfo=self.AdataInfo()):
26
27
  """filter or subset cells based on total genes expressed counts and numbers. or values in adata.obs[obs_key]"""
27
28
  try:
28
29
  result = forward_request("subset_cells", request, adinfo)
@@ -62,10 +63,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
62
63
  raise ToolError(e.__context__)
63
64
  else:
64
65
  raise ToolError(e)
65
- return _subset_cells
66
+ return Tool.from_function(_subset_cells, name="subset_cells")
66
67
 
67
68
  def _tool_subset_genes(self):
68
- def _subset_genes(request: SubsetGeneModel, adinfo: self.AdataInfo=self.AdataInfo()):
69
+ def _subset_genes(request: SubsetGeneParams, adinfo: self.AdataInfo=self.AdataInfo()):
69
70
  """filter or subset genes based on number of cells or counts, or values in adata.var[var_key] or subset highly variable genes"""
70
71
  try:
71
72
  result = forward_request("pp_subset_genes", request, adinfo)
@@ -74,6 +75,11 @@ class ScanpyPreprocessingMCP(BaseMCP):
74
75
  func_kwargs = filter_args(request, sc.pp.filter_genes)
75
76
  ads = get_ads()
76
77
  adata = ads.get_adata(adinfo=adinfo).copy()
78
+ if request.highly_variable:
79
+ adata = adata[:, adata.var.highly_variable]
80
+ add_op_log(adata, "subset_genes",
81
+ {"hpv": "true"}, adinfo
82
+ )
77
83
  if func_kwargs:
78
84
  sc.pp.filter_genes(adata, **func_kwargs)
79
85
  add_op_log(adata, sc.pp.filter_genes, func_kwargs, adinfo)
@@ -86,8 +92,6 @@ class ScanpyPreprocessingMCP(BaseMCP):
86
92
  if request.var_max is not None:
87
93
  mask = mask & (adata.var[request.var_key] <= request.var_max)
88
94
  adata = adata[:, mask]
89
- if request.highly_variable:
90
- adata = adata[:, mask & adata.var.highly_variable]
91
95
  add_op_log(adata, "subset_genes",
92
96
  {
93
97
  "var_key": request.var_key, "var_min": request.var_min, "var_max": request.var_max,
@@ -103,7 +107,7 @@ class ScanpyPreprocessingMCP(BaseMCP):
103
107
  raise ToolError(e.__context__)
104
108
  else:
105
109
  raise ToolError(e)
106
- return _subset_genes
110
+ return Tool.from_function(_subset_genes, name="subset_genes")
107
111
 
108
112
  def _tool_calculate_qc_metrics(self):
109
113
  def _calculate_qc_metrics(request: CalculateQCMetrics, adinfo: self.AdataInfo=self.AdataInfo()):
@@ -130,10 +134,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
130
134
  raise ToolError(e.__context__)
131
135
  else:
132
136
  raise ToolError(e)
133
- return _calculate_qc_metrics
137
+ return Tool.from_function(_calculate_qc_metrics, name="calculate_qc_metrics")
134
138
 
135
139
  def _tool_log1p(self):
136
- def _log1p(request: Log1PModel=Log1PModel(), adinfo: self.AdataInfo=self.AdataInfo()):
140
+ def _log1p(request: Log1PParams=Log1PParams(), adinfo: self.AdataInfo=self.AdataInfo()):
137
141
  """Logarithmize the data matrix"""
138
142
  try:
139
143
  result = forward_request("pp_log1p", request, adinfo)
@@ -157,10 +161,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
157
161
  raise ToolError(e.__context__)
158
162
  else:
159
163
  raise ToolError(e)
160
- return _log1p
164
+ return Tool.from_function(_log1p, name="log1p")
161
165
 
162
166
  def _tool_normalize_total(self):
163
- def _normalize_total(request: NormalizeTotalModel, adinfo: self.AdataInfo=self.AdataInfo()):
167
+ def _normalize_total(request: NormalizeTotalParams, adinfo: self.AdataInfo=self.AdataInfo()):
164
168
  """Normalize counts per cell to the same total count"""
165
169
  try:
166
170
  result = forward_request("pp_normalize_total", request, adinfo)
@@ -180,10 +184,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
180
184
  raise ToolError(e.__context__)
181
185
  else:
182
186
  raise ToolError(e)
183
- return _normalize_total
187
+ return Tool.from_function(_normalize_total, name="normalize_total")
184
188
 
185
189
  def _tool_highly_variable_genes(self):
186
- def _highly_variable_genes(request: HighlyVariableGenesModel, adinfo: self.AdataInfo=self.AdataInfo()):
190
+ def _highly_variable_genes(request: HighlyVariableGenesParams, adinfo: self.AdataInfo=self.AdataInfo()):
187
191
  """Annotate highly variable genes"""
188
192
  try:
189
193
  result = forward_request("pp_highly_variable_genes", request, adinfo)
@@ -205,10 +209,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
205
209
  raise ToolError(e.__context__)
206
210
  else:
207
211
  raise ToolError(e)
208
- return _highly_variable_genes
212
+ return Tool.from_function(_highly_variable_genes, name="highly_variable_genes")
209
213
 
210
214
  def _tool_regress_out(self):
211
- def _regress_out(request: RegressOutModel, adinfo: self.AdataInfo=self.AdataInfo()):
215
+ def _regress_out(request: RegressOutParams, adinfo: self.AdataInfo=self.AdataInfo()):
212
216
  """Regress out (mostly) unwanted sources of variation."""
213
217
  try:
214
218
  result = forward_request("pp_regress_out", request, adinfo)
@@ -228,10 +232,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
228
232
  raise ToolError(e.__context__)
229
233
  else:
230
234
  raise ToolError(e)
231
- return _regress_out
235
+ return Tool.from_function(_regress_out, name="regress_out")
232
236
 
233
237
  def _tool_scale(self):
234
- def _scale(request: ScaleModel, adinfo: self.AdataInfo=self.AdataInfo()):
238
+ def _scale(request: ScaleParams, adinfo: self.AdataInfo=self.AdataInfo()):
235
239
  """Scale data to unit variance and zero mean"""
236
240
  try:
237
241
  result = forward_request("pp_scale", request, adinfo)
@@ -253,10 +257,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
253
257
  raise ToolError(e.__context__)
254
258
  else:
255
259
  raise ToolError(e)
256
- return _scale
260
+ return Tool.from_function(_scale, name="scale")
257
261
 
258
262
  def _tool_combat(self):
259
- def _combat(request: CombatModel, adinfo: self.AdataInfo=self.AdataInfo()):
263
+ def _combat(request: CombatParams, adinfo: self.AdataInfo=self.AdataInfo()):
260
264
  """ComBat function for batch effect correction"""
261
265
  try:
262
266
  result = forward_request("pp_combat", request, adinfo)
@@ -278,10 +282,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
278
282
  raise ToolError(e.__context__)
279
283
  else:
280
284
  raise ToolError(e)
281
- return _combat
285
+ return Tool.from_function(_combat, name="combat")
282
286
 
283
287
  def _tool_scrublet(self):
284
- def _scrublet(request: ScrubletModel, adinfo: self.AdataInfo=self.AdataInfo()):
288
+ def _scrublet(request: ScrubletParams, adinfo: self.AdataInfo=self.AdataInfo()):
285
289
  """Predict doublets using Scrublet"""
286
290
  try:
287
291
  result = forward_request("pp_scrublet", request, adinfo)
@@ -300,10 +304,10 @@ class ScanpyPreprocessingMCP(BaseMCP):
300
304
  raise ToolError(e.__context__)
301
305
  else:
302
306
  raise ToolError(e)
303
- return _scrublet
307
+ return Tool.from_function(_scrublet, name="scrublet")
304
308
 
305
309
  def _tool_neighbors(self):
306
- def _neighbors(request: NeighborsModel, adinfo: self.AdataInfo=self.AdataInfo()):
310
+ def _neighbors(request: NeighborsParams, adinfo: self.AdataInfo=self.AdataInfo()):
307
311
  """Compute nearest neighbors distance matrix and neighborhood graph"""
308
312
  try:
309
313
  result = forward_request("pp_neighbors", request, adinfo)
@@ -322,4 +326,4 @@ class ScanpyPreprocessingMCP(BaseMCP):
322
326
  raise ToolError(e.__context__)
323
327
  else:
324
328
  raise ToolError(e)
325
- return _neighbors
329
+ return Tool.from_function(_neighbors, name="neighbors")
scmcp_shared/server/tl.py CHANGED
@@ -4,6 +4,7 @@ import inspect
4
4
  from fastmcp import FastMCP
5
5
  import scanpy as sc
6
6
  from fastmcp.exceptions import ToolError
7
+ from fastmcp.tools.tool import Tool
7
8
  from ..schema.tl import *
8
9
  from ..schema import AdataInfo
9
10
  from scmcp_shared.util import filter_args, add_op_log, forward_request, get_ads, generate_msg
@@ -23,7 +24,7 @@ class ScanpyToolsMCP(BaseMCP):
23
24
  super().__init__("ScanpyMCP-TL-Server", include_tools, exclude_tools, AdataInfo)
24
25
 
25
26
  def _tool_tsne(self):
26
- def _tsne(request: TSNEModel=TSNEModel(), adinfo: self.AdataInfo=self.AdataInfo()):
27
+ def _tsne(request: TSNEParams=TSNEParams(), adinfo: self.AdataInfo=self.AdataInfo()):
27
28
  """t-distributed stochastic neighborhood embedding (t-SNE) for visualization"""
28
29
  try:
29
30
  result = forward_request("tl_tsne", request, adinfo)
@@ -42,10 +43,10 @@ class ScanpyToolsMCP(BaseMCP):
42
43
  raise ToolError(e.__context__)
43
44
  else:
44
45
  raise ToolError(e)
45
- return _tsne
46
+ return Tool.from_function(_tsne, name="tsne")
46
47
 
47
48
  def _tool_umap(self):
48
- def _umap(request: UMAPModel=UMAPModel(), adinfo: self.AdataInfo=self.AdataInfo()):
49
+ def _umap(request: UMAPParams=UMAPParams(), adinfo: self.AdataInfo=self.AdataInfo()):
49
50
  """Uniform Manifold Approximation and Projection (UMAP) for visualization"""
50
51
  try:
51
52
  result = forward_request("tl_umap", request, adinfo)
@@ -64,10 +65,10 @@ class ScanpyToolsMCP(BaseMCP):
64
65
  raise ToolError(e.__context__)
65
66
  else:
66
67
  raise ToolError(e)
67
- return _umap
68
+ return Tool.from_function(_umap, name="umap")
68
69
 
69
70
  def _tool_draw_graph(self):
70
- def _draw_graph(request: DrawGraphModel, adinfo: self.AdataInfo=self.AdataInfo()):
71
+ def _draw_graph(request: DrawGraphParams, adinfo: self.AdataInfo=self.AdataInfo()):
71
72
  """Force-directed graph drawing"""
72
73
  try:
73
74
  result = forward_request("tl_draw_graph", request, adinfo)
@@ -86,10 +87,10 @@ class ScanpyToolsMCP(BaseMCP):
86
87
  raise ToolError(e.__context__)
87
88
  else:
88
89
  raise ToolError(e)
89
- return _draw_graph
90
+ return Tool.from_function(_draw_graph, name="draw_graph")
90
91
 
91
92
  def _tool_diffmap(self):
92
- def _diffmap(request: DiffMapModel, adinfo: self.AdataInfo=self.AdataInfo()):
93
+ def _diffmap(request: DiffMapParams, adinfo: self.AdataInfo=self.AdataInfo()):
93
94
  """Diffusion Maps for dimensionality reduction"""
94
95
  try:
95
96
  result = forward_request("tl_diffmap", request, adinfo)
@@ -109,10 +110,10 @@ class ScanpyToolsMCP(BaseMCP):
109
110
  raise ToolError(e.__context__)
110
111
  else:
111
112
  raise ToolError(e)
112
- return _diffmap
113
+ return Tool.from_function(_diffmap, name="diffmap")
113
114
 
114
115
  def _tool_embedding_density(self):
115
- def _embedding_density(request: EmbeddingDensityModel, adinfo: self.AdataInfo=self.AdataInfo()):
116
+ def _embedding_density(request: EmbeddingDensityParams, adinfo: self.AdataInfo=self.AdataInfo()):
116
117
  """Calculate the density of cells in an embedding"""
117
118
  try:
118
119
  result = forward_request("tl_embedding_density", request, adinfo)
@@ -131,10 +132,10 @@ class ScanpyToolsMCP(BaseMCP):
131
132
  raise ToolError(e.__context__)
132
133
  else:
133
134
  raise ToolError(e)
134
- return _embedding_density
135
+ return Tool.from_function(_embedding_density, name="embedding_density")
135
136
 
136
137
  def _tool_leiden(self):
137
- def _leiden(request: LeidenModel=LeidenModel(), adinfo: self.AdataInfo=self.AdataInfo()):
138
+ def _leiden(request: LeidenParams=LeidenParams(), adinfo: self.AdataInfo=self.AdataInfo()):
138
139
  """Leiden clustering algorithm for community detection"""
139
140
  try:
140
141
  result = forward_request("tl_leiden", request, adinfo)
@@ -153,10 +154,10 @@ class ScanpyToolsMCP(BaseMCP):
153
154
  raise ToolError(e.__context__)
154
155
  else:
155
156
  raise ToolError(e)
156
- return _leiden
157
+ return Tool.from_function(_leiden, name="leiden")
157
158
 
158
159
  def _tool_louvain(self):
159
- def _louvain(request: LouvainModel=LouvainModel(), adinfo: self.AdataInfo=self.AdataInfo()):
160
+ def _louvain(request: LouvainParams=LouvainParams(), adinfo: self.AdataInfo=self.AdataInfo()):
160
161
  """Louvain clustering algorithm for community detection"""
161
162
  try:
162
163
  result = forward_request("tl_louvain", request, adinfo)
@@ -175,10 +176,10 @@ class ScanpyToolsMCP(BaseMCP):
175
176
  raise ToolError(e.__context__)
176
177
  else:
177
178
  raise ToolError(e)
178
- return _louvain
179
+ return Tool.from_function(_louvain, name="louvain")
179
180
 
180
181
  def _tool_dendrogram(self):
181
- def _dendrogram(request: DendrogramModel, adinfo: self.AdataInfo=self.AdataInfo()):
182
+ def _dendrogram(request: DendrogramParams, adinfo: self.AdataInfo=self.AdataInfo()):
182
183
  """Hierarchical clustering dendrogram"""
183
184
  try:
184
185
  result = forward_request("tl_dendrogram", request, adinfo)
@@ -197,10 +198,10 @@ class ScanpyToolsMCP(BaseMCP):
197
198
  raise ToolError(e.__context__)
198
199
  else:
199
200
  raise ToolError(e)
200
- return _dendrogram
201
+ return Tool.from_function(_dendrogram, name="dendrogram")
201
202
 
202
203
  def _tool_dpt(self):
203
- def _dpt(request: DPTModel, adinfo: self.AdataInfo=self.AdataInfo()):
204
+ def _dpt(request: DPTParams, adinfo: self.AdataInfo=self.AdataInfo()):
204
205
  """Diffusion Pseudotime (DPT) analysis"""
205
206
  try:
206
207
  result = forward_request("tl_dpt", request, adinfo)
@@ -219,10 +220,10 @@ class ScanpyToolsMCP(BaseMCP):
219
220
  raise ToolError(e.__context__)
220
221
  else:
221
222
  raise ToolError(e)
222
- return _dpt
223
+ return Tool.from_function(_dpt, name="dpt")
223
224
 
224
225
  def _tool_paga(self):
225
- def _paga(request: PAGAModel, adinfo: self.AdataInfo=self.AdataInfo()):
226
+ def _paga(request: PAGAParams, adinfo: self.AdataInfo=self.AdataInfo()):
226
227
  """Partition-based graph abstraction"""
227
228
  try:
228
229
  result = forward_request("tl_paga", request, adinfo)
@@ -241,10 +242,10 @@ class ScanpyToolsMCP(BaseMCP):
241
242
  raise ToolError(e.__context__)
242
243
  else:
243
244
  raise ToolError(e)
244
- return _paga
245
+ return Tool.from_function(_paga, name="paga")
245
246
 
246
247
  def _tool_ingest(self):
247
- def _ingest(request: IngestModel, adinfo: self.AdataInfo=self.AdataInfo()):
248
+ def _ingest(request: IngestParams, adinfo: self.AdataInfo=self.AdataInfo()):
248
249
  """Map labels and embeddings from reference data to new data"""
249
250
  try:
250
251
  result = forward_request("tl_ingest", request, adinfo)
@@ -263,10 +264,10 @@ class ScanpyToolsMCP(BaseMCP):
263
264
  raise ToolError(e.__context__)
264
265
  else:
265
266
  raise ToolError(e)
266
- return _ingest
267
+ return Tool.from_function(_ingest, name="ingest")
267
268
 
268
269
  def _tool_rank_genes_groups(self):
269
- def _rank_genes_groups(request: RankGenesGroupsModel, adinfo: self.AdataInfo=self.AdataInfo()):
270
+ def _rank_genes_groups(request: RankGenesGroupsParams, adinfo: self.AdataInfo=self.AdataInfo()):
270
271
  """Rank genes for characterizing groups, for differentially expressison analysis"""
271
272
  try:
272
273
  result = forward_request("tl_rank_genes_groups", request, adinfo)
@@ -285,10 +286,10 @@ class ScanpyToolsMCP(BaseMCP):
285
286
  raise ToolError(e.__context__)
286
287
  else:
287
288
  raise ToolError(e)
288
- return _rank_genes_groups
289
+ return Tool.from_function(_rank_genes_groups, name="rank_genes_groups")
289
290
 
290
291
  def _tool_filter_rank_genes_groups(self):
291
- def _filter_rank_genes_groups(request: FilterRankGenesGroupsModel, adinfo: self.AdataInfo=self.AdataInfo()):
292
+ def _filter_rank_genes_groups(request: FilterRankGenesGroupsParams, adinfo: self.AdataInfo=self.AdataInfo()):
292
293
  """Filter out genes based on fold change and fraction of genes"""
293
294
  try:
294
295
  result = forward_request("tl_filter_rank_genes_groups", request, adinfo)
@@ -307,10 +308,10 @@ class ScanpyToolsMCP(BaseMCP):
307
308
  raise ToolError(e.__context__)
308
309
  else:
309
310
  raise ToolError(e)
310
- return _filter_rank_genes_groups
311
+ return Tool.from_function(_filter_rank_genes_groups, name="filter_rank_genes_groups")
311
312
 
312
313
  def _tool_marker_gene_overlap(self):
313
- def _marker_gene_overlap(request: MarkerGeneOverlapModel, adinfo: self.AdataInfo=self.AdataInfo()):
314
+ def _marker_gene_overlap(request: MarkerGeneOverlapParams, adinfo: self.AdataInfo=self.AdataInfo()):
314
315
  """Calculate overlap between data-derived marker genes and reference markers"""
315
316
  try:
316
317
  result = forward_request("tl_marker_gene_overlap", request, adinfo)
@@ -329,10 +330,10 @@ class ScanpyToolsMCP(BaseMCP):
329
330
  raise ToolError(e.__context__)
330
331
  else:
331
332
  raise ToolError(e)
332
- return _marker_gene_overlap
333
+ return Tool.from_function(_marker_gene_overlap, name="marker_gene_overlap")
333
334
 
334
335
  def _tool_score_genes(self):
335
- def _score_genes(request: ScoreGenesModel, adinfo: self.AdataInfo=self.AdataInfo()):
336
+ def _score_genes(request: ScoreGenesParams, adinfo: self.AdataInfo=self.AdataInfo()):
336
337
  """Score a set of genes based on their average expression"""
337
338
  try:
338
339
  result = forward_request("tl_score_genes", request, adinfo)
@@ -351,10 +352,10 @@ class ScanpyToolsMCP(BaseMCP):
351
352
  raise ToolError(e.__context__)
352
353
  else:
353
354
  raise ToolError(e)
354
- return _score_genes
355
+ return Tool.from_function(_score_genes, name="score_genes")
355
356
 
356
357
  def _tool_score_genes_cell_cycle(self):
357
- def _score_genes_cell_cycle(request: ScoreGenesCellCycleModel, adinfo: self.AdataInfo=self.AdataInfo()):
358
+ def _score_genes_cell_cycle(request: ScoreGenesCellCycleParams, adinfo: self.AdataInfo=self.AdataInfo()):
358
359
  """Score cell cycle genes and assign cell cycle phases"""
359
360
  try:
360
361
  result = forward_request("tl_score_genes_cell_cycle", request, adinfo)
@@ -373,10 +374,10 @@ class ScanpyToolsMCP(BaseMCP):
373
374
  raise ToolError(e.__context__)
374
375
  else:
375
376
  raise ToolError(e)
376
- return _score_genes_cell_cycle
377
+ return Tool.from_function(_score_genes_cell_cycle, name="score_genes_cell_cycle")
377
378
 
378
379
  def _tool_pca(self):
379
- def _pca(request: PCAModel=PCAModel(), adinfo: self.AdataInfo=self.AdataInfo()):
380
+ def _pca(request: PCAParams=PCAParams(), adinfo: self.AdataInfo=self.AdataInfo()):
380
381
  """Compute PCA (Principal Component Analysis)."""
381
382
  try:
382
383
  result = forward_request("tl_pca", request, adinfo)
@@ -395,4 +396,4 @@ class ScanpyToolsMCP(BaseMCP):
395
396
  raise ToolError(e.__context__)
396
397
  else:
397
398
  raise ToolError(e)
398
- return _pca
399
+ return Tool.from_function(_pca, name="pca")