Files
servers-modelcontextprotocol/src/everything/server/index.ts
cliffhall f8933ec3e6 Sync roots at startup. This was deferred to list_roots tool is used, but I'm putting it back.
The syncRoots call should be idempotent, requesting roots if they haven't been yet for the session, but always retuning the cached roots otherwise. That could be deferred but setting the handler for roots_list changed note should not.

* In server/roots.ts
  - only set the notification handler and call for initial roots list if the roots aren't already cached for this client.

* In server/index.ts
  - in the oninitialized handler
    - get the sessionId from the transport
    - set a 350ms timeout to call syncRoots with the server and sessionId
      - this delay cause it to run after the `notifications/initialized` handler finishes, otherwise, the request gets lost.

* All other changes attributable to prettier
2025-12-17 17:46:24 -05:00

95 lines
2.8 KiB
TypeScript

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import {
setSubscriptionHandlers,
stopSimulatedResourceUpdates,
} from "../resources/subscriptions.js";
import { registerConditionalTools, registerTools } from "../tools/index.js";
import { registerResources, readInstructions } from "../resources/index.js";
import { registerPrompts } from "../prompts/index.js";
import { stopSimulatedLogging } from "./logging.js";
import { syncRoots } from "./roots.js";
// Server Factory response
export type ServerFactoryResponse = {
server: McpServer;
cleanup: (sessionId?: string) => void;
};
/**
* Server Factory
*
* This function initializes a `McpServer` with specific capabilities and instructions,
* registers tools, resources, and prompts, and configures resource subscription handlers.
*
* @returns {ServerFactoryResponse} An object containing the server instance, and a `cleanup`
* function for handling server-side cleanup when a session ends.
*
* Properties of the returned object:
* - `server` {Object}: The initialized server instance.
* - `cleanup` {Function}: Function to perform cleanup operations for a closing session.
*/
export const createServer: () => ServerFactoryResponse = () => {
// Read the server instructions
const instructions = readInstructions();
// Create the server
const server = new McpServer(
{
name: "mcp-servers/everything",
title: "Everything Reference Server",
version: "2.0.0",
},
{
capabilities: {
tools: {
listChanged: true,
},
prompts: {
listChanged: true,
},
resources: {
subscribe: true,
listChanged: true,
},
logging: {},
},
instructions,
}
);
// Register the tools
registerTools(server);
// Register the resources
registerResources(server);
// Register the prompts
registerPrompts(server);
// Set resource subscription handlers
setSubscriptionHandlers(server);
// Perform post-initialization operations
server.server.oninitialized = async () => {
// Register conditional tools now that client capabilities are known.
// This finishes before the `notifications/initialized` handler finishes.
registerConditionalTools(server);
// Sync roots if the client supports them.
// This is delayed until after the `notifications/initialized` handler finishes,
// otherwise, the request gets lost.
const sessionId = server.server.transport?.sessionId;
setTimeout(() => syncRoots(server, sessionId), 350);
};
// Return the ServerFactoryResponse
return {
server,
cleanup: (sessionId?: string) => {
// Stop any simulated logging or resource updates that may have been initiated.
stopSimulatedLogging(sessionId);
stopSimulatedResourceUpdates(sessionId);
},
} satisfies ServerFactoryResponse;
};