astrbotmcp 0.3.1__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.
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/PKG-INFO +20 -27
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/README.md +19 -26
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/astrbot_client.py +115 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/config.py +0 -9
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/server.py +10 -2
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/__init__.py +5 -4
- astrbotmcp-0.4.0/astrbot_mcp/tools/mcp_panel_tools.py +135 -0
- astrbotmcp-0.4.0/astrbot_mcp/tools/message/__init__.py +3 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/message/webchat.py +85 -53
- astrbotmcp-0.4.0/astrbot_mcp/tools/plugin_admin_tools.py +344 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/plugin_market_tools.py +28 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools.py +6 -2
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/PKG-INFO +20 -27
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/SOURCES.txt +2 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/pyproject.toml +1 -1
- astrbotmcp-0.4.0/tests/test_smoke.py +86 -0
- astrbotmcp-0.3.1/astrbot_mcp/tools/message/__init__.py +0 -4
- astrbotmcp-0.3.1/tests/test_smoke.py +0 -24
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/LICENSE.txt +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/__init__.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/config_search_tool.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/config_tools.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/control_tools.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/helpers.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/log_tools.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/message/cache.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/message/direct.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/message/quote.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/message/utils.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/platform_tools.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/session_tools.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbot_mcp/tools/types.py +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/dependency_links.txt +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/entry_points.txt +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/requires.txt +0 -0
- {astrbotmcp-0.3.1 → astrbotmcp-0.4.0}/astrbotmcp.egg-info/top_level.txt +0 -0
- {astrbotmcp-0.3.1 → 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
|
+
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
|
[](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,25 +26,7 @@ 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
|
|
|
@@ -120,6 +101,7 @@ npm install -g astrbotmcp
|
|
|
120
101
|
|
|
121
102
|
</details>
|
|
122
103
|
|
|
104
|
+
|
|
123
105
|
#### 环境变量说明
|
|
124
106
|
|
|
125
107
|
| 变量 | 说明 | 默认值 |
|
|
@@ -130,6 +112,7 @@ npm install -g astrbotmcp
|
|
|
130
112
|
| `ASTRBOT_PASSWORD` | Dashboard 密码 | - |
|
|
131
113
|
| `ASTRBOT_LOG_LEVEL` | 日志级别 | `INFO` |
|
|
132
114
|
| `ASTRBOTMCP_DISABLE_PROXY` | 是否禁用代理(防止本地请求被代理拦截) | `true` |
|
|
115
|
+
| `ASTRBOTMCP_PLUGIN_PROXY` | 插件 URL 安装默认代理前缀(`install_astrbot_plugin`) | `https://gh-proxy.com` |
|
|
133
116
|
|
|
134
117
|
#### 代理配置说明
|
|
135
118
|
|
|
@@ -138,10 +121,9 @@ npm install -g astrbotmcp
|
|
|
138
121
|
**解决方案:**
|
|
139
122
|
|
|
140
123
|
1. **默认行为**:AstrBot MCP 默认禁用代理(`ASTRBOTMCP_DISABLE_PROXY=true`),确保本地请求直接发送到 AstrBot。
|
|
141
|
-
|
|
142
124
|
2. **如果需要使用代理**:设置 `ASTRBOTMCP_DISABLE_PROXY=false`,但请注意这可能导致本地 API 请求失败。
|
|
143
|
-
|
|
144
125
|
3. **推荐配置**:对于本地 AstrBot 实例,始终禁用代理:
|
|
126
|
+
|
|
145
127
|
```json
|
|
146
128
|
{
|
|
147
129
|
"mcpServers": {
|
|
@@ -180,13 +162,18 @@ npm install -g astrbotmcp
|
|
|
180
162
|
|
|
181
163
|
#### 消息工具
|
|
182
164
|
|
|
183
|
-
- `send_platform_message` - 通过 Web Chat API
|
|
184
|
-
- `send_platform_message_direct` - 直接发送到平台(绕过 LLM)
|
|
165
|
+
- `send_platform_message` - 通过 Web Chat API 发送消息链(仅 WebUI;无需 `platform_id` / `target_id`)
|
|
185
166
|
- `get_platform_session_messages` - 读取会话消息历史
|
|
186
167
|
|
|
187
168
|
#### 插件市场
|
|
188
169
|
|
|
189
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`)
|
|
190
177
|
|
|
191
178
|
---
|
|
192
179
|
|
|
@@ -211,12 +198,18 @@ logs = get_astrbot_logs(wait_seconds=10)
|
|
|
211
198
|
```python
|
|
212
199
|
# 发送带图片的消息链
|
|
213
200
|
send_platform_message(
|
|
214
|
-
platform_id="webchat",
|
|
215
201
|
message="Hello from MCP",
|
|
216
202
|
images=["/path/to/image.png"]
|
|
217
203
|
)
|
|
218
204
|
```
|
|
219
205
|
|
|
206
|
+
```python
|
|
207
|
+
# 插件命令请直接发送纯文本,不要命令前缀
|
|
208
|
+
send_platform_message(
|
|
209
|
+
message="抽老婆帮助"
|
|
210
|
+
)
|
|
211
|
+
```
|
|
212
|
+
|
|
220
213
|
---
|
|
221
214
|
|
|
222
215
|
### 技术架构
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[](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,25 +12,7 @@
|
|
|
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
|
|
|
@@ -106,6 +87,7 @@ npm install -g astrbotmcp
|
|
|
106
87
|
|
|
107
88
|
</details>
|
|
108
89
|
|
|
90
|
+
|
|
109
91
|
#### 环境变量说明
|
|
110
92
|
|
|
111
93
|
| 变量 | 说明 | 默认值 |
|
|
@@ -116,6 +98,7 @@ npm install -g astrbotmcp
|
|
|
116
98
|
| `ASTRBOT_PASSWORD` | Dashboard 密码 | - |
|
|
117
99
|
| `ASTRBOT_LOG_LEVEL` | 日志级别 | `INFO` |
|
|
118
100
|
| `ASTRBOTMCP_DISABLE_PROXY` | 是否禁用代理(防止本地请求被代理拦截) | `true` |
|
|
101
|
+
| `ASTRBOTMCP_PLUGIN_PROXY` | 插件 URL 安装默认代理前缀(`install_astrbot_plugin`) | `https://gh-proxy.com` |
|
|
119
102
|
|
|
120
103
|
#### 代理配置说明
|
|
121
104
|
|
|
@@ -124,10 +107,9 @@ npm install -g astrbotmcp
|
|
|
124
107
|
**解决方案:**
|
|
125
108
|
|
|
126
109
|
1. **默认行为**:AstrBot MCP 默认禁用代理(`ASTRBOTMCP_DISABLE_PROXY=true`),确保本地请求直接发送到 AstrBot。
|
|
127
|
-
|
|
128
110
|
2. **如果需要使用代理**:设置 `ASTRBOTMCP_DISABLE_PROXY=false`,但请注意这可能导致本地 API 请求失败。
|
|
129
|
-
|
|
130
111
|
3. **推荐配置**:对于本地 AstrBot 实例,始终禁用代理:
|
|
112
|
+
|
|
131
113
|
```json
|
|
132
114
|
{
|
|
133
115
|
"mcpServers": {
|
|
@@ -166,13 +148,18 @@ npm install -g astrbotmcp
|
|
|
166
148
|
|
|
167
149
|
#### 消息工具
|
|
168
150
|
|
|
169
|
-
- `send_platform_message` - 通过 Web Chat API
|
|
170
|
-
- `send_platform_message_direct` - 直接发送到平台(绕过 LLM)
|
|
151
|
+
- `send_platform_message` - 通过 Web Chat API 发送消息链(仅 WebUI;无需 `platform_id` / `target_id`)
|
|
171
152
|
- `get_platform_session_messages` - 读取会话消息历史
|
|
172
153
|
|
|
173
154
|
#### 插件市场
|
|
174
155
|
|
|
175
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`)
|
|
176
163
|
|
|
177
164
|
---
|
|
178
165
|
|
|
@@ -197,12 +184,18 @@ logs = get_astrbot_logs(wait_seconds=10)
|
|
|
197
184
|
```python
|
|
198
185
|
# 发送带图片的消息链
|
|
199
186
|
send_platform_message(
|
|
200
|
-
platform_id="webchat",
|
|
201
187
|
message="Hello from MCP",
|
|
202
188
|
images=["/path/to/image.png"]
|
|
203
189
|
)
|
|
204
190
|
```
|
|
205
191
|
|
|
192
|
+
```python
|
|
193
|
+
# 插件命令请直接发送纯文本,不要命令前缀
|
|
194
|
+
send_platform_message(
|
|
195
|
+
message="抽老婆帮助"
|
|
196
|
+
)
|
|
197
|
+
```
|
|
198
|
+
|
|
206
199
|
---
|
|
207
200
|
|
|
208
201
|
### 技术架构
|
|
@@ -402,6 +402,38 @@ class AstrBotClient:
|
|
|
402
402
|
response = await self._request("POST", "/api/config/astrbot/update", json_body=payload)
|
|
403
403
|
return response.json()
|
|
404
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
|
+
|
|
405
437
|
async def list_session_rules(
|
|
406
438
|
self,
|
|
407
439
|
*,
|
|
@@ -458,6 +490,40 @@ class AstrBotClient:
|
|
|
458
490
|
response = await self._request("GET", "/api/plugin/market_list", params=params or None)
|
|
459
491
|
return response.json()
|
|
460
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
|
+
|
|
461
527
|
# ---- Chat / platform session APIs --------------------------------
|
|
462
528
|
|
|
463
529
|
async def create_platform_session(
|
|
@@ -692,3 +758,52 @@ class AstrBotClient:
|
|
|
692
758
|
"""
|
|
693
759
|
response = await self._request("GET", "/api/stat/version")
|
|
694
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",
|
|
@@ -20,11 +20,12 @@ from .control_tools import restart_astrbot
|
|
|
20
20
|
from .log_tools import get_astrbot_logs
|
|
21
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
|
]
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Literal, Optional
|
|
4
|
+
|
|
5
|
+
from ..astrbot_client import AstrBotClient
|
|
6
|
+
from .helpers import _astrbot_connect_hint, _httpx_error_detail
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def _get_astrbot_log_tail(
|
|
10
|
+
client: AstrBotClient,
|
|
11
|
+
*,
|
|
12
|
+
limit: int = 120,
|
|
13
|
+
) -> Dict[str, Any] | None:
|
|
14
|
+
try:
|
|
15
|
+
hist = await client.get_log_history()
|
|
16
|
+
except Exception as e:
|
|
17
|
+
return {
|
|
18
|
+
"status": "error",
|
|
19
|
+
"message": f"AstrBot API error: {getattr(getattr(e, 'response', None), 'status_code', None) or 'Unknown'}",
|
|
20
|
+
"detail": _httpx_error_detail(e),
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if hist.get("status") != "ok":
|
|
24
|
+
return {
|
|
25
|
+
"status": hist.get("status"),
|
|
26
|
+
"message": hist.get("message"),
|
|
27
|
+
"raw": hist,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
logs = (hist.get("data") or {}).get("logs", [])
|
|
31
|
+
if not isinstance(logs, list):
|
|
32
|
+
return {
|
|
33
|
+
"status": "error",
|
|
34
|
+
"message": "Unexpected /api/log-history response shape (logs is not a list).",
|
|
35
|
+
"raw": hist,
|
|
36
|
+
}
|
|
37
|
+
return {"status": "ok", "logs": logs[-max(1, int(limit)) :]}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
async def manage_mcp_config_panel(
|
|
41
|
+
action: Literal["list", "add", "update", "delete", "test"] = "list",
|
|
42
|
+
name: Optional[str] = None,
|
|
43
|
+
server_config: Optional[Dict[str, Any]] = None,
|
|
44
|
+
active: Optional[bool] = None,
|
|
45
|
+
include_logs: bool = True,
|
|
46
|
+
log_tail_limit: int = 120,
|
|
47
|
+
) -> Dict[str, Any]:
|
|
48
|
+
"""
|
|
49
|
+
Manage AstrBot MCP config panel APIs.
|
|
50
|
+
|
|
51
|
+
Actions:
|
|
52
|
+
- list: GET /api/tools/mcp/servers
|
|
53
|
+
- add: POST /api/tools/mcp/add
|
|
54
|
+
- update: POST /api/tools/mcp/update
|
|
55
|
+
- delete: POST /api/tools/mcp/delete
|
|
56
|
+
- test: POST /api/tools/mcp/test
|
|
57
|
+
"""
|
|
58
|
+
client = AstrBotClient.from_env()
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
if action == "list":
|
|
62
|
+
raw = await client.get_mcp_servers()
|
|
63
|
+
elif action == "add":
|
|
64
|
+
if not name or not str(name).strip():
|
|
65
|
+
return {"status": "error", "message": "name is required for action='add'."}
|
|
66
|
+
if not isinstance(server_config, dict) or not server_config:
|
|
67
|
+
return {
|
|
68
|
+
"status": "error",
|
|
69
|
+
"message": "server_config is required for action='add'.",
|
|
70
|
+
}
|
|
71
|
+
payload = {"name": str(name).strip(), **server_config}
|
|
72
|
+
if active is not None:
|
|
73
|
+
payload["active"] = bool(active)
|
|
74
|
+
raw = await client.add_mcp_server(payload)
|
|
75
|
+
elif action == "update":
|
|
76
|
+
if not name or not str(name).strip():
|
|
77
|
+
return {"status": "error", "message": "name is required for action='update'."}
|
|
78
|
+
payload = {"name": str(name).strip()}
|
|
79
|
+
if isinstance(server_config, dict):
|
|
80
|
+
payload.update(server_config)
|
|
81
|
+
if active is not None:
|
|
82
|
+
payload["active"] = bool(active)
|
|
83
|
+
raw = await client.update_mcp_server(payload)
|
|
84
|
+
elif action == "delete":
|
|
85
|
+
if not name or not str(name).strip():
|
|
86
|
+
return {
|
|
87
|
+
"status": "error",
|
|
88
|
+
"message": "name is required for action='delete'.",
|
|
89
|
+
}
|
|
90
|
+
raw = await client.delete_mcp_server(name=str(name).strip())
|
|
91
|
+
else: # test
|
|
92
|
+
if not isinstance(server_config, dict) or not server_config:
|
|
93
|
+
return {
|
|
94
|
+
"status": "error",
|
|
95
|
+
"message": "server_config is required for action='test'.",
|
|
96
|
+
}
|
|
97
|
+
raw = await client.test_mcp_server_connection(
|
|
98
|
+
mcp_server_config=server_config
|
|
99
|
+
)
|
|
100
|
+
except Exception as e:
|
|
101
|
+
payload = {
|
|
102
|
+
"status": "error",
|
|
103
|
+
"message": _astrbot_connect_hint(client),
|
|
104
|
+
"base_url": client.base_url,
|
|
105
|
+
"detail": _httpx_error_detail(e),
|
|
106
|
+
"action": action,
|
|
107
|
+
"name": name,
|
|
108
|
+
}
|
|
109
|
+
if include_logs:
|
|
110
|
+
payload["astrbot_logs_tail"] = await _get_astrbot_log_tail(
|
|
111
|
+
client, limit=log_tail_limit
|
|
112
|
+
)
|
|
113
|
+
return payload
|
|
114
|
+
|
|
115
|
+
payload: Dict[str, Any] = {
|
|
116
|
+
"status": raw.get("status", "ok"),
|
|
117
|
+
"message": raw.get("message"),
|
|
118
|
+
"action": action,
|
|
119
|
+
"name": name,
|
|
120
|
+
"raw": raw,
|
|
121
|
+
}
|
|
122
|
+
if action == "list" and raw.get("status") == "ok":
|
|
123
|
+
servers = raw.get("data") if isinstance(raw.get("data"), list) else []
|
|
124
|
+
payload["servers"] = servers
|
|
125
|
+
payload["mcp_server_errlogs"] = [
|
|
126
|
+
{"name": s.get("name"), "errlogs": s.get("errlogs")}
|
|
127
|
+
for s in servers
|
|
128
|
+
if isinstance(s, dict) and s.get("errlogs")
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
if include_logs:
|
|
132
|
+
payload["astrbot_logs_tail"] = await _get_astrbot_log_tail(
|
|
133
|
+
client, limit=log_tail_limit
|
|
134
|
+
)
|
|
135
|
+
return payload
|