Find Contacts
find_contactsSearch contacts by name or ID with optional substring filter. Paginate results using limit and offset to control payload size.
Instructions
Find contacts for the pinned instance. Supports search (substring on pushName/name/remoteJid), limit, and offset to prevent large payloads. Returns normalized { remoteJid, pushName, profilePicUrl, isBusiness } — extra fields dropped.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| where | No | Optional Prisma-style filter object (power-user). If supplied, search is ignored. | |
| search | No | Convenience substring filter against pushName, name, or remoteJid (case-insensitive). Ignored when where is provided. | |
| limit | No | Max results to return (default 200, max 2000). | |
| offset | No | Skip first N results (default 0). |
Implementation Reference
- src/tools/find-contacts.ts:41-97 (handler)The registerFindContacts function that registers the 'find_contacts' tool on the MCP server. It contains the full handler logic: builds a payload with limit/offset (and optional where), calls Evolution API at /chat/findContacts/{instanceName}, optionally filters by search substring on pushName/name/remoteJid, applies client-side slice, normalizes output to { remoteJid, pushName, profilePicUrl, isBusiness }, and returns JSON text.
export function registerFindContacts(server: McpServer, client: EvolutionClient): void { server.registerTool( "find_contacts", { title: "Find Contacts", description: "Find contacts for the pinned instance. Supports search (substring on pushName/name/remoteJid), limit, and offset to prevent large payloads. " + "Returns normalized { remoteJid, pushName, profilePicUrl, isBusiness } — extra fields dropped.", inputSchema: schema, }, async (args) => { try { const limit = args.limit ?? 200; const offset = args.offset ?? 0; const payload: Record<string, unknown> = args.where ? { where: args.where, limit, offset } : { limit, offset }; const raw = await client.post(`/chat/findContacts/${client.instanceName}`, payload); let contacts: ContactItem[] = Array.isArray(raw) ? raw : []; // Client-side search only when no custom where was supplied if (!args.where && args.search) { const needle = args.search.toLowerCase(); contacts = contacts.filter( (c) => c.pushName?.toLowerCase().includes(needle) || c.name?.toLowerCase().includes(needle) || c.remoteJid?.toLowerCase().includes(needle) ); } // Client-side safety net for limit/offset (in case Evolution ignores them) contacts = contacts.slice(offset, offset + limit); // Normalize to compact shape — drop everything else const normalized = contacts.map(({ remoteJid, pushName, profilePicUrl, isBusiness }) => ({ remoteJid, pushName, profilePicUrl, isBusiness, })); return { content: [{ type: "text" as const, text: JSON.stringify(normalized, null, 2) }], }; } catch (e) { if (e instanceof McpError) { return { isError: true, content: [{ type: "text" as const, text: e.message }] }; } throw e; } } ); } - src/tools/find-contacts.ts:15-39 (schema)Input schema for find_contacts using Zod: 'where' (optional Prisma-style filter object), 'search' (optional substring filter), 'limit' (1-2000, default 200), 'offset' (min 0, default 0).
const schema = { where: z .record(z.unknown()) .optional() .describe("Optional Prisma-style filter object (power-user). If supplied, search is ignored."), search: z .string() .optional() .describe("Convenience substring filter against pushName, name, or remoteJid (case-insensitive). Ignored when where is provided."), limit: z .number() .int() .min(1) .max(2000) .default(200) .optional() .describe("Max results to return (default 200, max 2000)."), offset: z .number() .int() .min(0) .default(0) .optional() .describe("Skip first N results (default 0)."), }; - src/tools/find-contacts.ts:42-49 (registration)Tool registration call: server.registerTool('find_contacts', ...) with title 'Find Contacts' and description.
server.registerTool( "find_contacts", { title: "Find Contacts", description: "Find contacts for the pinned instance. Supports search (substring on pushName/name/remoteJid), limit, and offset to prevent large payloads. " + "Returns normalized { remoteJid, pushName, profilePicUrl, isBusiness } — extra fields dropped.", inputSchema: schema, - src/tools/index.ts:7-7 (registration)Import of registerFindContacts from './find-contacts.js' in the central tools barrel file.
import { registerFindContacts } from "./find-contacts.js"; - src/tools/index.ts:80-80 (registration)Call to registerFindContacts(server, client) inside registerAllTools to wire up the tool at startup.
registerFindContacts(server, client);