search_emails
Search emails by keyword with optional inbox filtering. Returns matching messages from your default or specified inbox.
Instructions
Search emails by keyword. If inbox_id is omitted, uses the default inbox.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| inbox_id | No | Inbox ID (optional, uses default inbox) | |
| query | Yes | Search query |
Implementation Reference
- mcp/index.js:240-257 (registration)MCP tool registration for 'search_emails' using server.tool(). Registers the tool with name 'search_emails', description 'Search emails by keyword. If inbox_id is omitted, uses the default inbox.', an optional inbox_id schema and a required query string schema. The handler calls the API endpoint GET /v1/inboxes/${inbox_id}/search?q=${query}.
server.tool( 'search_emails', 'Search emails by keyword. If inbox_id is omitted, uses the default inbox.', { inbox_id: idSchema.optional().describe('Inbox ID (optional, uses default inbox)'), query: z.string().describe('Search query') }, async ({ inbox_id, query }) => { if (!inbox_id) { const inbox = await getOrCreateDefaultInbox(); if (inbox.error) return { content: [{ type: 'text', text: JSON.stringify(inbox, null, 2) }] }; inbox_id = inboxId(inbox); } const params = new URLSearchParams({ q: query }); const result = await api('GET', `/v1/inboxes/${inbox_id}/search?${params}`); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } ); - mcp/index.js:243-246 (schema)Input schema for the search_emails tool. Defines optional inbox_id (number or numeric string via idSchema) and required query (string) parameters.
{ inbox_id: idSchema.optional().describe('Inbox ID (optional, uses default inbox)'), query: z.string().describe('Search query') }, - src/db.js:471-483 (handler)Core database function that executes the email search. Uses SQL with LIKE queries on subject, text_content, and from_addr columns, ordered by created_at descending with a limit (default 20).
export function searchEmails({ inboxId, query, limit = 20 }) { const like = `%${query}%`; const stmt = db.prepare(` SELECT * FROM emails WHERE inbox_id = ? AND (subject LIKE ? OR text_content LIKE ? OR from_addr LIKE ?) ORDER BY created_at DESC LIMIT ? `); stmt.bind([inboxId, like, like, like, limit]); const rows = []; while (stmt.step()) rows.push(formatEmail(stmt.getAsObject())); stmt.free(); return rows; } - src/index.js:266-281 (helper)REST API endpoint handler for GET /v1/inboxes/:inboxId/search. Parses query params q and limit, validates the inbox exists and belongs to the user, and delegates to the searchEmails function from db.js.
// === ๆ็ดข === app.get('/v1/inboxes/:inboxId/search', (req, res) => { try { const inbox = getInboxById(req.params.inboxId, req.user.id); if (!inbox) return res.status(404).json({ error: 'Inbox not found' }); const { q, limit = 20 } = req.query; if (!q) return res.status(400).json({ error: 'q (query) is required' }); const results = searchEmails({ inboxId: inbox.id, query: q, limit: parseInt(limit) }); res.json(results); } catch (err) { res.status(500).json({ error: err.message }); } }); - src/index.js:10-11 (helper)Import of searchEmails from db.js into the Express server (src/index.js), used by the REST API route.
getEmails, getEmailById, markAsRead, insertEmail, searchEmails, getThreads, getThreadMessages,