mcpengine/servers/clover/src/tools/orders-tools.ts
Jake Shore 7ee40342c8 Clover: Complete MCP server with 50+ tools and 18 React apps
- API client with Clover REST API v3 integration (OAuth2 + API key auth)
- 50+ comprehensive tools across 10 categories:
  * Orders: list, get, create, update, delete, add/remove line items, discounts, payments, fire order
  * Inventory: items, categories, modifiers, stock management
  * Customers: CRUD, search, addresses, payment cards
  * Employees: CRUD, roles, shifts, clock in/out
  * Payments: list, get, refunds
  * Merchants: settings, devices, tender types
  * Discounts: CRUD operations
  * Taxes: CRUD, tax rates
  * Reports: sales summary, revenue by item/category, employee performance
  * Cash: cash drawer tracking and events

- 18 React MCP apps with full UI:
  * Order management: dashboard, detail, grid
  * Inventory: dashboard, detail, category manager
  * Customer: detail, grid
  * Employee: dashboard, schedule
  * Payment history
  * Analytics: sales dashboard, revenue by item, revenue by category
  * Configuration: discount manager, tax manager, device manager
  * Cash drawer

- Complete TypeScript types for Clover API
- Pagination support with automatic result fetching
- Comprehensive error handling
- Full README with examples and setup guide
2026-02-12 17:42:59 -05:00

209 lines
6.4 KiB
TypeScript

import { CloverClient } from '../clients/clover.js';
import { CloverOrder, CloverLineItem, PaginatedResponse } from '../types/index.js';
export function createOrdersTools(client: CloverClient) {
return {
clover_list_orders: {
description: 'List orders from Clover POS',
inputSchema: {
type: 'object',
properties: {
filter: {
type: 'string',
description: 'Filter expression (e.g., "state=open", "createdTime>1234567890")',
},
expand: {
type: 'string',
description: 'Comma-separated list of fields to expand (lineItems, customers, payments)',
},
limit: {
type: 'number',
description: 'Maximum number of orders to return',
},
},
},
handler: async (args: any) => {
const orders = await client.fetchPaginated<CloverOrder>(
'/orders',
{ filter: args.filter, expand: args.expand },
args.limit
);
return { orders, count: orders.length };
},
},
clover_get_order: {
description: 'Get a specific order by ID',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order ID' },
expand: {
type: 'string',
description: 'Comma-separated list of fields to expand',
},
},
required: ['orderId'],
},
handler: async (args: any) => {
return await client.get<CloverOrder>(`/orders/${args.orderId}`, {
expand: args.expand,
});
},
},
clover_create_order: {
description: 'Create a new order',
inputSchema: {
type: 'object',
properties: {
state: {
type: 'string',
enum: ['open', 'locked'],
description: 'Order state (default: open)',
},
title: { type: 'string', description: 'Order title' },
note: { type: 'string', description: 'Order note' },
manualTransaction: {
type: 'boolean',
description: 'Manual transaction flag',
},
groupLineItems: { type: 'boolean', description: 'Group line items' },
},
},
handler: async (args: any) => {
return await client.post<CloverOrder>('/orders', {
state: args.state || 'open',
title: args.title,
note: args.note,
manualTransaction: args.manualTransaction,
groupLineItems: args.groupLineItems,
});
},
},
clover_update_order: {
description: 'Update an existing order',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order ID' },
title: { type: 'string', description: 'Order title' },
note: { type: 'string', description: 'Order note' },
state: { type: 'string', enum: ['open', 'locked'], description: 'Order state' },
},
required: ['orderId'],
},
handler: async (args: any) => {
const { orderId, ...updateData } = args;
return await client.post<CloverOrder>(`/orders/${orderId}`, updateData);
},
},
clover_delete_order: {
description: 'Delete an order',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order ID' },
},
required: ['orderId'],
},
handler: async (args: any) => {
await client.delete(`/orders/${args.orderId}`);
return { success: true, orderId: args.orderId };
},
},
clover_add_line_item: {
description: 'Add a line item to an order',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order ID' },
itemId: { type: 'string', description: 'Item ID from inventory' },
name: { type: 'string', description: 'Line item name (optional override)' },
price: { type: 'number', description: 'Price in cents (optional override)' },
unitQty: { type: 'number', description: 'Unit quantity (default: 1)' },
},
required: ['orderId', 'itemId'],
},
handler: async (args: any) => {
return await client.post<CloverLineItem>(
`/orders/${args.orderId}/line_items`,
{
item: { id: args.itemId },
name: args.name,
price: args.price,
unitQty: args.unitQty,
}
);
},
},
clover_remove_line_item: {
description: 'Remove a line item from an order',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order ID' },
lineItemId: { type: 'string', description: 'Line item ID' },
},
required: ['orderId', 'lineItemId'],
},
handler: async (args: any) => {
await client.delete(`/orders/${args.orderId}/line_items/${args.lineItemId}`);
return { success: true, lineItemId: args.lineItemId };
},
},
clover_add_order_discount: {
description: 'Add a discount to an order',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order ID' },
discountId: { type: 'string', description: 'Discount ID' },
},
required: ['orderId', 'discountId'],
},
handler: async (args: any) => {
return await client.post(
`/orders/${args.orderId}/discounts`,
{ discount: { id: args.discountId } }
);
},
},
clover_list_order_payments: {
description: 'List payments for an order',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order ID' },
},
required: ['orderId'],
},
handler: async (args: any) => {
return await client.get<PaginatedResponse<any>>(
`/orders/${args.orderId}/payments`
);
},
},
clover_fire_order: {
description: 'Fire/send an order to the kitchen (mark as ready for preparation)',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'Order ID' },
},
required: ['orderId'],
},
handler: async (args: any) => {
return await client.post(`/orders/${args.orderId}/fire`, {});
},
},
};
}