first commit

This commit is contained in:
douboer
2025-10-14 14:18:20 +08:00
commit d93bc02772
66 changed files with 21393 additions and 0 deletions

318
web/test-client.html Normal file
View File

@@ -0,0 +1,318 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MCP 客户端测试</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.status {
padding: 10px;
border-radius: 4px;
margin: 10px 0;
}
.success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
.error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
button {
background: #007bff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin: 5px;
}
button:hover { background: #0056b3; }
.form-group {
margin: 15px 0;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input, select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.server-list {
border: 1px solid #ddd;
border-radius: 4px;
margin: 15px 0;
}
.server-item {
padding: 15px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
}
.server-item:last-child { border-bottom: none; }
.server-info h3 { margin: 0 0 5px 0; }
.server-info p { margin: 0; color: #666; font-size: 14px; }
.tools-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 15px;
margin: 20px 0;
}
.tool-card {
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;
background: #f9f9f9;
}
.tool-card h4 { margin: 0 0 10px 0; color: #333; }
.tool-card p { margin: 0 0 10px 0; color: #666; font-size: 14px; }
</style>
</head>
<body>
<div class="container">
<h1>🚀 MCP Vue 客户端</h1>
<p>Model Context Protocol 客户端 - 支持 HTTP 和 SSE 传输</p>
<div id="status" class="status success">
✅ 客户端已加载
</div>
<!-- 添加服务器表单 -->
<div class="form-section">
<h2>添加 MCP 服务器</h2>
<div class="form-group">
<label>服务器名称:</label>
<input type="text" id="serverName" placeholder="例如: xhslogin" value="xhslogin">
</div>
<div class="form-group">
<label>服务器 URL:</label>
<input type="text" id="serverUrl" placeholder="http://127.0.0.1:3100/mcp" value="http://127.0.0.1:3100/mcp">
</div>
<div class="form-group">
<label>传输类型:</label>
<select id="transportType">
<option value="http">HTTP</option>
<option value="sse">Server-Sent Events</option>
</select>
</div>
<button onclick="addServer()">添加并连接服务器</button>
</div>
<!-- 服务器列表 -->
<div class="servers-section">
<h2>已连接的服务器</h2>
<div id="serverList" class="server-list">
<div class="server-item">
<div class="server-info">
<p>暂无服务器</p>
</div>
</div>
</div>
</div>
<!-- 工具列表 -->
<div class="tools-section">
<h2>可用工具</h2>
<div id="toolsList" class="tools-grid">
<div class="tool-card">
<p>请先添加并连接 MCP 服务器</p>
</div>
</div>
</div>
</div>
<script type="module">
// 模拟 MCP 客户端功能
let servers = [];
let tools = [];
// 模拟添加服务器
async function addServer() {
const name = document.getElementById('serverName').value;
const url = document.getElementById('serverUrl').value;
const type = document.getElementById('transportType').value;
if (!name || !url) {
updateStatus('请填写服务器名称和URL', 'error');
return;
}
updateStatus('正在连接服务器...', 'success');
try {
// 测试连接
const response = await fetch(url.replace('/mcp', '/health'));
if (response.ok) {
// 模拟成功连接
const server = {
id: Date.now().toString(),
name,
url,
type,
status: 'connected'
};
servers.push(server);
updateServerList();
// 模拟获取工具列表
await loadTools(server);
updateStatus(`✅ 成功连接到 ${name}`, 'success');
} else {
throw new Error(`服务器响应错误: ${response.status}`);
}
} catch (error) {
updateStatus(`❌ 连接失败: ${error.message}`, 'error');
}
}
// 模拟加载工具
async function loadTools(server) {
// 这里应该调用真正的 MCP 协议
const mockTools = [
{
name: 'get_account',
description: '获取账户信息',
serverId: server.id,
serverName: server.name
},
{
name: 'check_login_status',
description: '检查登录状态',
serverId: server.id,
serverName: server.name
},
{
name: 'publish_content',
description: '发布内容到小红书',
serverId: server.id,
serverName: server.name
}
];
tools = tools.concat(mockTools);
updateToolsList();
}
// 更新状态显示
function updateStatus(message, type = 'success') {
const statusEl = document.getElementById('status');
statusEl.textContent = message;
statusEl.className = `status ${type}`;
}
// 更新服务器列表
function updateServerList() {
const listEl = document.getElementById('serverList');
if (servers.length === 0) {
listEl.innerHTML = '<div class="server-item"><div class="server-info"><p>暂无服务器</p></div></div>';
return;
}
listEl.innerHTML = servers.map(server => `
<div class="server-item">
<div class="server-info">
<h3>${server.name}</h3>
<p>${server.url} (${server.type.toUpperCase()})</p>
</div>
<div class="server-actions">
<span style="color: green;">✅ 已连接</span>
<button onclick="removeServer('${server.id}')" style="background: #dc3545;">删除</button>
</div>
</div>
`).join('');
}
// 更新工具列表
function updateToolsList() {
const listEl = document.getElementById('toolsList');
if (tools.length === 0) {
listEl.innerHTML = '<div class="tool-card"><p>请先添加并连接 MCP 服务器</p></div>';
return;
}
listEl.innerHTML = tools.map(tool => `
<div class="tool-card">
<h4>🔧 ${tool.name}</h4>
<p>${tool.description}</p>
<p><small>来自: ${tool.serverName}</small></p>
<button onclick="callTool('${tool.serverId}', '${tool.name}')">调用工具</button>
</div>
`).join('');
}
// 删除服务器
function removeServer(serverId) {
servers = servers.filter(s => s.id !== serverId);
tools = tools.filter(t => t.serverId !== serverId);
updateServerList();
updateToolsList();
updateStatus('服务器已删除', 'success');
}
// 调用工具
async function callTool(serverId, toolName) {
const server = servers.find(s => s.id === serverId);
if (!server) return;
try {
updateStatus(`正在调用工具: ${toolName}...`, 'success');
// 这里应该调用真正的 MCP 工具
const response = await fetch(server.url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: Date.now().toString(),
method: 'tools/call',
params: {
name: toolName,
arguments: {}
}
})
});
if (response.ok) {
const result = await response.json();
updateStatus(`✅ 工具 ${toolName} 调用成功`, 'success');
console.log('工具调用结果:', result);
alert(`工具调用成功!\n${JSON.stringify(result, null, 2)}`);
} else {
throw new Error(`HTTP ${response.status}`);
}
} catch (error) {
updateStatus(`❌ 工具调用失败: ${error.message}`, 'error');
}
}
// 暴露函数到全局作用域
window.addServer = addServer;
window.removeServer = removeServer;
window.callTool = callTool;
// 页面加载完成
updateStatus('🚀 MCP 客户端已就绪,可以开始添加服务器', 'success');
</script>
</body>
</html>