routerFor method

Future Function(String tool, Map<String, dynamic> params) routerFor(
  1. Client? client, {
  2. void onNoClient(
    1. String tool
    )?,
})

The routing a host hands the runtime as onToolCall: an in-process tool when there is no client, the full dispatch when there is.

Shared because it is needed at two moments — before initialize, so a definition-level onInit tool call has somewhere to land (MCP UI DSL §1.5.2 fires that hook ahead of the first render), and again at buildUI for everything after. Two copies of it would drift.

Implementation

Future<dynamic> Function(String, Map<String, dynamic>) routerFor(
  Client? client, {
  void Function(String tool)? onNoClient,
}) {
  return (String tool, Map<String, dynamic> params) async {
    if (client == null) {
      if (_inProcess.containsKey(tool)) {
        return _callInProcessForRuntime(tool, params);
      }
      onNoClient?.call(tool);
      // Not `null`: the runtime reads a null return as a successful call
      // with no payload, so a misspelled tool name came back as `onSuccess`
      // and the document carried on as though the call had happened.
      throw ToolExecutionException(
        tool,
        cause: StateError('no tool named "$tool" and no connected server'),
      );
    }
    return call(client: client, tool: tool, params: params);
  };
}