Write a complete, single-file MCP (Model Context Protocol) tool server in TypeScript using `@modelcontextprotocol/sdk` (OR Python using the `mcp` package) that exposes 3 tools against the public JSONPlaceholder API (https://jsonplaceholder.typicode.com).

### Tools to implement
1. `get_user(id)` — fetch a single user by numeric id. Validate `id` is a positive integer.
2. `list_posts_by_user(user_id, limit)` — fetch a user's posts. `user_id` is a positive int; `limit` is an optional int between 1 and 100 (default 10).
3. `search_posts(query)` — fetch posts whose `title` contains the query string (case-insensitive). `query` is a non-empty string max 200 chars.

### Requirements
- **Schema validation:** every tool must validate its inputs with a schema (Zod for TS, Pydantic for Python). Invalid input returns a structured error, never crashes.
- **Typed results:** tools return typed/structured output (not raw strings).
- **Error handling:** handle HTTP errors, timeouts, and non-JSON responses gracefully — NO silent failures. Each failure path returns a clear error result. Use a reasonable per-request timeout (e.g. 8s).
- **Transport:** run over stdio (`StdioServerTransport` / `stdio_server`).
- **No external state:** pure stdlib + fetch/httpx + the MCP SDK. No database, no files.

### Included tests
At the bottom of the file, include a runnable test section that exercises:
- a) Happy path: `get_user(1)` returns a user with the expected fields.
- b) Bad-id 404 / not-found is handled (does not throw).
- c) Malformed input (e.g. `get_user(-5)`, `list_posts_by_user("x")`, `search_posts("")`) is rejected by validation with a clear error.

Provide clean, well-commented code. The file must be directly runnable: `npx tsx file.ts` (or `python file.py`).
