Template for a remote Model Context Protocol (MCP) server with a built-in OAuth 2.1 authorization server (auth code + PKCE + dynamic client registration). Delegates login/consent to your existing web app and passes your backend's JWT through as the access token — no session state on the MCP server.
Three tools with clear verb-noun naming (whoami, list_notes, create_note) and reasonable descriptions (90-150 chars). Input schemas present for all tools; create_note has typed parameters with constraints (minLength, maxLength). However, parameter descriptions are minimal or missing context. Output schemas are undocumented, LLMs cannot predict response structure. Error handling exists but lacks recovery guidance. No tool annotations (readOnlyHint/destructiveHint). Schemas use Zod but lack explicit JSON Schema documentation in tool registration.
Create a note for the authenticated user (POST /api/notes).
List the authenticated user's notes (GET /api/notes). Each note has id, title, content, and createdAt.
Return the profile of the authenticated user (GET /api/auth/me). Useful to confirm the OAuth flow completed and see who is logged in.
Output schemas undocumented. LLMs cannot predict response structure (user profile fields, note list format, created note shape). Forces agents to guess field names for downstream operations.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). LLMs cannot distinguish safe reads from destructive writes without explicit hints. create_note should be marked destructiveHint=true.
Error messages lack recovery guidance. apiCall() returns generic 'Backend API error (HTTP 401)' without suggesting next steps (e.g., 'OAuth flow incomplete, re-authenticate').
create_note 'content' parameter marked optional but description says 'optional' redundantly. No constraint on minimum length or format guidance.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | <=2025-11-25 | v2 |
whoami and list_notes have empty inputSchema ({}). While correct for parameterless tools, no description explains what data they return or when to call them.