astrbotmcp 0.3.0__tar.gz → 0.4.0__tar.gz

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.
Files changed (36) hide show
  1. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/PKG-INFO +59 -30
  2. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/README.md +58 -29
  3. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/astrbot_client.py +176 -17
  4. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/config.py +0 -9
  5. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/server.py +10 -2
  6. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/__init__.py +6 -5
  7. astrbotmcp-0.4.0/astrbot_mcp/tools/mcp_panel_tools.py +135 -0
  8. astrbotmcp-0.4.0/astrbot_mcp/tools/message/__init__.py +3 -0
  9. astrbotmcp-0.4.0/astrbot_mcp/tools/message/cache.py +23 -0
  10. astrbotmcp-0.4.0/astrbot_mcp/tools/message/direct.py +252 -0
  11. astrbotmcp-0.4.0/astrbot_mcp/tools/message/quote.py +71 -0
  12. astrbotmcp-0.4.0/astrbot_mcp/tools/message/utils.py +62 -0
  13. astrbotmcp-0.3.0/astrbot_mcp/tools/message_tools.py → astrbotmcp-0.4.0/astrbot_mcp/tools/message/webchat.py +289 -431
  14. astrbotmcp-0.4.0/astrbot_mcp/tools/plugin_admin_tools.py +344 -0
  15. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/plugin_market_tools.py +28 -0
  16. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools.py +6 -2
  17. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/PKG-INFO +59 -30
  18. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/SOURCES.txt +8 -1
  19. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/pyproject.toml +1 -1
  20. astrbotmcp-0.4.0/tests/test_smoke.py +86 -0
  21. astrbotmcp-0.3.0/tests/test_smoke.py +0 -24
  22. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/LICENSE.txt +0 -0
  23. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/__init__.py +0 -0
  24. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/config_search_tool.py +0 -0
  25. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/config_tools.py +0 -0
  26. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/control_tools.py +0 -0
  27. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/helpers.py +0 -0
  28. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/log_tools.py +0 -0
  29. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/platform_tools.py +0 -0
  30. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/session_tools.py +0 -0
  31. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbot_mcp/tools/types.py +0 -0
  32. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/dependency_links.txt +0 -0
  33. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/entry_points.txt +0 -0
  34. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/requires.txt +0 -0
  35. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/top_level.txt +0 -0
  36. {astrbotmcp-0.3.0 → astrbotmcp-0.4.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: astrbotmcp
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -16,9 +16,8 @@ Dynamic: license-file
16
16
 
17
17
  [![MCP Badge](https://lobehub.com/badge/mcp/xunxiing-astrbotmcp)](https://lobehub.com/mcp/xunxiing-astrbotmcp)
18
18
 
19
- > **AstrBot 无法通过 MCP 控制自身。本项目填补了这一空白。**
19
+ > **AstrBot 无法通过 MCP 控制自身。本项目填补了这一空白,为Astrbot开发者提供AI AGENT时代调试插件的自动化工具**
20
20
 
21
- ### 警告与免责声明
22
21
 
23
22
  ⚠️ **本项目提供的是运维级控制能力,使用时请注意:**
24
23
 
@@ -27,30 +26,15 @@ Dynamic: license-file
27
26
  3. **生产环境** - 建议仅在开发/测试环境使用控制面功能
28
27
  4. **数据安全** - 日志可能包含敏感信息,注意脱敏处理
29
28
 
30
- **本项目与 AstrBot 官方无直接关联,由社区独立维护。**
31
-
32
- ---
33
-
34
- ### 这个项目到底在干什么
35
-
36
- #### AstrBot 自身的 MCP 控制面
37
-
38
- 通过 MCP tool 实现:
39
-
40
- - **重启 AstrBot Core** - 进程级控制,直接调用 `/api/stat/restart-core`
41
- - **运行状态监听** - 实时日志流、平台状态监控
42
- - **配置热加载** - 动态读取/修改配置
43
- - **发送信息** -自动化测试插件
44
- - **浏览插件市场**
45
-
46
- #### 为astrbot开发者提供AI AGENT时代调试插件的自动化工具
47
-
48
- ---
29
+ ### **本项目与 AstrBot 官方无直接关联,由社区独立维护。**
49
30
 
50
31
  ### 快速开始
51
32
 
52
33
  #### 安装
53
34
 
35
+ <details>
36
+ <summary>通过 PyPI 或 uv 安装</summary>
37
+
54
38
  ```bash
55
39
  # 通过 PyPI 安装(推荐)
56
40
  pip install astrbotmcp
@@ -59,9 +43,7 @@ pip install astrbotmcp
59
43
  uv add astrbotmcp
60
44
  ```
61
45
 
62
- #### MCP 客户端配置
63
-
64
- 在 Cursor、Cline、Claude Desktop 等支持 MCP 的客户端中配置:
46
+ 安装完成后,您可以通过以下方式在 MCP 客户端中配置:
65
47
 
66
48
  ```json
67
49
  {
@@ -84,6 +66,42 @@ uv add astrbotmcp
84
66
  }
85
67
  ```
86
68
 
69
+ </details>
70
+
71
+ <details>
72
+ <summary>通过 npm 安装(需要先安装 npm)</summary>
73
+
74
+ > 注意:npm 安装方式需要您先在系统中安装 Node.js 和 npm。
75
+
76
+ ```bash
77
+ # 通过 npm 安装
78
+ npm install -g astrbotmcp
79
+ ```
80
+
81
+ 安装完成后,您可以通过以下方式在 MCP 客户端中配置:
82
+
83
+ ```json
84
+ {
85
+ "mcpServers": {
86
+ "astrbot-mcp": {
87
+ "command": "npx",
88
+ "args": [
89
+ "astrbotmcp"
90
+ ],
91
+ "env": {
92
+ "ASTRBOT_BASE_URL": "http://127.0.0.1:6185",
93
+ "ASTRBOT_TIMEOUT": "30",
94
+ "ASTRBOT_USERNAME": "your_username",
95
+ "ASTRBOT_PASSWORD": "your_password"
96
+ }
97
+ }
98
+ }
99
+ }
100
+ ```
101
+
102
+ </details>
103
+
104
+
87
105
  #### 环境变量说明
88
106
 
89
107
  | 变量 | 说明 | 默认值 |
@@ -94,6 +112,7 @@ uv add astrbotmcp
94
112
  | `ASTRBOT_PASSWORD` | Dashboard 密码 | - |
95
113
  | `ASTRBOT_LOG_LEVEL` | 日志级别 | `INFO` |
96
114
  | `ASTRBOTMCP_DISABLE_PROXY` | 是否禁用代理(防止本地请求被代理拦截) | `true` |
115
+ | `ASTRBOTMCP_PLUGIN_PROXY` | 插件 URL 安装默认代理前缀(`install_astrbot_plugin`) | `https://gh-proxy.com` |
97
116
 
98
117
  #### 代理配置说明
99
118
 
@@ -102,10 +121,9 @@ uv add astrbotmcp
102
121
  **解决方案:**
103
122
 
104
123
  1. **默认行为**:AstrBot MCP 默认禁用代理(`ASTRBOTMCP_DISABLE_PROXY=true`),确保本地请求直接发送到 AstrBot。
105
-
106
124
  2. **如果需要使用代理**:设置 `ASTRBOTMCP_DISABLE_PROXY=false`,但请注意这可能导致本地 API 请求失败。
107
-
108
125
  3. **推荐配置**:对于本地 AstrBot 实例,始终禁用代理:
126
+
109
127
  ```json
110
128
  {
111
129
  "mcpServers": {
@@ -144,13 +162,18 @@ uv add astrbotmcp
144
162
 
145
163
  #### 消息工具
146
164
 
147
- - `send_platform_message` - 通过 Web Chat API 发送消息链
148
- - `send_platform_message_direct` - 直接发送到平台(绕过 LLM)
165
+ - `send_platform_message` - 通过 Web Chat API 发送消息链(仅 WebUI;无需 `platform_id` / `target_id`)
149
166
  - `get_platform_session_messages` - 读取会话消息历史
150
167
 
151
168
  #### 插件市场
152
169
 
153
170
  - `browse_plugin_market` - 浏览插件市场(搜索/排序)
171
+ - `install_astrbot_plugin` - Install plugin via URL or local zip path (proxy enabled by default)
172
+ - `configure_astrbot_plugin_json` - Configure plugin JSON by reusing AstrBot config ops
173
+
174
+ #### MCP 面板
175
+
176
+ - `manage_mcp_config_panel` - Access MCP panel APIs (`list` / `add` / `update` / `delete` / `test`)
154
177
 
155
178
  ---
156
179
 
@@ -175,12 +198,18 @@ logs = get_astrbot_logs(wait_seconds=10)
175
198
  ```python
176
199
  # 发送带图片的消息链
177
200
  send_platform_message(
178
- platform_id="webchat",
179
201
  message="Hello from MCP",
180
202
  images=["/path/to/image.png"]
181
203
  )
182
204
  ```
183
205
 
206
+ ```python
207
+ # 插件命令请直接发送纯文本,不要命令前缀
208
+ send_platform_message(
209
+ message="抽老婆帮助"
210
+ )
211
+ ```
212
+
184
213
  ---
185
214
 
186
215
  ### 技术架构
@@ -2,9 +2,8 @@
2
2
 
3
3
  [![MCP Badge](https://lobehub.com/badge/mcp/xunxiing-astrbotmcp)](https://lobehub.com/mcp/xunxiing-astrbotmcp)
4
4
 
5
- > **AstrBot 无法通过 MCP 控制自身。本项目填补了这一空白。**
5
+ > **AstrBot 无法通过 MCP 控制自身。本项目填补了这一空白,为Astrbot开发者提供AI AGENT时代调试插件的自动化工具**
6
6
 
7
- ### 警告与免责声明
8
7
 
9
8
  ⚠️ **本项目提供的是运维级控制能力,使用时请注意:**
10
9
 
@@ -13,30 +12,15 @@
13
12
  3. **生产环境** - 建议仅在开发/测试环境使用控制面功能
14
13
  4. **数据安全** - 日志可能包含敏感信息,注意脱敏处理
15
14
 
16
- **本项目与 AstrBot 官方无直接关联,由社区独立维护。**
17
-
18
- ---
19
-
20
- ### 这个项目到底在干什么
21
-
22
- #### AstrBot 自身的 MCP 控制面
23
-
24
- 通过 MCP tool 实现:
25
-
26
- - **重启 AstrBot Core** - 进程级控制,直接调用 `/api/stat/restart-core`
27
- - **运行状态监听** - 实时日志流、平台状态监控
28
- - **配置热加载** - 动态读取/修改配置
29
- - **发送信息** -自动化测试插件
30
- - **浏览插件市场**
31
-
32
- #### 为astrbot开发者提供AI AGENT时代调试插件的自动化工具
33
-
34
- ---
15
+ ### **本项目与 AstrBot 官方无直接关联,由社区独立维护。**
35
16
 
36
17
  ### 快速开始
37
18
 
38
19
  #### 安装
39
20
 
21
+ <details>
22
+ <summary>通过 PyPI 或 uv 安装</summary>
23
+
40
24
  ```bash
41
25
  # 通过 PyPI 安装(推荐)
42
26
  pip install astrbotmcp
@@ -45,9 +29,7 @@ pip install astrbotmcp
45
29
  uv add astrbotmcp
46
30
  ```
47
31
 
48
- #### MCP 客户端配置
49
-
50
- 在 Cursor、Cline、Claude Desktop 等支持 MCP 的客户端中配置:
32
+ 安装完成后,您可以通过以下方式在 MCP 客户端中配置:
51
33
 
52
34
  ```json
53
35
  {
@@ -70,6 +52,42 @@ uv add astrbotmcp
70
52
  }
71
53
  ```
72
54
 
55
+ </details>
56
+
57
+ <details>
58
+ <summary>通过 npm 安装(需要先安装 npm)</summary>
59
+
60
+ > 注意:npm 安装方式需要您先在系统中安装 Node.js 和 npm。
61
+
62
+ ```bash
63
+ # 通过 npm 安装
64
+ npm install -g astrbotmcp
65
+ ```
66
+
67
+ 安装完成后,您可以通过以下方式在 MCP 客户端中配置:
68
+
69
+ ```json
70
+ {
71
+ "mcpServers": {
72
+ "astrbot-mcp": {
73
+ "command": "npx",
74
+ "args": [
75
+ "astrbotmcp"
76
+ ],
77
+ "env": {
78
+ "ASTRBOT_BASE_URL": "http://127.0.0.1:6185",
79
+ "ASTRBOT_TIMEOUT": "30",
80
+ "ASTRBOT_USERNAME": "your_username",
81
+ "ASTRBOT_PASSWORD": "your_password"
82
+ }
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ </details>
89
+
90
+
73
91
  #### 环境变量说明
74
92
 
75
93
  | 变量 | 说明 | 默认值 |
@@ -80,6 +98,7 @@ uv add astrbotmcp
80
98
  | `ASTRBOT_PASSWORD` | Dashboard 密码 | - |
81
99
  | `ASTRBOT_LOG_LEVEL` | 日志级别 | `INFO` |
82
100
  | `ASTRBOTMCP_DISABLE_PROXY` | 是否禁用代理(防止本地请求被代理拦截) | `true` |
101
+ | `ASTRBOTMCP_PLUGIN_PROXY` | 插件 URL 安装默认代理前缀(`install_astrbot_plugin`) | `https://gh-proxy.com` |
83
102
 
84
103
  #### 代理配置说明
85
104
 
@@ -88,10 +107,9 @@ uv add astrbotmcp
88
107
  **解决方案:**
89
108
 
90
109
  1. **默认行为**:AstrBot MCP 默认禁用代理(`ASTRBOTMCP_DISABLE_PROXY=true`),确保本地请求直接发送到 AstrBot。
91
-
92
110
  2. **如果需要使用代理**:设置 `ASTRBOTMCP_DISABLE_PROXY=false`,但请注意这可能导致本地 API 请求失败。
93
-
94
111
  3. **推荐配置**:对于本地 AstrBot 实例,始终禁用代理:
112
+
95
113
  ```json
96
114
  {
97
115
  "mcpServers": {
@@ -130,13 +148,18 @@ uv add astrbotmcp
130
148
 
131
149
  #### 消息工具
132
150
 
133
- - `send_platform_message` - 通过 Web Chat API 发送消息链
134
- - `send_platform_message_direct` - 直接发送到平台(绕过 LLM)
151
+ - `send_platform_message` - 通过 Web Chat API 发送消息链(仅 WebUI;无需 `platform_id` / `target_id`)
135
152
  - `get_platform_session_messages` - 读取会话消息历史
136
153
 
137
154
  #### 插件市场
138
155
 
139
156
  - `browse_plugin_market` - 浏览插件市场(搜索/排序)
157
+ - `install_astrbot_plugin` - Install plugin via URL or local zip path (proxy enabled by default)
158
+ - `configure_astrbot_plugin_json` - Configure plugin JSON by reusing AstrBot config ops
159
+
160
+ #### MCP 面板
161
+
162
+ - `manage_mcp_config_panel` - Access MCP panel APIs (`list` / `add` / `update` / `delete` / `test`)
140
163
 
141
164
  ---
142
165
 
@@ -161,12 +184,18 @@ logs = get_astrbot_logs(wait_seconds=10)
161
184
  ```python
162
185
  # 发送带图片的消息链
163
186
  send_platform_message(
164
- platform_id="webchat",
165
187
  message="Hello from MCP",
166
188
  images=["/path/to/image.png"]
167
189
  )
168
190
  ```
169
191
 
192
+ ```python
193
+ # 插件命令请直接发送纯文本,不要命令前缀
194
+ send_platform_message(
195
+ message="抽老婆帮助"
196
+ )
197
+ ```
198
+
170
199
  ---
171
200
 
172
201
  ### 技术架构
@@ -98,7 +98,16 @@ class AstrBotClient:
98
98
  pwd = hashlib.md5(pwd.encode("utf-8")).hexdigest()
99
99
 
100
100
  url = f"{self.base_url}/api/auth/login"
101
- client_kwargs = {"timeout": self.timeout}
101
+ # SSE endpoints can legitimately stay quiet for a long time while work is happening.
102
+ # Use an infinite read timeout, while keeping connect/write/pool bounded.
103
+ client_kwargs = {
104
+ "timeout": httpx.Timeout(
105
+ connect=self.timeout,
106
+ read=None,
107
+ write=self.timeout,
108
+ pool=self.timeout,
109
+ )
110
+ }
102
111
  if self.settings.disable_proxy:
103
112
  client_kwargs["trust_env"] = False # 禁用代理,忽略环境变量设置
104
113
 
@@ -175,9 +184,12 @@ class AstrBotClient:
175
184
  max_events: Optional[int] = None,
176
185
  ) -> List[Dict[str, Any]]:
177
186
  """
178
- Consume a simple SSE endpoint and return parsed JSON payloads.
187
+ Consume an SSE endpoint and return parsed event payloads.
179
188
 
180
- AstrBot's SSE endpoints use `data: {...}\\n\\n` format per event.
189
+ AstrBot's SSE endpoints typically use `data: {...}\\n\\n` format per event.
190
+ This parser is tolerant:
191
+ - Supports multi-line `data:` frames per SSE spec (joined with `\\n`).
192
+ - If `data:` is not valid JSON, returns it as `{\"type\":\"raw\",\"data\":...}`.
181
193
 
182
194
  `max_seconds` is a soft upper bound for how long we wait:
183
195
  - 如果持续有事件流入,最多等待约 `max_seconds` 秒;
@@ -223,31 +235,63 @@ class AstrBotClient:
223
235
  )
224
236
 
225
237
  async def consume() -> None:
226
- async for line in response.aiter_lines():
227
- if not line:
228
- # Heartbeats / blank lines
229
- continue
230
-
231
- if not line.startswith("data:"):
232
- continue
238
+ current_event: str | None = None
239
+ data_lines: List[str] = []
233
240
 
234
- _, data_str = line.split("data:", 1)
235
- data_str = data_str.strip()
241
+ def flush() -> None:
242
+ nonlocal current_event, data_lines
243
+ if not data_lines:
244
+ current_event = None
245
+ return
246
+ data_str = "\n".join(data_lines).strip()
247
+ data_lines = []
236
248
 
237
249
  if not data_str:
238
- continue
250
+ current_event = None
251
+ return
239
252
 
240
253
  try:
241
254
  payload = json.loads(data_str)
242
255
  except json.JSONDecodeError:
243
- continue
256
+ payload = None
244
257
 
245
258
  if isinstance(payload, dict):
259
+ if current_event and "event" not in payload:
260
+ payload = {**payload, "event": current_event}
246
261
  events.append(payload)
262
+ else:
263
+ events.append(
264
+ {
265
+ "type": "raw",
266
+ "event": current_event,
267
+ "data": data_str,
268
+ }
269
+ )
270
+ current_event = None
247
271
 
248
- if max_events is not None and len(events) >= max_events:
249
- # Enough events collected; stop consuming.
250
- break
272
+ async for line in response.aiter_lines():
273
+ # Blank line terminates an SSE event.
274
+ if line == "":
275
+ flush()
276
+ if max_events is not None and len(events) >= max_events:
277
+ break
278
+ continue
279
+
280
+ # Comments / heartbeats
281
+ if line.startswith(":"):
282
+ continue
283
+
284
+ if line.startswith("event:"):
285
+ current_event = line.split("event:", 1)[1].strip() or None
286
+ continue
287
+
288
+ if line.startswith("data:"):
289
+ data_lines.append(line.split("data:", 1)[1].lstrip())
290
+ continue
291
+
292
+ continue
293
+
294
+ flush()
251
295
 
252
296
  if max_seconds is not None and max_seconds > 0:
253
297
  try:
@@ -358,6 +402,38 @@ class AstrBotClient:
358
402
  response = await self._request("POST", "/api/config/astrbot/update", json_body=payload)
359
403
  return response.json()
360
404
 
405
+ async def get_plugin_config(
406
+ self,
407
+ *,
408
+ plugin_name: str,
409
+ ) -> Dict[str, Any]:
410
+ """
411
+ Get plugin config via /api/config/get?plugin_name=<name>.
412
+ """
413
+ response = await self._request(
414
+ "GET",
415
+ "/api/config/get",
416
+ params={"plugin_name": plugin_name},
417
+ )
418
+ return response.json()
419
+
420
+ async def update_plugin_config(
421
+ self,
422
+ *,
423
+ plugin_name: str,
424
+ config: Dict[str, Any],
425
+ ) -> Dict[str, Any]:
426
+ """
427
+ Update plugin config via /api/config/plugin/update?plugin_name=<name>.
428
+ """
429
+ response = await self._request(
430
+ "POST",
431
+ "/api/config/plugin/update",
432
+ params={"plugin_name": plugin_name},
433
+ json_body=config,
434
+ )
435
+ return response.json()
436
+
361
437
  async def list_session_rules(
362
438
  self,
363
439
  *,
@@ -414,6 +490,40 @@ class AstrBotClient:
414
490
  response = await self._request("GET", "/api/plugin/market_list", params=params or None)
415
491
  return response.json()
416
492
 
493
+ async def install_plugin_from_url(
494
+ self,
495
+ *,
496
+ url: str,
497
+ proxy: str | None = None,
498
+ ) -> Dict[str, Any]:
499
+ """
500
+ Install a plugin from repository URL via /api/plugin/install.
501
+ """
502
+ payload: Dict[str, Any] = {"url": url}
503
+ if proxy:
504
+ payload["proxy"] = proxy
505
+ response = await self._request("POST", "/api/plugin/install", json_body=payload)
506
+ return response.json()
507
+
508
+ async def install_plugin_from_file(
509
+ self,
510
+ file_path: str,
511
+ ) -> Dict[str, Any]:
512
+ """
513
+ Install a plugin from uploaded zip file via /api/plugin/install-upload.
514
+ """
515
+ send_name = os.path.basename(file_path)
516
+ with open(file_path, "rb") as f:
517
+ files = {
518
+ "file": (send_name, f, "application/zip"),
519
+ }
520
+ response = await self._request(
521
+ "POST",
522
+ "/api/plugin/install-upload",
523
+ files=files,
524
+ )
525
+ return response.json()
526
+
417
527
  # ---- Chat / platform session APIs --------------------------------
418
528
 
419
529
  async def create_platform_session(
@@ -648,3 +758,52 @@ class AstrBotClient:
648
758
  """
649
759
  response = await self._request("GET", "/api/stat/version")
650
760
  return response.json()
761
+
762
+ # ---- MCP panel APIs ----------------------------------------------
763
+
764
+ async def get_mcp_servers(self) -> Dict[str, Any]:
765
+ """
766
+ Get MCP server list from panel API /api/tools/mcp/servers.
767
+ """
768
+ response = await self._request("GET", "/api/tools/mcp/servers")
769
+ return response.json()
770
+
771
+ async def add_mcp_server(self, payload: Dict[str, Any]) -> Dict[str, Any]:
772
+ """
773
+ Add MCP server via panel API /api/tools/mcp/add.
774
+ """
775
+ response = await self._request("POST", "/api/tools/mcp/add", json_body=payload)
776
+ return response.json()
777
+
778
+ async def update_mcp_server(self, payload: Dict[str, Any]) -> Dict[str, Any]:
779
+ """
780
+ Update MCP server via panel API /api/tools/mcp/update.
781
+ """
782
+ response = await self._request("POST", "/api/tools/mcp/update", json_body=payload)
783
+ return response.json()
784
+
785
+ async def delete_mcp_server(self, *, name: str) -> Dict[str, Any]:
786
+ """
787
+ Delete MCP server via panel API /api/tools/mcp/delete.
788
+ """
789
+ response = await self._request(
790
+ "POST",
791
+ "/api/tools/mcp/delete",
792
+ json_body={"name": name},
793
+ )
794
+ return response.json()
795
+
796
+ async def test_mcp_server_connection(
797
+ self,
798
+ *,
799
+ mcp_server_config: Dict[str, Any],
800
+ ) -> Dict[str, Any]:
801
+ """
802
+ Test MCP connection via panel API /api/tools/mcp/test.
803
+ """
804
+ response = await self._request(
805
+ "POST",
806
+ "/api/tools/mcp/test",
807
+ json_body={"mcp_server_config": mcp_server_config},
808
+ )
809
+ return response.json()
@@ -15,7 +15,6 @@ class AstrBotSettings:
15
15
  default_provider: str | None = None
16
16
  default_model: str | None = None
17
17
  file_root: str | None = None
18
- direct_media_mode: str | None = None
19
18
  disable_proxy: bool = True # 默认禁用代理,防止本地请求被代理拦截
20
19
 
21
20
 
@@ -41,10 +40,6 @@ def get_settings() -> AstrBotSettings:
41
40
  - ASTRBOT_DEFAULT_PROVIDER: Default provider id to use for /api/chat/send.
42
41
  - ASTRBOT_DEFAULT_MODEL: Default model id to use for /api/chat/send.
43
42
  - ASTRBOTMCP_FILE_ROOT: Base directory for resolving relative local file_path.
44
- - ASTRBOTMCP_DIRECT_MEDIA_MODE: How send_platform_message_direct handles local media:
45
- - auto (default): try local path first, then fallback to upload+URL.
46
- - local: always send local absolute paths to AstrBot platform adapters.
47
- - upload: upload to AstrBot first and send an http(s) URL.
48
43
  """
49
44
  base_url = _get_env("ASTRBOT_BASE_URL")
50
45
  if not base_url:
@@ -69,9 +64,6 @@ def get_settings() -> AstrBotSettings:
69
64
  default_provider = _get_env("ASTRBOT_DEFAULT_PROVIDER")
70
65
  default_model = _get_env("ASTRBOT_DEFAULT_MODEL")
71
66
  file_root = _get_env("ASTRBOTMCP_FILE_ROOT") or _get_env("ASTRBOT_MCP_FILE_ROOT")
72
- direct_media_mode = _get_env("ASTRBOTMCP_DIRECT_MEDIA_MODE") or _get_env(
73
- "ASTRBOT_MCP_DIRECT_MEDIA_MODE"
74
- )
75
67
 
76
68
  # 默认禁用代理,除非明确设置为false
77
69
  disable_proxy_str = _get_env("ASTRBOTMCP_DISABLE_PROXY")
@@ -87,6 +79,5 @@ def get_settings() -> AstrBotSettings:
87
79
  default_provider=default_provider,
88
80
  default_model=default_model,
89
81
  file_root=file_root,
90
- direct_media_mode=direct_media_mode,
91
82
  disable_proxy=disable_proxy,
92
83
  )
@@ -15,6 +15,7 @@ server = FastMCP(
15
15
  "MCP server for interacting with an existing AstrBot instance. "
16
16
  "Provides tools to read logs, list configured message platforms, "
17
17
  "send message chains (including files) via the web chat API, "
18
+ "install/configure plugins, manage MCP panel config, "
18
19
  "restart AstrBot core, read platform session message history, "
19
20
  "and browse the AstrBot plugin market."
20
21
  ),
@@ -23,7 +24,6 @@ server = FastMCP(
23
24
  # Register tools with FastMCP
24
25
  server.tool(astrbot_tools.get_astrbot_logs, name="get_astrbot_logs")
25
26
  server.tool(astrbot_tools.get_message_platforms, name="get_message_platforms")
26
- server.tool(astrbot_tools.send_platform_message_direct, name="send_platform_message_direct")
27
27
  server.tool(astrbot_tools.send_platform_message, name="send_platform_message")
28
28
  server.tool(astrbot_tools.restart_astrbot, name="restart_astrbot")
29
29
  server.tool(
@@ -31,6 +31,12 @@ server.tool(
31
31
  name="get_platform_session_messages",
32
32
  )
33
33
  server.tool(astrbot_tools.browse_plugin_market, name="browse_plugin_market")
34
+ server.tool(astrbot_tools.install_astrbot_plugin, name="install_astrbot_plugin")
35
+ server.tool(
36
+ astrbot_tools.configure_astrbot_plugin_json,
37
+ name="configure_astrbot_plugin_json",
38
+ )
39
+ server.tool(astrbot_tools.manage_mcp_config_panel, name="manage_mcp_config_panel")
34
40
  server.tool(astrbot_tools.list_astrbot_config_files, name="list_astrbot_config_files")
35
41
  server.tool(astrbot_tools.inspect_astrbot_config, name="inspect_astrbot_config")
36
42
  server.tool(astrbot_tools.apply_astrbot_config_ops, name="apply_astrbot_config_ops")
@@ -49,10 +55,12 @@ def astrbot_info():
49
55
  "get_astrbot_logs",
50
56
  "get_message_platforms",
51
57
  "send_platform_message",
52
- "send_platform_message_direct",
53
58
  "restart_astrbot",
54
59
  "get_platform_session_messages",
55
60
  "browse_plugin_market",
61
+ "install_astrbot_plugin",
62
+ "configure_astrbot_plugin_json",
63
+ "manage_mcp_config_panel",
56
64
  "list_astrbot_config_files",
57
65
  "inspect_astrbot_config",
58
66
  "apply_astrbot_config_ops",
@@ -18,13 +18,14 @@ All functions are re-exported from this module for convenience.
18
18
  # 导入所有工具函数,保持向后兼容
19
19
  from .control_tools import restart_astrbot
20
20
  from .log_tools import get_astrbot_logs
21
- from .message_tools import (
21
+ from .message import (
22
22
  send_platform_message,
23
- send_platform_message_direct,
24
23
  )
25
24
  from .platform_tools import get_message_platforms
26
25
  from .session_tools import get_platform_session_messages
27
26
  from .plugin_market_tools import browse_plugin_market
27
+ from .plugin_admin_tools import install_astrbot_plugin, configure_astrbot_plugin_json
28
+ from .mcp_panel_tools import manage_mcp_config_panel
28
29
  from .config_tools import (
29
30
  list_astrbot_config_files,
30
31
  inspect_astrbot_config,
@@ -40,7 +41,6 @@ from .helpers import (
40
41
  _as_file_uri,
41
42
  _attachment_download_url,
42
43
  _astrbot_connect_hint,
43
- _direct_media_mode,
44
44
  _httpx_error_detail,
45
45
  _resolve_local_file_path,
46
46
  )
@@ -49,11 +49,13 @@ __all__ = [
49
49
  # 工具函数
50
50
  "get_astrbot_logs",
51
51
  "get_message_platforms",
52
- "send_platform_message_direct",
53
52
  "send_platform_message",
54
53
  "restart_astrbot",
55
54
  "get_platform_session_messages",
56
55
  "browse_plugin_market",
56
+ "install_astrbot_plugin",
57
+ "configure_astrbot_plugin_json",
58
+ "manage_mcp_config_panel",
57
59
  "list_astrbot_config_files",
58
60
  "inspect_astrbot_config",
59
61
  "apply_astrbot_config_ops",
@@ -67,6 +69,5 @@ __all__ = [
67
69
  "_attachment_download_url",
68
70
  "_astrbot_connect_hint",
69
71
  "_httpx_error_detail",
70
- "_direct_media_mode",
71
72
  "_as_file_uri",
72
73
  ]