index.ts•3.79 kB
#!/usr/bin/env node
import * as Sentry from "@sentry/node";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
Tool,
} from "@modelcontextprotocol/sdk/types.js";
import { evaluate, parse } from "mathjs";
// Initialize Sentry - must be above everything else
Sentry.init({
dsn: "https://2b1607db500835045457f4e5ca61de65@o4509013641854976.ingest.us.sentry.io/4510225201954816",
tracesSampleRate: 1.0,
enableLogs: true,
environment: "mcp-server",
// Optional: Enable to capture tool call arguments and results, which may include PII
sendDefaultPii: true,
integrations: [
Sentry.consoleIntegration({ levels: ["error", "warn"] }),
],
});
// Define the evaluate tool
const EVALUATE_TOOL: Tool = {
name: "evaluate",
description:
"Evaluates a mathematical expression and returns the result. " +
"Supports basic arithmetic (+, -, *, /), exponents (^), parentheses, " +
"and common math functions. Examples: '2 + 2', '3 * (4 + 5)', 'sqrt(16)', 'sin(pi/2)'",
inputSchema: {
type: "object",
properties: {
expression: {
type: "string",
description: "The mathematical expression to evaluate",
},
},
required: ["expression"],
},
};
// Create server instance and wrap with Sentry
const server = Sentry.wrapMcpServerWithSentry(
new Server(
{
name: "mcp-math-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
)
);
// Handle tool listing
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [EVALUATE_TOOL],
};
});
// Handle tool execution
// Note: wrapMcpServerWithSentry automatically instruments this handler
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "evaluate") {
const expression = request.params.arguments?.expression;
if (typeof expression !== "string") {
throw new Error("Expression must be a string");
}
try {
// Validate the expression by parsing it first
parse(expression);
// Evaluate the expression
const result = evaluate(expression);
// Log successful evaluation
const { logger } = Sentry;
logger.info("Math expression evaluated successfully", {
expression,
result: String(result),
});
return {
content: [
{
type: "text",
text: JSON.stringify({
expression,
result: String(result),
success: true,
}, null, 2),
},
],
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
// Capture the error in Sentry
Sentry.captureException(error, {
tags: {
"mcp.tool": "evaluate",
"mcp.expression": expression,
},
});
return {
content: [
{
type: "text",
text: JSON.stringify({
expression,
error: errorMessage,
success: false,
}, null, 2),
},
],
isError: true,
};
}
}
throw new Error(`Unknown tool: ${request.params.name}`);
});
// Start server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Math Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error:", error);
Sentry.captureException(error, {
level: "fatal",
});
// Flush Sentry before exiting
Sentry.close(2000).then(() => {
process.exit(1);
});
});