130 lines
5.1 KiB
JavaScript

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
import { ToastAPIClient } from './api-client.js';
import { registerOrdersTools } from './tools/orders-tools.js';
import { registerMenusTools } from './tools/menus-tools.js';
import { registerEmployeesTools } from './tools/employees-tools.js';
import { registerLaborTools } from './tools/labor-tools.js';
import { registerRestaurantTools } from './tools/restaurant-tools.js';
import { registerPaymentsTools } from './tools/payments-tools.js';
import { registerInventoryTools } from './tools/inventory-tools.js';
import { registerCustomersTools } from './tools/customers-tools.js';
import { registerReportingTools } from './tools/reporting-tools.js';
import { registerCashTools } from './tools/cash-tools.js';
import { apps } from './apps/index.js';
export class ToastMCPServer {
server;
client;
tools;
constructor() {
// Get configuration from environment
const apiToken = process.env.TOAST_API_TOKEN;
const restaurantGuid = process.env.TOAST_RESTAURANT_GUID;
const baseUrl = process.env.TOAST_BASE_URL;
if (!apiToken || !restaurantGuid) {
throw new Error('TOAST_API_TOKEN and TOAST_RESTAURANT_GUID environment variables are required');
}
// Initialize Toast API client
this.client = new ToastAPIClient({
apiToken,
restaurantGuid,
baseUrl,
});
// Initialize MCP server
this.server = new Server({
name: 'toast-mcp-server',
version: '1.0.0',
}, {
capabilities: {
tools: {},
resources: {},
},
});
// Register all tools
this.tools = [
...registerOrdersTools(this.client),
...registerMenusTools(this.client),
...registerEmployeesTools(this.client),
...registerLaborTools(this.client),
...registerRestaurantTools(this.client),
...registerPaymentsTools(this.client),
...registerInventoryTools(this.client),
...registerCustomersTools(this.client),
...registerReportingTools(this.client),
...registerCashTools(this.client),
];
this.setupHandlers();
}
setupHandlers() {
// List available tools
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: this.tools.map((tool) => ({
name: tool.name,
description: tool.description,
inputSchema: tool.inputSchema,
})),
}));
// Execute tool calls
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const tool = this.tools.find((t) => t.name === request.params.name);
if (!tool) {
throw new Error(`Tool not found: ${request.params.name}`);
}
try {
return await tool.execute(request.params.arguments);
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error executing ${request.params.name}: ${error.message}`,
},
],
isError: true,
};
}
});
// List resources (MCP apps)
this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: apps.map((app) => ({
uri: `toast://apps/${app.name}`,
name: app.name,
description: app.description,
mimeType: 'application/json',
})),
}));
// Read resource (get app definition)
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const appName = request.params.uri.replace('toast://apps/', '');
const app = apps.find((a) => a.name === appName);
if (!app) {
throw new Error(`App not found: ${appName}`);
}
return {
contents: [
{
uri: request.params.uri,
mimeType: 'application/json',
text: JSON.stringify(app, null, 2),
},
],
};
});
// Error handling
this.server.onerror = (error) => {
console.error('[MCP Error]', error);
};
process.on('SIGINT', async () => {
await this.server.close();
process.exit(0);
});
}
async start() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Toast MCP Server running on stdio');
}
}
//# sourceMappingURL=server.js.map