fix(MCP): 修复导入MCP时传输代码丢失导致无法连接的问题
- 前端 MarketPage 提交时随 download_url 发送粘贴的 MCP 代码(handleSubmit+handleCreateApp) - 后端新增 parse_mcp_config 解析标准 JSON 配置, 提取 url/headers/transport - upload_app 与 _sync 使用解析器落库 mcp_servers 并自动连通性测试 - _test_mcp_server 连接测试携带 headers 鉴权头 - 优化 MCP 代码输入框占位符为真实配置格式
This commit is contained in:
1 parent
24ed907ba5
commit
47d38ca173
3 files changed
+4548
-1741
No files matched your search
File diff suppressed because it is too large.
Load diff
+821
-818
File diff suppressed because it is too large.
Load diff
@@ -541,7 +541,10 @@ const CreateToolModal: React.FC<CreateToolModalProps> = ({ appType, onClose, onS
|
|||||||
publisherName: 'demo_user',
|
publisherName: 'demo_user',
|
||||||
status: 'published' as const,
|
status: 'published' as const,
|
||||||
icon: appType === 'skill' ? 'S' : appType === 'agent' ? 'A' : 'M',
|
icon: appType === 'skill' ? 'S' : appType === 'agent' ? 'A' : 'M',
|
||||||
});
|
// 关键修复:把粘贴的 MCP 传输代码随提交一起发给后端,否则后端拿不到代码、URL 为空、永远连不上
|
||||||
|
mcpCode: appType === 'mcp' ? mcpCode.trim() : undefined,
|
||||||
|
mcpTransport: appType === 'mcp' ? mcpTransport : undefined,
|
||||||
|
} as any);
|
||||||
}, 1500);
|
}, 1500);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
};
|
};
|
||||||
@@ -721,13 +724,17 @@ const CreateToolModal: React.FC<CreateToolModalProps> = ({ appType, onClose, onS
|
|||||||
<label className="form-label">MCP客户端代码 <span className="required">*</span></label>
|
<label className="form-label">MCP客户端代码 <span className="required">*</span></label>
|
||||||
<textarea
|
<textarea
|
||||||
className="mcp-code-editor"
|
className="mcp-code-editor"
|
||||||
placeholder={`粘贴MCP客户端代码,例如:
|
placeholder={`粘贴 MCP 传输代码(标准 JSON 配置),例如:
|
||||||
const client = new MCPClient({
|
{
|
||||||
transport: {
|
"mcpServers": {
|
||||||
type: "${mcpTransport}",
|
"我的MCP服务": {
|
||||||
endpoint: "https://your-mcp-server.com/sse"
|
"type": "streamable_http",
|
||||||
|
"url": "https://your-mcp-server.com/mcp",
|
||||||
|
"headers": { "X-API-KEY": "your-key" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});`}
|
}
|
||||||
|
注意:请直接粘贴完整的传输代码,系统会自动解析 url / headers / 传输类型并建立连接`}
|
||||||
value={mcpCode}
|
value={mcpCode}
|
||||||
onChange={e => { setMcpCode(e.target.value); setMcpCodeVerifyResult('idle'); }}
|
onChange={e => { setMcpCode(e.target.value); setMcpCodeVerifyResult('idle'); }}
|
||||||
rows={10}
|
rows={10}
|
||||||
@@ -1044,10 +1051,16 @@ const HubImportModal: React.FC<HubImportModalProps> = ({ appType, platforms, onC
|
|||||||
<label className="form-label">MCP传输代码 <span className="required">*</span></label>
|
<label className="form-label">MCP传输代码 <span className="required">*</span></label>
|
||||||
<textarea
|
<textarea
|
||||||
className="mcp-code-editor"
|
className="mcp-code-editor"
|
||||||
placeholder={`粘贴MCP客户端代码(需通过AI验证后才能导入),例如:
|
placeholder={`粘贴 MCP 传输代码(标准 JSON 配置,需通过AI验证后才能导入),例如:
|
||||||
const mcpClient = new MCPClient({
|
{
|
||||||
transport: { type: "streamable-http", endpoint: "https://..." }
|
"mcpServers": {
|
||||||
});`}
|
"我的MCP服务": {
|
||||||
|
"type": "streamable_http",
|
||||||
|
"url": "https://your-mcp-server.com/mcp",
|
||||||
|
"headers": { "X-API-KEY": "your-key" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`}
|
||||||
value={hubCode}
|
value={hubCode}
|
||||||
onChange={e => { setHubCode(e.target.value); setHubCodeVerifyResult('idle'); }}
|
onChange={e => { setHubCode(e.target.value); setHubCodeVerifyResult('idle'); }}
|
||||||
rows={8}
|
rows={8}
|
||||||
@@ -1178,10 +1191,16 @@ const mcpClient = new MCPClient({
|
|||||||
<label className="form-label">Streamable HTTP 传输代码 <span className="required">*</span></label>
|
<label className="form-label">Streamable HTTP 传输代码 <span className="required">*</span></label>
|
||||||
<textarea
|
<textarea
|
||||||
className="mcp-code-editor"
|
className="mcp-code-editor"
|
||||||
placeholder={`粘贴 ${p.name} 的 MCP 客户端代码(需通过AI验证后才能导入),例如:
|
placeholder={`粘贴 ${p.name} 的 MCP 传输代码(标准 JSON 配置,需通过AI验证后才能导入),例如:
|
||||||
const mcpClient = new MCPClient({
|
{
|
||||||
transport: { type: "streamable-http", endpoint: "https://..." }
|
"mcpServers": {
|
||||||
});`}
|
"我的MCP服务": {
|
||||||
|
"type": "streamable_http",
|
||||||
|
"url": "https://your-mcp-server.com/mcp",
|
||||||
|
"headers": { "X-API-KEY": "your-key" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`}
|
||||||
value={hubCodeMap[p.id] || ''}
|
value={hubCodeMap[p.id] || ''}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
setHubCodeMap(prev => ({ ...prev, [p.id]: e.target.value }));
|
setHubCodeMap(prev => ({ ...prev, [p.id]: e.target.value }));
|
||||||
@@ -1471,7 +1490,7 @@ const MarketPage: React.FC = () => {
|
|||||||
// Handle create tool - 调用后端 API 创建应用
|
// Handle create tool - 调用后端 API 创建应用
|
||||||
const handleCreateApp = async (data: Partial<MarketApp>) => {
|
const handleCreateApp = async (data: Partial<MarketApp>) => {
|
||||||
try {
|
try {
|
||||||
await marketAPI.createApp({
|
const payload: any = {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
type: data.type || 'skill',
|
type: data.type || 'skill',
|
||||||
description: data.description || '',
|
description: data.description || '',
|
||||||
@@ -1479,11 +1498,20 @@ const MarketPage: React.FC = () => {
|
|||||||
is_member_free: data.isMemberFree ?? true,
|
is_member_free: data.isMemberFree ?? true,
|
||||||
join_promotion: data.joinPromotion ?? false,
|
join_promotion: data.joinPromotion ?? false,
|
||||||
source: 'user',
|
source: 'user',
|
||||||
});
|
};
|
||||||
|
// 关键修复:把粘贴的 MCP 传输代码作为 download_url 传给后端,
|
||||||
|
// 后端会据此解析出 url / headers / transport 并自动注册到 mcp_servers 表做一次连通性测试
|
||||||
|
const mcpCode = (data as any).mcpCode as string | undefined;
|
||||||
|
if (data.type === 'mcp' && mcpCode) {
|
||||||
|
payload.download_url = mcpCode;
|
||||||
|
payload.mcp_transport = (data as any).mcpTransport || 'streamable_http';
|
||||||
|
}
|
||||||
|
await marketAPI.createApp(payload);
|
||||||
// 重新加载列表
|
// 重新加载列表
|
||||||
loadApps();
|
loadApps();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error('创建应用失败:', e);
|
console.error('创建应用失败:', e);
|
||||||
|
alert('创建应用失败:' + (e?.detail || e?.message || '未知错误'));
|
||||||
}
|
}
|
||||||
setShowCreateModal(null);
|
setShowCreateModal(null);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user