import { type McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod/v4"; import { EwsClient, loadConfig } from "../ews_client.ts"; export function registerPeopleTools(server: McpServer): void { server.registerTool( "find_person", { description: "Search for people in the corporate directory (Active Directory)" + " by name, email, or keyword.", inputSchema: z.object({ query: z.string().describe( "Name, email address, or keyword to search for", ), }), outputSchema: z.object({ name: z.string(), email: z.string(), mailboxType: z.string(), firstName: z.string(), lastName: z.string(), jobTitle: z.string(), department: z.string(), company: z.string(), office: z.string(), alias: z.string(), manager: z.string(), managerEmail: z.string(), phones: z.record(z.string(), z.string()), address: z.string(), directReports: z.array(z.object({ name: z.string(), email: z.string(), })), }), }, async ({ query }) => { try { const client = new EwsClient(loadConfig()); const resolutions = await client.resolveNames(query); const people = resolutions.map((r: any) => { const mailbox = r.Mailbox ?? {}; const contact = r.Contact ?? {}; const person: any = { name: mailbox.Name ?? contact.DisplayName ?? "", email: mailbox.EmailAddress ?? "", mailboxType: mailbox.MailboxType ?? "", firstName: contact.GivenName ?? "", lastName: contact.Surname ?? "", jobTitle: contact.JobTitle ?? "", department: contact.Department ?? "", company: contact.CompanyName ?? "", office: contact.OfficeLocation ?? "", alias: contact.Alias ?? "", manager: "", managerEmail: "", phones: {}, address: "", directReports: [], }; const phones = contact.PhoneNumbers?.PhoneNumber ?? []; const phoneList = Array.isArray(phones) ? phones : [phones]; for (const p of phoneList) { if (p?.Key && p?.PhoneNumber) { person.phones[p.Key] = p.PhoneNumber; } } const addrs = contact.PhysicalAddresses?.PhysicalAddress ?? []; const addrList = Array.isArray(addrs) ? addrs : [addrs]; for (const a of addrList) { if (a?.Key === "Business") { const parts = [a.Street, a.City, a.PostalCode, a.CountryOrRegion] .filter(Boolean); if (parts.length) { person.address = parts.join(", "); } } } const managerData = contact.ManagerMailbox?.Mailbox ?? {}; if (managerData.Name || managerData.EmailAddress) { person.manager = managerData.Name ?? ""; person.managerEmail = managerData.EmailAddress ?? ""; } else if (contact.Manager) { person.manager = contact.Manager; } const reports = contact.DirectReports?.DirectReport ?? []; const reportList = Array.isArray(reports) ? reports : [reports]; for (const rp of reportList) { if (rp?.Name || rp?.EmailAddress) { person.directReports.push({ name: rp.Name ?? "", email: rp.EmailAddress ?? "", }); } } return person; }); return { content: [{ type: "text" as const, text: JSON.stringify(people) }], structuredContent: { people }, }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ error: error.message ?? String(error) }), }], }; } }, ); }