Files
map-client-vue/web/public/debug.html
2025-10-14 14:18:20 +08:00

442 lines
14 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>