167 lines
4.4 KiB
TypeScript
167 lines
4.4 KiB
TypeScript
import { type McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
import { z } from "zod/v4";
|
|
import {
|
|
clearConfig,
|
|
EwsClient,
|
|
hasPassword,
|
|
loadConfig,
|
|
saveConfig,
|
|
setPassword,
|
|
} from "../ews_client.ts";
|
|
import type { LoginConfig } from "../types/login_config.ts";
|
|
|
|
export function registerAuthTools(server: McpServer): void {
|
|
server.registerTool(
|
|
"login",
|
|
{
|
|
description: "Authenticate to Exchange EWS using NTLM credentials",
|
|
inputSchema: z.object({
|
|
serverUrl: z.string().optional().describe(
|
|
"EWS server URL (e.g. https://mail.example.com)",
|
|
),
|
|
email: z.string().optional().describe("Email address"),
|
|
username: z.string().optional().describe("NTLM username"),
|
|
password: z.string().describe("NTLM password"),
|
|
domain: z.string().optional().describe("NTLM domain (default: corp)"),
|
|
}),
|
|
},
|
|
async ({ serverUrl, email, username, password, domain }) => {
|
|
try {
|
|
let savedConfig: Partial<LoginConfig> = {};
|
|
try {
|
|
savedConfig = loadConfig();
|
|
} catch {
|
|
// no saved config — all fields must be provided
|
|
}
|
|
|
|
const config: LoginConfig = {
|
|
serverUrl: (serverUrl ?? savedConfig.serverUrl)!,
|
|
email: (email ?? savedConfig.email)!,
|
|
username: (username ?? savedConfig.username)!,
|
|
domain: domain ?? savedConfig.domain ?? "corp",
|
|
};
|
|
|
|
if (!config.serverUrl || !config.email || !config.username) {
|
|
return {
|
|
content: [{
|
|
type: "text" as const,
|
|
text: JSON.stringify({
|
|
success: false,
|
|
error:
|
|
"Missing required fields. Provide serverUrl, email, and username, or login once with all fields first.",
|
|
}),
|
|
}],
|
|
};
|
|
}
|
|
|
|
config.serverUrl = config.serverUrl.replace(/\/+$/, "");
|
|
|
|
const client = new EwsClient(config, password);
|
|
const result = await client.verifyConnection();
|
|
|
|
if (!result.ok) {
|
|
return {
|
|
content: [{
|
|
type: "text" as const,
|
|
text: JSON.stringify({
|
|
success: false,
|
|
error: result.error ?? "Connection verification failed",
|
|
}),
|
|
}],
|
|
};
|
|
}
|
|
|
|
saveConfig(config);
|
|
|
|
return {
|
|
content: [{
|
|
type: "text" as const,
|
|
text: JSON.stringify({
|
|
success: true,
|
|
message: `Logged in as ${email} to ${serverUrl}`,
|
|
}),
|
|
}],
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
content: [{
|
|
type: "text" as const,
|
|
text: JSON.stringify({
|
|
success: false,
|
|
error: error.message ?? String(error),
|
|
}),
|
|
}],
|
|
};
|
|
}
|
|
},
|
|
);
|
|
|
|
server.registerTool(
|
|
"check_session",
|
|
{
|
|
description: "Check whether the current EWS session is authenticated",
|
|
inputSchema: z.object({}),
|
|
},
|
|
async () => {
|
|
try {
|
|
if (!hasPassword()) {
|
|
return {
|
|
content: [{
|
|
type: "text" as const,
|
|
text: JSON.stringify({
|
|
authenticated: false,
|
|
error: "Not logged in. Password not found in memory.",
|
|
}),
|
|
}],
|
|
};
|
|
}
|
|
const config = loadConfig();
|
|
const client = new EwsClient(config);
|
|
const result = await client.verifyConnection();
|
|
|
|
return {
|
|
content: [{
|
|
type: "text" as const,
|
|
text: JSON.stringify({
|
|
authenticated: result.ok,
|
|
email: config.email,
|
|
serverUrl: config.serverUrl,
|
|
error: result.error,
|
|
}),
|
|
}],
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
content: [{
|
|
type: "text" as const,
|
|
text: JSON.stringify({
|
|
authenticated: false,
|
|
error: error.message ?? String(error),
|
|
}),
|
|
}],
|
|
};
|
|
}
|
|
},
|
|
);
|
|
|
|
server.registerTool(
|
|
"logout",
|
|
{
|
|
description: "Clear stored credentials",
|
|
inputSchema: z.object({}),
|
|
},
|
|
async () => {
|
|
clearConfig();
|
|
return {
|
|
content: [{
|
|
type: "text" as const,
|
|
text: JSON.stringify({
|
|
success: true,
|
|
message: "Logged out. Credentials cleared.",
|
|
}),
|
|
}],
|
|
};
|
|
},
|
|
);
|
|
}
|