Tools are actions AI can perform — the primary way AI interacts with your system. When an AI agent needs to do something (send email, create task, query database), it calls a tool.
Tools are triggered by the AI agent, not the user. The LLM decides when to call a tool based on the user’s request and the tool’s description. Users don’t directly invoke tools — they ask the AI, and the AI decides which tools to use.
Claude Desktop / Cursor — Connect your MCP and chat with it
LeanMCP Sandbox — Test tools directly in the browser
Postman — Send raw MCP requests to your server
Every tool you add increases token usage. Keep descriptions concise and only expose tools the AI actually needs. See Reducing Tokens in MCPs for optimization strategies.
AI uses descriptions to understand when to use tools.Bad:"Process data"Good:"Search customer orders by date range and status"
Design for minimal tool calls
Every tool call costs tokens and time. Design tools that accomplish goals in one call, not a chain of 7-8 calls.❌ BAD: Hotel booking with 7+ tool callsEach call: AI generates request → waits for response → processes → generates next request. 7 round trips, thousands of tokens.✅ GOOD: One tool that does it all
class BookHotelInput { @SchemaConstraint({ description: "City name" }) city!: string; @SchemaConstraint({ description: "Check-in date (YYYY-MM-DD)" }) checkIn!: string; @SchemaConstraint({ description: "Check-out date (YYYY-MM-DD)" }) checkOut!: string; @SchemaConstraint({ description: "Number of guests" }) guests!: number; @Optional() @SchemaConstraint({ description: "Max price per night in USD" }) maxPrice?: number;}@Tool({ description: "Book a hotel room. Returns available options with prices, or confirms booking if user approves.", inputClass: BookHotelInput})async bookHotel(input: BookHotelInput) { // All logic happens server-side in one call const options = await this.findAndPriceRooms(input); return { options: options.slice(0, 3), // Top 3 choices message: "Reply with option number to confirm booking" };}
One call, one response. The server handles the complexity, not the AI.
Keep tools focused
One tool, one job. Don’t combine unrelated actions.Bad:"manageUser" (create, update, delete in one)Good:"createUser", "updateUser", "deleteUser"
Validate all inputs
Use @SchemaConstraint for all inputs. AI makes fewer mistakes with validated schemas.
Return meaningful data
Return useful data AI can use in follow-up actions.Bad:return { success: true }Good:return { created: true, id: "123", name: "John" }
Handle errors gracefully
Throw clear errors. AI can explain issues to users.