Files
servers-modelcontextprotocol/src/everything/docs/how-it-works.md
cliffhall 1b8f376b90 Demonstrate registration of tools conditioned upon client capability support. Also, obviated need for clientConnected callback to pass sessionId because we defer initial fetching of roots happens when you run the get-roots-list tool.
* In how-it-works.md,
  - added a section on conditional tool registration

* In server/index.ts
  - import registerConditionalTools
  - in an oninitialized handler for the server, call registerConditionalTools
  - removed clientConnected from ServerFactoryResponse and all mentions in docs

* In tools/index.ts
  - export a registerConditionalTools function
  - refactor/move calls to registerGetRootsListTool, registerTriggerElicitationRequestTool, and registerTriggerSamplingRequestTool out of registerTools and into registerConditionalTools

* In server/roots.ts
  - only act if client supports roots
  - remove setInterval from call to requestRoots. It isn't happening during the initialze handshake anymore, so it doesn't interfere with that process if called immediaately

* In get-roots-list.ts, trigger-elicitation-request.ts, and trigger-sampling-request.ts,
  - only register tool if client supports capability

* Throughout the rest of the files, removing all references to `clientConnected`
2025-12-15 17:51:30 -05:00

2.7 KiB
Raw Blame History

Everything Server - How It Works

Architecture | Project Structure | Startup Process | Server Features | Extension Points | How It Works

Conditional Tool Registration

Module: server/index.ts

  • Some tools require client support for the capability they demonstrate. These are:
    • get-roots-list
    • trigger-elicitation-request
    • trigger-sampling-request
  • Client capabilities aren't known until after initilization handshake is complete.
  • Most tools are registered immediately during the Server Factory execution, prior to client connection.
  • To defer registration of these commands until client capabilities are known, a registerConditionalTools(server) function is invoked from an onintitialized handler.

Resource Subscriptions

Module: resources/subscriptions.ts

  • Tracks subscribers per URI: Map<uri, Set<sessionId>>.
  • Installs handlers via setSubscriptionHandlers(server) to process subscribe/unsubscribe requests and keep the map updated.
  • Updates are started/stopped on demand by the toggle-subscriber-updates tool, which calls beginSimulatedResourceUpdates(server, sessionId) and stopSimulatedResourceUpdates(sessionId).
  • cleanup(sessionId?) calls stopSimulatedResourceUpdates(sessionId) to clear intervals and remove sessionscoped state.

Sessionscoped Resources

Module: resources/session.ts

  • getSessionResourceURI(name: string): Builds a session resource URI: demo://resource/session/<name>.
  • registerSessionResource(server, resource, type, payload): Registers a resource with the given uri, name, and mimeType, returning a resource_link. The content is served from memory for the life of the session only. Supports type: "text" | "blob" and returns data in the corresponding field.
  • Intended usage: tools can create and expose per-session artifacts without persisting them. For example, tools/gzip-file-as-resource.ts compresses fetched content, registers it as a session resource with mimeType: application/gzip, and returns either a resource_link or an inline resource based on outputType.

Simulated Logging

Module: server/logging.ts

  • Periodically sends randomized log messages at different levels. Messages can include the session ID for clarity during demos.
  • Started/stopped on demand via the toggle-simulated-logging tool, which calls beginSimulatedLogging(server, sessionId?) and stopSimulatedLogging(sessionId?). Note that transport disconnect triggers cleanup() which also stops any active intervals.
  • Uses server.sendLoggingMessage({ level, data }, sessionId?) so that the clients configured minimum logging level is respected by the SDK.