diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 32013fc..9e3c248 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -49,6 +49,7 @@ export default defineConfig({ vite: { server: { host: "0.0.0.0", + allowedHosts: [domain.split(":")[0]], ...(process.env.VITE_HMR_HOST && { hmr: { host: process.env.VITE_HMR_HOST, diff --git a/docs/src/content/docs/getting-started/index.mdx b/docs/src/content/docs/getting-started/index.mdx index 98ce91e..390f9cf 100644 --- a/docs/src/content/docs/getting-started/index.mdx +++ b/docs/src/content/docs/getting-started/index.mdx @@ -22,10 +22,11 @@ federal data mariners and forecasters rely on. ## Capabilities - + Station discovery, tide predictions, observed water levels, meteorological - data, marine conditions snapshots, SmartPot deployment intelligence, and - chart visualization. + data, marine conditions snapshots, SmartPot deployment intelligence, + chart visualization, and client capability diagnostics. All tools declare + MCP annotations for safe retry and caching. [Tool reference](/reference/) diff --git a/docs/src/content/docs/reference/tools.mdx b/docs/src/content/docs/reference/tools.mdx index f465c96..e92645d 100644 --- a/docs/src/content/docs/reference/tools.mdx +++ b/docs/src/content/docs/reference/tools.mdx @@ -1,6 +1,6 @@ --- title: Tools Reference -description: Complete reference for all 13 MCP tools +description: Complete reference for all 14 MCP tools sidebar: order: 1 --- @@ -13,6 +13,29 @@ All tools are registered on the `mcnoaa-tides` MCP server and available through Date parameters accept `yyyyMMdd` or `yyyyMMdd HH:mm` format. The maximum time range is 720 hours (~30 days). +### Tool Annotations + +Every tool declares [MCP tool annotations](https://spec.modelcontextprotocol.io/specification/2025-03-26/server/tools/#annotations) so clients can make informed decisions about retries, caching, and approval: + +| Annotation | Value | Meaning | +|------------|-------|---------| +| `readOnlyHint` | `true` (all tools) | Tools never write or modify data -- safe to retry | +| `openWorldHint` | `true` (13 tools) | Fetches data from NOAA's external API | +| `openWorldHint` | `false` (diagnostics) | `test_client_capabilities` only inspects the MCP session | + +### Structured Logging + +Tools send diagnostic messages to the client via MCP `notifications/message`: +- **`ctx.info()`** before data fetches (e.g., "Fetching hilo predictions for station 8454000") +- **`ctx.warning()`** for data quality issues (preliminary/unverified readings), unavailable products, and NO-GO/CAUTION deployment assessments +- **`ctx.debug()`** for search result counts and phase classification details + +These messages appear in the client's log stream, not in the tool return value. + +### Sampling Summaries + +Three tools -- `marine_conditions_snapshot`, `deployment_briefing`, and `water_level_anomaly` -- attempt to generate a natural-language `"summary"` key via [MCP sampling](https://spec.modelcontextprotocol.io/specification/2025-03-26/client/sampling/). If the connected client supports sampling, the server asks its LLM to synthesize a concise briefing from the raw data. If sampling is unavailable, the raw data is returned without a summary -- the feature is purely additive. + --- ## Station Discovery @@ -757,6 +780,64 @@ Install visualization dependencies with `uv pip install mcnoaa-tides[viz]`. The --- +## Diagnostics + +Tools for inspecting the MCP session and client capabilities. + +### test_client_capabilities + +Report which MCP features the connected client supports. Returns the client implementation info, protocol version, and capability flags for sampling, elicitation, roots, and tasks. Useful for understanding what features are available before calling tools that depend on optional client capabilities. + +*No parameters required.* + +**Example call:** + +```json +{ + "tool": "test_client_capabilities", + "arguments": {} +} +``` + +**Example response:** + +```json +{ + "session_id": "cb6ddc2d-f866-4fa3-bf2e-15eebd133481", + "client": { + "name": "claude-code", + "version": "2.1.38" + }, + "protocol_version": "2025-11-25", + "capabilities": { + "sampling": false, + "elicitation": false, + "roots": true, + "tasks": false + }, + "roots_detail": { + "list_changed": false + } +} +``` + +When a capability is `true`, additional `*_detail` keys are included with sub-capability flags. For example, a client that supports sampling would include: + +```json +{ + "sampling_detail": { + "context": true, + "tools": true + } +} +``` + + + +--- + ## Datum Options Several tools accept a `datum` parameter. The most common options: diff --git a/docs/src/content/docs/understanding/architecture.mdx b/docs/src/content/docs/understanding/architecture.mdx index 20850f5..04fc5e8 100644 --- a/docs/src/content/docs/understanding/architecture.mdx +++ b/docs/src/content/docs/understanding/architecture.mdx @@ -130,12 +130,13 @@ The codebase is split into focused modules, each with a `register(mcp)` function - conditions.py -- marine_conditions_snapshot - smartpot.py -- tidal_phase, deployment_briefing, catch_tidal_context, water_level_anomaly - charts.py -- visualize_tides, visualize_conditions + - diagnostics.py -- test_client_capabilities - charts/ - tides.py -- Matplotlib/Plotly tide chart renderers - conditions.py -- Matplotlib/Plotly conditions dashboard renderers -Each tool module has a single `register()` function. The server imports all six and calls them in sequence during startup. This keeps the server module small and makes it straightforward to add new tool groups without touching existing ones. +Each tool module has a single `register()` function. The server imports all seven and calls them in sequence during startup. This keeps the server module small and makes it straightforward to add new tool groups without touching existing ones. ### Pure logic separation @@ -163,3 +164,53 @@ MCP_TRANSPORT=streamable-http MCP_PORT=8000 uvx mcnoaa-tides ``` The version banner is always printed to stderr (never stdout) to avoid corrupting the JSON-RPC stream in stdio mode. + +## MCP Primitives + +Beyond tools, resources, and prompts, the server uses several MCP protocol features for observability and client interop. + +### Tool Annotations + +Every tool declares `ToolAnnotations` from the MCP spec. These are metadata hints that clients can use for automatic retry policies, caching, and approval workflows. + +```python +from mcp.types import ToolAnnotations + +_ANNOTATIONS = ToolAnnotations(readOnlyHint=True, openWorldHint=True) + +@mcp.tool(tags={"discovery"}, annotations=_ANNOTATIONS) +async def search_stations(ctx: Context, ...) -> list[dict]: + ... +``` + +All tools set `readOnlyHint=True` (they never write data). The `openWorldHint` is `True` for tools that call NOAA's API and `False` for `test_client_capabilities`, which only inspects the MCP session. + +### Structured Logging + +Tools send diagnostic messages to the client via `ctx.info()`, `ctx.warning()`, and `ctx.debug()`. These are delivered as MCP `notifications/message` -- separate from the tool return value and intended for the client's log stream. + +The logging strategy is intentionally sparse: +- **`ctx.info()`** before data fetches, providing station ID and product context +- **`ctx.warning()`** for actionable signals: preliminary data quality flags, unavailable products, NO-GO/CAUTION deployment assessments, and elevated/high anomaly risk levels +- **`ctx.debug()`** for search match counts, proximity results, and phase classification details + +### Sampling + +Three tools use `ctx.sample()` to request natural-language summaries from the connected client's LLM: + +| Tool | Summary content | +|------|----------------| +| `marine_conditions_snapshot` | 2-3 sentence marine weather briefing for a boat captain | +| `deployment_briefing` | Concise deployment briefing paragraph for a crab pot crew | +| `water_level_anomaly` | 2-sentence risk summary for a marine operator | + +Sampling is purely additive -- the raw structured data is always returned regardless. Each `ctx.sample()` call is wrapped in `try/except Exception: pass` because not all clients support sampling. A compact subset of the data (latest readings only, not hundreds of 6-minute records) is sent to keep the sampling prompt efficient. + +### Client Capability Discovery + +The `test_client_capabilities` diagnostic tool introspects `ctx.session.client_params` to report what the connected client supports. This lets users (and the LLM) discover which optional features are available before attempting them: + +- **Sampling** -- Can the server ask the client's LLM to generate summaries? +- **Elicitation** -- Can the server prompt the user for input mid-tool-call? +- **Roots** -- Does the client expose its project directory context? +- **Tasks** -- Does the client support long-running background operations?