food402 1.0.4-beta.1 → 1.1.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 CHANGED
@@ -4,7 +4,20 @@
4
4
 
5
5
  An MCP (Model Context Protocol) server that enables AI assistants to order food from TGO Yemek. Simply chat with your AI assistant to browse restaurants, build your order, and complete checkout.
6
6
 
7
- ## Installation
7
+ ## Deployment Options
8
+
9
+ Food402 supports two deployment methods:
10
+
11
+ | Method | Best For | Transport | Auth |
12
+ |--------|----------|-----------|------|
13
+ | **Local MCP Server** | Claude Desktop, Claude Code | stdio | Environment variables |
14
+ | **Remote MCP Server** | Claude.ai (web) | HTTP | OAuth 2.0 |
15
+
16
+ ---
17
+
18
+ ## Local MCP Server (npm package)
19
+
20
+ ### Claude Desktop
8
21
 
9
22
  Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
10
23
 
@@ -25,7 +38,7 @@ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_
25
38
 
26
39
  Replace `your-email@example.com` and `your-password` with your TGO Yemek credentials.
27
40
 
28
- ## Local Installation (Claude Code)
41
+ ### Claude Code
29
42
 
30
43
  For project-specific installation with Claude Code:
31
44
 
@@ -40,7 +53,7 @@ This automatically adds `food402` to your `.mcp.json`. Open the file and update
40
53
  "mcpServers": {
41
54
  "food402": {
42
55
  "command": "node",
43
- "args": ["./node_modules/food402/dist/index.js"],
56
+ "args": ["./node_modules/food402/dist/src/index.js"],
44
57
  "env": {
45
58
  "TGO_EMAIL": "your-email@example.com",
46
59
  "TGO_PASSWORD": "your-password"
@@ -50,6 +63,25 @@ This automatically adds `food402` to your `.mcp.json`. Open the file and update
50
63
  }
51
64
  ```
52
65
 
66
+ ---
67
+
68
+ ## Remote MCP Server (Claude.ai Web)
69
+
70
+ For Claude.ai web access, use the remote MCP server deployed on Cloudflare Workers.
71
+
72
+ ### Connect to Claude.ai
73
+
74
+ 1. Go to Claude.ai **Settings > Connectors**
75
+ 2. Click **"Add Custom Connector"**
76
+ 3. Enter the remote server URL
77
+ 4. Complete the OAuth flow by logging in with your TGO Yemek credentials
78
+
79
+ No local setup required—your credentials are securely stored via OAuth.
80
+
81
+ > **Self-hosting?** See [remote/README.md](./remote/README.md) for deployment instructions.
82
+
83
+ ---
84
+
53
85
  ## Prerequisites
54
86
 
55
87
  ### Account Setup Required
@@ -131,11 +163,35 @@ Here's the typical workflow when ordering food through the AI assistant:
131
163
 
132
164
  ## Development
133
165
 
134
- ```bash
135
- # Clone the repository
136
- git clone https://github.com/rersozlu/food402.git
137
- cd food402
166
+ ### Repository Structure
167
+
168
+ ```
169
+ food402/
170
+ ├── src/ # Local MCP server (stdio transport)
171
+ │ ├── index.ts # MCP entry point with tool definitions
172
+ │ ├── auth.ts # TGO auth with token caching
173
+ │ ├── api.ts # Thin wrapper around shared/api.ts
174
+ │ └── postinstall.ts # Auto-configures .mcp.json on npm install
175
+ ├── shared/ # Shared code between local and remote
176
+ │ ├── api.ts # Token-parameterized TGO API functions
177
+ │ └── types.ts # TypeScript interfaces
178
+ ├── remote/ # Remote MCP server (HTTP transport)
179
+ │ ├── src/
180
+ │ │ ├── worker.ts # Cloudflare Worker entry (Hono)
181
+ │ │ ├── server.ts # MCP server with tool definitions
182
+ │ │ ├── auth/ # OAuth 2.0 provider + TGO login
183
+ │ │ ├── payment/ # 3DS verification page handler
184
+ │ │ └── session/ # Encrypted session management
185
+ │ ├── wrangler.toml # CF Workers config
186
+ │ └── package.json # Remote-specific dependencies
187
+ ├── package.json # Root package (npm: food402)
188
+ ├── README.md
189
+ └── CLAUDE.md
190
+ ```
191
+
192
+ ### Local Server Development
138
193
 
194
+ ```bash
139
195
  # Install dependencies
140
196
  npm install
141
197
 
@@ -146,6 +202,23 @@ npm start
146
202
  npm run build
147
203
  ```
148
204
 
205
+ ### Remote Server Development
206
+
207
+ ```bash
208
+ cd remote
209
+
210
+ # Install dependencies
211
+ npm install
212
+
213
+ # Run local dev server (http://localhost:8787)
214
+ npm run dev
215
+
216
+ # Deploy to Cloudflare Workers
217
+ npm run deploy
218
+ ```
219
+
220
+ See [remote/README.md](./remote/README.md) for full deployment instructions including KV namespace setup and secrets configuration.
221
+
149
222
  ## License
150
223
 
151
224
  MIT
@@ -6,7 +6,7 @@ const projectRoot = process.env.INIT_CWD || process.cwd();
6
6
  const mcpJsonPath = join(projectRoot, '.mcp.json');
7
7
  const food402Config = {
8
8
  command: "node",
9
- args: ["./node_modules/food402/dist/index.js"],
9
+ args: ["./node_modules/food402/dist/src/index.js"],
10
10
  env: {
11
11
  TGO_EMAIL: "your-email@example.com",
12
12
  TGO_PASSWORD: "your-password"
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "food402",
3
- "version": "1.0.4-beta.1",
3
+ "version": "1.1.0",
4
4
  "description": "MCP server for ordering food from TGO Yemek",
5
5
  "type": "module",
6
6
  "bin": {
7
- "food402": "./dist/index.js"
7
+ "food402": "./dist/src/index.js"
8
8
  },
9
9
  "files": [
10
10
  "dist"
@@ -12,7 +12,7 @@
12
12
  "scripts": {
13
13
  "start": "tsx src/index.ts",
14
14
  "build": "tsc",
15
- "postinstall": "node dist/postinstall.js",
15
+ "postinstall": "node dist/src/postinstall.js",
16
16
  "prepublishOnly": "npm run build"
17
17
  },
18
18
  "keywords": [
package/dist/api.d.ts DELETED
@@ -1,417 +0,0 @@
1
- export interface Address {
2
- id: number;
3
- name: string;
4
- surname: string;
5
- phone: string;
6
- countryPhoneCode: string;
7
- addressLine: string;
8
- addressName: string;
9
- postalCode: string;
10
- cityId: number;
11
- cityName: string;
12
- districtId: number;
13
- districtName: string;
14
- neighborhoodId: number;
15
- neighborhoodName: string;
16
- latitude: string;
17
- longitude: string;
18
- addressDescription: string;
19
- apartmentNumber: string;
20
- floor: string;
21
- doorNumber: string;
22
- addressType: string;
23
- elevatorAvailable: boolean;
24
- }
25
- export interface AddressesResponse {
26
- infoMessage: string | null;
27
- id: string;
28
- addresses: Address[];
29
- }
30
- export interface Restaurant {
31
- id: number;
32
- name: string;
33
- kitchen: string;
34
- rating: number;
35
- ratingText: string;
36
- minBasketPrice: number;
37
- averageDeliveryInterval: string;
38
- distance: number;
39
- neighborhoodName: string;
40
- isClosed: boolean;
41
- campaignText?: string;
42
- }
43
- export interface RestaurantsResponse {
44
- restaurants: Restaurant[];
45
- totalCount: number;
46
- currentPage: number;
47
- pageSize: number;
48
- hasNextPage: boolean;
49
- }
50
- export declare function getAddresses(): Promise<AddressesResponse>;
51
- export interface MenuItem {
52
- id: number;
53
- name: string;
54
- description: string;
55
- price: number;
56
- likePercentage?: string;
57
- }
58
- export interface MenuCategory {
59
- name: string;
60
- slug: string;
61
- items: MenuItem[];
62
- }
63
- export interface RestaurantInfo {
64
- id: number;
65
- name: string;
66
- status: string;
67
- rating: number;
68
- ratingText: string;
69
- workingHours: string;
70
- deliveryTime: string;
71
- minOrderPrice: number;
72
- }
73
- export interface RestaurantMenuResponse {
74
- info: RestaurantInfo;
75
- categories: MenuCategory[];
76
- totalItems: number;
77
- }
78
- export declare function getRestaurants(latitude: string, longitude: string, page?: number): Promise<RestaurantsResponse>;
79
- export declare function getRestaurantMenu(restaurantId: number, latitude: string, longitude: string): Promise<RestaurantMenuResponse>;
80
- export interface RecommendedItem {
81
- id: number;
82
- name: string;
83
- description: string | null;
84
- price: number;
85
- imageUrl: string;
86
- }
87
- export interface RecommendationCollection {
88
- name: string;
89
- items: RecommendedItem[];
90
- }
91
- export interface ProductRecommendationsResponse {
92
- collections: RecommendationCollection[];
93
- totalItems: number;
94
- }
95
- export declare function getProductRecommendations(restaurantId: number, productIds: number[]): Promise<ProductRecommendationsResponse>;
96
- export interface ProductOption {
97
- id: number;
98
- name: string;
99
- price: number;
100
- selected: boolean;
101
- isPopular?: boolean;
102
- }
103
- export interface ProductComponent {
104
- type: "INGREDIENTS" | "MODIFIER_GROUP";
105
- title: string;
106
- description?: string;
107
- modifierGroupId?: number;
108
- options: ProductOption[];
109
- isSingleChoice: boolean;
110
- minSelections: number;
111
- maxSelections: number;
112
- }
113
- export interface ProductDetailsResponse {
114
- restaurantId: number;
115
- restaurantName: string;
116
- productId: number;
117
- productName: string;
118
- description: string;
119
- imageUrl: string;
120
- price: number;
121
- maxQuantity: number;
122
- components: ProductComponent[];
123
- }
124
- export declare function getProductDetails(restaurantId: number, productId: number, latitude: string, longitude: string): Promise<ProductDetailsResponse>;
125
- export interface IngredientExclusion {
126
- id: number;
127
- }
128
- export interface ModifierProduct {
129
- productId: number;
130
- modifierGroupId: number;
131
- modifierProducts: ModifierProduct[];
132
- ingredientOptions: {
133
- excludes: IngredientExclusion[];
134
- includes: [];
135
- };
136
- }
137
- export interface BasketItem {
138
- productId: number;
139
- quantity: number;
140
- modifierProducts: ModifierProduct[];
141
- ingredientOptions: {
142
- excludes: IngredientExclusion[];
143
- includes: [];
144
- };
145
- }
146
- export interface AddToBasketRequest {
147
- storeId: number;
148
- items: BasketItem[];
149
- isFlashSale: boolean;
150
- storePickup: boolean;
151
- latitude: number;
152
- longitude: number;
153
- }
154
- export interface CartProduct {
155
- productId: number;
156
- itemId: string;
157
- name: string;
158
- quantity: number;
159
- salePrice: number;
160
- description: string;
161
- }
162
- export interface CartStore {
163
- id: number;
164
- name: string;
165
- imageUrl: string;
166
- rating: number;
167
- averageDeliveryInterval: string;
168
- minAmount: number;
169
- }
170
- export interface CartSummaryLine {
171
- title: string;
172
- amount: number;
173
- isPromotion?: boolean;
174
- }
175
- export interface AddToBasketResponse {
176
- store: CartStore;
177
- products: CartProduct[];
178
- summary: CartSummaryLine[];
179
- totalProductCount: number;
180
- totalProductPrice: number;
181
- totalProductPriceDiscounted: number;
182
- totalPrice: number;
183
- deliveryPrice: number;
184
- }
185
- export interface SetShippingAddressRequest {
186
- shippingAddressId: number;
187
- invoiceAddressId: number;
188
- }
189
- export declare function setShippingAddress(request: SetShippingAddressRequest): Promise<void>;
190
- export declare function addToBasket(request: AddToBasketRequest): Promise<AddToBasketResponse>;
191
- export interface CartProductDetails extends CartProduct {
192
- marketPrice: number;
193
- modifierProducts: Array<{
194
- productId: number;
195
- modifierGroupId: number;
196
- name: string;
197
- price: number;
198
- }>;
199
- ingredientExcludes: Array<{
200
- id: number;
201
- name: string;
202
- }>;
203
- }
204
- export interface CartStoreGroup {
205
- store: CartStore;
206
- products: CartProductDetails[];
207
- }
208
- export interface GetBasketResponse {
209
- storeGroups: CartStoreGroup[];
210
- summary: CartSummaryLine[];
211
- totalProductCount: number;
212
- totalProductPrice: number;
213
- totalProductPriceDiscounted: number;
214
- totalPrice: number;
215
- deliveryPrice: number;
216
- isEmpty: boolean;
217
- }
218
- export declare function getBasket(): Promise<GetBasketResponse>;
219
- export declare function removeFromBasket(itemId: string): Promise<GetBasketResponse>;
220
- export declare function clearBasket(): Promise<void>;
221
- export interface SearchProduct {
222
- id: number;
223
- name: string;
224
- description?: string;
225
- price: number;
226
- imageUrl?: string;
227
- }
228
- export interface SearchRestaurant extends Restaurant {
229
- products: SearchProduct[];
230
- warning?: string;
231
- }
232
- export interface SearchRestaurantsResponse {
233
- restaurants: SearchRestaurant[];
234
- totalCount: number;
235
- currentPage: number;
236
- pageSize: number;
237
- hasNextPage: boolean;
238
- searchQuery: string;
239
- }
240
- export interface City {
241
- id: number;
242
- code: string;
243
- name: string;
244
- }
245
- export interface District {
246
- id: number;
247
- name: string;
248
- }
249
- export interface Neighborhood {
250
- id: number;
251
- name: string;
252
- }
253
- export interface CitiesResponse {
254
- cities: City[];
255
- count: number;
256
- }
257
- export interface DistrictsResponse {
258
- districts: District[];
259
- count: number;
260
- cityId: number;
261
- }
262
- export interface NeighborhoodsResponse {
263
- neighborhoods: Neighborhood[];
264
- count: number;
265
- districtId: number;
266
- }
267
- export declare function getCities(): Promise<CitiesResponse>;
268
- export declare function getDistricts(cityId: number): Promise<DistrictsResponse>;
269
- export declare function getNeighborhoods(districtId: number): Promise<NeighborhoodsResponse>;
270
- export interface AddAddressRequest {
271
- name: string;
272
- surname: string;
273
- phone: string;
274
- apartmentNumber?: string;
275
- floor?: string;
276
- doorNumber?: string;
277
- addressName: string;
278
- addressDescription?: string;
279
- addressLine: string;
280
- cityId: number;
281
- districtId: number;
282
- neighborhoodId: number;
283
- latitude: string;
284
- longitude: string;
285
- countryCode?: string;
286
- elevatorAvailable?: boolean;
287
- }
288
- export interface AddAddressResponse {
289
- success: boolean;
290
- address?: Address;
291
- requiresOtp?: boolean;
292
- message: string;
293
- }
294
- export declare function addAddress(request: AddAddressRequest): Promise<AddAddressResponse>;
295
- export interface SavedCard {
296
- cardId: number;
297
- name: string;
298
- maskedCardNumber: string;
299
- cardTypeName: string;
300
- bankName: string;
301
- isDebitCard: boolean;
302
- cvvRequired: boolean;
303
- cardNetwork: string;
304
- }
305
- export interface SavedCardsResponse {
306
- cards: SavedCard[];
307
- hasCards: boolean;
308
- message?: string;
309
- }
310
- export interface CheckoutReadyResponse {
311
- ready: boolean;
312
- store: CartStore;
313
- products: CartProductDetails[];
314
- summary: CartSummaryLine[];
315
- totalPrice: number;
316
- deliveryPrice: number;
317
- warnings: string[];
318
- }
319
- export interface PlaceOrderResponse {
320
- success: boolean;
321
- orderId?: string;
322
- requires3DSecure?: boolean;
323
- redirectUrl?: string;
324
- htmlContent?: string;
325
- message: string;
326
- }
327
- export interface CustomerNoteRequest {
328
- customerNote: string;
329
- noServiceWare: boolean;
330
- contactlessDelivery: boolean;
331
- dontRingBell: boolean;
332
- }
333
- export declare function updateCustomerNote(request: CustomerNoteRequest): Promise<void>;
334
- export declare function getSavedCards(): Promise<SavedCardsResponse>;
335
- export declare function getCheckoutReady(): Promise<CheckoutReadyResponse>;
336
- export declare function placeOrder(cardId: number): Promise<PlaceOrderResponse>;
337
- export interface OrderStatus {
338
- status: string;
339
- statusText: string;
340
- statusColor: string;
341
- }
342
- export interface OrderStore {
343
- id: number;
344
- name: string;
345
- }
346
- export interface OrderPrice {
347
- totalPrice: number;
348
- totalPriceText: string;
349
- refundedPrice: number;
350
- cancelledPrice: number;
351
- totalDeliveryPrice: number;
352
- totalServicePrice: number;
353
- }
354
- export interface OrderProductSummary {
355
- productId: number;
356
- name: string;
357
- imageUrl: string;
358
- }
359
- export interface Order {
360
- id: string;
361
- orderDate: string;
362
- store: OrderStore;
363
- status: OrderStatus;
364
- price: OrderPrice;
365
- productSummary: string;
366
- products: OrderProductSummary[];
367
- isReady: boolean;
368
- }
369
- export interface OrdersResponse {
370
- orders: Order[];
371
- pagination: {
372
- currentPage: number;
373
- pageSize: number;
374
- totalCount: number;
375
- hasNext: boolean;
376
- };
377
- }
378
- export interface OrderDetailProduct {
379
- name: string;
380
- imageUrl: string;
381
- salePrice: number;
382
- salePriceText: string;
383
- quantity: number;
384
- description: string;
385
- }
386
- export interface OrderStatusStep {
387
- status: string;
388
- statusText: string;
389
- }
390
- export interface OrderShipmentItem {
391
- status: OrderStatus;
392
- statusSteps: OrderStatusStep[];
393
- products: OrderDetailProduct[];
394
- }
395
- export interface OrderDetail {
396
- orderId: string;
397
- orderNumber: string;
398
- orderDate: string;
399
- customerNote: string;
400
- store: OrderStore;
401
- eta: string;
402
- deliveredDate: string;
403
- status: OrderStatus;
404
- statusSteps: OrderStatusStep[];
405
- products: OrderDetailProduct[];
406
- price: OrderPrice;
407
- paymentDescription: string;
408
- deliveryAddress: {
409
- name: string;
410
- address: string;
411
- districtCity: string;
412
- phoneNumber: string;
413
- };
414
- }
415
- export declare function getOrders(page?: number): Promise<OrdersResponse>;
416
- export declare function getOrderDetail(orderId: string): Promise<OrderDetail>;
417
- export declare function searchRestaurants(searchQuery: string, latitude: string, longitude: string, page?: number): Promise<SearchRestaurantsResponse>;