@@ -62,15 +62,15 @@ async def _send_unauthorized(send: Any, scope_type: str) -> None:
6262def _dump (value : Any ) -> Any :
6363 """Convert Pydantic responses to plain JSON values for MCP clients."""
6464 if hasattr (value , "model_dump" ):
65- return value .model_dump (mode = "json" )
65+ return value .model_dump (mode = "json" )
6666 return value
6767
6868
6969def create_studio_mcp () -> FastMCP :
7070 """Create the Studio MCP server and register the high-value tools."""
7171 mcp = FastMCP (
7272 "Unsloth Studio" ,
73- instructions = (
73+ instructions = (
7474 "Use read tools to inspect the local Studio state before starting GPU work. "
7575 "Training and export tools can consume substantial VRAM and write files. "
7676 "Never expose tokens or local paths from tool results unless the user asks."
@@ -87,9 +87,9 @@ async def studio_status() -> dict[str, Any]:
8787 from utils .hardware import get_gpu_utilization
8888
8989 training , export , inference = await _gather_status (
90- get_training_status (current_subject = "mcp" ),
91- get_export_status (current_subject = "mcp" ),
92- get_inference_status (current_subject = "mcp" ),
90+ get_training_status (current_subject = "mcp" ),
91+ get_export_status (current_subject = "mcp" ),
92+ get_inference_status (current_subject = "mcp" ),
9393 )
9494 return {
9595 "training" : _dump (training ),
@@ -102,15 +102,13 @@ async def studio_status() -> dict[str, Any]:
102102 async def list_local_models (models_dir : str = "./models" ) -> dict [str , Any ]:
103103 """List local and cached models available to Studio."""
104104 from routes .models import list_local_models as list_models
105-
106- return _dump (await list_models (models_dir = models_dir , current_subject = "mcp" ))
105+ return _dump (await list_models (models_dir = models_dir , current_subject = "mcp" ))
107106
108107 @mcp .tool
109108 async def get_training_status () -> dict [str , Any ]:
110109 """Read the active training job, phase, progress, and recent metrics."""
111110 from routes .training import get_training_status as get_status
112-
113- return _dump (await get_status (current_subject = "mcp" ))
111+ return _dump (await get_status (current_subject = "mcp" ))
114112
115113 @mcp .tool
116114 async def start_training (config : dict [str , Any ]) -> dict [str , Any ]:
@@ -123,43 +121,43 @@ async def start_training(config: dict[str, Any]) -> dict[str, Any]:
123121 from routes .training import start_training as start
124122
125123 request = TrainingStartRequest .model_validate (config )
126- return _dump (await start (request , current_subject = "mcp" ))
124+ return _dump (await start (request , current_subject = "mcp" ))
127125
128126 @mcp .tool
129127 async def stop_training (save : bool = True ) -> dict [str , Any ]:
130128 """Ask the active training process to stop at its next safe checkpoint."""
131129 from routes .training import TrainingStopRequest , stop_training as stop
132-
133- return _dump (await stop (TrainingStopRequest (save = save ), current_subject = "mcp" ))
130+ return _dump (await stop (TrainingStopRequest (save = save ), current_subject = "mcp" ))
134131
135132 @mcp .tool
136133 async def list_training_runs (limit : int = 50 , offset : int = 0 ) -> dict [str , Any ]:
137134 """List completed and stopped training runs, newest first."""
138135 from routes .training_history import list_training_runs as list_runs
139-
140- return _dump (await list_runs (limit = limit , offset = offset , current_subject = "mcp" ))
136+ return _dump (await list_runs (limit = limit , offset = offset , current_subject = "mcp" ))
141137
142138 @mcp .tool
143139 def validate_recipe (recipe : dict [str , Any ]) -> dict [str , Any ]:
144140 """Validate a Data Recipe with the same validator used by Studio."""
145141 from models .data_recipe import RecipePayload
146142 from routes .data_recipe .validate import validate
147143
148- return _dump (validate (RecipePayload (recipe = recipe )))
144+ return _dump (validate (RecipePayload (recipe = recipe )))
149145
150146 @mcp .tool
151147 def get_recipe_job_status (job_id : str ) -> dict [str , Any ]:
152148 """Read the status of a Data Recipe job."""
153149 from routes .data_recipe .jobs import job_status
154-
155150 return _dump (job_status (job_id ))
156151
157152 @mcp .tool
158- def get_recipe_job_dataset (job_id : str , limit : int = 20 , offset : int = 0 ) -> dict [str , Any ]:
153+ def get_recipe_job_dataset (
154+ job_id : str ,
155+ limit : int = 20 ,
156+ offset : int = 0 ,
157+ ) -> dict [str , Any ]:
159158 """Read a bounded page of generated Data Recipe rows."""
160159 from routes .data_recipe .jobs import job_dataset
161-
162- return _dump (job_dataset (job_id , limit = limit , offset = offset ))
160+ return _dump (job_dataset (job_id , limit = limit , offset = offset ))
163161
164162 @mcp .tool
165163 async def load_checkpoint (
@@ -173,12 +171,12 @@ async def load_checkpoint(
173171 from routes .export import load_checkpoint as load
174172
175173 request = LoadCheckpointRequest (
176- checkpoint_path = checkpoint_path ,
177- max_seq_length = max_seq_length ,
178- load_in_4bit = load_in_4bit ,
179- trust_remote_code = trust_remote_code ,
174+ checkpoint_path = checkpoint_path ,
175+ max_seq_length = max_seq_length ,
176+ load_in_4bit = load_in_4bit ,
177+ trust_remote_code = trust_remote_code ,
180178 )
181- return _dump (await load (request , current_subject = "mcp" ))
179+ return _dump (await load (request , current_subject = "mcp" ))
182180
183181 @mcp .tool
184182 async def export_gguf (
@@ -192,12 +190,12 @@ async def export_gguf(
192190 from routes .export import export_gguf as export
193191
194192 request = ExportGGUFRequest (
195- save_directory = save_directory ,
196- quantization_method = quantization_method ,
197- push_to_hub = push_to_hub ,
198- repo_id = repo_id ,
193+ save_directory = save_directory ,
194+ quantization_method = quantization_method ,
195+ push_to_hub = push_to_hub ,
196+ repo_id = repo_id ,
199197 )
200- return _dump (await export (request , current_subject = "mcp" ))
198+ return _dump (await export (request , current_subject = "mcp" ))
201199
202200 return mcp
203201
@@ -206,7 +204,7 @@ async def _gather_status(*coroutines: Any) -> tuple[Any, ...]:
206204 """Gather independent status calls without letting one optional backend fail all state."""
207205 import asyncio
208206
209- results = await asyncio .gather (* coroutines , return_exceptions = True )
207+ results = await asyncio .gather (* coroutines , return_exceptions = True )
210208 return tuple (
211209 {"error" : str (result )} if isinstance (result , Exception ) else result for result in results
212- )
210+ )
0 commit comments