food402 1.0.2 → 1.0.4-beta.1
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 +27 -0
- package/dist/postinstall.d.ts +2 -0
- package/dist/postinstall.js +29 -0
- package/dist/shared/api.d.ts +23 -0
- package/dist/shared/api.js +945 -0
- package/dist/shared/types.d.ts +396 -0
- package/dist/shared/types.js +2 -0
- package/dist/src/api.d.ts +23 -0
- package/dist/src/api.js +88 -0
- package/dist/src/auth.d.ts +16 -0
- package/dist/src/auth.js +117 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +455 -0
- package/dist/src/postinstall.d.ts +2 -0
- package/dist/src/postinstall.js +29 -0
- package/package.json +2 -1
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// src/index.ts - TGO Yemek MCP Server
|
|
3
|
+
import "dotenv/config";
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { getAddresses, getRestaurants, getRestaurantMenu, getProductDetails, getProductRecommendations, setShippingAddress, addToBasket, getBasket, removeFromBasket, clearBasket, searchRestaurants, getCities, getDistricts, getNeighborhoods, addAddress, getSavedCards, getCheckoutReady, placeOrder, getOrders, getOrderDetail, updateCustomerNote, } from "./api.js";
|
|
8
|
+
const server = new McpServer({
|
|
9
|
+
name: "tgo-yemek",
|
|
10
|
+
version: "1.0.0",
|
|
11
|
+
});
|
|
12
|
+
// Prompt: order_food - Main entry point for food ordering
|
|
13
|
+
server.prompt("order_food", "Start a food ordering session. Always begin by asking user to select a delivery address.", async () => {
|
|
14
|
+
// Fetch addresses to include in the prompt
|
|
15
|
+
try {
|
|
16
|
+
const addressesResult = await getAddresses();
|
|
17
|
+
const addressList = addressesResult.addresses
|
|
18
|
+
.map((a, i) => `${i + 1}. ${a.addressName} - ${a.addressLine}, ${a.neighborhoodName}, ${a.districtName} (ID: ${a.id})`)
|
|
19
|
+
.join("\n");
|
|
20
|
+
return {
|
|
21
|
+
messages: [
|
|
22
|
+
{
|
|
23
|
+
role: "user",
|
|
24
|
+
content: {
|
|
25
|
+
type: "text",
|
|
26
|
+
text: `I want to order food. Here are my saved addresses:\n\n${addressList}\n\nWhich address should I deliver to?`
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return {
|
|
34
|
+
messages: [
|
|
35
|
+
{
|
|
36
|
+
role: "user",
|
|
37
|
+
content: {
|
|
38
|
+
type: "text",
|
|
39
|
+
text: "I want to order food. Please fetch my addresses first using get_addresses and ask me which one to use for delivery."
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
// Helper to format successful responses
|
|
47
|
+
function formatResponse(data) {
|
|
48
|
+
return {
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: "text",
|
|
52
|
+
text: JSON.stringify(data, null, 2),
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Helper to format error responses
|
|
58
|
+
function formatError(error) {
|
|
59
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60
|
+
return {
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: "text",
|
|
64
|
+
text: `Error: ${message}`,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
isError: true,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Tool: get_addresses
|
|
71
|
+
server.tool("get_addresses", "Get user's saved delivery addresses. User must select an address with select_address before browsing restaurants.", {}, async () => {
|
|
72
|
+
try {
|
|
73
|
+
const result = await getAddresses();
|
|
74
|
+
return formatResponse(result);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return formatError(error);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// Tool: select_address
|
|
81
|
+
server.tool("select_address", "Select a delivery address. MUST be called before get_restaurants or add_to_basket. Sets the shipping address for the cart.", {
|
|
82
|
+
addressId: z.number().describe("Address ID from get_addresses"),
|
|
83
|
+
}, async (args) => {
|
|
84
|
+
try {
|
|
85
|
+
// Set shipping address for cart
|
|
86
|
+
await setShippingAddress({
|
|
87
|
+
shippingAddressId: args.addressId,
|
|
88
|
+
invoiceAddressId: args.addressId,
|
|
89
|
+
});
|
|
90
|
+
// Get address details to return to user
|
|
91
|
+
const addressesResult = await getAddresses();
|
|
92
|
+
const selectedAddress = addressesResult.addresses.find(a => a.id === args.addressId);
|
|
93
|
+
if (!selectedAddress) {
|
|
94
|
+
return formatResponse({
|
|
95
|
+
success: true,
|
|
96
|
+
message: "Shipping address set successfully",
|
|
97
|
+
addressId: args.addressId
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return formatResponse({
|
|
101
|
+
success: true,
|
|
102
|
+
message: "Delivery address selected",
|
|
103
|
+
address: {
|
|
104
|
+
id: selectedAddress.id,
|
|
105
|
+
name: selectedAddress.addressName,
|
|
106
|
+
addressLine: selectedAddress.addressLine,
|
|
107
|
+
neighborhood: selectedAddress.neighborhoodName,
|
|
108
|
+
district: selectedAddress.districtName,
|
|
109
|
+
city: selectedAddress.cityName,
|
|
110
|
+
latitude: selectedAddress.latitude,
|
|
111
|
+
longitude: selectedAddress.longitude
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
return formatError(error);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
// Tool: get_restaurants
|
|
120
|
+
server.tool("get_restaurants", "Search restaurants near a location. Requires select_address to be called first.", {
|
|
121
|
+
latitude: z.string().describe("Latitude coordinate from selected address"),
|
|
122
|
+
longitude: z.string().describe("Longitude coordinate from selected address"),
|
|
123
|
+
page: z.number().optional().describe("Page number for pagination (default: 1)"),
|
|
124
|
+
}, async (args) => {
|
|
125
|
+
try {
|
|
126
|
+
const result = await getRestaurants(args.latitude, args.longitude, args.page ?? 1);
|
|
127
|
+
return formatResponse(result);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return formatError(error);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
// Tool: get_restaurant_menu
|
|
134
|
+
server.tool("get_restaurant_menu", "Get a restaurant's full menu with categories and items", {
|
|
135
|
+
restaurantId: z.number().describe("Restaurant ID"),
|
|
136
|
+
latitude: z.string().describe("Latitude coordinate"),
|
|
137
|
+
longitude: z.string().describe("Longitude coordinate"),
|
|
138
|
+
}, async (args) => {
|
|
139
|
+
try {
|
|
140
|
+
const result = await getRestaurantMenu(args.restaurantId, args.latitude, args.longitude);
|
|
141
|
+
return formatResponse(result);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
return formatError(error);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
// Tool: get_product_details
|
|
148
|
+
server.tool("get_product_details", "Get product customization options (ingredients, modifiers)", {
|
|
149
|
+
restaurantId: z.number().describe("Restaurant ID"),
|
|
150
|
+
productId: z.number().describe("Product ID"),
|
|
151
|
+
latitude: z.string().describe("Latitude coordinate"),
|
|
152
|
+
longitude: z.string().describe("Longitude coordinate"),
|
|
153
|
+
}, async (args) => {
|
|
154
|
+
try {
|
|
155
|
+
const result = await getProductDetails(args.restaurantId, args.productId, args.latitude, args.longitude);
|
|
156
|
+
return formatResponse(result);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
return formatError(error);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
// Tool: get_product_recommendations
|
|
163
|
+
server.tool("get_product_recommendations", "Get 'goes well with' suggestions for products", {
|
|
164
|
+
restaurantId: z.number().describe("Restaurant ID"),
|
|
165
|
+
productIds: z.array(z.number()).describe("Array of product IDs to get recommendations for"),
|
|
166
|
+
}, async (args) => {
|
|
167
|
+
try {
|
|
168
|
+
const result = await getProductRecommendations(args.restaurantId, args.productIds);
|
|
169
|
+
return formatResponse(result);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
return formatError(error);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
// Simplified schemas for add_to_basket (avoiding recursive $ref which breaks some MCP clients)
|
|
176
|
+
const ModifierProductSchema = z.object({
|
|
177
|
+
productId: z.number().describe("Selected option's product ID"),
|
|
178
|
+
modifierGroupId: z.number().describe("The modifier group this belongs to"),
|
|
179
|
+
});
|
|
180
|
+
const BasketItemSchema = z.object({
|
|
181
|
+
productId: z.number().describe("Product ID to add"),
|
|
182
|
+
quantity: z.number().describe("Quantity to add"),
|
|
183
|
+
modifierProducts: z.array(ModifierProductSchema).optional().describe("Selected modifiers (optional)"),
|
|
184
|
+
excludeIngredientIds: z.array(z.number()).optional().describe("IDs of ingredients to exclude (optional)"),
|
|
185
|
+
});
|
|
186
|
+
// Tool: add_to_basket
|
|
187
|
+
server.tool("add_to_basket", "Add items to the shopping cart. Requires select_address to be called first.", {
|
|
188
|
+
storeId: z.number().describe("Restaurant ID"),
|
|
189
|
+
items: z.array(BasketItemSchema).describe("Items to add to basket"),
|
|
190
|
+
latitude: z.number().describe("Latitude coordinate (number)"),
|
|
191
|
+
longitude: z.number().describe("Longitude coordinate (number)"),
|
|
192
|
+
}, async (args) => {
|
|
193
|
+
try {
|
|
194
|
+
// Transform simplified schema to full API format
|
|
195
|
+
const items = args.items.map((item) => ({
|
|
196
|
+
productId: item.productId,
|
|
197
|
+
quantity: item.quantity,
|
|
198
|
+
modifierProducts: (item.modifierProducts || []).map((mod) => ({
|
|
199
|
+
productId: mod.productId,
|
|
200
|
+
modifierGroupId: mod.modifierGroupId,
|
|
201
|
+
modifierProducts: [],
|
|
202
|
+
ingredientOptions: { excludes: [], includes: [] },
|
|
203
|
+
})),
|
|
204
|
+
ingredientOptions: {
|
|
205
|
+
excludes: (item.excludeIngredientIds || []).map((id) => ({ id })),
|
|
206
|
+
includes: [],
|
|
207
|
+
},
|
|
208
|
+
}));
|
|
209
|
+
const result = await addToBasket({
|
|
210
|
+
storeId: args.storeId,
|
|
211
|
+
items,
|
|
212
|
+
latitude: args.latitude,
|
|
213
|
+
longitude: args.longitude,
|
|
214
|
+
isFlashSale: false,
|
|
215
|
+
storePickup: false,
|
|
216
|
+
});
|
|
217
|
+
return formatResponse(result);
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
return formatError(error);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
// Tool: get_basket
|
|
224
|
+
server.tool("get_basket", "Get current cart contents", {}, async () => {
|
|
225
|
+
try {
|
|
226
|
+
const result = await getBasket();
|
|
227
|
+
return formatResponse(result);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
return formatError(error);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
// Tool: remove_from_basket
|
|
234
|
+
server.tool("remove_from_basket", "Remove an item from the cart", {
|
|
235
|
+
itemId: z.string().describe("Item UUID from the cart (from get_basket response)"),
|
|
236
|
+
}, async (args) => {
|
|
237
|
+
try {
|
|
238
|
+
const result = await removeFromBasket(args.itemId);
|
|
239
|
+
return formatResponse(result);
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
return formatError(error);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
// Tool: clear_basket
|
|
246
|
+
server.tool("clear_basket", "Clear the entire cart", {}, async () => {
|
|
247
|
+
try {
|
|
248
|
+
await clearBasket();
|
|
249
|
+
return formatResponse({ success: true, message: "Basket cleared successfully" });
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
return formatError(error);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
// Tool: search_restaurants
|
|
256
|
+
server.tool("search_restaurants", "Search restaurants and products by keyword", {
|
|
257
|
+
searchQuery: z.string().describe("Search keyword (e.g., 'dürüm', 'pizza', 'burger')"),
|
|
258
|
+
latitude: z.string().describe("Latitude coordinate"),
|
|
259
|
+
longitude: z.string().describe("Longitude coordinate"),
|
|
260
|
+
page: z.number().optional().describe("Page number for pagination (default: 1)"),
|
|
261
|
+
}, async (args) => {
|
|
262
|
+
try {
|
|
263
|
+
const result = await searchRestaurants(args.searchQuery, args.latitude, args.longitude, args.page ?? 1);
|
|
264
|
+
return formatResponse(result);
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
return formatError(error);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
// Tool: get_cities
|
|
271
|
+
server.tool("get_cities", "Get list of all cities for address selection", {}, async () => {
|
|
272
|
+
try {
|
|
273
|
+
const result = await getCities();
|
|
274
|
+
return formatResponse(result);
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
return formatError(error);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
// Tool: get_districts
|
|
281
|
+
server.tool("get_districts", "Get districts for a city", {
|
|
282
|
+
cityId: z.number().describe("City ID"),
|
|
283
|
+
}, async (args) => {
|
|
284
|
+
try {
|
|
285
|
+
const result = await getDistricts(args.cityId);
|
|
286
|
+
return formatResponse(result);
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
return formatError(error);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
// Tool: get_neighborhoods
|
|
293
|
+
server.tool("get_neighborhoods", "Get neighborhoods for a district", {
|
|
294
|
+
districtId: z.number().describe("District ID"),
|
|
295
|
+
}, async (args) => {
|
|
296
|
+
try {
|
|
297
|
+
const result = await getNeighborhoods(args.districtId);
|
|
298
|
+
return formatResponse(result);
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
return formatError(error);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
// Tool: add_address
|
|
305
|
+
server.tool("add_address", "Add a new delivery address. Use get_cities, get_districts, get_neighborhoods to find location IDs first.", {
|
|
306
|
+
name: z.string().describe("First name"),
|
|
307
|
+
surname: z.string().describe("Last name"),
|
|
308
|
+
phone: z.string().describe("Phone number without country code (e.g., '5356437070')"),
|
|
309
|
+
addressName: z.string().describe("Name for this address (e.g., 'Home', 'Work')"),
|
|
310
|
+
addressLine: z.string().describe("Street address"),
|
|
311
|
+
cityId: z.number().describe("City ID (from get_cities)"),
|
|
312
|
+
districtId: z.number().describe("District ID (from get_districts)"),
|
|
313
|
+
neighborhoodId: z.number().describe("Neighborhood ID (from get_neighborhoods)"),
|
|
314
|
+
latitude: z.string().describe("Latitude coordinate"),
|
|
315
|
+
longitude: z.string().describe("Longitude coordinate"),
|
|
316
|
+
apartmentNumber: z.string().optional().describe("Apartment/building number"),
|
|
317
|
+
floor: z.string().optional().describe("Floor number"),
|
|
318
|
+
doorNumber: z.string().optional().describe("Door number"),
|
|
319
|
+
addressDescription: z.string().optional().describe("Additional details/directions"),
|
|
320
|
+
elevatorAvailable: z.boolean().optional().describe("Whether elevator is available"),
|
|
321
|
+
}, async (args) => {
|
|
322
|
+
try {
|
|
323
|
+
const result = await addAddress({
|
|
324
|
+
name: args.name,
|
|
325
|
+
surname: args.surname,
|
|
326
|
+
phone: args.phone,
|
|
327
|
+
addressName: args.addressName,
|
|
328
|
+
addressLine: args.addressLine,
|
|
329
|
+
cityId: args.cityId,
|
|
330
|
+
districtId: args.districtId,
|
|
331
|
+
neighborhoodId: args.neighborhoodId,
|
|
332
|
+
latitude: args.latitude,
|
|
333
|
+
longitude: args.longitude,
|
|
334
|
+
apartmentNumber: args.apartmentNumber,
|
|
335
|
+
floor: args.floor,
|
|
336
|
+
doorNumber: args.doorNumber,
|
|
337
|
+
addressDescription: args.addressDescription,
|
|
338
|
+
elevatorAvailable: args.elevatorAvailable,
|
|
339
|
+
});
|
|
340
|
+
return formatResponse(result);
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
return formatError(error);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
// Tool: get_saved_cards
|
|
347
|
+
server.tool("get_saved_cards", "Get user's saved payment cards (masked). If no cards, user must add one on the website.", {}, async () => {
|
|
348
|
+
try {
|
|
349
|
+
const result = await getSavedCards();
|
|
350
|
+
return formatResponse(result);
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
return formatError(error);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
// Tool: checkout_ready
|
|
357
|
+
server.tool("checkout_ready", "Get basket ready for checkout with payment context. Call this before placing an order.", {}, async () => {
|
|
358
|
+
try {
|
|
359
|
+
const result = await getCheckoutReady();
|
|
360
|
+
return formatResponse(result);
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
return formatError(error);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
// Tool: set_order_note
|
|
367
|
+
server.tool("set_order_note", "Set order note and service preferences. Call before place_order.", {
|
|
368
|
+
note: z.string().optional().describe("Note for courier/restaurant"),
|
|
369
|
+
noServiceWare: z.boolean().optional().describe("Don't include plastic/cutlery (default: false)"),
|
|
370
|
+
contactlessDelivery: z.boolean().optional().describe("Leave at door (default: false)"),
|
|
371
|
+
dontRingBell: z.boolean().optional().describe("Don't ring doorbell (default: false)"),
|
|
372
|
+
}, async (args) => {
|
|
373
|
+
try {
|
|
374
|
+
await updateCustomerNote({
|
|
375
|
+
customerNote: args.note ?? "",
|
|
376
|
+
noServiceWare: args.noServiceWare ?? false,
|
|
377
|
+
contactlessDelivery: args.contactlessDelivery ?? false,
|
|
378
|
+
dontRingBell: args.dontRingBell ?? false,
|
|
379
|
+
});
|
|
380
|
+
return formatResponse({
|
|
381
|
+
success: true,
|
|
382
|
+
message: "Order note and preferences saved"
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
return formatError(error);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
// Tool: place_order
|
|
390
|
+
server.tool("place_order", "Place the order using a saved card with 3D Secure. Opens browser for bank verification if needed.", {
|
|
391
|
+
cardId: z.number().describe("Card ID from get_saved_cards"),
|
|
392
|
+
}, async (args) => {
|
|
393
|
+
try {
|
|
394
|
+
const result = await placeOrder(args.cardId);
|
|
395
|
+
// If 3D Secure is required and we have HTML content, open it in browser
|
|
396
|
+
if (result.requires3DSecure && result.htmlContent) {
|
|
397
|
+
const { writeFileSync } = await import("fs");
|
|
398
|
+
const { execSync } = await import("child_process");
|
|
399
|
+
const { tmpdir } = await import("os");
|
|
400
|
+
const { join } = await import("path");
|
|
401
|
+
const tempFile = join(tmpdir(), `3dsecure_${Date.now()}.html`);
|
|
402
|
+
writeFileSync(tempFile, result.htmlContent);
|
|
403
|
+
// Open in default browser (works on macOS, Linux, Windows)
|
|
404
|
+
const platform = process.platform;
|
|
405
|
+
if (platform === "darwin") {
|
|
406
|
+
execSync(`open "${tempFile}"`);
|
|
407
|
+
}
|
|
408
|
+
else if (platform === "win32") {
|
|
409
|
+
execSync(`start "" "${tempFile}"`);
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
execSync(`xdg-open "${tempFile}"`);
|
|
413
|
+
}
|
|
414
|
+
return formatResponse({
|
|
415
|
+
...result,
|
|
416
|
+
htmlContent: undefined, // Don't return the full HTML in response
|
|
417
|
+
browserOpened: true,
|
|
418
|
+
message: "3D Secure verification page opened in browser. Complete the payment there."
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
return formatResponse(result);
|
|
422
|
+
}
|
|
423
|
+
catch (error) {
|
|
424
|
+
return formatError(error);
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
// Tool: get_orders
|
|
428
|
+
server.tool("get_orders", "Get user's order history with status", {
|
|
429
|
+
page: z.number().optional().describe("Page number (default: 1)"),
|
|
430
|
+
}, async (args) => {
|
|
431
|
+
try {
|
|
432
|
+
const result = await getOrders(args.page ?? 1);
|
|
433
|
+
return formatResponse(result);
|
|
434
|
+
}
|
|
435
|
+
catch (error) {
|
|
436
|
+
return formatError(error);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
// Tool: get_order_detail
|
|
440
|
+
server.tool("get_order_detail", "Get detailed information about a specific order including delivery status", {
|
|
441
|
+
orderId: z.string().describe("Order ID from get_orders"),
|
|
442
|
+
}, async (args) => {
|
|
443
|
+
try {
|
|
444
|
+
const result = await getOrderDetail(args.orderId);
|
|
445
|
+
return formatResponse(result);
|
|
446
|
+
}
|
|
447
|
+
catch (error) {
|
|
448
|
+
return formatError(error);
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
async function main() {
|
|
452
|
+
const transport = new StdioServerTransport();
|
|
453
|
+
await server.connect(transport);
|
|
454
|
+
}
|
|
455
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
// Find project root (where npm install was run)
|
|
5
|
+
const projectRoot = process.env.INIT_CWD || process.cwd();
|
|
6
|
+
const mcpJsonPath = join(projectRoot, '.mcp.json');
|
|
7
|
+
const food402Config = {
|
|
8
|
+
command: "node",
|
|
9
|
+
args: ["./node_modules/food402/dist/index.js"],
|
|
10
|
+
env: {
|
|
11
|
+
TGO_EMAIL: "your-email@example.com",
|
|
12
|
+
TGO_PASSWORD: "your-password"
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
let config = { mcpServers: {} };
|
|
16
|
+
if (existsSync(mcpJsonPath)) {
|
|
17
|
+
try {
|
|
18
|
+
config = JSON.parse(readFileSync(mcpJsonPath, 'utf-8'));
|
|
19
|
+
if (!config.mcpServers)
|
|
20
|
+
config.mcpServers = {};
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Invalid JSON, start fresh
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
config.mcpServers.food402 = food402Config;
|
|
27
|
+
writeFileSync(mcpJsonPath, JSON.stringify(config, null, 2) + '\n');
|
|
28
|
+
console.log('✓ Added food402 to .mcp.json');
|
|
29
|
+
console.log('→ Update TGO_EMAIL and TGO_PASSWORD in .mcp.json with your credentials');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "food402",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4-beta.1",
|
|
4
4
|
"description": "MCP server for ordering food from TGO Yemek",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"start": "tsx src/index.ts",
|
|
14
14
|
"build": "tsc",
|
|
15
|
+
"postinstall": "node dist/postinstall.js",
|
|
15
16
|
"prepublishOnly": "npm run build"
|
|
16
17
|
},
|
|
17
18
|
"keywords": [
|