Skip to main content
Glama

calculate

Perform basic arithmetic calculations with two numbers using addition, subtraction, multiplication, or division operations.

Instructions

Perform a basic arithmetic calculation

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
aYesFirst operand
bYesSecond operand
opYesOperation to perform
streamNoIf true, emit progress notifications

Implementation Reference

  • The handler function for the 'calculate' tool. It handles input parameters, optional streaming progress, calls the core calculation helper, manages history, and returns structured output with error handling.
    async ({ a, b, op, stream }, { sendNotification }) => { log.info(`Executing calculate: ${a} ${op} ${b}`); requestCount++; try { // FEATURE: Progress notifications for streaming calculations // WHY: Demonstrates real-time feedback using sendNotification if (stream) { const progressId = `calc-${Date.now()}`; await sendNotification({ method: 'notifications/progress', params: { progressToken: progressId, progress: 33, message: `Calculating ${a} ${op} ${b}`, }, }); await new Promise((resolve) => setTimeout(resolve, 100)); await sendNotification({ method: 'notifications/progress', params: { progressToken: progressId, progress: 66 }, }); await new Promise((resolve) => setTimeout(resolve, 100)); await sendNotification({ method: 'notifications/progress', params: { progressToken: progressId, progress: 100, message: 'Complete' }, }); await new Promise((resolve) => setTimeout(resolve, 100)); } // Core business logic: perform the calculation const result = performBasicCalculation(op, a, b); // Create and store history entry const historyEntry = createHistoryEntry(op, a, b, result); addToHistory(historyEntry); // SDK-NOTE: The return object must match the `outputSchema`. // The SDK will validate this before sending the response. // We provide both a simple text `content` for basic UIs and a // `structuredContent` for richer clients. return { content: [ { type: 'text', text: historyEntry.expression, }, ], structuredContent: { value: result, meta: { calculationId: historyEntry.id, timestamp: historyEntry.timestamp, }, }, }; } catch (error) { // CAVEAT: We catch the error from our business logic and re-throw it. // While `performBasicCalculation` already returns an McpError, this pattern // is crucial for wrapping any *unexpected* errors that might occur, // preventing stack traces from leaking to the client. log.error(`Calculation failed: ${error instanceof Error ? error.message : String(error)}`); throw new McpError( ErrorCode.InvalidParams, `Calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, { operation: op, a, b }, ); } },
  • Zod input and output schemas for the 'calculate' tool, defining parameters a, b, op (enum of arithmetic operations), optional stream flag, and output value with metadata.
    const calculateInputSchema = { a: z.number().describe('First operand'), b: z.number().describe('Second operand'), op: z.enum(['add', 'subtract', 'multiply', 'divide']).describe('Operation to perform'), stream: z.boolean().optional().describe('If true, emit progress notifications'), }; const calculateOutputSchema = { value: z.number(), meta: z.object({ calculationId: z.string(), timestamp: z.string(), }), };
  • src/server.ts:274-355 (registration)
    Registration of the 'calculate' tool with the MCP server, including title, description, schemas, and handler function.
    server.registerTool( 'calculate', { title: 'Calculate', description: 'Perform a basic arithmetic calculation', inputSchema: calculateInputSchema, outputSchema: calculateOutputSchema, }, // HANDLER LOGIC: // - Async function, receives validated & typed parameters. // - The SDK automatically parses the input against `inputSchema`. // - If validation fails, the SDK sends the error; this code doesn't run. async ({ a, b, op, stream }, { sendNotification }) => { log.info(`Executing calculate: ${a} ${op} ${b}`); requestCount++; try { // FEATURE: Progress notifications for streaming calculations // WHY: Demonstrates real-time feedback using sendNotification if (stream) { const progressId = `calc-${Date.now()}`; await sendNotification({ method: 'notifications/progress', params: { progressToken: progressId, progress: 33, message: `Calculating ${a} ${op} ${b}`, }, }); await new Promise((resolve) => setTimeout(resolve, 100)); await sendNotification({ method: 'notifications/progress', params: { progressToken: progressId, progress: 66 }, }); await new Promise((resolve) => setTimeout(resolve, 100)); await sendNotification({ method: 'notifications/progress', params: { progressToken: progressId, progress: 100, message: 'Complete' }, }); await new Promise((resolve) => setTimeout(resolve, 100)); } // Core business logic: perform the calculation const result = performBasicCalculation(op, a, b); // Create and store history entry const historyEntry = createHistoryEntry(op, a, b, result); addToHistory(historyEntry); // SDK-NOTE: The return object must match the `outputSchema`. // The SDK will validate this before sending the response. // We provide both a simple text `content` for basic UIs and a // `structuredContent` for richer clients. return { content: [ { type: 'text', text: historyEntry.expression, }, ], structuredContent: { value: result, meta: { calculationId: historyEntry.id, timestamp: historyEntry.timestamp, }, }, }; } catch (error) { // CAVEAT: We catch the error from our business logic and re-throw it. // While `performBasicCalculation` already returns an McpError, this pattern // is crucial for wrapping any *unexpected* errors that might occur, // preventing stack traces from leaking to the client. log.error(`Calculation failed: ${error instanceof Error ? error.message : String(error)}`); throw new McpError( ErrorCode.InvalidParams, `Calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`, { operation: op, a, b }, ); } }, );
  • Core helper function that executes the basic arithmetic logic based on the operation type, with validation for division by zero and unknown operations.
    function performBasicCalculation(op: string, a: number, b: number): number { switch (op) { case 'add': return a + b; case 'subtract': return a - b; case 'multiply': return a * b; case 'divide': if (b === 0) throw new McpError(ErrorCode.InvalidParams, 'Division by zero'); return a / b; default: throw new McpError(ErrorCode.InvalidParams, `Unknown operation: ${op}`); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yigitkonur/example-mcp-server-stdio'

If you have feedback or need assistance with the MCP directory API, please join our Discord server