Przeglądaj źródła

feat(mcp): reformat tool responses to plain text for LLM consumption

- Updated Products, Orders, and Customers responses to plain text format
- Products: Id, Name, SKU, Price, Status, Tags, Description
- Orders: Id (#orderNumber), Customer (name phone email), Status, Total, Items
- Customers: Name, Email, Phone, Total Orders
- Applied consistently across mcp-shopify, mcp-woocommerce, mcp-shoprenter
- Removed JSON wrapper objects from responses for better LLM parsing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fszontagh 4 miesięcy temu
rodzic
commit
6cfc970519

+ 110 - 109
supabase/functions/mcp-shopify/index.ts

@@ -281,6 +281,26 @@ function formatOrderForLlm(order: ShopifyOrder): LlmOrder {
   };
   };
 }
 }
 
 
+/**
+ * Format a product as plain text for LLM consumption
+ */
+function formatProductAsPlainText(p: LlmProduct): string {
+  let text = `Id: ${p.id}\nName: ${p.name}`;
+  if (p.sku) text += `\nSKU: ${p.sku}`;
+  if (p.price) text += `\nPrice: ${p.price}${p.currency ? ' ' + p.currency : ''}`;
+  if (p.status) text += `\nStatus: ${p.status}`;
+  if (p.tags) {
+    const tagsStr = Array.isArray(p.tags) ? p.tags.join(', ') : p.tags;
+    text += `\nTags: ${tagsStr}`;
+  }
+  if (p.description) {
+    // Strip HTML tags from description
+    const cleanDesc = p.description.replace(/<[^>]*>/g, '').trim();
+    if (cleanDesc) text += `\nDescription:\n${cleanDesc}`;
+  }
+  return text;
+}
+
 /**
 /**
  * Handle shopify_get_products tool
  * Handle shopify_get_products tool
  */
  */
@@ -350,19 +370,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
         tags: p.tags || undefined
         tags: p.tags || undefined
       }));
       }));
 
 
-      const cleanedProducts = cleanResponseData(formattedProducts);
+      // Format as plain text
+      const plainTextProducts = formattedProducts.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            count: products.length,
-            limit: actualLimit,
-            source: 'api_direct',
-            access_mode: 'api_only',
-            notice: createApiOnlyNotice('products'),
-            products: cleanedProducts
-          })
+          text: `Products (${products.length} results):\n\n${plainTextProducts}`
         }]
         }]
       };
       };
     }
     }
@@ -379,18 +393,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
           actualLimit
           actualLimit
         );
         );
 
 
-        const cleanedProducts = cleanResponseData(products);
+        // Format as plain text
+        const plainTextProducts = products.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              count: products.length,
-              limit: actualLimit,
-              source: 'qdrant',
-              access_mode: 'sync',
-              products: cleanedProducts
-            })
+            text: `Products (${products.length} results):\n\n${plainTextProducts}`
           }]
           }]
         };
         };
       } else {
       } else {
@@ -410,7 +419,7 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({ error: `Failed to fetch products: ${cacheError.message}` })
+            text: `Error: Failed to fetch products: ${cacheError.message}`
           }],
           }],
           isError: true
           isError: true
         };
         };
@@ -446,18 +455,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
         tags: p.tags || undefined
         tags: p.tags || undefined
       }));
       }));
 
 
-      const cleanedProducts = cleanResponseData(formattedProducts);
+      // Format as plain text
+      const plainTextProducts = formattedProducts.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            count: formattedProducts.length,
-            limit: actualLimit,
-            source: 'sql_cache',
-            access_mode: 'sync',
-            products: cleanedProducts
-          })
+          text: `Products (${formattedProducts.length} results):\n\n${plainTextProducts}`
         }]
         }]
       };
       };
       }
       }
@@ -467,7 +471,7 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: 'Invalid access policy configuration' })
+        text: 'Error: Invalid access policy configuration'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -475,13 +479,30 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: `Failed to fetch products: ${error instanceof Error ? error.message : 'Unknown error'}` })
+        text: `Error: Failed to fetch products: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
   }
   }
 }
 }
 
 
+/**
+ * Format an order as plain text for LLM consumption
+ */
+function formatOrderAsPlainText(o: LlmOrder): string {
+  let text = `Id: #${o.orderNumber}`;
+  text += `\nCustomer: ${o.customer.name || ''}${o.customer.phone ? ' ' + o.customer.phone : ''}${o.customer.email ? ' ' + o.customer.email : ''}`;
+  text += `\nStatus: ${o.status}`;
+  text += `\nTotal: ${o.total}${o.currency ? ' ' + o.currency : ''}`;
+  if (o.items && o.items.length > 0) {
+    text += '\nItems:';
+    for (const item of o.items) {
+      text += `\n    - Name: ${item.name} Quantity: ${item.quantity} Price: ${item.price}${o.currency ? ' ' + o.currency : ''}`;
+    }
+  }
+  return text;
+}
+
 /**
 /**
  * Handle shopify_get_order tool
  * Handle shopify_get_order tool
  */
  */
@@ -493,9 +514,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'Either order_id or order_name parameter is required'
-        })
+        text: 'Error: Either order_id or order_name parameter is required'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -528,9 +547,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            error: `Order not found: ${order_id || order_name}`
-          })
+          text: `Error: Order not found: ${order_id || order_name}`
         }],
         }],
         isError: true
         isError: true
       };
       };
@@ -538,16 +555,12 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
 
 
     // Format for LLM
     // Format for LLM
     const formattedOrder = formatOrderForLlm(order);
     const formattedOrder = formatOrderForLlm(order);
-    const cleanedOrder = cleanResponseData(formattedOrder);
 
 
+    // Format as plain text
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          access_mode: policy,
-          notice: isApiOnlyMode(policy) ? createApiOnlyNotice('orders') : undefined,
-          order: cleanedOrder
-        })
+        text: formatOrderAsPlainText(formattedOrder)
       }]
       }]
     };
     };
   } catch (error) {
   } catch (error) {
@@ -555,9 +568,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch order: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch order: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -586,9 +597,7 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'At least one filter is required: created_at_min, created_at_max, updated_at_min, updated_at_max, customer_email, or customer_name'
-        })
+        text: 'Error: At least one filter is required: created_at_min, created_at_max, updated_at_min, updated_at_max, customer_email, or customer_name'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -625,28 +634,14 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
 
 
     // Format for LLM
     // Format for LLM
     const formattedOrders = limitedOrders.map(formatOrderForLlm);
     const formattedOrders = limitedOrders.map(formatOrderForLlm);
-    const cleanedOrders = cleanResponseData(formattedOrders);
+
+    // Format as plain text
+    const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
 
 
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          count: formattedOrders.length,
-          limit: actualLimit,
-          total_available: allOrders.length,
-          access_mode: policy,
-          notice: isApiOnlyMode(policy) ? createApiOnlyNotice('orders') : undefined,
-          filters_applied: {
-            created_at_min,
-            created_at_max,
-            updated_at_min,
-            updated_at_max,
-            customer_email,
-            customer_name,
-            status
-          },
-          orders: cleanedOrders
-        })
+        text: `Orders (${formattedOrders.length} results):\n\n${plainTextOrders}`
       }]
       }]
     };
     };
   } catch (error) {
   } catch (error) {
@@ -654,15 +649,24 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch orders: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch orders: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
   }
   }
 }
 }
 
 
+/**
+ * Format a customer as plain text for LLM consumption
+ */
+function formatCustomerAsPlainText(c: LlmCustomer): string {
+  let text = `Name: ${c.name}`;
+  text += `\nEmail: ${c.email}`;
+  if (c.phone) text += `\nPhone: ${c.phone}`;
+  if (c.ordersCount !== undefined) text += `\nTotal Orders: ${c.ordersCount}`;
+  return text;
+}
+
 /**
 /**
  * Handle shopify_get_customer tool (replaces list_customers)
  * Handle shopify_get_customer tool (replaces list_customers)
  */
  */
@@ -674,9 +678,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'Email parameter is required'
-        })
+        text: 'Error: Email parameter is required'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -699,9 +701,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            error: `No customer found with email: ${email}`
-          })
+          text: `Error: No customer found with email: ${email}`
         }],
         }],
         isError: true
         isError: true
       };
       };
@@ -709,16 +709,12 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
 
 
     // Return only the first customer
     // Return only the first customer
     const customer = formatCustomerForLlm(customers[0]);
     const customer = formatCustomerForLlm(customers[0]);
-    const cleanedCustomer = cleanResponseData(customer);
 
 
+    // Format as plain text
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          access_mode: policy,
-          notice: isApiOnlyMode(policy) ? createApiOnlyNotice('customers') : undefined,
-          customer: cleanedCustomer
-        })
+        text: formatCustomerAsPlainText(customer)
       }]
       }]
     };
     };
   } catch (error) {
   } catch (error) {
@@ -726,9 +722,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch customer: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch customer: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -778,22 +772,19 @@ async function handleSearchCustomContent(args: Record<string, any>): Promise<Too
       };
       };
     }
     }
 
 
+    // Format as plain text for LLM consumption
+    const plainTextResults = results.map(r => {
+      let text = `Title: ${r.title}\nContent:\n${r.excerpt}`;
+      if (r.pageCount) {
+        text += `\nNumber of pages: ${r.pageCount}`;
+      }
+      return text;
+    }).join('\n\n---\n\n');
+
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          results: results.map(r => ({
-            id: r.id,
-            title: r.title,
-            content_type: r.contentType,
-            excerpt: r.excerpt,
-            chunk_info: `Chunk ${r.chunkIndex + 1} of ${r.totalChunks}`,
-            relevance_score: Math.round(r.relevanceScore * 100) / 100,
-            original_filename: r.originalFilename,
-            page_count: r.pageCount
-          })),
-          total: results.length
-        })
+        text: plainTextResults || 'No matching content found.'
       }],
       }],
       isError: false
       isError: false
     };
     };
@@ -822,22 +813,32 @@ async function handleListCustomContents(args: Record<string, any>): Promise<Tool
     // Filter to only enabled content for display
     // Filter to only enabled content for display
     const enabledContents = contents.filter(c => c.isEnabled);
     const enabledContents = contents.filter(c => c.isEnabled);
 
 
+    if (enabledContents.length === 0) {
+      return {
+        content: [{
+          type: 'text',
+          text: 'No custom content available for this store.'
+        }],
+        isError: false
+      };
+    }
+
+    // Format as plain text list
+    const plainTextList = enabledContents.map(c => {
+      let text = `Title: ${c.title}\nType: ${c.contentType === 'pdf_upload' ? 'PDF' : 'Text Entry'}`;
+      if (c.originalFilename) {
+        text += `\nFilename: ${c.originalFilename}`;
+      }
+      if (c.pageCount) {
+        text += `\nPages: ${c.pageCount}`;
+      }
+      return text;
+    }).join('\n\n---\n\n');
+
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          total: enabledContents.length,
-          contents: enabledContents.map(c => ({
-            id: c.id,
-            title: c.title,
-            content_type: c.contentType,
-            original_filename: c.originalFilename,
-            page_count: c.pageCount,
-            chunk_count: c.chunkCount,
-            sync_status: c.syncStatus,
-            created_at: c.createdAt
-          }))
-        })
+        text: `Available custom content (${enabledContents.length} items):\n\n${plainTextList}`
       }],
       }],
       isError: false
       isError: false
     };
     };
@@ -846,7 +847,7 @@ async function handleListCustomContents(args: Record<string, any>): Promise<Tool
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: `Failed to list custom contents: ${error instanceof Error ? error.message : 'Unknown error'}` })
+        text: `Failed to list custom contents: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };

+ 137 - 184
supabase/functions/mcp-shoprenter/index.ts

@@ -329,6 +329,66 @@ function formatOrderForLlm(order: any): any {
   return formattedOrder;
   return formattedOrder;
 }
 }
 
 
+/**
+ * Format a product as plain text for LLM consumption
+ */
+function formatProductAsPlainText(p: LlmProduct): string {
+  let text = `Id: ${p.id}\nName: ${p.name}`;
+  if (p.sku) text += `\nSKU: ${p.sku}`;
+  if (p.price) text += `\nPrice: ${p.price}${p.currency ? ' ' + p.currency : ''}`;
+  if (p.status) text += `\nStatus: ${p.status}`;
+  if (p.tags) {
+    const tagsStr = Array.isArray(p.tags) ? p.tags.join(', ') : p.tags;
+    text += `\nTags: ${tagsStr}`;
+  }
+  if (p.description) {
+    // Strip HTML tags from description
+    const cleanDesc = p.description.replace(/<[^>]*>/g, '').trim();
+    if (cleanDesc) text += `\nDescription:\n${cleanDesc}`;
+  }
+  return text;
+}
+
+/**
+ * Format an order as plain text for LLM consumption
+ */
+function formatOrderAsPlainText(o: any): string {
+  const orderNum = o.orderNumber || o.innerId || o.id;
+  const customerName = `${o.firstname || ''} ${o.lastname || ''}`.trim() || (o.customer?.name || '');
+  const phone = o.phone || (o.customer?.phone || '');
+  const email = o.email || (o.customer?.email || '');
+
+  let text = `Id: #${orderNum}`;
+  text += `\nCustomer: ${customerName}${phone ? ' ' + phone : ''}${email ? ' ' + email : ''}`;
+  text += `\nStatus: ${o.status || 'unknown'}`;
+
+  const currency = o.currency?.code || o.currency || '';
+  text += `\nTotal: ${o.total || '0'}${currency ? ' ' + currency : ''}`;
+
+  const items = o.orderProducts || o.items || [];
+  if (items.length > 0) {
+    text += '\nItems:';
+    for (const item of items) {
+      const itemName = item.name || item.title || 'Unknown';
+      const qty = item.stock1 || item.quantity || 1;
+      const price = item.price || item.total || '0';
+      text += `\n    - Name: ${itemName} Quantity: ${qty} Price: ${price}${currency ? ' ' + currency : ''}`;
+    }
+  }
+  return text;
+}
+
+/**
+ * Format a customer as plain text for LLM consumption
+ */
+function formatCustomerAsPlainText(c: LlmCustomer): string {
+  let text = `Name: ${c.name}`;
+  text += `\nEmail: ${c.email}`;
+  if (c.phone) text += `\nPhone: ${c.phone}`;
+  if (c.ordersCount !== undefined) text += `\nTotal Orders: ${c.ordersCount}`;
+  return text;
+}
+
 /**
 /**
  * Handle shoprenter_get_products tool
  * Handle shoprenter_get_products tool
  */
  */
@@ -397,19 +457,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
         tags: p.tags || undefined
         tags: p.tags || undefined
       }));
       }));
 
 
-      const cleanedProducts = cleanResponseData(formattedProducts);
+      // Format as plain text
+      const plainTextProducts = formattedProducts.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            count: products.length,
-            limit: actualLimit,
-            source: 'api_direct',
-            access_mode: 'api_only',
-            notice: createApiOnlyNotice('products'),
-            products: cleanedProducts
-          })
+          text: `Products (${products.length} results):\n\n${plainTextProducts}`
         }]
         }]
       };
       };
     }
     }
@@ -430,19 +484,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
           actualLimit
           actualLimit
         );
         );
 
 
-        // Clean response data
-        const cleanedProducts = cleanResponseData(products);
+        // Format as plain text
+        const plainTextProducts = products.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              count: products.length,
-              limit: actualLimit,
-              source: 'qdrant',
-              access_mode: 'sync',
-              products: cleanedProducts
-            })
+            text: `Products (${products.length} results):\n\n${plainTextProducts}`
           }]
           }]
         };
         };
       } else {
       } else {
@@ -472,9 +520,7 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              error: `Failed to fetch products from cache: ${cacheError.message}`
-            })
+            text: `Error: Failed to fetch products from cache: ${cacheError.message}`
           }],
           }],
           isError: true
           isError: true
         };
         };
@@ -518,19 +564,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
         tags: p.tags || undefined
         tags: p.tags || undefined
       }));
       }));
 
 
-        // Clean response data
-        const cleanedProducts = cleanResponseData(formattedProducts);
+        // Format as plain text
+        const plainTextProducts = formattedProducts.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              count: formattedProducts.length,
-              limit: actualLimit,
-              source: 'sql_cache',
-              access_mode: 'sync',
-              products: cleanedProducts
-            })
+            text: `Products (${formattedProducts.length} results):\n\n${plainTextProducts}`
           }]
           }]
         };
         };
       }
       }
@@ -540,7 +580,7 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: 'Invalid access policy configuration' })
+        text: 'Error: Invalid access policy configuration'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -549,9 +589,7 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch products: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch products: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -599,9 +637,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'order_id parameter is required'
-        })
+        text: 'Error: order_id parameter is required'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -634,9 +670,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              error: `No order found with order number: ${order_id}`
-            })
+            text: `Error: No order found with order number: ${order_id}`
           }],
           }],
           isError: true
           isError: true
         };
         };
@@ -647,18 +681,11 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
       // Format for LLM
       // Format for LLM
       const formattedOrder = formatOrderForLlm(orders[0]);
       const formattedOrder = formatOrderForLlm(orders[0]);
 
 
-      // Clean response data
-      const cleanedOrder = cleanResponseData(formattedOrder);
-
+      // Format as plain text
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            source: isApiOnlyMode(policy) ? 'api_direct' : 'api',
-            access_mode: policy,
-            notice: isApiOnlyMode(policy) ? createApiOnlyNotice('orders') : undefined,
-            order: cleanedOrder
-          })
+          text: formatOrderAsPlainText(formattedOrder)
         }]
         }]
       };
       };
     }
     }
@@ -687,25 +714,17 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
           return {
           return {
             content: [{
             content: [{
               type: 'text',
               type: 'text',
-              text: JSON.stringify({
-                error: `No order found with order number: ${order_id}`
-              })
+              text: `Error: No order found with order number: ${order_id}`
             }],
             }],
             isError: true
             isError: true
           };
           };
         }
         }
 
 
-        // Clean response data
-        const cleanedOrder = cleanResponseData(order);
-
+        // Format as plain text
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              source: 'qdrant',
-              access_mode: 'sync',
-              order: cleanedOrder
-            })
+            text: formatOrderAsPlainText(order)
           }]
           }]
         };
         };
       } else {
       } else {
@@ -724,9 +743,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
           return {
           return {
             content: [{
             content: [{
               type: 'text',
               type: 'text',
-              text: JSON.stringify({
-                error: `No order found with order number: ${order_id}`
-              })
+              text: `Error: No order found with order number: ${order_id}`
             }],
             }],
             isError: true
             isError: true
           };
           };
@@ -737,17 +754,11 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
         // Format for LLM
         // Format for LLM
         const formattedOrder = formatOrderForLlm(orders[0]);
         const formattedOrder = formatOrderForLlm(orders[0]);
 
 
-        // Clean response data
-        const cleanedOrder = cleanResponseData(formattedOrder);
-
+        // Format as plain text
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              source: 'api',
-              access_mode: 'sync',
-              order: cleanedOrder
-            })
+            text: formatOrderAsPlainText(formattedOrder)
           }]
           }]
         };
         };
       }
       }
@@ -757,7 +768,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: 'Invalid access policy configuration' })
+        text: 'Error: Invalid access policy configuration'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -766,9 +777,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch order: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch order: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -798,9 +807,7 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'At least one filter is required: createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, or email'
-        })
+        text: 'Error: At least one filter is required: createdAtMin, createdAtMax, updatedAtMin, updatedAtMax, or email'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -844,28 +851,13 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
       // Format for LLM (now preserves all ShopRenter fields)
       // Format for LLM (now preserves all ShopRenter fields)
       const formattedOrders = limitedOrders.map(formatOrderForLlm);
       const formattedOrders = limitedOrders.map(formatOrderForLlm);
 
 
-      // Clean response data (removes URLs, empty values)
-      const cleanedOrders = cleanResponseData(formattedOrders);
+      // Format as plain text
+      const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
 
 
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            count: formattedOrders.length,
-            limit: actualLimit,
-            source: 'api_direct',
-            access_mode: 'api_only',
-            notice: createApiOnlyNotice('orders'),
-            filters_applied: {
-              createdAtMin,
-              createdAtMax,
-              updatedAtMin,
-              updatedAtMax,
-              email,
-              status
-            },
-            orders: cleanedOrders
-          })
+          text: `Orders (${formattedOrders.length} results):\n\n${plainTextOrders}`
         }]
         }]
       };
       };
     }
     }
@@ -924,27 +916,13 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
         // Limit after filtering
         // Limit after filtering
         filteredOrders = filteredOrders.slice(0, actualLimit);
         filteredOrders = filteredOrders.slice(0, actualLimit);
 
 
-        // Clean response data
-        const cleanedOrders = cleanResponseData(filteredOrders);
+        // Format as plain text
+        const plainTextOrders = filteredOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
 
 
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              count: filteredOrders.length,
-              limit: actualLimit,
-              source: 'qdrant',
-              access_mode: 'sync',
-              filters_applied: {
-                createdAtMin,
-                createdAtMax,
-                updatedAtMin,
-                updatedAtMax,
-                email,
-                status
-              },
-              orders: cleanedOrders
-            })
+            text: `Orders (${filteredOrders.length} results):\n\n${plainTextOrders}`
           }]
           }]
         };
         };
       } else {
       } else {
@@ -971,27 +949,13 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
         // Format for LLM (now preserves all ShopRenter fields)
         // Format for LLM (now preserves all ShopRenter fields)
         const formattedOrders = limitedOrders.map(formatOrderForLlm);
         const formattedOrders = limitedOrders.map(formatOrderForLlm);
 
 
-        // Clean response data (removes URLs, empty values)
-        const cleanedOrders = cleanResponseData(formattedOrders);
+        // Format as plain text
+        const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
 
 
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              count: formattedOrders.length,
-              limit: actualLimit,
-              source: 'api',
-              access_mode: 'sync',
-              filters_applied: {
-                createdAtMin,
-                createdAtMax,
-                updatedAtMin,
-                updatedAtMax,
-                email,
-                status
-              },
-              orders: cleanedOrders
-            })
+            text: `Orders (${formattedOrders.length} results):\n\n${plainTextOrders}`
           }]
           }]
         };
         };
       }
       }
@@ -1001,7 +965,7 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: 'Invalid access policy configuration' })
+        text: 'Error: Invalid access policy configuration'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -1010,9 +974,7 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch orders: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch orders: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -1030,9 +992,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'Email parameter is required'
-        })
+        text: 'Error: Email parameter is required'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -1056,9 +1016,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            error: `No customer found with email: ${email}`
-          })
+          text: `Error: No customer found with email: ${email}`
         }],
         }],
         isError: true
         isError: true
       };
       };
@@ -1067,18 +1025,11 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
     // Return only the first customer
     // Return only the first customer
     const customer = formatCustomerForLlm(customers[0]);
     const customer = formatCustomerForLlm(customers[0]);
 
 
-    // Clean response data
-    const cleanedCustomer = cleanResponseData(customer);
-
+    // Format as plain text
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          source: isApiOnlyMode(policy) ? 'api_direct' : 'api',
-          access_mode: policy,
-          notice: isApiOnlyMode(policy) ? createApiOnlyNotice('customers') : undefined,
-          customer: cleanedCustomer
-        })
+        text: formatCustomerAsPlainText(customer)
       }]
       }]
     };
     };
   } catch (error) {
   } catch (error) {
@@ -1086,9 +1037,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch customer: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch customer: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -1129,31 +1078,25 @@ async function handleSearchCustomContent(args: Record<string, any>): Promise<Too
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            message: 'No custom content found matching your query',
-            results: []
-          })
+          text: 'No matching content found.'
         }],
         }],
         isError: false
         isError: false
       };
       };
     }
     }
 
 
+    // Format as plain text for LLM consumption
+    const plainTextResults = results.map(r => {
+      let text = `Title: ${r.title}\nContent:\n${r.excerpt}`;
+      if (r.pageCount) {
+        text += `\nNumber of pages: ${r.pageCount}`;
+      }
+      return text;
+    }).join('\n\n---\n\n');
+
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          results: results.map(r => ({
-            id: r.id,
-            title: r.title,
-            content_type: r.contentType,
-            excerpt: r.excerpt,
-            chunk_info: `Chunk ${r.chunkIndex + 1} of ${r.totalChunks}`,
-            relevance_score: Math.round(r.relevanceScore * 100) / 100,
-            original_filename: r.originalFilename,
-            page_count: r.pageCount
-          })),
-          total: results.length
-        })
+        text: plainTextResults
       }],
       }],
       isError: false
       isError: false
     };
     };
@@ -1162,7 +1105,7 @@ async function handleSearchCustomContent(args: Record<string, any>): Promise<Too
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: `Failed to search custom content: ${error instanceof Error ? error.message : 'Unknown error'}` })
+        text: `Failed to search custom content: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -1182,22 +1125,32 @@ async function handleListCustomContents(args: Record<string, any>): Promise<Tool
     // Filter to only enabled content for display
     // Filter to only enabled content for display
     const enabledContents = contents.filter(c => c.isEnabled);
     const enabledContents = contents.filter(c => c.isEnabled);
 
 
+    if (enabledContents.length === 0) {
+      return {
+        content: [{
+          type: 'text',
+          text: 'No custom content available for this store.'
+        }],
+        isError: false
+      };
+    }
+
+    // Format as plain text list
+    const plainTextList = enabledContents.map(c => {
+      let text = `Title: ${c.title}\nType: ${c.contentType === 'pdf_upload' ? 'PDF' : 'Text Entry'}`;
+      if (c.originalFilename) {
+        text += `\nFilename: ${c.originalFilename}`;
+      }
+      if (c.pageCount) {
+        text += `\nPages: ${c.pageCount}`;
+      }
+      return text;
+    }).join('\n\n---\n\n');
+
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          total: enabledContents.length,
-          contents: enabledContents.map(c => ({
-            id: c.id,
-            title: c.title,
-            content_type: c.contentType,
-            original_filename: c.originalFilename,
-            page_count: c.pageCount,
-            chunk_count: c.chunkCount,
-            sync_status: c.syncStatus,
-            created_at: c.createdAt
-          }))
-        })
+        text: `Available custom content (${enabledContents.length} items):\n\n${plainTextList}`
       }],
       }],
       isError: false
       isError: false
     };
     };
@@ -1206,7 +1159,7 @@ async function handleListCustomContents(args: Record<string, any>): Promise<Tool
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: `Failed to list custom contents: ${error instanceof Error ? error.message : 'Unknown error'}` })
+        text: `Failed to list custom contents: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };

+ 115 - 137
supabase/functions/mcp-woocommerce/index.ts

@@ -275,6 +275,54 @@ function formatOrderForLlm(order: WooCommerceOrder): LlmOrder {
   };
   };
 }
 }
 
 
+/**
+ * Format a product as plain text for LLM consumption
+ */
+function formatProductAsPlainText(p: LlmProduct): string {
+  let text = `Id: ${p.id}\nName: ${p.name}`;
+  if (p.sku) text += `\nSKU: ${p.sku}`;
+  if (p.price) text += `\nPrice: ${p.price}${p.currency ? ' ' + p.currency : ''}`;
+  if (p.status) text += `\nStatus: ${p.status}`;
+  if (p.tags) {
+    const tagsStr = Array.isArray(p.tags) ? p.tags.join(', ') : p.tags;
+    text += `\nTags: ${tagsStr}`;
+  }
+  if (p.description) {
+    // Strip HTML tags from description
+    const cleanDesc = p.description.replace(/<[^>]*>/g, '').trim();
+    if (cleanDesc) text += `\nDescription:\n${cleanDesc}`;
+  }
+  return text;
+}
+
+/**
+ * Format an order as plain text for LLM consumption
+ */
+function formatOrderAsPlainText(o: LlmOrder): string {
+  let text = `Id: #${o.orderNumber}`;
+  text += `\nCustomer: ${o.customer.name || ''}${o.customer.phone ? ' ' + o.customer.phone : ''}${o.customer.email ? ' ' + o.customer.email : ''}`;
+  text += `\nStatus: ${o.status}`;
+  text += `\nTotal: ${o.total}${o.currency ? ' ' + o.currency : ''}`;
+  if (o.items && o.items.length > 0) {
+    text += '\nItems:';
+    for (const item of o.items) {
+      text += `\n    - Name: ${item.name} Quantity: ${item.quantity} Price: ${item.price}${o.currency ? ' ' + o.currency : ''}`;
+    }
+  }
+  return text;
+}
+
+/**
+ * Format a customer as plain text for LLM consumption
+ */
+function formatCustomerAsPlainText(c: LlmCustomer): string {
+  let text = `Name: ${c.name}`;
+  text += `\nEmail: ${c.email}`;
+  if (c.phone) text += `\nPhone: ${c.phone}`;
+  if (c.ordersCount !== undefined) text += `\nTotal Orders: ${c.ordersCount}`;
+  return text;
+}
+
 /**
 /**
  * Handle woocommerce_get_products tool
  * Handle woocommerce_get_products tool
  */
  */
@@ -337,19 +385,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
         tags: p.tags?.map((t: any) => t.name) || undefined
         tags: p.tags?.map((t: any) => t.name) || undefined
       }));
       }));
 
 
-      const cleanedProducts = cleanResponseData(formattedProducts);
+      // Format as plain text
+      const plainTextProducts = formattedProducts.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            count: products.length,
-            limit: actualLimit,
-            source: 'api_direct',
-            access_mode: 'api_only',
-            notice: createApiOnlyNotice('products'),
-            products: cleanedProducts
-          })
+          text: `Products (${products.length} results):\n\n${plainTextProducts}`
         }]
         }]
       };
       };
     }
     }
@@ -366,18 +408,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
           actualLimit
           actualLimit
         );
         );
 
 
-        const cleanedProducts = cleanResponseData(products);
+        // Format as plain text
+        const plainTextProducts = products.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              count: products.length,
-              limit: actualLimit,
-              source: 'qdrant',
-              access_mode: 'sync',
-              products: cleanedProducts
-            })
+            text: `Products (${products.length} results):\n\n${plainTextProducts}`
           }]
           }]
         };
         };
       } else {
       } else {
@@ -397,7 +434,7 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
           return {
           return {
             content: [{
             content: [{
               type: 'text',
               type: 'text',
-              text: JSON.stringify({ error: `Failed to fetch products: ${cacheError.message}` })
+              text: `Error: Failed to fetch products: ${cacheError.message}`
             }],
             }],
             isError: true
             isError: true
           };
           };
@@ -433,18 +470,13 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
           tags: undefined
           tags: undefined
         }));
         }));
 
 
-        const cleanedProducts = cleanResponseData(formattedProducts);
+        // Format as plain text
+        const plainTextProducts = formattedProducts.map(formatProductAsPlainText).join('\n\n---\n\n');
 
 
         return {
         return {
           content: [{
           content: [{
             type: 'text',
             type: 'text',
-            text: JSON.stringify({
-              count: formattedProducts.length,
-              limit: actualLimit,
-              source: 'sql_cache',
-              access_mode: 'sync',
-              products: cleanedProducts
-            })
+            text: `Products (${formattedProducts.length} results):\n\n${plainTextProducts}`
           }]
           }]
         };
         };
       }
       }
@@ -454,7 +486,7 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: 'Invalid access policy configuration' })
+        text: 'Error: Invalid access policy configuration'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -462,7 +494,7 @@ async function handleGetProducts(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: `Failed to fetch products: ${error instanceof Error ? error.message : 'Unknown error'}` })
+        text: `Error: Failed to fetch products: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -507,9 +539,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'order_id parameter is required'
-        })
+        text: 'Error: order_id parameter is required'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -530,16 +560,12 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
 
 
     // Format for LLM
     // Format for LLM
     const formattedOrder = formatOrderForLlm(order);
     const formattedOrder = formatOrderForLlm(order);
-    const cleanedOrder = cleanResponseData(formattedOrder);
 
 
+    // Format as plain text
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          access_mode: policy,
-          notice: isApiOnlyMode(policy) ? createApiOnlyNotice('orders') : undefined,
-          order: cleanedOrder
-        })
+        text: formatOrderAsPlainText(formattedOrder)
       }]
       }]
     };
     };
   } catch (error) {
   } catch (error) {
@@ -547,9 +573,7 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch order: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch order: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -578,9 +602,7 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'At least one filter is required: created_after, created_before, updated_after, updated_before, customer_email, or customer_name'
-        })
+        text: 'Error: At least one filter is required: created_after, created_before, updated_after, updated_before, customer_email, or customer_name'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -630,21 +652,7 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
             return {
             return {
               content: [{
               content: [{
                 type: 'text',
                 type: 'text',
-                text: JSON.stringify({
-                  count: 0,
-                  limit: actualLimit,
-                  filters_applied: {
-                    created_after,
-                    created_before,
-                    updated_after,
-                    updated_before,
-                    customer_email,
-                    customer_name,
-                    status
-                  },
-                  orders: [],
-                  message: `No orders found for email: ${customer_email}`
-                })
+                text: `No orders found for email: ${customer_email}`
               }]
               }]
             };
             };
           }
           }
@@ -653,24 +661,13 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
           orders = matchedOrders.slice(0, actualLimit);
           orders = matchedOrders.slice(0, actualLimit);
           const formattedOrders = orders.map(formatOrderForLlm);
           const formattedOrders = orders.map(formatOrderForLlm);
 
 
+          // Format as plain text
+          const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
+
           return {
           return {
             content: [{
             content: [{
               type: 'text',
               type: 'text',
-              text: JSON.stringify({
-                count: formattedOrders.length,
-                limit: actualLimit,
-                filters_applied: {
-                  created_after,
-                  created_before,
-                  updated_after,
-                  updated_before,
-                  customer_email,
-                  customer_name,
-                  status
-                },
-                orders: formattedOrders,
-                note: 'Found via billing email search (customer not found in customer list)'
-              })
+              text: `Orders (${formattedOrders.length} results):\n\n${plainTextOrders}`
             }]
             }]
           };
           };
         }
         }
@@ -705,28 +702,14 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
 
 
     // Format for LLM
     // Format for LLM
     const formattedOrders = limitedOrders.map(formatOrderForLlm);
     const formattedOrders = limitedOrders.map(formatOrderForLlm);
-    const cleanedOrders = cleanResponseData(formattedOrders);
+
+    // Format as plain text
+    const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
 
 
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          count: formattedOrders.length,
-          limit: actualLimit,
-          source: isApiOnlyMode(policy) ? 'api_direct' : 'api',
-          access_mode: policy,
-          notice: isApiOnlyMode(policy) ? createApiOnlyNotice('orders') : undefined,
-          filters_applied: {
-            created_after,
-            created_before,
-            updated_after,
-            updated_before,
-            customer_email,
-            customer_name,
-            status
-          },
-          orders: cleanedOrders
-        })
+        text: `Orders (${formattedOrders.length} results):\n\n${plainTextOrders}`
       }]
       }]
     };
     };
   } catch (error) {
   } catch (error) {
@@ -734,9 +717,7 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch orders: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch orders: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -754,9 +735,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: 'Email parameter is required'
-        })
+        text: 'Error: Email parameter is required'
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -779,9 +758,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
       return {
       return {
         content: [{
         content: [{
           type: 'text',
           type: 'text',
-          text: JSON.stringify({
-            error: `No customer found with email: ${email}`
-          })
+          text: `Error: No customer found with email: ${email}`
         }],
         }],
         isError: true
         isError: true
       };
       };
@@ -789,16 +766,12 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
 
 
     // Return only the first customer
     // Return only the first customer
     const customer = formatCustomerForLlm(customers[0]);
     const customer = formatCustomerForLlm(customers[0]);
-    const cleanedCustomer = cleanResponseData(customer);
 
 
+    // Format as plain text
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          access_mode: policy,
-          notice: isApiOnlyMode(policy) ? createApiOnlyNotice('customers') : undefined,
-          customer: cleanedCustomer
-        })
+        text: formatCustomerAsPlainText(customer)
       }]
       }]
     };
     };
   } catch (error) {
   } catch (error) {
@@ -806,9 +779,7 @@ async function handleGetCustomer(args: Record<string, any>): Promise<ToolCallRes
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          error: `Failed to fetch customer: ${error instanceof Error ? error.message : 'Unknown error'}`
-        })
+        text: `Error: Failed to fetch customer: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -858,22 +829,19 @@ async function handleSearchCustomContent(args: Record<string, any>): Promise<Too
       };
       };
     }
     }
 
 
+    // Format as plain text for LLM consumption
+    const plainTextResults = results.map(r => {
+      let text = `Title: ${r.title}\nContent:\n${r.excerpt}`;
+      if (r.pageCount) {
+        text += `\nNumber of pages: ${r.pageCount}`;
+      }
+      return text;
+    }).join('\n\n---\n\n');
+
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          results: results.map(r => ({
-            id: r.id,
-            title: r.title,
-            content_type: r.contentType,
-            excerpt: r.excerpt,
-            chunk_info: `Chunk ${r.chunkIndex + 1} of ${r.totalChunks}`,
-            relevance_score: Math.round(r.relevanceScore * 100) / 100,
-            original_filename: r.originalFilename,
-            page_count: r.pageCount
-          })),
-          total: results.length
-        })
+        text: plainTextResults || 'No matching content found.'
       }],
       }],
       isError: false
       isError: false
     };
     };
@@ -882,7 +850,7 @@ async function handleSearchCustomContent(args: Record<string, any>): Promise<Too
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: `Failed to search custom content: ${error instanceof Error ? error.message : 'Unknown error'}` })
+        text: `Failed to search custom content: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };
@@ -902,22 +870,32 @@ async function handleListCustomContents(args: Record<string, any>): Promise<Tool
     // Filter to only enabled content for display
     // Filter to only enabled content for display
     const enabledContents = contents.filter(c => c.isEnabled);
     const enabledContents = contents.filter(c => c.isEnabled);
 
 
+    if (enabledContents.length === 0) {
+      return {
+        content: [{
+          type: 'text',
+          text: 'No custom content available for this store.'
+        }],
+        isError: false
+      };
+    }
+
+    // Format as plain text list
+    const plainTextList = enabledContents.map(c => {
+      let text = `Title: ${c.title}\nType: ${c.contentType === 'pdf_upload' ? 'PDF' : 'Text Entry'}`;
+      if (c.originalFilename) {
+        text += `\nFilename: ${c.originalFilename}`;
+      }
+      if (c.pageCount) {
+        text += `\nPages: ${c.pageCount}`;
+      }
+      return text;
+    }).join('\n\n---\n\n');
+
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({
-          total: enabledContents.length,
-          contents: enabledContents.map(c => ({
-            id: c.id,
-            title: c.title,
-            content_type: c.contentType,
-            original_filename: c.originalFilename,
-            page_count: c.pageCount,
-            chunk_count: c.chunkCount,
-            sync_status: c.syncStatus,
-            created_at: c.createdAt
-          }))
-        })
+        text: `Available custom content (${enabledContents.length} items):\n\n${plainTextList}`
       }],
       }],
       isError: false
       isError: false
     };
     };
@@ -926,7 +904,7 @@ async function handleListCustomContents(args: Record<string, any>): Promise<Tool
     return {
     return {
       content: [{
       content: [{
         type: 'text',
         type: 'text',
-        text: JSON.stringify({ error: `Failed to list custom contents: ${error instanceof Error ? error.message : 'Unknown error'}` })
+        text: `Failed to list custom contents: ${error instanceof Error ? error.message : 'Unknown error'}`
       }],
       }],
       isError: true
       isError: true
     };
     };