"""An MCP server exposing search_notes and add_note over stdio.

`SEARCH_SCHEMA`, `ADD_SCHEMA`, `search_notes`, `add_note`, `list_tools` and `call_tool` below are
what you implement. `main` and the stdio wiring are plumbing -- mcp's own `call_tool()` decorator
validates `arguments` against a tool's `inputSchema` (via `jsonschema.validate`) before your
function runs, so a tight schema is what turns a bad argument into a clean rejection instead of a
crash inside your code.
"""

from __future__ import annotations

from typing import Any

import anyio
import mcp.types as types
from mcp.server.lowlevel import Server
from mcp.server.stdio import stdio_server

server: Server = Server("mcp-notes")

NOTES: list[dict[str, Any]] = []

SEARCH_SCHEMA: dict[str, Any] = {"type": "object"}
ADD_SCHEMA: dict[str, Any] = {"type": "object"}


def search_notes(query: str, limit: int = 10) -> dict[str, Any]:
    ...


def add_note(title: str, body: str) -> dict[str, Any]:
    ...


@server.list_tools()  # type: ignore[untyped-decorator,no-untyped-call]
async def list_tools() -> list[types.Tool]:
    ...


@server.call_tool()  # type: ignore[untyped-decorator]
async def call_tool(name: str, arguments: dict[str, Any]) -> dict[str, Any]:
    ...


async def main() -> None:
    async with stdio_server() as (read, write):
        await server.run(read, write, server.create_initialization_options())


if __name__ == "__main__":
    anyio.run(main)
