index.ts•4.5 kB
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
Tool,
TextContent,
} from '@modelcontextprotocol/sdk/types.js';
// Input validation helper
const validateString = (value: unknown, fieldName: string): string => {
if (typeof value !== 'string') {
throw new Error(`${fieldName} must be a string`);
}
return value;
};
const validateNumber = (value: unknown, fieldName: string): number => {
const num = Number(value);
if (isNaN(num)) {
throw new Error(`${fieldName} must be a valid number`);
}
return num;
};
// Define the available tools
const tools: Tool[] = [
{
name: 'echo',
description: 'Echo back the input text',
inputSchema: {
type: 'object',
properties: {
message: {
type: 'string',
description: 'The message to echo back',
},
},
required: ['message'],
},
},
{
name: 'uppercase',
description: 'Convert text to uppercase',
inputSchema: {
type: 'object',
properties: {
text: {
type: 'string',
description: 'The text to convert to uppercase',
},
},
required: ['text'],
},
},
{
name: 'calculate',
description: 'Perform basic mathematical calculations',
inputSchema: {
type: 'object',
properties: {
operation: {
type: 'string',
enum: ['add', 'subtract', 'multiply', 'divide'],
description: 'The mathematical operation to perform',
},
a: {
type: 'number',
description: 'First number',
},
b: {
type: 'number',
description: 'Second number',
},
},
required: ['operation', 'a', 'b'],
},
},
];
// Create the server
const server = new Server(
{
name: 'mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
// Handle list tools request
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools,
};
});
// Handle call tool request
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (!args) {
throw new Error('No arguments provided');
}
try {
switch (name) {
case 'echo':
const message = validateString(args.message, 'message');
return {
content: [
{
type: 'text',
text: message,
} as TextContent,
],
};
case 'uppercase':
const text = validateString(args.text, 'text');
return {
content: [
{
type: 'text',
text: text.toUpperCase(),
} as TextContent,
],
};
case 'calculate':
const operation = validateString(args.operation, 'operation');
const a = validateNumber(args.a, 'a');
const b = validateNumber(args.b, 'b');
let result: number;
switch (operation) {
case 'add':
result = a + b;
break;
case 'subtract':
result = a - b;
break;
case 'multiply':
result = a * b;
break;
case 'divide':
if (b === 0) {
throw new Error('Division by zero is not allowed');
}
result = a / b;
break;
default:
throw new Error(`Unknown operation: ${operation}`);
}
return {
content: [
{
type: 'text',
text: `Result: ${result}`,
} as TextContent,
],
};
default:
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
content: [
{
type: 'text',
text: `Error: ${errorMessage}`,
} as TextContent,
],
isError: true,
};
}
});
// Start the server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('MCP Server started successfully');
}
main().catch((error) => {
console.error('Server error:', error);
process.exit(1);
});