Skip to main content
Glama

calculate

Perform basic arithmetic operations like addition, subtraction, multiplication, and division with two operands. Supports progress notifications for streaming calculations directly from the MCP server.

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 primary handler function for the 'calculate' tool. Handles input validation (already done by SDK), optional progress streaming, delegates to performBasicCalculation, manages history, and returns protocol-compliant response with both text content and structured data.
    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-based input and output schemas defining the contract for the 'calculate' tool. Input includes operands a/b, operation op, and optional stream flag. Output includes the result value and 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)
    Registers the 'calculate' tool on the MCP server instance, specifying name, metadata, 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 pure function implementing the basic arithmetic operations (add, subtract, multiply, divide) with fail-fast error handling for invalid operations and division by zero. Called by the 'calculate' handler.
    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}`); } }

Other Tools

Related Tools

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