Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- mcp.json +21 -0
- static/dashboard.html +164 -22
mcp.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"version": 1,
|
| 3 |
+
"servers": [
|
| 4 |
+
{
|
| 5 |
+
"id": "example-local",
|
| 6 |
+
"name": "Example MCP Server",
|
| 7 |
+
"url": "http://localhost:3000/mcp",
|
| 8 |
+
"auth": {
|
| 9 |
+
"apiKey": "",
|
| 10 |
+
"token": ""
|
| 11 |
+
},
|
| 12 |
+
"headers": {},
|
| 13 |
+
"tools": [
|
| 14 |
+
"search",
|
| 15 |
+
"read_file",
|
| 16 |
+
"write_file"
|
| 17 |
+
]
|
| 18 |
+
}
|
| 19 |
+
]
|
| 20 |
+
}
|
| 21 |
+
|
static/dashboard.html
CHANGED
|
@@ -479,6 +479,31 @@
|
|
| 479 |
</div>
|
| 480 |
</div>
|
| 481 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 482 |
</div>
|
| 483 |
</div>
|
| 484 |
|
|
@@ -786,10 +811,22 @@
|
|
| 786 |
}
|
| 787 |
const id = preferScope === 'agent' ? activeAgentTerminalId : activeTerminalId;
|
| 788 |
const t = terminals[id];
|
| 789 |
-
if (autoShow)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 790 |
if (t && t.ws && t.ws.readyState === WebSocket.OPEN) t.ws.send(data);
|
| 791 |
}
|
| 792 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 793 |
function openSettings() {
|
| 794 |
const overlay = document.getElementById('settings-overlay');
|
| 795 |
const drawer = document.getElementById('settings-drawer');
|
|
@@ -909,6 +946,22 @@
|
|
| 909 |
});
|
| 910 |
}
|
| 911 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 912 |
// Apply defaults if fields are empty
|
| 913 |
if (config.default_base_url && !document.getElementById('chat-base-url').value) {
|
| 914 |
document.getElementById('chat-base-url').value = config.default_base_url;
|
|
@@ -1200,6 +1253,7 @@
|
|
| 1200 |
function openAutonomousMode() {
|
| 1201 |
switchMode('chat');
|
| 1202 |
setChatMode('autonomous');
|
|
|
|
| 1203 |
}
|
| 1204 |
|
| 1205 |
window.addEventListener('resize', () => {
|
|
@@ -1667,11 +1721,71 @@
|
|
| 1667 |
url,
|
| 1668 |
apiKey: '',
|
| 1669 |
token: '',
|
| 1670 |
-
headersJson: '{}'
|
|
|
|
| 1671 |
});
|
| 1672 |
saveMcpServers(servers);
|
| 1673 |
}
|
| 1674 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1675 |
function deleteMcpServer(id) {
|
| 1676 |
if (!confirm('Delete this MCP server?')) return;
|
| 1677 |
const servers = loadMcpServers().filter(s => s.id !== id);
|
|
@@ -1683,8 +1797,8 @@
|
|
| 1683 |
saveMcpServers(servers);
|
| 1684 |
}
|
| 1685 |
|
| 1686 |
-
async function testMcpServer(id) {
|
| 1687 |
-
const statusEl = document.getElementById(`mcp-status-${id}`);
|
| 1688 |
const server = loadMcpServers().find(s => s.id === id);
|
| 1689 |
if (!server) return;
|
| 1690 |
statusEl.textContent = 'Testing...';
|
|
@@ -1712,7 +1826,12 @@
|
|
| 1712 |
}
|
| 1713 |
|
| 1714 |
function renderMcpServers() {
|
| 1715 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1716 |
if (!list) return;
|
| 1717 |
const servers = loadMcpServers();
|
| 1718 |
list.innerHTML = '';
|
|
@@ -1723,7 +1842,20 @@
|
|
| 1723 |
|
| 1724 |
servers.forEach((s) => {
|
| 1725 |
const card = document.createElement('div');
|
| 1726 |
-
card.className =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1727 |
card.innerHTML = `
|
| 1728 |
<div class="flex items-start justify-between gap-3">
|
| 1729 |
<div class="min-w-0">
|
|
@@ -1731,40 +1863,50 @@
|
|
| 1731 |
<div class="text-xs text-gray-400 truncate">${sanitizeHtml(s.url)}</div>
|
| 1732 |
</div>
|
| 1733 |
<div class="flex gap-2 shrink-0">
|
| 1734 |
-
<button class="bg-gray-700 hover:bg-gray-600 text-white px-2 py-1 rounded text-xs" type="button" id="mcp-test-${s.id}">Test</button>
|
| 1735 |
-
<button class="bg-red-600 hover:bg-red-700 text-white px-2 py-1 rounded text-xs" type="button" id="mcp-del-${s.id}">Delete</button>
|
| 1736 |
</div>
|
| 1737 |
</div>
|
|
|
|
|
|
|
| 1738 |
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
| 1739 |
<div>
|
| 1740 |
<label class="block text-xs font-semibold text-gray-400 mb-1 uppercase">API Key</label>
|
| 1741 |
-
<input type="password" value="${sanitizeHtml(s.apiKey || '')}" class="w-full bg-gray-700 text-sm rounded border border-gray-600 p-2 text-white outline-none focus:border-blue-500" id="mcp-apikey-${s.id}">
|
| 1742 |
</div>
|
| 1743 |
<div>
|
| 1744 |
<label class="block text-xs font-semibold text-gray-400 mb-1 uppercase">Bearer Token</label>
|
| 1745 |
-
<input type="password" value="${sanitizeHtml(s.token || '')}" class="w-full bg-gray-700 text-sm rounded border border-gray-600 p-2 text-white outline-none focus:border-blue-500" id="mcp-token-${s.id}">
|
| 1746 |
</div>
|
| 1747 |
</div>
|
| 1748 |
<div>
|
| 1749 |
<label class="block text-xs font-semibold text-gray-400 mb-1 uppercase">Extra Headers (JSON)</label>
|
| 1750 |
-
<textarea rows="2" class="w-full bg-gray-700 text-sm rounded border border-gray-600 p-2 text-white outline-none focus:border-blue-500 font-mono" id="mcp-headers-${s.id}">${sanitizeHtml(s.headersJson || '{}')}</textarea>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1751 |
</div>
|
| 1752 |
<div class="flex items-center justify-between">
|
| 1753 |
-
<div class="text-xs text-gray-300">Status: <span class="text-gray-100" id="mcp-status-${s.id}">—</span></div>
|
| 1754 |
-
<button class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-xs" type="button" id="mcp-save-${s.id}">Save</button>
|
| 1755 |
</div>
|
|
|
|
| 1756 |
`;
|
| 1757 |
list.appendChild(card);
|
| 1758 |
|
| 1759 |
-
document.getElementById(`mcp-del-${s.id}`).onclick = () => deleteMcpServer(s.id);
|
| 1760 |
-
document.getElementById(`mcp-test-${s.id}`).onclick = () => testMcpServer(s.id);
|
| 1761 |
-
|
| 1762 |
-
|
| 1763 |
-
|
| 1764 |
-
|
| 1765 |
-
|
| 1766 |
-
|
| 1767 |
-
|
|
|
|
|
|
|
|
|
|
| 1768 |
});
|
| 1769 |
}
|
| 1770 |
|
|
|
|
| 479 |
</div>
|
| 480 |
</div>
|
| 481 |
</div>
|
| 482 |
+
|
| 483 |
+
<div class="pt-4 border-t border-gray-700">
|
| 484 |
+
<div class="flex items-center justify-between gap-2 mb-2">
|
| 485 |
+
<div class="font-semibold text-gray-200">MCP</div>
|
| 486 |
+
<button onclick="addMcpServerPrompt()"
|
| 487 |
+
class="bg-blue-600 hover:bg-blue-700 text-white px-2 py-1 rounded text-xs">+ Add</button>
|
| 488 |
+
</div>
|
| 489 |
+
<div class="text-xs text-gray-400 mb-2">
|
| 490 |
+
Configure MCP servers (URLs + auth). Stored in <code>localStorage</code>. Import/export via <code>mcp.json</code>.
|
| 491 |
+
</div>
|
| 492 |
+
<div class="flex gap-2 mb-3">
|
| 493 |
+
<button onclick="exportMcpConfig()"
|
| 494 |
+
class="bg-gray-700 hover:bg-gray-600 text-white px-2 py-1 rounded text-xs">Export</button>
|
| 495 |
+
<input id="mcp-import-input" type="file" accept="application/json" class="hidden" />
|
| 496 |
+
<button onclick="document.getElementById('mcp-import-input').click()"
|
| 497 |
+
class="bg-gray-700 hover:bg-gray-600 text-white px-2 py-1 rounded text-xs">Import</button>
|
| 498 |
+
</div>
|
| 499 |
+
<div class="flex gap-2 mb-3">
|
| 500 |
+
<input id="mcp-direct-url" type="text" placeholder="Direct MCP URL (https://...)"
|
| 501 |
+
class="flex-grow bg-gray-700 text-sm rounded border border-gray-600 p-2 text-white outline-none focus:border-blue-500">
|
| 502 |
+
<button onclick="addMcpServerByUrl()"
|
| 503 |
+
class="bg-gray-700 hover:bg-gray-600 text-white px-2 rounded text-xs">Add</button>
|
| 504 |
+
</div>
|
| 505 |
+
<div id="settings-mcp-server-list" class="space-y-3"></div>
|
| 506 |
+
</div>
|
| 507 |
</div>
|
| 508 |
</div>
|
| 509 |
|
|
|
|
| 811 |
}
|
| 812 |
const id = preferScope === 'agent' ? activeAgentTerminalId : activeTerminalId;
|
| 813 |
const t = terminals[id];
|
| 814 |
+
if (autoShow) {
|
| 815 |
+
if (preferScope === 'agent') {
|
| 816 |
+
openAutonomousMode();
|
| 817 |
+
ensureAgentTerminalVisible();
|
| 818 |
+
} else {
|
| 819 |
+
switchMode('terminal');
|
| 820 |
+
}
|
| 821 |
+
}
|
| 822 |
if (t && t.ws && t.ws.readyState === WebSocket.OPEN) t.ws.send(data);
|
| 823 |
}
|
| 824 |
|
| 825 |
+
function ensureAgentTerminalVisible() {
|
| 826 |
+
const paneTerminal = document.getElementById('agent-pane-terminal');
|
| 827 |
+
if (paneTerminal && paneTerminal.classList.contains('hidden')) toggleAgentTerminalCollapsed();
|
| 828 |
+
}
|
| 829 |
+
|
| 830 |
function openSettings() {
|
| 831 |
const overlay = document.getElementById('settings-overlay');
|
| 832 |
const drawer = document.getElementById('settings-drawer');
|
|
|
|
| 946 |
});
|
| 947 |
}
|
| 948 |
|
| 949 |
+
// MCP import
|
| 950 |
+
const mcpImport = document.getElementById('mcp-import-input');
|
| 951 |
+
if (mcpImport) {
|
| 952 |
+
mcpImport.addEventListener('change', async (e) => {
|
| 953 |
+
const file = e.target.files?.[0];
|
| 954 |
+
if (!file) return;
|
| 955 |
+
try {
|
| 956 |
+
await importMcpConfigFromFile(file);
|
| 957 |
+
} catch (err) {
|
| 958 |
+
alert(`Failed to import mcp.json: ${err?.message || err}`);
|
| 959 |
+
} finally {
|
| 960 |
+
mcpImport.value = '';
|
| 961 |
+
}
|
| 962 |
+
});
|
| 963 |
+
}
|
| 964 |
+
|
| 965 |
// Apply defaults if fields are empty
|
| 966 |
if (config.default_base_url && !document.getElementById('chat-base-url').value) {
|
| 967 |
document.getElementById('chat-base-url').value = config.default_base_url;
|
|
|
|
| 1253 |
function openAutonomousMode() {
|
| 1254 |
switchMode('chat');
|
| 1255 |
setChatMode('autonomous');
|
| 1256 |
+
ensureAgentTerminalVisible();
|
| 1257 |
}
|
| 1258 |
|
| 1259 |
window.addEventListener('resize', () => {
|
|
|
|
| 1721 |
url,
|
| 1722 |
apiKey: '',
|
| 1723 |
token: '',
|
| 1724 |
+
headersJson: '{}',
|
| 1725 |
+
toolsJson: '[]'
|
| 1726 |
});
|
| 1727 |
saveMcpServers(servers);
|
| 1728 |
}
|
| 1729 |
|
| 1730 |
+
function addMcpServerByUrl() {
|
| 1731 |
+
const urlEl = document.getElementById('mcp-direct-url');
|
| 1732 |
+
const url = (urlEl?.value || '').trim();
|
| 1733 |
+
if (!url) return;
|
| 1734 |
+
const name = url.replace(/^https?:\/\//, '').replace(/\/+$/, '');
|
| 1735 |
+
const servers = loadMcpServers();
|
| 1736 |
+
servers.push({
|
| 1737 |
+
id: crypto.randomUUID ? crypto.randomUUID() : String(Date.now()),
|
| 1738 |
+
name,
|
| 1739 |
+
url,
|
| 1740 |
+
apiKey: '',
|
| 1741 |
+
token: '',
|
| 1742 |
+
headersJson: '{}',
|
| 1743 |
+
toolsJson: '[]'
|
| 1744 |
+
});
|
| 1745 |
+
saveMcpServers(servers);
|
| 1746 |
+
if (urlEl) urlEl.value = '';
|
| 1747 |
+
}
|
| 1748 |
+
|
| 1749 |
+
function exportMcpConfig() {
|
| 1750 |
+
const servers = loadMcpServers().map((s) => {
|
| 1751 |
+
let headers = {};
|
| 1752 |
+
let tools = [];
|
| 1753 |
+
try { headers = s.headersJson ? JSON.parse(s.headersJson) : {}; } catch { headers = {}; }
|
| 1754 |
+
try { tools = s.toolsJson ? JSON.parse(s.toolsJson) : []; } catch { tools = []; }
|
| 1755 |
+
return {
|
| 1756 |
+
id: s.id,
|
| 1757 |
+
name: s.name,
|
| 1758 |
+
url: s.url,
|
| 1759 |
+
auth: { apiKey: s.apiKey || '', token: s.token || '' },
|
| 1760 |
+
headers,
|
| 1761 |
+
tools
|
| 1762 |
+
};
|
| 1763 |
+
});
|
| 1764 |
+
const payload = { version: 1, servers };
|
| 1765 |
+
const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' });
|
| 1766 |
+
const a = document.createElement('a');
|
| 1767 |
+
a.href = URL.createObjectURL(blob);
|
| 1768 |
+
a.download = 'mcp.json';
|
| 1769 |
+
a.click();
|
| 1770 |
+
setTimeout(() => URL.revokeObjectURL(a.href), 500);
|
| 1771 |
+
}
|
| 1772 |
+
|
| 1773 |
+
async function importMcpConfigFromFile(file) {
|
| 1774 |
+
const text = await file.text();
|
| 1775 |
+
const parsed = JSON.parse(text);
|
| 1776 |
+
const servers = Array.isArray(parsed?.servers) ? parsed.servers : [];
|
| 1777 |
+
const normalized = servers.map((s) => ({
|
| 1778 |
+
id: s.id || (crypto.randomUUID ? crypto.randomUUID() : String(Date.now())),
|
| 1779 |
+
name: s.name || s.id || 'mcp-server',
|
| 1780 |
+
url: s.url || '',
|
| 1781 |
+
apiKey: s?.auth?.apiKey || '',
|
| 1782 |
+
token: s?.auth?.token || '',
|
| 1783 |
+
headersJson: JSON.stringify(s.headers || {}, null, 2),
|
| 1784 |
+
toolsJson: JSON.stringify(s.tools || [], null, 2)
|
| 1785 |
+
})).filter((s) => s.url);
|
| 1786 |
+
saveMcpServers(normalized);
|
| 1787 |
+
}
|
| 1788 |
+
|
| 1789 |
function deleteMcpServer(id) {
|
| 1790 |
if (!confirm('Delete this MCP server?')) return;
|
| 1791 |
const servers = loadMcpServers().filter(s => s.id !== id);
|
|
|
|
| 1797 |
saveMcpServers(servers);
|
| 1798 |
}
|
| 1799 |
|
| 1800 |
+
async function testMcpServer(id, statusElementId = null) {
|
| 1801 |
+
const statusEl = document.getElementById(statusElementId || `mcp-status-${id}`);
|
| 1802 |
const server = loadMcpServers().find(s => s.id === id);
|
| 1803 |
if (!server) return;
|
| 1804 |
statusEl.textContent = 'Testing...';
|
|
|
|
| 1826 |
}
|
| 1827 |
|
| 1828 |
function renderMcpServers() {
|
| 1829 |
+
renderMcpServersInto('mcp-server-list', { compact: false });
|
| 1830 |
+
renderMcpServersInto('settings-mcp-server-list', { compact: true });
|
| 1831 |
+
}
|
| 1832 |
+
|
| 1833 |
+
function renderMcpServersInto(containerId, { compact } = {}) {
|
| 1834 |
+
const list = document.getElementById(containerId);
|
| 1835 |
if (!list) return;
|
| 1836 |
const servers = loadMcpServers();
|
| 1837 |
list.innerHTML = '';
|
|
|
|
| 1842 |
|
| 1843 |
servers.forEach((s) => {
|
| 1844 |
const card = document.createElement('div');
|
| 1845 |
+
card.className = compact
|
| 1846 |
+
? 'bg-gray-900/40 border border-gray-700 rounded-lg p-3 space-y-2'
|
| 1847 |
+
: 'bg-gray-800 border border-gray-700 rounded-lg p-4 space-y-3';
|
| 1848 |
+
|
| 1849 |
+
const toolsPreview = (() => {
|
| 1850 |
+
try {
|
| 1851 |
+
const tools = s.toolsJson ? JSON.parse(s.toolsJson) : [];
|
| 1852 |
+
if (!Array.isArray(tools) || tools.length === 0) return '—';
|
| 1853 |
+
return tools.slice(0, 8).join(', ') + (tools.length > 8 ? '…' : '');
|
| 1854 |
+
} catch {
|
| 1855 |
+
return 'Invalid tools JSON';
|
| 1856 |
+
}
|
| 1857 |
+
})();
|
| 1858 |
+
|
| 1859 |
card.innerHTML = `
|
| 1860 |
<div class="flex items-start justify-between gap-3">
|
| 1861 |
<div class="min-w-0">
|
|
|
|
| 1863 |
<div class="text-xs text-gray-400 truncate">${sanitizeHtml(s.url)}</div>
|
| 1864 |
</div>
|
| 1865 |
<div class="flex gap-2 shrink-0">
|
| 1866 |
+
<button class="bg-gray-700 hover:bg-gray-600 text-white px-2 py-1 rounded text-xs" type="button" id="${containerId}-mcp-test-${s.id}">Test</button>
|
| 1867 |
+
<button class="bg-red-600 hover:bg-red-700 text-white px-2 py-1 rounded text-xs" type="button" id="${containerId}-mcp-del-${s.id}">Delete</button>
|
| 1868 |
</div>
|
| 1869 |
</div>
|
| 1870 |
+
<div class="text-xs text-gray-300">Tools: <span class="text-gray-100">${sanitizeHtml(toolsPreview)}</span></div>
|
| 1871 |
+
${compact ? '' : `
|
| 1872 |
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
| 1873 |
<div>
|
| 1874 |
<label class="block text-xs font-semibold text-gray-400 mb-1 uppercase">API Key</label>
|
| 1875 |
+
<input type="password" value="${sanitizeHtml(s.apiKey || '')}" class="w-full bg-gray-700 text-sm rounded border border-gray-600 p-2 text-white outline-none focus:border-blue-500" id="${containerId}-mcp-apikey-${s.id}">
|
| 1876 |
</div>
|
| 1877 |
<div>
|
| 1878 |
<label class="block text-xs font-semibold text-gray-400 mb-1 uppercase">Bearer Token</label>
|
| 1879 |
+
<input type="password" value="${sanitizeHtml(s.token || '')}" class="w-full bg-gray-700 text-sm rounded border border-gray-600 p-2 text-white outline-none focus:border-blue-500" id="${containerId}-mcp-token-${s.id}">
|
| 1880 |
</div>
|
| 1881 |
</div>
|
| 1882 |
<div>
|
| 1883 |
<label class="block text-xs font-semibold text-gray-400 mb-1 uppercase">Extra Headers (JSON)</label>
|
| 1884 |
+
<textarea rows="2" class="w-full bg-gray-700 text-sm rounded border border-gray-600 p-2 text-white outline-none focus:border-blue-500 font-mono" id="${containerId}-mcp-headers-${s.id}">${sanitizeHtml(s.headersJson || '{}')}</textarea>
|
| 1885 |
+
</div>
|
| 1886 |
+
<div>
|
| 1887 |
+
<label class="block text-xs font-semibold text-gray-400 mb-1 uppercase">Tools (JSON array)</label>
|
| 1888 |
+
<textarea rows="2" class="w-full bg-gray-700 text-sm rounded border border-gray-600 p-2 text-white outline-none focus:border-blue-500 font-mono" id="${containerId}-mcp-tools-${s.id}">${sanitizeHtml(s.toolsJson || '[]')}</textarea>
|
| 1889 |
</div>
|
| 1890 |
<div class="flex items-center justify-between">
|
| 1891 |
+
<div class="text-xs text-gray-300">Status: <span class="text-gray-100" id="${containerId}-mcp-status-${s.id}">—</span></div>
|
| 1892 |
+
<button class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-xs" type="button" id="${containerId}-mcp-save-${s.id}">Save</button>
|
| 1893 |
</div>
|
| 1894 |
+
`}
|
| 1895 |
`;
|
| 1896 |
list.appendChild(card);
|
| 1897 |
|
| 1898 |
+
document.getElementById(`${containerId}-mcp-del-${s.id}`).onclick = () => deleteMcpServer(s.id);
|
| 1899 |
+
document.getElementById(`${containerId}-mcp-test-${s.id}`).onclick = () => testMcpServer(s.id, `${containerId}-mcp-status-${s.id}`);
|
| 1900 |
+
if (!compact) {
|
| 1901 |
+
document.getElementById(`${containerId}-mcp-save-${s.id}`).onclick = () => {
|
| 1902 |
+
updateMcpServer(s.id, {
|
| 1903 |
+
apiKey: document.getElementById(`${containerId}-mcp-apikey-${s.id}`).value || '',
|
| 1904 |
+
token: document.getElementById(`${containerId}-mcp-token-${s.id}`).value || '',
|
| 1905 |
+
headersJson: document.getElementById(`${containerId}-mcp-headers-${s.id}`).value || '{}',
|
| 1906 |
+
toolsJson: document.getElementById(`${containerId}-mcp-tools-${s.id}`).value || '[]'
|
| 1907 |
+
});
|
| 1908 |
+
};
|
| 1909 |
+
}
|
| 1910 |
});
|
| 1911 |
}
|
| 1912 |
|