@bowlly/mcp-server 0.1.9 → 0.1.10
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/README.md +6 -1
- package/dist/cli/configure.d.ts +1 -1
- package/dist/cli/configure.d.ts.map +1 -1
- package/dist/cli/configure.js +15 -2
- package/dist/cli/configure.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +2 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/index.js +0 -0
- package/package.json +1 -1
- package/scripts/smoke-prod.ts +3 -3
- package/dist/__tests__/curation-tool.test.d.ts +0 -2
- package/dist/__tests__/curation-tool.test.d.ts.map +0 -1
- package/dist/__tests__/curation-tool.test.js +0 -329
- package/dist/__tests__/curation-tool.test.js.map +0 -1
- package/dist/__tests__/nutrition-tool.test.d.ts +0 -2
- package/dist/__tests__/nutrition-tool.test.d.ts.map +0 -1
- package/dist/__tests__/nutrition-tool.test.js +0 -286
- package/dist/__tests__/nutrition-tool.test.js.map +0 -1
- package/dist/__tests__/rate-limit.test.d.ts +0 -2
- package/dist/__tests__/rate-limit.test.d.ts.map +0 -1
- package/dist/__tests__/rate-limit.test.js +0 -154
- package/dist/__tests__/rate-limit.test.js.map +0 -1
- package/dist/__tests__/safeguard.test.d.ts +0 -2
- package/dist/__tests__/safeguard.test.d.ts.map +0 -1
- package/dist/__tests__/safeguard.test.js +0 -146
- package/dist/__tests__/safeguard.test.js.map +0 -1
- package/dist/__tests__/search-tool.test.d.ts +0 -2
- package/dist/__tests__/search-tool.test.d.ts.map +0 -1
- package/dist/__tests__/search-tool.test.js +0 -260
- package/dist/__tests__/search-tool.test.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"search-tool.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/search-tool.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { AgentApiClient } from "../client.js";
|
|
3
|
-
import { TokenBucketManager } from "../rate-limit.js";
|
|
4
|
-
import { registerSearchTool } from "../tools/search-products.js";
|
|
5
|
-
describe("search_products tool", () => {
|
|
6
|
-
let client;
|
|
7
|
-
let bucketManager;
|
|
8
|
-
const getClientId = () => "test-client";
|
|
9
|
-
let capturedHandler = null;
|
|
10
|
-
// Mock server that captures the registered tool handler
|
|
11
|
-
// Supports both 3-param (name, schema, handler) and 4-param (name, description, schema, handler) signatures
|
|
12
|
-
const createMockServer = () => {
|
|
13
|
-
return {
|
|
14
|
-
tool: (name, arg2, arg3, arg4) => {
|
|
15
|
-
if (name === "search_products") {
|
|
16
|
-
// 4-param signature: (name, description, schema, handler)
|
|
17
|
-
// 3-param signature: (name, schema, handler)
|
|
18
|
-
const handler = arg4 !== undefined ? arg4 : arg3;
|
|
19
|
-
capturedHandler = handler;
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
// Helper to create mock products with ingredientsPreview
|
|
25
|
-
const createMockProducts = () => [
|
|
26
|
-
{
|
|
27
|
-
id: "prod-1",
|
|
28
|
-
name: "Chicken Delight",
|
|
29
|
-
brand: "Premium Pet",
|
|
30
|
-
form: "dry",
|
|
31
|
-
detailUrl: "https://fitpick.com/products/prod-1",
|
|
32
|
-
imageUrl: "https://fitpick.com/images/prod-1.jpg",
|
|
33
|
-
ingredientsPreview: ["chicken meal", "rice", "pea protein"],
|
|
34
|
-
ingredientsFull: ["chicken meal", "rice", "pea protein", "chicken fat", "taurine"],
|
|
35
|
-
conditionTags: ["sensitive"],
|
|
36
|
-
lifeStageTags: ["adult"],
|
|
37
|
-
hasOffer: true,
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
id: "prod-2",
|
|
41
|
-
name: "Salmon Feast",
|
|
42
|
-
brand: "Ocean Catch",
|
|
43
|
-
form: "wet",
|
|
44
|
-
detailUrl: "https://fitpick.com/products/prod-2",
|
|
45
|
-
imageUrl: "https://fitpick.com/images/prod-2.jpg",
|
|
46
|
-
ingredientsPreview: ["salmon", "chicken", "fish broth"],
|
|
47
|
-
ingredientsFull: ["salmon", "chicken", "fish broth", "vitamin E", "taurine"],
|
|
48
|
-
conditionTags: ["urinary"],
|
|
49
|
-
lifeStageTags: ["adult", "senior"],
|
|
50
|
-
hasOffer: true,
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
id: "prod-3",
|
|
54
|
-
name: "Grain Free Formula",
|
|
55
|
-
brand: "Healthy Cat",
|
|
56
|
-
form: "dry",
|
|
57
|
-
detailUrl: "https://fitpick.com/products/prod-3",
|
|
58
|
-
imageUrl: "https://fitpick.com/images/prod-3.jpg",
|
|
59
|
-
ingredientsPreview: ["turkey", "chicken meal", "potato"],
|
|
60
|
-
ingredientsFull: ["turkey", "chicken meal", "potato", "pea protein", "flaxseed"],
|
|
61
|
-
conditionTags: ["diet"],
|
|
62
|
-
lifeStageTags: ["kitten", "adult"],
|
|
63
|
-
hasOffer: false,
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
id: "prod-4",
|
|
67
|
-
name: "Grain Mix",
|
|
68
|
-
brand: "Budget Pet",
|
|
69
|
-
form: "dry",
|
|
70
|
-
detailUrl: "https://fitpick.com/products/prod-4",
|
|
71
|
-
imageUrl: "https://fitpick.com/images/prod-4.jpg",
|
|
72
|
-
ingredientsPreview: ["corn", "wheat", "chicken by-product"],
|
|
73
|
-
ingredientsFull: ["corn", "wheat", "chicken by-product", "soybean meal", "vitamins"],
|
|
74
|
-
conditionTags: ["indoor"],
|
|
75
|
-
lifeStageTags: ["adult"],
|
|
76
|
-
hasOffer: true,
|
|
77
|
-
},
|
|
78
|
-
];
|
|
79
|
-
beforeEach(() => {
|
|
80
|
-
client = new AgentApiClient();
|
|
81
|
-
bucketManager = new TokenBucketManager(100, 60000);
|
|
82
|
-
capturedHandler = null;
|
|
83
|
-
vi.clearAllMocks();
|
|
84
|
-
});
|
|
85
|
-
afterEach(() => {
|
|
86
|
-
vi.restoreAllMocks();
|
|
87
|
-
});
|
|
88
|
-
it("should filter by ingredientsPreview with partial matching", async () => {
|
|
89
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
90
|
-
products: createMockProducts(),
|
|
91
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
92
|
-
});
|
|
93
|
-
const mockServer = createMockServer();
|
|
94
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
95
|
-
expect(capturedHandler).not.toBeNull();
|
|
96
|
-
const result = await capturedHandler({ includeIngredients: "chicken" });
|
|
97
|
-
const content = JSON.parse(result.content[0].text);
|
|
98
|
-
// Should match prod-1 ("chicken meal"), prod-2 ("chicken"), prod-3 ("chicken meal")
|
|
99
|
-
// Should NOT match prod-4 ("chicken by-product" contains "chicken")
|
|
100
|
-
expect(content.data.items).toHaveLength(4); // All have "chicken" in ingredientsPreview
|
|
101
|
-
// Verify partial matching works - "chicken" matches "chicken meal"
|
|
102
|
-
const productNames = content.data.items.map((item) => item.name);
|
|
103
|
-
expect(productNames).toContain("Chicken Delight");
|
|
104
|
-
expect(productNames).toContain("Salmon Feast");
|
|
105
|
-
expect(productNames).toContain("Grain Free Formula");
|
|
106
|
-
expect(productNames).toContain("Grain Mix");
|
|
107
|
-
});
|
|
108
|
-
it("should use exact matching for quoted ingredients", async () => {
|
|
109
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
110
|
-
products: createMockProducts(),
|
|
111
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
112
|
-
});
|
|
113
|
-
const mockServer = createMockServer();
|
|
114
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
115
|
-
expect(capturedHandler).not.toBeNull();
|
|
116
|
-
// Exact match for "chicken meal" - should NOT match "chicken" alone
|
|
117
|
-
const result = await capturedHandler({ includeIngredients: '"chicken meal"' });
|
|
118
|
-
const content = JSON.parse(result.content[0].text);
|
|
119
|
-
// Should match prod-1 and prod-3 (have "chicken meal")
|
|
120
|
-
// Should NOT match prod-2 (only has "chicken", not "chicken meal")
|
|
121
|
-
expect(content.data.items).toHaveLength(2);
|
|
122
|
-
const productNames = content.data.items.map((item) => item.name);
|
|
123
|
-
expect(productNames).toContain("Chicken Delight");
|
|
124
|
-
expect(productNames).toContain("Grain Free Formula");
|
|
125
|
-
expect(productNames).not.toContain("Salmon Feast");
|
|
126
|
-
});
|
|
127
|
-
it("should exclude products with excluded ingredients in ingredientsPreview", async () => {
|
|
128
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
129
|
-
products: createMockProducts(),
|
|
130
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
131
|
-
});
|
|
132
|
-
const mockServer = createMockServer();
|
|
133
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
134
|
-
expect(capturedHandler).not.toBeNull();
|
|
135
|
-
const result = await capturedHandler({ excludeIngredients: "corn" });
|
|
136
|
-
const content = JSON.parse(result.content[0].text);
|
|
137
|
-
// Should exclude prod-4 (has "corn")
|
|
138
|
-
expect(content.data.items).toHaveLength(3);
|
|
139
|
-
const productNames = content.data.items.map((item) => item.name);
|
|
140
|
-
expect(productNames).toContain("Chicken Delight");
|
|
141
|
-
expect(productNames).toContain("Salmon Feast");
|
|
142
|
-
expect(productNames).toContain("Grain Free Formula");
|
|
143
|
-
expect(productNames).not.toContain("Grain Mix");
|
|
144
|
-
});
|
|
145
|
-
it("should require ALL include terms to match (AND logic)", async () => {
|
|
146
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
147
|
-
products: createMockProducts(),
|
|
148
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
149
|
-
});
|
|
150
|
-
const mockServer = createMockServer();
|
|
151
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
152
|
-
expect(capturedHandler).not.toBeNull();
|
|
153
|
-
// Must have BOTH chicken AND rice
|
|
154
|
-
const result = await capturedHandler({ includeIngredients: "chicken,rice" });
|
|
155
|
-
const content = JSON.parse(result.content[0].text);
|
|
156
|
-
// Only prod-1 has both "chicken" (in "chicken meal") and "rice"
|
|
157
|
-
expect(content.data.items).toHaveLength(1);
|
|
158
|
-
expect(content.data.items[0].name).toBe("Chicken Delight");
|
|
159
|
-
});
|
|
160
|
-
it("should provide suggestions when no exact matches found", async () => {
|
|
161
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
162
|
-
products: createMockProducts(),
|
|
163
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
164
|
-
});
|
|
165
|
-
const mockServer = createMockServer();
|
|
166
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
167
|
-
expect(capturedHandler).not.toBeNull();
|
|
168
|
-
// Exact match for "chick" - no product has "chick" as a whole word
|
|
169
|
-
// But "chicken" contains "chick" so relaxed matching would find matches
|
|
170
|
-
const result = await capturedHandler({ includeIngredients: '"chick"' });
|
|
171
|
-
const content = JSON.parse(result.content[0].text);
|
|
172
|
-
// Should return empty items (no exact match for "chick" as whole word)
|
|
173
|
-
expect(content.data.items).toHaveLength(0);
|
|
174
|
-
// Should provide suggestions (relaxed matching finds "chicken")
|
|
175
|
-
expect(content.data.suggestions).toBeDefined();
|
|
176
|
-
expect(content.data.suggestions.length).toBeGreaterThan(0);
|
|
177
|
-
expect(content.data.suggestions[0]).toContain("No exact matches found");
|
|
178
|
-
});
|
|
179
|
-
it("should handle case-insensitive matching", async () => {
|
|
180
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
181
|
-
products: createMockProducts(),
|
|
182
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
183
|
-
});
|
|
184
|
-
const mockServer = createMockServer();
|
|
185
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
186
|
-
expect(capturedHandler).not.toBeNull();
|
|
187
|
-
// Uppercase search term
|
|
188
|
-
const result = await capturedHandler({ includeIngredients: "CHICKEN" });
|
|
189
|
-
const content = JSON.parse(result.content[0].text);
|
|
190
|
-
// Should match all products with "chicken" (case insensitive)
|
|
191
|
-
expect(content.data.items.length).toBeGreaterThan(0);
|
|
192
|
-
const productNames = content.data.items.map((item) => item.name);
|
|
193
|
-
expect(productNames).toContain("Chicken Delight");
|
|
194
|
-
});
|
|
195
|
-
it("should include filterNote in response when ingredient filtering is used", async () => {
|
|
196
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
197
|
-
products: createMockProducts(),
|
|
198
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
199
|
-
});
|
|
200
|
-
const mockServer = createMockServer();
|
|
201
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
202
|
-
expect(capturedHandler).not.toBeNull();
|
|
203
|
-
const result = await capturedHandler({ includeIngredients: "chicken" });
|
|
204
|
-
const content = JSON.parse(result.content[0].text);
|
|
205
|
-
expect(content.data.filterNote).toBeDefined();
|
|
206
|
-
expect(content.data.filterNote).toContain("partial matching");
|
|
207
|
-
expect(content.data.filterNote).toContain("quotes");
|
|
208
|
-
});
|
|
209
|
-
it("should handle combined include and exclude filters", async () => {
|
|
210
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
211
|
-
products: createMockProducts(),
|
|
212
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
213
|
-
});
|
|
214
|
-
const mockServer = createMockServer();
|
|
215
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
216
|
-
expect(capturedHandler).not.toBeNull();
|
|
217
|
-
// Include chicken, exclude corn
|
|
218
|
-
const result = await capturedHandler({
|
|
219
|
-
includeIngredients: "chicken",
|
|
220
|
-
excludeIngredients: "corn",
|
|
221
|
-
});
|
|
222
|
-
const content = JSON.parse(result.content[0].text);
|
|
223
|
-
// Should have chicken but not corn
|
|
224
|
-
const productNames = content.data.items.map((item) => item.name);
|
|
225
|
-
expect(productNames).toContain("Chicken Delight");
|
|
226
|
-
expect(productNames).toContain("Salmon Feast");
|
|
227
|
-
expect(productNames).toContain("Grain Free Formula");
|
|
228
|
-
expect(productNames).not.toContain("Grain Mix"); // Has corn
|
|
229
|
-
});
|
|
230
|
-
it("should include rate limit info in response", async () => {
|
|
231
|
-
vi.spyOn(client, "getProducts").mockResolvedValue({
|
|
232
|
-
products: createMockProducts(),
|
|
233
|
-
pagination: { total: 4, limit: 200, offset: 0 },
|
|
234
|
-
});
|
|
235
|
-
const mockServer = createMockServer();
|
|
236
|
-
registerSearchTool(mockServer, client, bucketManager, getClientId);
|
|
237
|
-
expect(capturedHandler).not.toBeNull();
|
|
238
|
-
const result = await capturedHandler({});
|
|
239
|
-
const content = JSON.parse(result.content[0].text);
|
|
240
|
-
expect(content.rateLimit).toBeDefined();
|
|
241
|
-
expect(content.rateLimit.limit).toBe(100);
|
|
242
|
-
expect(typeof content.rateLimit.remaining).toBe("number");
|
|
243
|
-
expect(typeof content.rateLimit.resetEpochMs).toBe("number");
|
|
244
|
-
});
|
|
245
|
-
it("should handle rate limit exceeded", async () => {
|
|
246
|
-
// Create a bucket manager with 0 tokens to simulate rate limit
|
|
247
|
-
const limitedBucketManager = new TokenBucketManager(0, 60000);
|
|
248
|
-
const mockServer = createMockServer();
|
|
249
|
-
registerSearchTool(mockServer, client, limitedBucketManager, getClientId);
|
|
250
|
-
expect(capturedHandler).not.toBeNull();
|
|
251
|
-
const result = await capturedHandler({});
|
|
252
|
-
const content = JSON.parse(result.content[0].text);
|
|
253
|
-
expect(content.error).toBeDefined();
|
|
254
|
-
expect(content.error.type).toBe('RATE_LIMITED');
|
|
255
|
-
expect(content.error.message).toContain("Rate limit exceeded");
|
|
256
|
-
expect(content.retryAfterSeconds).toBeDefined();
|
|
257
|
-
expect(typeof content.retryAfterSeconds).toBe("number");
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
//# sourceMappingURL=search-tool.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"search-tool.test.js","sourceRoot":"","sources":["../../src/__tests__/search-tool.test.ts"],"names":[],"mappings":"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"}
|