@striderlabs/mcp-postmates 1.0.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/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # @striderlabs/mcp-postmates
2
+
3
+ MCP connector for [Postmates](https://postmates.com) food delivery service. Uses Playwright (headless Chromium) for browser automation.
4
+
5
+ **Author:** Strider Labs <hello@striderlabs.ai>
6
+
7
+ ## Tools
8
+
9
+ | Tool | Description |
10
+ |------|-------------|
11
+ | `postmates_search_restaurants` | Search restaurants by location and cuisine |
12
+ | `postmates_get_menu` | Get restaurant menu items |
13
+ | `postmates_add_to_cart` | Add items to cart |
14
+ | `postmates_view_cart` | View current cart |
15
+ | `postmates_place_order` | Place a delivery order |
16
+ | `postmates_track_order` | Track order status |
17
+
18
+ ## Setup
19
+
20
+ ```bash
21
+ npm install
22
+ npx playwright install chromium
23
+ npm run build
24
+ ```
25
+
26
+ ## Usage with MCP
27
+
28
+ Add to your MCP configuration:
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "postmates": {
34
+ "command": "node",
35
+ "args": ["./node_modules/@striderlabs/mcp-postmates/dist/index.js"]
36
+ }
37
+ }
38
+ }
39
+ ```
@@ -0,0 +1,26 @@
1
+ import { type Page } from 'playwright';
2
+ import { type SessionManager } from './session.js';
3
+ export declare class PostmatesBrowser {
4
+ private browser;
5
+ private context;
6
+ private page;
7
+ private readonly session;
8
+ constructor(session: SessionManager);
9
+ launch(): Promise<void>;
10
+ close(): Promise<void>;
11
+ getPage(): Page;
12
+ navigate(path: string): Promise<void>;
13
+ waitForSelector(selector: string, timeout?: number): Promise<void>;
14
+ getText(selector: string): Promise<string>;
15
+ getTexts(selector: string): Promise<string[]>;
16
+ getAttribute(selector: string, attr: string): Promise<string | null>;
17
+ click(selector: string): Promise<void>;
18
+ fill(selector: string, value: string): Promise<void>;
19
+ searchRestaurants(location: string, cuisine?: string): Promise<unknown[]>;
20
+ getRestaurantMenu(restaurantId: string): Promise<unknown[]>;
21
+ addItemToCart(restaurantId: string, itemId: string, quantity: number): Promise<boolean>;
22
+ getCurrentCart(): Promise<unknown>;
23
+ placeOrder(deliveryAddress: string, paymentMethod: string): Promise<unknown>;
24
+ trackOrder(orderId: string): Promise<unknown>;
25
+ }
26
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAInD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;gBAE7B,OAAO,EAAE,cAAc;IAI7B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IA6CvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B,OAAO,IAAI,IAAI;IAKT,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlE,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAO7C,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKpE,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKpD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAwEzE,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAqD3D,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BvF,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IA8ClC,UAAU,CAAC,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsC5E,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAmCpD"}
@@ -0,0 +1,330 @@
1
+ import { chromium } from 'playwright';
2
+ const BASE_URL = 'https://postmates.com';
3
+ export class PostmatesBrowser {
4
+ browser = null;
5
+ context = null;
6
+ page = null;
7
+ session;
8
+ constructor(session) {
9
+ this.session = session;
10
+ }
11
+ async launch() {
12
+ if (this.browser)
13
+ return;
14
+ this.browser = await chromium.launch({
15
+ headless: true,
16
+ args: [
17
+ '--no-sandbox',
18
+ '--disable-setuid-sandbox',
19
+ '--disable-dev-shm-usage',
20
+ '--disable-accelerated-2d-canvas',
21
+ '--no-first-run',
22
+ '--no-zygote',
23
+ '--disable-gpu',
24
+ ],
25
+ });
26
+ this.context = await this.browser.newContext({
27
+ userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
28
+ viewport: { width: 1280, height: 800 },
29
+ locale: 'en-US',
30
+ });
31
+ // Restore cookies from session if available
32
+ const cookies = this.session.getCookies();
33
+ if (Object.keys(cookies).length > 0) {
34
+ const cookieArray = Object.entries(cookies).map(([name, value]) => ({
35
+ name,
36
+ value,
37
+ domain: '.postmates.com',
38
+ path: '/',
39
+ }));
40
+ await this.context.addCookies(cookieArray);
41
+ }
42
+ this.page = await this.context.newPage();
43
+ // Block unnecessary resources for performance
44
+ await this.page.route('**/*.{png,jpg,jpeg,gif,webp,svg,woff,woff2,ttf}', (route) => route.abort());
45
+ await this.page.route('**/analytics/**', (route) => route.abort());
46
+ await this.page.route('**/tracking/**', (route) => route.abort());
47
+ }
48
+ async close() {
49
+ if (this.page) {
50
+ await this.page.close().catch(() => { });
51
+ this.page = null;
52
+ }
53
+ if (this.context) {
54
+ // Persist cookies to session before closing
55
+ const cookies = await this.context.cookies();
56
+ for (const cookie of cookies) {
57
+ this.session.setCookie(cookie.name, cookie.value);
58
+ }
59
+ await this.context.close().catch(() => { });
60
+ this.context = null;
61
+ }
62
+ if (this.browser) {
63
+ await this.browser.close().catch(() => { });
64
+ this.browser = null;
65
+ }
66
+ }
67
+ getPage() {
68
+ if (!this.page)
69
+ throw new Error('Browser not launched. Call launch() first.');
70
+ return this.page;
71
+ }
72
+ async navigate(path) {
73
+ const page = this.getPage();
74
+ const url = path.startsWith('http') ? path : `${BASE_URL}${path}`;
75
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
76
+ this.session.touch();
77
+ }
78
+ async waitForSelector(selector, timeout = 10_000) {
79
+ const page = this.getPage();
80
+ await page.waitForSelector(selector, { timeout });
81
+ }
82
+ async getText(selector) {
83
+ const page = this.getPage();
84
+ const el = await page.$(selector);
85
+ return el ? (await el.textContent() ?? '').trim() : '';
86
+ }
87
+ async getTexts(selector) {
88
+ const page = this.getPage();
89
+ const elements = await page.$$(selector);
90
+ const texts = await Promise.all(elements.map((el) => el.textContent()));
91
+ return texts.map((t) => (t ?? '').trim()).filter((t) => t.length > 0);
92
+ }
93
+ async getAttribute(selector, attr) {
94
+ const page = this.getPage();
95
+ return page.getAttribute(selector, attr);
96
+ }
97
+ async click(selector) {
98
+ const page = this.getPage();
99
+ await page.click(selector, { timeout: 10_000 });
100
+ this.session.touch();
101
+ }
102
+ async fill(selector, value) {
103
+ const page = this.getPage();
104
+ await page.fill(selector, value, { timeout: 10_000 });
105
+ }
106
+ async searchRestaurants(location, cuisine) {
107
+ await this.navigate(`/feed?pl=${encodeURIComponent(location)}`);
108
+ await this.waitForSelector('[data-testid="store-card"], .store-card, [class*="StoreCard"]', 10_000)
109
+ .catch(() => { });
110
+ const page = this.getPage();
111
+ // Attempt to extract restaurant cards via page evaluation
112
+ const restaurants = await page.evaluate(({ loc, cui }) => {
113
+ const cards = [];
114
+ const selectors = [
115
+ '[data-testid="store-card"]',
116
+ '[class*="StoreCard"]',
117
+ 'a[href*="/store/"]',
118
+ ];
119
+ let elements = null;
120
+ for (const sel of selectors) {
121
+ const found = document.querySelectorAll(sel);
122
+ if (found.length > 0) {
123
+ elements = found;
124
+ break;
125
+ }
126
+ }
127
+ if (!elements)
128
+ return cards;
129
+ elements.forEach((el, idx) => {
130
+ const name = el.querySelector('[class*="title"], h3, h4, [data-testid*="name"]')?.textContent?.trim() ?? '';
131
+ const ratingEl = el.querySelector('[class*="rating"], [data-testid*="rating"]');
132
+ const rating = parseFloat(ratingEl?.textContent?.trim() ?? '0') || 0;
133
+ const deliveryTimeEl = el.querySelector('[class*="eta"], [class*="time"], [data-testid*="time"]');
134
+ const deliveryTime = deliveryTimeEl?.textContent?.trim() ?? 'N/A';
135
+ const feeEl = el.querySelector('[class*="fee"], [data-testid*="fee"]');
136
+ const deliveryFee = feeEl?.textContent?.trim() ?? 'N/A';
137
+ const href = el.href ?? el.querySelector('a')?.href ?? '';
138
+ const idMatch = href.match(/\/store\/([^/?#]+)/);
139
+ const id = idMatch ? idMatch[1] : `restaurant-${idx}`;
140
+ const cuisineTag = el.querySelector('[class*="cuisine"], [class*="category"]')?.textContent?.trim() ?? '';
141
+ if (!name)
142
+ return;
143
+ const item = {
144
+ id,
145
+ name,
146
+ cuisine: cuisineTag,
147
+ rating,
148
+ deliveryTime,
149
+ deliveryFee,
150
+ minimumOrder: '$0',
151
+ isOpen: !el.querySelector('[class*="closed"], [data-testid*="closed"]'),
152
+ href,
153
+ };
154
+ // Filter by cuisine if provided
155
+ if (cui && cuisineTag && !cuisineTag.toLowerCase().includes(cui.toLowerCase()) && !name.toLowerCase().includes(cui.toLowerCase())) {
156
+ return;
157
+ }
158
+ cards.push(item);
159
+ });
160
+ return cards.slice(0, 20);
161
+ }, { loc: location, cui: cuisine });
162
+ return restaurants;
163
+ }
164
+ async getRestaurantMenu(restaurantId) {
165
+ await this.navigate(`/store/${restaurantId}`);
166
+ await this.waitForSelector('[data-testid="menu-item"], [class*="MenuItem"], [class*="menu-item"]', 15_000)
167
+ .catch(() => { });
168
+ const menuItems = await this.getPage().evaluate(() => {
169
+ const items = [];
170
+ const selectors = [
171
+ '[data-testid="menu-item"]',
172
+ '[class*="MenuItem"]',
173
+ '[class*="menu-item"]',
174
+ 'li[class*="item"]',
175
+ ];
176
+ let elements = null;
177
+ for (const sel of selectors) {
178
+ const found = document.querySelectorAll(sel);
179
+ if (found.length > 0) {
180
+ elements = found;
181
+ break;
182
+ }
183
+ }
184
+ if (!elements)
185
+ return items;
186
+ elements.forEach((el, idx) => {
187
+ const name = el.querySelector('[class*="title"], [class*="name"], h3, h4')?.textContent?.trim() ?? '';
188
+ const desc = el.querySelector('[class*="description"], [class*="desc"], p')?.textContent?.trim() ?? '';
189
+ const priceText = el.querySelector('[class*="price"], [data-testid*="price"]')?.textContent?.trim() ?? '0';
190
+ const price = parseFloat(priceText.replace(/[^0-9.]/g, '')) || 0;
191
+ const category = el.closest('[class*="section"], [class*="category"]')
192
+ ?.querySelector('h2, h3, [class*="header"]')?.textContent?.trim() ?? 'Menu';
193
+ const isUnavailable = !!el.querySelector('[class*="unavailable"], [class*="sold-out"]');
194
+ if (!name)
195
+ return;
196
+ items.push({
197
+ id: `item-${idx}`,
198
+ name,
199
+ description: desc,
200
+ price,
201
+ category,
202
+ isAvailable: !isUnavailable,
203
+ });
204
+ });
205
+ return items.slice(0, 100);
206
+ });
207
+ return menuItems;
208
+ }
209
+ async addItemToCart(restaurantId, itemId, quantity) {
210
+ await this.navigate(`/store/${restaurantId}`);
211
+ this.session.touch();
212
+ // Click the item to open its modal
213
+ const page = this.getPage();
214
+ const itemSelector = `[data-testid="menu-item"]:nth-child(${parseInt(itemId.replace('item-', ''), 10) + 1}), [class*="MenuItem"]:nth-child(${parseInt(itemId.replace('item-', ''), 10) + 1})`;
215
+ try {
216
+ await page.click(itemSelector, { timeout: 5_000 });
217
+ await page.waitForSelector('[class*="add-to-cart"], [data-testid="add-to-order"]', { timeout: 5_000 });
218
+ // Set quantity if > 1
219
+ if (quantity > 1) {
220
+ for (let i = 1; i < quantity; i++) {
221
+ await page.click('[class*="increment"], [data-testid="increment"]', { timeout: 3_000 }).catch(() => { });
222
+ }
223
+ }
224
+ await page.click('[class*="add-to-cart"], [data-testid="add-to-order"]', { timeout: 5_000 });
225
+ return true;
226
+ }
227
+ catch {
228
+ return false;
229
+ }
230
+ }
231
+ async getCurrentCart() {
232
+ const page = this.getPage();
233
+ return page.evaluate(() => {
234
+ // Attempt to read cart state from various storage locations
235
+ const cartData = {};
236
+ // Try localStorage
237
+ for (let i = 0; i < localStorage.length; i++) {
238
+ const key = localStorage.key(i);
239
+ if (key && (key.includes('cart') || key.includes('basket') || key.includes('order'))) {
240
+ try {
241
+ cartData[key] = JSON.parse(localStorage.getItem(key) ?? 'null');
242
+ }
243
+ catch {
244
+ cartData[key] = localStorage.getItem(key);
245
+ }
246
+ }
247
+ }
248
+ // Try to read rendered cart UI
249
+ const cartItems = [];
250
+ const itemSelectors = [
251
+ '[class*="CartItem"]',
252
+ '[data-testid="cart-item"]',
253
+ '[class*="basket-item"]',
254
+ ];
255
+ for (const sel of itemSelectors) {
256
+ const elements = document.querySelectorAll(sel);
257
+ if (elements.length > 0) {
258
+ elements.forEach((el) => {
259
+ const name = el.querySelector('[class*="name"], [class*="title"]')?.textContent?.trim() ?? '';
260
+ const qty = el.querySelector('[class*="quantity"], [class*="qty"]')?.textContent?.trim() ?? '1';
261
+ const price = el.querySelector('[class*="price"]')?.textContent?.trim() ?? '0';
262
+ if (name)
263
+ cartItems.push({ name, quantity: parseInt(qty, 10) || 1, price });
264
+ });
265
+ break;
266
+ }
267
+ }
268
+ const subtotal = document.querySelector('[class*="subtotal"], [data-testid="subtotal"]')?.textContent?.trim() ?? '';
269
+ const total = document.querySelector('[class*="total"], [data-testid="total"]')?.textContent?.trim() ?? '';
270
+ return { items: cartItems, subtotal, total, storageData: cartData };
271
+ });
272
+ }
273
+ async placeOrder(deliveryAddress, paymentMethod) {
274
+ const page = this.getPage();
275
+ // Navigate to checkout
276
+ await page.click('[class*="checkout"], [data-testid="checkout-button"]', { timeout: 10_000 });
277
+ await page.waitForSelector('[class*="checkout"], [data-testid="checkout-page"]', { timeout: 15_000 });
278
+ // Fill delivery address if needed
279
+ const addressField = await page.$('[class*="delivery-address"] input, [data-testid="address-input"]');
280
+ if (addressField) {
281
+ await addressField.fill(deliveryAddress);
282
+ await page.waitForTimeout(500);
283
+ await page.keyboard.press('Enter');
284
+ }
285
+ // Select payment
286
+ const paymentEl = await page.$(`[data-testid="payment-${paymentMethod}"], [class*="payment-method"]`);
287
+ if (paymentEl)
288
+ await paymentEl.click();
289
+ // Confirm order
290
+ await page.click('[data-testid="place-order"], [class*="place-order"], [class*="submit-order"]', {
291
+ timeout: 10_000,
292
+ });
293
+ await page.waitForSelector('[data-testid="order-confirmation"], [class*="confirmation"]', {
294
+ timeout: 30_000,
295
+ });
296
+ return page.evaluate(() => {
297
+ const orderId = document.querySelector('[data-testid="order-id"], [class*="order-id"]')?.textContent?.trim() ??
298
+ `ORDER-${Date.now()}`;
299
+ const eta = document.querySelector('[class*="eta"], [data-testid="eta"]')?.textContent?.trim() ?? '30-45 min';
300
+ return { orderId, estimatedDelivery: eta, status: 'placed' };
301
+ });
302
+ }
303
+ async trackOrder(orderId) {
304
+ await this.navigate(`/orders/${orderId}`);
305
+ await this.waitForSelector('[class*="order-status"], [data-testid="order-tracking"]', 15_000).catch(() => { });
306
+ return this.getPage().evaluate((id) => {
307
+ const status = document.querySelector('[class*="status-label"], [data-testid="status"]')?.textContent?.trim() ??
308
+ 'unknown';
309
+ const eta = document.querySelector('[class*="eta"], [data-testid="eta"]')?.textContent?.trim() ?? 'N/A';
310
+ const courier = document.querySelector('[class*="courier-name"], [data-testid="courier"]')?.textContent?.trim();
311
+ const steps = [];
312
+ document.querySelectorAll('[class*="step"], [data-testid*="step"]').forEach((el) => {
313
+ steps.push({
314
+ label: el.querySelector('[class*="label"]')?.textContent?.trim() ?? el.textContent?.trim() ?? '',
315
+ completed: el.classList.toString().includes('completed') || el.classList.toString().includes('done'),
316
+ });
317
+ });
318
+ return {
319
+ orderId: id,
320
+ status,
321
+ statusMessage: status,
322
+ estimatedDelivery: eta,
323
+ courierName: courier,
324
+ lastUpdated: new Date().toISOString(),
325
+ steps,
326
+ };
327
+ }, orderId);
328
+ }
329
+ }
330
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @striderlabs/mcp-postmates
4
+ *
5
+ * MCP connector for Postmates food delivery service.
6
+ * Uses Playwright (headless Chromium) for browser automation.
7
+ *
8
+ * Author: Strider Labs <hello@striderlabs.ai>
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
package/dist/index.js ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @striderlabs/mcp-postmates
4
+ *
5
+ * MCP connector for Postmates food delivery service.
6
+ * Uses Playwright (headless Chromium) for browser automation.
7
+ *
8
+ * Author: Strider Labs <hello@striderlabs.ai>
9
+ */
10
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
12
+ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
13
+ import { zodToJsonSchema } from 'zod-to-json-schema';
14
+ import { SessionManager } from './session.js';
15
+ import { PostmatesBrowser } from './browser.js';
16
+ import { AddToCartSchema, GetMenuSchema, PlaceOrderSchema, SearchRestaurantsSchema, TrackOrderSchema, ViewCartSchema, handleAddToCart, handleGetMenu, handlePlaceOrder, handleSearchRestaurants, handleTrackOrder, handleViewCart, } from './tools.js';
17
+ // ─── Server Setup ──────────────────────────────────────────────────────────
18
+ const session = new SessionManager();
19
+ const browser = new PostmatesBrowser(session);
20
+ const server = new Server({
21
+ name: 'mcp-postmates',
22
+ version: '1.0.0',
23
+ }, {
24
+ capabilities: {
25
+ tools: {},
26
+ },
27
+ });
28
+ // ─── Tool Definitions ──────────────────────────────────────────────────────
29
+ const TOOLS = [
30
+ {
31
+ name: 'postmates_search_restaurants',
32
+ description: 'Search for restaurants on Postmates by delivery location and optional cuisine type. ' +
33
+ 'Returns a list of restaurants with IDs, ratings, delivery times, and fees.',
34
+ inputSchema: zodToJsonSchema(SearchRestaurantsSchema, { name: 'SearchRestaurantsInput' }),
35
+ },
36
+ {
37
+ name: 'postmates_get_menu',
38
+ description: 'Get the full menu for a specific restaurant on Postmates. ' +
39
+ 'Returns menu items grouped by category with names, descriptions, prices, and item IDs. ' +
40
+ 'Use restaurant IDs from postmates_search_restaurants.',
41
+ inputSchema: zodToJsonSchema(GetMenuSchema, { name: 'GetMenuInput' }),
42
+ },
43
+ {
44
+ name: 'postmates_add_to_cart',
45
+ description: 'Add a menu item to the Postmates cart. ' +
46
+ 'All items in a cart must be from the same restaurant. ' +
47
+ 'Use item IDs from postmates_get_menu.',
48
+ inputSchema: zodToJsonSchema(AddToCartSchema, { name: 'AddToCartInput' }),
49
+ },
50
+ {
51
+ name: 'postmates_view_cart',
52
+ description: 'View the current Postmates cart contents including items, quantities, and pricing breakdown (subtotal, delivery fee, taxes, total).',
53
+ inputSchema: zodToJsonSchema(ViewCartSchema, { name: 'ViewCartInput' }),
54
+ },
55
+ {
56
+ name: 'postmates_place_order',
57
+ description: 'Place a Postmates food delivery order using the current cart contents. ' +
58
+ 'Requires a delivery address and optionally a payment method and tip. ' +
59
+ 'Clears the cart upon successful order placement.',
60
+ inputSchema: zodToJsonSchema(PlaceOrderSchema, { name: 'PlaceOrderInput' }),
61
+ },
62
+ {
63
+ name: 'postmates_track_order',
64
+ description: 'Track the real-time status of a Postmates order by order ID. ' +
65
+ 'Returns current status, estimated delivery time, courier info, and step-by-step progress.',
66
+ inputSchema: zodToJsonSchema(TrackOrderSchema, { name: 'TrackOrderInput' }),
67
+ },
68
+ ];
69
+ // ─── Request Handlers ──────────────────────────────────────────────────────
70
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
71
+ tools: TOOLS,
72
+ }));
73
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
74
+ const { name, arguments: args } = request.params;
75
+ try {
76
+ switch (name) {
77
+ case 'postmates_search_restaurants': {
78
+ const input = SearchRestaurantsSchema.parse(args);
79
+ return await handleSearchRestaurants(input, browser, session);
80
+ }
81
+ case 'postmates_get_menu': {
82
+ const input = GetMenuSchema.parse(args);
83
+ return await handleGetMenu(input, browser, session);
84
+ }
85
+ case 'postmates_add_to_cart': {
86
+ const input = AddToCartSchema.parse(args);
87
+ return await handleAddToCart(input, browser, session);
88
+ }
89
+ case 'postmates_view_cart': {
90
+ const input = ViewCartSchema.parse(args ?? {});
91
+ return await handleViewCart(input, browser, session);
92
+ }
93
+ case 'postmates_place_order': {
94
+ const input = PlaceOrderSchema.parse(args);
95
+ return await handlePlaceOrder(input, browser, session);
96
+ }
97
+ case 'postmates_track_order': {
98
+ const input = TrackOrderSchema.parse(args);
99
+ return await handleTrackOrder(input, browser, session);
100
+ }
101
+ default:
102
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
103
+ }
104
+ }
105
+ catch (error) {
106
+ if (error instanceof McpError)
107
+ throw error;
108
+ const message = error instanceof Error ? error.message : String(error);
109
+ // Return user-friendly error as tool content rather than crashing
110
+ return {
111
+ content: [
112
+ {
113
+ type: 'text',
114
+ text: `❌ **Error executing ${name}**\n\n${message}\n\nPlease try again or check your inputs.`,
115
+ },
116
+ ],
117
+ isError: true,
118
+ };
119
+ }
120
+ });
121
+ // ─── Graceful Shutdown ─────────────────────────────────────────────────────
122
+ async function shutdown() {
123
+ await browser.close().catch(() => { });
124
+ process.exit(0);
125
+ }
126
+ process.on('SIGINT', shutdown);
127
+ process.on('SIGTERM', shutdown);
128
+ // ─── Start Server ──────────────────────────────────────────────────────────
129
+ async function main() {
130
+ const transport = new StdioServerTransport();
131
+ await server.connect(transport);
132
+ // Server is now running — MCP communicates over stdio
133
+ }
134
+ main().catch((error) => {
135
+ process.stderr.write(`Fatal error: ${error instanceof Error ? error.message : String(error)}\n`);
136
+ process.exit(1);
137
+ });
138
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { type Cart } from './types.js';
2
+ export declare class SessionManager {
3
+ private state;
4
+ private cookies;
5
+ private storageData;
6
+ isActive(): boolean;
7
+ isAuthenticated(): boolean;
8
+ setAuthenticated(userId: string): void;
9
+ invalidate(): void;
10
+ touch(): void;
11
+ getUserId(): string | undefined;
12
+ getCart(): Cart | undefined;
13
+ setCart(cart: Cart): void;
14
+ clearCart(): void;
15
+ setCookie(name: string, value: string): void;
16
+ getCookies(): Record<string, string>;
17
+ setStorageItem(key: string, value: string): void;
18
+ getStorageItem(key: string): string | undefined;
19
+ getStatus(): {
20
+ authenticated: boolean;
21
+ userId?: string;
22
+ hasCart: boolean;
23
+ sessionAge: number;
24
+ };
25
+ }
26
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAI1D,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAGX;IAEF,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,WAAW,CAA8B;IAEjD,QAAQ,IAAI,OAAO;IAKnB,eAAe,IAAI,OAAO;IAI1B,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMtC,UAAU,IAAI,IAAI;IASlB,KAAK,IAAI,IAAI;IAIb,SAAS,IAAI,MAAM,GAAG,SAAS;IAI/B,OAAO,IAAI,IAAI,GAAG,SAAS;IAI3B,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAKzB,SAAS,IAAI,IAAI;IAKjB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI5C,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAIpC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIhD,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI/C,SAAS,IAAI;QAAE,aAAa,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;CAW/F"}