Skip to main content
Tools are the core unit of work in redop. Each tool becomes an MCP tool that a client can discover and call.

The shape

app.tool("create_post", {
  description: "Create a post",
  input: z.object({
    title: z.string(),
  }),
  handler: ({ input }) => {
    return { ok: true, title: input.title };
  },
});

Tool config fields

  • description explains what the tool does
  • input defines runtime validation and tool schema generation
  • handler contains the business logic
  • before runs after global onBeforeHandle
  • after runs before global onAfterHandle
  • annotations adds MCP tool metadata hints

When to use tool-local hooks

Use tool-local before / after when logic is specific to one tool:
  • result-aware analytics
  • domain events
  • tool-specific audit trails
  • post-processing close to the handler
Keep framework-wide logging and aggregate analytics in global hooks instead.

Common mistake

Do not move all logic into hooks. Your handler should still be the main place where the tool does its work.