|
|
@@ -1,23 +1,27 @@
|
|
|
-# MCP HTTP Servers for Webshop API Access
|
|
|
+# MCP SSE 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.
|
|
|
+This document describes the MCP (Model Context Protocol) SSE (Server-Sent Events) servers implemented for accessing webshop orders and customers data in a GDPR-compliant manner. These servers allow LLMs (like n8n workflows) to access personal data on-demand without storing it in the database.
|
|
|
+
|
|
|
+**Protocol**: MCP over HTTP with Server-Sent Events (2024-11-05)
|
|
|
+**Transport**: HTTP POST with SSE streaming responses
|
|
|
+**Format**: JSON-RPC 2.0
|
|
|
|
|
|
## Architecture
|
|
|
|
|
|
```
|
|
|
-┌─────┐ ┌──────────────────┐ ┌────────────────┐ ┌──────────────┐
|
|
|
-│ LLM │───▶│ MCP HTTP Server │───▶│ Internal API │───▶│ Webshop │
|
|
|
-│ │ │ (Edge Function) │ │ Key Auth │ │ API │
|
|
|
-└─────┘ └──────────────────┘ └────────────────┘ └──────────────┘
|
|
|
- │ │
|
|
|
- │ │
|
|
|
- ▼ ▼
|
|
|
- ┌─────────────┐ ┌──────────────────┐
|
|
|
- │ Store │ │ internal_api_keys│
|
|
|
- │ Permissions │ │ table │
|
|
|
- └─────────────┘ └──────────────────┘
|
|
|
+┌─────────┐ POST (JSON-RPC) ┌──────────────────┐ ┌────────────────┐ ┌──────────────┐
|
|
|
+│ n8n │────────────────────▶│ MCP SSE Server │───▶│ Internal API │───▶│ Webshop │
|
|
|
+│ LLM │◀────────────────────│ (Edge Function) │ │ Key Auth │ │ API │
|
|
|
+└─────────┘ SSE Stream └──────────────────┘ └────────────────┘ └──────────────┘
|
|
|
+ │ │
|
|
|
+ │ │
|
|
|
+ ▼ ▼
|
|
|
+ ┌─────────────┐ ┌──────────────────┐
|
|
|
+ │ Store │ │ internal_api_keys│
|
|
|
+ │ Permissions │ │ table │
|
|
|
+ └─────────────┘ └──────────────────┘
|
|
|
```
|
|
|
|
|
|
## Implemented MCP Servers
|
|
|
@@ -72,90 +76,119 @@ Authorization: Bearer int_shopcall_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
|
- `X-RateLimit-Remaining: 150`
|
|
|
- `X-RateLimit-Reset: 2025-01-15T10:30:00Z`
|
|
|
|
|
|
-## MCP Protocol
|
|
|
+## MCP SSE Protocol
|
|
|
+
|
|
|
+### Single Endpoint: POST /
|
|
|
+
|
|
|
+All MCP communication happens through a single POST endpoint using Server-Sent Events.
|
|
|
+
|
|
|
+**URL**: `https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-{platform}/`
|
|
|
|
|
|
-### Endpoint: GET /tools
|
|
|
+**Method**: POST
|
|
|
|
|
|
-Returns available tools (no authentication required):
|
|
|
+**Authentication**: Required (Bearer token in Authorization header)
|
|
|
+
|
|
|
+**Protocol**: JSON-RPC 2.0 over SSE
|
|
|
+
|
|
|
+### Supported JSON-RPC Methods
|
|
|
+
|
|
|
+#### 1. `initialize` - Initialize MCP connection
|
|
|
|
|
|
**Request:**
|
|
|
```bash
|
|
|
-GET /functions/v1/mcp-shopify/tools
|
|
|
-```
|
|
|
+POST /functions/v1/mcp-shopify
|
|
|
+Authorization: Bearer int_shopcall_xxxxx
|
|
|
+Content-Type: application/json
|
|
|
|
|
|
-**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"]
|
|
|
- }
|
|
|
+ "jsonrpc": "2.0",
|
|
|
+ "id": 1,
|
|
|
+ "method": "initialize",
|
|
|
+ "params": {
|
|
|
+ "protocolVersion": "2024-11-05",
|
|
|
+ "capabilities": {
|
|
|
+ "roots": { "listChanged": true }
|
|
|
+ },
|
|
|
+ "clientInfo": {
|
|
|
+ "name": "n8n",
|
|
|
+ "version": "1.0.0"
|
|
|
}
|
|
|
- ]
|
|
|
+ }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-### Endpoint: POST /call
|
|
|
+**Response (SSE Stream):**
|
|
|
+```
|
|
|
+data: {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{"listChanged":false}},"serverInfo":{"name":"mcp-shopify","version":"1.0.0"}}}
|
|
|
+
|
|
|
+```
|
|
|
|
|
|
-Executes a tool (requires authentication):
|
|
|
+#### 2. `tools/list` - Get available tools
|
|
|
|
|
|
**Request:**
|
|
|
```bash
|
|
|
-POST /functions/v1/mcp-shopify/call
|
|
|
+POST /functions/v1/mcp-shopify
|
|
|
Authorization: Bearer int_shopcall_xxxxx
|
|
|
Content-Type: application/json
|
|
|
|
|
|
{
|
|
|
- "name": "shopify_list_orders",
|
|
|
- "arguments": {
|
|
|
- "shop_id": "abc-123-def-456",
|
|
|
- "status": "any",
|
|
|
- "limit": 10
|
|
|
- }
|
|
|
+ "jsonrpc": "2.0",
|
|
|
+ "id": 2,
|
|
|
+ "method": "tools/list",
|
|
|
+ "params": {}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-**Success Response:**
|
|
|
-```json
|
|
|
+**Response (SSE Stream):**
|
|
|
+```
|
|
|
+data: {"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"shopify_list_orders","description":"List orders from a Shopify store...","inputSchema":{...}}]}}
|
|
|
+
|
|
|
+```
|
|
|
+
|
|
|
+#### 3. `tools/call` - Execute a tool
|
|
|
+
|
|
|
+**Request:**
|
|
|
+```bash
|
|
|
+POST /functions/v1/mcp-shopify
|
|
|
+Authorization: Bearer int_shopcall_xxxxx
|
|
|
+Content-Type: application/json
|
|
|
+
|
|
|
{
|
|
|
- "content": [
|
|
|
- {
|
|
|
- "type": "text",
|
|
|
- "text": "{\"count\":3,\"total\":10,\"orders\":[...]}"
|
|
|
+ "jsonrpc": "2.0",
|
|
|
+ "id": 3,
|
|
|
+ "method": "tools/call",
|
|
|
+ "params": {
|
|
|
+ "name": "shopify_list_orders",
|
|
|
+ "arguments": {
|
|
|
+ "shop_id": "abc-123-def-456",
|
|
|
+ "status": "any",
|
|
|
+ "limit": 10
|
|
|
}
|
|
|
- ]
|
|
|
+ }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-**Error Response:**
|
|
|
-```json
|
|
|
-{
|
|
|
- "error": {
|
|
|
- "code": "STORE_NOT_FOUND",
|
|
|
- "message": "Shopify store not found"
|
|
|
- },
|
|
|
- "isError": true
|
|
|
-}
|
|
|
+**Success Response (SSE Stream):**
|
|
|
+```
|
|
|
+data: {"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"{\"count\":3,\"total\":10,\"orders\":[...]}"}]}}
|
|
|
+
|
|
|
+```
|
|
|
+
|
|
|
+**Error Response (SSE Stream):**
|
|
|
```
|
|
|
+data: {"jsonrpc":"2.0","id":3,"error":{"code":-32603,"message":"Shopify store not found"}}
|
|
|
+
|
|
|
+```
|
|
|
+
|
|
|
+### JSON-RPC Error Codes
|
|
|
+
|
|
|
+| Code | Name | Description |
|
|
|
+|------|------|-------------|
|
|
|
+| -32700 | Parse error | Invalid JSON was received |
|
|
|
+| -32600 | Invalid Request | The JSON sent is not a valid Request object |
|
|
|
+| -32601 | Method not found | The method does not exist / is not available |
|
|
|
+| -32602 | Invalid params | Invalid method parameter(s) |
|
|
|
+| -32603 | Internal error | Internal JSON-RPC error |
|
|
|
|
|
|
## Store Permissions
|
|
|
|
|
|
@@ -267,28 +300,56 @@ curl https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify/tools
|
|
|
|
|
|
## Testing
|
|
|
|
|
|
-### Test Tool Discovery
|
|
|
-
|
|
|
-```bash
|
|
|
-curl https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify/tools
|
|
|
-```
|
|
|
-
|
|
|
-### Test Tool Execution
|
|
|
+### Test with curl
|
|
|
|
|
|
```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 \
|
|
|
+# Test initialize
|
|
|
+curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify \
|
|
|
+ -H "Authorization: Bearer $INTERNAL_API_KEY" \
|
|
|
+ -H "Content-Type: application/json" \
|
|
|
+ -d '{
|
|
|
+ "jsonrpc": "2.0",
|
|
|
+ "id": 1,
|
|
|
+ "method": "initialize",
|
|
|
+ "params": {
|
|
|
+ "protocolVersion": "2024-11-05",
|
|
|
+ "capabilities": {},
|
|
|
+ "clientInfo": {
|
|
|
+ "name": "test-client",
|
|
|
+ "version": "1.0.0"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }'
|
|
|
+
|
|
|
+# Test tools/list
|
|
|
+curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify \
|
|
|
+ -H "Authorization: Bearer $INTERNAL_API_KEY" \
|
|
|
+ -H "Content-Type: application/json" \
|
|
|
+ -d '{
|
|
|
+ "jsonrpc": "2.0",
|
|
|
+ "id": 2,
|
|
|
+ "method": "tools/list",
|
|
|
+ "params": {}
|
|
|
+ }'
|
|
|
+
|
|
|
+# Test tools/call (list orders)
|
|
|
+curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify \
|
|
|
-H "Authorization: Bearer $INTERNAL_API_KEY" \
|
|
|
-H "Content-Type: application/json" \
|
|
|
-d "{
|
|
|
- \"name\": \"shopify_list_orders\",
|
|
|
- \"arguments\": {
|
|
|
- \"shop_id\": \"$SHOP_ID\",
|
|
|
- \"limit\": 5
|
|
|
+ \"jsonrpc\": \"2.0\",
|
|
|
+ \"id\": 3,
|
|
|
+ \"method\": \"tools/call\",
|
|
|
+ \"params\": {
|
|
|
+ \"name\": \"shopify_list_orders\",
|
|
|
+ \"arguments\": {
|
|
|
+ \"shop_id\": \"$SHOP_ID\",
|
|
|
+ \"limit\": 5
|
|
|
+ }
|
|
|
}
|
|
|
}"
|
|
|
```
|
|
|
@@ -297,17 +358,76 @@ curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify/c
|
|
|
|
|
|
```bash
|
|
|
# Test missing shop_id
|
|
|
-curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify/call \
|
|
|
+curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-shopify \
|
|
|
-H "Authorization: Bearer $INTERNAL_API_KEY" \
|
|
|
-H "Content-Type: application/json" \
|
|
|
- -d "{
|
|
|
- \"name\": \"shopify_list_orders\",
|
|
|
- \"arguments\": {}
|
|
|
- }"
|
|
|
+ -d '{
|
|
|
+ "jsonrpc": "2.0",
|
|
|
+ "id": 4,
|
|
|
+ "method": "tools/call",
|
|
|
+ "params": {
|
|
|
+ "name": "shopify_list_orders",
|
|
|
+ "arguments": {}
|
|
|
+ }
|
|
|
+ }'
|
|
|
|
|
|
-# Expected: MISSING_PARAMS error
|
|
|
+# Expected: JSON-RPC error with missing parameters
|
|
|
```
|
|
|
|
|
|
+## n8n Integration
|
|
|
+
|
|
|
+### Configuring MCP Servers in n8n
|
|
|
+
|
|
|
+1. **Add MCP Server Credential in n8n:**
|
|
|
+ - Type: `HTTP Streamable`
|
|
|
+ - URL: `https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/mcp-woocommerce`
|
|
|
+ - Or use `/mcp-shopify` or `/mcp-shoprenter` based on your needs
|
|
|
+ - Authentication: `Bearer Token`
|
|
|
+ - Add custom header:
|
|
|
+ - Header: `Authorization`
|
|
|
+ - Value: `Bearer int_shopcall_[your-api-key]`
|
|
|
+
|
|
|
+2. **Using MCP Tools in n8n Workflow:**
|
|
|
+ - Add an "AI Agent" or "MCP Tool" node
|
|
|
+ - Select your MCP server credential
|
|
|
+ - The agent will automatically discover available tools
|
|
|
+ - Call tools with required parameters (always include `shop_id`)
|
|
|
+
|
|
|
+3. **Example n8n Tool Call:**
|
|
|
+ ```javascript
|
|
|
+ // In n8n AI Agent node, the MCP client will call:
|
|
|
+ {
|
|
|
+ "name": "woocommerce_list_orders",
|
|
|
+ "arguments": {
|
|
|
+ "shop_id": "uuid-of-woocommerce-store",
|
|
|
+ "status": "completed",
|
|
|
+ "per_page": 10
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ```
|
|
|
+
|
|
|
+### Troubleshooting n8n Integration
|
|
|
+
|
|
|
+**Issue: "No tools found"**
|
|
|
+- Check that the URL ends with the function name (e.g., `/mcp-woocommerce`)
|
|
|
+- Verify the Bearer token is correctly set in headers
|
|
|
+- Check Supabase Edge Function logs for 401 errors
|
|
|
+
|
|
|
+**Issue: "Connection timeout"**
|
|
|
+- Ensure the Edge Function is deployed and active
|
|
|
+- Check network connectivity to Supabase
|
|
|
+- Verify CORS headers are present
|
|
|
+
|
|
|
+**Issue: "401 Unauthorized"**
|
|
|
+- Verify the internal API key is active in the database
|
|
|
+- Check that the API key has `read_orders` permission
|
|
|
+- Ensure the Bearer token format is: `Bearer int_shopcall_...`
|
|
|
+
|
|
|
+**Issue: "Tools executing but returning errors"**
|
|
|
+- Check that `shop_id` parameter is a valid UUID
|
|
|
+- Verify the store exists and matches the platform (e.g., don't use a Shopify store ID with mcp-woocommerce)
|
|
|
+- Check store permissions allow order/customer access
|
|
|
+
|
|
|
## Security Best Practices
|
|
|
|
|
|
1. **API Key Management**
|
|
|
@@ -436,5 +556,6 @@ For issues or questions:
|
|
|
---
|
|
|
|
|
|
**Last Updated**: 2025-01-12
|
|
|
-**Version**: 1.0.0
|
|
|
+**Version**: 2.0.0 (SSE Protocol)
|
|
|
**Related Issue**: #76
|
|
|
+**Protocol**: MCP over HTTP with SSE (2024-11-05)
|