guohanghui commited on
Commit
a2d1b96
·
verified ·
1 Parent(s): c56cb87

Update auto-sklearn/mcp_output/mcp_plugin/mcp_service.py

Browse files
auto-sklearn/mcp_output/mcp_plugin/mcp_service.py CHANGED
@@ -1,260 +1,451 @@
 
 
 
 
 
1
  from fastmcp import FastMCP
 
 
 
 
2
 
3
  # Create the FastMCP service application
4
  mcp = FastMCP("auto_sklearn_service")
5
 
6
- # Define tools here following the AgML MCP structure
 
 
 
7
 
8
- # Example tool
9
- @mcp.tool(name="example_tool", description="Example tool description")
10
- def example_tool() -> dict:
11
  """
12
- Example tool function.
13
 
14
  Returns:
15
- - dict: Example response.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  """
17
- return {"success": True, "message": "This is an example tool."}
 
 
 
 
 
 
 
 
 
 
18
 
19
- @mcp.tool(name="load_dataset", description="Load a dataset using auto-sklearn")
20
- def load_dataset(dataset_name: str) -> dict:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  """
22
- Load a dataset using auto-sklearn.
23
 
24
  Parameters:
25
- - dataset_name: Name of the dataset to load (e.g., 'breast_cancer')
 
 
 
 
 
 
 
26
 
27
  Returns:
28
- - dict: Information about the loaded dataset.
29
  """
30
  try:
31
- import sklearn.datasets
32
- X, y = sklearn.datasets.fetch_openml(data_id=dataset_name, return_X_y=True, as_frame=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  return {
34
  "success": True,
35
- "dataset_name": dataset_name,
36
- "num_samples": len(X),
37
- "num_features": X.shape[1],
38
- "num_classes": len(set(y))
 
 
 
39
  }
40
  except Exception as e:
41
- return {"success": False, "error": str(e)}
42
 
43
 
44
- @mcp.tool(name="create_classifier", description="Create an AutoSklearnClassifier")
45
- def create_classifier(time_limit: int, per_run_time_limit: int, memory_limit: int = 3072) -> dict:
46
  """
47
- Create an AutoSklearnClassifier instance.
48
 
49
  Parameters:
50
- - time_limit: Total time limit for the AutoML process.
51
- - per_run_time_limit: Time limit for each model training.
52
- - memory_limit: Memory limit for each model training (default: 3072MB).
53
 
54
  Returns:
55
- - dict: Information about the created classifier.
56
  """
57
  try:
58
- import autosklearn.classification
59
- classifier = autosklearn.classification.AutoSklearnClassifier(
60
- time_left_for_this_task=time_limit,
61
- per_run_time_limit=per_run_time_limit,
62
- memory_limit=memory_limit
63
- )
 
 
 
64
  return {
65
  "success": True,
66
- "message": "Classifier created successfully",
67
- "time_limit": time_limit,
68
- "per_run_time_limit": per_run_time_limit,
69
- "memory_limit": memory_limit
 
 
 
70
  }
71
  except Exception as e:
72
- return {"success": False, "error": str(e)}
73
 
74
 
75
- @mcp.tool(name="fit_classifier", description="Fit the AutoSklearnClassifier")
76
- def fit_classifier(classifier, X_train, y_train, dataset_name: str) -> dict:
77
  """
78
- Fit the AutoSklearnClassifier on the training data.
79
 
80
  Parameters:
81
- - classifier: The AutoSklearnClassifier instance.
82
- - X_train: Training features.
83
- - y_train: Training labels.
84
- - dataset_name: Name of the dataset.
85
 
86
  Returns:
87
- - dict: Information about the fitting process.
88
  """
89
  try:
90
- classifier.fit(X_train, y_train, dataset_name=dataset_name)
 
 
 
 
 
 
 
 
91
  return {
92
  "success": True,
93
- "message": "Classifier fitted successfully",
94
- "dataset_name": dataset_name
 
 
 
 
 
95
  }
96
  except Exception as e:
97
- return {"success": False, "error": str(e)}
98
 
99
 
100
- @mcp.tool(name="predict", description="Make predictions using the trained classifier")
101
- def predict(classifier, X_test) -> dict:
102
  """
103
- Make predictions using the trained AutoSklearnClassifier.
104
 
105
  Parameters:
106
- - classifier: The trained AutoSklearnClassifier instance.
107
- - X_test: Test features.
108
 
109
  Returns:
110
- - dict: Predictions and success status.
111
  """
112
  try:
113
- predictions = classifier.predict(X_test)
 
 
 
 
 
 
 
114
  return {
115
  "success": True,
116
- "predictions": predictions.tolist()
 
 
 
 
117
  }
118
  except Exception as e:
119
- return {"success": False, "error": str(e)}
120
 
121
 
122
- @mcp.tool(name="optimize_hyperparameters", description="Optimize hyperparameters using AutoSklearn")
123
- def optimize_hyperparameters(X_train, y_train, time_limit: int, per_run_time_limit: int, memory_limit: int = 3072) -> dict:
124
  """
125
- Optimize hyperparameters using AutoSklearn.
126
 
127
  Parameters:
128
- - X_train: Training features.
129
- - y_train: Training labels.
130
- - time_limit: Total time limit for the AutoML process.
131
- - per_run_time_limit: Time limit for each model training.
132
- - memory_limit: Memory limit for each model training (default: 3072MB).
133
 
134
  Returns:
135
- - dict: Optimization results and best model information.
136
  """
137
  try:
138
- import autosklearn.classification
139
- automl = autosklearn.classification.AutoSklearnClassifier(
140
- time_left_for_this_task=time_limit,
141
- per_run_time_limit=per_run_time_limit,
142
- memory_limit=memory_limit
143
- )
144
- automl.fit(X_train, y_train)
 
145
  return {
146
  "success": True,
147
- "message": "Hyperparameter optimization completed successfully",
148
- "best_model": automl.show_models(),
149
- "statistics": automl.sprint_statistics()
 
 
150
  }
151
  except Exception as e:
152
- return {"success": False, "error": str(e)}
153
 
154
 
155
- @mcp.tool(name="evaluate_model", description="Evaluate a trained model on test data")
156
- def evaluate_model(classifier, X_test, y_test) -> dict:
157
  """
158
- Evaluate a trained model on test data.
159
 
160
  Parameters:
161
- - classifier: The trained AutoSklearnClassifier instance.
162
- - X_test: Test features.
163
- - y_test: Test labels.
164
 
165
  Returns:
166
- - dict: Evaluation metrics.
167
  """
168
  try:
169
- import sklearn.metrics
170
- predictions = classifier.predict(X_test)
171
- accuracy = sklearn.metrics.accuracy_score(y_test, predictions)
 
 
 
 
 
172
  return {
173
  "success": True,
174
- "accuracy": accuracy,
175
- "message": "Model evaluation completed successfully"
 
 
 
 
176
  }
177
  except Exception as e:
178
- return {"success": False, "error": str(e)}
179
 
180
 
181
- @mcp.tool(name="get_pipeline_components", description="Get pipeline components used by AutoSklearn")
182
- def get_pipeline_components() -> dict:
183
  """
184
- Get pipeline components used by AutoSklearn.
 
 
 
185
 
186
  Returns:
187
- - dict: Information about pipeline components.
188
  """
189
  try:
190
- import autosklearn.pipeline.components.classification as classification_components
191
- import autosklearn.pipeline.components.feature_preprocessing as preprocessing_components
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
- classifiers = classification_components.ClassifierChoice.get_components()
194
- preprocessors = preprocessing_components.PreprocessorChoice.get_components()
195
 
 
 
 
 
 
 
 
 
 
196
  return {
197
  "success": True,
198
- "classifiers": list(classifiers.keys()),
199
- "preprocessors": list(preprocessors.keys())
 
 
 
 
200
  }
201
  except Exception as e:
202
- return {"success": False, "error": str(e)}
203
 
204
 
205
- @mcp.tool(name="meta_learning", description="Perform meta-learning using AutoSklearn")
206
- def meta_learning(meta_features: dict, time_limit: int, per_run_time_limit: int) -> dict:
207
  """
208
- Perform meta-learning using AutoSklearn.
209
 
210
  Parameters:
211
- - meta_features: A dictionary of meta-features for the dataset.
212
- - time_limit: Total time limit for the meta-learning process.
213
- - per_run_time_limit: Time limit for each meta-learning iteration.
214
 
215
  Returns:
216
- - dict: Meta-learning results.
217
  """
218
  try:
219
- from autosklearn.metalearning import MetaLearning
220
-
221
- meta_learner = MetaLearning(meta_features)
222
- meta_learner.run(time_limit=time_limit, per_run_time_limit=per_run_time_limit)
223
-
224
  return {
225
  "success": True,
226
- "message": "Meta-learning completed successfully",
227
- "recommendations": meta_learner.get_recommendations()
228
  }
229
  except Exception as e:
230
- return {"success": False, "error": str(e)}
231
 
232
 
233
- @mcp.tool(name="get_model_leaderboard", description="Retrieve the leaderboard of models")
234
- def get_model_leaderboard(classifier) -> dict:
235
  """
236
- Retrieve the leaderboard of models from AutoSklearn.
237
 
238
  Parameters:
239
- - classifier: The AutoSklearnClassifier instance.
240
 
241
  Returns:
242
- - dict: Leaderboard information.
243
  """
244
  try:
245
- leaderboard = classifier.leaderboard()
 
 
 
 
246
  return {
247
  "success": True,
248
- "leaderboard": leaderboard
 
249
  }
250
  except Exception as e:
251
- return {"success": False, "error": str(e)}}
 
252
 
253
  def create_app() -> FastMCP:
254
  """
255
  Create and return the FastMCP application instance.
256
 
257
  Returns:
258
- - FastMCP: The FastMCP application instance.
259
  """
260
- return mcp
 
1
+ import os
2
+ import sys
3
+ from typing import Dict, Any, List, Optional
4
+ import json
5
+
6
  from fastmcp import FastMCP
7
+ import numpy as np
8
+
9
+ # Import core modules from installed auto-sklearn package
10
+ from autosklearn.estimators import AutoSklearnClassifier, AutoSklearnRegressor
11
 
12
  # Create the FastMCP service application
13
  mcp = FastMCP("auto_sklearn_service")
14
 
15
+ # Store models by ID
16
+ _classifiers: Dict[str, AutoSklearnClassifier] = {}
17
+ _regressors: Dict[str, AutoSklearnRegressor] = {}
18
+
19
 
20
+ @mcp.tool(name="get_library_info")
21
+ def get_library_info() -> dict:
 
22
  """
23
+ Get information about the auto-sklearn library.
24
 
25
  Returns:
26
+ dict: Version and configuration information.
27
+ """
28
+ try:
29
+ from autosklearn import __version__
30
+
31
+ return {
32
+ "success": True,
33
+ "result": {
34
+ "library": "auto-sklearn",
35
+ "version": __version__,
36
+ "estimators": ["AutoSklearnClassifier", "AutoSklearnRegressor"],
37
+ "features": [
38
+ "Automated Machine Learning",
39
+ "Ensemble Learning",
40
+ "Meta-learning",
41
+ "Hyperparameter Optimization (SMAC)",
42
+ ],
43
+ },
44
+ "error": None,
45
+ }
46
+ except Exception as e:
47
+ return {"success": False, "result": None, "error": str(e)}
48
+
49
+
50
+ @mcp.tool(name="create_classifier")
51
+ def create_classifier(
52
+ classifier_id: str,
53
+ time_left_for_this_task: int = 3600,
54
+ per_run_time_limit: Optional[int] = None,
55
+ ensemble_size: int = 50,
56
+ ensemble_nbest: int = 50,
57
+ seed: int = 1,
58
+ memory_limit: int = 3072,
59
+ n_jobs: Optional[int] = None,
60
+ ) -> dict:
61
  """
62
+ Create a new AutoSklearnClassifier.
63
+
64
+ Parameters:
65
+ classifier_id (str): Unique identifier for the classifier.
66
+ time_left_for_this_task (int): Total time budget in seconds.
67
+ per_run_time_limit (Optional[int]): Time limit per model evaluation.
68
+ ensemble_size (int): Number of models in the final ensemble.
69
+ ensemble_nbest (int): Consider only the best n models for ensemble.
70
+ seed (int): Random seed.
71
+ memory_limit (int): Memory limit in MB.
72
+ n_jobs (Optional[int]): Number of parallel jobs.
73
 
74
+ Returns:
75
+ dict: Success status and classifier information.
76
+ """
77
+ try:
78
+ if classifier_id in _classifiers:
79
+ return {"success": False, "result": None, "error": f"Classifier '{classifier_id}' already exists"}
80
+
81
+ clf = AutoSklearnClassifier(
82
+ time_left_for_this_task=time_left_for_this_task,
83
+ per_run_time_limit=per_run_time_limit,
84
+ ensemble_size=ensemble_size,
85
+ ensemble_nbest=ensemble_nbest,
86
+ seed=seed,
87
+ memory_limit=memory_limit,
88
+ n_jobs=n_jobs,
89
+ )
90
+
91
+ _classifiers[classifier_id] = clf
92
+
93
+ return {
94
+ "success": True,
95
+ "result": {
96
+ "classifier_id": classifier_id,
97
+ "time_budget": time_left_for_this_task,
98
+ "ensemble_size": ensemble_size,
99
+ "message": "Classifier created successfully",
100
+ },
101
+ "error": None,
102
+ }
103
+ except Exception as e:
104
+ return {"success": False, "result": None, "error": str(e)}
105
+
106
+
107
+ @mcp.tool(name="create_regressor")
108
+ def create_regressor(
109
+ regressor_id: str,
110
+ time_left_for_this_task: int = 3600,
111
+ per_run_time_limit: Optional[int] = None,
112
+ ensemble_size: int = 50,
113
+ ensemble_nbest: int = 50,
114
+ seed: int = 1,
115
+ memory_limit: int = 3072,
116
+ n_jobs: Optional[int] = None,
117
+ ) -> dict:
118
  """
119
+ Create a new AutoSklearnRegressor.
120
 
121
  Parameters:
122
+ regressor_id (str): Unique identifier for the regressor.
123
+ time_left_for_this_task (int): Total time budget in seconds.
124
+ per_run_time_limit (Optional[int]): Time limit per model evaluation.
125
+ ensemble_size (int): Number of models in the final ensemble.
126
+ ensemble_nbest (int): Consider only the best n models for ensemble.
127
+ seed (int): Random seed.
128
+ memory_limit (int): Memory limit in MB.
129
+ n_jobs (Optional[int]): Number of parallel jobs.
130
 
131
  Returns:
132
+ dict: Success status and regressor information.
133
  """
134
  try:
135
+ if regressor_id in _regressors:
136
+ return {"success": False, "result": None, "error": f"Regressor '{regressor_id}' already exists"}
137
+
138
+ reg = AutoSklearnRegressor(
139
+ time_left_for_this_task=time_left_for_this_task,
140
+ per_run_time_limit=per_run_time_limit,
141
+ ensemble_size=ensemble_size,
142
+ ensemble_nbest=ensemble_nbest,
143
+ seed=seed,
144
+ memory_limit=memory_limit,
145
+ n_jobs=n_jobs,
146
+ )
147
+
148
+ _regressors[regressor_id] = reg
149
+
150
  return {
151
  "success": True,
152
+ "result": {
153
+ "regressor_id": regressor_id,
154
+ "time_budget": time_left_for_this_task,
155
+ "ensemble_size": ensemble_size,
156
+ "message": "Regressor created successfully",
157
+ },
158
+ "error": None,
159
  }
160
  except Exception as e:
161
+ return {"success": False, "result": None, "error": str(e)}
162
 
163
 
164
+ @mcp.tool(name="fit_classifier")
165
+ def fit_classifier(classifier_id: str, X_train: List[List[float]], y_train: List) -> dict:
166
  """
167
+ Fit a classifier with training data.
168
 
169
  Parameters:
170
+ classifier_id (str): ID of the classifier to fit.
171
+ X_train (List[List[float]]): Training features.
172
+ y_train (List): Training labels.
173
 
174
  Returns:
175
+ dict: Success status and fitting information.
176
  """
177
  try:
178
+ if classifier_id not in _classifiers:
179
+ return {"success": False, "result": None, "error": f"Classifier '{classifier_id}' not found"}
180
+
181
+ clf = _classifiers[classifier_id]
182
+ X_train_np = np.array(X_train)
183
+ y_train_np = np.array(y_train)
184
+
185
+ clf.fit(X_train_np, y_train_np)
186
+
187
  return {
188
  "success": True,
189
+ "result": {
190
+ "classifier_id": classifier_id,
191
+ "num_samples": len(X_train),
192
+ "num_features": len(X_train[0]) if X_train else 0,
193
+ "message": "Classifier fitted successfully",
194
+ },
195
+ "error": None,
196
  }
197
  except Exception as e:
198
+ return {"success": False, "result": None, "error": str(e)}
199
 
200
 
201
+ @mcp.tool(name="fit_regressor")
202
+ def fit_regressor(regressor_id: str, X_train: List[List[float]], y_train: List[float]) -> dict:
203
  """
204
+ Fit a regressor with training data.
205
 
206
  Parameters:
207
+ regressor_id (str): ID of the regressor to fit.
208
+ X_train (List[List[float]]): Training features.
209
+ y_train (List[float]): Training targets.
 
210
 
211
  Returns:
212
+ dict: Success status and fitting information.
213
  """
214
  try:
215
+ if regressor_id not in _regressors:
216
+ return {"success": False, "result": None, "error": f"Regressor '{regressor_id}' not found"}
217
+
218
+ reg = _regressors[regressor_id]
219
+ X_train_np = np.array(X_train)
220
+ y_train_np = np.array(y_train)
221
+
222
+ reg.fit(X_train_np, y_train_np)
223
+
224
  return {
225
  "success": True,
226
+ "result": {
227
+ "regressor_id": regressor_id,
228
+ "num_samples": len(X_train),
229
+ "num_features": len(X_train[0]) if X_train else 0,
230
+ "message": "Regressor fitted successfully",
231
+ },
232
+ "error": None,
233
  }
234
  except Exception as e:
235
+ return {"success": False, "result": None, "error": str(e)}
236
 
237
 
238
+ @mcp.tool(name="predict_classifier")
239
+ def predict_classifier(classifier_id: str, X_test: List[List[float]]) -> dict:
240
  """
241
+ Make predictions using a fitted classifier.
242
 
243
  Parameters:
244
+ classifier_id (str): ID of the classifier.
245
+ X_test (List[List[float]]): Test features.
246
 
247
  Returns:
248
+ dict: Predictions.
249
  """
250
  try:
251
+ if classifier_id not in _classifiers:
252
+ return {"success": False, "result": None, "error": f"Classifier '{classifier_id}' not found"}
253
+
254
+ clf = _classifiers[classifier_id]
255
+ X_test_np = np.array(X_test)
256
+
257
+ predictions = clf.predict(X_test_np)
258
+
259
  return {
260
  "success": True,
261
+ "result": {
262
+ "predictions": predictions.tolist(),
263
+ "num_predictions": len(predictions),
264
+ },
265
+ "error": None,
266
  }
267
  except Exception as e:
268
+ return {"success": False, "result": None, "error": str(e)}
269
 
270
 
271
+ @mcp.tool(name="predict_regressor")
272
+ def predict_regressor(regressor_id: str, X_test: List[List[float]]) -> dict:
273
  """
274
+ Make predictions using a fitted regressor.
275
 
276
  Parameters:
277
+ regressor_id (str): ID of the regressor.
278
+ X_test (List[List[float]]): Test features.
 
 
 
279
 
280
  Returns:
281
+ dict: Predictions.
282
  """
283
  try:
284
+ if regressor_id not in _regressors:
285
+ return {"success": False, "result": None, "error": f"Regressor '{regressor_id}' not found"}
286
+
287
+ reg = _regressors[regressor_id]
288
+ X_test_np = np.array(X_test)
289
+
290
+ predictions = reg.predict(X_test_np)
291
+
292
  return {
293
  "success": True,
294
+ "result": {
295
+ "predictions": predictions.tolist(),
296
+ "num_predictions": len(predictions),
297
+ },
298
+ "error": None,
299
  }
300
  except Exception as e:
301
+ return {"success": False, "result": None, "error": str(e)}
302
 
303
 
304
+ @mcp.tool(name="get_classifier_model_performance")
305
+ def get_classifier_model_performance(classifier_id: str) -> dict:
306
  """
307
+ Get performance statistics of explored models.
308
 
309
  Parameters:
310
+ classifier_id (str): ID of the classifier.
 
 
311
 
312
  Returns:
313
+ dict: Performance statistics.
314
  """
315
  try:
316
+ if classifier_id not in _classifiers:
317
+ return {"success": False, "result": None, "error": f"Classifier '{classifier_id}' not found"}
318
+
319
+ clf = _classifiers[classifier_id]
320
+
321
+ # Get leaderboard information
322
+ leaderboard = clf.leaderboard()
323
+
324
  return {
325
  "success": True,
326
+ "result": {
327
+ "classifier_id": classifier_id,
328
+ "num_models": len(leaderboard) if leaderboard is not None else 0,
329
+ "leaderboard_summary": leaderboard.head(10).to_dict() if leaderboard is not None else {},
330
+ },
331
+ "error": None,
332
  }
333
  except Exception as e:
334
+ return {"success": False, "result": None, "error": str(e)}
335
 
336
 
337
+ @mcp.tool(name="get_regressor_model_performance")
338
+ def get_regressor_model_performance(regressor_id: str) -> dict:
339
  """
340
+ Get performance statistics of explored models.
341
+
342
+ Parameters:
343
+ regressor_id (str): ID of the regressor.
344
 
345
  Returns:
346
+ dict: Performance statistics.
347
  """
348
  try:
349
+ if regressor_id not in _regressors:
350
+ return {"success": False, "result": None, "error": f"Regressor '{regressor_id}' not found"}
351
+
352
+ reg = _regressors[regressor_id]
353
+
354
+ # Get leaderboard information
355
+ leaderboard = reg.leaderboard()
356
+
357
+ return {
358
+ "success": True,
359
+ "result": {
360
+ "regressor_id": regressor_id,
361
+ "num_models": len(leaderboard) if leaderboard is not None else 0,
362
+ "leaderboard_summary": leaderboard.head(10).to_dict() if leaderboard is not None else {},
363
+ },
364
+ "error": None,
365
+ }
366
+ except Exception as e:
367
+ return {"success": False, "result": None, "error": str(e)}
368
 
 
 
369
 
370
+ @mcp.tool(name="list_models")
371
+ def list_models() -> dict:
372
+ """
373
+ List all stored classifiers and regressors.
374
+
375
+ Returns:
376
+ dict: List of model IDs.
377
+ """
378
+ try:
379
  return {
380
  "success": True,
381
+ "result": {
382
+ "classifiers": list(_classifiers.keys()),
383
+ "regressors": list(_regressors.keys()),
384
+ "total": len(_classifiers) + len(_regressors),
385
+ },
386
+ "error": None,
387
  }
388
  except Exception as e:
389
+ return {"success": False, "result": None, "error": str(e)}
390
 
391
 
392
+ @mcp.tool(name="delete_classifier")
393
+ def delete_classifier(classifier_id: str) -> dict:
394
  """
395
+ Delete a stored classifier.
396
 
397
  Parameters:
398
+ classifier_id (str): ID of the classifier to delete.
 
 
399
 
400
  Returns:
401
+ dict: Confirmation of deletion.
402
  """
403
  try:
404
+ if classifier_id not in _classifiers:
405
+ return {"success": False, "result": None, "error": f"Classifier '{classifier_id}' not found"}
406
+
407
+ del _classifiers[classifier_id]
408
+
409
  return {
410
  "success": True,
411
+ "result": {"message": f"Classifier '{classifier_id}' deleted"},
412
+ "error": None,
413
  }
414
  except Exception as e:
415
+ return {"success": False, "result": None, "error": str(e)}
416
 
417
 
418
+ @mcp.tool(name="delete_regressor")
419
+ def delete_regressor(regressor_id: str) -> dict:
420
  """
421
+ Delete a stored regressor.
422
 
423
  Parameters:
424
+ regressor_id (str): ID of the regressor to delete.
425
 
426
  Returns:
427
+ dict: Confirmation of deletion.
428
  """
429
  try:
430
+ if regressor_id not in _regressors:
431
+ return {"success": False, "result": None, "error": f"Regressor '{regressor_id}' not found"}
432
+
433
+ del _regressors[regressor_id]
434
+
435
  return {
436
  "success": True,
437
+ "result": {"message": f"Regressor '{regressor_id}' deleted"},
438
+ "error": None,
439
  }
440
  except Exception as e:
441
+ return {"success": False, "result": None, "error": str(e)}
442
+
443
 
444
  def create_app() -> FastMCP:
445
  """
446
  Create and return the FastMCP application instance.
447
 
448
  Returns:
449
+ FastMCP: the FastMCP application instance
450
  """
451
+ return mcp