# Using TypedDict for Type-Safe API Response Handling in Python

> Learn how to use TypedDict in Python for type-safe API response handling. Validate JSON schemas and prevent KeyError exceptions with static type checking before deployment.

- Repository: [CSK/mcp-wordle-python](https://github.com/cr2007/mcp-wordle-python)
- Tags: best-practices
- Published: 2026-02-28

---

**The Wordle MCP Python server leverages `TypedDict` subclasses to enforce strict JSON schemas for external API responses, enabling static type checkers to validate data access patterns and eliminate runtime `KeyError` exceptions before deployment.**

The `cr2007/mcp-wordle-python` repository demonstrates production-grade patterns for external API integration by leveraging Python's `typing.TypedDict`. By declaring explicit shapes for both success and error payloads from the New York Times Wordle endpoint, the codebase achieves compile-time safety and self-documenting API contracts.

## Defining Strict API Contracts with TypedDict

In [`src/mcp_wordle/main.py`](https://github.com/cr2007/mcp-wordle-python/blob/main/src/mcp_wordle/main.py) (lines 16-27), the server defines two distinct `TypedDict` subclasses that mirror the Wordle API's JSON format. The `WordleAPIData` class specifies required string fields including `id`, `solution`, `print_date`, `days_since_launch`, and `editor`. Conversely, `WordleError` captures failure states with `status`, `errors`, and `results` fields.

These declarations serve as executable documentation that static analysis tools like `mypy` and `pyright` can verify against actual usage patterns. By separating success and error concerns into distinct types, the code enforces exhaustive handling of both scenarios at the type level.

## Annotating Function Signatures for Safety

The `get_wordle_data` function uses a `Union[WordleAPIData, WordleError]` return annotation (line 40), making the dual-state nature of the API explicit. This signature forces callers to implement defensive checks rather than assuming successful responses, preventing unhandled exceptions in production environments.

## Implementation in the Wordle MCP Server

The actual request logic (lines 64-67) performs a standard `requests.get` call and returns the parsed JSON. Because the function returns a TypedDict union, type checkers automatically flag invalid key access attempts. Attempting to retrieve `result["solution"]` without first narrowing the type will generate a mypy error, as that key only exists on `WordleAPIData` and is absent from `WordleError`.

The function is registered as an MCP tool using the `@mcp.tool` decorator from the **FastMCP** framework. This exposes the typed function to any MCP-compatible client while preserving the strict `TypedDict` contracts across service boundaries.

## Static Type Checking in Practice

When consuming the API, you must narrow the type before accessing payload-specific fields:

```python
from mcp_wordle.main import get_wordle_data, WordleAPIData, WordleError
import asyncio

async def fetch_today():
    result = await get_wordle_data()  # defaults to today

    
    if "solution" in result:          # Type narrowing check

        data: WordleAPIData = result
        print(f"Today's Wordle solution: {data['solution']}")
    else:                             # Error path handling

        err: WordleError = result
        print(f"Error {err['status']}: {err['errors']}")

asyncio.run(fetch_today())

```

Validate your implementation with `mypy` to catch potential key access violations:

```bash
pip install mypy
mypy src/mcp_wordle/main.py

```

If you mistakenly treat an error response as successful data (e.g., accessing `result["solution"]` without validation), the type checker flags the invalid key lookup immediately, long before runtime execution.

## Packaging and Distribution

The project uses `hatchling` as its build backend (defined in [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml)), packaging the type-safe server as a console script entry point named `mcp-wordle`. This allows the typed tool to execute via command line, Docker, or `uvx` while maintaining strict validation of response shapes defined in the `TypedDict` classes.

## Summary

- **`TypedDict` definitions** in [`src/mcp_wordle/main.py`](https://github.com/cr2007/mcp-wordle-python/blob/main/src/mcp_wordle/main.py) create formal schemas for JSON responses, documenting the Wordle API contract directly in Python code with zero runtime overhead.
- **Union return types** force explicit handling of both success (`WordleAPIData`) and error (`WordleError`) scenarios at compile time, eliminating unhandled `KeyError` exceptions.
- **FastMCP integration** exposes type-safe tools to external clients while preserving strict type constraints across the MCP protocol boundary.
- **Static analysis compatibility** with `mypy` and `pyright` enables immediate feedback on invalid API response handling during development.

## Frequently Asked Questions

### What is the performance cost of using TypedDict for API responses?

There is no runtime performance penalty. `TypedDict` exists solely in Python's type system for static analysis by tools like `mypy` and `pyright`. At runtime, the objects are standard dictionaries with no additional validation overhead or memory consumption.

### How does TypedDict improve error handling compared to regular dictionaries?

Unlike standard dictionaries, `TypedDict` requires explicit type narrowing through key presence checks or `isinstance` validation. This forces developers to handle error payloads separately from successful responses, preventing `KeyError` exceptions when accessing fields that may not exist in error states returned by the Wordle API.

### Can TypedDict handle optional fields in API responses?

Yes. The `WordleAPIData` and `WordleError` definitions in [`src/mcp_wordle/main.py`](https://github.com/cr2007/mcp-wordle-python/blob/main/src/mcp_wordle/main.py) can include optional fields using `NotRequired` or `Optional` type hints (depending on Python version). This flexibility allows the type system to model APIs where certain keys may be absent without breaking static validation of the fields that are guaranteed to exist.

### Which static type checkers support TypedDict structural validation?

Both `mypy` and `pyright` (the engine behind VS Code's Pylance extension) fully support `TypedDict` structural subtyping. These tools validate that code accessing `WordleAPIData` only uses keys defined in the class (such as `solution` or `print_date`) and will flag attempts to access undefined keys or improperly narrow the `Union` type.