fix(everything): convert to modern TypeScript SDK APIs

Convert the everything server to use the modern McpServer API instead
of the low-level Server API.

Key changes:
- Replace Server with McpServer from @modelcontextprotocol/sdk/server/mcp.js
- Convert simple tools to use registerTool() for cleaner code
- Convert simple prompts to use registerPrompt()
- Keep advanced features using server.server.setRequestHandler() for low-level access
- Add type dependencies (@types/jszip, @types/cors)
- Update all transport files to use server.server.connect/close pattern
- Fix type literals to use 'as const' assertions

Tools converted to registerTool():
- echo, add, printEnv, getTinyImage, annotatedMessage, getResourceLinks,
  structuredContent, zip

Tools still using setRequestHandler() (need low-level access):
- longRunningOperation (progress tokens)
- sampleLLM (sampling protocol)
- elicitation (elicitation protocol)
- listRoots (client capabilities)
- getResourceReference (strict resource content typing)

All features maintained:
- 13 tools including progress notifications, sampling, elicitation
- 3 prompts (simple, complex, resource)
- 100 paginated resources with templates
- Resource subscriptions
- Completions for prompts and resources
- Roots protocol support
- Logging at various levels
- All three transports (stdio, SSE, streamable HTTP)

The modern API provides:
- Less boilerplate code where applicable
- Better type safety with Zod
- More declarative registration
- Cleaner, more maintainable code
This commit is contained in:
Adam Jones
2025-11-17 15:02:37 +00:00
parent 0d0d2f87bf
commit 0965e9fa38
6 changed files with 392 additions and 430 deletions

11
package-lock.json generated
View File

@@ -1341,6 +1341,16 @@
"integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
"dev": true
},
"node_modules/@types/jszip": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/@types/jszip/-/jszip-3.4.0.tgz",
"integrity": "sha512-GFHqtQQP3R4NNuvZH3hNCYD0NbyBZ42bkN7kO3NDrU/SnvIZWMS8Bp38XCsRKBT5BXvgm0y1zqpZWp/ZkRzBzg==",
"dev": true,
"license": "MIT",
"dependencies": {
"jszip": "*"
}
},
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
@@ -4107,6 +4117,7 @@
"devDependencies": {
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/jszip": "^3.4.0",
"shx": "^0.3.4",
"typescript": "^5.6.2"
}

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,7 @@
"devDependencies": {
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/jszip": "^3.4.0",
"shx": "^0.3.4",
"typescript": "^5.6.2"
}

View File

@@ -28,14 +28,14 @@ app.get("/sse", async (req, res) => {
transports.set(transport.sessionId, transport);
// Connect server to transport
await server.connect(transport);
await server.server.connect(transport);
console.error("Client Connected: ", transport.sessionId);
// Start notification intervals after client connects
startNotificationIntervals(transport.sessionId);
// Handle close of connection
server.onclose = async () => {
server.server.onclose = async () => {
console.error("Client Disconnected: ", transport.sessionId);
transports.delete(transport.sessionId);
await cleanup();

View File

@@ -9,13 +9,13 @@ async function main() {
const transport = new StdioServerTransport();
const {server, cleanup, startNotificationIntervals} = createServer();
await server.connect(transport);
await server.server.connect(transport);
startNotificationIntervals();
// Cleanup on exit
process.on("SIGINT", async () => {
await cleanup();
await server.close();
await server.server.close();
process.exit(0);
});
}

View File

@@ -52,7 +52,7 @@ app.post('/mcp', async (req: Request, res: Response) => {
// Set up onclose handler to clean up transport when closed
server.onclose = async () => {
server.server.onclose = async () => {
const sid = transport.sessionId;
if (sid && transports.has(sid)) {
console.error(`Transport closed for session ${sid}, removing from transports map`);
@@ -63,7 +63,7 @@ app.post('/mcp', async (req: Request, res: Response) => {
// Connect the transport to the MCP server BEFORE handling the request
// so responses can flow back through the same transport
await server.connect(transport);
await server.server.connect(transport);
await transport.handleRequest(req, res);