import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { sfQuery } from "../salesforce-client.js"; export function registerPipelineTools(server: McpServer): void { server.tool( "search_leads", "Search for leads in Salesforce", { query: z.string().describe("Search query"), status: z .string() .optional() .describe("Lead status filter (e.g., Open, Working, Closed)"), limit: z.number().default(10).describe("Maximum number of results"), }, async ({ query, status, limit }) => { const escapedQuery = query.replace(/'/g, "\\'"); let whereClause = `Name LIKE '%${escapedQuery}%' OR Email LIKE '%${escapedQuery}%' OR Company LIKE '%${escapedQuery}%'`; if (status) { whereClause = `(${whereClause}) AND Status = '${status}'`; } const soql = ` SELECT Id, Name, Email, Phone, Company, Status, LeadSource, CreatedDate FROM Lead WHERE ${whereClause} ORDER BY CreatedDate DESC LIMIT ${limit} `; const records = await sfQuery(soql); return { content: [{ type: "text", text: JSON.stringify(records, null, 2) }], }; } ); server.tool( "get_opportunities", "Get opportunities from Salesforce pipeline", { stage: z .string() .optional() .describe( "Filter by stage (e.g., Prospecting, Negotiation, Closed Won)" ), accountId: z.string().optional().describe("Filter by account ID"), limit: z.number().default(20).describe("Maximum number of results"), }, async ({ stage, accountId, limit }) => { const conditions: string[] = []; if (stage) conditions.push(`StageName = '${stage}'`); if (accountId) conditions.push(`AccountId = '${accountId}'`); const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : ""; const soql = ` SELECT Id, Name, StageName, Amount, CloseDate, Account.Name, Owner.Name, Probability FROM Opportunity ${whereClause} ORDER BY CloseDate ASC LIMIT ${limit} `; const records = await sfQuery(soql); return { content: [{ type: "text", text: JSON.stringify(records, null, 2) }], }; } ); server.tool( "soql_query", "Execute a custom SOQL query against Salesforce (read-only)", { query: z.string().describe("SOQL query to execute"), }, async ({ query }) => { if (!query.trim().toUpperCase().startsWith("SELECT")) { return { content: [ { type: "text", text: "Error: Only SELECT queries are allowed" }, ], isError: true, }; } const records = await sfQuery(query); return { content: [{ type: "text", text: JSON.stringify(records, null, 2) }], }; } ); }