sopo-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +10 -0
- package/.env +7 -0
- package/.ghaymah.json +20 -0
- package/Dockerfile +37 -0
- package/GUIDE.md +311 -0
- package/README.md +143 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/sopo.prompts.d.ts +8 -0
- package/dist/prompts/sopo.prompts.d.ts.map +1 -0
- package/dist/prompts/sopo.prompts.js +102 -0
- package/dist/prompts/sopo.prompts.js.map +1 -0
- package/dist/resources/platform.resources.d.ts +9 -0
- package/dist/resources/platform.resources.d.ts.map +1 -0
- package/dist/resources/platform.resources.js +143 -0
- package/dist/resources/platform.resources.js.map +1 -0
- package/dist/sopo-client.d.ts +51 -0
- package/dist/sopo-client.d.ts.map +1 -0
- package/dist/sopo-client.js +145 -0
- package/dist/sopo-client.js.map +1 -0
- package/dist/tools/aggregate-request.tools.d.ts +8 -0
- package/dist/tools/aggregate-request.tools.d.ts.map +1 -0
- package/dist/tools/aggregate-request.tools.js +57 -0
- package/dist/tools/aggregate-request.tools.js.map +1 -0
- package/dist/tools/auth.tools.d.ts +12 -0
- package/dist/tools/auth.tools.d.ts.map +1 -0
- package/dist/tools/auth.tools.js +152 -0
- package/dist/tools/auth.tools.js.map +1 -0
- package/dist/tools/collection.tools.d.ts +8 -0
- package/dist/tools/collection.tools.d.ts.map +1 -0
- package/dist/tools/collection.tools.js +54 -0
- package/dist/tools/collection.tools.js.map +1 -0
- package/dist/tools/gateway-plugin.tools.d.ts +8 -0
- package/dist/tools/gateway-plugin.tools.d.ts.map +1 -0
- package/dist/tools/gateway-plugin.tools.js +64 -0
- package/dist/tools/gateway-plugin.tools.js.map +1 -0
- package/dist/tools/gateway-route.tools.d.ts +8 -0
- package/dist/tools/gateway-route.tools.d.ts.map +1 -0
- package/dist/tools/gateway-route.tools.js +68 -0
- package/dist/tools/gateway-route.tools.js.map +1 -0
- package/dist/tools/gateway.tools.d.ts +8 -0
- package/dist/tools/gateway.tools.d.ts.map +1 -0
- package/dist/tools/gateway.tools.js +56 -0
- package/dist/tools/gateway.tools.js.map +1 -0
- package/dist/tools/observability.tools.d.ts +9 -0
- package/dist/tools/observability.tools.d.ts.map +1 -0
- package/dist/tools/observability.tools.js +54 -0
- package/dist/tools/observability.tools.js.map +1 -0
- package/dist/tools/service-target.tools.d.ts +8 -0
- package/dist/tools/service-target.tools.d.ts.map +1 -0
- package/dist/tools/service-target.tools.js +52 -0
- package/dist/tools/service-target.tools.js.map +1 -0
- package/dist/tools/service.tools.d.ts +8 -0
- package/dist/tools/service.tools.d.ts.map +1 -0
- package/dist/tools/service.tools.js +67 -0
- package/dist/tools/service.tools.js.map +1 -0
- package/dist/tools/user-profile.tools.d.ts +8 -0
- package/dist/tools/user-profile.tools.d.ts.map +1 -0
- package/dist/tools/user-profile.tools.js +46 -0
- package/dist/tools/user-profile.tools.js.map +1 -0
- package/package.json +33 -0
- package/src/index.ts +115 -0
- package/src/prompts/sopo.prompts.ts +128 -0
- package/src/resources/platform.resources.ts +163 -0
- package/src/sopo-client.ts +180 -0
- package/src/tools/aggregate-request.tools.ts +83 -0
- package/src/tools/auth.tools.ts +187 -0
- package/src/tools/collection.tools.ts +80 -0
- package/src/tools/gateway-plugin.tools.ts +90 -0
- package/src/tools/gateway-route.tools.ts +94 -0
- package/src/tools/gateway.tools.ts +82 -0
- package/src/tools/observability.tools.ts +87 -0
- package/src/tools/service-target.tools.ts +78 -0
- package/src/tools/service.tools.ts +93 -0
- package/src/tools/user-profile.tools.ts +72 -0
- package/tsconfig.json +19 -0
package/.dockerignore
ADDED
package/.env
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Sopo Backend URL (where sopo_backend is running)
|
|
2
|
+
SOPO_BACKEND_URL=https://sopo-backend-ebbe5030f148.hosted.ghaymah.systems
|
|
3
|
+
|
|
4
|
+
# Authentication: Provide a valid JWT access token for the Sopo Backend.
|
|
5
|
+
# This token is used by the MCP server to authenticate all API calls.
|
|
6
|
+
# You can obtain this token by signing in through the Sopo Backend auth endpoints.
|
|
7
|
+
SOPO_ACCESS_TOKEN=your_jwt_access_token_here
|
package/.ghaymah.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "3a1850f8-684b-4b16-bf86-2f8d4b58d3bc",
|
|
3
|
+
"name": "sopo-mcp-server",
|
|
4
|
+
"projectId": "dcec3220-caed-40a4-aaa6-d66fbe7533d6",
|
|
5
|
+
"ports": [
|
|
6
|
+
{
|
|
7
|
+
"expose": true,
|
|
8
|
+
"number": 4000
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"publicAccess": {
|
|
12
|
+
"enabled": true,
|
|
13
|
+
"domain": "auto"
|
|
14
|
+
},
|
|
15
|
+
"env": {
|
|
16
|
+
"SOPO_BACKEND_URL": "https://sopo-backend-ebbe5030f148.hosted.ghaymah.systems"
|
|
17
|
+
},
|
|
18
|
+
"resourceTier": "t7",
|
|
19
|
+
"dockerFileName": "Dockerfile"
|
|
20
|
+
}
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Use an official Node.js runtime as a parent image
|
|
2
|
+
FROM node:22-alpine AS builder
|
|
3
|
+
|
|
4
|
+
# Set the working directory in the container
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
# Copy package files to install dependencies
|
|
8
|
+
COPY package*.json ./
|
|
9
|
+
|
|
10
|
+
# Install all dependencies (including devDependencies needed for build)
|
|
11
|
+
RUN npm ci
|
|
12
|
+
|
|
13
|
+
# Copy the rest of the application code
|
|
14
|
+
COPY . .
|
|
15
|
+
|
|
16
|
+
# Build the TypeScript code
|
|
17
|
+
RUN npm run build
|
|
18
|
+
|
|
19
|
+
# Production stage using a smaller image
|
|
20
|
+
FROM node:22-alpine
|
|
21
|
+
|
|
22
|
+
WORKDIR /app
|
|
23
|
+
|
|
24
|
+
# Copy package files
|
|
25
|
+
COPY package*.json ./
|
|
26
|
+
|
|
27
|
+
# Install only production dependencies
|
|
28
|
+
RUN npm ci --omit=dev
|
|
29
|
+
|
|
30
|
+
# Copy compiled files from the builder stage
|
|
31
|
+
COPY --from=builder /app/dist ./dist
|
|
32
|
+
|
|
33
|
+
# Set the environment to production
|
|
34
|
+
ENV NODE_ENV=production
|
|
35
|
+
|
|
36
|
+
# Command to run the MCP server
|
|
37
|
+
CMD ["node", "dist/index.js"]
|
package/GUIDE.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
<div dir="rtl" style="text-align: right; font-family: sans-serif;">
|
|
2
|
+
|
|
3
|
+
# 📘 دليل استخدام Sopo MCP Server
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ❓ إيه هو الـ MCP Server ده؟
|
|
8
|
+
|
|
9
|
+
الـ **MCP (Model Context Protocol)** هو بروتوكول رسمي من Anthropic بيسمح لنماذج الذكاء الاصطناعي (زي Claude) إنها **تتفاعل مباشرة** مع أنظمة وبرامج خارجية.
|
|
10
|
+
|
|
11
|
+
الـ **Sopo MCP Server** هو جسر بين الـ AI وبين **Sopo Backend**، بيخلي الذكاء الاصطناعي يقدر:
|
|
12
|
+
- 📖 **يقرأ** بيانات الـ Gateways والـ Services والـ Routes
|
|
13
|
+
- ✏️ **ينشئ ويعدل ويحذف** أي مورد في المنصة
|
|
14
|
+
- 📊 **يراقب** سجلات الطلبات والمقاييس والإحصائيات
|
|
15
|
+
- 🔧 **ينفذ سيناريوهات معقدة** زي إنشاء بوابة كاملة بضغطة واحدة
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🛠️ إزاي أجهزه؟
|
|
20
|
+
|
|
21
|
+
### الخطوة 1: ضبط ملف `.env`
|
|
22
|
+
|
|
23
|
+
في مجلد `sopo-mcp-server`، افتح ملف `.env` وحط القيم الصحيحة:
|
|
24
|
+
|
|
25
|
+
```env
|
|
26
|
+
# عنوان الباك إند (لو شغال محلياً)
|
|
27
|
+
SOPO_BACKEND_URL=http://localhost:4000
|
|
28
|
+
|
|
29
|
+
# أو لو على السيرفر السحابي
|
|
30
|
+
# SOPO_BACKEND_URL=https://sopo-backend-ebbe5030f148.hosted.ghaymah.systems
|
|
31
|
+
|
|
32
|
+
# التوكن: ده بيبقى JWT Access Token بتاعك
|
|
33
|
+
# تقدر تجيبه لما تعمل Login من الفرونت إند أو من Insomnia
|
|
34
|
+
SOPO_ACCESS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### 💡 إزاي أجيب الـ Access Token؟
|
|
38
|
+
1. سجل دخول من الـ **Sopo Frontend** عادي
|
|
39
|
+
2. افتح **DevTools** في المتصفح (F12)
|
|
40
|
+
3. روح على تاب **Application** → **Cookies** أو **Local Storage**
|
|
41
|
+
4. هتلاقي الـ `accessToken` — انسخه
|
|
42
|
+
5. حطه في `.env` في خانة `SOPO_ACCESS_TOKEN`
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### الخطوة 2: تثبيت وبناء المشروع
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
cd sopo-mcp-server
|
|
50
|
+
npm install
|
|
51
|
+
npm run build
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### الخطوة 3: ربطه بـ Claude Desktop
|
|
57
|
+
|
|
58
|
+
افتح ملف إعدادات Claude Desktop:
|
|
59
|
+
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
60
|
+
- **Mac**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
61
|
+
|
|
62
|
+
أضف الإعداد ده:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"mcpServers": {
|
|
67
|
+
"sopo": {
|
|
68
|
+
"command": "node",
|
|
69
|
+
"args": ["d:/FCI/Fourth/Graduation Project/Code/sopo-mcp-server/dist/index.js"],
|
|
70
|
+
"env": {
|
|
71
|
+
"SOPO_BACKEND_URL": "http://localhost:4000",
|
|
72
|
+
"SOPO_ACCESS_TOKEN": "ضع_التوكن_هنا"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
بعد كده **أعد تشغيل Claude Desktop** وهتلاقي أيقونة 🔧 جنب مربع الكتابة — معناها إن الـ MCP متصل.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### الخطوة 4 (اختياري): الاختبار بالـ MCP Inspector
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm run inspect
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
ده بيفتح واجهة ويب تقدر تجرب منها كل الأدوات يدوياً.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 🤖 الـ AI يقدر يعمل إيه؟
|
|
94
|
+
|
|
95
|
+
### 🔷 إدارة الـ Gateways (البوابات)
|
|
96
|
+
|
|
97
|
+
| الأداة | الوصف |
|
|
98
|
+
|---|---|
|
|
99
|
+
| `list_gateways` | عرض كل البوابات الخاصة بيك |
|
|
100
|
+
| `create_gateway` | إنشاء بوابة جديدة |
|
|
101
|
+
| `update_gateway` | تعديل اسم أو حالة بوابة |
|
|
102
|
+
| `delete_gateway` | حذف بوابة |
|
|
103
|
+
|
|
104
|
+
**مثال محادثة:**
|
|
105
|
+
> 🧑 "اعرض كل البوابات اللي عندي"
|
|
106
|
+
> 🤖 يستدعي `list_gateways` ويعرض القائمة
|
|
107
|
+
> 🧑 "اعمل بوابة جديدة اسمها production-api في وضع pro"
|
|
108
|
+
> 🤖 يستدعي `create_gateway` بالاسم والوضع
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### 🔷 إدارة الـ Services (الخدمات)
|
|
113
|
+
|
|
114
|
+
| الأداة | الوصف |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `list_services` | عرض كل الخدمات |
|
|
117
|
+
| `create_service` | إنشاء خدمة تحت بوابة معينة |
|
|
118
|
+
| `update_service` | تعديل إعدادات الخدمة |
|
|
119
|
+
| `delete_service` | حذف خدمة |
|
|
120
|
+
|
|
121
|
+
**مثال محادثة:**
|
|
122
|
+
> 🧑 "أضف خدمة اسمها user-api تحت البوابة production-api بروتوكول http وتوزيع حمل round_robin"
|
|
123
|
+
> 🤖 يستدعي `create_service` بالمعلومات المطلوبة
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### 🔷 إدارة الـ Service Targets (عناوين الخدمات)
|
|
128
|
+
|
|
129
|
+
| الأداة | الوصف |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `list_service_targets` | عرض كل عناوين URL |
|
|
132
|
+
| `create_service_target` | إضافة عنوان URL لخدمة |
|
|
133
|
+
| `update_service_target` | تعديل العنوان |
|
|
134
|
+
| `delete_service_target` | حذف العنوان |
|
|
135
|
+
|
|
136
|
+
**مثال محادثة:**
|
|
137
|
+
> 🧑 "أضف عنوان https://api.example.com للخدمة user-api بوزن 1"
|
|
138
|
+
> 🤖 يستدعي `create_service_target`
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 🔷 إدارة الـ Routes (المسارات)
|
|
143
|
+
|
|
144
|
+
| الأداة | الوصف |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `list_gateway_routes` | عرض كل المسارات |
|
|
147
|
+
| `create_gateway_route` | إنشاء مسار يربط path بخدمة |
|
|
148
|
+
| `update_gateway_route` | تعديل مسار |
|
|
149
|
+
| `delete_gateway_route` | حذف مسار |
|
|
150
|
+
|
|
151
|
+
**مثال محادثة:**
|
|
152
|
+
> 🧑 "اعمل مسار /api/users على البوابة production-api يوجه للخدمة user-api"
|
|
153
|
+
> 🤖 يستدعي `create_gateway_route`
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
### 🔷 إدارة الـ Plugins (الإضافات/الميدل وير)
|
|
158
|
+
|
|
159
|
+
| الأداة | الوصف |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `list_gateway_plugins` | عرض كل الإضافات |
|
|
162
|
+
| `create_gateway_plugin` | تركيب إضافة على بوابة أو مسار |
|
|
163
|
+
| `update_gateway_plugin` | تعديل إعدادات إضافة |
|
|
164
|
+
| `delete_gateway_plugin` | حذف إضافة |
|
|
165
|
+
|
|
166
|
+
**مثال محادثة:**
|
|
167
|
+
> 🧑 "فعّل rate limiting على البوابة production-api بحد أقصى 100 طلب في الدقيقة"
|
|
168
|
+
> 🤖 يستدعي `create_gateway_plugin` بـ name "rate_limit" و plugin_config مناسب
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### 🔷 إدارة الـ Aggregate Requests (الطلبات المتوازية)
|
|
173
|
+
|
|
174
|
+
| الأداة | الوصف |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `list_aggregate_requests` | عرض الطلبات المتوازية |
|
|
177
|
+
| `create_aggregate_request` | إنشاء طلب متوازي |
|
|
178
|
+
| `update_aggregate_request` | تعديل طلب |
|
|
179
|
+
| `delete_aggregate_request` | حذف طلب |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### 🔷 إدارة الـ Collections (المجموعات)
|
|
184
|
+
|
|
185
|
+
| الأداة | الوصف |
|
|
186
|
+
|---|---|
|
|
187
|
+
| `list_collections` | عرض المجموعات |
|
|
188
|
+
| `create_collection` | إنشاء مجموعة تنظيمية |
|
|
189
|
+
| `update_collection` | تعديل مجموعة |
|
|
190
|
+
| `delete_collection` | حذف مجموعة |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### 🔷 إدارة الـ User Profiles (ملفات المستخدمين)
|
|
195
|
+
|
|
196
|
+
| الأداة | الوصف |
|
|
197
|
+
|---|---|
|
|
198
|
+
| `get_user_profile` | عرض بروفايلك والـ slug بتاعك |
|
|
199
|
+
| `create_user_profile` | إنشاء بروفايل بـ slug جديد |
|
|
200
|
+
| `update_user_profile` | تعديل الـ slug |
|
|
201
|
+
| `delete_user_profile` | حذف البروفايل |
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### 🔷 المراقبة والإحصائيات (Observability)
|
|
206
|
+
|
|
207
|
+
| الأداة | الوصف |
|
|
208
|
+
|---|---|
|
|
209
|
+
| `check_health` | فحص حالة النظام (شغال ولا لا) |
|
|
210
|
+
| `get_resource_stats` | عدد البوابات والخدمات والمسارات والإضافات |
|
|
211
|
+
| `get_request_logs` | سجل الطلبات الأخيرة (من ClickHouse) |
|
|
212
|
+
| `get_hourly_metrics` | إحصائيات كل ساعة (طلبات، أخطاء، زمن استجابة) |
|
|
213
|
+
| `get_hourly_metrics_mv` | نفس الإحصائيات بس أسرع (Materialized View) |
|
|
214
|
+
|
|
215
|
+
**مثال محادثة:**
|
|
216
|
+
> 🧑 "إيه حالة النظام دلوقتي؟"
|
|
217
|
+
> 🤖 يستدعي `check_health` + `get_resource_stats` + `get_hourly_metrics` ويعرض تقرير شامل
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 💬 القوالب الجاهزة (Prompts)
|
|
222
|
+
|
|
223
|
+
دي سيناريوهات معقدة جاهزة بتنفذ عدة خطوات مرة واحدة:
|
|
224
|
+
|
|
225
|
+
### 1. `setup_new_gateway` — إنشاء بوابة كاملة من الصفر
|
|
226
|
+
بيسألك:
|
|
227
|
+
- اسم البوابة
|
|
228
|
+
- عنوان URL للخدمة
|
|
229
|
+
- المسار اللي عايزه
|
|
230
|
+
|
|
231
|
+
وبينفذ تلقائياً: إنشاء Gateway → Service → ServiceTarget → Route
|
|
232
|
+
|
|
233
|
+
### 2. `diagnose_gateway` — تشخيص بوابة
|
|
234
|
+
بيفحص بوابة معينة ويقولك:
|
|
235
|
+
- ✅ الحاجات اللي تمام
|
|
236
|
+
- ⚠️ المشاكل المحتملة
|
|
237
|
+
- 🔧 الإجراءات المقترحة
|
|
238
|
+
|
|
239
|
+
### 3. `platform_report` — تقرير شامل عن المنصة
|
|
240
|
+
بيجمع كل البيانات ويعمل تقرير كامل عن حالة المنصة.
|
|
241
|
+
|
|
242
|
+
### 4. `add_plugin_to_gateway` — إضافة plugin
|
|
243
|
+
بيسألك اسم البوابة ونوع الـ plugin وبيركبه تلقائياً.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## 🎯 أمثلة عملية كاملة
|
|
248
|
+
|
|
249
|
+
### مثال 1: إنشاء بوابة كاملة
|
|
250
|
+
|
|
251
|
+
> 🧑 "عايز أعمل بوابة API كاملة اسمها my-api توجه المسار /users لـ https://jsonplaceholder.typicode.com"
|
|
252
|
+
|
|
253
|
+
الـ AI هيعمل:
|
|
254
|
+
1. `create_gateway` → ينشئ بوابة "my-api"
|
|
255
|
+
2. `create_service` → ينشئ خدمة تحت البوابة
|
|
256
|
+
3. `create_service_target` → يضيف عنوان URL
|
|
257
|
+
4. `create_gateway_route` → يربط المسار /users بالخدمة
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
### مثال 2: تشخيص مشكلة
|
|
262
|
+
|
|
263
|
+
> 🧑 "حاسس إن البوابة بطيئة، اعملي تحليل"
|
|
264
|
+
|
|
265
|
+
الـ AI هيعمل:
|
|
266
|
+
1. `get_resource_stats` → يشوف عدد الموارد
|
|
267
|
+
2. `get_hourly_metrics` → يحلل الأداء
|
|
268
|
+
3. `get_request_logs` → يبحث عن أخطاء أو بطء
|
|
269
|
+
4. يقدم تقرير بالمشاكل والحلول
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### مثال 3: إضافة حماية
|
|
274
|
+
|
|
275
|
+
> 🧑 "عايز أضيف API Key authentication على البوابة my-api"
|
|
276
|
+
|
|
277
|
+
الـ AI هيعمل:
|
|
278
|
+
1. `list_gateways` → يلاقي الـ ID بتاع "my-api"
|
|
279
|
+
2. `create_gateway_plugin` → يركب plugin "apikey" على البوابة
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## ⚙️ ملاحظات مهمة
|
|
284
|
+
|
|
285
|
+
1. **الـ Access Token**: لازم يكون **صالح** (مش منتهي الصلاحية). لو انتهى، سجل دخول تاني وجدد التوكن.
|
|
286
|
+
2. **الـ Backend لازم يكون شغال**: الـ MCP بيتواصل مع الـ Backend عبر HTTP، فلازم الباك إند يكون شغال.
|
|
287
|
+
3. **الصلاحيات**: الـ AI بيشتغل بنفس صلاحيات التوكن اللي إنت حاططه. يعني لو التوكن بتاع يوزر معين، الـ AI هيشوف بس بيانات اليوزر ده (بفضل Hasura RLS).
|
|
288
|
+
4. **الـ Transport**: الـ MCP بيستخدم `stdio` (Standard I/O)، يعني Claude Desktop بيشغل الـ Server كـ process محلي ويتواصل معاه عبر stdin/stdout.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## 📁 هيكل الملفات
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
sopo-mcp-server/
|
|
296
|
+
├── .env ← إعدادات البيئة (التوكن والعنوان)
|
|
297
|
+
├── .env.example ← نموذج الإعدادات
|
|
298
|
+
├── package.json ← التبعيات والسكربتات
|
|
299
|
+
├── tsconfig.json ← إعدادات TypeScript
|
|
300
|
+
├── README.md ← التوثيق بالإنجليزي
|
|
301
|
+
├── GUIDE.md ← الدليل ده (بالعربي)
|
|
302
|
+
├── src/
|
|
303
|
+
│ ├── index.ts ← نقطة البداية الرئيسية
|
|
304
|
+
│ ├── sopo-client.ts ← عميل HTTP للتواصل مع الباك إند
|
|
305
|
+
│ ├── tools/ ← 37 أداة MCP
|
|
306
|
+
│ ├── resources/ ← 3 موارد للقراءة فقط
|
|
307
|
+
│ └── prompts/ ← 4 قوالب جاهزة
|
|
308
|
+
└── dist/ ← الكود المبني (JavaScript)
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
</div>
|
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# sopo-mcp
|
|
2
|
+
|
|
3
|
+
> Model Context Protocol (MCP) server for the **Sopo API Gateway Platform**.
|
|
4
|
+
> Enables AI models (like Claude) to fully manage and monitor the Sopo platform through natural language.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
To install sopo-mcp globally:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install -g sopo-mcp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or install locally in your project:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install sopo-mcp
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
### 🔧 37 Tools (Full CRUD)
|
|
23
|
+
| Domain | Tools | Description |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| **Gateways** | `list_gateways`, `create_gateway`, `update_gateway`, `delete_gateway` | Manage API gateway instances |
|
|
26
|
+
| **Services** | `list_services`, `create_service`, `update_service`, `delete_service` | Manage upstream backends |
|
|
27
|
+
| **Service Targets** | `list_service_targets`, `create_service_target`, `update_service_target`, `delete_service_target` | Manage load balancing URLs |
|
|
28
|
+
| **Routes** | `list_gateway_routes`, `create_gateway_route`, `update_gateway_route`, `delete_gateway_route` | Manage path → service mappings |
|
|
29
|
+
| **Plugins** | `list_gateway_plugins`, `create_gateway_plugin`, `update_gateway_plugin`, `delete_gateway_plugin` | Manage middleware (auth, rate-limit, etc.) |
|
|
30
|
+
| **Aggregation** | `list_aggregate_requests`, `create_aggregate_request`, `update_aggregate_request`, `delete_aggregate_request` | Manage parallel sub-requests |
|
|
31
|
+
| **Collections** | `list_collections`, `create_collection`, `update_collection`, `delete_collection` | Manage organizational groups |
|
|
32
|
+
| **User Profiles** | `get_user_profile`, `create_user_profile`, `update_user_profile`, `delete_user_profile` | Manage user slugs |
|
|
33
|
+
| **Observability** | `check_health`, `get_resource_stats`, `get_request_logs`, `get_hourly_metrics`, `get_hourly_metrics_mv` | Monitor system health and performance |
|
|
34
|
+
|
|
35
|
+
### 📚 3 Resources (Read-Only Context)
|
|
36
|
+
- **Platform Overview** (`sopo://platform/overview`) — Architecture, domain model, and API documentation
|
|
37
|
+
- **Gateway Config** (`sopo://gateways/current-config`) — Live gateway configuration snapshot
|
|
38
|
+
- **Resource Stats** (`sopo://stats/resources`) — Live resource counts
|
|
39
|
+
|
|
40
|
+
### 💬 4 Prompts (Guided Workflows)
|
|
41
|
+
- **`setup_new_gateway`** — Step-by-step gateway creation with service, target, and route
|
|
42
|
+
- **`diagnose_gateway`** — Comprehensive health diagnosis of a gateway
|
|
43
|
+
- **`platform_report`** — Full platform status report
|
|
44
|
+
- **`add_plugin_to_gateway`** — Guided plugin attachment
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
### 1. Configure Environment
|
|
49
|
+
|
|
50
|
+
Set the `SOPO_BACKEND_URL` environment variable pointing to your Sopo backend:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# For Unix/Linux/macOS
|
|
54
|
+
export SOPO_BACKEND_URL=https://sopo-backend-ebbe5030f148.hosted.ghaymah.systems
|
|
55
|
+
|
|
56
|
+
# Windows PowerShell
|
|
57
|
+
$env:SOPO_BACKEND_URL="https://sopo-backend-ebbe5030f148.hosted.ghaymah.systems"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. Usage
|
|
61
|
+
|
|
62
|
+
#### Option A: Use in Claude Desktop
|
|
63
|
+
|
|
64
|
+
Add this to your `claude_desktop_config.json`:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"mcpServers": {
|
|
69
|
+
"sopo": {
|
|
70
|
+
"command": "npx",
|
|
71
|
+
"args": ["sopo-mcp"],
|
|
72
|
+
"env": {
|
|
73
|
+
"SOPO_BACKEND_URL": "https://sopo-backend-ebbe5030f148.hosted.ghaymah.systems"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Option B: Use in Cursor / Windsurf (SSE)
|
|
81
|
+
|
|
82
|
+
If you are using an IDE that supports SSE, you can use the hosted server:
|
|
83
|
+
- **Type:** `SSE`
|
|
84
|
+
- **URL:** `https://sopo-mcp-server-2aa6baac9e7f.hosted.ghaymah.systems`
|
|
85
|
+
|
|
86
|
+
#### Option C: Local Installation from Source
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Clone the repo
|
|
90
|
+
git clone <your-repo-url>
|
|
91
|
+
cd sopo-mcp
|
|
92
|
+
|
|
93
|
+
# Install dependencies
|
|
94
|
+
npm install
|
|
95
|
+
|
|
96
|
+
# Build
|
|
97
|
+
npm run build
|
|
98
|
+
|
|
99
|
+
# Start
|
|
100
|
+
npm start
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 3. Test with MCP Inspector (Optional)
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npm run inspect
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Architecture
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
┌──────────────┐ stdio / SSE ┌──────────────────┐ HTTP ┌──────────────┐
|
|
113
|
+
│ AI Client │ ◄───────────────►│ Sopo MCP Server │ ───────────► │ Sopo Backend │
|
|
114
|
+
│ (Claude etc.)│ │ (Hosted/Local) │ │ (port 4000) │
|
|
115
|
+
└──────────────┘ └──────────────────┘ └──────────────┘
|
|
116
|
+
│ │
|
|
117
|
+
37 Tools Express REST API
|
|
118
|
+
3 Resources │
|
|
119
|
+
4 Prompts Hasura GraphQL
|
|
120
|
+
│
|
|
121
|
+
┌─────┴─────┐
|
|
122
|
+
│PostgreSQL │ │ClickHouse│
|
|
123
|
+
│ (config) │ │ (logs) │
|
|
124
|
+
└───────────┘ └──────────┘
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Package Name
|
|
128
|
+
|
|
129
|
+
The package is published as `sopo-mcp` on npm. Users can install it using:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm install sopo-mcp
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Or run it directly with:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx sopo-mcp
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import 'dotenv/config';
|
|
3
|
+
/**
|
|
4
|
+
* ╔═══════════════════════════════════════════════════════════════╗
|
|
5
|
+
* ║ Sopo MCP Server ║
|
|
6
|
+
* ║ ║
|
|
7
|
+
* ║ Model Context Protocol server for the Sopo API Gateway ║
|
|
8
|
+
* ║ platform. Enables AI models (Claude, etc.) to manage ║
|
|
9
|
+
* ║ gateways, services, routes, plugins, and monitor metrics. ║
|
|
10
|
+
* ╚═══════════════════════════════════════════════════════════════╝
|
|
11
|
+
*
|
|
12
|
+
* Transport: stdio (for Claude Desktop / local AI clients)
|
|
13
|
+
*
|
|
14
|
+
* Environment Variables:
|
|
15
|
+
* SOPO_BACKEND_URL — Base URL of the Sopo Backend (default: http://localhost:4000)
|
|
16
|
+
* SOPO_ACCESS_TOKEN — JWT access token for authentication
|
|
17
|
+
*/
|
|
18
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
19
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
20
|
+
import { configureSopoClient } from './sopo-client.js';
|
|
21
|
+
// ── Tool Registrations ──────────────────────────────────────────
|
|
22
|
+
import { registerAuthTools } from './tools/auth.tools.js';
|
|
23
|
+
import { registerGatewayTools } from './tools/gateway.tools.js';
|
|
24
|
+
import { registerServiceTools } from './tools/service.tools.js';
|
|
25
|
+
import { registerServiceTargetTools } from './tools/service-target.tools.js';
|
|
26
|
+
import { registerGatewayRouteTools } from './tools/gateway-route.tools.js';
|
|
27
|
+
import { registerGatewayPluginTools } from './tools/gateway-plugin.tools.js';
|
|
28
|
+
import { registerAggregateRequestTools } from './tools/aggregate-request.tools.js';
|
|
29
|
+
import { registerCollectionTools } from './tools/collection.tools.js';
|
|
30
|
+
import { registerUserProfileTools } from './tools/user-profile.tools.js';
|
|
31
|
+
import { registerObservabilityTools } from './tools/observability.tools.js';
|
|
32
|
+
// ── Resource Registrations ──────────────────────────────────────
|
|
33
|
+
import { registerResources } from './resources/platform.resources.js';
|
|
34
|
+
// ── Prompt Registrations ────────────────────────────────────────
|
|
35
|
+
import { registerPrompts } from './prompts/sopo.prompts.js';
|
|
36
|
+
// ═══════════════════════════════════════════════════════════════
|
|
37
|
+
// Configuration
|
|
38
|
+
// ═══════════════════════════════════════════════════════════════
|
|
39
|
+
const BACKEND_URL = process.env.SOPO_BACKEND_URL || 'http://localhost:4000';
|
|
40
|
+
const ACCESS_TOKEN = process.env.SOPO_ACCESS_TOKEN || '';
|
|
41
|
+
if (!ACCESS_TOKEN) {
|
|
42
|
+
console.error('⚠️ Warning: SOPO_ACCESS_TOKEN is not set. All API calls will fail with 401 Unauthorized.\n' +
|
|
43
|
+
' Set it via environment variable or .env file.\n' +
|
|
44
|
+
' See .env.example for reference.');
|
|
45
|
+
}
|
|
46
|
+
// ═══════════════════════════════════════════════════════════════
|
|
47
|
+
// Initialize
|
|
48
|
+
// ═══════════════════════════════════════════════════════════════
|
|
49
|
+
// Configure the HTTP client
|
|
50
|
+
configureSopoClient({
|
|
51
|
+
backendUrl: BACKEND_URL,
|
|
52
|
+
accessToken: ACCESS_TOKEN,
|
|
53
|
+
});
|
|
54
|
+
// Create the MCP Server
|
|
55
|
+
const server = new McpServer({
|
|
56
|
+
name: 'sopo-mcp-server',
|
|
57
|
+
version: '1.0.0',
|
|
58
|
+
description: 'MCP Server for the Sopo API Gateway Platform — manage gateways, services, routes, plugins, and monitor metrics via AI.',
|
|
59
|
+
});
|
|
60
|
+
// ═══════════════════════════════════════════════════════════════
|
|
61
|
+
// Register All Capabilities
|
|
62
|
+
// ═══════════════════════════════════════════════════════════════
|
|
63
|
+
// Tools — Authentication (login + refresh)
|
|
64
|
+
registerAuthTools(server); // 2 tools: login, refresh_token
|
|
65
|
+
// Tools (30 tools covering full CRUD for all entities + observability)
|
|
66
|
+
registerGatewayTools(server); // 4 tools: list, create, update, delete
|
|
67
|
+
registerServiceTools(server); // 4 tools: list, create, update, delete
|
|
68
|
+
registerServiceTargetTools(server); // 4 tools: list, create, update, delete
|
|
69
|
+
registerGatewayRouteTools(server); // 4 tools: list, create, update, delete
|
|
70
|
+
registerGatewayPluginTools(server); // 4 tools: list, create, update, delete
|
|
71
|
+
registerAggregateRequestTools(server); // 4 tools: list, create, update, delete
|
|
72
|
+
registerCollectionTools(server); // 4 tools: list, create, update, delete
|
|
73
|
+
registerUserProfileTools(server); // 4 tools: get, create, update, delete
|
|
74
|
+
registerObservabilityTools(server); // 5 tools: health, stats, logs, metrics, metrics-mv
|
|
75
|
+
// Resources (3 resources: platform overview, live config, live stats)
|
|
76
|
+
registerResources(server);
|
|
77
|
+
// Prompts (4 prompts: setup gateway, diagnose, full report, add plugin)
|
|
78
|
+
registerPrompts(server);
|
|
79
|
+
// ═══════════════════════════════════════════════════════════════
|
|
80
|
+
// Start Server
|
|
81
|
+
// ═══════════════════════════════════════════════════════════════
|
|
82
|
+
async function main() {
|
|
83
|
+
const transport = new StdioServerTransport();
|
|
84
|
+
await server.connect(transport);
|
|
85
|
+
console.error('🚀 Sopo MCP Server started successfully');
|
|
86
|
+
console.error(` Backend URL: ${BACKEND_URL}`);
|
|
87
|
+
console.error(` Token: ${ACCESS_TOKEN ? '✅ configured' : '❌ missing'}`);
|
|
88
|
+
console.error(` Tools: 39 | Resources: 3 | Prompts: 4`);
|
|
89
|
+
}
|
|
90
|
+
main().catch((error) => {
|
|
91
|
+
console.error('Fatal error starting Sopo MCP Server:', error);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sopo MCP Server — Prompts
|
|
3
|
+
*
|
|
4
|
+
* Predefined prompt templates that guide the AI for common Sopo operations.
|
|
5
|
+
*/
|
|
6
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
export declare function registerPrompts(server: McpServer): void;
|
|
8
|
+
//# sourceMappingURL=sopo.prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sopo.prompts.d.ts","sourceRoot":"","sources":["../../src/prompts/sopo.prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsHvD"}
|