Architecture | Project Structure | Startup Process | Server Features | Extension Points | How It Works
- Create a new file under
tools/with yourregisterXTool(server)function that registers the tool viaserver.registerTool(...). Take thecontext(server/context.ts) as a second argument if the tool needs the protocol era, the change publisher, or state that lives as long as the connection. - Export and call it from
tools/index.ts, in the function for the eras that get it:registerTools(server, context)for both,registerModernToolsfor 2026-07-28 only,registerLegacyToolsorregisterConditionalTools(capability-gated) for the 2025 era only. - Never keep state in a module-level map keyed by session id: the 2026-07-28 protocol has no sessions, and its HTTP path builds a fresh server per request. Keep per-connection state in the registration closure, and state that must outlive a request under a handle the server mints (as
server/tasks.tsandresources/minted.tsdo). - For client input (elicitation, sampling, roots), return
inputRequired(...)from the handler rather than sending a request; the SDK's legacy shim serves the same handler to 2025-era clients.
- Create a new file under
prompts/with yourregisterXPrompt(server)function that registers the prompt viaserver.registerPrompt(...). - Export and call it from
prompts/index.tsinsideregisterPrompts(server).
- Create a new file under
resources/with yourregisterXResources(server)function usingserver.registerResource(...)(optionally withResourceTemplate). - Export and call it from
resources/index.tsinsideregisterResources(server, context).