pikapikachuchu commited on
Commit
10a90f2
·
verified ·
1 Parent(s): 443be2e

Update app.py

Browse files

Added the gradio MCP server app.

Files changed (1) hide show
  1. app.py +655 -4
app.py CHANGED
@@ -1,7 +1,658 @@
1
  import gradio as gr
 
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import psycopg2
3
+ from psycopg2.extras import RealDictCursor
4
+ import os
5
+ from dotenv import load_dotenv
6
+ from typing import Dict, Any, List, Optional
7
 
8
+ load_dotenv()
 
9
 
10
+ def get_db_connection():
11
+ """Get database connection using environment variables."""
12
+ try:
13
+ conn = psycopg2.connect(
14
+ host=os.getenv("POSTGRES_HOST", "localhost"),
15
+ database=os.getenv("POSTGRES_DB", "erp_db"),
16
+ user=os.getenv("POSTGRES_USER", "postgres"),
17
+ password=os.getenv("POSTGRES_PASSWORD", ""),
18
+ port=os.getenv("POSTGRES_PORT", "5432")
19
+ )
20
+ return conn
21
+ except Exception as e:
22
+ raise Exception(f"Database connection failed: {str(e)}")
23
+
24
+ def execute_query(query: str, params: str = None):
25
+ """
26
+ Execute a custom SQL query on the ERP database.
27
+
28
+ Args:
29
+ query: SQL query to execute
30
+ params: Parameters for parameterized queries (as a comma-separated string)
31
+
32
+ Returns:
33
+ Query results or error message
34
+ """
35
+ try:
36
+ conn = get_db_connection()
37
+ cursor = conn.cursor(cursor_factory=RealDictCursor)
38
+
39
+ # Convert string params to list if provided
40
+ param_list = None
41
+ if params and params.strip():
42
+ param_list = [p.strip() for p in params.split(',')]
43
+
44
+ if param_list:
45
+ cursor.execute(query, param_list)
46
+ else:
47
+ cursor.execute(query)
48
+
49
+ # Check if it's a SELECT query
50
+ if query.strip().upper().startswith('SELECT'):
51
+ results = cursor.fetchall()
52
+ # Convert RealDictRow to regular dict for JSON serialization
53
+ results = [dict(row) for row in results]
54
+ if not results:
55
+ return str({
56
+ "success": True,
57
+ "message": "No results found",
58
+ "results": []
59
+ })
60
+ return str({
61
+ "success": True,
62
+ "message": f"Query returned {len(results)} results",
63
+ "count": len(results),
64
+ "results": results
65
+ })
66
+ else:
67
+ # For INSERT, UPDATE, DELETE queries
68
+ conn.commit()
69
+ return str({
70
+ "success": True,
71
+ "message": f"Query executed successfully",
72
+ "rows_affected": cursor.rowcount
73
+ })
74
+
75
+ except Exception as e:
76
+ return str({
77
+ "success": False,
78
+ "error": str(e)
79
+ })
80
+ finally:
81
+ if 'conn' in locals():
82
+ conn.close()
83
+
84
+ def list_erp_tables():
85
+ """
86
+ List all ERP tables in the database.
87
+
88
+ Returns:
89
+ List of ERP table names
90
+ """
91
+ query = """
92
+ SELECT table_name
93
+ FROM information_schema.tables
94
+ WHERE table_schema = 'public'
95
+ AND table_name LIKE 'erp_%'
96
+ ORDER BY table_name;
97
+ """
98
+
99
+ try:
100
+ conn = get_db_connection()
101
+ cursor = conn.cursor(cursor_factory=RealDictCursor)
102
+ cursor.execute(query)
103
+ results = cursor.fetchall()
104
+
105
+ table_names = [row['table_name'] for row in results]
106
+ if not table_names:
107
+ return str({
108
+ "success": False,
109
+ "message": "No ERP tables found",
110
+ "tables": []
111
+ })
112
+ return str({
113
+ "success": True,
114
+ "message": f"Found {len(table_names)} tables",
115
+ "count": len(table_names),
116
+ "tables": table_names
117
+ })
118
+
119
+ except Exception as e:
120
+ return str({
121
+ "success": False,
122
+ "error": str(e)
123
+ })
124
+ finally:
125
+ if 'conn' in locals():
126
+ conn.close()
127
+
128
+ def get_order_status(order_id: int):
129
+ """
130
+ Get the status of an order by order ID.
131
+
132
+ Args:
133
+ order_id: The ID of the order to check
134
+
135
+ Returns:
136
+ Order status information including shipping and destination countries
137
+ """
138
+ query = """
139
+ SELECT o.*, c.name as customer_name, c.email as customer_email,
140
+ o.shipping_country, o.destination_country
141
+ FROM erp_orders o
142
+ JOIN erp_customers c ON o.customer_id = c.customer_id
143
+ WHERE o.order_id = %s;
144
+ """
145
+
146
+ try:
147
+ conn = get_db_connection()
148
+ cursor = conn.cursor(cursor_factory=RealDictCursor)
149
+ cursor.execute(query, [order_id])
150
+ order = cursor.fetchone()
151
+
152
+ if not order:
153
+ return str({
154
+ "success": False,
155
+ "message": f"Order with ID {order_id} not found"
156
+ })
157
+
158
+ # Get order items
159
+ items_query = """
160
+ SELECT oi.order_item_id, oi.order_id, oi.product_id, oi.quantity, oi.unit_price, oi.subtotal,
161
+ p.product_name, p.sku
162
+ FROM erp_order_items oi
163
+ JOIN erp_products p ON oi.product_id = p.product_id
164
+ WHERE oi.order_id = %s;
165
+ """
166
+ cursor.execute(items_query, [order_id])
167
+ items = cursor.fetchall()
168
+
169
+ # Get order history
170
+ history_query = """
171
+ SELECT * FROM erp_order_history
172
+ WHERE order_id = %s
173
+ ORDER BY timestamp DESC;
174
+ """
175
+ cursor.execute(history_query, [order_id])
176
+ history = cursor.fetchall()
177
+
178
+ order_dict = dict(order)
179
+ items_list = [dict(item) for item in items]
180
+ history_list = [dict(entry) for entry in history]
181
+
182
+ # Return JSON formatted response
183
+ return str({
184
+ "success": True,
185
+ "order": {
186
+ "order_id": order_id,
187
+ "customer": {
188
+ "customer_id": order_dict['customer_id'],
189
+ "name": order_dict['customer_name'],
190
+ "email": order_dict['customer_email']
191
+ },
192
+ "status": order_dict['status'],
193
+ "shipping_address": order_dict.get('shipping_address', 'N/A'),
194
+ "shipping_country": order_dict.get('shipping_country', 'N/A'),
195
+ "destination_country": order_dict.get('destination_country', 'N/A'),
196
+ "items": items_list,
197
+ "history": history_list
198
+ }
199
+ })
200
+
201
+ except Exception as e:
202
+ return str({
203
+ "success": False,
204
+ "error": str(e)
205
+ })
206
+ finally:
207
+ if 'conn' in locals():
208
+ conn.close()
209
+
210
+ def place_new_order(
211
+ customer_id: int,
212
+ product_ids: str,
213
+ quantities: str,
214
+ shipping_address: str,
215
+ shipping_country: str,
216
+ destination_country: str,
217
+ previous_order_id: int = None
218
+ ):
219
+ """
220
+ Place a new order in the ERP system.
221
+
222
+ Args:
223
+ customer_id: ID of the customer placing the order
224
+ product_ids: Comma-separated list of product IDs
225
+ quantities: Comma-separated list of quantities corresponding to product IDs
226
+ shipping_address: Shipping address for the order
227
+ shipping_country: Country where the order will be shipped from
228
+ destination_country: Country where the order will be delivered to
229
+ previous_order_id: ID of a previous order this is replacing (optional)
230
+
231
+ Returns:
232
+ New order information
233
+ """
234
+ try:
235
+ # Parse product IDs and quantities
236
+ product_id_list = [int(pid.strip()) for pid in product_ids.split(',')]
237
+ quantity_list = [int(qty.strip()) for qty in quantities.split(',')]
238
+
239
+ if len(product_id_list) != len(quantity_list):
240
+ return str({
241
+ "success": False,
242
+ "error": "Number of product IDs must match number of quantities"
243
+ })
244
+
245
+ # Create items list
246
+ items = [
247
+ {"product_id": pid, "quantity": qty}
248
+ for pid, qty in zip(product_id_list, quantity_list)
249
+ ]
250
+
251
+ conn = get_db_connection()
252
+ cursor = conn.cursor(cursor_factory=RealDictCursor)
253
+
254
+ # Calculate total amount based on the total items and their prices
255
+ total_amount = 0
256
+ for item in items:
257
+ product_query = "SELECT price FROM erp_products WHERE product_id = %s;"
258
+ cursor.execute(product_query, [item['product_id']])
259
+ product = cursor.fetchone()
260
+ if not product:
261
+ return str({
262
+ "success": False,
263
+ "error": f"Product with ID {item['product_id']} not found"
264
+ })
265
+ total_amount += product['price'] * item['quantity']
266
+
267
+ # Insert new order into the erp_orders table for the customer
268
+ order_query = """
269
+ INSERT INTO erp_orders (
270
+ customer_id, order_date, total_amount, status,
271
+ shipping_address, shipping_country, destination_country, previous_order_id,
272
+ estimated_delivery, payment_status
273
+ ) VALUES (
274
+ %s, CURRENT_DATE, %s, 'Processing',
275
+ %s, %s, %s, %s,
276
+ CURRENT_DATE + INTERVAL '7 days', 'Pending'
277
+ ) RETURNING order_id;
278
+ """
279
+ cursor.execute(order_query, [
280
+ customer_id, total_amount, shipping_address, shipping_country, destination_country, previous_order_id
281
+ ])
282
+ new_order_id = cursor.fetchone()['order_id']
283
+
284
+ # Insert order items into erp_order_items table for the new order
285
+ for item in items:
286
+ # Get product price
287
+ cursor.execute(product_query, [item['product_id']])
288
+ product = cursor.fetchone()
289
+ unit_price = product['price']
290
+ subtotal = unit_price * item['quantity']
291
+
292
+ item_query = """
293
+ INSERT INTO erp_order_items (
294
+ order_id, product_id, quantity, unit_price, subtotal
295
+ ) VALUES (
296
+ %s, %s, %s, %s, %s
297
+ );
298
+ """
299
+ cursor.execute(item_query, [
300
+ new_order_id, item['product_id'], item['quantity'],
301
+ unit_price, subtotal
302
+ ])
303
+
304
+ # Update product stock
305
+ update_stock_query = """
306
+ UPDATE erp_products
307
+ SET stock_quantity = stock_quantity - %s
308
+ WHERE product_id = %s;
309
+ """
310
+ cursor.execute(update_stock_query, [item['quantity'], item['product_id']])
311
+
312
+ # Create order history entry into the erp_order_history for the new order
313
+ history_query = """
314
+ INSERT INTO erp_order_history (
315
+ order_id, timestamp, status_change, notes, updated_by
316
+ ) VALUES (
317
+ %s, CURRENT_TIMESTAMP, 'Order Created', 'New order placed', 'System'
318
+ );
319
+ """
320
+ cursor.execute(history_query, [new_order_id])
321
+
322
+ # If this is a replacement order, add a note to the previous order
323
+ if previous_order_id:
324
+ prev_order_note_query = """
325
+ INSERT INTO erp_order_history (
326
+ order_id, timestamp, status_change, notes, updated_by
327
+ ) VALUES (
328
+ %s, CURRENT_TIMESTAMP, 'Replaced', 'Order replaced by order #%s', 'System'
329
+ );
330
+ """
331
+ cursor.execute(prev_order_note_query, [previous_order_id, new_order_id])
332
+
333
+ # Generate invoice for the new order
334
+ invoice_query = """
335
+ INSERT INTO erp_invoices (
336
+ order_id, invoice_date, amount, payment_terms, due_date, is_paid, invoice_number
337
+ ) VALUES (
338
+ %s, CURRENT_DATE, %s, 'Net 30', CURRENT_DATE + INTERVAL '30 days', FALSE, 'INV-' || %s
339
+ ) RETURNING invoice_id;
340
+ """
341
+ cursor.execute(invoice_query, [new_order_id, total_amount, new_order_id])
342
+ invoice_id = cursor.fetchone()['invoice_id']
343
+
344
+ conn.commit()
345
+
346
+ # Get the complete new order details
347
+ cursor.execute("SELECT * FROM erp_orders WHERE order_id = %s;", [new_order_id])
348
+ order = cursor.fetchone()
349
+
350
+ order_dict = dict(order)
351
+
352
+ # Return JSON formatted response
353
+ return str({
354
+ "success": True,
355
+ "order": {
356
+ "order_id": new_order_id,
357
+ "invoice_id": invoice_id,
358
+ "total_amount": float(total_amount),
359
+ "status": order_dict['status'],
360
+ "estimated_delivery": str(order_dict['estimated_delivery']) if order_dict['estimated_delivery'] else None,
361
+ "customer_id": customer_id,
362
+ "shipping_address": shipping_address,
363
+ "shipping_country": shipping_country,
364
+ "destination_country": destination_country,
365
+ "previous_order_id": previous_order_id,
366
+ "items": [{"product_id": pid, "quantity": qty} for pid, qty in zip(product_id_list, quantity_list)]
367
+ }
368
+ })
369
+
370
+ except Exception as e:
371
+ if 'conn' in locals():
372
+ conn.rollback()
373
+ return str({
374
+ "success": False,
375
+ "error": str(e)
376
+ })
377
+ finally:
378
+ if 'conn' in locals():
379
+ conn.close()
380
+
381
+ def cancel_order(order_id: int, reason: str):
382
+ """
383
+ Cancel an existing order in the ERP system.
384
+
385
+ Args:
386
+ order_id: ID of the order to cancel
387
+ reason: Reason for cancellation
388
+
389
+ Returns:
390
+ Result of the cancellation operation
391
+ """
392
+ try:
393
+ conn = get_db_connection()
394
+ cursor = conn.cursor(cursor_factory=RealDictCursor)
395
+
396
+ # Check if order exists and can be cancelled
397
+ check_query = """
398
+ SELECT status, customer_id FROM erp_orders WHERE order_id = %s;
399
+ """
400
+ cursor.execute(check_query, [order_id])
401
+ order = cursor.fetchone()
402
+
403
+ if not order:
404
+ return str({
405
+ "success": False,
406
+ "error": f"Order with ID {order_id} not found"
407
+ })
408
+
409
+ if order['status'] in ['Delivered', 'Cancelled']:
410
+ return str({
411
+ "success": False,
412
+ "error": f"Cannot cancel order with status '{order['status']}'"
413
+ })
414
+
415
+ # Get order items to restore stock
416
+ items_query = """
417
+ SELECT product_id, quantity FROM erp_order_items WHERE order_id = %s;
418
+ """
419
+ cursor.execute(items_query, [order_id])
420
+ items = cursor.fetchall()
421
+
422
+ # Update order status to Cancelled
423
+ update_query = """
424
+ UPDATE erp_orders SET status = 'Cancelled', payment_status = 'Cancelled'
425
+ WHERE order_id = %s;
426
+ """
427
+ cursor.execute(update_query, [order_id])
428
+
429
+ # Add entry to order history
430
+ history_query = """
431
+ INSERT INTO erp_order_history (
432
+ order_id, timestamp, status_change, notes, updated_by
433
+ ) VALUES (
434
+ %s, CURRENT_TIMESTAMP, 'Cancelled', %s, 'System'
435
+ );
436
+ """
437
+ cursor.execute(history_query, [order_id, f"Order cancelled: {reason}"])
438
+
439
+ # Restore product stock quantities
440
+ for item in items:
441
+ restore_stock_query = """
442
+ UPDATE erp_products
443
+ SET stock_quantity = stock_quantity + %s
444
+ WHERE product_id = %s;
445
+ """
446
+ cursor.execute(restore_stock_query, [item['quantity'], item['product_id']])
447
+
448
+ # Update invoice if exists
449
+ invoice_query = """
450
+ UPDATE erp_invoices
451
+ SET is_paid = FALSE
452
+ WHERE order_id = %s;
453
+ """
454
+ cursor.execute(invoice_query, [order_id])
455
+
456
+ conn.commit()
457
+
458
+ return str({
459
+ "success": True,
460
+ "message": f"Order #{order_id} has been successfully cancelled",
461
+ "order_id": order_id,
462
+ "reason": reason,
463
+ "items_restored": len(items)
464
+ })
465
+
466
+ except Exception as e:
467
+ if 'conn' in locals():
468
+ conn.rollback()
469
+ return str({
470
+ "success": False,
471
+ "error": str(e)
472
+ })
473
+ finally:
474
+ if 'conn' in locals():
475
+ conn.close()
476
+
477
+ def get_invoice_details(invoice_id: int = None, order_id: int = None):
478
+ """
479
+ Get invoice details by invoice ID or order ID.
480
+
481
+ Args:
482
+ invoice_id: ID of the invoice (optional)
483
+ order_id: ID of the order (optional)
484
+
485
+ Returns:
486
+ Invoice details including customer and order information
487
+ """
488
+ if not invoice_id and not order_id:
489
+ return str({
490
+ "success": False,
491
+ "error": "Either invoice_id or order_id must be provided"
492
+ })
493
+
494
+ try:
495
+ conn = get_db_connection()
496
+ cursor = conn.cursor(cursor_factory=RealDictCursor)
497
+
498
+ if invoice_id:
499
+ query = """
500
+ SELECT i.*, o.order_date, o.status as order_status,
501
+ c.name as customer_name, c.email as customer_email, c.address as customer_address
502
+ FROM erp_invoices i
503
+ JOIN erp_orders o ON i.order_id = o.order_id
504
+ JOIN erp_customers c ON o.customer_id = c.customer_id
505
+ WHERE i.invoice_id = %s;
506
+ """
507
+ cursor.execute(query, [invoice_id])
508
+ else:
509
+ query = """
510
+ SELECT i.*, o.order_date, o.status as order_status,
511
+ c.name as customer_name, c.email as customer_email, c.address as customer_address
512
+ FROM erp_invoices i
513
+ JOIN erp_orders o ON i.order_id = o.order_id
514
+ JOIN erp_customers c ON o.customer_id = c.customer_id
515
+ WHERE i.order_id = %s;
516
+ """
517
+ cursor.execute(query, [order_id])
518
+
519
+ invoice = cursor.fetchone()
520
+
521
+ if not invoice:
522
+ return str({
523
+ "success": False,
524
+ "error": f"Invoice not found for the provided {'invoice_id' if invoice_id else 'order_id'}"
525
+ })
526
+
527
+ # Get order items
528
+ items_query = """
529
+ SELECT oi.*, p.product_name, p.sku
530
+ FROM erp_order_items oi
531
+ JOIN erp_products p ON oi.product_id = p.product_id
532
+ WHERE oi.order_id = %s;
533
+ """
534
+ cursor.execute(items_query, [invoice['order_id']])
535
+ items = cursor.fetchall()
536
+
537
+ invoice_dict = dict(invoice)
538
+ items_list = [dict(item) for item in items]
539
+
540
+ # Return JSON formatted response
541
+ return str({
542
+ "success": True,
543
+ "invoice": {
544
+ "invoice_id": invoice_dict['invoice_id'],
545
+ "invoice_number": invoice_dict.get('invoice_number', ''),
546
+ "order_id": invoice_dict['order_id'],
547
+ "order_date": str(invoice_dict['order_date']) if invoice_dict['order_date'] else None,
548
+ "order_status": invoice_dict['order_status'],
549
+ "amount": float(invoice_dict['amount']),
550
+ "due_date": str(invoice_dict['due_date']) if invoice_dict['due_date'] else None,
551
+ "payment_status": "Paid" if invoice_dict['is_paid'] else "Unpaid",
552
+ "customer": {
553
+ "name": invoice_dict['customer_name'],
554
+ "email": invoice_dict['customer_email'],
555
+ "address": invoice_dict['customer_address']
556
+ },
557
+ "items": items_list
558
+ }
559
+ })
560
+
561
+ except Exception as e:
562
+ return str({
563
+ "success": False,
564
+ "error": str(e)
565
+ })
566
+ finally:
567
+ if 'conn' in locals():
568
+ conn.close()
569
+
570
+ # Create Gradio interfaces for each function
571
+ execute_query_interface = gr.Interface(
572
+ fn=execute_query,
573
+ inputs=[
574
+ gr.Textbox(lines=5, label="SQL Query"),
575
+ gr.Textbox(label="Parameters (comma-separated)", placeholder="Optional")
576
+ ],
577
+ outputs=gr.Textbox(lines=10),
578
+ title="Execute SQL Query",
579
+ description="Execute a custom SQL query on the ERP database"
580
+ )
581
+
582
+ list_tables_interface = gr.Interface(
583
+ fn=list_erp_tables,
584
+ inputs=[],
585
+ outputs=gr.Textbox(lines=10),
586
+ title="List ERP Tables",
587
+ description="List all ERP tables in the database"
588
+ )
589
+
590
+ order_status_interface = gr.Interface(
591
+ fn=get_order_status,
592
+ inputs=gr.Number(label="Order ID", precision=0),
593
+ outputs=gr.Textbox(lines=15),
594
+ title="Get Order Status",
595
+ description="Get the status of an order by order ID"
596
+ )
597
+
598
+ place_order_interface = gr.Interface(
599
+ fn=place_new_order,
600
+ inputs=[
601
+ gr.Number(label="Customer ID", precision=0),
602
+ gr.Textbox(label="Product IDs (comma-separated)", placeholder="1, 2, 3"),
603
+ gr.Textbox(label="Quantities (comma-separated)", placeholder="2, 1, 3"),
604
+ gr.Textbox(label="Shipping Address"),
605
+ gr.Textbox(label="Shipping Country"),
606
+ gr.Textbox(label="Destination Country"),
607
+ gr.Number(label="Previous Order ID (optional)", precision=0)
608
+ ],
609
+ outputs=gr.Textbox(lines=10),
610
+ title="Place New Order",
611
+ description="Place a new order in the ERP system"
612
+ )
613
+
614
+ cancel_order_interface = gr.Interface(
615
+ fn=cancel_order,
616
+ inputs=[
617
+ gr.Number(label="Order ID", precision=0),
618
+ gr.Textbox(label="Reason for Cancellation")
619
+ ],
620
+ outputs=gr.Textbox(lines=5),
621
+ title="Cancel Order",
622
+ description="Cancel an existing order in the ERP system"
623
+ )
624
+
625
+ invoice_details_interface = gr.Interface(
626
+ fn=get_invoice_details,
627
+ inputs=[
628
+ gr.Number(label="Invoice ID (optional)", precision=0),
629
+ gr.Number(label="Order ID (optional)", precision=0)
630
+ ],
631
+ outputs=gr.Textbox(lines=15),
632
+ title="Get Invoice Details",
633
+ description="Get invoice details by invoice ID or order ID"
634
+ )
635
+
636
+ # Create a Gradio TabItem for each interface
637
+ demo = gr.TabbedInterface(
638
+ [
639
+ execute_query_interface,
640
+ list_tables_interface,
641
+ order_status_interface,
642
+ place_order_interface,
643
+ cancel_order_interface,
644
+ invoice_details_interface
645
+ ],
646
+ [
647
+ "Execute Query",
648
+ "List Tables",
649
+ "Order Status",
650
+ "Place Order",
651
+ "Cancel Order",
652
+ "Invoice Details"
653
+ ],
654
+ title="ERP System Tools"
655
+ )
656
+
657
+ # Launch the demo with MCP server enabled
658
+ demo.launch(mcp_server=True, server_port=7090)