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

441
web/public/debug.html Normal file
View File

@@ -0,0 +1,441 @@
<!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: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background: #f5f5f5;
}
h1 {
color: #333;
border-bottom: 2px solid #4CAF50;
padding-bottom: 10px;
}
.section {
background: white;
padding: 20px;
margin: 20px 0;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.button {
background: #4CAF50;
color: white;
border: none;
padding: 10px 20px;
margin: 5px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.button:hover {
background: #45a049;
}
.button:disabled {
background: #ccc;
cursor: not-allowed;
}
.output {
background: #f9f9f9;
border: 1px solid #ddd;
padding: 15px;
margin-top: 10px;
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 13px;
max-height: 400px;
overflow-y: auto;
white-space: pre-wrap;
word-wrap: break-word;
}
.success { color: #4CAF50; }
.error { color: #f44336; }
.info { color: #2196F3; }
.status {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 8px;
}
.status.connected { background: #4CAF50; }
.status.disconnected { background: #9e9e9e; }
.status.connecting { background: #2196F3; }
.status.error { background: #f44336; }
input, select {
width: 100%;
padding: 8px;
margin: 5px 0;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
label {
display: block;
margin-top: 10px;
font-weight: bold;
color: #555;
}
</style>
</head>
<body>
<h1>🔧 MCP 客户端调试工具</h1>
<div class="section">
<h2>📊 系统状态</h2>
<p><strong>前端:</strong> <span id="frontendStatus">检查中...</span></p>
<p><strong>MCP HTTP服务器:</strong> <span id="httpServerStatus">检查中...</span></p>
<p><strong>MCP SSE服务器:</strong> <span id="sseServerStatus">检查中...</span></p>
<button class="button" onclick="checkSystemStatus()">🔄 刷新状态</button>
</div>
<div class="section">
<h2>🧪 测试 MCP 协议</h2>
<label>服务器URL:</label>
<input type="text" id="testServerUrl" value="http://localhost:3100/mcp" placeholder="http://localhost:3100/mcp">
<label>传输类型:</label>
<select id="testTransportType">
<option value="http">HTTP</option>
<option value="sse">SSE</option>
</select>
<div style="margin-top: 15px;">
<button class="button" onclick="testInitialize()">1⃣ 测试 Initialize</button>
<button class="button" onclick="testListTools()">2⃣ 测试 List Tools</button>
<button class="button" onclick="testCallTool()">3⃣ 测试 Call Tool</button>
</div>
<div class="output" id="protocolOutput">等待测试...</div>
</div>
<div class="section">
<h2>🎯 测试前端功能</h2>
<p><strong>提示:</strong> 请在浏览器中打开 <a href="http://localhost:5173" target="_blank">http://localhost:5173</a></p>
<h3>编辑按钮测试清单:</h3>
<ol>
<li>打开控制台 (F12 或 Cmd+Option+I)</li>
<li>切换到 Console 标签</li>
<li>点击任意服务器的"编辑"按钮</li>
<li>查看是否有以下日志输出:
<ul>
<li><code class="info">🔍 打开服务器详情: {...}</code></li>
<li><code class="info">✅ 详情页状态: true {...}</code></li>
</ul>
</li>
<li>检查是否弹出服务器详情对话框</li>
</ol>
<h3>连接测试清单:</h3>
<ol>
<li>确保MCP服务器正在运行 (见上方系统状态)</li>
<li>添加新服务器或选择现有服务器</li>
<li>服务器状态应该是 <span class="status disconnected"></span> 断开连接</li>
<li>点击"连接"按钮</li>
<li>查看控制台日志:
<ul>
<li><code class="info">🔌 开始连接服务器: xxx</code></li>
<li><code class="info">📡 正在连接 xxx...</code></li>
<li><code class="success">✅ 连接成功: xxx</code></li>
</ul>
</li>
<li>状态应该变为 <span class="status connected"></span> 已连接</li>
<li>点击"断开"按钮测试断开连接</li>
<li>再次点击"连接"测试重新连接 (这是修复的关键!)</li>
</ol>
</div>
<div class="section">
<h2>📝 调试信息收集</h2>
<button class="button" onclick="collectDebugInfo()">🔍 收集调试信息</button>
<div class="output" id="debugOutput">点击按钮收集调试信息...</div>
</div>
<script>
// 输出辅助函数
function log(element, message, type = 'info') {
const output = document.getElementById(element);
const timestamp = new Date().toLocaleTimeString();
const className = type === 'success' ? 'success' : type === 'error' ? 'error' : 'info';
output.innerHTML += `<span class="${className}">[${timestamp}] ${message}</span>\n`;
output.scrollTop = output.scrollHeight;
}
function clearLog(element) {
document.getElementById(element).innerHTML = '';
}
// 检查系统状态
async function checkSystemStatus() {
// 检查前端
try {
const frontendResp = await fetch('http://localhost:5173');
document.getElementById('frontendStatus').innerHTML =
'<span class="success">✅ 运行中</span>';
} catch (e) {
document.getElementById('frontendStatus').innerHTML =
'<span class="error">❌ 未运行</span>';
}
// 检查 HTTP MCP 服务器
try {
const httpResp = await fetch('http://localhost:3100/mcp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
clientInfo: { name: 'debug-tool', version: '1.0.0' }
}
})
});
const data = await httpResp.json();
if (data.result) {
document.getElementById('httpServerStatus').innerHTML =
`<span class="success">✅ 运行中 (${data.result.serverInfo?.name})</span>`;
} else {
throw new Error('Invalid response');
}
} catch (e) {
document.getElementById('httpServerStatus').innerHTML =
'<span class="error">❌ 未运行或无响应</span>';
}
// 检查 SSE MCP 服务器
try {
const sseResp = await fetch('http://localhost:3200/sse');
if (sseResp.ok) {
document.getElementById('sseServerStatus').innerHTML =
'<span class="success">✅ 运行中</span>';
} else {
throw new Error('Invalid response');
}
} catch (e) {
document.getElementById('sseServerStatus').innerHTML =
'<span class="error">❌ 未运行或无响应</span>';
}
}
// 测试 Initialize
async function testInitialize() {
clearLog('protocolOutput');
const url = document.getElementById('testServerUrl').value;
const type = document.getElementById('testTransportType').value;
log('protocolOutput', `开始测试 initialize 方法...`);
log('protocolOutput', `服务器: ${url}`);
log('protocolOutput', `传输类型: ${type}`);
try {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
clientInfo: {
name: 'mcp-debug-tool',
version: '1.0.0'
},
capabilities: {}
}
})
});
const data = await response.json();
log('protocolOutput', '响应:', 'success');
log('protocolOutput', JSON.stringify(data, null, 2), 'success');
if (data.result) {
log('protocolOutput', `✅ 服务器: ${data.result.serverInfo?.name} v${data.result.serverInfo?.version}`, 'success');
log('protocolOutput', `✅ 协议版本: ${data.result.protocolVersion}`, 'success');
} else if (data.error) {
log('protocolOutput', `❌ 错误: ${data.error.message}`, 'error');
}
} catch (error) {
log('protocolOutput', `❌ 请求失败: ${error.message}`, 'error');
}
}
// 测试 List Tools
async function testListTools() {
clearLog('protocolOutput');
const url = document.getElementById('testServerUrl').value;
log('protocolOutput', `开始测试 tools/list 方法...`);
try {
// 先 initialize
const initResp = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
clientInfo: { name: 'mcp-debug-tool', version: '1.0.0' },
capabilities: {}
}
})
});
await initResp.json();
// 然后列出工具
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 2,
method: 'tools/list',
params: {}
})
});
const data = await response.json();
log('protocolOutput', '响应:', 'success');
log('protocolOutput', JSON.stringify(data, null, 2), 'success');
if (data.result?.tools) {
log('protocolOutput', `✅ 找到 ${data.result.tools.length} 个工具`, 'success');
data.result.tools.forEach((tool, index) => {
log('protocolOutput', ` ${index + 1}. ${tool.name} - ${tool.description}`, 'info');
});
} else if (data.error) {
log('protocolOutput', `❌ 错误: ${data.error.message}`, 'error');
}
} catch (error) {
log('protocolOutput', `❌ 请求失败: ${error.message}`, 'error');
}
}
// 测试 Call Tool
async function testCallTool() {
clearLog('protocolOutput');
const url = document.getElementById('testServerUrl').value;
log('protocolOutput', `开始测试 tools/call 方法...`);
log('protocolOutput', `将调用 get_account 工具...`);
try {
// 先 initialize
const initResp = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
clientInfo: { name: 'mcp-debug-tool', version: '1.0.0' },
capabilities: {}
}
})
});
await initResp.json();
// 调用工具
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 3,
method: 'tools/call',
params: {
name: 'get_account',
arguments: {}
}
})
});
const data = await response.json();
log('protocolOutput', '响应:', 'success');
log('protocolOutput', JSON.stringify(data, null, 2), 'success');
if (data.result) {
log('protocolOutput', `✅ 工具调用成功`, 'success');
} else if (data.error) {
log('protocolOutput', `❌ 错误: ${data.error.message}`, 'error');
}
} catch (error) {
log('protocolOutput', `❌ 请求失败: ${error.message}`, 'error');
}
}
// 收集调试信息
async function collectDebugInfo() {
clearLog('debugOutput');
log('debugOutput', '=== 系统信息 ===');
log('debugOutput', `浏览器: ${navigator.userAgent}`);
log('debugOutput', `时间: ${new Date().toLocaleString()}`);
log('debugOutput', '');
log('debugOutput', '=== 服务状态检查 ===');
// 检查前端
try {
const frontendResp = await fetch('http://localhost:5173');
log('debugOutput', '✅ 前端服务: 运行中', 'success');
} catch (e) {
log('debugOutput', '❌ 前端服务: 未运行', 'error');
}
// 检查 HTTP MCP
try {
const httpResp = await fetch('http://localhost:3100/mcp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
clientInfo: { name: 'debug', version: '1.0.0' }
}
})
});
const data = await httpResp.json();
log('debugOutput', `✅ HTTP MCP服务: ${data.result?.serverInfo?.name} v${data.result?.serverInfo?.version}`, 'success');
} catch (e) {
log('debugOutput', `❌ HTTP MCP服务: ${e.message}`, 'error');
}
log('debugOutput', '');
log('debugOutput', '=== 建议操作 ===');
log('debugOutput', '1. 如果MCP服务未运行请执行:');
log('debugOutput', ' cd /Users/gavin/xhs/mcp_client/xhsLoginMCP && node server.js');
log('debugOutput', '');
log('debugOutput', '2. 如果前端未运行,请执行:');
log('debugOutput', ' cd /Users/gavin/xhs/mcp_client/mcp-client-vue/web && npm run dev');
log('debugOutput', '');
log('debugOutput', '3. 打开前端应用: http://localhost:5173');
log('debugOutput', '4. 打开浏览器控制台查看日志');
log('debugOutput', '5. 测试编辑按钮和连接功能');
}
// 页面加载时检查状态
window.addEventListener('load', checkSystemStatus);
</script>
</body>
</html>