Tool Registration
Each entry in tools becomes an MCP tool:
{ name: 'mm_harvest_list_projects', description: 'List active Harvest projects with budget and client.', inputSchema: z.object({ project_path: z.string() }), handler: async (args) => ({ content: [{ type: 'text', text: '…' }] })}mm_-prefixed, unique across every loaded plugin and built-in. A collision refuses the whole plugin, so nothing silently shadows a core tool.
Schemas
Section titled “Schemas”Zod in, JSON Schema out. Describe each field — agents choose arguments from those descriptions alone. Optional fields need sensible defaults; an agent won’t guess.
Visibility
Section titled “Visibility”Bundled plugin tools belong to a tool group (harvest, slack, trello, voice, imports) and are hidden until that group is opted into with MM_TOOL_GROUPS. A community plugin’s tools belong to no group, so they’re always listed.
Hidden never means disabled — any tool still runs when called by name.
Errors
Section titled “Errors”Throw with a message a person can act on (“no Harvest token — set HARVEST_ACCESS_TOKEN”). The agent shows it to the user.