Jelajahi Sumber

docs: add comprehensive MCP servers documentation #76

Claude 5 bulan lalu
induk
melakukan
8c49c1d2b2
1 mengubah file dengan 440 tambahan dan 0 penghapusan
  1. 440 0
      docs/MCP_SERVERS.md

+ 440 - 0
docs/MCP_SERVERS.md

@@ -0,0 +1,440 @@
+# MCP HTTP Servers for Webshop API Access
+
+## Overview
+
+This document describes the MCP (Model Context Protocol) HTTP servers implemented for accessing webshop orders and customers data in a GDPR-compliant manner. These servers allow LLMs to access personal data on-demand without storing it in the database.
+
+## Architecture
+
+```
+┌─────┐    ┌──────────────────┐    ┌────────────────┐    ┌──────────────┐
+│ LLM │───▶│ MCP HTTP Server  │───▶│ Internal API   │───▶│   Webshop    │
+│     │    │ (Edge Function)  │    │ Key Auth       │    │   API        │
+└─────┘    └──────────────────┘    └────────────────┘    └──────────────┘
+              │                           │
+              │                           │
+              ▼                           ▼
+         ┌─────────────┐          ┌──────────────────┐
+         │   Store     │          │ internal_api_keys│
+         │ Permissions │          │     table        │
+         └─────────────┘          └──────────────────┘
+```
+
+## Implemented MCP Servers
+
+### 1. mcp-shopify
+- **Endpoint**: `/functions/v1/mcp-shopify`
+- **Purpose**: Access Shopify orders and customers
+- **Tools**: 3 (list_orders, list_customers, get_customer_orders)
+
+### 2. mcp-woocommerce
+- **Endpoint**: `/functions/v1/mcp-woocommerce`
+- **Purpose**: Access WooCommerce orders and customers
+- **Tools**: 3 (list_orders, list_customers, get_customer_orders)
+
+### 3. mcp-shoprenter
+- **Endpoint**: `/functions/v1/mcp-shoprenter`
+- **Purpose**: Access ShopRenter orders and customers
+- **Tools**: 3 (list_orders, list_customers, get_customer_orders)
+
+## Authentication
+
+### Internal API Keys
+
+All MCP servers require authentication using internal API keys stored in the `internal_api_keys` table:
+
+```sql
+-- Example internal API key structure
+{
+  "id": "uuid",
+  "api_key": "int_shopcall_xxxxx...",
+  "permissions": {
+    "read_orders": true,
+    "read_customers": true,
+    "all_webshops": true
+  },
+  "is_active": true,
+  "expires_at": null
+}
+```
+
+### Authorization Header
+
+```
+Authorization: Bearer int_shopcall_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+```
+
+### Rate Limiting
+
+- **Limit**: 200 requests per minute per API key
+- **Headers**:
+  - `X-RateLimit-Limit: 200`
+  - `X-RateLimit-Remaining: 150`
+  - `X-RateLimit-Reset: 2025-01-15T10:30:00Z`
+
+## MCP Protocol
+
+### Endpoint: GET /tools
+
+Returns available tools (no authentication required):
+
+**Request:**
+```bash
+GET /functions/v1/mcp-shopify/tools
+```
+
+**Response:**
+```json
+{
+  "tools": [
+    {
+      "name": "shopify_list_orders",
+      "description": "List orders from a Shopify store. Returns order details including customer info, items, status, and totals.",
+      "inputSchema": {
+        "type": "object",
+        "properties": {
+          "shop_id": {
+            "type": "string",
+            "description": "The UUID of the Shopify store from the stores table"
+          },
+          "status": {
+            "type": "string",
+            "description": "Filter by order status: any (default), open, closed, cancelled",
+            "enum": ["any", "open", "closed", "cancelled"]
+          },
+          "limit": {
+            "type": "number",
+            "description": "Maximum number of orders to return (default: 50, max: 250)"
+          }
+        },
+        "required": ["shop_id"]
+      }
+    }
+  ]
+}
+```
+
+### Endpoint: POST /call
+
+Executes a tool (requires authentication):
+
+**Request:**
+```bash
+POST /functions/v1/mcp-shopify/call
+Authorization: Bearer int_shopcall_xxxxx
+Content-Type: application/json
+
+{
+  "name": "shopify_list_orders",
+  "arguments": {
+    "shop_id": "abc-123-def-456",
+    "status": "any",
+    "limit": 10
+  }
+}
+```
+
+**Success Response:**
+```json
+{
+  "content": [
+    {
+      "type": "text",
+      "text": "{\"count\":3,\"total\":10,\"orders\":[...]}"
+    }
+  ]
+}
+```
+
+**Error Response:**
+```json
+{
+  "error": {
+    "code": "STORE_NOT_FOUND",
+    "message": "Shopify store not found"
+  },
+  "isError": true
+}
+```
+
+## Store Permissions
+
+Each store has a `data_access_permissions` field that controls access:
+
+```json
+{
+  "allow_product_access": true,
+  "allow_customer_access": true,
+  "allow_order_access": true
+}
+```
+
+MCP servers check these permissions before accessing data:
+- **Orders**: Requires `allow_order_access: true`
+- **Customers**: Requires `allow_customer_access: true`
+- **Customer Orders**: Requires both permissions
+
+## LLM-Friendly Data Format
+
+All responses use compact, clear formats optimized for LLM consumption:
+
+### Customer Format
+
+```typescript
+interface LlmCustomer {
+  id: string;
+  name: string;              // "John Doe"
+  email: string;             // "john@example.com"
+  phone?: string;            // "+1234567890"
+  ordersCount?: number;      // 5
+  totalSpent?: string;       // "1250.00 USD"
+}
+```
+
+### Order Format
+
+```typescript
+interface LlmOrder {
+  id: string;
+  orderNumber: string;       // "#1001"
+  customer: {
+    name: string;
+    email: string;
+    phone?: string;
+  };
+  status: string;            // "paid/fulfilled"
+  total: string;             // "250.00"
+  currency?: string;         // "USD"
+  items: Array<{
+    name: string;            // "Product A"
+    quantity: number;        // 2
+    price: string;           // "100.00"
+  }>;
+  createdAt: string;         // ISO 8601 timestamp
+}
+```
+
+## Error Codes
+
+| Code | HTTP Status | Description |
+|------|-------------|-------------|
+| `MISSING_API_KEY` | 401 | No Authorization header provided |
+| `INVALID_FORMAT` | 401 | API key format is invalid |
+| `NOT_FOUND` | 401 | API key not found in database |
+| `INACTIVE` | 401 | API key is inactive |
+| `EXPIRED` | 401 | API key has expired |
+| `INSUFFICIENT_PERMISSIONS` | 401 | Missing required permission |
+| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests |
+| `MISSING_PARAMS` | 400 | Required parameters missing |
+| `STORE_NOT_FOUND` | 404 | Store not found or wrong platform |
+| `PERMISSION_DENIED` | 403 | Store permissions deny access |
+| `FETCH_ERROR` | 500 | Error fetching from webshop API |
+| `UNKNOWN_TOOL` | 404 | Tool name not recognized |
+| `INTERNAL_ERROR` | 500 | Server error |
+
+## Deployment
+
+### Prerequisites
+
+1. Supabase project with Edge Functions enabled
+2. Environment variables configured:
+   - `SUPABASE_URL`
+   - `SUPABASE_SERVICE_ROLE_KEY`
+   - Platform-specific credentials (Shopify, WooCommerce, ShopRenter)
+
+### Deploy via CLI
+
+```bash
+cd supabase
+
+# Deploy individual MCP servers
+supabase functions deploy mcp-shopify --project-ref ztklqodcdjeqpsvhlpud
+supabase functions deploy mcp-woocommerce --project-ref ztklqodcdjeqpsvhlpud
+supabase functions deploy mcp-shoprenter --project-ref ztklqodcdjeqpsvhlpud
+
+# Or deploy all at once
+supabase functions deploy mcp-shopify mcp-woocommerce mcp-shoprenter --project-ref ztklqodcdjeqpsvhlpud
+```
+
+### Verify Deployment
+
+```bash
+# Check if function is live
+curl https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify/tools
+
+# Should return JSON with tools array
+```
+
+## Testing
+
+### Test Tool Discovery
+
+```bash
+curl https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify/tools
+```
+
+### Test Tool Execution
+
+```bash
+# Set your internal API key
+INTERNAL_API_KEY="int_shopcall_xxxxx"
+SHOP_ID="your-store-uuid"
+
+# List orders
+curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify/call \
+  -H "Authorization: Bearer $INTERNAL_API_KEY" \
+  -H "Content-Type: application/json" \
+  -d "{
+    \"name\": \"shopify_list_orders\",
+    \"arguments\": {
+      \"shop_id\": \"$SHOP_ID\",
+      \"limit\": 5
+    }
+  }"
+```
+
+### Test Error Handling
+
+```bash
+# Test missing shop_id
+curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify/call \
+  -H "Authorization: Bearer $INTERNAL_API_KEY" \
+  -H "Content-Type: application/json" \
+  -d "{
+    \"name\": \"shopify_list_orders\",
+    \"arguments\": {}
+  }"
+
+# Expected: MISSING_PARAMS error
+```
+
+## Security Best Practices
+
+1. **API Key Management**
+   - Store internal API keys securely
+   - Rotate keys periodically
+   - Set expiration dates when appropriate
+   - Monitor `last_used_at` for anomalies
+
+2. **Rate Limiting**
+   - Default: 200 req/min per key
+   - Adjust based on usage patterns
+   - Monitor for abuse
+
+3. **Store Permissions**
+   - Review permissions regularly
+   - Audit permission changes via `store_permission_audit` table
+   - Default to least privilege
+
+4. **Logging**
+   - Monitor Edge Function logs for errors
+   - Track tool usage patterns
+   - Alert on suspicious activity
+
+## GDPR Compliance
+
+### How MCP Servers Ensure GDPR Compliance
+
+1. **No Data Storage**
+   - Personal data is fetched on-demand from webshop APIs
+   - Data is never stored in Supabase database
+   - Data exists only in memory during request processing
+
+2. **Access Control**
+   - Strict authentication via internal API keys
+   - Permission checks at store level
+   - Audit trail of all data access
+
+3. **Data Minimization**
+   - Only requested data is fetched
+   - LLM-friendly format includes only necessary fields
+   - No unnecessary data retention
+
+4. **Right to be Forgotten**
+   - Deleting store credentials immediately prevents access
+   - No cached personal data to delete
+   - All data access is real-time from source
+
+## Troubleshooting
+
+### Issue: "API key not found"
+
+**Cause**: Internal API key doesn't exist in database
+
+**Solution**:
+```sql
+-- Check if key exists
+SELECT * FROM internal_api_keys WHERE api_key = 'int_shopcall_xxxxx';
+
+-- Create new key if needed (see INTERNAL_API_KEYS.md)
+```
+
+### Issue: "Rate limit exceeded"
+
+**Cause**: Too many requests in 1 minute window
+
+**Solution**: Wait until reset time shown in error message or increase limit
+
+### Issue: "Store not found"
+
+**Cause**: Invalid shop_id or wrong platform
+
+**Solution**:
+```sql
+-- Verify store exists and check platform
+SELECT id, platform_name, store_name FROM stores WHERE id = 'shop-uuid';
+```
+
+### Issue: "Permission denied"
+
+**Cause**: Store's `data_access_permissions` deny access
+
+**Solution**:
+```sql
+-- Check store permissions
+SELECT data_access_permissions FROM stores WHERE id = 'shop-uuid';
+
+-- Update if needed
+UPDATE stores
+SET data_access_permissions = '{"allow_order_access": true, "allow_customer_access": true}'::jsonb
+WHERE id = 'shop-uuid';
+```
+
+## File Structure
+
+```
+supabase/functions/
+├── _shared/
+│   ├── mcp-types.ts          # MCP type definitions
+│   ├── mcp-helpers.ts        # Helper functions
+│   ├── shopify-client.ts     # Shopify API client
+│   ├── woocommerce-client.ts # WooCommerce API client
+│   ├── shoprenter-client.ts  # ShopRenter API client
+│   └── internal-api-key-auth.ts # Auth middleware
+├── mcp-shopify/
+│   └── index.ts              # Shopify MCP server
+├── mcp-woocommerce/
+│   └── index.ts              # WooCommerce MCP server
+└── mcp-shoprenter/
+    └── index.ts              # ShopRenter MCP server
+```
+
+## Related Documentation
+
+- [INTERNAL_API_KEYS.md](../INTERNAL_API_KEYS.md) - Managing internal API keys
+- [CLAUDE.md](../CLAUDE.md) - Project overview and architecture
+- [Supabase Edge Functions Docs](https://supabase.com/docs/guides/functions)
+- [MCP Protocol Specification](https://modelcontextprotocol.io)
+
+## Support
+
+For issues or questions:
+1. Check Supabase Edge Function logs
+2. Review error codes and troubleshooting section
+3. Contact: ferenc.szontagh@smartbotics.ai
+
+---
+
+**Last Updated**: 2025-01-12
+**Version**: 1.0.0
+**Related Issue**: #76