Files
modelcontextprotocol--pytho…/docs_src/real_host/tutorial001.py
Max Isbey ab24c34d89 Address review: keep three anticipated failures out of the crash path, docs sweep
- pre_parse_json leaves a string alone when json.loads refuses it with
  something other than JSONDecodeError (over-long integer, deep nesting),
  so validation rejects it as a bad argument instead of it surfacing as a
  crash with a traceback per request.
- convert_result skips output-schema validation for a returned
  CallToolResult(is_error=True); an error result has no structured content
  to check, and the author's message now reaches the client as written.
- read_resource checks that Resource.read() returned str or bytes, so a
  mistyped custom resource is logged as a crash and answered with -32603
  rather than "Invalid request parameters" with no log record.
- Docs and examples that still said "raise any exception and the model
  reads it" now say ToolError; deprecated.md lists the deprecated
  FuncMetadata helper; docstrings spell out the MCPError carve-out and the
  nested-crash __cause__.
- Two tests tightened: the prompt argument-validation test proves the body
  never ran, and the invalid-types check asserts on validate_arguments.
2026-08-21 16:23:48 +00:00

36 lines
913 B
Python

from mcp.server import MCPServer
from mcp.server.mcpserver.exceptions import ToolError
mcp = MCPServer("Bookshop")
CATALOG = {
"Dune": "Frank Herbert",
"Neuromancer": "William Gibson",
"The Left Hand of Darkness": "Ursula K. Le Guin",
}
@mcp.tool()
def search_books(query: str) -> list[str]:
"""Search the catalog by title or author."""
needle = query.lower()
return [title for title, author in CATALOG.items() if needle in title.lower() or needle in author.lower()]
@mcp.tool()
def get_author(title: str) -> str:
"""Look up the author of a book in the catalog."""
if title not in CATALOG:
raise ToolError(f"No book titled {title!r} in the catalog.")
return CATALOG[title]
@mcp.resource("catalog://titles")
def titles() -> str:
"""Every title in the catalog, one per line."""
return "\n".join(sorted(CATALOG))
if __name__ == "__main__":
mcp.run()