Compare commits
1 Commits
master
...
codex/igno
| Author | SHA1 | Date |
|---|---|---|
|
|
0e39635a04 |
|
|
@ -0,0 +1,6 @@
|
|||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
.idea/
|
||||
.opencode/
|
||||
|
|
@ -3,5 +3,4 @@
|
|||
<component name="Black">
|
||||
<option name="sdkName" value="loratest" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
|
|
@ -14,24 +14,7 @@
|
|||
"name": "MiniMax-M2.7"
|
||||
}
|
||||
}
|
||||
},
|
||||
"glm-5.1": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "GLM-5.1 Self-hosted",
|
||||
"options": {
|
||||
"baseURL": "https://www.glmfast.ai4mats.com/v1",
|
||||
"apiKey": "sk-glm-96de15fe331cd6955929bbd4469e641fe2541afa8e09758dea0c9cbce257e0c3 "
|
||||
},
|
||||
"models": {
|
||||
"glm-5.1-fast": { "name": "GLM-5.1-fast",
|
||||
"limit": {
|
||||
"context": 30000,
|
||||
"output": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"bayesian-analysis": {
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
---
|
||||
name: create-code
|
||||
description: 当用户需要新增代码配置时,请使用此技能。
|
||||
triggers:
|
||||
- "新增代码配置"
|
||||
- "创建代码配置"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 创建代码配置(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要创建一个新的代码配置
|
||||
- 用户提到“创建代码配置”“新建代码配置”“调用创建代码配置 API”
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- 代码仓库名称 `code_repo_name`
|
||||
- Git 地址 `git_url`
|
||||
- 代码分支/Tag `git_branch`
|
||||
|
||||
4. **创建代码配置**
|
||||
- 调用`scripts/create_code_mcp_server.create_code`方法
|
||||
- 参数:`token`(来自步骤2), `code_repo_name`(来自步骤3), `git_url`(来自步骤3), `git_branch`(来自步骤3)
|
||||
|
||||
5. **反馈结果**
|
||||
- ✅ 成功:返回创建结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_code(
|
||||
token: str,
|
||||
code_repo_name: str,
|
||||
git_url: str,
|
||||
git_branch: str,
|
||||
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/codeConfig"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"code_repo_name": code_repo_name,
|
||||
"is_public": True,
|
||||
"git_url": git_url,
|
||||
"git_branch": git_branch
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型版本失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
---
|
||||
name: create-image
|
||||
description: 当用户需要新增镜像时,请使用此技能。
|
||||
triggers:
|
||||
- "新增镜像"
|
||||
- "创建镜像"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 创建镜像(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要创建一个新的镜像
|
||||
- 用户提到“创建镜像”“新建镜像”“调用创建镜像 API”
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- 镜像名称 `name`
|
||||
- 版本名称 `tag_name`
|
||||
- 镜像描述 `description`
|
||||
- 版本描述 `version_description`
|
||||
- 公网镜像地址 `path`
|
||||
|
||||
4. **创建镜像**
|
||||
- 调用`scripts/create_image_mcp_server.create_image`方法
|
||||
- 参数:`token`(来自步骤2), `name`(来自步骤3), `tag_name`(来自步骤3), `description`(来自步骤3), `version_description`(来自步骤3), `path`(来自步骤3)
|
||||
|
||||
5. **反馈结果**
|
||||
- ✅ 成功:返回创建结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_image(
|
||||
token: str,
|
||||
name: str,
|
||||
tag_name: str,
|
||||
description: str,
|
||||
version_description: str,
|
||||
path: str,
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/image/addImageAndVersion"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"upload_type": 0,
|
||||
"is_public": False,
|
||||
"tag_name": tag_name,
|
||||
"description": description,
|
||||
"name": name,
|
||||
"version_description": version_description,
|
||||
"path": path
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型版本失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
---
|
||||
name: create-model
|
||||
description: 当用户需要新增模型时,请使用此技能。
|
||||
triggers:
|
||||
- "新增模型"
|
||||
- "创建模型"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 创建模型(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要创建一个新的模型
|
||||
- 用户提到“创建模型”“新建模型”“调用创建模型 API”
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 模型名称 `name`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **查询模型类型列表**
|
||||
- 调用`scripts/model_mcp_server.query_model_type_list`方法
|
||||
- 结果中的二级目录`second_asset_icon_list`字段的`name`为所有的模型类型
|
||||
|
||||
4. **输入参数**
|
||||
- 模型类型 `model_type` (范围来自于步骤3的结果,不能超出范围)
|
||||
- 模型标签 `model_tag`
|
||||
|
||||
5. **创建模型**
|
||||
- 调用`scripts/model_mcp_server.create_model`方法
|
||||
- 参数:`token`(来自步骤2), `name`(来自步骤1), `model_tag`(来自步骤4), `model_type`(来自步骤4)
|
||||
|
||||
6. **反馈结果**
|
||||
- ✅ 成功:返回模型名称和创建结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
7. **询问是否创建模型版本**
|
||||
- 如果创建模型成功,则继续询问用户是否需要创建模型版本
|
||||
- 用户回答是则进行以下步骤,否则终止。
|
||||
|
||||
8. **输入版本描述**
|
||||
- 输入版本描述version_desc
|
||||
|
||||
9. **上传文件**
|
||||
- 调用`scripts/upload_file.upload_file`方法分片上传文件
|
||||
- 参数:`token`(来自步骤2), file_path
|
||||
|
||||
10. **获取最新的版本号**
|
||||
- 调用`scripts/model_mcp_server.query_next_version`方法获取最新的版本号
|
||||
- 参数:`token`(来自步骤2), `identifier`(来自步骤6), `owner`:username
|
||||
|
||||
11. **创建模型版本**
|
||||
- 调用`scripts/model_mcp_server.create_model_version`方法
|
||||
- 参数:`token`(来自步骤2), `git_id`(来自步骤6), `id`(来自步骤6), `identifier`(来自步骤6), `file_path`(来自步骤9的输入), `file_data`(来自步骤9的结果), `name`:name, `owner`:username, `version`(来自步骤10), `version_desc`(来自步骤8)
|
||||
|
||||
12. **反馈结果**
|
||||
- ✅ 成功:返回创建模型版本结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
---
|
||||
|
||||
## 示例对话
|
||||
|
||||
**用户:**
|
||||
> 帮我创建一个模型,名字叫 material-filter-v1,标签是 material,screening
|
||||
|
||||
**Agent 行为:**
|
||||
1. 询问用户名和密码(如未知)
|
||||
2. 调用登录接口获取token
|
||||
3. 调用创建模型
|
||||
4. 返回:
|
||||
> ✅ 模型 `material-filter-v1` 创建成功
|
||||
5. 询问是否创建模型版本
|
||||
6. 输入版本描述
|
||||
7. 上传文件
|
||||
8. 获取最新的版本号
|
||||
9. 创建模型版本
|
||||
10. 反馈结果
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
- Token 有效期由服务端控制,过期需重新登录
|
||||
- 不建议将用户名、密码、Token 写入日志
|
||||
- 创建失败时应明确提示是 **登录失败** 还是 **创建失败**
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
---
|
||||
name: create-model
|
||||
description: 当用户需要新增模型时,请使用此技能。
|
||||
triggers:
|
||||
- "新增模型"
|
||||
- "创建模型"
|
||||
metadata:
|
||||
api-base: http://172.20.32.121:31213
|
||||
---
|
||||
|
||||
# 创建模型(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要创建一个新的模型
|
||||
- 用户提到“创建模型”“新建模型”“调用创建模型 API”
|
||||
|
||||
## 接口信息
|
||||
### 1. 登录获取access_token接口
|
||||
- 方法:POST
|
||||
- 路径:/api/auth/login
|
||||
- Content-Type:application/json; charset=UTF-8
|
||||
- 请求参数:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| username | string | ✅ | 用户名 |
|
||||
| password | string | ✅ | 密码 |
|
||||
|
||||
#### 示例请求
|
||||
curl -X POST http://172.20.32.121:31213/api/auth/login \
|
||||
-H "Content-Type: application/json; charset=UTF-8" \
|
||||
-d '{"username": "fanshuai","password": "h1n2x3j4y5@"}'
|
||||
|
||||
#### 返回示例
|
||||
{"code":200,"msg":null,"data":{"access_token":"eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX2tleSI6IjU1ZTdiOGIxLWFmNjYtNDQyYS1iMjgyLTM4YWVmMzhlODI3MyIsInVzZXJuYW1lIjoiZmFuc2h1YWkifQ.SCu4a85IKUY9OlFApDWVlEvHeuacf4FoW0agzIKrmR8a8uLdur3Rb8Y7_1tu71JEKT_pQBGSTDhtf7FobqdIrg","expires_in":1779433929217}}
|
||||
|
||||
### 2. 新增模型接口
|
||||
- 方法:POST
|
||||
- 路径:/api/mmp/newmodel/addModel
|
||||
- Headers:
|
||||
- `Authorization: Bearer <access_token>`
|
||||
- `Content-Type: application/json; charset=UTF-8`
|
||||
- 请求参数:
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认值 |
|
||||
|---|---|---|---|
|
||||
| name | string | ✅ | — |
|
||||
| model_type | string | ❌ | `"多模态模型"` |
|
||||
| model_tag | string | ✅ | — |
|
||||
| is_hot_stone | boolean | ❌ | `false` |
|
||||
| is_public | boolean | ❌ | `false` |
|
||||
| model_source | string | ❌ | `"add"` |
|
||||
| preview_pic | string | ❌ | `http://172.20.32.121:31213/minio/data/mini-model-platform-data/temp/fanshuai/1761528061144/model/材料筛选.png` |
|
||||
|
||||
#### 示例请求
|
||||
curl -X POST http://172.20.32.121:31213/api/mmp/newmodel/addModel \
|
||||
-H "Authorization: Bearer $access_token" \
|
||||
-H "Content-Type: application/json; charset=UTF-8" \
|
||||
-d '{
|
||||
"name": "material-filter-v1",
|
||||
"model_type": "多模态模型",
|
||||
"model_tag": "material,screening",
|
||||
"is_hot_stone": false,
|
||||
"is_public": false,
|
||||
"model_source": "add",
|
||||
"preview_pic": "http://172.20.32.121:31213/minio/data/mini-model-platform-data/temp/fanshuai/1761528061144/model/材料筛选.png"}'
|
||||
|
||||
#### 返回示例
|
||||
{"code":200,"msg":"操作成功","data":{"id":23,"name":"material-filter-v1","create_by":"fanshuai","create_time":"2026-05-21 15:28:26","update_time":"2026-05-21 15:28:26","model_size":"0 B","model_source":"add","model_tag":"material,screening","model_type":"多模态模型","owner":"fanshuai","identifier":"fanshuai_model_20260521152825","is_public":false,"relative_paths":"fanshuai/model/128/fanshuai_model_20260521152825/origin/model","preview_pic":"http://172.20.32.121:31213/minio/data/mini-model-platform-data/temp/fanshuai/1761528061144/model/材料筛选.png","is_hot_stone":false,"git_id":128}}
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名
|
||||
- 密码
|
||||
- 模型名称 `name`
|
||||
- 模型标签 `model_tag`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口**
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `access_token`
|
||||
|
||||
3. **构造创建模型请求**
|
||||
- 使用默认值补齐未传参数
|
||||
- 使用 `Bearer Token` 鉴权
|
||||
|
||||
4. **调用创建模型接口**
|
||||
|
||||
5. **反馈结果**
|
||||
- ✅ 成功:返回模型名称和创建结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
---
|
||||
|
||||
## 示例对话
|
||||
|
||||
**用户:**
|
||||
> 帮我创建一个模型,名字叫 material-filter-v1,标签是 material,screening
|
||||
|
||||
**Agent 行为:**
|
||||
1. 询问用户名和密码(如未知)
|
||||
2. 调用登录接口
|
||||
3. 调用创建模型接口
|
||||
4. 返回:
|
||||
> ✅ 模型 `material-filter-v1` 创建成功
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
- Token 有效期由服务端控制,过期需重新登录
|
||||
- 不建议将用户名、密码、Token 写入日志
|
||||
- preview_pic 如用户未指定,必须使用默认图片地址
|
||||
- 创建失败时应明确提示是 **登录失败** 还是 **创建失败**
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import asyncio
|
||||
import httpx
|
||||
import json
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
API_BASE_URL = "https://www.ai4mats.com"
|
||||
|
||||
async def create_model(token: str, name: str, model_tag: str, model_type: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/addModel"
|
||||
headers = {"Content-Type": "application/json; charset=UTF-8", "Authorization": f"Bearer {token}"}
|
||||
payload = {
|
||||
"name": name,
|
||||
"model_type": model_type,
|
||||
"model_tag": model_tag,
|
||||
"is_hot_stone": False,
|
||||
"is_public": False,
|
||||
"model_source": "add",
|
||||
"preview_pic": "https://www.ai4mats.com/minio/data/mini-model-platform-data/temp/fanshuai/1761528061144/model/材料筛选.png"
|
||||
}
|
||||
print(f"请求参数: {json.dumps(payload, ensure_ascii=False, indent=2)}")
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def main():
|
||||
# Load state
|
||||
with open("flow_state.json", "r", encoding="utf-8") as f:
|
||||
state = json.load(f)
|
||||
token = state.get("token")
|
||||
|
||||
name = "skill2"
|
||||
model_tag = "123"
|
||||
model_type = "模型材料筛选"
|
||||
|
||||
print("正在创建模型...")
|
||||
result = await create_model(token, name, model_tag, model_type)
|
||||
print(f"创建结果: {json.dumps(result, ensure_ascii=False, indent=2)}")
|
||||
|
||||
# Save result for next steps
|
||||
with open("create_result.json", "w", encoding="utf-8") as f:
|
||||
json.dump(result, f, ensure_ascii=False, indent=2)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
import asyncio
|
||||
import httpx
|
||||
import json
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
API_BASE_URL = "https://www.ai4mats.com"
|
||||
|
||||
async def login(username: str, password: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {"Content-Type": "application/json; charset=UTF-8"}
|
||||
payload = {"username": username, "password": password}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def query_model_type_list(token: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/assetIcon"
|
||||
headers = {"Content-Type": "application/json; charset=UTF-8", "Authorization": f"Bearer {token}"}
|
||||
params = {"category_id": 2}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def main():
|
||||
username = "fanshuai"
|
||||
password = "h1n2x3j4y5@"
|
||||
|
||||
print("正在登录...")
|
||||
login_result = await login(username, password)
|
||||
|
||||
if login_result.get("code") != 200:
|
||||
print(f"登录失败: {login_result}")
|
||||
return
|
||||
|
||||
token = login_result.get("data", {}).get("access_token")
|
||||
if not token:
|
||||
print("获取token失败")
|
||||
return
|
||||
print("登录成功")
|
||||
|
||||
# Query model type list
|
||||
print("\n正在查询模型类型列表...")
|
||||
type_result = await query_model_type_list(token)
|
||||
|
||||
if type_result.get("code") == 200:
|
||||
data = type_result.get("data", [])
|
||||
print(f"共 {len(data)} 个一级分类:\n")
|
||||
for item in data:
|
||||
print(f"--- {item.get('name')} ---")
|
||||
second_list = item.get("second_asset_icon_list", [])
|
||||
for second in second_list:
|
||||
print(f" - {second.get('name')}")
|
||||
print()
|
||||
|
||||
# Save token and types for next steps
|
||||
with open("flow_state.json", "w", encoding="utf-8") as f:
|
||||
json.dump({"token": token, "types": type_result.get("data", [])}, f, ensure_ascii=False)
|
||||
print("状态已保存到 flow_state.json")
|
||||
else:
|
||||
print(f"查询失败: {type_result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"id": 37,
|
||||
"name": "skill2",
|
||||
"create_by": "fanshuai",
|
||||
"create_time": "2026-05-25 11:02:39",
|
||||
"update_time": "2026-05-25 11:02:39",
|
||||
"model_size": "0 B",
|
||||
"model_source": "add",
|
||||
"model_tag": "123",
|
||||
"model_type": "模型材料筛选",
|
||||
"owner": "fanshuai",
|
||||
"identifier": "fanshuai_model_20260525110238",
|
||||
"is_public": false,
|
||||
"relative_paths": "fanshuai/model/143/fanshuai_model_20260525110238/origin/model",
|
||||
"preview_pic": "https://www.ai4mats.com/minio/data/mini-model-platform-data/temp/fanshuai/1761528061144/model/材料筛选.png",
|
||||
"is_hot_stone": false,
|
||||
"git_id": 143
|
||||
}
|
||||
}
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
import asyncio
|
||||
import httpx
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
API_BASE_URL = "https://www.ai4mats.com"
|
||||
DEFAULT_SIZE = 10 * 1024 * 1024 # 10MB
|
||||
|
||||
import hashlib
|
||||
|
||||
def compute_md5(file_path: str) -> str:
|
||||
file_size = os.path.getsize(file_path)
|
||||
chunk_size = min(DEFAULT_SIZE, file_size)
|
||||
with open(file_path, "rb") as f:
|
||||
data = f.read(chunk_size)
|
||||
md5 = hashlib.md5(data).hexdigest()
|
||||
filename = os.path.basename(file_path)
|
||||
name_bytes = filename.encode('utf-8')
|
||||
combined = md5.encode('utf-8') + name_bytes
|
||||
return hashlib.md5(combined).hexdigest()
|
||||
|
||||
async def get_upload_task(token: str, params: dict) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def upload_chunk(token: str, file_path: str, part_number: int, total_chunks: int, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
start = DEFAULT_SIZE * (part_number - 1)
|
||||
end = min(start + DEFAULT_SIZE, file_size)
|
||||
current_chunk_size = end - start
|
||||
with open(file_path, "rb") as f:
|
||||
f.seek(start)
|
||||
blob_data = f.read(current_chunk_size)
|
||||
data = {
|
||||
"chunkNumber": str(part_number),
|
||||
"chunkSize": str(DEFAULT_SIZE),
|
||||
"currentChunkSize": str(current_chunk_size),
|
||||
"filename": filename,
|
||||
"relativePath": filename,
|
||||
"identifier": identifier,
|
||||
"totalChunks": str(total_chunks),
|
||||
"totalSize": str(file_size),
|
||||
}
|
||||
files = {"upfile": (str(part_number), blob_data, "application/octet-stream")}
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
async with httpx.AsyncClient(timeout=600.0) as client:
|
||||
response = await client.post(url, data=data, files=files, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def merge_chunks(token: str, file_path: str, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/mergeFile"
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json; charset=UTF-8"}
|
||||
payload = {
|
||||
"fileType": "application/zip",
|
||||
"name": filename,
|
||||
"relativePath": filename,
|
||||
"size": file_size,
|
||||
"uniqueIdentifier": identifier,
|
||||
"refProjectId": "123456789",
|
||||
}
|
||||
async with httpx.AsyncClient(timeout=600.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def get_merge_status(token: str, filename: str, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/selectFile"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
params = {"filename": filename, "identifier": identifier}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def upload_file(token: str, file_path: str) -> dict:
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
total_chunks = max(1, (file_size + DEFAULT_SIZE - 1) // DEFAULT_SIZE)
|
||||
identifier = compute_md5(file_path)
|
||||
print(f"文件: {filename}, 大小: {file_size}, 分片数: {total_chunks}")
|
||||
task_params = {
|
||||
"chunkNumber": 1,
|
||||
"chunkSize": DEFAULT_SIZE,
|
||||
"currentChunkSize": min(DEFAULT_SIZE, file_size),
|
||||
"totalSize": file_size,
|
||||
"identifier": identifier,
|
||||
"filename": filename,
|
||||
"relativePath": filename,
|
||||
"totalChunks": total_chunks,
|
||||
}
|
||||
task_result = await get_upload_task(token, task_params)
|
||||
if task_result.get("code") != 200:
|
||||
raise Exception(f"获取上传任务失败: {task_result}")
|
||||
task = task_result.get("data", {})
|
||||
if task.get("skip_upload"):
|
||||
print("文件已存在,跳过上传")
|
||||
return task
|
||||
for part in range(1, total_chunks + 1):
|
||||
print(f"上传分片 {part}/{total_chunks}...")
|
||||
result = await upload_chunk(token, file_path, part, total_chunks, identifier)
|
||||
print(f" 分片 {part} 完成")
|
||||
print("合并分片中...")
|
||||
merge_result = await merge_chunks(token, file_path, identifier)
|
||||
if merge_result.get("code") != 200:
|
||||
raise Exception(f"合并失败: {merge_result}")
|
||||
merge_data = merge_result.get("data", {})
|
||||
if merge_data.get("state") == "Succeeded":
|
||||
print("合并成功!")
|
||||
return merge_data
|
||||
for i in range(30):
|
||||
await asyncio.sleep(3)
|
||||
status_result = await get_merge_status(token, filename, identifier)
|
||||
status_data = status_result.get("data", {})
|
||||
state = status_data.get("state")
|
||||
print(f" 合并状态查询 #{i+1}: {state}")
|
||||
if state == "Succeeded":
|
||||
print("合并成功!")
|
||||
return status_data
|
||||
elif state == "Failed":
|
||||
raise Exception(f"合并失败: {status_result}")
|
||||
raise Exception("合并状态查询超时")
|
||||
|
||||
async def query_next_version(token: str, identifier: str, owner: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/queryNextVersion"
|
||||
headers = {"Content-Type": "application/json; charset=UTF-8", "Authorization": f"Bearer {token}"}
|
||||
payload = {"identifier": identifier, "owner": owner}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def create_model_version(token: str, git_id: int, id: int, identifier: str, file_path: str, file_data: dict, name: str, owner: str, version: str, version_desc: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/addVersion"
|
||||
headers = {"Content-Type": "application/json; charset=UTF-8", "Authorization": f"Bearer {token}"}
|
||||
model_version_vos = [{"file_name": os.path.basename(file_path), "file_size": os.path.getsize(file_path), "url": file_data.get("location")}]
|
||||
payload = {
|
||||
"git_id": git_id,
|
||||
"id": id,
|
||||
"identifier": identifier,
|
||||
"is_public": False,
|
||||
"model_source": "add",
|
||||
"model_version_vos": model_version_vos,
|
||||
"name": name,
|
||||
"owner": owner,
|
||||
"version": version,
|
||||
"version_desc": version_desc,
|
||||
}
|
||||
print(f"创建版本请求: {json.dumps(payload, ensure_ascii=False, indent=2)}")
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def main():
|
||||
# Load model create result
|
||||
with open("create_result.json", "r", encoding="utf-8") as f:
|
||||
create_result = json.load(f)
|
||||
model_data = create_result.get("data", {})
|
||||
git_id = model_data.get("git_id")
|
||||
model_id = model_data.get("id")
|
||||
identifier = model_data.get("identifier")
|
||||
name = model_data.get("name")
|
||||
owner = model_data.get("owner")
|
||||
|
||||
# Load token
|
||||
with open("flow_state.json", "r", encoding="utf-8") as f:
|
||||
state = json.load(f)
|
||||
token = state.get("token")
|
||||
|
||||
file_path = "D:\\code\\nginx.zip"
|
||||
version_desc = "skill2-v1"
|
||||
|
||||
# Step 1: Upload file
|
||||
print("Step 1: 上传文件...")
|
||||
file_data = await upload_file(token, file_path)
|
||||
print(f"上传结果: {json.dumps(file_data, ensure_ascii=False, indent=2)}")
|
||||
|
||||
# Step 2: Get next version
|
||||
print("\nStep 2: 获取最新版本号...")
|
||||
version_result = await query_next_version(token, identifier, owner)
|
||||
print(f"版本号查询结果: {json.dumps(version_result, ensure_ascii=False, indent=2)}")
|
||||
|
||||
if version_result.get("code") != 200:
|
||||
print(f"查询版本号失败")
|
||||
return
|
||||
version = version_result.get("data")
|
||||
print(f"最新版本号: {version}")
|
||||
|
||||
# Step 3: Create model version
|
||||
print("\nStep 3: 创建模型版本...")
|
||||
result = await create_model_version(token, git_id, model_id, identifier, file_path, file_data, name, owner, version, version_desc)
|
||||
print(f"创建模型版本结果: {json.dumps(result, ensure_ascii=False, indent=2)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -1,178 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("文件mcp server")
|
||||
|
||||
|
||||
# 3. 定义工具(所有工具都增加 token 参数)
|
||||
@mcp.tool()
|
||||
async def chunk_get(
|
||||
token: str,
|
||||
chunkNumber: int,
|
||||
chunkSize: int,
|
||||
currentChunkSize: int,
|
||||
filename: str,
|
||||
relativePath: str,
|
||||
identifier: str,
|
||||
totalChunks: int,
|
||||
totalSize: int,
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"chunkNumber": chunkNumber,
|
||||
"chunkSize": chunkSize,
|
||||
"currentChunkSize": currentChunkSize,
|
||||
"filename": filename,
|
||||
"relativePath": relativePath,
|
||||
"identifier": identifier,
|
||||
"totalChunks": totalChunks,
|
||||
"totalSize": totalSize
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 获取文件信息失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def chunk_post(
|
||||
token: str,
|
||||
chunkNumber: int,
|
||||
chunkSize: int,
|
||||
currentChunkSize: int,
|
||||
filename: str,
|
||||
relativePath: str,
|
||||
identifier: str,
|
||||
totalChunks: int,
|
||||
totalSize: int,
|
||||
upfile: UploadFile
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
headers = {
|
||||
"Content-Type": "multipart/form-data; application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"chunkNumber": chunkNumber,
|
||||
"chunkSize": chunkSize,
|
||||
"currentChunkSize": currentChunkSize,
|
||||
"filename": filename,
|
||||
"relativePath": relativePath,
|
||||
"identifier": identifier,
|
||||
"totalChunks": totalChunks,
|
||||
"totalSize": totalSize,
|
||||
"upfile": upfile
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 上传文件分片失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def mergeFile(
|
||||
token: str,
|
||||
fileType: str,
|
||||
name: str,
|
||||
refProjectId: str,
|
||||
relativePath: str,
|
||||
size: int,
|
||||
uniqueIdentifierstr,
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/mergeFile"
|
||||
headers = {
|
||||
"Content-Type": "multipart/form-data; application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"fileType": fileType,
|
||||
"name": name,
|
||||
"refProjectId": refProjectId,
|
||||
"relativePath": relativePath,
|
||||
"size": size,
|
||||
"uniqueIdentifierstr": uniqueIdentifierstr
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 聚合文件分片失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def selectFile(token: str,
|
||||
filename: str,
|
||||
identifier: str) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/mergeFile"
|
||||
headers = {
|
||||
"Content-Type": "multipart/form-data; application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"filename": filename,
|
||||
"identifier": identifier
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询文件信息失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,62 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("模型mcp server")
|
||||
|
||||
|
||||
# 3. 定义工具(所有工具都增加 token 参数)
|
||||
@mcp.tool()
|
||||
async def create_model(
|
||||
token: str, # 新增:认证令牌
|
||||
name: str,
|
||||
model_tag: str,
|
||||
model_type: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/addModel"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"name": name,
|
||||
"model_type": model_type,
|
||||
"model_tag": model_tag,
|
||||
"is_hot_stone": False,
|
||||
"is_public": False,
|
||||
"model_source": "add",
|
||||
"preview_pic": "https://www.ai4mats.com/minio/data/mini-model-platform-data/temp/fanshuai/1761528061144/model/材料筛选.png"
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_next_version(
|
||||
token: str,
|
||||
identifier: str,
|
||||
owner: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/queryNextVersion"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"identifier": identifier,
|
||||
"owner": owner
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询模型最新版本失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_model_version(
|
||||
token: str,
|
||||
git_id: int,
|
||||
id: int,
|
||||
identifier: str,
|
||||
file_path: str,
|
||||
file_data: dict,
|
||||
name: str,
|
||||
owner: str,
|
||||
version: str,
|
||||
version_desc: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/addVersion"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
|
||||
model_version_vos = [{"file_name": os.path.basename(file_path), "file_size": os.path.getsize(file_path),
|
||||
"url": file_data.get("location")}]
|
||||
|
||||
payload = {
|
||||
"git_id": git_id,
|
||||
"id": id,
|
||||
"identifier": identifier,
|
||||
"is_public": False,
|
||||
"model_source": "add",
|
||||
"model_version_vos": model_version_vos,
|
||||
"name": name,
|
||||
"owner": owner,
|
||||
"version": version,
|
||||
"version_desc": version_desc
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型版本失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def query_model_type_list(
|
||||
token: str
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/assetIcon"
|
||||
headers = { "Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"}
|
||||
params = {
|
||||
"category_id": 2,
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询模型类型列表失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import httpx
|
||||
|
||||
API_BASE_URL = "https://www.ai4mats.com"
|
||||
DEFAULT_SIZE = 10 * 1024 * 1024 # 10MB
|
||||
|
||||
def compute_md5(file_path: str) -> str:
|
||||
# Only compute MD5 of the first chunk for performance
|
||||
file_size = os.path.getsize(file_path)
|
||||
chunk_size = min(DEFAULT_SIZE, file_size)
|
||||
with open(file_path, "rb") as f:
|
||||
data = f.read(chunk_size)
|
||||
md5 = hashlib.md5(data).hexdigest()
|
||||
# Add filename to md5 like the frontend does
|
||||
filename = os.path.basename(file_path)
|
||||
name_bytes = filename.encode('utf-8')
|
||||
combined = md5.encode('utf-8') + name_bytes
|
||||
return hashlib.md5(combined).hexdigest()
|
||||
|
||||
async def get_upload_task(token: str, params: dict) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def upload_chunk(token: str, file_path: str, part_number: int, total_chunks: int, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
|
||||
start = DEFAULT_SIZE * (part_number - 1)
|
||||
end = min(start + DEFAULT_SIZE, file_size)
|
||||
current_chunk_size = end - start
|
||||
|
||||
with open(file_path, "rb") as f:
|
||||
f.seek(start)
|
||||
blob_data = f.read(current_chunk_size)
|
||||
|
||||
data = httpx.MultipartData(
|
||||
chunkNumber=str(part_number),
|
||||
chunkSize=str(DEFAULT_SIZE),
|
||||
currentChunkSize=str(current_chunk_size),
|
||||
filename=filename,
|
||||
relativePath=filename,
|
||||
identifier=identifier,
|
||||
totalChunks=str(total_chunks),
|
||||
totalSize=str(file_size),
|
||||
upfile=(str(part_number), blob_data),
|
||||
)
|
||||
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
async with httpx.AsyncClient(timeout=600.0) as client:
|
||||
response = await client.post(url, data=data, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def merge_chunks(token: str, file_path: str, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/mergeFile"
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
}
|
||||
payload = {
|
||||
"fileType": "application/zip",
|
||||
"name": filename,
|
||||
"relativePath": filename,
|
||||
"size": file_size,
|
||||
"uniqueIdentifier": identifier,
|
||||
"refProjectId": "123456789",
|
||||
}
|
||||
async with httpx.AsyncClient(timeout=600.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def get_merge_status(token: str, filename: str, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/selectFile"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
params = {"filename": filename, "identifier": identifier}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def upload_file(token: str, file_path: str) -> dict:
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
total_chunks = max(1, (file_size + DEFAULT_SIZE - 1) // DEFAULT_SIZE)
|
||||
|
||||
identifier = compute_md5(file_path)
|
||||
print(f"File: {filename}, Size: {file_size}, Chunks: {total_chunks}, MD5: {identifier}")
|
||||
|
||||
# Step 1: Get upload task
|
||||
task_params = {
|
||||
"chunkNumber": 1,
|
||||
"chunkSize": DEFAULT_SIZE,
|
||||
"currentChunkSize": min(DEFAULT_SIZE, file_size),
|
||||
"totalSize": file_size,
|
||||
"identifier": identifier,
|
||||
"filename": filename,
|
||||
"relativePath": filename,
|
||||
"totalChunks": total_chunks,
|
||||
}
|
||||
task_result = await get_upload_task(token, task_params)
|
||||
print(f"Task result: {json.dumps(task_result, ensure_ascii=False)}")
|
||||
|
||||
if task_result.get("code") != 200:
|
||||
raise Exception(f"Get upload task failed: {task_result}")
|
||||
|
||||
task = task_result.get("data", {})
|
||||
if task.get("skip_upload"):
|
||||
print("File already uploaded, skipping upload")
|
||||
return task
|
||||
|
||||
# Step 2: Upload chunks
|
||||
for part in range(1, total_chunks + 1):
|
||||
print(f"Uploading chunk {part}/{total_chunks}...")
|
||||
result = await upload_chunk(token, file_path, part, total_chunks, identifier)
|
||||
print(f" Chunk {part} result: {json.dumps(result, ensure_ascii=False)}")
|
||||
|
||||
# Step 3: Merge chunks
|
||||
print("Merging chunks...")
|
||||
merge_result = await merge_chunks(token, file_path, identifier)
|
||||
print(f"Merge result: {json.dumps(merge_result, ensure_ascii=False)}")
|
||||
|
||||
if merge_result.get("code") != 200:
|
||||
raise Exception(f"Merge failed: {merge_result}")
|
||||
|
||||
# Step 4: Poll merge status
|
||||
merge_data = merge_result.get("data", {})
|
||||
if merge_data.get("state") == "Succeeded":
|
||||
print("Merge succeeded immediately!")
|
||||
return merge_data
|
||||
|
||||
# Poll for status
|
||||
for i in range(30):
|
||||
await asyncio.sleep(3)
|
||||
status_result = await get_merge_status(token, filename, identifier)
|
||||
status_data = status_result.get("data", {})
|
||||
state = status_data.get("state")
|
||||
print(f" Merge status poll #{i+1}: {state}")
|
||||
if state == "Succeeded":
|
||||
print("Merge succeeded!")
|
||||
return status_data
|
||||
elif state == "Failed":
|
||||
raise Exception(f"Merge failed: {status_result}")
|
||||
|
||||
raise Exception("Merge status polling timed out")
|
||||
|
||||
async def main():
|
||||
token = sys.argv[1]
|
||||
file_path = sys.argv[2]
|
||||
result = await upload_file(token, file_path)
|
||||
print(f"\nFinal result:\n{json.dumps(result, ensure_ascii=False, indent=2)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
---
|
||||
name: create-service
|
||||
description: 当用户需要新增应用时,请使用此技能。
|
||||
triggers:
|
||||
- "创建应用"
|
||||
- "新增应用"
|
||||
- "创建智算应用"
|
||||
- "新增智算应用"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 创建应用
|
||||
## 何时使用
|
||||
- 用户需要创建一个新的应用
|
||||
- 用户提到“创建应用”“新建应用”“调用创建应用 API”“创建智算应用”
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
1. **确认应用类型**
|
||||
- 询问用户需要创建:常规应用 还是 智算应用
|
||||
- 记录用户选择
|
||||
|
||||
2. **确认参数**
|
||||
- 如果有token则跳过步骤2,步骤3,token过期则再从这一步开始执行
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
3. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
4. **查询应用类型列表**
|
||||
- 调用`scripts/create_service_mcp_server.get_service_types`方法
|
||||
- 结果中的`type`字段为所有的应用类型
|
||||
|
||||
5. **输入参数**
|
||||
- 应用名称 `service_name`
|
||||
- 应用类型 `service_type` (范围来自于步骤4的结果,不能超出范围)
|
||||
- 应用标签 `tag`
|
||||
- 应用描述 `description`
|
||||
|
||||
6. **创建应用**
|
||||
- 如果用户选择**常规应用**:
|
||||
- 调用`scripts/create_service_mcp_server.create_servive`方法
|
||||
- 如果用户选择**智算应用**:
|
||||
- 调用`scripts/create_service_mcp_server.create_zs_service`方法
|
||||
- 参数:`token`(来自步骤3), `service_name`(来自步骤5), `service_type`(来自步骤5), `tag`(来自步骤5), `description`(来自步骤5)
|
||||
|
||||
7. **反馈结果**
|
||||
- ✅ 成功:返回应用名称和创建结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
7. **询问用户是否需要创建版本**
|
||||
- 询问用户是否需要创建应用版本,如果需要则进行以下步骤,不需要则终止任务
|
||||
|
||||
8. **输入参数**
|
||||
- 应用版本 `version`
|
||||
- 版本描述 `description`
|
||||
- 副本数量 `replicas`
|
||||
|
||||
9. **选择运行镜像**
|
||||
- 输入参数:
|
||||
- 查询公开镜像还是个人镜像 `is_public`(bool类型)
|
||||
- `page`(默认0)
|
||||
- `size`(默认20)
|
||||
- 调用 `scripts/create_service_mcp_server.query_image`方法,参数:`token`(来自步骤2), `page`(来自步骤9), `size`(来自步骤9), `is_public`(来自步骤9)
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次查询。
|
||||
- 用户选择了镜像之后,调用 `scripts/create_service_mcp_server.query_image_version`方法查询镜像版本
|
||||
- 用户选择某一个镜像版本
|
||||
|
||||
10. **选择资源规格**
|
||||
- 调用 `scripts/create_service_mcp_server.query_computing_resource`方法查询资源规格列表
|
||||
- 用户选择某一个资源规格
|
||||
|
||||
11. **选择模型**
|
||||
- 询问用户是否需要选择模型,如果是,则进行以下步骤,如果否,则跳过此环节,直接进入下一环节
|
||||
- 调用 `scripts/create_service_mcp_server.query_models`方法查询模型列表
|
||||
- 输入参数:
|
||||
- 查询公开模型还是个人模型 `is_public`(bool类型)
|
||||
- `page`(默认0)
|
||||
- `size`(默认20)
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次查询。
|
||||
- 用户选择了模型之后,调用 `scripts/create_service_mcp_server.query_model_version`方法查询模型版本,参数:`token`(来自步骤2),`owner`,`identifier`
|
||||
- 用户选择某一个模型版本,调用`scripts/create_service_mcp_server.query_model_version_detail`方法查询模型版本详情,参数:`token`(来自步骤2), `id`(模型id), `name`(模型名称), `owner`,`identifier`, `version`(模型版本), `is_public`, `git_id`
|
||||
- 并要求输入参数挂载路径:`mount_path`
|
||||
|
||||
12. **输入环境变量**
|
||||
- 询问用户是否需要输入环境变量,如果是,则进行以下步骤,如果否,则跳过此环节,直接进入下一环节
|
||||
- 用户可以输入多个key-value键值对,key和value都是str类型,然后存放在变量`env_variables`中
|
||||
|
||||
13. **创建应用版本**
|
||||
- 调用 `scripts/create_service_mcp_server.create_service_version`方法
|
||||
- 参数:`token`(来自步骤2), `service_id`(应用id,来自步骤5的返回结果中的id字段), `service_name`(来自步骤4), `version`(来自步骤8), `description`(来自步骤8),
|
||||
`replicas`(来自步骤8), `computing_resource_id`(来自步骤10中用户选择的结果中的id字段), `model`(来自步骤11用户选择的模型版本对象), `mount_path`(来自步骤11),
|
||||
`image`(来自步骤9中选择的镜像版本对象), `env_variables`(来自步骤12)
|
||||
|
||||
14. **反馈结果**
|
||||
- ✅ 成功:返回应用版本创建结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
|
@ -1,316 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("service mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_service_types(token: str):
|
||||
url = f"{API_BASE_URL}/api/mmp/service/getServiceTypes"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询应用类型失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_servive(
|
||||
token: str,
|
||||
service_name: str,
|
||||
service_type: str,
|
||||
description: str,
|
||||
tag: str,
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/service"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"service_name": service_name,
|
||||
"service_type": service_type,
|
||||
"description": description,
|
||||
"tag": tag,
|
||||
"source": 0,
|
||||
"img_url": "https://www.minio.ai4mats.com/data/mini-model-platform-data/temp/fanshuai/1761528061144/app-1.png"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模应用失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_image(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
is_public: bool
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/image"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": is_public
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询镜像列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_image_version(token: str,
|
||||
image_id: int):
|
||||
url = f"{API_BASE_URL}/api/mmp/imageVersion"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": 0,
|
||||
"size": 2000,
|
||||
"image_id": image_id,
|
||||
"status": "Available"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询镜像版本列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_computing_resource(token: str):
|
||||
url = f"{API_BASE_URL}/api/mmp/computingResource"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": 0,
|
||||
"size": 1000}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询资源规格列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_models(token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
is_public: bool):
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/queryModels"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": is_public,
|
||||
"is_hot_stone": False
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询镜像列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_model_version(
|
||||
token: str,
|
||||
owner: str,
|
||||
identifier: str
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/getVersionList"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"owner": owner,
|
||||
"identifier": identifier
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询镜像列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_model_version_detail(token: str,
|
||||
id: int,
|
||||
name: str,
|
||||
owner: str,
|
||||
identifier: str,
|
||||
version: str,
|
||||
is_public: bool,
|
||||
git_id: int
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/getModelDetail"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"owner": owner,
|
||||
"identifier": identifier,
|
||||
"id": id,
|
||||
"name": name,
|
||||
"version": version,
|
||||
"is_public": is_public,
|
||||
"git_id": git_id
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询镜像列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_service_version(
|
||||
token: str,
|
||||
service_id: int,
|
||||
service_name: str,
|
||||
version: str,
|
||||
description: str,
|
||||
replicas: int,
|
||||
computing_resource_id: int,
|
||||
model: dict,
|
||||
mount_path: str,
|
||||
image: dict,
|
||||
env_variables: dict
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/service/version"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"service_id": service_id,
|
||||
"service_name": service_name,
|
||||
"source": 0,
|
||||
"deploy_type": "web",
|
||||
"version": version,
|
||||
"description": description,
|
||||
"replicas": replicas,
|
||||
"computing_resource_id": computing_resource_id,
|
||||
"model": model,
|
||||
"mount_path": mount_path,
|
||||
"image": image,
|
||||
"env_variables": env_variables
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模应用失败: {str(e)}"
|
||||
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_zs_service(
|
||||
token: str,
|
||||
service_name: str,
|
||||
service_type: str,
|
||||
description: str,
|
||||
tag: str,
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/service"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"service_name": service_name,
|
||||
"service_type": service_type,
|
||||
"description": description,
|
||||
"tag": tag,
|
||||
"source": 2,
|
||||
"img_url": "https://www.minio.ai4mats.com/data/mini-model-platform-data/temp/fanshuai/1761528061144/app-1.png"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建智算应用失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
except Exception as e:
|
||||
print("读取配置文件失败: {}".format(e))
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
except Exception as e:
|
||||
print("读取配置文件失败: {}".format(e))
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = "{}/api/auth/login".format(API_BASE_URL)
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return "登录失败: {}".format(str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("启动登录 MCP 服务,传输模式: {}".format(TRANSPORT_MODE))
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
---
|
||||
name: create-dataset
|
||||
description: 当用户需要新增数据集时,请使用此技能。
|
||||
triggers:
|
||||
- "新增数据集"
|
||||
- "创建数据集"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 创建数据集(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要创建一个新的数据集
|
||||
- 用户提到“创建数据集”“新建数据集”“调用创建数据集 API”
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 数据集名称 `name`
|
||||
- 数据集标签 `data_tag`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`common/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **获取父级分类列表**
|
||||
- 调用`scripts/dataset_mcp_server.get_parent_categories`方法
|
||||
- 参数: `token`(来自步骤2)
|
||||
- 返回父级分类列表,供用户选择需要展开的分类
|
||||
|
||||
4. **选择需要展开的父级分类**
|
||||
- 展示父级分类列表给用户
|
||||
- 询问用户需要展开哪个父级分类
|
||||
- 获取用户选择的父级分类ID `parent_id`
|
||||
|
||||
5. **获取叶子节点列表**
|
||||
- 调用`scripts/dataset_mcp_server.get_child_categories`方法
|
||||
- 参数: `token`(来自步骤2), `parent_id`(来自步骤4)
|
||||
- 返回该父级分类下的所有叶子节点列表
|
||||
|
||||
6. **选择数据类型**
|
||||
- 展示叶子节点列表给用户
|
||||
- 询问用户选择哪种数据类型 `data_type`
|
||||
|
||||
7. **创建数据集**
|
||||
- 调用`scripts/dataset_mcp_server.create_dataset`方法
|
||||
- 参数:`token`(来自步骤2), `name`, `data_tag`, `data_type`(来自步骤6)
|
||||
|
||||
8. **反馈结果**
|
||||
- ✅ 成功:返回数据集名称和创建结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
9. **询问是否创建数据集版本**
|
||||
- 如果创建数据集成功,则继续询问用户是否需要创建数据集版本
|
||||
- 用户回答是则进行以下步骤,否则终止。
|
||||
|
||||
10. **输入版本描述**
|
||||
- 输入版本描述version_desc
|
||||
|
||||
11. **上传文件**
|
||||
- 调用`scripts/upload_file.upload_file`方法分片上传文件
|
||||
|
||||
12. **获取最新的版本号**
|
||||
- 调用`scripts/dataset_mcp_server.query_next_version`方法获取最新的版本号
|
||||
|
||||
13. **创建数据集版本**
|
||||
- 调用`scripts/dataset_mcp_server.create_dataset_version`方法
|
||||
- 参数:`token`(来自步骤2), `git_id`(来自步骤7), `id`(来自步骤7), `identifier`(来自步骤7), `file_path`(来自步骤11的输入), `file_data`(来自步骤11的结果), `name`:name, `owner`:username, `version`(来自步骤12), `version_desc`(来自步骤10)
|
||||
|
||||
14. **反馈结果**
|
||||
- 打印第13步的参数
|
||||
- ✅ 成功:返回创建数据集版本结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
---
|
||||
|
||||
## 示例对话
|
||||
|
||||
**用户:**
|
||||
> 帮我创建一个数据集,名字叫 test121,标签是 test
|
||||
|
||||
**Agent 行为:**
|
||||
1. 询问用户名和密码(如未知)
|
||||
2. 调用登录接口获取token
|
||||
3. 调用获取父级分类列表接口,返回:知识层级数据
|
||||
4. 询问用户需要展开哪个父级分类
|
||||
5. 用户选择"知识层级数据"
|
||||
6. 调用获取叶子节点列表接口,返回:通用数据、领域基础数据、领域专业数据
|
||||
7. 询问用户选择哪种数据类型
|
||||
8. 用户选择"通用数据"
|
||||
9. 调用创建数据集
|
||||
10. 返回:
|
||||
> ✅ 数据集 `test121` 创建成功
|
||||
11. 询问是否创建数据集版本
|
||||
12. 输入版本描述
|
||||
13. 上传文件
|
||||
14. 获取最新的版本号
|
||||
15. 创建数据集版本
|
||||
16. 反馈结果
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
- Token 有效期由服务端控制,过期需重新登录
|
||||
- 不建议将用户名、密码、Token 写入日志
|
||||
- 创建失败时应明确提示是 **登录失败** 还是 **创建失败**
|
||||
- 数据类型选择流程:先选择父级分类 → 展开叶子节点 → 选择叶子节点作为数据类型
|
||||
- 如用户直接指定数据类型名称,可调用`get_data_types`获取所有叶子节点进行匹配验证
|
||||
|
|
@ -1,310 +0,0 @@
|
|||
import httpx
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from common.config import API_BASE_URL, TRANSPORT_MODE
|
||||
|
||||
mcp = FastMCP("数据集mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_dataset(
|
||||
token: str,
|
||||
name: str,
|
||||
data_tag: str,
|
||||
data_type: str = "通用数据"
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/addDataset"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"name": name,
|
||||
"preview_pic": "https://www.ai4mats.com/minio/data/mini-model-platform-data/temp/fanshuai/1761528061144/dataset/电学材料.png",
|
||||
"dataset_source": "add",
|
||||
"data_type": data_type,
|
||||
"data_tag": data_tag,
|
||||
"is_public": False,
|
||||
"is_hot_stone": False
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建数据集失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_next_version(
|
||||
token: str,
|
||||
identifier: str,
|
||||
owner: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/queryNextVersion"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"identifier": identifier,
|
||||
"owner": owner
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 获取版本号失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_dataset_version(
|
||||
token: str,
|
||||
git_id: int,
|
||||
id: int,
|
||||
identifier: str,
|
||||
file_path: str,
|
||||
file_data: dict,
|
||||
name: str,
|
||||
owner: str,
|
||||
version: str,
|
||||
version_desc: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/addVersion"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
|
||||
dataset_version_vos = [{"file_name": os.path.basename(file_path), "file_size": os.path.getsize(file_path), "url": file_data.get("location")}]
|
||||
|
||||
payload = {
|
||||
"git_id": git_id,
|
||||
"id": id,
|
||||
"identifier": identifier,
|
||||
"is_public": False,
|
||||
"owner": owner,
|
||||
"dataset_version_vos": dataset_version_vos,
|
||||
"name": name,
|
||||
"version": version,
|
||||
"version_desc": version_desc,
|
||||
"dataset_source": "add"
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建数据集版本失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_asset_icon(
|
||||
token: str,
|
||||
category_id: int = 1
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/assetIcon"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": 0,
|
||||
"size": 10000,
|
||||
"category_id": category_id
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询数据集分类失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_parent_categories(token: str) -> str:
|
||||
"""
|
||||
获取父级分类列表,用于用户选择需要展开的分类
|
||||
|
||||
参数:
|
||||
- token: 访问令牌
|
||||
|
||||
返回: 父级分类列表,格式为 {"code": 200, "msg": "操作成功", "data": [{"id": 137, "name": "知识层级数据"}, ...]}
|
||||
"""
|
||||
import json
|
||||
|
||||
try:
|
||||
asset_icon_result = await query_asset_icon(token)
|
||||
|
||||
if isinstance(asset_icon_result, str):
|
||||
try:
|
||||
asset_icon_result = json.loads(asset_icon_result)
|
||||
except:
|
||||
return f"❌ 解析数据集分类失败"
|
||||
|
||||
if asset_icon_result.get("code") != 200:
|
||||
return f"❌ 获取数据集分类失败: {asset_icon_result.get('msg', '未知错误')}"
|
||||
|
||||
data = asset_icon_result.get("data", [])
|
||||
parent_categories = []
|
||||
|
||||
for category in data:
|
||||
parent_categories.append({
|
||||
"id": category.get("id"),
|
||||
"name": category.get("name"),
|
||||
"category_id": category.get("category_id"),
|
||||
"parent_id": category.get("parent_id")
|
||||
})
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": parent_categories
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return f"❌ 获取父级分类列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_child_categories(token: str, parent_id: int) -> str:
|
||||
"""
|
||||
根据父级分类ID获取其下的叶子节点列表
|
||||
|
||||
参数:
|
||||
- token: 访问令牌
|
||||
- parent_id: 父级分类ID
|
||||
|
||||
返回: 叶子节点列表,格式为 {"code": 200, "msg": "操作成功", "data": [{"id": 138, "name": "通用数据", "parent_id": 137, "path": "icon-tongyongshuju"}, ...]}
|
||||
"""
|
||||
import json
|
||||
|
||||
try:
|
||||
asset_icon_result = await query_asset_icon(token)
|
||||
|
||||
if isinstance(asset_icon_result, str):
|
||||
try:
|
||||
asset_icon_result = json.loads(asset_icon_result)
|
||||
except:
|
||||
return f"❌ 解析数据集分类失败"
|
||||
|
||||
if asset_icon_result.get("code") != 200:
|
||||
return f"❌ 获取数据集分类失败: {asset_icon_result.get('msg', '未知错误')}"
|
||||
|
||||
data = asset_icon_result.get("data", [])
|
||||
child_categories = []
|
||||
|
||||
for category in data:
|
||||
if category.get("id") == parent_id:
|
||||
second_list = category.get("second_asset_icon_list", [])
|
||||
if second_list:
|
||||
for item in second_list:
|
||||
grandchild_list = item.get("second_asset_icon_list", [])
|
||||
if grandchild_list:
|
||||
for grandchild in grandchild_list:
|
||||
child_categories.append({
|
||||
"id": grandchild.get("id"),
|
||||
"name": grandchild.get("name"),
|
||||
"parent_id": grandchild.get("parent_id"),
|
||||
"path": grandchild.get("path")
|
||||
})
|
||||
else:
|
||||
child_categories.append({
|
||||
"id": item.get("id"),
|
||||
"name": item.get("name"),
|
||||
"parent_id": item.get("parent_id"),
|
||||
"path": item.get("path")
|
||||
})
|
||||
break
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": child_categories
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return f"❌ 获取叶子节点列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_data_types(token: str) -> str:
|
||||
"""
|
||||
获取所有可用的数据类型列表(仅叶子节点),用于直接选择
|
||||
|
||||
参数:
|
||||
- token: 访问令牌
|
||||
|
||||
返回: 所有叶子节点列表,格式为 {"code": 200, "msg": "操作成功", "data": [{"id": 138, "name": "通用数据", "parent_id": 137, "path": "icon-tongyongshuju"}, ...]}
|
||||
"""
|
||||
import json
|
||||
|
||||
try:
|
||||
asset_icon_result = await query_asset_icon(token)
|
||||
|
||||
if isinstance(asset_icon_result, str):
|
||||
try:
|
||||
asset_icon_result = json.loads(asset_icon_result)
|
||||
except:
|
||||
return f"❌ 解析数据集分类失败"
|
||||
|
||||
if asset_icon_result.get("code") != 200:
|
||||
return f"❌ 获取数据集分类失败: {asset_icon_result.get('msg', '未知错误')}"
|
||||
|
||||
data = asset_icon_result.get("data", [])
|
||||
data_types = []
|
||||
|
||||
for category in data:
|
||||
second_list = category.get("second_asset_icon_list", [])
|
||||
if second_list:
|
||||
for item in second_list:
|
||||
grandchild_list = item.get("second_asset_icon_list", [])
|
||||
if grandchild_list:
|
||||
for grandchild in grandchild_list:
|
||||
data_types.append({
|
||||
"id": grandchild.get("id"),
|
||||
"name": grandchild.get("name"),
|
||||
"parent_id": grandchild.get("parent_id"),
|
||||
"path": grandchild.get("path")
|
||||
})
|
||||
else:
|
||||
data_types.append({
|
||||
"id": item.get("id"),
|
||||
"name": item.get("name"),
|
||||
"parent_id": item.get("parent_id"),
|
||||
"path": item.get("path")
|
||||
})
|
||||
else:
|
||||
data_types.append({
|
||||
"id": category.get("id"),
|
||||
"name": category.get("name"),
|
||||
"parent_id": category.get("parent_id"),
|
||||
"path": category.get("path")
|
||||
})
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": data_types
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return f"❌ 获取数据类型列表失败: {str(e)}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动数据集 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import httpx
|
||||
from common.config import API_BASE_URL
|
||||
|
||||
DEFAULT_SIZE = 10 * 1024 * 1024 # 10MB
|
||||
|
||||
def compute_md5(file_path: str) -> str:
|
||||
file_size = os.path.getsize(file_path)
|
||||
chunk_size = min(DEFAULT_SIZE, file_size)
|
||||
with open(file_path, "rb") as f:
|
||||
data = f.read(chunk_size)
|
||||
md5 = hashlib.md5(data).hexdigest()
|
||||
filename = os.path.basename(file_path)
|
||||
name_bytes = filename.encode('utf-8')
|
||||
combined = md5.encode('utf-8') + name_bytes
|
||||
return hashlib.md5(combined).hexdigest()
|
||||
|
||||
async def get_upload_task(token: str, params: dict) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def upload_chunk(token: str, file_path: str, part_number: int, total_chunks: int, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
|
||||
start = DEFAULT_SIZE * (part_number - 1)
|
||||
end = min(start + DEFAULT_SIZE, file_size)
|
||||
current_chunk_size = end - start
|
||||
|
||||
with open(file_path, "rb") as f:
|
||||
f.seek(start)
|
||||
blob_data = f.read(current_chunk_size)
|
||||
|
||||
files = {
|
||||
"chunkNumber": (None, str(part_number)),
|
||||
"chunkSize": (None, str(DEFAULT_SIZE)),
|
||||
"currentChunkSize": (None, str(current_chunk_size)),
|
||||
"filename": (None, filename),
|
||||
"relativePath": (None, filename),
|
||||
"identifier": (None, identifier),
|
||||
"totalChunks": (None, str(total_chunks)),
|
||||
"totalSize": (None, str(file_size)),
|
||||
"upfile": (filename, blob_data),
|
||||
}
|
||||
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
async with httpx.AsyncClient(timeout=600.0) as client:
|
||||
response = await client.post(url, files=files, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def merge_chunks(token: str, file_path: str, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/mergeFile"
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
}
|
||||
payload = {
|
||||
"fileType": "application/zip",
|
||||
"name": filename,
|
||||
"relativePath": filename,
|
||||
"size": file_size,
|
||||
"uniqueIdentifier": identifier,
|
||||
"refProjectId": "123456789",
|
||||
}
|
||||
async with httpx.AsyncClient(timeout=600.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def get_merge_status(token: str, filename: str, identifier: str) -> dict:
|
||||
url = f"{API_BASE_URL}/api/mmp/uploader/selectFile"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
params = {"filename": filename, "identifier": identifier}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def upload_file(token: str, file_path: str) -> dict:
|
||||
file_size = os.path.getsize(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
total_chunks = max(1, (file_size + DEFAULT_SIZE - 1) // DEFAULT_SIZE)
|
||||
|
||||
identifier = compute_md5(file_path)
|
||||
print(f"File: {filename}, Size: {file_size}, Chunks: {total_chunks}, MD5: {identifier}")
|
||||
|
||||
task_params = {
|
||||
"chunkNumber": 1,
|
||||
"chunkSize": DEFAULT_SIZE,
|
||||
"currentChunkSize": min(DEFAULT_SIZE, file_size),
|
||||
"totalSize": file_size,
|
||||
"identifier": identifier,
|
||||
"filename": filename,
|
||||
"relativePath": filename,
|
||||
"totalChunks": total_chunks,
|
||||
}
|
||||
task_result = await get_upload_task(token, task_params)
|
||||
print(f"Task result: {json.dumps(task_result, ensure_ascii=False)}")
|
||||
|
||||
if task_result.get("code") != 200:
|
||||
raise Exception(f"Get upload task failed: {task_result}")
|
||||
|
||||
task = task_result.get("data", {})
|
||||
if task.get("skip_upload"):
|
||||
print("File already uploaded, skipping upload")
|
||||
return task
|
||||
|
||||
for part in range(1, total_chunks + 1):
|
||||
print(f"Uploading chunk {part}/{total_chunks}...")
|
||||
result = await upload_chunk(token, file_path, part, total_chunks, identifier)
|
||||
print(f" Chunk {part} result: {json.dumps(result, ensure_ascii=False)}")
|
||||
|
||||
print("Merging chunks...")
|
||||
merge_result = await merge_chunks(token, file_path, identifier)
|
||||
print(f"Merge result: {json.dumps(merge_result, ensure_ascii=False)}")
|
||||
|
||||
if merge_result.get("code") != 200:
|
||||
raise Exception(f"Merge failed: {merge_result}")
|
||||
|
||||
merge_data = merge_result.get("data", {})
|
||||
if merge_data.get("state") == "Succeeded":
|
||||
print("Merge succeeded immediately!")
|
||||
return merge_data
|
||||
if merge_data.get("location"):
|
||||
print("Merge has location, returning immediately despite state:", merge_data.get("state"))
|
||||
return merge_data
|
||||
|
||||
for i in range(30):
|
||||
await asyncio.sleep(3)
|
||||
status_result = await get_merge_status(token, filename, identifier)
|
||||
status_data = status_result.get("data", {})
|
||||
state = status_data.get("state")
|
||||
print(f" Merge status poll #{i+1}: {state}")
|
||||
if state == "Succeeded":
|
||||
print("Merge succeeded!")
|
||||
return status_data
|
||||
elif state == "Failed":
|
||||
if status_data.get("location"):
|
||||
print("Merge has location despite Failed state, using it")
|
||||
return status_data
|
||||
raise Exception(f"Merge failed: {status_result}")
|
||||
|
||||
raise Exception("Merge status polling timed out")
|
||||
|
||||
async def main():
|
||||
token = sys.argv[1]
|
||||
file_path = sys.argv[2]
|
||||
result = await upload_file(token, file_path)
|
||||
print(f"\nFinal result:\n{json.dumps(result, ensure_ascii=False, indent=2)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
---
|
||||
name: delete-dataset
|
||||
description: 当用户需要删除数据集或版本时,请使用此技能。
|
||||
triggers:
|
||||
- "删除数据集"
|
||||
- "删除数据集版本"
|
||||
metadata:
|
||||
api-base: http://172.20.32.121:31213
|
||||
---
|
||||
|
||||
# 删除数据集(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要删除数据集版本
|
||||
- 用户需要删除整个数据集
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
### 删除数据集版本
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- git_id `git_id`
|
||||
- owner `owner`
|
||||
- identifier `identifier`
|
||||
- relative_paths `relative_paths`
|
||||
- version `version`
|
||||
- 若缺失用户名和密码,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`common/login_mcp_server.login`方法
|
||||
- 获取 `access_token`
|
||||
|
||||
3. **删除版本**
|
||||
- 调用`scripts/delete_mcp_server.delete_dataset_version`方法
|
||||
|
||||
4. **反馈结果**
|
||||
- ✅ 成功:返回操作成功信息
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
### 删除数据集
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- id `id`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
|
||||
3. **删除数据集**
|
||||
- 调用`scripts/delete_mcp_server.delete_dataset`方法
|
||||
|
||||
4. **反馈结果**
|
||||
|
||||
---
|
||||
|
||||
## 示例对话
|
||||
|
||||
**用户:**
|
||||
> 帮我删除数据集,id是46
|
||||
|
||||
**Agent 行为:**
|
||||
1. 询问用户名和密码
|
||||
2. 调用登录接口获取token
|
||||
3. 调用删除数据集接口
|
||||
4. 返回删除结果
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
- Token 有效期由服务端控制,过期需重新登录
|
||||
- 不建议将用户名、密码、Token 写入日志
|
||||
- 删除操作不可逆,请谨慎操作
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from common.config import API_BASE_URL, TRANSPORT_MODE
|
||||
|
||||
mcp = FastMCP("删除数据集mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def delete_dataset_version(
|
||||
token: str,
|
||||
git_id: int,
|
||||
owner: str,
|
||||
identifier: str,
|
||||
relative_paths: str,
|
||||
version: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/deleteDatasetVersion"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"git_id": git_id,
|
||||
"owner": owner,
|
||||
"identifier": identifier,
|
||||
"relative_paths": relative_paths,
|
||||
"version": version
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.delete(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 删除数据集版本失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def delete_dataset(
|
||||
token: str,
|
||||
id: int
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/deleteDataset/{id}"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.delete(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 删除数据集失败: {str(e)}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动删除数据集 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
---
|
||||
name: download-dataset
|
||||
description: 当用户需要下载数据集版本文件时,请使用此技能。
|
||||
triggers:
|
||||
- "下载数据集"
|
||||
- "下载数据集版本"
|
||||
- "下载数据集文件"
|
||||
metadata:
|
||||
api-base: http://172.20.32.121:31213
|
||||
---
|
||||
|
||||
# 下载数据集版本文件(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要下载数据集当前版本的所有文件
|
||||
- 用户需要下载数据集当前版本的单个文件
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
### 下载当前版本所有文件打包
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- name `name`
|
||||
- git_id `git_id`
|
||||
- version `version`
|
||||
- identifier `identifier`
|
||||
- owner `owner`
|
||||
- is_public `is_public`
|
||||
- 若缺失用户名和密码,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`common/login_mcp_server.login`方法
|
||||
- 获取 `access_token`
|
||||
|
||||
3. **下载文件**
|
||||
- 调用`scripts/download_mcp_server.download_all_files`方法
|
||||
|
||||
4. **反馈结果**
|
||||
- ✅ 成功:返回文件内容
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
### 下载当前版本选中文件
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- url `url`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
|
||||
3. **下载文件**
|
||||
- 调用`scripts/download_mcp_server.download_single_file`方法
|
||||
|
||||
4. **反馈结果**
|
||||
|
||||
---
|
||||
|
||||
## 示例对话
|
||||
|
||||
**用户:**
|
||||
> 帮我下载数据集的所有文件,name是test121,git_id是125,version是v1,identifier是fanshuai_dataset_20260519104635,owner是fanshuai,is_public是false
|
||||
|
||||
**Agent 行为:**
|
||||
1. 询问用户名和密码
|
||||
2. 调用登录接口获取token
|
||||
3. 调用下载所有文件接口
|
||||
4. 返回文件内容
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
- Token 有效期由服务端控制,过期需重新登录
|
||||
- 不建议将用户名、密码、Token 写入日志
|
||||
- 下载文件可能较大,请确保网络连接稳定
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from common.config import API_BASE_URL, TRANSPORT_MODE
|
||||
|
||||
mcp = FastMCP("下载数据集mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def download_all_files(
|
||||
token: str,
|
||||
name: str,
|
||||
git_id: int,
|
||||
version: str,
|
||||
identifier: str,
|
||||
owner: str,
|
||||
is_public: bool
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/downloadAllFiles"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"name": name,
|
||||
"git_id": git_id,
|
||||
"version": version,
|
||||
"identifier": identifier,
|
||||
"owner": owner,
|
||||
"is_public": is_public
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=300.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return f"✅ 下载成功,文件大小: {len(response.content)} 字节"
|
||||
except Exception as e:
|
||||
return f"❌ 下载所有文件失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def download_single_file(
|
||||
token: str,
|
||||
url: str
|
||||
) -> str:
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/downloadSingleFile"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"url": url
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=300.0) as client:
|
||||
response = await client.get(api_url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return f"✅ 下载成功,文件大小: {len(response.content)} 字节"
|
||||
except Exception as e:
|
||||
return f"❌ 下载单个文件失败: {str(e)}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动下载数据集 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
---
|
||||
name: query-dataset
|
||||
description: 当用户需要查询数据集信息时,请使用此技能。
|
||||
triggers:
|
||||
- "查询数据集"
|
||||
- "查询数据集列表"
|
||||
- "查询数据集详情"
|
||||
- "发布数据集"
|
||||
metadata:
|
||||
api-base: http://172.20.32.121:31213
|
||||
---
|
||||
|
||||
# 查询数据集(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要查询数据集列表
|
||||
- 用户需要查询数据集详情
|
||||
- 用户需要发布数据集
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
### 查询数据集列表
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 页码 `page`(可选,默认0)
|
||||
- 每页大小 `size`(可选,默认20)
|
||||
- 是否公开 `is_public`(可选)
|
||||
- 数据类型 `data_type`(可选)
|
||||
- 是否热门 `is_hot_stone`(可选)
|
||||
- 若缺失用户名和密码,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`common/login_mcp_server.login`方法
|
||||
- 获取 `access_token`
|
||||
|
||||
3. **查询数据集列表**
|
||||
- 调用`scripts/query_mcp_server.query_datasets`方法
|
||||
|
||||
4. **反馈结果**
|
||||
- ✅ 成功:返回数据集列表
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
### 查询数据集详情
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- git_id `git_id`
|
||||
- owner `owner`
|
||||
- name `name`
|
||||
- identifier `identifier`
|
||||
- is_public `is_public`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
|
||||
3. **查询数据集详情**
|
||||
- 调用`scripts/query_mcp_server.get_dataset_detail`方法
|
||||
|
||||
4. **反馈结果**
|
||||
|
||||
### 发布数据集
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- id `id`
|
||||
- name `name`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
|
||||
3. **发布数据集**
|
||||
- 调用`scripts/query_mcp_server.publish_dataset`方法
|
||||
|
||||
4. **反馈结果**
|
||||
|
||||
---
|
||||
|
||||
## 示例对话
|
||||
|
||||
**用户:**
|
||||
> 帮我查询数据集列表
|
||||
|
||||
**Agent 行为:**
|
||||
1. 询问用户名和密码
|
||||
2. 调用登录接口获取token
|
||||
3. 调用查询数据集列表接口
|
||||
4. 返回数据集列表
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
- Token 有效期由服务端控制,过期需重新登录
|
||||
- 不建议将用户名、密码、Token 写入日志
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from common.config import API_BASE_URL, TRANSPORT_MODE
|
||||
|
||||
mcp = FastMCP("查询数据集mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_datasets(
|
||||
token: str,
|
||||
page: int = 0,
|
||||
size: int = 20,
|
||||
is_public: bool = None,
|
||||
data_type: str = "",
|
||||
is_hot_stone: bool = None
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/queryDatasets"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size
|
||||
}
|
||||
if is_public is not None:
|
||||
params["is_public"] = is_public
|
||||
if data_type:
|
||||
params["data_type"] = data_type
|
||||
if is_hot_stone is not None:
|
||||
params["is_hot_stone"] = is_hot_stone
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询数据集列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_dataset_detail(
|
||||
token: str,
|
||||
git_id: int,
|
||||
owner: str,
|
||||
name: str,
|
||||
identifier: str,
|
||||
is_public: bool
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/getDatasetDetail"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"git_id": git_id,
|
||||
"owner": owner,
|
||||
"name": name,
|
||||
"identifier": identifier,
|
||||
"is_public": is_public
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询数据集详情失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def publish_dataset(
|
||||
token: str,
|
||||
id: int,
|
||||
name: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/publish"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"id": id,
|
||||
"name": name
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 发布数据集失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_version_list(
|
||||
token: str,
|
||||
owner: str,
|
||||
identifier: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/getVersionList"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"owner": owner,
|
||||
"identifier": identifier
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 获取版本列表失败: {str(e)}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动查询数据集 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
---
|
||||
name: update-dataset
|
||||
description: 当用户需要修改数据集信息时,请使用此技能。
|
||||
triggers:
|
||||
- "修改数据集"
|
||||
- "编辑数据集"
|
||||
- "修改数据集简介"
|
||||
metadata:
|
||||
api-base: http://172.20.32.121:31213
|
||||
---
|
||||
|
||||
# 修改数据集(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要修改数据集信息
|
||||
- 用户需要修改数据集简介
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
### 修改数据集
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- id `id`
|
||||
- name `name`
|
||||
- identifier `identifier`
|
||||
- description `description`(可选)
|
||||
- is_public `is_public`
|
||||
- data_type `data_type`
|
||||
- data_tag `data_tag`
|
||||
- owner `owner`
|
||||
- dataset_source `dataset_source`
|
||||
- relative_paths `relative_paths`
|
||||
- is_hot_stone `is_hot_stone`
|
||||
- git_id `git_id`
|
||||
- preview_pic `preview_pic`
|
||||
- 若缺失用户名和密码,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`common/login_mcp_server.login`方法
|
||||
- 获取 `access_token`
|
||||
|
||||
3. **修改数据集**
|
||||
- 调用`scripts/update_mcp_server.update_dataset`方法
|
||||
|
||||
4. **反馈结果**
|
||||
- ✅ 成功:返回修改后的数据集信息
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
### 修改数据集简介
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- git_id `git_id`
|
||||
- identifier `identifier`
|
||||
- description `description`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
|
||||
3. **修改数据集简介**
|
||||
- 调用`scripts/update_mcp_server.update_dataset_desc`方法
|
||||
|
||||
4. **反馈结果**
|
||||
|
||||
---
|
||||
|
||||
## 示例对话
|
||||
|
||||
**用户:**
|
||||
> 帮我修改数据集简介,git_id是125,identifier是fanshuai_dataset_20260519104635,简介是新的描述内容
|
||||
|
||||
**Agent 行为:**
|
||||
1. 询问用户名和密码
|
||||
2. 调用登录接口获取token
|
||||
3. 调用修改数据集简介接口
|
||||
4. 返回修改结果
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
- Token 有效期由服务端控制,过期需重新登录
|
||||
- 不建议将用户名、密码、Token 写入日志
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from common.config import API_BASE_URL, TRANSPORT_MODE
|
||||
|
||||
mcp = FastMCP("修改数据集mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def update_dataset(
|
||||
token: str,
|
||||
id: int,
|
||||
name: str,
|
||||
identifier: str,
|
||||
description: str = "",
|
||||
is_public: bool = False,
|
||||
data_type: str = "通用数据",
|
||||
data_tag: str = "",
|
||||
owner: str = "",
|
||||
dataset_source: str = "add",
|
||||
relative_paths: str = "",
|
||||
is_hot_stone: bool = False,
|
||||
git_id: int = 0,
|
||||
preview_pic: str = ""
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/updateDataset"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"identifier": identifier,
|
||||
"description": description,
|
||||
"is_public": is_public,
|
||||
"data_type": data_type,
|
||||
"data_tag": data_tag,
|
||||
"praises_count": 0,
|
||||
"praised": False,
|
||||
"create_by": owner,
|
||||
"update_time": "",
|
||||
"owner": owner,
|
||||
"dataset_source": dataset_source,
|
||||
"relative_paths": relative_paths,
|
||||
"is_hot_stone": is_hot_stone,
|
||||
"git_id": git_id,
|
||||
"preview_pic": preview_pic,
|
||||
"type": 0
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.put(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 修改数据集失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def update_dataset_desc(
|
||||
token: str,
|
||||
git_id: int,
|
||||
identifier: str,
|
||||
description: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newdataset/updateDesc"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"git_id": git_id,
|
||||
"identifier": identifier,
|
||||
"description": description
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.put(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 修改数据集简介失败: {str(e)}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动修改数据集 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
---
|
||||
name: delete-code
|
||||
description: 当用户需要删除代码配置时,请使用此技能。
|
||||
triggers:
|
||||
- "删除代码配置"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 删除代码配置(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要删除代码配置时
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- `page` (默认0)
|
||||
- `size` (默认20)
|
||||
- `code_repo_name`(镜像名称,非必填)
|
||||
|
||||
4. **查询代码配置**
|
||||
- 调用`scripts/query_code_mcp_server.query_code`方法
|
||||
- 参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `code_repo_name`(来自步骤3)
|
||||
|
||||
5. **展示结果**
|
||||
- 将查询结果的总数展示出来,列表展示代码配置列表
|
||||
|
||||
6. **继续查询**
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次运行步骤4,步骤5
|
||||
- 否则结束查询
|
||||
|
||||
7. **删除代码配置**
|
||||
- 用户从步骤4的结果中选择需要删除的代码配置
|
||||
- 调用`scripts/delete_code_mcp_server.delete_code`方法
|
||||
- 参数:`token`(来自步骤2), `id`(来自步骤4)
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_code(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
code_repo_name: str
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/codeConfig"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": False,
|
||||
"code_repo_name": code_repo_name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询代码配置列表失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def delete_code(
|
||||
token: str,
|
||||
id: int
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/codeConfig/" + str(id)
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.delete(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 删除代码配置失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
---
|
||||
name: delete-image
|
||||
description: 当用户需要删除镜像时,请使用此技能。
|
||||
triggers:
|
||||
- "删除镜像"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 删除镜像(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要删除镜像时
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- `page` (默认0)
|
||||
- `size` (默认20)
|
||||
- `name`(镜像名称,非必填)
|
||||
|
||||
4. **查询镜像**
|
||||
- 调用`scripts/query_image_mcp_server.query_image`方法
|
||||
- 参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `name`(来自步骤3)
|
||||
|
||||
5. **展示结果**
|
||||
- 将查询结果的总数展示出来,列表展示镜像列表
|
||||
|
||||
6. **继续查询**
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次运行步骤4,步骤5
|
||||
- 否则结束查询
|
||||
|
||||
7. **删除镜像**
|
||||
- 用户从步骤4的结果中选择需要删除的镜像
|
||||
- 调用`scripts/delete_image_mcp_server.delete_image`方法
|
||||
- 参数:`token`(来自步骤2), id(来自步骤4)
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_image(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
name: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/image"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": False,
|
||||
"name": name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询镜像列表失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def delete_image(
|
||||
token: str,
|
||||
id: int
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/image/" + str(id)
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.delete(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 删除镜像失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
---
|
||||
name: delete-model
|
||||
description: 当用户需要删除模型时,请使用此技能。
|
||||
triggers:
|
||||
- "删除模型"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 删除模型(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要删除模型时
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **用户登录**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
- 非必填参数:
|
||||
- 模型类型 `model_type`
|
||||
- 模型标签 `model_tag`
|
||||
- 是否包含火石模型 `is_hot_stone`
|
||||
- 模型名称 `name`
|
||||
- 可以询问用户是否需要查询指定模型类型,模型标签,是否包含火石模型,模型名称的模型
|
||||
- 默认参数:
|
||||
- page = 0
|
||||
- size = 20
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **查询模型**
|
||||
- 调用`scripts/delete_model_mcp_server.query_model`方法
|
||||
- 参数:`token`(来自步骤2), `model_type`, `model_tag`, `is_hot_stone`, `name`, `page`, `size`
|
||||
- 如果用户说继续查询下一页,则page加1后继续查询,否则结束查询
|
||||
|
||||
4. **删除模型**
|
||||
- 用户从步骤3的结果中选择需要删除的模型
|
||||
- 调用`scripts/delete_model_mcp_server.delete_model`方法
|
||||
- 参数:`token`(来自步骤2), id(来自步骤3)
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("模型mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_model(
|
||||
token: str,
|
||||
model_type: str,
|
||||
model_tag: str,
|
||||
is_hot_stone: bool,
|
||||
name: str,
|
||||
page: int,
|
||||
size: int
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/queryModels"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"model_type": model_type,
|
||||
"model_tag": model_tag,
|
||||
"is_hot_stone": is_hot_stone,
|
||||
"name": name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询模型失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def delete_model(
|
||||
token: str,
|
||||
id: int
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/delete/" + str(id)
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.delete(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 删除模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
---
|
||||
name: delete-serivce
|
||||
description: 当用户需要删除应用时,请使用此技能。
|
||||
triggers:
|
||||
- "删除应用"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 删除应用
|
||||
|
||||
## 何时使用
|
||||
- 用户需要删除应用时
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
1. **确认参数**
|
||||
- 如果有token则跳过步骤1,步骤2,token过期则再从这一步开始执行
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- `page` (默认0)
|
||||
- `size` (默认20)
|
||||
- `service_name`(镜像名称,非必填)
|
||||
|
||||
4. **查询我的应用**
|
||||
- 调用`scripts/delete_service_mcp_server.query_service`方法
|
||||
- 参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `service_name`, `order_by` = "mine"
|
||||
|
||||
5. **展示结果**
|
||||
- 将查询结果的总数展示出来,列表展示应用列表
|
||||
|
||||
6. **继续查询**
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次运行步骤4,步骤5
|
||||
- 否则结束查询
|
||||
|
||||
7. **删除应用**
|
||||
- 用户从步骤4的结果中选择需要删除的应用
|
||||
- 调用`scripts/delete_service_mcp_server.delete_service`方法
|
||||
- 参数:`token`(来自步骤2), id(来自步骤4)
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("service mcp server")
|
||||
|
||||
@mcp.tool()
|
||||
async def query_service(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
service_name: str,
|
||||
is_selected: bool,
|
||||
is_public: bool,
|
||||
order_by: str
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/service"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"service_name": service_name,
|
||||
"is_selected": is_selected,
|
||||
"is_public": is_public,
|
||||
"order_by": order_by,
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询应用列表失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def delete_service(token: str,
|
||||
id: int):
|
||||
url = f"{API_BASE_URL}/api/mmp/service/" + str(id)
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.delete(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 删除应用失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
---
|
||||
name: query-code
|
||||
description: 当用户需要查询代码配置时,请使用此技能。
|
||||
triggers:
|
||||
- "查询代码配置"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 查询代码配置(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要查询代码配置时
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- 查询公开代码配置还是个人代码配置 `is_public`(bool类型)
|
||||
- `page` (默认0)
|
||||
- `size` (默认20)
|
||||
- `code_repo_name`(代码配置名称,非必填)
|
||||
|
||||
4. **查询代码配置**
|
||||
- 调用`scripts/query_code_mcp_server.query_code`方法
|
||||
- 参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `is_public`(来自步骤3), `code_repo_name`(来自步骤3)
|
||||
|
||||
5. **展示结果**
|
||||
- 将查询结果的总数展示出来,列表展示代码配置列表
|
||||
|
||||
6. **继续查询**
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次运行步骤4,步骤5
|
||||
- 否则结束任务
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_code(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
is_public: bool,
|
||||
code_repo_name: str
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/codeConfig"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": is_public,
|
||||
"code_repo_name": code_repo_name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询代码配置列表失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
---
|
||||
name: query-image
|
||||
description: 当用户需要查询镜像时,请使用此技能。
|
||||
triggers:
|
||||
- "查询镜像"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 查询镜像(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要查询镜像时
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- 查询公开镜像还是个人镜像 `is_public`(bool类型)
|
||||
- `page` (默认0)
|
||||
- `size` (默认20)
|
||||
- `name`(镜像名称,非必填)
|
||||
|
||||
4. **查询镜像**
|
||||
- 调用`scripts/query_image_mcp_server.query_image`方法
|
||||
- 参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `is_public`(来自步骤3), `name`(来自步骤3)
|
||||
|
||||
5. **展示结果**
|
||||
- 将查询结果的总数展示出来,列表展示镜像列表
|
||||
|
||||
6. **继续查询**
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次运行步骤4,步骤5
|
||||
- 否则结束任务
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_image(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
is_public: bool,
|
||||
name: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/image"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": is_public,
|
||||
"name": name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询镜像列表失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
---
|
||||
name: query-model
|
||||
description: 当用户需要查询模型时,请使用此技能。
|
||||
triggers:
|
||||
- "查询模型"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 查询模型(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要查询模型时
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 查询公开还是私有模型 `is_public`
|
||||
- 若缺失,必须先向用户询问
|
||||
- 非必填参数:
|
||||
- 模型类型 `model_type`
|
||||
- 模型标签 `model_tag`
|
||||
- 是否包含火石模型 `is_hot_stone`
|
||||
- 模型名称 `name`
|
||||
- 可以询问用户是否需要查询指定模型类型,模型标签,是否包含火石模型,模型名称的模型
|
||||
- 默认参数:
|
||||
- page = 0
|
||||
- size = 20
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **查询模型**
|
||||
- 调用`scripts/query_model_mcp_server.query_model`方法
|
||||
- 参数:`token`(来自步骤2), `is_public`, `model_type`, `model_tag`, `is_hot_stone`, `name`, `page`, `size`
|
||||
|
||||
4. **展示结果**
|
||||
- 将查询结果的总数展示出来,列表展示模型列表
|
||||
|
||||
5. **继续查询**
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次运行步骤3,步骤4
|
||||
- 询问用户是否需要查询某一个模型的详细信息,如果需要则调用`scripts/query_model_mcp_server.get_model_detail`方法
|
||||
- 参数: `token`(来自步骤2), `git_id`(来自步骤3), `identifier`(来自步骤3), `owner`(来自步骤3的结果中的create_by字段), `is_public`
|
||||
- 否则结束任务
|
||||
Binary file not shown.
|
|
@ -1,62 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("模型mcp server")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_model(
|
||||
token: str,
|
||||
is_public: bool,
|
||||
model_type: str,
|
||||
model_tag: str,
|
||||
is_hot_stone: bool,
|
||||
name: str,
|
||||
page: int,
|
||||
size: int
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/queryModels"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": is_public,
|
||||
"model_type": model_type,
|
||||
"model_tag": model_tag,
|
||||
"is_hot_stone": is_hot_stone,
|
||||
"name": name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询模型列表失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def get_model_detail(
|
||||
token: str,
|
||||
git_id: int,
|
||||
identifier: str,
|
||||
owner: str,
|
||||
is_public: bool
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/getModelDetail"
|
||||
headers = {"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"}
|
||||
params = {
|
||||
"git_id": git_id,
|
||||
"identifier": identifier,
|
||||
"is_public": is_public,
|
||||
"owner": owner
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询模型详情失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import sys
|
||||
|
||||
API_BASE_URL = "https://www.ai4mats.com"
|
||||
|
||||
async def login(username, password):
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {"Content-Type": "application/json; charset=UTF-8"}
|
||||
payload = {"username": username, "password": password}
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def query_model(token, is_public, model_type="", model_tag="", is_hot_stone=None, name="", page=0, size=20):
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/queryModels"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": is_public,
|
||||
"model_type": model_type,
|
||||
"model_tag": model_tag,
|
||||
"name": name
|
||||
}
|
||||
if is_hot_stone is not None:
|
||||
params["is_hot_stone"] = is_hot_stone
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import asyncio
|
||||
args = sys.argv[1:]
|
||||
username = args[0]
|
||||
password = args[1]
|
||||
is_public = args[2] == "true"
|
||||
model_type = args[3]
|
||||
model_tag = args[4]
|
||||
is_hot_stone = args[5] if args[5] != "None" else None
|
||||
if is_hot_stone is not None:
|
||||
is_hot_stone = is_hot_stone == "true"
|
||||
name = args[6]
|
||||
page = int(args[7])
|
||||
size = int(args[8])
|
||||
|
||||
result = asyncio.run(login(username, password))
|
||||
token = result.get("access_token") or result.get("token") or result.get("data", {}).get("access_token") or result.get("data", {}).get("token")
|
||||
print(f"TOKEN:{token}")
|
||||
|
||||
result = asyncio.run(query_model(token, is_public, model_type, model_tag, is_hot_stone, name, page, size))
|
||||
print(f"RESULT:{json.dumps(result, ensure_ascii=False)}")
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
---
|
||||
name: query-service
|
||||
description: 当用户需要查询应用时,请使用此技能。
|
||||
triggers:
|
||||
- "查询应用"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 查询应用
|
||||
|
||||
## 何时使用
|
||||
- 用户需要查询应用时
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
1. **确认参数**
|
||||
- 如果有token则跳过步骤1,步骤2,token过期则再从这一步开始执行
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- `page` (默认0)
|
||||
- `size` (默认20)
|
||||
- `service_name`(镜像名称,非必填)
|
||||
|
||||
4. **查询应用**
|
||||
- 询问用户是需要查询精选应用,全部应用,我的应用,还是我的收藏;调用`scripts/query_service_mcp_server.query_service`方法
|
||||
- 1. 如果是查询精选应用,则传入参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `service_name`, `is_selected` = True, `is_public` = True, `order_by` = "markCount"
|
||||
- 2. 如果是查询全部应用,则传入参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `service_name`, `is_public` = True, `order_by` = "markCount"
|
||||
- 3. 如果是查询我的应用,则传入参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `service_name`, `order_by` = "mine"
|
||||
- 4. 如果是查询我的收藏,则调用`scripts/query_service_mcp_server.query_mark_service`方法,传入参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `service_name`
|
||||
|
||||
5. **展示结果**
|
||||
- 将查询结果的总数展示出来,列表展示应用列表
|
||||
|
||||
6. **继续查询**
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次运行步骤4,步骤5
|
||||
- 询问用户是否需要查询某一个应用的详细信息,如果需要则调用`scripts/query_service_mcp_server.get_service_detail`方法,传入参数:`token`(来自步骤2), `id`(来自选择的应用)
|
||||
- 否则结束任务
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("service mcp server")
|
||||
|
||||
@mcp.tool()
|
||||
async def query_service(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
service_name: str,
|
||||
is_selected: bool,
|
||||
is_public: bool,
|
||||
order_by: str
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/service"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"service_name": service_name,
|
||||
"is_selected": is_selected,
|
||||
"is_public": is_public,
|
||||
"order_by": order_by,
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询应用列表失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def query_mark_service(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
service_name: str):
|
||||
url = f"{API_BASE_URL}/api/mmp/service"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"service_name": service_name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询我的收藏应用列表失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def get_service_detail(token: str,
|
||||
id: int):
|
||||
url = f"{API_BASE_URL}/api/mmp/service/serviceDetail/" + str(id)
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询应用详情失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
---
|
||||
name: smart-compute
|
||||
description: 智算应用创建和部署,包括登录、镜像查询、模型查询、代码查询等功能
|
||||
triggers:
|
||||
- "创建智算应用"
|
||||
- "智算应用部署"
|
||||
- "部署智算应用"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
jsm-api-base: https://ai4m.jointcloud.net
|
||||
---
|
||||
|
||||
# 智算应用创建与部署
|
||||
|
||||
## 何时使用
|
||||
- 用户需要创建智算应用
|
||||
- 用户需要查询镜像、模型、代码资源
|
||||
- 用户提到"创建智算应用"、"智算应用部署"等
|
||||
|
||||
## 接口文档参考
|
||||
执行过程中,请随时参考接口文档:`智算应用创建全流程接口文档.md`
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
### 1. 登录平台获取 Token
|
||||
- 确认是否已有 token,如没有则询问用户名和密码
|
||||
- 调用 `scripts/login_mcp_server.login_platform` 方法
|
||||
- 参数:`username`, `password`
|
||||
- 获取以下信息并保存:
|
||||
- `platform_token`:`data.access_token`
|
||||
|
||||
### 2. 创建智算应用
|
||||
- 询问用户:应用名称
|
||||
- 调用 `scripts/deploy_mcp_server.create_service` 方法
|
||||
- 参数:
|
||||
- `token`:`platform_token`
|
||||
- `service_name`:用户输入
|
||||
- `service_type`:"机器学习"(默认)
|
||||
- `description`:同应用名称
|
||||
- `tag`:同应用名称
|
||||
- `img_url`:默认值
|
||||
- 保存返回的应用ID
|
||||
|
||||
### 3. 登录外部系统获取 Token 和 UserID
|
||||
- 调用 `scripts/login_mcp_server.login_jsm` 方法
|
||||
- 获取以下信息并保存:
|
||||
- `jsm_token`:`data.token`
|
||||
- `user_id`:`data.jsmUserInfo.data.userID`
|
||||
|
||||
### 4. 查询资源类型列表
|
||||
- 调用 `scripts/resource_mcp_server.get_resource_ranges` 方法
|
||||
- 参数:
|
||||
- `token`:`jsm_token`
|
||||
- `user_id`:从登录结果获取
|
||||
- `compute_type`:"1"(默认)
|
||||
- 获取可用的资源范围
|
||||
|
||||
### 5. 查询资源规格列表
|
||||
- 调用 `scripts/resource_mcp_server.query_resource_specs` 方法
|
||||
- 参数:
|
||||
- `token`:`jsm_token`
|
||||
- `query_resource`:从资源类型列表取第一个
|
||||
- `resource_type`:"Train"(默认)
|
||||
- `cluster_ids`:["1865927992266461184"](默认)
|
||||
- 获取可用的资源规格,让用户选择一个
|
||||
|
||||
### 6. 查询镜像资源
|
||||
- 调用 `scripts/image_mcp_server.query_images` 方法
|
||||
- 参数:
|
||||
- `token`:`jsm_token`
|
||||
- `card_types`:["GPU"](默认)
|
||||
- 获取可用镜像列表,让用户选择一个
|
||||
|
||||
### 7. 查询代码资源
|
||||
- 调用 `scripts/code_mcp_server.query_code` 方法
|
||||
- 参数:
|
||||
- `token`:`platform_token`
|
||||
- `page`:0
|
||||
- `size`:20
|
||||
- `is_public`:true
|
||||
- 获取可用代码列表,让用户选择一个
|
||||
|
||||
### 8. 查询模型资源
|
||||
- 调用 `scripts/model_mcp_server.query_model` 方法
|
||||
- 参数:
|
||||
- `token`:`platform_token`
|
||||
- `is_public`:false
|
||||
- `page`:0
|
||||
- `size`:2000
|
||||
- 获取可用模型列表,让用户选择一个
|
||||
|
||||
### 9. 获取模型版本列表
|
||||
- 调用 `scripts/model_mcp_server.get_version_list` 方法
|
||||
- 参数:
|
||||
- `token`:`platform_token`
|
||||
- `owner`:从选中模型中获取
|
||||
- `identifier`:从选中模型中获取
|
||||
- 获取版本列表,让用户选择一个
|
||||
|
||||
### 10. 获取模型详情
|
||||
- 调用 `scripts/model_mcp_server.get_model_detail` 方法
|
||||
- 参数:
|
||||
- `token`:`platform_token`
|
||||
- `git_id`:从选中模型中获取
|
||||
- `identifier`:从选中模型中获取
|
||||
- `owner`:从选中模型中获取
|
||||
- `is_public`:false
|
||||
- `id`:从选中模型中获取
|
||||
- `name`:从选中模型中获取
|
||||
- `version`:从选中版本中获取
|
||||
- 获取模型详情,保存路径
|
||||
|
||||
### 11. 创建智算应用版本
|
||||
- 询问用户:版本号
|
||||
- 调用 `scripts/deploy_mcp_server.create_version` 方法
|
||||
- 参数:
|
||||
- `token`:`platform_token`
|
||||
- `service_id`:从步骤2获取
|
||||
- `version`:用户输入(如:v1)
|
||||
- `description`:同版本号
|
||||
- `resource_type`:从选中资源规格中获取
|
||||
- `image_resource`:从选中资源规格中获取,添加 label/value 字段
|
||||
- `image`:从选中镜像中获取,添加 label/value 字段
|
||||
- `command`:"test_pl_vor.py"(默认)
|
||||
- `code_config`:从选中代码中获取,添加 label/value/showValue/fromSelect/activeTab 字段
|
||||
- `model`:从模型详情中获取,添加 label/value/showValue/fromSelect/activeTab 字段
|
||||
- `deploy_type`:"web"(默认)
|
||||
|
||||
### 12. 反馈结果
|
||||
- ✅ 成功:返回创建结果
|
||||
- ❌ 失败:返回错误码和错误信息
|
||||
|
||||
## 注意事项
|
||||
- 有两套系统:
|
||||
- 平台系统(www.ai4mats.com):用于创建应用、查询模型和代码
|
||||
- JSM 系统(ai4m.jointcloud.net):用于查询资源和镜像
|
||||
- Token 有效期为 604800 秒(7天)
|
||||
- UserID 来自 data.jsmUserInfo.data.userID
|
||||
- 不建议将用户名、密码、Token 写入日志
|
||||
- 参考接口文档构建完整的 payload,特别是 image_resource/image/code_config/model 等对象需要添加额外的字段
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"PLATFORM_API_BASE": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
PLATFORM_API_BASE = config.get("PLATFORM_API_BASE")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("智算应用代码查询")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_code(
|
||||
token: str,
|
||||
page: int = 0,
|
||||
size: int = 20,
|
||||
is_public: bool = True,
|
||||
code_repo_name: str = ""
|
||||
) -> str:
|
||||
"""查询代码配置列表"""
|
||||
url = f"{PLATFORM_API_BASE}/api/mmp/codeConfig"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": is_public
|
||||
}
|
||||
if code_repo_name:
|
||||
params["code_repo_name"] = code_repo_name
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询代码配置列表失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动智算应用代码查询 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"PLATFORM_API_BASE": "https://www.ai4mats.com",
|
||||
"JSM_API_BASE": "https://ai4m.jointcloud.net",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"PLATFORM_API_BASE": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
PLATFORM_API_BASE = config.get("PLATFORM_API_BASE")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("智算应用部署")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_service(
|
||||
token: str,
|
||||
service_name: str,
|
||||
service_type: str = "机器学习",
|
||||
description: str = "",
|
||||
tag: str = "",
|
||||
img_url: str = "https://www.minio.ai4mats.com/data/mini-model-platform-data/temp/fanshuai/1761528061144/app-1.png"
|
||||
) -> str:
|
||||
"""创建智算应用"""
|
||||
url = f"{PLATFORM_API_BASE}/api/mmp/service"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"service_name": service_name,
|
||||
"service_type": service_type,
|
||||
"source": 2,
|
||||
"description": description or service_name,
|
||||
"img_url": img_url,
|
||||
"tag": tag or service_name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建智算应用失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def create_version(
|
||||
token: str,
|
||||
service_id: int,
|
||||
version: str,
|
||||
description: str,
|
||||
resource_type: str,
|
||||
image_resource: dict,
|
||||
image: dict,
|
||||
command: str,
|
||||
code_config: dict,
|
||||
model: dict,
|
||||
deploy_type: str = "web"
|
||||
) -> str:
|
||||
"""创建智算应用版本"""
|
||||
url = f"{PLATFORM_API_BASE}/api/mmp/service/version"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"service_id": service_id,
|
||||
"version": version,
|
||||
"description": description,
|
||||
"resource_type": resource_type,
|
||||
"image_resource": image_resource,
|
||||
"image": image,
|
||||
"command": command,
|
||||
"code_config": code_config,
|
||||
"model": model,
|
||||
"source": 2,
|
||||
"deploy_type": deploy_type
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建智算应用版本失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动智算应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://ai4m.jointcloud.net",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("智算应用镜像查询")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_images(
|
||||
token: str,
|
||||
card_types: list = None
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/jsm/jobSet/queryImages"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
|
||||
if card_types is None:
|
||||
card_types = ["GPU"]
|
||||
|
||||
payload = {
|
||||
"cardTypes": card_types
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询镜像列表失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动智算应用镜像查询 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"PLATFORM_API_BASE": "https://www.ai4mats.com",
|
||||
"JSM_API_BASE": "https://ai4m.jointcloud.net",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
PLATFORM_API_BASE = config.get("PLATFORM_API_BASE")
|
||||
JSM_API_BASE = config.get("JSM_API_BASE")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("智算应用登录")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def login_platform(username: str, password: str) -> str:
|
||||
"""登录平台系统(www.ai4mats.com)"""
|
||||
url = f"{PLATFORM_API_BASE}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 登录平台失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def login_jsm() -> str:
|
||||
"""登录 JSM 系统(ai4m.jointcloud.net)"""
|
||||
url = f"{JSM_API_BASE}/jcc-admin/admin/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": "hnxjy-super1",
|
||||
"password": "h1n2x3j4y5@"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 登录 JSM 失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动智算应用登录 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"PLATFORM_API_BASE": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
PLATFORM_API_BASE = config.get("PLATFORM_API_BASE")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("智算应用模型查询")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_model(
|
||||
token: str,
|
||||
is_public: bool = False,
|
||||
model_type: str = "",
|
||||
model_tag: str = "",
|
||||
is_hot_stone: bool = False,
|
||||
name: str = "",
|
||||
page: int = 0,
|
||||
size: int = 2000
|
||||
) -> str:
|
||||
"""查询模型列表"""
|
||||
url = f"{PLATFORM_API_BASE}/api/mmp/newmodel/queryModels"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": is_public,
|
||||
"is_hot_stone": is_hot_stone
|
||||
}
|
||||
if model_type:
|
||||
params["model_type"] = model_type
|
||||
if model_tag:
|
||||
params["model_tag"] = model_tag
|
||||
if name:
|
||||
params["name"] = name
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询模型列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_version_list(token: str, owner: str, identifier: str) -> str:
|
||||
"""获取模型版本列表"""
|
||||
url = f"{PLATFORM_API_BASE}/api/mmp/newmodel/getVersionList"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"owner": owner,
|
||||
"identifier": identifier
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 获取模型版本列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_model_detail(
|
||||
token: str,
|
||||
git_id: int = None,
|
||||
identifier: str = None,
|
||||
owner: str = None,
|
||||
is_public: bool = False,
|
||||
id: int = None,
|
||||
name: str = None,
|
||||
version: str = None
|
||||
) -> str:
|
||||
"""获取模型详情"""
|
||||
url = f"{PLATFORM_API_BASE}/api/mmp/newmodel/getModelDetail"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"is_public": is_public
|
||||
}
|
||||
if git_id is not None:
|
||||
params["git_id"] = git_id
|
||||
if identifier is not None:
|
||||
params["identifier"] = identifier
|
||||
if owner is not None:
|
||||
params["owner"] = owner
|
||||
if id is not None:
|
||||
params["id"] = id
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if version is not None:
|
||||
params["version"] = version
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 获取模型详情失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动智算应用模型查询 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://ai4m.jointcloud.net",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("智算应用资源查询")
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def get_resource_ranges(
|
||||
token: str,
|
||||
user_id: int,
|
||||
compute_type: str = "1"
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/jsm/v2/resource/range"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
payload = {
|
||||
"userID": user_id,
|
||||
"computeType": compute_type
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询资源类型列表失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def query_resource_specs(
|
||||
token: str,
|
||||
query_resource: dict = None,
|
||||
resource_type: str = "Train",
|
||||
cluster_ids: list = None
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/jsm/v2/resource/query"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
|
||||
if query_resource is None:
|
||||
query_resource = {
|
||||
"cpu": {"min": 0, "max": 0},
|
||||
"memory": {"min": 0, "max": 0},
|
||||
"gpu": {"min": 0, "max": 0},
|
||||
"storage": {"min": 0, "max": 0},
|
||||
"type": "GPU"
|
||||
}
|
||||
|
||||
if cluster_ids is None:
|
||||
cluster_ids = ["1865927992266461184"]
|
||||
|
||||
payload = {
|
||||
"queryResource": query_resource,
|
||||
"resourceType": resource_type,
|
||||
"clusterIDs": cluster_ids
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询资源规格列表失败: {str(e)}"
|
||||
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动智算应用资源查询 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import httpx, json, sys
|
||||
r = httpx.post('https://www.ai4mats.com/api/auth/login', json={'username': 'chenzhihang11', 'password': 'H1n2x3j4y5@'}, timeout=30)
|
||||
result = r.json()
|
||||
print(json.dumps(result, ensure_ascii=False))
|
||||
sys.stdout.flush()
|
||||
|
|
@ -1,770 +0,0 @@
|
|||
# 智算应用
|
||||
|
||||
## 1. 登录系统页面
|
||||
|
||||
https://www.ai4mats.com/api/auth/login
|
||||
|
||||
POST
|
||||
|
||||
入参:
|
||||
|
||||
```json
|
||||
{
|
||||
"password": "H1n2x3j4y5@",
|
||||
"username": "chenzhihang11"
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": null,
|
||||
"data": {
|
||||
"access_token": "eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjo1OSwidXNlcl9rZXkiOiI2NWEyNjJiZi1lMzZiLTQ1ZDEtYjUwZi1kM2IyNDI2N2VlMGUiLCJ1c2VybmFtZSI6ImNoZW56aGloYW5nMTEifQ.67N9INM8UNTaO5buK4ClyZkBWttfaz6hl_A8iv9SpbC7eGb_kTy3R4rtrYJBhOWu3UHL9Tio93aG43qUnOh-aw",
|
||||
"expires_in": 1780473393445
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. 创建智算应用
|
||||
|
||||
https://www.ai4mats.com/api/mmp/service
|
||||
|
||||
POST
|
||||
|
||||
入参:
|
||||
|
||||
```json
|
||||
{
|
||||
"service_name": "智算应用创建",
|
||||
"service_type": "机器学习",
|
||||
"source": 2,
|
||||
"description": "测试",
|
||||
"img_url": "https://www.minio.ai4mats.com/data/mini-model-platform-data/temp/fanshuai/1761528061144/app-1.png",
|
||||
"tag": "智算"
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"id": 51,
|
||||
"service_name": "智算应用创建",
|
||||
"service_type": "机器学习",
|
||||
"source": 2,
|
||||
"tag": "智算",
|
||||
"service_type_name": null,
|
||||
"img_url": "https://www.minio.ai4mats.com/data/mini-model-platform-data/temp/fanshuai/1761528061144/app-1.png",
|
||||
"url": null,
|
||||
"description": "测试",
|
||||
"detail": null,
|
||||
"manual": null,
|
||||
"create_by": "chenzhihang11",
|
||||
"update_by": "chenzhihang11",
|
||||
"create_time": null,
|
||||
"update_time": null,
|
||||
"state": null,
|
||||
"mark_count": null,
|
||||
"is_public": null,
|
||||
"public_version_id": null,
|
||||
"is_selected": null,
|
||||
"is_marked": null,
|
||||
"version_count": null,
|
||||
"comment_count": null,
|
||||
"service_temp_id": null,
|
||||
"service_temp_name": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 2. 智算应用详情
|
||||
|
||||
https://www.ai4mats.com/api/mmp/service/serviceDetail/51
|
||||
|
||||
GET
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"id": 51,
|
||||
"service_name": "智算应用创建",
|
||||
"service_type": "机器学习",
|
||||
"source": 2,
|
||||
"tag": "智算",
|
||||
"service_type_name": null,
|
||||
"img_url": "https://www.minio.ai4mats.com/data/mini-model-platform-data/temp/fanshuai/1761528061144/app-1.png",
|
||||
"url": null,
|
||||
"description": "测试",
|
||||
"detail": null,
|
||||
"manual": null,
|
||||
"create_by": "chenzhihang11",
|
||||
"update_by": "chenzhihang11",
|
||||
"create_time": "2026-06-05T09:07:17.000+08:00",
|
||||
"update_time": "2026-06-05T09:07:17.000+08:00",
|
||||
"state": 1,
|
||||
"mark_count": 0,
|
||||
"is_public": false,
|
||||
"public_version_id": null,
|
||||
"is_selected": false,
|
||||
"is_marked": false,
|
||||
"version_count": 0,
|
||||
"comment_count": 0,
|
||||
"service_temp_id": null,
|
||||
"service_temp_name": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 智算应用版本创建
|
||||
|
||||
## 4. 登录外部系统,获取资源类型,资源规格和运行镜像信息
|
||||
|
||||
https://ai4m.jointcloud.net/jcc-admin/admin/login
|
||||
|
||||
POST
|
||||
|
||||
入参:
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "hnxjy-super1",
|
||||
"password": "h1n2x3j4y5@"
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "OK",
|
||||
"data": {
|
||||
"tokenHead": "Bearer ",
|
||||
"expiresIn": 604800,
|
||||
"jsmUserInfo": {
|
||||
"code": "OK",
|
||||
"message": "",
|
||||
"data": {
|
||||
"userID": 137,
|
||||
"buckets": {
|
||||
"HPCSlurm": 787,
|
||||
"code": 782,
|
||||
"dataset": 783,
|
||||
"image": 785,
|
||||
"model": 784,
|
||||
"result": 786
|
||||
}
|
||||
}
|
||||
},
|
||||
"tokenTimeout": 604800,
|
||||
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOjE5NTU1NDY1Njc5ODUyMjE2MzIsInJuU3RyIjoiYWpkTllzNUpwSUF5ZVMzck9HYlk1ekZqOUxjU0pxcEIiLCJ1c2VyX25hbWUiOiJobnhqeS1zdXBlcjEiLCJpZCI6MTk1NTU0NjU2Nzk4NTIyMTYzMn0.j6SxmuVhn3nvV_HXl0R0jIpTtM7dOC2waU68AOvKVFQ"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 获取远程资源类型列表
|
||||
|
||||
https://ai4m.jointcloud.net/jsm/v2/resource/range
|
||||
|
||||
POST
|
||||
|
||||
入参:
|
||||
|
||||
```json
|
||||
{
|
||||
"userID": 137,
|
||||
"computeType": "1"
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "OK",
|
||||
"message": "",
|
||||
"data": {
|
||||
"resourceRanges": [
|
||||
{
|
||||
"userID": 0,
|
||||
"type": "GPU",
|
||||
"gpu": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"gpuNumber": 4,
|
||||
"cpu": {
|
||||
"min": 0,
|
||||
"max": 64
|
||||
},
|
||||
"memory": {
|
||||
"min": 0,
|
||||
"max": 40
|
||||
},
|
||||
"storage": {
|
||||
"min": 0,
|
||||
"max": 1024
|
||||
},
|
||||
"ids": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 获取远程资源规格列表
|
||||
|
||||
https://ai4m.jointcloud.net/jsm/v2/resource/query
|
||||
|
||||
POST
|
||||
|
||||
入参:
|
||||
|
||||
```json
|
||||
{
|
||||
"queryResource": {
|
||||
"cpu": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"memory": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"gpu": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"storage": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"type": "GPU"
|
||||
},
|
||||
"resourceType": "Train",
|
||||
"clusterIDs": [
|
||||
"1865927992266461184"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "OK",
|
||||
"message": "",
|
||||
"data": {
|
||||
"resource": [
|
||||
{
|
||||
"id": 362,
|
||||
"sourceKey": "GPU::A100::Train",
|
||||
"type": "GPU",
|
||||
"name": "A100",
|
||||
"totalCount": 1,
|
||||
"availableCount": 1,
|
||||
"changeType": 0,
|
||||
"status": 1,
|
||||
"region": "",
|
||||
"clusterId": "1865927992266461184",
|
||||
"costPerUnit": 2,
|
||||
"costType": "hourly",
|
||||
"tag": "Train",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2026-03-25T11:15:08+08:00",
|
||||
"baseResourceSpecs": [
|
||||
{
|
||||
"id": 2331,
|
||||
"resourceSpecId": 362,
|
||||
"type": "STORAGE",
|
||||
"name": "disk",
|
||||
"totalValue": 1024,
|
||||
"totalUnit": "gb",
|
||||
"availableValue": 1024,
|
||||
"availableUnit": "gb",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2025-07-25T20:19:51+08:00"
|
||||
},
|
||||
{
|
||||
"id": 2332,
|
||||
"resourceSpecId": 362,
|
||||
"type": "CPU",
|
||||
"name": "CPU",
|
||||
"totalValue": 8,
|
||||
"totalUnit": "core",
|
||||
"availableValue": 8,
|
||||
"availableUnit": "core",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2025-07-25T20:19:51+08:00"
|
||||
},
|
||||
{
|
||||
"id": 2333,
|
||||
"resourceSpecId": 362,
|
||||
"type": "MEMORY",
|
||||
"name": "RAM",
|
||||
"totalValue": 50,
|
||||
"totalUnit": "gb",
|
||||
"availableValue": 50,
|
||||
"availableUnit": "gb",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2025-07-25T20:19:51+08:00"
|
||||
},
|
||||
{
|
||||
"id": 2334,
|
||||
"resourceSpecId": 362,
|
||||
"type": "MEMORY",
|
||||
"name": "VRAM",
|
||||
"totalValue": 40,
|
||||
"totalUnit": "gb",
|
||||
"availableValue": 40,
|
||||
"availableUnit": "gb",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2025-07-25T20:19:51+08:00"
|
||||
}
|
||||
],
|
||||
"networkCost": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 获取远程镜像列表
|
||||
|
||||
https://ai4m.jointcloud.net/jsm/jobSet/queryImages
|
||||
|
||||
POST
|
||||
|
||||
入参:
|
||||
|
||||
```json
|
||||
{
|
||||
"cardTypes": [
|
||||
"GPU"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "OK",
|
||||
"message": "",
|
||||
"data": {
|
||||
"images": [
|
||||
{
|
||||
"imageID": 59,
|
||||
"name": "原子掺杂推理服务镜像",
|
||||
"createTime": "2025-12-24T17:04:55+08:00",
|
||||
"clusterImages": [
|
||||
{
|
||||
"imageID": 59,
|
||||
"clusterID": "1865927992266461184",
|
||||
"originImageType": "id",
|
||||
"originImageID": "6288897d8fe84a8d8c1f5c9debd1bf6e",
|
||||
"originImageName": "6288897d8fe84a8d8c1f5c9debd1bf6e",
|
||||
"cards": [
|
||||
{
|
||||
"originImageID": "6288897d8fe84a8d8c1f5c9debd1bf6e",
|
||||
"card": "GPU"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 8. 查询代码配置列表
|
||||
|
||||
https://www.ai4mats.com/api/mmp/codeConfig?page=0&size=9&is_public=true
|
||||
|
||||
GET
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"content": [
|
||||
{
|
||||
"id": 14,
|
||||
"code_repo_name": "钙钛晶体特征提取1",
|
||||
"code_repo_vis": 1,
|
||||
"is_public": true,
|
||||
"git_url": "http://192.168.20.156:30202/chenzhihang11/pipelingaitai.git",
|
||||
"git_branch": "master",
|
||||
"verify_mode": null,
|
||||
"git_user_name": null,
|
||||
"git_password": null,
|
||||
"ssh_key": null,
|
||||
"create_by": "chenzhihang11",
|
||||
"create_time": "2026-03-16T15:28:25.000+08:00",
|
||||
"update_by": "chenzhihang11",
|
||||
"update_time": "2026-03-16T15:28:25.000+08:00",
|
||||
"state": 1,
|
||||
"is_visible": true
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"code_repo_name": "钙钛晶体特征提取",
|
||||
"code_repo_vis": 1,
|
||||
"is_public": true,
|
||||
"git_url": "http://192.168.20.156:30202/chenzhihang11/perovskite_crystal_feature_extraction.git",
|
||||
"git_branch": "master",
|
||||
"verify_mode": null,
|
||||
"git_user_name": null,
|
||||
"git_password": null,
|
||||
"ssh_key": null,
|
||||
"create_by": "chenzhihang11",
|
||||
"create_time": "2026-03-04T15:14:57.000+08:00",
|
||||
"update_by": "chenzhihang11",
|
||||
"update_time": "2026-03-04T15:14:57.000+08:00",
|
||||
"state": 1,
|
||||
"is_visible": true
|
||||
}
|
||||
],
|
||||
"pageable": {
|
||||
"sort": {
|
||||
"sorted": false,
|
||||
"unsorted": true,
|
||||
"empty": true
|
||||
},
|
||||
"pageNumber": 1,
|
||||
"pageSize": 9,
|
||||
"offset": 9,
|
||||
"unpaged": false,
|
||||
"paged": true
|
||||
},
|
||||
"last": true,
|
||||
"totalPages": 2,
|
||||
"totalElements": 16,
|
||||
"first": false,
|
||||
"sort": {
|
||||
"sorted": false,
|
||||
"unsorted": true,
|
||||
"empty": true
|
||||
},
|
||||
"number": 1,
|
||||
"numberOfElements": 7,
|
||||
"size": 9,
|
||||
"empty": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 查询模型列表
|
||||
|
||||
https://www.ai4mats.com/api/mmp/newmodel/queryModels?is_public=false&page=0&size=2000&is_hot_stone=false
|
||||
|
||||
GET
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"msg": "操作成功",
|
||||
"code": 200,
|
||||
"data": {
|
||||
"content": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "原子掺杂识别模型",
|
||||
"create_by": "chenzhihang11",
|
||||
"model_size": "0 B",
|
||||
"model_tag": "原子掺杂识别",
|
||||
"model_type": "分类",
|
||||
"full_last_update_time": "2026-05-12T15:36:15.000+08:00",
|
||||
"owner": "chenzhihang11",
|
||||
"identifier": "chenzhihang11_model_20260126141937",
|
||||
"is_public": true,
|
||||
"relative_paths": "chenzhihang11/model/10/chenzhihang11_model_20260126141937/origin/model",
|
||||
"preview_pic": "https://www.minio.ai4mats.com/data/mini-model-platform-data/temp/fanshuai/1761528061144/app-2.png",
|
||||
"praises_count": 0,
|
||||
"is_hot_stone": false,
|
||||
"git_id": 10
|
||||
}
|
||||
],
|
||||
"pageable": {
|
||||
"sort": {
|
||||
"sorted": false,
|
||||
"unsorted": true,
|
||||
"empty": true
|
||||
},
|
||||
"pageNumber": 0,
|
||||
"pageSize": 2000,
|
||||
"offset": 0,
|
||||
"unpaged": false,
|
||||
"paged": true
|
||||
},
|
||||
"last": true,
|
||||
"totalPages": 1,
|
||||
"totalElements": 31,
|
||||
"first": true,
|
||||
"sort": {
|
||||
"sorted": false,
|
||||
"unsorted": true,
|
||||
"empty": true
|
||||
},
|
||||
"number": 0,
|
||||
"numberOfElements": 31,
|
||||
"size": 2000,
|
||||
"empty": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 10. 获取指定模型的版本列表
|
||||
|
||||
https://www.ai4mats.com/api/mmp/newmodel/getVersionList?owner=chenzhihang11&identifier=chenzhihang11_model_20260126141937
|
||||
|
||||
GET
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"msg": "操作成功",
|
||||
"code": 200,
|
||||
"data": [
|
||||
{
|
||||
"name": "v45"
|
||||
},
|
||||
{
|
||||
"name": "v44"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 11. 根据模型版本查询模型详情
|
||||
|
||||
https://www.ai4mats.com/api/mmp/newmodel/getModelDetail?owner=chenzhihang11&identifier=chenzhihang11_model_20260126141937&id=2&name=%E5%8E%9F%E5%AD%90%E6%8E%BA%E6%9D%82%E8%AF%86%E5%88%AB%E6%A8%A1%E5%9E%8B&version=v45&is_public=true&git_id=10
|
||||
|
||||
GET
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"msg": "操作成功",
|
||||
"code": 200,
|
||||
"data": {
|
||||
"id": 2,
|
||||
"name": "原子掺杂识别模型",
|
||||
"version": "v45",
|
||||
"version_desc": "远程训练任务导出",
|
||||
"create_by": "chenzhihang11",
|
||||
"create_time": "2026-06-04 17:31:32",
|
||||
"update_time": "2026-06-04 17:31:32",
|
||||
"model_size": "114.52 KB",
|
||||
"model_source": "auto_export",
|
||||
"description": "",
|
||||
"usage": "<pre><code># 克隆模型配置文件与存储参数到本地\ngit clone -b v45 https://www.gitlink2.ai4mats.com/chenzhihang11/chenzhihang11_model_20260126141937.git\n# 远程拉取配置文件\ndvc pull\n</code></pre>",
|
||||
"owner": "chenzhihang11",
|
||||
"identifier": "chenzhihang11_model_20260126141937",
|
||||
"is_public": false,
|
||||
"relative_paths": "chenzhihang11/model/10/chenzhihang11_model_20260126141937/v45/model",
|
||||
"praises_count": 0,
|
||||
"praised": false,
|
||||
"model_version_vos": [
|
||||
{
|
||||
"url": "/home/resource/chenzhihang11/model/10/chenzhihang11_model_20260126141937/v45/model/final_model.ckpt",
|
||||
"file_name": "final_model.ckpt",
|
||||
"file_size": "87.00 KB"
|
||||
},
|
||||
{
|
||||
"url": "/home/resource/chenzhihang11/model/10/chenzhihang11_model_20260126141937/v45/model/test.json",
|
||||
"file_name": "test.json",
|
||||
"file_size": "27.52 KB"
|
||||
}
|
||||
],
|
||||
"git_id": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 12. 创建智算应用版本接口
|
||||
|
||||
https://www.ai4mats.com/api/mmp/service/version
|
||||
|
||||
POST
|
||||
|
||||
入参:
|
||||
|
||||
```json
|
||||
{
|
||||
"service_name": "智算应用创建",
|
||||
"version": "v1",
|
||||
"description": "智算应用创建",
|
||||
"resource_type": "GPU",
|
||||
"image_resource": {
|
||||
"id": 363,
|
||||
"sourceKey": "GPU::V100::Train",
|
||||
"type": "GPU",
|
||||
"name": "V100",
|
||||
"totalCount": 2,
|
||||
"availableCount": 2,
|
||||
"changeType": 0,
|
||||
"status": 1,
|
||||
"region": "",
|
||||
"clusterId": "1865927992266461184",
|
||||
"costPerUnit": 1,
|
||||
"costType": "perUse",
|
||||
"tag": "Train",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2026-03-25T11:15:08+08:00",
|
||||
"baseResourceSpecs": [
|
||||
{
|
||||
"id": 2335,
|
||||
"resourceSpecId": 363,
|
||||
"type": "STORAGE",
|
||||
"name": "disk",
|
||||
"totalValue": 1024,
|
||||
"totalUnit": "gb",
|
||||
"availableValue": 1024,
|
||||
"availableUnit": "gb",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2025-07-25T20:19:51+08:00"
|
||||
},
|
||||
{
|
||||
"id": 2336,
|
||||
"resourceSpecId": 363,
|
||||
"type": "CPU",
|
||||
"name": "CPU",
|
||||
"totalValue": 16,
|
||||
"totalUnit": "core",
|
||||
"availableValue": 16,
|
||||
"availableUnit": "core",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2025-07-25T20:19:51+08:00"
|
||||
},
|
||||
{
|
||||
"id": 2337,
|
||||
"resourceSpecId": 363,
|
||||
"type": "MEMORY",
|
||||
"name": "RAM",
|
||||
"totalValue": 100,
|
||||
"totalUnit": "gb",
|
||||
"availableValue": 100,
|
||||
"availableUnit": "gb",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2025-07-25T20:19:51+08:00"
|
||||
},
|
||||
{
|
||||
"id": 2338,
|
||||
"resourceSpecId": 363,
|
||||
"type": "MEMORY",
|
||||
"name": "VRAM",
|
||||
"totalValue": 32,
|
||||
"totalUnit": "gb",
|
||||
"availableValue": 32,
|
||||
"availableUnit": "gb",
|
||||
"userId": "3",
|
||||
"createTime": "2025-07-25T20:19:51+08:00",
|
||||
"updateTime": "2025-07-25T20:19:51+08:00"
|
||||
}
|
||||
],
|
||||
"networkCost": 0,
|
||||
"label": "GPU: 2*V100(显存32GB), CPU:16, 内存: 100GB",
|
||||
"value": 363
|
||||
},
|
||||
"image": {
|
||||
"imageID": 59,
|
||||
"name": "原子掺杂推理服务镜像",
|
||||
"createTime": "2025-12-24T17:04:55+08:00",
|
||||
"clusterImages": [
|
||||
{
|
||||
"imageID": 59,
|
||||
"clusterID": "1865927992266461184",
|
||||
"originImageType": "id",
|
||||
"originImageID": "6288897d8fe84a8d8c1f5c9debd1bf6e",
|
||||
"originImageName": "6288897d8fe84a8d8c1f5c9debd1bf6e",
|
||||
"cards": [
|
||||
{
|
||||
"originImageID": "6288897d8fe84a8d8c1f5c9debd1bf6e",
|
||||
"card": "GPU"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "原子掺杂推理服务镜像",
|
||||
"value": 59
|
||||
},
|
||||
"command": "test_pl_vor.py",
|
||||
"code_config": {
|
||||
"id": 9,
|
||||
"code_repo_name": "钙钛晶体特征提取",
|
||||
"code_repo_vis": 1,
|
||||
"is_public": true,
|
||||
"git_url": "http://192.168.20.156:30202/chenzhihang11/perovskite_crystal_feature_extraction.git",
|
||||
"git_branch": "master",
|
||||
"verify_mode": null,
|
||||
"git_user_name": null,
|
||||
"git_password": null,
|
||||
"ssh_key": null,
|
||||
"create_by": "chenzhihang11",
|
||||
"create_time": "2026-03-04T15:14:57.000+08:00",
|
||||
"update_by": "chenzhihang11",
|
||||
"update_time": "2026-03-04T15:14:57.000+08:00",
|
||||
"state": 1,
|
||||
"is_visible": true,
|
||||
"activeTab": "Public",
|
||||
"value": "钙钛晶体特征提取",
|
||||
"showValue": "钙钛晶体特征提取",
|
||||
"fromSelect": true
|
||||
},
|
||||
"model": {
|
||||
"id": 2,
|
||||
"name": "原子掺杂识别模型",
|
||||
"path": "chenzhihang11/model/10/chenzhihang11_model_20260126141937/v45/model",
|
||||
"version": "v45",
|
||||
"identifier": "chenzhihang11_model_20260126141937",
|
||||
"owner": "chenzhihang11",
|
||||
"git_id": 10,
|
||||
"value": "原子掺杂识别模型:v45",
|
||||
"showValue": "原子掺杂识别模型:v45",
|
||||
"fromSelect": true,
|
||||
"activeTab": "Private"
|
||||
},
|
||||
"service_id": 51,
|
||||
"source": 2,
|
||||
"deploy_type": "web"
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "创建成功",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
---
|
||||
name: update-model
|
||||
description: 当用户需要更新代码配置时,请使用此技能。
|
||||
triggers:
|
||||
- "更新代码配置"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 更新代码配置(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要更新代码配置时
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
1. **确认参数**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **输入参数**
|
||||
- `page` (默认0)
|
||||
- `size` (默认20)
|
||||
- `code_repo_name`(镜像名称,非必填)
|
||||
|
||||
4. **查询代码配置**
|
||||
- 调用`scripts/query_code_mcp_server.query_code`方法
|
||||
- 参数:`token`(来自步骤2), `page`(来自步骤3), `size`(来自步骤3), `code_repo_name`(来自步骤3)
|
||||
|
||||
5. **展示结果**
|
||||
- 将查询结果的总数展示出来,列表展示代码配置列表
|
||||
|
||||
6. **继续查询**
|
||||
- 询问用户是否需要查询下一页的数据,如果需要,则page参数加1,再次运行步骤4,步骤5
|
||||
- 否则结束查询
|
||||
|
||||
7. **输入参数**
|
||||
- 用户从步骤4的结果中选择需要修改的代码配置
|
||||
- 输入修改后的`code_repo_name`,`git_branch`,`git_url`,如果不输入,则默认使用步骤3的结果,即不修改。
|
||||
|
||||
8. **更新代码配置**
|
||||
- 调用`scripts/update_code_mcp_server.update_code`方法
|
||||
- 参数:`token`(来自步骤2), `id`(来自步骤4), `code_repo_name`(来自步骤7), `git_branch`(来自步骤7), `git_url`(来自步骤7), `is_public`(来自步骤4)
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("模型mcp server")
|
||||
|
||||
@mcp.tool()
|
||||
async def query_code(
|
||||
token: str,
|
||||
page: int,
|
||||
size: int,
|
||||
code_repo_name: str
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/codeConfig"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": False,
|
||||
"code_repo_name": code_repo_name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询代码配置列表失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def update_code(
|
||||
token: str,
|
||||
id: int,
|
||||
code_repo_name: str,
|
||||
git_branch: str,
|
||||
git_url: str,
|
||||
is_public:bool
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/codeConfig"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"id": id,
|
||||
"code_repo_name": code_repo_name,
|
||||
"git_branch": git_branch,
|
||||
"git_url": git_url,
|
||||
"is_public": is_public
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.put(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 更新代码配置失败: {str(e)}"
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
---
|
||||
name: update-model
|
||||
description: 当用户需要更新模型时,请使用此技能。
|
||||
triggers:
|
||||
- "更新模型"
|
||||
metadata:
|
||||
api-base: https://www.ai4mats.com
|
||||
---
|
||||
|
||||
# 更新模型(调用接口)
|
||||
|
||||
## 何时使用
|
||||
- 用户需要更新模型时
|
||||
|
||||
## 执行流程(Agent 必须遵守)
|
||||
|
||||
1. **用户登录**
|
||||
- 是否已提供:
|
||||
- 用户名 `username`
|
||||
- 密码 `password`
|
||||
- 若缺失,必须先向用户询问
|
||||
- 非必填参数:
|
||||
- 模型类型 `model_type`
|
||||
- 模型标签 `model_tag`
|
||||
- 是否包含火石模型 `is_hot_stone`
|
||||
- 模型名称 `name`
|
||||
- 可以询问用户是否需要查询指定模型类型,模型标签,是否包含火石模型,模型名称的模型
|
||||
- 默认参数:
|
||||
- page = 0
|
||||
- size = 20
|
||||
|
||||
2. **调用登录接口获取token**
|
||||
- 调用`scripts/login_mcp_server.login`方法
|
||||
- 参数: `username`, `password`
|
||||
- 获取 `access_token`
|
||||
- 保存为临时变量 `token`
|
||||
|
||||
3. **查询模型**
|
||||
- 调用`scripts/update_model_mcp_server.query_model`方法
|
||||
- 参数:`token`(来自步骤2), `model_type`, `model_tag`, `is_hot_stone`, `name`, `page`, `size`
|
||||
- 如果用户说继续查询下一页,则page加1后继续查询,否则结束查询
|
||||
|
||||
4. **输入参数**
|
||||
- 调用`scripts/update_model_mcp_server.query_model_type_list`方法,查询所有模型类型
|
||||
- 输入修改后的`model_type`(范围在查询出的模型类型之内),`model_tag`,如果不输入,则默认使用步骤3的结果,即不修改。
|
||||
|
||||
5. **更新模型**
|
||||
- 用户从步骤3的结果中选择需要更新的模型
|
||||
- 调用`scripts/update_model_mcp_server.update_model`方法
|
||||
- 参数:`token`(来自步骤2), `id`(来自步骤3), `git_id`(来自步骤3), `identifier`(来自步骤3), `owner`(来自步骤3的结果中的create_by字段), `model_type`(来自步骤3), `model_tag`(来自步骤3)
|
||||
Binary file not shown.
|
|
@ -1,62 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import httpx
|
||||
from fastapi import UploadFile
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("login mcp server")
|
||||
|
||||
# 3. 定义工具
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str,
|
||||
password: str
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/auth/login"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
}
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 创建模型失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
import httpx
|
||||
import json
|
||||
import os
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
|
||||
# 1. 读取配置文件(不再包含 TOKEN)
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e}")
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("API_BASE_URL")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
# 2. 初始化 MCP Server
|
||||
mcp = FastMCP("模型mcp server")
|
||||
|
||||
@mcp.tool()
|
||||
async def query_model(
|
||||
token: str,
|
||||
model_type: str,
|
||||
model_tag: str,
|
||||
is_hot_stone: bool,
|
||||
name: str,
|
||||
page: int,
|
||||
size: int
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/queryModels"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"is_public": False,
|
||||
"model_type": model_type,
|
||||
"model_tag": model_tag,
|
||||
"is_hot_stone": is_hot_stone,
|
||||
"name": name
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询模型失败: {str(e)}"
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def update_model(token: str,
|
||||
id: int,
|
||||
git_id: int,
|
||||
identifier: str,
|
||||
owner: str,
|
||||
model_type: str,
|
||||
model_tag: str,
|
||||
) -> str:
|
||||
url = f"{API_BASE_URL}/api/mmp/newmodel/updateModel"
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
params = {
|
||||
"id": id,
|
||||
"git_id": git_id,
|
||||
"identifier": identifier,
|
||||
"owner": owner,
|
||||
"model_type": model_type,
|
||||
"model_tag": model_tag,
|
||||
"preview_pic": "https://www.ai4mats.com/minio/data/mini-model-platform-data/temp/fanshuai/1761528061144/model/材料筛选.png"
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.put(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 更新模型失败: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def query_model_type_list(
|
||||
token: str
|
||||
):
|
||||
url = f"{API_BASE_URL}/api/mmp/assetIcon"
|
||||
headers = { "Content-Type": "application/json; charset=UTF-8",
|
||||
"Authorization": f"Bearer {token}"}
|
||||
params = {
|
||||
"category_id": 2,
|
||||
}
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.get(url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
# return f"✅ 应用模型成功!\n{json.dumps(result, indent=2, ensure_ascii=False)}"
|
||||
return result
|
||||
except Exception as e:
|
||||
return f"❌ 查询模型类型列表失败: {str(e)}"
|
||||
|
||||
# 4. 运行服务
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 启动应用部署 MCP 服务,传输模式: {TRANSPORT_MODE}")
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
FROM python:3.10-slim
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 复制依赖文件
|
||||
COPY requirements.txt .
|
||||
|
||||
# 安装依赖
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# 复制代码
|
||||
COPY . .
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 8000
|
||||
|
||||
# 启动命令
|
||||
CMD ["python", "main.py"]
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
|
||||
"BAYESIAN_API_BASE_URL": "http://218.77.58.19:22222",
|
||||
"TIMEOUT": 120
|
||||
"MCP_TRANSPORT": "http"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,108 +0,0 @@
|
|||
{
|
||||
"add_dataset": {
|
||||
"name": "测试数据集",
|
||||
"preview_pic": "http://172.20.32.121:31213/minio/data/mini-model-platform-data/temp/test/test.png",
|
||||
"dataset_source": "add",
|
||||
"data_type": "通用数据",
|
||||
"data_tag": "test",
|
||||
"is_public": false,
|
||||
"is_hot_stone": false
|
||||
},
|
||||
"get_asset_icon": {
|
||||
"page": 0,
|
||||
"size": 100,
|
||||
"category_id": 1
|
||||
},
|
||||
"upload_chunk": {
|
||||
"chunkNumber": 1,
|
||||
"chunkSize": 10485760,
|
||||
"currentChunkSize": 9577,
|
||||
"totalSize": 9577,
|
||||
"identifier": "e174a5dd7c5357a2efc3416ee0465e3c",
|
||||
"filename": "test.zip",
|
||||
"relativePath": "test.zip",
|
||||
"totalChunks": 1
|
||||
},
|
||||
"add_version": {
|
||||
"git_id": 125,
|
||||
"id": 47,
|
||||
"identifier": "test_dataset_20260520100000",
|
||||
"is_public": false,
|
||||
"owner": "test_user",
|
||||
"name": "测试数据集",
|
||||
"version": "v1",
|
||||
"version_desc": "初始版本",
|
||||
"dataset_source": "add",
|
||||
"dataset_version_vos": [
|
||||
{
|
||||
"file_name": "test.zip",
|
||||
"file_size": 9577,
|
||||
"url": "/home/resource/temp/test/e174a5dd7c5357a2efc3416ee0465e3c/test.zip"
|
||||
}
|
||||
]
|
||||
},
|
||||
"update_dataset": {
|
||||
"id": 47,
|
||||
"name": "测试数据集_修改",
|
||||
"identifier": "test_dataset_20260520100000",
|
||||
"description": "测试描述",
|
||||
"is_public": false,
|
||||
"data_type": "通用数据",
|
||||
"data_tag": "test",
|
||||
"praises_count": 0,
|
||||
"praised": false,
|
||||
"create_by": "test_user",
|
||||
"update_time": "2026-05-20 10:00:00",
|
||||
"owner": "test_user",
|
||||
"dataset_source": "add",
|
||||
"relative_paths": "test/datasets/125/test_dataset_20260520100000/origin/dataset",
|
||||
"is_hot_stone": false,
|
||||
"git_id": 125,
|
||||
"preview_pic": "http://172.20.32.121:31213/minio/data/mini-model-platform-data/temp/test/test.png",
|
||||
"type": 0
|
||||
},
|
||||
"update_desc": {
|
||||
"git_id": 125,
|
||||
"identifier": "test_dataset_20260520100000",
|
||||
"description": "更新后的数据集简介"
|
||||
},
|
||||
"publish_dataset": {
|
||||
"id": 47,
|
||||
"name": "测试数据集"
|
||||
},
|
||||
"download_all_files": {
|
||||
"name": "测试数据集",
|
||||
"git_id": 125,
|
||||
"version": "v1",
|
||||
"identifier": "test_dataset_20260520100000",
|
||||
"owner": "test_user",
|
||||
"is_public": false
|
||||
},
|
||||
"download_single_file": {
|
||||
"url": "/home/resource/test/datasets/125/test_dataset_20260520100000/v1/dataset/test.zip"
|
||||
},
|
||||
"delete_version": {
|
||||
"git_id": 125,
|
||||
"owner": "test_user",
|
||||
"identifier": "test_dataset_20260520100000",
|
||||
"relative_paths": "test/datasets/125/test_dataset_20260520100000/v1/dataset",
|
||||
"version": "v1"
|
||||
},
|
||||
"delete_dataset": {
|
||||
"id": 47
|
||||
},
|
||||
"query_datasets": {
|
||||
"page": 0,
|
||||
"size": 20,
|
||||
"is_public": false,
|
||||
"data_type": "",
|
||||
"is_hot_stone": false
|
||||
},
|
||||
"get_dataset_detail": {
|
||||
"git_id": 74,
|
||||
"owner": "test_user",
|
||||
"name": "测试数据集",
|
||||
"identifier": "test_dataset_20260520100000",
|
||||
"is_public": false
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,14 @@
|
|||
version: "3.9"
|
||||
|
||||
services:
|
||||
mcp-service:
|
||||
build: ./tools
|
||||
container_name: cvd-app
|
||||
environment:
|
||||
- API_BASE_URL=http://218.77.58.19:22222
|
||||
mcp-services:
|
||||
build: .
|
||||
container_name: ai4mats-mcp
|
||||
ports:
|
||||
- "18889:8000"
|
||||
- "18425:8000"
|
||||
volumes:
|
||||
# 如需动态修改配置,可挂载
|
||||
- ./config:/app/config
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
restart: unless-stopped
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import uvicorn
|
||||
from starlette.applications import Starlette
|
||||
from starlette.routing import Mount
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
|
||||
from tools.bayesian_mcp_server import mcp as bayesian_mcp
|
||||
from tools.app_deploy_mcp_server import mcp as app_deploy_mcp
|
||||
from tools.cvd_chat_recommender_mcp_server import mcp as cvd_chat_mcp
|
||||
from tools.cvd_param_recommender_mcp_server import mcp as cvd_param_mcp
|
||||
from tools.tem_analysis_mcp_server import mcp as tem_mcp
|
||||
|
||||
# FastMCP 内部就是 Starlette app
|
||||
routes = [
|
||||
Mount("/mcp/bayesian", bayesian_mcp.sse_app()),
|
||||
Mount("/mcp/app-deploy", app_deploy_mcp.sse_app()),
|
||||
Mount("/mcp/cvd-chat", cvd_chat_mcp.sse_app()),
|
||||
Mount("/mcp/cvd-param", cvd_param_mcp.sse_app()),
|
||||
Mount("/mcp/tem-analysis", tem_mcp.sse_app()),
|
||||
]
|
||||
|
||||
app = Starlette(routes=routes)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# test_bayesian.py
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
from tools.bayesian_mcp_server import predict_next_five_rounds
|
||||
|
||||
|
||||
async def main():
|
||||
print("🚀 开始测试 贝叶斯分析 MCP 服务...")
|
||||
|
||||
# 测试参数(使用您之前提供的示例数据)
|
||||
try:
|
||||
result = await predict_next_five_rounds(
|
||||
Concentration=6,
|
||||
T_S=210,
|
||||
T_Mo=860,
|
||||
growth_time=35,
|
||||
Ar=520,
|
||||
CO2=80,
|
||||
H2=10,
|
||||
Density=0.32,
|
||||
Width=0.48,
|
||||
R_stacking_ratio=0.77,
|
||||
rounds=5,
|
||||
suggestions_per_round=1
|
||||
)
|
||||
|
||||
print("\n✅ 贝叶斯分析 MCP 服务调用成功!")
|
||||
print("=" * 60)
|
||||
print("返回结果:")
|
||||
print(result)
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ 贝叶斯分析 MCP 服务调用失败: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from tools.cvd_chat_recommender_mcp_server import recommend_cvd_params
|
||||
|
||||
|
||||
async def main():
|
||||
print("🚀 开始测试 CVD 聊天推荐 MCP 服务...")
|
||||
|
||||
# 测试参数
|
||||
test_query = "我想制备单层MoS2,用于制作化学传感器"
|
||||
|
||||
# 调用 MCP 工具函数
|
||||
try:
|
||||
result = await recommend_cvd_params(test_query)
|
||||
|
||||
print("\n✅ MCP 服务调用成功!")
|
||||
print("=" * 50)
|
||||
print("返回结果:")
|
||||
print(result)
|
||||
print("=" * 50)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ MCP 服务调用失败: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import asyncio
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from tools.cvd_param_recommender_mcp_server import convert_to_device_params
|
||||
|
||||
|
||||
async def main():
|
||||
print("🚀 开始测试 CVD 参数推荐 MCP 服务...")
|
||||
|
||||
# 读取测试参数文件
|
||||
try:
|
||||
with open("../dataset/test_cvd.json", "r", encoding="utf-8") as f:
|
||||
params = json.load(f)
|
||||
except FileNotFoundError:
|
||||
print("❌ 错误:找不到 test_cvd.json 文件")
|
||||
return
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"❌ 错误:test_cvd.json 格式不正确: {e}")
|
||||
return
|
||||
|
||||
# 调用 MCP 工具函数
|
||||
try:
|
||||
# 注意:convert_to_device_params 是 async 函数
|
||||
result = await convert_to_device_params(
|
||||
start_order=params["start_order"],
|
||||
schemes_json_str=json.dumps(params["schemes"], ensure_ascii=False)
|
||||
)
|
||||
|
||||
print("\n✅ MCP 服务调用成功!")
|
||||
print("=" * 50)
|
||||
print("返回结果:")
|
||||
print(result)
|
||||
print("=" * 50)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ MCP 服务调用失败: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
import asyncio
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from tools.dataset_mcp_server import (
|
||||
login,
|
||||
add_dataset,
|
||||
get_asset_icon,
|
||||
get_data_types,
|
||||
upload_chunk,
|
||||
add_version,
|
||||
update_dataset,
|
||||
update_desc,
|
||||
publish_dataset,
|
||||
download_all_files,
|
||||
download_single_file,
|
||||
delete_version,
|
||||
delete_dataset,
|
||||
query_datasets,
|
||||
get_dataset_detail
|
||||
)
|
||||
|
||||
|
||||
async def run_test(test_name, func, params, retries=1):
|
||||
"""运行单个测试用例"""
|
||||
print(f"\n{'='*60}")
|
||||
print(f"🔧 测试: {test_name}")
|
||||
print(f"{'='*60}")
|
||||
print(f"参数: {json.dumps(params, indent=2, ensure_ascii=False)}")
|
||||
|
||||
try:
|
||||
result = await func(**params)
|
||||
print(f"\n✅ 成功!")
|
||||
print(f"返回结果: {result[:500]}{'...' if len(result) > 500 else ''}")
|
||||
return result, True
|
||||
except Exception as e:
|
||||
if retries > 0:
|
||||
print(f"\n⚠️ 失败,重试中 ({retries}次剩余): {e}")
|
||||
return await run_test(test_name, func, params, retries - 1)
|
||||
print(f"\n❌ 失败: {e}")
|
||||
return None, False
|
||||
|
||||
|
||||
async def main():
|
||||
print("🚀 开始测试数据集 MCP 服务...")
|
||||
|
||||
try:
|
||||
with open("../dataset/test_dataset.json", "r", encoding="utf-8") as f:
|
||||
test_data = json.load(f)
|
||||
except FileNotFoundError:
|
||||
print("❌ 错误:找不到 test_dataset.json 文件")
|
||||
return
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"❌ 错误:test_dataset.json 格式不正确: {e}")
|
||||
return
|
||||
|
||||
token = None
|
||||
|
||||
login_result, success = await run_test("登录获取Token", login, {})
|
||||
if success:
|
||||
try:
|
||||
login_data = json.loads(login_result)
|
||||
token = login_data.get("data", {}).get("access_token")
|
||||
print(f"\n📋 获取到Token: {token[:20]}...")
|
||||
except:
|
||||
print("❌ 解析Token失败")
|
||||
return
|
||||
else:
|
||||
print("❌ 登录失败,无法继续测试")
|
||||
return
|
||||
|
||||
test_cases = [
|
||||
("查询数据集分类", get_asset_icon, {"token": token, **test_data["get_asset_icon"]}),
|
||||
("获取可用数据类型", get_data_types, {"token": token}),
|
||||
("查询数据集列表", query_datasets, {"token": token, **test_data["query_datasets"]}),
|
||||
]
|
||||
|
||||
passed = 1
|
||||
failed = 0
|
||||
|
||||
for test_name, func, params in test_cases:
|
||||
_, success = await run_test(test_name, func, params)
|
||||
if success:
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
new_dataset_params = {"token": token, **test_data["add_dataset"]}
|
||||
dataset_name = test_data["add_dataset"]["name"]
|
||||
|
||||
add_result, success = await run_test("新增数据集", add_dataset, new_dataset_params)
|
||||
|
||||
while not success or (add_result and "项目名称已被使用" in add_result):
|
||||
if add_result and "项目名称已被使用" in add_result:
|
||||
timestamp = int(time.time())
|
||||
new_name = f"{dataset_name}_{timestamp}"
|
||||
print(f"\n⚠️ 项目名称已被使用,尝试新名称: {new_name}")
|
||||
new_dataset_params["name"] = new_name
|
||||
add_result, success = await run_test("新增数据集", add_dataset, new_dataset_params)
|
||||
else:
|
||||
break
|
||||
|
||||
if success:
|
||||
passed += 1
|
||||
try:
|
||||
add_result_data = json.loads(add_result)
|
||||
dataset_id = add_result_data.get("data", {}).get("id", test_data["add_version"]["id"])
|
||||
print(f"\n📋 创建的数据集ID: {dataset_id}")
|
||||
except:
|
||||
dataset_id = test_data["add_version"]["id"]
|
||||
else:
|
||||
failed += 1
|
||||
dataset_id = test_data["add_version"]["id"]
|
||||
|
||||
remaining_tests = [
|
||||
("上传文件分片", upload_chunk, {"token": token, **test_data["upload_chunk"]}),
|
||||
("新增版本", add_version, {"token": token, **{"id": dataset_id, **test_data["add_version"]}}),
|
||||
("修改数据集", update_dataset, {"token": token, **{"id": dataset_id, **test_data["update_dataset"]}}),
|
||||
("编辑数据集简介", update_desc, {"token": token, **test_data["update_desc"]}),
|
||||
("发布数据集", publish_dataset, {"token": token, **{"id": dataset_id, **test_data["publish_dataset"]}}),
|
||||
("下载全部文件", download_all_files, {"token": token, **test_data["download_all_files"]}),
|
||||
("下载单个文件", download_single_file, {"token": token, **test_data["download_single_file"]}),
|
||||
("删除版本", delete_version, {"token": token, **test_data["delete_version"]}),
|
||||
("删除数据集", delete_dataset, {"token": token, **{"id": dataset_id}}),
|
||||
("查询数据集详情", get_dataset_detail, {"token": token, **test_data["get_dataset_detail"]})
|
||||
]
|
||||
|
||||
for test_name, func, params in remaining_tests:
|
||||
_, success = await run_test(test_name, func, params)
|
||||
if success:
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print("📊 测试结果汇总")
|
||||
print(f"{'='*60}")
|
||||
print(f"通过: {passed}")
|
||||
print(f"失败: {failed}")
|
||||
print(f"成功率: {passed / (passed + failed) * 100:.1f}%")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# test_tem.py
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from tools.tem_analysis_mcp_server import analyze_tem_image
|
||||
|
||||
|
||||
async def main():
|
||||
print("🚀 开始测试 TEM 分析 MCP 服务...")
|
||||
|
||||
# 这是一个 1x1 像素的透明 PNG 图片的 Base64 编码(仅用于测试连通性)
|
||||
dummy_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
|
||||
|
||||
# 测试参数
|
||||
try:
|
||||
result = await analyze_tem_image(
|
||||
filename="test_sample.jpg",
|
||||
content_base64=dummy_base64,
|
||||
model="/detection/predict"
|
||||
)
|
||||
|
||||
print("\n✅ TEM 分析 MCP 服务调用成功!")
|
||||
print("=" * 60)
|
||||
print("返回结果:")
|
||||
print(result)
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ TEM 分析 MCP 服务调用失败: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN pip install --no-cache-dir \
|
||||
fastmcp==3.3.1 \
|
||||
httpx[http2]>=0.24.0 \
|
||||
uvicorn[standard]>=0.23.0
|
||||
|
||||
COPY cvd-app.py .
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["python", "cvd-app.py"]
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -10,7 +10,7 @@ def load_config():
|
|||
"""加载配置"""
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "https://www.ai4mats.com"
|
||||
"API_BASE_URL": "http://172.20.32.121:31213"
|
||||
}
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
import os
|
||||
import json
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# ============================================
|
||||
# 配置
|
||||
# ============================================
|
||||
def load_config():
|
||||
"""加载配置"""
|
||||
config_path = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "http://218.77.58.19:22222"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
default_config.update(json.load(f))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config["API_BASE_URL"]
|
||||
|
||||
# ============================================
|
||||
# MCP 服务定义
|
||||
# ============================================
|
||||
mcp = FastMCP("Bayesian-Analysis")
|
||||
|
||||
|
||||
# ============================================
|
||||
# 工具:贝叶斯预测
|
||||
# ============================================
|
||||
@mcp.tool()
|
||||
async def predict_next_five_rounds(
|
||||
Concentration: float,
|
||||
T_S: int,
|
||||
T_Mo: int,
|
||||
growth_time: int,
|
||||
Ar: int,
|
||||
CO2: int,
|
||||
H2: int,
|
||||
Density: float,
|
||||
Width: float,
|
||||
R_stacking_ratio: float,
|
||||
rounds: int = 5,
|
||||
suggestions_per_round: int = 1,
|
||||
) -> str:
|
||||
"""
|
||||
调用贝叶斯分析模型,预测未来几轮的工艺参数建议。
|
||||
|
||||
参数说明:
|
||||
- Concentration: 浓度
|
||||
- T_S: 温度 S
|
||||
- T_Mo: 温度 Mo
|
||||
- growth_time: 生长时间
|
||||
- Ar: 氩气流量
|
||||
- CO2: 二氧化碳流量
|
||||
- H2: 氢气流量
|
||||
- Density: 密度
|
||||
- Width: 宽度
|
||||
- R_stacking_ratio: 堆叠比
|
||||
- rounds: 预测轮数
|
||||
- suggestions_per_round: 每轮建议数
|
||||
"""
|
||||
|
||||
# ---------- 参数校验 ----------
|
||||
if Concentration <= 0 or Density <= 0 or Width <= 0:
|
||||
return "❌ 参数错误:浓度 / 密度 / 宽度必须大于 0"
|
||||
|
||||
if not (0 < R_stacking_ratio < 1):
|
||||
return "❌ 参数错误:堆叠比应在 0~1 之间"
|
||||
|
||||
# ---------- 构造请求 ----------
|
||||
url = f"{API_BASE_URL}/next-five-rounds"
|
||||
payload = {
|
||||
"Concentration": Concentration,
|
||||
"T_S": T_S,
|
||||
"T_Mo": T_Mo,
|
||||
"growth_time": growth_time,
|
||||
"Ar": Ar,
|
||||
"CO2": CO2,
|
||||
"H2": H2,
|
||||
"Density": Density,
|
||||
"Width": Width,
|
||||
"R_stacking_ratio": R_stacking_ratio,
|
||||
"rounds": rounds,
|
||||
"suggestions_per_round": suggestions_per_round,
|
||||
}
|
||||
|
||||
# ---------- 调用 API ----------
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=120.0) as client:
|
||||
response = await client.post(url, json=payload)
|
||||
response.raise_for_status()
|
||||
return json.dumps(
|
||||
response.json(),
|
||||
indent=2,
|
||||
ensure_ascii=False
|
||||
)
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"❌ 贝叶斯接口错误 ({e.response.status_code})"
|
||||
except httpx.TimeoutException:
|
||||
return "❌ 贝叶斯接口超时"
|
||||
except Exception as e:
|
||||
return f"❌ 调用失败:{e}"
|
||||
|
||||
|
||||
# ============================================
|
||||
# ⚠️ 注意:这里不写 mcp.run()
|
||||
# 由主网关统一启动
|
||||
# ============================================
|
||||
131
tools/cvd-app.py
131
tools/cvd-app.py
|
|
@ -1,131 +0,0 @@
|
|||
import os
|
||||
import json
|
||||
import uuid
|
||||
import httpx
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# ============================================
|
||||
# 配置
|
||||
# ============================================
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "../config/config.json")
|
||||
default_config = {
|
||||
"API_BASE_URL": "http://218.77.58.19:22222"
|
||||
}
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
default_config.update(json.load(f))
|
||||
except Exception:
|
||||
pass
|
||||
return default_config
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config["API_BASE_URL"]
|
||||
|
||||
mcp = FastMCP("CVD-TEM-MCP-Service")
|
||||
|
||||
|
||||
# ============================================
|
||||
# Tool:用户在 MCPHub 里只看到一个框「query」
|
||||
# ============================================
|
||||
@mcp.tool()
|
||||
async def recommend_cvd_chat(query: str) -> dict:
|
||||
"""
|
||||
推荐CVD工艺方案。
|
||||
用户直接描述需求即可,例如:
|
||||
"我想制备单层MoS₂,用于制作化学传感器"
|
||||
"""
|
||||
# item_id 内部自动生成,不让用户操心
|
||||
item_id = f"auto_{uuid.uuid4().hex[:8]}"
|
||||
|
||||
api_url = f"{API_BASE_URL}/svc/cvd/recommend_CVD_chat"
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=httpx.Timeout(120.0)) as client:
|
||||
async with client.stream(
|
||||
"POST",
|
||||
api_url,
|
||||
json={"item_id": item_id, "message": query}
|
||||
) as resp:
|
||||
resp.raise_for_status()
|
||||
content = ""
|
||||
async for chunk in resp.aiter_text():
|
||||
if chunk:
|
||||
content += chunk
|
||||
return {
|
||||
"content": [{"type": "text", "text": content.strip()}]
|
||||
}
|
||||
except httpx.ConnectTimeout:
|
||||
return {
|
||||
"content": [{"type": "text", "text": "❌ 连接后端服务超时,请检查网络"}],
|
||||
"isError": True,
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"content": [{"type": "text", "text": f"❌ 调用失败: {str(e)}"}],
|
||||
"isError": True,
|
||||
}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def convert_to_device_params(config_json: str) -> dict:
|
||||
"""
|
||||
CVD配置转设备参数。
|
||||
直接粘贴JSON配置字符串即可,例如:
|
||||
{"temperature": 700, "pressure": 5}
|
||||
"""
|
||||
import json as _json
|
||||
try:
|
||||
cfg = _json.loads(config_json)
|
||||
except Exception:
|
||||
return {
|
||||
"content": [{"type": "text", "text": "❌ 请输入合法JSON字符串"}],
|
||||
"isError": True,
|
||||
}
|
||||
|
||||
item_id = f"auto_{uuid.uuid4().hex[:8]}"
|
||||
api_url = f"{API_BASE_URL}/svc/cvd/convert_to_device_params"
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
resp = await client.post(
|
||||
api_url,
|
||||
json={"item_id": item_id, "config": cfg}
|
||||
)
|
||||
return resp.json()
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def bayesian(item_id: str = "") -> dict:
|
||||
"""贝叶斯预测(可不填item_id,直接回车)"""
|
||||
if not item_id:
|
||||
item_id = f"auto_{uuid.uuid4().hex[:8]}"
|
||||
api_url = f"{API_BASE_URL}/next-five-rounds"
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
resp = await client.get(api_url, params={"item_id": item_id})
|
||||
return resp.json()
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def tem_analysis(query: str) -> dict:
|
||||
"""
|
||||
TEM图像分析。
|
||||
描述你要做的分析即可,例如:
|
||||
"对sample_001做原子位置识别"
|
||||
"""
|
||||
item_id = f"auto_{uuid.uuid4().hex[:8]}"
|
||||
api_url = f"{API_BASE_URL}/svc/tem/analysis"
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
resp = await client.post(
|
||||
api_url,
|
||||
json={"item_id": item_id, "query": query}
|
||||
)
|
||||
return resp.json()
|
||||
|
||||
|
||||
# ============================================
|
||||
if __name__ == "__main__":
|
||||
mcp.run(
|
||||
transport="streamable-http",
|
||||
host="0.0.0.0",
|
||||
port=8000
|
||||
)
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
import os
|
||||
import json
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# ============================================
|
||||
# 配置
|
||||
# ============================================
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "../config/config.json")
|
||||
default_config = {
|
||||
"BAYESIAN_API_BASE_URL": "http://218.77.58.19:22222"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
default_config.update(json.load(f))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config["BAYESIAN_API_BASE_URL"]
|
||||
|
||||
# ============================================
|
||||
# MCP 服务定义
|
||||
# ============================================
|
||||
mcp = FastMCP("CVD-Chat-Recommender")
|
||||
|
||||
|
||||
# ============================================
|
||||
# 工具:CVD 参数推荐
|
||||
# ============================================
|
||||
@mcp.tool()
|
||||
async def recommend_cvd_params(query: str) -> str:
|
||||
"""
|
||||
根据用户的自然语言需求,推荐 CVD(化学气相沉积)工艺参数。
|
||||
|
||||
参数说明:
|
||||
- query: 用户的工艺需求描述
|
||||
示例:"我想制备单层MoS2,用于制作化学传感器"
|
||||
|
||||
返回:
|
||||
推荐的 CVD 工艺参数方案(温度、流量、时间等)
|
||||
"""
|
||||
|
||||
api_url = f"{API_BASE_URL}/svc/cvd/recommend_CVD_chat"
|
||||
payload = {"query": query}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=120.0) as client:
|
||||
response = await client.post(api_url, json=payload)
|
||||
response.raise_for_status()
|
||||
|
||||
try:
|
||||
return json.dumps(
|
||||
response.json(),
|
||||
indent=2,
|
||||
ensure_ascii=False
|
||||
)
|
||||
except:
|
||||
return response.text
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"❌ CVD 推荐接口错误 ({e.response.status_code})"
|
||||
except httpx.RequestError:
|
||||
return "❌ 无法连接 CVD 推荐服务"
|
||||
except Exception as e:
|
||||
return f"❌ 调用失败:{e}"
|
||||
|
||||
|
||||
# ============================================
|
||||
# ⚠️ 不写 mcp.run()
|
||||
# 由主网关统一启动
|
||||
# ============================================
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
import os
|
||||
import json
|
||||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
# ============================================
|
||||
# 配置
|
||||
# ============================================
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "../config/config.json")
|
||||
default_config = {
|
||||
"BAYESIAN_API_BASE_URL": "http://218.77.58.19:22222"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
default_config.update(json.load(f))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return default_config
|
||||
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config["BAYESIAN_API_BASE_URL"]
|
||||
|
||||
# ============================================
|
||||
# MCP 服务定义
|
||||
# ============================================
|
||||
mcp = FastMCP("CVD-Param-Recommender")
|
||||
|
||||
|
||||
# ============================================
|
||||
# 工具:转换为设备参数
|
||||
# ============================================
|
||||
@mcp.tool()
|
||||
async def convert_to_device_params(
|
||||
start_order: int,
|
||||
schemes_json_str: str
|
||||
) -> str:
|
||||
"""
|
||||
将 CVD 工艺方案(Schemes)转换为设备可执行的具体参数。
|
||||
|
||||
参数说明:
|
||||
- start_order: 起始指令序号(例如:1)
|
||||
- schemes_json_str: 工艺方案的 JSON 字符串数组。
|
||||
示例:'[{"非金属前驱体A": "S", "金属前驱体B": "MoO3"}]'
|
||||
"""
|
||||
|
||||
api_url = f"{API_BASE_URL}/svc/cvd/convert_to_device_params"
|
||||
|
||||
# ---------- 解析 JSON ----------
|
||||
try:
|
||||
schemes_data = json.loads(schemes_json_str)
|
||||
except json.JSONDecodeError as e:
|
||||
return f"❌ JSON 解析失败:{e}"
|
||||
|
||||
payload = {
|
||||
"start_order": start_order,
|
||||
"schemes": schemes_data
|
||||
}
|
||||
|
||||
# ---------- 调用 API ----------
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.post(api_url, json=payload)
|
||||
response.raise_for_status()
|
||||
|
||||
try:
|
||||
return json.dumps(
|
||||
response.json(),
|
||||
indent=2,
|
||||
ensure_ascii=False
|
||||
)
|
||||
except:
|
||||
return response.text
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"❌ 设备参数转换接口错误 ({e.response.status_code})"
|
||||
except httpx.RequestError:
|
||||
return "❌ 无法连接设备参数转换服务"
|
||||
except Exception as e:
|
||||
return f"❌ 调用失败:{e}"
|
||||
|
||||
|
||||
# ============================================
|
||||
# ⚠️ 不写 mcp.run()
|
||||
# 由主网关统一启动
|
||||
# ============================================
|
||||
|
|
@ -1,779 +0,0 @@
|
|||
import httpx
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
import os
|
||||
import json
|
||||
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(__file__), "../config/config.json")
|
||||
default_config = {
|
||||
"DATASET_API_BASE_URL": "https://www.ai4mats.com",
|
||||
"DATASET_DEFAULT_USERNAME": "fanshuai",
|
||||
"DATASET_DEFAULT_PASSWORD": "h1n2x3j4y5@",
|
||||
"MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
|
||||
try:
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
default_config.update(config)
|
||||
print(f"✅ 已加载配置文件: {config_path}")
|
||||
else:
|
||||
print(f"⚠️ 配置文件不存在,使用默认配置: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ 读取配置文件失败: {e},使用默认配置")
|
||||
|
||||
return default_config
|
||||
|
||||
config = load_config()
|
||||
API_BASE_URL = config.get("DATASET_API_BASE_URL")
|
||||
DEFAULT_USERNAME = config.get("DATASET_DEFAULT_USERNAME")
|
||||
DEFAULT_PASSWORD = config.get("DATASET_DEFAULT_PASSWORD")
|
||||
TRANSPORT_MODE = config.get("MCP_TRANSPORT")
|
||||
|
||||
mcp = FastMCP("Dataset-Service")
|
||||
|
||||
@mcp.tool()
|
||||
async def login(
|
||||
username: str = "",
|
||||
password: str = ""
|
||||
) -> str:
|
||||
"""
|
||||
获取访问token
|
||||
|
||||
参数说明:
|
||||
- username: 用户名 (可选,默认使用配置文件中的用户名)
|
||||
- password: 密码 (可选,默认使用配置文件中的密码)
|
||||
|
||||
返回: 包含access_token和expires_in的JSON字符串。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/auth/login"
|
||||
|
||||
if not username:
|
||||
username = DEFAULT_USERNAME
|
||||
if not password:
|
||||
password = DEFAULT_PASSWORD
|
||||
|
||||
payload = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.post(api_url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"登录 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接认证服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"登录时发生未知错误: {str(e)}"
|
||||
|
||||
def build_auth_headers(token: str) -> dict:
|
||||
"""构建包含token的请求头"""
|
||||
return {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
|
||||
@mcp.tool()
|
||||
async def add_dataset(
|
||||
name: str,
|
||||
token: str,
|
||||
preview_pic: str = "",
|
||||
dataset_source: str = "add",
|
||||
data_type: str = "通用数据",
|
||||
data_tag: str = "",
|
||||
is_public: bool = False,
|
||||
is_hot_stone: bool = False
|
||||
) -> str:
|
||||
"""
|
||||
新增数据集
|
||||
|
||||
参数说明:
|
||||
- name: 数据集名称
|
||||
- token: 访问令牌
|
||||
- preview_pic: 预览图片URL (可选)
|
||||
- dataset_source: 数据集来源 (默认: add)
|
||||
- data_type: 数据类型 (默认: 通用数据)
|
||||
- data_tag: 数据标签 (可选)
|
||||
- is_public: 是否公开 (默认: False)
|
||||
- is_hot_stone: 是否热门 (默认: False)
|
||||
|
||||
返回: 新增数据集的详细信息。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/addDataset"
|
||||
|
||||
payload = {
|
||||
"name": name,
|
||||
"preview_pic": preview_pic,
|
||||
"dataset_source": dataset_source,
|
||||
"data_type": data_type,
|
||||
"data_tag": data_tag,
|
||||
"is_public": is_public,
|
||||
"is_hot_stone": is_hot_stone
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.post(api_url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"新增数据集 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"新增数据集时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def get_asset_icon(
|
||||
token: str,
|
||||
page: int = 0,
|
||||
size: int = 10000,
|
||||
category_id: int = 1
|
||||
) -> str:
|
||||
"""
|
||||
查询数据集分类接口
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- page: 页码 (默认: 0)
|
||||
- size: 每页数量 (默认: 10000)
|
||||
- category_id: 分类ID (默认: 1)
|
||||
|
||||
返回: 数据集分类列表,包含一级分类和二级分类信息。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/assetIcon"
|
||||
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size,
|
||||
"category_id": category_id
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.get(api_url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"查询数据集分类 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"查询数据集分类时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def get_data_types(token: str) -> str:
|
||||
"""
|
||||
获取可用的数据集类型列表
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
|
||||
返回: 可用的数据类型列表,格式为[{"id": 138, "name": "通用数据"}, ...]
|
||||
"""
|
||||
try:
|
||||
asset_icon_result = await get_asset_icon(token)
|
||||
asset_icon_data = json.loads(asset_icon_result)
|
||||
|
||||
if asset_icon_data.get("code") != 200:
|
||||
return f"获取数据集分类失败: {asset_icon_data.get('msg', '未知错误')}"
|
||||
|
||||
data = asset_icon_data.get("data", [])
|
||||
data_types = []
|
||||
|
||||
for category in data:
|
||||
second_list = category.get("second_asset_icon_list", [])
|
||||
if second_list:
|
||||
for item in second_list:
|
||||
data_types.append({
|
||||
"id": item.get("id"),
|
||||
"name": item.get("name"),
|
||||
"parent_id": item.get("parent_id"),
|
||||
"path": item.get("path")
|
||||
})
|
||||
else:
|
||||
data_types.append({
|
||||
"id": category.get("id"),
|
||||
"name": category.get("name"),
|
||||
"parent_id": category.get("parent_id"),
|
||||
"path": category.get("path")
|
||||
})
|
||||
|
||||
return json.dumps({
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": data_types
|
||||
}, indent=2, ensure_ascii=False)
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
return f"解析数据集分类失败: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"获取数据类型列表时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def upload_chunk(
|
||||
token: str,
|
||||
chunkNumber: int,
|
||||
chunkSize: int,
|
||||
currentChunkSize: int,
|
||||
totalSize: int,
|
||||
identifier: str,
|
||||
filename: str,
|
||||
relativePath: str,
|
||||
totalChunks: int
|
||||
) -> str:
|
||||
"""
|
||||
上传版本文件(分片上传)
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- chunkNumber: 当前分片序号
|
||||
- chunkSize: 分片大小
|
||||
- currentChunkSize: 当前分片实际大小
|
||||
- totalSize: 总文件大小
|
||||
- identifier: 文件唯一标识
|
||||
- filename: 文件名
|
||||
- relativePath: 相对路径
|
||||
- totalChunks: 总分片数
|
||||
|
||||
返回: 上传结果,包含文件location用于新增版本。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/uploader/chunk"
|
||||
|
||||
params = {
|
||||
"chunkNumber": chunkNumber,
|
||||
"chunkSize": chunkSize,
|
||||
"currentChunkSize": currentChunkSize,
|
||||
"totalSize": totalSize,
|
||||
"identifier": identifier,
|
||||
"filename": filename,
|
||||
"relativePath": relativePath,
|
||||
"totalChunks": totalChunks
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.get(api_url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"上传文件 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"上传文件时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def add_version(
|
||||
token: str,
|
||||
git_id: int,
|
||||
id: int,
|
||||
identifier: str,
|
||||
is_public: bool,
|
||||
owner: str,
|
||||
name: str,
|
||||
version: str,
|
||||
version_desc: str,
|
||||
dataset_source: str = "add",
|
||||
dataset_version_vos: list = None
|
||||
) -> str:
|
||||
"""
|
||||
新增数据集版本
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- git_id: Git仓库ID
|
||||
- id: 数据集ID
|
||||
- identifier: 数据集标识
|
||||
- is_public: 是否公开
|
||||
- owner: 所有者
|
||||
- name: 数据集名称
|
||||
- version: 版本号 (例如: v1)
|
||||
- version_desc: 版本描述
|
||||
- dataset_source: 数据集来源 (默认: add)
|
||||
- dataset_version_vos: 版本文件列表,格式: [{"file_name":"xxx","file_size":xxx,"url":"xxx"}]
|
||||
|
||||
返回: 新增版本结果。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/addVersion"
|
||||
|
||||
payload = {
|
||||
"git_id": git_id,
|
||||
"id": id,
|
||||
"identifier": identifier,
|
||||
"is_public": is_public,
|
||||
"owner": owner,
|
||||
"name": name,
|
||||
"version": version,
|
||||
"version_desc": version_desc,
|
||||
"dataset_source": dataset_source,
|
||||
"dataset_version_vos": dataset_version_vos if dataset_version_vos else []
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.post(api_url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"新增版本 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"新增版本时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def update_dataset(
|
||||
token: str,
|
||||
id: int,
|
||||
name: str,
|
||||
identifier: str,
|
||||
description: str = "",
|
||||
is_public: bool = False,
|
||||
data_type: str = "通用数据",
|
||||
data_tag: str = "",
|
||||
praises_count: int = 0,
|
||||
praised: bool = False,
|
||||
create_by: str = "",
|
||||
update_time: str = "",
|
||||
owner: str = "",
|
||||
dataset_source: str = "add",
|
||||
relative_paths: str = "",
|
||||
is_hot_stone: bool = False,
|
||||
git_id: int = 0,
|
||||
preview_pic: str = "",
|
||||
type: int = 0
|
||||
) -> str:
|
||||
"""
|
||||
修改数据集
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- id: 数据集ID
|
||||
- name: 数据集名称
|
||||
- identifier: 数据集标识
|
||||
- description: 描述 (可选)
|
||||
- is_public: 是否公开 (默认: False)
|
||||
- data_type: 数据类型 (默认: 通用数据)
|
||||
- data_tag: 数据标签 (可选)
|
||||
- praises_count: 点赞数 (默认: 0)
|
||||
- praised: 是否已点赞 (默认: False)
|
||||
- create_by: 创建者 (可选)
|
||||
- update_time: 更新时间 (可选)
|
||||
- owner: 所有者 (可选)
|
||||
- dataset_source: 数据集来源 (默认: add)
|
||||
- relative_paths: 相对路径 (可选)
|
||||
- is_hot_stone: 是否热门 (默认: False)
|
||||
- git_id: Git仓库ID (默认: 0)
|
||||
- preview_pic: 预览图片URL (可选)
|
||||
- type: 类型 (默认: 0)
|
||||
|
||||
返回: 修改后的数据集信息。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/updateDataset"
|
||||
|
||||
payload = {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"identifier": identifier,
|
||||
"description": description,
|
||||
"is_public": is_public,
|
||||
"data_type": data_type,
|
||||
"data_tag": data_tag,
|
||||
"praises_count": praises_count,
|
||||
"praised": praised,
|
||||
"create_by": create_by,
|
||||
"update_time": update_time,
|
||||
"owner": owner,
|
||||
"dataset_source": dataset_source,
|
||||
"relative_paths": relative_paths,
|
||||
"is_hot_stone": is_hot_stone,
|
||||
"git_id": git_id,
|
||||
"preview_pic": preview_pic,
|
||||
"type": type
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.put(api_url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"修改数据集 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"修改数据集时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def update_desc(
|
||||
token: str,
|
||||
git_id: int,
|
||||
identifier: str,
|
||||
description: str
|
||||
) -> str:
|
||||
"""
|
||||
编辑数据集简介
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- git_id: Git仓库ID
|
||||
- identifier: 数据集标识
|
||||
- description: 数据集简介
|
||||
|
||||
返回: 操作结果。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/updateDesc"
|
||||
|
||||
payload = {
|
||||
"git_id": git_id,
|
||||
"identifier": identifier,
|
||||
"description": description
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.put(api_url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"编辑简介 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"编辑简介时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def publish_dataset(
|
||||
token: str,
|
||||
id: int,
|
||||
name: str
|
||||
) -> str:
|
||||
"""
|
||||
发布数据集
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- id: 数据集ID
|
||||
- name: 数据集名称
|
||||
|
||||
返回: 发布后的数据集信息。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/publish"
|
||||
|
||||
payload = {
|
||||
"id": id,
|
||||
"name": name
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.post(api_url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"发布数据集 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"发布数据集时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def download_all_files(
|
||||
token: str,
|
||||
name: str,
|
||||
git_id: int,
|
||||
version: str,
|
||||
identifier: str,
|
||||
owner: str,
|
||||
is_public: bool
|
||||
) -> str:
|
||||
"""
|
||||
当前版本所有文件打包下载
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- name: 数据集名称
|
||||
- git_id: Git仓库ID
|
||||
- version: 版本号
|
||||
- identifier: 数据集标识
|
||||
- owner: 所有者
|
||||
- is_public: 是否公开
|
||||
|
||||
返回: 文件下载链接或文件内容。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/downloadAllFiles"
|
||||
|
||||
params = {
|
||||
"name": name,
|
||||
"git_id": git_id,
|
||||
"version": version,
|
||||
"identifier": identifier,
|
||||
"owner": owner,
|
||||
"is_public": is_public
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=120.0) as client:
|
||||
response = await client.get(api_url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
content_type = response.headers.get("content-type", "")
|
||||
if "application/json" in content_type:
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
else:
|
||||
return f"文件下载成功,内容长度: {len(response.content)} bytes"
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"下载文件 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"下载文件时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def download_single_file(
|
||||
token: str,
|
||||
url: str
|
||||
) -> str:
|
||||
"""
|
||||
当前版本选中文件下载
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- url: 文件路径
|
||||
|
||||
返回: 文件下载链接或文件内容。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/downloadSingleFile"
|
||||
|
||||
params = {"url": url}
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=120.0) as client:
|
||||
response = await client.get(api_url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
content_type = response.headers.get("content-type", "")
|
||||
if "application/json" in content_type:
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
else:
|
||||
return f"文件下载成功,内容长度: {len(response.content)} bytes"
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"下载单个文件 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"下载单个文件时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def delete_version(
|
||||
token: str,
|
||||
git_id: int,
|
||||
owner: str,
|
||||
identifier: str,
|
||||
relative_paths: str,
|
||||
version: str
|
||||
) -> str:
|
||||
"""
|
||||
删除当前版本
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- git_id: Git仓库ID
|
||||
- owner: 所有者
|
||||
- identifier: 数据集标识
|
||||
- relative_paths: 相对路径
|
||||
- version: 版本号
|
||||
|
||||
返回: 操作结果。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/deleteDatasetVersion"
|
||||
|
||||
params = {
|
||||
"git_id": git_id,
|
||||
"owner": owner,
|
||||
"identifier": identifier,
|
||||
"relative_paths": relative_paths,
|
||||
"version": version
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.delete(api_url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"删除版本 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"删除版本时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def delete_dataset(
|
||||
token: str,
|
||||
id: int
|
||||
) -> str:
|
||||
"""
|
||||
删除数据集
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- id: 数据集ID
|
||||
|
||||
返回: 操作结果。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/deleteDataset/{id}"
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.delete(api_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"删除数据集 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"删除数据集时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def query_datasets(
|
||||
token: str,
|
||||
page: int = 0,
|
||||
size: int = 20,
|
||||
is_public: bool = None,
|
||||
data_type: str = "",
|
||||
is_hot_stone: bool = None
|
||||
) -> str:
|
||||
"""
|
||||
查询数据集列表
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- page: 页码 (默认: 0)
|
||||
- size: 每页数量 (默认: 20)
|
||||
- is_public: 是否公开 (可选)
|
||||
- data_type: 数据类型 (可选)
|
||||
- is_hot_stone: 是否热门 (可选)
|
||||
|
||||
返回: 数据集列表。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/queryDatasets"
|
||||
|
||||
params = {
|
||||
"page": page,
|
||||
"size": size
|
||||
}
|
||||
|
||||
if is_public is not None:
|
||||
params["is_public"] = is_public
|
||||
if data_type:
|
||||
params["data_type"] = data_type
|
||||
if is_hot_stone is not None:
|
||||
params["is_hot_stone"] = is_hot_stone
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.get(api_url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"查询数据集列表 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"查询数据集列表时发生未知错误: {str(e)}"
|
||||
|
||||
@mcp.tool()
|
||||
async def get_dataset_detail(
|
||||
token: str,
|
||||
git_id: int,
|
||||
owner: str,
|
||||
name: str,
|
||||
identifier: str,
|
||||
is_public: bool
|
||||
) -> str:
|
||||
"""
|
||||
查询数据集详情
|
||||
|
||||
参数说明:
|
||||
- token: 访问令牌
|
||||
- git_id: Git仓库ID
|
||||
- owner: 所有者
|
||||
- name: 数据集名称
|
||||
- identifier: 数据集标识
|
||||
- is_public: 是否公开
|
||||
|
||||
返回: 数据集详细信息。
|
||||
"""
|
||||
api_url = f"{API_BASE_URL}/api/mmp/newdataset/getDatasetDetail"
|
||||
|
||||
params = {
|
||||
"git_id": git_id,
|
||||
"owner": owner,
|
||||
"name": name,
|
||||
"identifier": identifier,
|
||||
"is_public": is_public
|
||||
}
|
||||
|
||||
headers = build_auth_headers(token)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=60.0) as client:
|
||||
response = await client.get(api_url, params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||
except httpx.HTTPStatusError as e:
|
||||
return f"查询数据集详情 API 返回错误 ({e.response.status_code}): {e.response.text}"
|
||||
except httpx.RequestError as e:
|
||||
return f"无法连接数据集服务: {str(e)}"
|
||||
except Exception as e:
|
||||
return f"查询数据集详情时发生未知错误: {str(e)}"
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport=TRANSPORT_MODE)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue