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

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

Browse files
auto-sklearn/mcp_output/mcp_plugin/mcp_service.py CHANGED
@@ -1,451 +1,260 @@
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
 
 
 
 
 
 
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