Documentation Index Fetch the complete documentation index at: https://docs.agentfront.dev/llms.txt
Use this file to discover all available pages before exploring further.
Build a simple calculator tool to learn the fundamentals of FrontMCP tool development. By the end of this guide, you’ll understand how to create, validate, and test MCP tools.
What You’ll Build
A simple add tool that adds two numbers together with full type safety and input validation.
Create a new file src/apps/calculator/tools/add.tool.ts:
import { Tool , ToolContext } from ' @frontmcp/sdk ' ;
import { z } from ' @frontmcp/sdk ' ;
@ Tool ({
name : ' add ' ,
description : ' Add two numbers together ' ,
inputSchema : {
a : z . number (). describe ( ' First number ' ),
b : z . number (). describe ( ' Second number ' ),
},
outputSchema : ' number ' ,
})
export default class AddTool extends ToolContext {
async execute ( input : { a : number ; b : number }) {
return input . a + input . b ;
}
}
Let’s break this down:
Property Purpose nameUnique identifier for the tool descriptionHelps LLMs understand when to use this tool inputSchemaZod schema for input validation outputSchemaCan be a Zod schema or shorthand like 'number' execute()The logic that runs when the tool is called
Step 2: Create the App
Create src/apps/calculator/index.ts to group your tools:
import { App } from ' @frontmcp/sdk ' ;
import AddTool from ' ./tools/add.tool ' ;
@ App ({
id : ' calculator ' ,
name : ' Calculator App ' ,
tools : [ AddTool ],
})
export default class CalculatorApp {}
Step 3: Register with the Server
Update your main server file to include the app:
import { FrontMcp , LogLevel } from ' @frontmcp/sdk ' ;
import CalculatorApp from ' ./apps/calculator ' ;
@ FrontMcp ({
info : { name : ' My MCP Server ' , version : ' 1.0.0 ' },
apps : [ CalculatorApp ],
http : { port : 3000 },
logging : { level : LogLevel . INFO },
})
export default class Server {}
Open MCP Inspector
npx @modelcontextprotocol/inspector
Connect to http://localhost:3000 and you’ll see your calculator:add tool listed.
Call the tool
In the Inspector, call the tool with: You should get back 8.
Let’s add a multiply tool. Create src/apps/calculator/tools/multiply.tool.ts:
import { Tool , ToolContext } from ' @frontmcp/sdk ' ;
import { z } from ' @frontmcp/sdk ' ;
@ Tool ({
name : ' multiply ' ,
description : ' Multiply two numbers together ' ,
inputSchema : {
a : z . number (). describe ( ' First number ' ),
b : z . number (). describe ( ' Second number ' ),
},
outputSchema : ' number ' ,
})
export default class MultiplyTool extends ToolContext {
async execute ( input : { a : number ; b : number }) {
return input . a * input . b ;
}
}
Then add it to your app:
import { App } from ' @frontmcp/sdk ' ;
import AddTool from ' ./tools/add.tool ' ;
import MultiplyTool from ' ./tools/multiply.tool ' ;
@ App ({
id : ' calculator ' ,
name : ' Calculator App ' ,
tools : [ AddTool , MultiplyTool ],
})
export default class CalculatorApp {}
Zod automatically validates inputs. Try calling add with invalid input:
{ " a " : " not a number " , " b " : 3 }
You’ll get a validation error because "not a number" isn’t a valid number.
Common Validation Patterns
inputSchema : {
// Required string
name : z . string (). min ( 1 ),
// Optional with default
limit : z . number (). default ( 10 ),
// Enum values
status : z . enum ([ ' active ' , ' inactive ' ]),
// Array of strings
tags : z . array ( z . string ()),
// Nested object
config : z . object ({
enabled : z . boolean (),
threshold : z . number (). positive (),
}),
}
Best Practices
Good descriptions help LLMs choose the right tool: // Good - specific and actionable
description : ' Add two numbers together and return their sum '
// Bad - too vague
description : ' Math operation '
Use .describe() on schema fields
Add context for each input field: inputSchema : {
amount : z . number (). positive (). describe ( ' Amount in USD ' ),
category : z . string (). describe ( ' Expense category like "travel" or "meals" ' ),
}
Each tool should do one thing well. Instead of a calculate tool that handles add/subtract/multiply/divide, create separate tools for each operation.
async execute ( input : { a : number ; b : number }) {
if ( input . b === 0 ) {
throw new Error ( ' Cannot divide by zero ' );
}
return input . a / input . b ;
}
Next Steps
Add Caching Cache tool results for better performance
Create Prompts Build prompts and resources alongside tools
Add UI Templates Render rich HTML widgets for tool outputs
Tool Reference Full tool decorator documentation