// @ts-check
/**
* Product-level operation handlers for Inflow Inventory MCP Server
*/
/** @typedef {import('../inflow-client').InflowClient} InflowClient */
export const productHandlers = {
/**
* List products (ingredients) with optional filters
* @param {InflowClient} client
* @param {Object} args
* @param {string} [args.name] - Filter by name
* @param {string} [args.description] - Filter by description
* @param {boolean} [args.isActive] - Filter by active status
* @param {string} [args.barcode] - Filter by barcode
* @param {string} [args.smart] - Full-text search
* @param {string} [args.include] - Related entities to include
* @param {number} [args.limit] - Max results (default: 50)
* @returns {Promise<Object>}
*/
async listProducts(client, args) {
const options = {
name: args.name,
description: args.description,
isActive: args.isActive,
barcode: args.barcode,
smart: args.smart,
include: args.include,
limit: args.limit || 50
};
return await client.listProducts(options);
},
/**
* Get a specific product by ID
* @param {InflowClient} client
* @param {Object} args
* @param {string} args.productId - The product ID
* @param {string} [args.include] - Related entities to include
* @returns {Promise<Object>}
*/
async getProduct(client, args) {
if (!args.productId) {
return {
success: false,
error: 'productId is required'
};
}
return await client.getProduct(args.productId, args.include);
},
/**
* Get product inventory summary
* @param {InflowClient} client
* @param {Object} args
* @param {string} args.productId - The product ID
* @returns {Promise<Object>}
*/
async getProductSummary(client, args) {
if (!args.productId) {
return {
success: false,
error: 'productId is required'
};
}
return await client.getProductSummary(args.productId);
},
/**
* Search products using smart search
* @param {InflowClient} client
* @param {Object} args
* @param {string} args.query - Search query
* @param {number} [args.limit] - Max results (default: 25)
* @param {string} [args.include] - Related entities to include
* @returns {Promise<Object>}
*/
async searchProducts(client, args) {
if (!args.query) {
return {
success: false,
error: 'query is required'
};
}
return await client.listProducts({
smart: args.query,
limit: args.limit || 25,
include: args.include
});
},
/**
* Create a new product (ingredient)
* @param {InflowClient} client
* @param {Object} args
* @param {string} args.productId - UUID for the new product (generate with crypto.randomUUID())
* @param {string} args.name - Product name
* @param {string} [args.sku] - SKU
* @param {string} [args.description] - Description
* @param {boolean} [args.isActive] - Active status (default: true)
* @param {Object} [args.additionalFields] - Any additional product fields
* @returns {Promise<Object>}
*/
async createProduct(client, args) {
if (!args.productId) {
return {
success: false,
error: 'productId is required (generate a UUID)'
};
}
if (!args.name) {
return {
success: false,
error: 'name is required'
};
}
const product = {
productId: args.productId,
name: args.name,
sku: args.sku,
description: args.description,
isActive: args.isActive !== undefined ? args.isActive : true,
...args.additionalFields
};
return await client.upsertProduct(product);
},
/**
* Update an existing product (ingredient)
* @param {InflowClient} client
* @param {Object} args
* @param {string} args.productId - The product ID to update
* @param {string} [args.name] - New name
* @param {string} [args.sku] - New SKU
* @param {string} [args.description] - New description
* @param {boolean} [args.isActive] - Active status
* @param {Object} [args.additionalFields] - Any additional fields to update
* @returns {Promise<Object>}
*/
async updateProduct(client, args) {
if (!args.productId) {
return {
success: false,
error: 'productId is required'
};
}
// Build update object with only provided fields
const updates = {
productId: args.productId
};
if (args.name !== undefined) updates.name = args.name;
if (args.sku !== undefined) updates.sku = args.sku;
if (args.description !== undefined) updates.description = args.description;
if (args.isActive !== undefined) updates.isActive = args.isActive;
// Merge any additional fields
if (args.additionalFields) {
Object.assign(updates, args.additionalFields);
}
return await client.upsertProduct(updates);
}
};