442 lines
14 KiB
HTML
442 lines
14 KiB
HTML
<!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>
|