Tulip Logo IconTulip
Concepts

Tools

Define one canonical tool and resolve it for agents, MCP, and client rendering.

Tools are split into a canonical definition and transport-specific resolvers.

Define a tool

import { defineTool, resolveAgentTool, resolveMCPTool } from "@tulip-systems/ai/tools/server";
import { json } from "@tulip-systems/ai/mcp/server";
import { z } from "zod";

export const createProspect = defineTool({
  name: "create_prospect",
  title: "Create Prospect",
  description: "Create a prospect after duplicate checks and user approval.",
  inputSchema: z.object({
    prospect: z.object({
      name: z.string().min(1),
      email: z.string().email().optional(),
      website: z.string().url().optional(),
    }),
  }),
  outputSchema: z.object({
    prospectId: z.string(),
  }),
  async execute(input) {
    return { prospectId: input.prospect.name };
  },
});

export const createProspectTool = resolveAgentTool(createProspect, {
  permissions: ["prospect:create"],
  confirmation: {
    required: true,
    title: "Create prospect?",
    description: "Review the prospect details before creating a CRM record.",
  },
  audit: {
    action: "prospect.create",
    resource: "prospect",
    severity: "medium",
  },
});

export const createProspectMCPTool = resolveMCPTool(createProspect, {
  description: "Create a new prospect in the CRM.",
  content: ({ output }) => json(output, { label: "Created prospect" }),
});

Client renderers

Use defineToolClient() to render tool parts in chat without importing server code into the client bundle.

"use client";

import { ToolCallCard } from "@tulip-systems/ai/chat/client";
import { defineToolClient } from "@tulip-systems/ai/tools/client";
import type { createProspect } from "./tool.server";

export const createProspectToolClient = defineToolClient<typeof createProspect>({
  toolName: "create_prospect",
  render: (part) => <ToolCallCard part={part} title="Prospect aanmaken" />,
});

Guidance

  • Keep defineTool() lean and reusable.
  • Put permissions, confirmation, audit, and UI metadata in resolvers.
  • Use type-only imports from server tools in client renderers.
  • Use read tools before write tools for safer agent behavior.
  • Add confirmation metadata for business mutations.

On this page