fastmcp/examples/dynamic_story_prompt
zzstoatzz 7d2f1f9671 Fix: Prompt arg handling & docs for #541
Addresses #541:
- Server now auto-deserializes JSON string args (list, dict, BaseModel) for prompts. This simplifies server-side prompt logic by reducing boilerplate `json.loads()` calls.
- Docs updated to clarify `list_resource_templates` usage for templatized resources.
- Docs updated to require client-side `json.dumps()` for complex `get_prompt` arguments, resolving the original Pydantic error.
- Adds a new example (`examples/dynamic_story_prompt/`) demonstrating the server-side deserialization benefit and correct client-side serialization.

Closes #541.

---
Notes for Reviewers:
- **Server-Side Auto-Deserialization:** This change introduces a "magic" `json.loads()` in `Prompt.render`. This is an intentional DX improvement. It only triggers for `str` inputs targeting `list`, `dict`, or `BaseModel` type hints. If `json.loads()` fails (e.g., malformed JSON), the original string is passed to Pydantic's `validate_call`, ensuring robust error handling. This avoids boilerplate in user prompt functions.
- **Client `get_prompt()` Return Value:** The `examples/dynamic_story_prompt/story_client.py` parses the result of `client.get_prompt()` by iterating and looking for a `('messages', ...)` tuple. This reflects the observed behavior of the current `client.get_prompt()`. This commit does *not* change `client.get_prompt()`'s return behavior; the example merely adapts to it. A separate discussion might be warranted for potentially simplifying `client.get_prompt()`'s return signature in the future.
2025-05-27 19:38:32 -05:00
..
README.md Fix: Prompt arg handling & docs for #541 2025-05-27 19:38:32 -05:00
story_client.py Fix: Prompt arg handling & docs for #541 2025-05-27 19:38:32 -05:00
story_server.py Fix: Prompt arg handling & docs for #541 2025-05-27 19:38:32 -05:00

Dynamic Story Prompt Generator Example

This example demonstrates how FastMCP's automatic JSON string deserialization for prompt arguments can simplify server-side prompt logic.

Scenario

We have a FastMCP server with a prompt named generate_dynamic_story_prompt. This prompt is designed to create an engaging story starter based on several complex inputs:

  1. Character Details: Information about the main character, structured as a Pydantic model (name, archetype, quirky trait).
  2. Mysterious Objects: A list of unusual items the character stumbles upon.
  3. Active World Laws: A dictionary describing peculiar rules or conditions currently affecting the story world.

The server-side prompt function takes these as a Character object, a list[str], and a dict[str, str] respectively. It then combines them into a creative text prompt.

Motivation for Auto-Deserialization

The developer writing the generate_dynamic_story_prompt function wants to work with these inputs as native Python objects for clarity and ease of use within their creative logic. They shouldn't need to manually parse JSON strings for each complex argument.

The client application (e.g., a web UI, another script) will gather this information and serialize the complex parts (character details, list of objects, world laws dictionary) into JSON strings before sending them to the FastMCP server.

FastMCP's auto-deserialization feature (for list, dict, and Pydantic BaseModel arguments) bridges this gap:

  • The client sends complex data as JSON strings (as required by the MCP spec for prompt arguments: dict[str, str]).
  • The server-side FastMCP prompt automatically attempts to json.loads() these strings into the Python types hinted in the prompt function signature.

This keeps the server-side prompt function clean, Pythonic, and focused on its core task of generating the story prompt, without boilerplate json.loads() calls.

Files

  • story_server.py: The FastMCP server code defining the Character model and the generate_dynamic_story_prompt.
  • story_client.py: A conceptual Python client script showing how to call this prompt, including serializing complex arguments to JSON strings.

How to Run (Conceptual)

  1. Run the story_server.py.
  2. In a separate terminal, run the story_client.py.

The client will output the creative story prompt generated by the server.