This commit is contained in:
2026-07-09 01:12:40 +03:00
parent cefb27349c
commit 4d621e0a54
6 changed files with 1193 additions and 74 deletions
+78 -45
View File
@@ -1,6 +1,6 @@
import { McpServer } from "@modelcontextprotocol/server"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { serveStdio } from "@modelcontextprotocol/server/stdio"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node"; import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { Command } from "commander"; import { Command } from "commander";
import http from "node:http"; import http from "node:http";
import crypto from "node:crypto"; import crypto from "node:crypto";
@@ -32,59 +32,92 @@ function buildServer(): McpServer {
return server; return server;
} }
async function main() { async function runStdio() {
const transportType: string = options.transport; const server = buildServer();
const transport = new StdioServerTransport();
await server.connect(transport);
}
if (transportType === "stdio") { async function runSSE() {
serveStdio(buildServer); const transports = new Map<string, SSEServerTransport>();
return;
}
if (transportType === "sse") { const httpServer = http.createServer(async (req, res) => {
const server = buildServer(); if (options.tokenHash) {
const auth = req.headers.authorization || "";
const mcpTransport = new NodeStreamableHTTPServerTransport({ const token = auth.startsWith("Bearer ") ? auth.slice(7) : "";
sessionIdGenerator: () => crypto.randomUUID(), const hash = crypto.createHash("sha256").update(token).digest("hex");
}); if (hash !== options.tokenHash) {
res.writeHead(401, { "Content-Type": "text/plain" });
await server.connect(mcpTransport); res.end("Unauthorized");
return;
const httpServer = http.createServer(async (req, res) => {
if (options.tokenHash) {
const auth = req.headers.authorization || "";
const token = auth.startsWith("Bearer ") ? auth.slice(7) : "";
const hash = crypto.createHash("sha256").update(token).digest("hex");
if (hash !== options.tokenHash) {
res.writeHead(401, { "Content-Type": "text/plain" });
res.end("Unauthorized");
return;
}
} }
}
res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
if (req.method === "OPTIONS") { if (req.method === "OPTIONS") {
res.writeHead(200); res.writeHead(200);
res.end(); res.end();
return;
}
const url = new URL(req.url || "/", `http://${req.headers.host}`);
if (req.method === "GET") {
const sessionId = crypto.randomUUID();
const transport = new SSEServerTransport("/message", res);
transports.set(sessionId, transport);
res.on("close", () => {
transports.delete(sessionId);
});
const server = buildServer();
await server.connect(transport);
return;
}
if (req.method === "POST" && url.pathname === "/message") {
const sessionId = url.searchParams.get("sessionId") || "";
const transport = transports.get(sessionId);
if (!transport) {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Session not found");
return; return;
} }
await mcpTransport.handleRequest(req, res); await transport.handlePostMessage(req, res);
}); return;
}
const port = Number(options.port); res.writeHead(404);
httpServer.listen(port, options.host); res.end("Not found");
});
console.error( const port = Number(options.port);
`Exchange MCP Server running via SSE on http://${options.host}:${port}`, httpServer.listen(port, options.host);
);
return; console.error(
`Exchange MCP Server running via SSE on http://${options.host}:${port}`,
);
}
async function main() {
const transportType: string = options.transport;
switch (transportType) {
case "stdio":
await runStdio();
break;
case "sse":
await runSSE();
break;
default:
console.error(`Unsupported transport: "${transportType}". Use "stdio" or "sse".`);
process.exit(1);
} }
console.error(`Unsupported transport: ${transportType}. Use "stdio" or "sse".`);
process.exit(1);
} }
main().catch((error) => { main().catch((error) => {
+1111 -24
View File
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -7,8 +7,7 @@
"format": "dprint fmt" "format": "dprint fmt"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/node": "^2.0.0-beta.2", "@modelcontextprotocol/sdk": "^1.29.0",
"@modelcontextprotocol/server": "^2.0.0-beta.2",
"commander": "^15.0.0", "commander": "^15.0.0",
"fast-xml-parser": "^5.2.0", "fast-xml-parser": "^5.2.0",
"httpntlm": "^1.8.13", "httpntlm": "^1.8.13",
+1 -1
View File
@@ -1,6 +1,6 @@
import { z } from "zod/v4"; import { z } from "zod/v4";
import { EwsClient, loadConfig, saveConfig, clearConfig } from "../ews_client.ts"; import { EwsClient, loadConfig, saveConfig, clearConfig } from "../ews_client.ts";
import { type McpServer } from "@modelcontextprotocol/server"; import { type McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
export function registerAuthTools(server: McpServer): void { export function registerAuthTools(server: McpServer): void {
server.registerTool( server.registerTool(
+1 -1
View File
@@ -1,6 +1,6 @@
import { z } from "zod/v4"; import { z } from "zod/v4";
import { EwsClient, loadConfig } from "../ews_client.ts"; import { EwsClient, loadConfig } from "../ews_client.ts";
import { type McpServer } from "@modelcontextprotocol/server"; import { type McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
function getClient(): EwsClient { function getClient(): EwsClient {
return new EwsClient(loadConfig()); return new EwsClient(loadConfig());
+1 -1
View File
@@ -1,6 +1,6 @@
import { z } from "zod/v4"; import { z } from "zod/v4";
import { EwsClient, loadConfig } from "../ews_client.ts"; import { EwsClient, loadConfig } from "../ews_client.ts";
import { type McpServer } from "@modelcontextprotocol/server"; import { type McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
export function registerFolderTools(server: McpServer): void { export function registerFolderTools(server: McpServer): void {
server.registerTool( server.registerTool(