ikea-mcp 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/schemas/index.js
CHANGED
|
@@ -69,3 +69,10 @@ export const CheckMultiItemStockInput = z.object({
|
|
|
69
69
|
storeId: z.string().min(1),
|
|
70
70
|
itemNos: z.array(ItemNo).min(1).max(20),
|
|
71
71
|
});
|
|
72
|
+
export const CheckCartAvailabilityInput = z.object({
|
|
73
|
+
storeId: z.string().min(1),
|
|
74
|
+
items: z.array(z.object({
|
|
75
|
+
itemNo: ItemNo,
|
|
76
|
+
quantity: z.number().int().min(1).max(99).default(1),
|
|
77
|
+
})).min(1).max(20),
|
|
78
|
+
});
|
package/dist/server.js
CHANGED
|
@@ -7,7 +7,8 @@ import { findBestStoreForItemTool } from "./tools/find_best_store_for_item.js";
|
|
|
7
7
|
import { getProductDetailsTool } from "./tools/get_product_details.js";
|
|
8
8
|
import { checkMultiItemStockTool } from "./tools/check_multi_item_stock.js";
|
|
9
9
|
import { listStoresTool } from "./tools/list_stores.js";
|
|
10
|
-
|
|
10
|
+
import { checkCartAvailabilityTool } from "./tools/check_cart_availability.js";
|
|
11
|
+
const tools = [listStoresTool, searchProductsTool, checkStoreStockTool, compareStoreStockTool, findBestStoreForItemTool, getProductDetailsTool, checkMultiItemStockTool, checkCartAvailabilityTool];
|
|
11
12
|
export function createServer() {
|
|
12
13
|
const server = new Server({ name: "ikea-mcp", version: "1.0.0" }, { capabilities: { tools: {} } });
|
|
13
14
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { CheckCartAvailabilityInput } from "../schemas/index.js";
|
|
2
|
+
import { getMultiItemStock } from "../services/ikea.js";
|
|
3
|
+
import { storeLabel } from "../data/stores.js";
|
|
4
|
+
export const checkCartAvailabilityTool = {
|
|
5
|
+
name: "check_cart_availability",
|
|
6
|
+
description: "Check whether all items in a shopping list are available in sufficient quantity at a single IKEA store.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
storeId: { type: "string" },
|
|
11
|
+
items: {
|
|
12
|
+
type: "array",
|
|
13
|
+
items: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
itemNo: { type: "string" },
|
|
17
|
+
quantity: { type: "number", default: 1 },
|
|
18
|
+
},
|
|
19
|
+
required: ["itemNo"],
|
|
20
|
+
},
|
|
21
|
+
minItems: 1,
|
|
22
|
+
maxItems: 20,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
required: ["storeId", "items"],
|
|
26
|
+
},
|
|
27
|
+
async handler(rawInput) {
|
|
28
|
+
const input = CheckCartAvailabilityInput.parse(rawInput);
|
|
29
|
+
const itemNos = input.items.map((i) => i.itemNo);
|
|
30
|
+
const result = await getMultiItemStock(itemNos, input.storeId);
|
|
31
|
+
const byItemNo = new Map();
|
|
32
|
+
for (const a of result.availabilities ?? []) {
|
|
33
|
+
byItemNo.set(a.itemKey.itemNo, a);
|
|
34
|
+
}
|
|
35
|
+
const errorByItemNo = new Map();
|
|
36
|
+
for (const e of result.errors ?? []) {
|
|
37
|
+
if (e.details?.itemNo) {
|
|
38
|
+
errorByItemNo.set(e.details.itemNo, {
|
|
39
|
+
...e,
|
|
40
|
+
meaning: e.code === 404 ? "item not stocked at this store" : "unknown",
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const storeError = result.errors?.find((e) => e.code === 405);
|
|
45
|
+
const items = input.items.map((item) => {
|
|
46
|
+
if (storeError) {
|
|
47
|
+
return {
|
|
48
|
+
itemNo: item.itemNo,
|
|
49
|
+
quantity: item.quantity,
|
|
50
|
+
inStock: null,
|
|
51
|
+
sufficient: false,
|
|
52
|
+
eligibleForStockNotification: null,
|
|
53
|
+
errors: [{ code: storeError.code, message: storeError.message, meaning: "store ID does not exist" }],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const a = byItemNo.get(item.itemNo);
|
|
57
|
+
if (a) {
|
|
58
|
+
const inStock = a.buyingOption.cashCarry.availability.quantity;
|
|
59
|
+
return {
|
|
60
|
+
itemNo: item.itemNo,
|
|
61
|
+
quantity: item.quantity,
|
|
62
|
+
inStock,
|
|
63
|
+
sufficient: inStock >= item.quantity,
|
|
64
|
+
eligibleForStockNotification: a.buyingOption.cashCarry.eligibleForStockNotification ?? null,
|
|
65
|
+
errors: [],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const err = errorByItemNo.get(item.itemNo);
|
|
69
|
+
return {
|
|
70
|
+
itemNo: item.itemNo,
|
|
71
|
+
quantity: item.quantity,
|
|
72
|
+
inStock: null,
|
|
73
|
+
sufficient: false,
|
|
74
|
+
eligibleForStockNotification: null,
|
|
75
|
+
errors: err
|
|
76
|
+
? [err]
|
|
77
|
+
: [{ code: 404, message: "Not found", meaning: "item not stocked at this store" }],
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
const allSufficient = items.every((i) => i.sufficient);
|
|
81
|
+
return {
|
|
82
|
+
content: [{
|
|
83
|
+
type: "text",
|
|
84
|
+
text: JSON.stringify({
|
|
85
|
+
storeId: input.storeId,
|
|
86
|
+
storeLabel: storeLabel(input.storeId) ?? input.storeId,
|
|
87
|
+
allSufficient,
|
|
88
|
+
items,
|
|
89
|
+
}, null, 2),
|
|
90
|
+
}],
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
};
|
package/package.json
CHANGED