mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-18 01:54:10 +02:00
Adding Trigger Elicitation Request and Get Roots List tools
* Updated architecture.md
* Added roots.ts
- tracks roots by sessionId
- setRootsListChangedHandler
- listens for roots changed notification from the client
- updates the roots map by sessionId
- sends log notification or error to the client
* In server/index.ts
- import setRootsListChangedHandler
- in clientConnected callback
- call setRootsListChangedHandler passing server and sessionId
* In sse.ts, stdio.ts, and streamableHttp.ts
- receive clientConnected from server factory
- call clientConnected when server is connected to transport
* Added get-roots-list.ts
- registerGetRootsListTool
- Registers the 'get-roots-list' tool with the given MCP server.
* Added trigger-elicitation-request.ts
- registerTriggerElicitationRequestTool
- registered tool sends an elicitation request that exercises all supported field types
* In tools/index.ts
- imports registerTriggerElicitationRequestTool and registerGetRootsListTool
- in registerTools
- call registerTriggerElicitationRequestTool and registerGetRootsListTool, passing server
70 lines
2.1 KiB
TypeScript
70 lines
2.1 KiB
TypeScript
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
import express from "express";
|
|
import { createServer } from "../server/index.js";
|
|
import cors from "cors";
|
|
|
|
console.error("Starting SSE server...");
|
|
|
|
const app = express();
|
|
app.use(
|
|
cors({
|
|
origin: "*", // use "*" with caution in production
|
|
methods: "GET,POST",
|
|
preflightContinue: false,
|
|
optionsSuccessStatus: 204,
|
|
})
|
|
); // Enable CORS for all routes so Inspector can connect
|
|
const transports: Map<string, SSEServerTransport> = new Map<
|
|
string,
|
|
SSEServerTransport
|
|
>();
|
|
|
|
app.get("/sse", async (req, res) => {
|
|
let transport: SSEServerTransport;
|
|
const { server, clientConnected, cleanup } = createServer();
|
|
|
|
if (req?.query?.sessionId) {
|
|
const sessionId = req?.query?.sessionId as string;
|
|
transport = transports.get(sessionId) as SSEServerTransport;
|
|
console.error(
|
|
"Client Reconnecting? This shouldn't happen; when client has a sessionId, GET /sse should not be called again.",
|
|
transport.sessionId
|
|
);
|
|
} else {
|
|
// Create and store transport for new session
|
|
transport = new SSEServerTransport("/message", res);
|
|
transports.set(transport.sessionId, transport);
|
|
|
|
// Connect server to transport
|
|
await server.connect(transport);
|
|
const sessionId = transport.sessionId;
|
|
clientConnected(sessionId);
|
|
|
|
console.error("Client Connected: ", sessionId);
|
|
|
|
// Handle close of connection
|
|
server.server.onclose = async () => {
|
|
const sessionId = transport.sessionId;
|
|
console.error("Client Disconnected: ", sessionId);
|
|
transports.delete(sessionId);
|
|
await cleanup(sessionId);
|
|
};
|
|
}
|
|
});
|
|
|
|
app.post("/message", async (req, res) => {
|
|
const sessionId = req?.query?.sessionId as string;
|
|
const transport = transports.get(sessionId);
|
|
if (transport) {
|
|
console.error("Client Message from", sessionId);
|
|
await transport.handlePostMessage(req, res);
|
|
} else {
|
|
console.error(`No transport found for sessionId ${sessionId}`);
|
|
}
|
|
});
|
|
|
|
const PORT = process.env.PORT || 3001;
|
|
app.listen(PORT, () => {
|
|
console.error(`Server is running on port ${PORT}`);
|
|
});
|