1010import json
1111import typing
1212from functools import cached_property
13- from typing import Any
13+ from typing import Any , cast
1414
1515from mcp .types import Tool
1616
2727 CallbackDependency ,
2828 CallbackExecutionBody ,
2929 CallbackInput ,
30+ CallbackInputs ,
3031 CallbackOutput ,
3132 CallbackOutputTarget ,
3233 WildcardId ,
@@ -360,9 +361,7 @@ def _param_annotations(self) -> list[Any | None]:
360361 return [hints .get (func_name ) for func_name , _ in self ._dep_param_map ]
361362
362363
363- def _expand_dep (
364- dep : CallbackDependency , value : Any
365- ) -> CallbackInput | list [CallbackInput ]:
364+ def _expand_dep (dep : CallbackDependency , value : Any ) -> CallbackInputs :
366365 """Attach a concrete value to a callback dependency to produce a valid callback input.
367366
368367 For regular deps, returns ``{id, property, value}``.
@@ -371,20 +370,20 @@ def _expand_dep(
371370 """
372371 pattern = parse_wildcard_id (dep .get ("id" , "" ))
373372 if pattern is None :
374- return { ** dep , "value" : value }
373+ return CallbackInput ( id = dep [ "id" ], property = dep [ "property" ], value = value )
375374
376375 # LLM provides browser-like format
377376 if isinstance (value , list ):
378- return value
377+ return cast ( list [ CallbackInput ], value )
379378 if isinstance (value , dict ) and "id" in value :
380- return value
381- return { ** dep , "value" : value }
379+ return cast ( CallbackInput , value )
380+ return CallbackInput ( id = dep [ "id" ], property = dep [ "property" ], value = value )
382381
383382
384383def _expand_output_spec (
385384 output_id : str ,
386385 cb_info : dict ,
387- resolved_inputs : list [CallbackInput ],
386+ resolved_inputs : list [CallbackInputs ],
388387) -> CallbackOutputTarget | list [CallbackOutputTarget ]:
389388 """Build the outputs spec, expanding wildcards to concrete IDs.
390389
@@ -407,15 +406,19 @@ def _expand_output_spec(
407406 if pattern is not None :
408407 concrete_ids = _derive_output_ids (pattern , resolved_inputs )
409408 if not concrete_ids :
410- concrete_ids = [comp .id for comp in find_matching_components (pattern )]
411- expanded = [{"id" : cid , "property" : prop } for cid in concrete_ids ]
409+ concrete_ids = [
410+ getattr (comp , "id" ) for comp in find_matching_components (pattern )
411+ ]
412+ expanded : list [CallbackDependency ] = [
413+ CallbackDependency (id = cid , property = prop ) for cid in concrete_ids
414+ ]
412415 # ALL/ALLSMALLER → nested list; MATCH → single dict
413416 if len (expanded ) == 1 :
414417 results .append (expanded [0 ])
415418 else :
416419 results .append (expanded )
417420 else :
418- results .append ({ "id" : pid , " property" : prop } )
421+ results .append (CallbackDependency ( id = pid , property = prop ) )
419422
420423 # Mirror the Dash renderer: single-output callbacks send a bare dict,
421424 # multi-output callbacks send a list. The framework's output value
@@ -427,7 +430,7 @@ def _expand_output_spec(
427430
428431def _derive_output_ids (
429432 output_pattern : WildcardId ,
430- resolved_inputs : list [CallbackInput ],
433+ resolved_inputs : list [CallbackInputs ],
431434) -> list [WildcardId ] | None :
432435 """Derive concrete output IDs from the resolved input entries.
433436
@@ -456,15 +459,19 @@ def _substitute(item_id: WildcardId) -> WildcardId | None:
456459 if isinstance (entry , list ) and entry :
457460 concrete_ids = []
458461 for item in entry :
459- out = _substitute (item .get ("id" ))
460- if out :
461- concrete_ids .append (out )
462+ item_id = item .get ("id" )
463+ if isinstance (item_id , dict ):
464+ out = _substitute (item_id )
465+ if out :
466+ concrete_ids .append (out )
462467 if concrete_ids :
463468 return concrete_ids
464469 # MATCH: single {id, property, value} dict
465- elif isinstance (entry , dict ) and isinstance (entry .get ("id" ), dict ):
466- out = _substitute (entry ["id" ])
467- if out :
468- return [out ]
470+ elif isinstance (entry , dict ):
471+ entry_id = entry .get ("id" )
472+ if isinstance (entry_id , dict ):
473+ out = _substitute (entry_id )
474+ if out :
475+ return [out ]
469476
470477 return None
0 commit comments