> ## Documentation Index
> Fetch the complete documentation index at: https://gofastmcp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# async_utils

# `fastmcp.utilities.async_utils`

Async utilities for FastMCP.

## Functions

### `is_coroutine_function` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/utilities/async_utils.py#L14" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
is_coroutine_function(fn: Any) -> bool
```

Check if a callable is a coroutine function, unwrapping functools.partial.

`inspect.iscoroutinefunction` returns `False` for
`functools.partial` objects wrapping an async function on Python \< 3.12.
This helper unwraps any layers of `partial` before checking.

### `call_sync_fn_in_threadpool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/utilities/async_utils.py#L26" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
call_sync_fn_in_threadpool(fn: Callable[..., Any], *args: Any, **kwargs: Any) -> Any
```

Call a sync function in a threadpool to avoid blocking the event loop.

Uses anyio.to\_thread.run\_sync which properly propagates contextvars,
making this safe for functions that depend on context (like dependency injection).

### `gather` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/utilities/async_utils.py#L53" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
gather(awaitables: Iterable[Awaitable[T]]) -> list[T] | list[T | BaseException]
```

Run awaitables concurrently and return results in order.

Uses anyio TaskGroup for structured concurrency.

`awaitables` is consumed lazily, one item at a time, right before each
is handed to the task group. Callers with a dynamic number of awaitables
should pass a generator expression (e.g. `gather(f(x) for x in xs)`)
rather than a list or list comprehension: a list comprehension calls
every `f(x)` up front, creating a batch of coroutine objects before
this function even starts, whereas a generator expression creates each
coroutine only as this function's own scheduling loop asks for it. That
matters because coroutine creation and scheduling can be interrupted
between any two bytecode instructions by a synchronous signal handler
(for example pytest-timeout's SIGALRM-based per-test timeout). If that
happens while a whole batch of coroutines is sitting unscheduled, they
are silently abandoned and eventually trigger a "coroutine was never
awaited" warning attributed to whatever unrelated code happens to be
running when the garbage collector gets to them. Lazy consumption keeps
the window in which a created-but-unscheduled coroutine can exist as
small as possible.

**Args:**

* `awaitables`: Iterable of awaitables to run concurrently.
* `return_exceptions`: If True, exceptions are returned in results.
  If False, first exception cancels all and raises.

**Returns:**

* List of results in the same order as input awaitables.
