beast-agent 2.42.0 → 2.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "beast-agent",
3
3
  "productName": "Beast Agent",
4
- "version": "2.42.0",
4
+ "version": "2.43.0",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
@@ -594,6 +594,7 @@
594
594
  tipIde: 'IDE Modu — dosyalar + chat + preview',
595
595
  tipStudio: 'Beast Studio — video yapma/düzenleme modu',
596
596
  tipSandbox: 'Beast Sandbox — GitHub reposu indir & içinde çalış',
597
+ tipMcp: 'Beast MCP — dış araç sunucuları (Model Context Protocol)',
597
598
  tipCodeHide: 'Editörü kapat',
598
599
  tipCodeShow: 'Editörü göster',
599
600
  ide_files: 'DOSYALAR',
@@ -1387,6 +1388,7 @@
1387
1388
  tipIde: 'IDE Mode — files + chat + preview',
1388
1389
  tipStudio: 'Beast Studio — video making/editing mode',
1389
1390
  tipSandbox: 'Beast Sandbox — download a GitHub repo & work inside it',
1391
+ tipMcp: 'Beast MCP — external tool servers (Model Context Protocol)',
1390
1392
  tipCodeHide: 'Hide editor',
1391
1393
  tipCodeShow: 'Show editor',
1392
1394
  ide_files: 'FILES',
@@ -103,6 +103,7 @@
103
103
  <button id="studioBtn" class="dd-btn dd-icon-btn" title="Beast Studio — video yapma/düzenleme" data-i18n-title="tipStudio"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="13" height="12" rx="2"/><path d="M15 10l7-4v12l-7-4"/></svg></button>
104
104
  <button id="finBtn" class="dd-btn dd-icon-btn" title="Beast Finance — MT5 trade paneli (bilgisayardaki MetaTrader 5 ile çalışır)"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="M7 15l4-5 3 3 5-7"/></svg></button>
105
105
  <button id="sbBtn" class="dd-btn dd-icon-btn" title="Beast Sandbox — GitHub reposu indir &amp; içinde çalış" data-i18n-title="tipSandbox"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg></button>
106
+ <button id="mcpBtn" class="dd-btn dd-icon-btn" title="Beast MCP — dış araç sunucuları (Model Context Protocol)" data-i18n-title="tipMcp"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><line x1="7" y1="7.5" x2="7.01" y2="7.5"/><line x1="7" y1="16.5" x2="7.01" y2="16.5"/></svg></button>
106
107
  <button id="railBtn" class="dd-btn dd-icon-btn" title="Paralel Ajan Konsolu" data-i18n-title="tipRail">&#x25A4;</button>
107
108
  <button id="dmBtn" class="dd-btn dd-icon-btn" title="Ajan DM — ajanlar arası konuşma" data-i18n-title="tipAgentDm">&#x2709;&#xFE0E;</button>
108
109
  <button id="watchBtn" class="dd-btn dd-icon-btn" title="İzleyiciler (Watchers)" data-i18n-title="tipWatch">&#x25CE;</button>
@@ -452,6 +453,37 @@
452
453
  </div>
453
454
  </section>
454
455
  </div>
456
+
457
+ <div id="mcpRow">
458
+ <section id="mcpPanel">
459
+ <div id="mcpHead">
460
+ <span id="mcpTitle">BEAST MCP</span>
461
+ <span class="file-spacer"></span>
462
+ <button id="mcpReload" title="Durumu yenile">&#x27F3;&#xFE0E;</button>
463
+ </div>
464
+ <div id="mcpList"></div>
465
+ <div id="mcpFoot">
466
+ <button id="mcpAddBtn" title="mcp.json'a örnek bir server bloğu ekler">+ Yeni Server</button>
467
+ </div>
468
+ </section>
469
+ <section id="mcpDetail">
470
+ <div id="mcpDetailHead">
471
+ <span id="mcpDetailTitle">Detay</span>
472
+ <span id="mcpDetailState" class="mcp-badge"></span>
473
+ </div>
474
+ <div id="mcpDetailBody"></div>
475
+ <div id="mcpJsonWrap">
476
+ <div id="mcpJsonHead">
477
+ <span>mcp.json</span>
478
+ <span id="mcpJsonPath" title=""></span>
479
+ <span class="file-spacer"></span>
480
+ <span id="mcpMsg"></span>
481
+ <button id="mcpSave">Kaydet</button>
482
+ </div>
483
+ <textarea id="mcpJson" spellcheck="false"></textarea>
484
+ </div>
485
+ </section>
486
+ </div>
455
487
  </main>
456
488
 
457
489
  <aside id="rail">
@@ -150,6 +150,18 @@ const els = {
150
150
  sbRunOut: $('#sbRunOut'),
151
151
  sbRunOpen: $('#sbRunOpen'),
152
152
  sbRunUrl: $('#sbRunUrl'),
153
+ mcpBtn: $('#mcpBtn'),
154
+ mcpRow: $('#mcpRow'),
155
+ mcpList: $('#mcpList'),
156
+ mcpReload: $('#mcpReload'),
157
+ mcpAddBtn: $('#mcpAddBtn'),
158
+ mcpDetailTitle: $('#mcpDetailTitle'),
159
+ mcpDetailState: $('#mcpDetailState'),
160
+ mcpDetailBody: $('#mcpDetailBody'),
161
+ mcpJson: $('#mcpJson'),
162
+ mcpJsonPath: $('#mcpJsonPath'),
163
+ mcpSave: $('#mcpSave'),
164
+ mcpMsg: $('#mcpMsg'),
153
165
  stPanel: $('#stPanel'),
154
166
  stTitle: $('#stTitle'),
155
167
  stCwd: $('#stCwd'),
@@ -8358,6 +8370,7 @@ async function setIdeMode(on) {
8358
8370
  if (on && studioModeOn()) await setStudioMode(false); /* Studio açıkken IDE'ye geçiş — Studio kapanır */
8359
8371
  if (on && sbModeOn()) setSandboxMode(false); /* Sandbox açıkken IDE'ye geçiş — Sandbox kapanır */
8360
8372
  if (on && financeModeOn()) setFinanceMode(false); /* Finance açıkken IDE'ye geçiş — Finance kapanır */
8373
+ if (on && mcpModeOn()) setMcpMode(false); /* MCP açıkken IDE'ye geçiş — MCP kapanır */
8361
8374
  document.body.classList.toggle('ide-mode', !!on);
8362
8375
  if (els.ideBtn) els.ideBtn.classList.toggle('on', !!on);
8363
8376
  /* soldaki marka: chat modunda BEAST Agent, IDE modunda BEAST Code, Studio modunda BEAST Studio */
@@ -8433,6 +8446,7 @@ async function setStudioMode(on) {
8433
8446
  if (on && ideModeOn()) await setIdeMode(false); /* IDE açıkken Studio'ya geçiş — IDE kapanır */
8434
8447
  if (on && sbModeOn()) setSandboxMode(false); /* Sandbox açıkken Studio'ya geçiş — Sandbox kapanır */
8435
8448
  if (on && financeModeOn()) setFinanceMode(false); /* Finance açıkken Studio'ya geçiş — Finance kapanır */
8449
+ if (on && mcpModeOn()) setMcpMode(false); /* MCP açıkken Studio'ya geçiş — MCP kapanır */
8436
8450
  document.body.classList.toggle('studio-mode', !!on);
8437
8451
  if (els.studioBtn) els.studioBtn.classList.toggle('on', !!on);
8438
8452
  /* ALT TERMINAL: yalnız Beast Code'a özgü — Studio'ya geçişte kapanır */
@@ -9729,6 +9743,7 @@ async function setFinanceMode(on) {
9729
9743
  if (on && ideModeOn()) await setIdeMode(false);
9730
9744
  if (on && studioModeOn()) await setStudioMode(false);
9731
9745
  if (on && sbModeOn()) setSandboxMode(false);
9746
+ if (on && mcpModeOn()) setMcpMode(false); /* MCP açıkken Finance'a geçiş — MCP kapanır */
9732
9747
  document.body.classList.toggle('finance-mode', !!on);
9733
9748
  if (els.finBtn) els.finBtn.classList.toggle('on', !!on);
9734
9749
  const brandSub = document.querySelector('#brand .brand-sub');
@@ -12262,6 +12277,7 @@ function setSandboxMode(on) {
12262
12277
  if (on && ideModeOn()) { setIdeMode(false); }
12263
12278
  if (on && studioModeOn()) { setStudioMode(false); }
12264
12279
  if (on && financeModeOn()) { setFinanceMode(false); }
12280
+ if (on && mcpModeOn()) setMcpMode(false); /* MCP açıkken Sandbox'a geçiş — MCP kapanır */
12265
12281
  document.body.classList.toggle('sandbox-mode', !!on);
12266
12282
  if (els.sbBtn) els.sbBtn.classList.toggle('on', !!on);
12267
12283
  sbPreviewApply();
@@ -12282,6 +12298,160 @@ function setSandboxMode(on) {
12282
12298
  }
12283
12299
  }
12284
12300
 
12301
+ /* ================= BEAST MCP MODU =================
12302
+ Model Context Protocol sunucuları: tek panelde durum, araç listesi,
12303
+ aç/kapat, yeniden bağlan ve mcp.json düzenleme. Ana sohbeti bozmaz —
12304
+ diğer modlar gibi body.mcp-mode ile ayrı satır. */
12305
+ function mcpModeOn() {
12306
+ return document.body.classList.contains('mcp-mode');
12307
+ }
12308
+
12309
+ const MCP_STATE_TR = { up: 'BAĞLI', starting: 'BAĞLANIYOR', down: 'HATA', idle: 'BEKLEMEDE', disabled: 'KAPALI' };
12310
+ let mcpSel = '';
12311
+ let mcpTimer = null;
12312
+
12313
+ async function setMcpMode(on) {
12314
+ if (on && ideModeOn()) await setIdeMode(false);
12315
+ if (on && studioModeOn()) await setStudioMode(false);
12316
+ if (on && sbModeOn()) setSandboxMode(false);
12317
+ if (on && financeModeOn()) setFinanceMode(false);
12318
+ document.body.classList.toggle('mcp-mode', !!on);
12319
+ if (els.mcpBtn) els.mcpBtn.classList.toggle('on', !!on);
12320
+ const brandSub = document.querySelector('#brand .brand-sub');
12321
+ if (brandSub) brandSub.textContent = on ? 'MCP' : 'Agent';
12322
+ if (on) {
12323
+ await renderMcpPanel();
12324
+ if (!mcpTimer) {
12325
+ mcpTimer = setInterval(() => { if (mcpModeOn()) renderMcpPanel(); }, 5000);
12326
+ }
12327
+ } else if (mcpTimer) {
12328
+ clearInterval(mcpTimer);
12329
+ mcpTimer = null;
12330
+ }
12331
+ }
12332
+
12333
+ async function renderMcpPanel() {
12334
+ if (!els.mcpList || !mcpModeOn()) return;
12335
+ const st = await beast.mcpStatus().catch(() => ({ path: '', servers: [] }));
12336
+ const cfg = await beast.mcpConfigGet().catch(() => ({ path: '', raw: '' }));
12337
+ const servers = st.servers || [];
12338
+ if (!servers.length) {
12339
+ els.mcpList.innerHTML = '<div class="file-empty">Henüz MCP server yok — aşağıdaki mcp.json\'a ekle ya da “Yeni Server”e bas.</div>';
12340
+ } else {
12341
+ if (!servers.some((s) => s.name === mcpSel)) mcpSel = servers[0].name;
12342
+ els.mcpList.innerHTML = servers.map((s) => {
12343
+ const badge = MCP_STATE_TR[s.state] || s.state;
12344
+ return '<div class="mcp-card' + (s.name === mcpSel ? ' sel' : '') + '" data-n="' + escapeHtml(s.name) + '">' +
12345
+ '<div class="mc-top"><span class="mc-name">' + escapeHtml(s.name) + '</span>' +
12346
+ '<span class="mcp-badge ' + escapeHtml(s.state) + '">' + escapeHtml(badge) + '</span>' +
12347
+ '<span class="file-spacer"></span>' +
12348
+ (s.enabled && s.toolCount ? '<span class="mcp-badge">' + s.toolCount + ' araç</span>' : '') + '</div>' +
12349
+ '<div class="mc-cmd">' + escapeHtml((s.command || '') + ' ' + (s.args || []).join(' ')) + '</div>' +
12350
+ (s.lastError && s.state === 'down' ? '<div class="mc-err">' + escapeHtml(String(s.lastError).slice(0, 140)) + '</div>' : '') +
12351
+ '<div class="mc-actions">' +
12352
+ '<button class="mcp-tgl" data-n="' + escapeHtml(s.name) + '">' + (s.enabled ? '⏸ Durdur' : '▶ Başlat') + '</button>' +
12353
+ '<button class="mcp-ref" data-n="' + escapeHtml(s.name) + '">⟳ Yenile</button>' +
12354
+ '</div></div>';
12355
+ }).join('');
12356
+ }
12357
+ renderMcpDetail(servers.find((s) => s.name === mcpSel) || null);
12358
+ if (els.mcpJson && document.activeElement !== els.mcpJson) {
12359
+ els.mcpJson.value = cfg.raw || JSON.stringify({ servers: {} }, null, 2);
12360
+ }
12361
+ if (els.mcpJsonPath) {
12362
+ els.mcpJsonPath.textContent = cfg.path || '';
12363
+ els.mcpJsonPath.title = cfg.path || '';
12364
+ }
12365
+
12366
+ els.mcpList.querySelectorAll('.mcp-card').forEach((c) => c.addEventListener('click', (ev) => {
12367
+ if (ev.target.closest('button')) return;
12368
+ mcpSel = c.dataset.n;
12369
+ renderMcpPanel();
12370
+ }));
12371
+ els.mcpList.querySelectorAll('.mcp-ref').forEach((b) => b.addEventListener('click', async () => {
12372
+ b.disabled = true;
12373
+ mcpSel = b.dataset.n;
12374
+ await beast.mcpRefresh(b.dataset.n).catch(() => {});
12375
+ renderMcpPanel();
12376
+ }));
12377
+ els.mcpList.querySelectorAll('.mcp-tgl').forEach((b) => b.addEventListener('click', async () => {
12378
+ b.disabled = true;
12379
+ try {
12380
+ const obj = JSON.parse(els.mcpJson.value || '{}');
12381
+ const name = b.dataset.n;
12382
+ if (obj.servers && obj.servers[name]) {
12383
+ obj.servers[name].enabled = obj.servers[name].enabled === false;
12384
+ await beast.mcpConfigSet(JSON.stringify(obj)).catch(() => {});
12385
+ mcpSel = name;
12386
+ }
12387
+ } catch (e) {
12388
+ toast('JSON hatası: ' + String((e && e.message) || e));
12389
+ }
12390
+ renderMcpPanel();
12391
+ }));
12392
+ }
12393
+
12394
+ function renderMcpDetail(s) {
12395
+ if (els.mcpDetailTitle) els.mcpDetailTitle.textContent = s ? s.name : 'Detay';
12396
+ if (els.mcpDetailState) {
12397
+ els.mcpDetailState.className = 'mcp-badge' + (s ? ' ' + s.state : '');
12398
+ els.mcpDetailState.textContent = s ? (MCP_STATE_TR[s.state] || s.state) : '';
12399
+ }
12400
+ if (!els.mcpDetailBody) return;
12401
+ if (!s) {
12402
+ els.mcpDetailBody.innerHTML = '<div class="file-empty">Soldan bir server seç.</div>';
12403
+ return;
12404
+ }
12405
+ const rows = [
12406
+ ['Komut', (s.command || '') + ' ' + (s.args || []).join(' ')],
12407
+ ['Durum', (MCP_STATE_TR[s.state] || s.state) + (s.enabled ? '' : ' (kapalı)')],
12408
+ ['Araç', s.enabled ? String(s.toolCount || 0) + ' araç' : '—'],
12409
+ s.timeoutMs ? ['Zaman aşımı', s.timeoutMs + ' ms'] : null,
12410
+ s.tools && s.tools.length ? ['İzinli liste', s.tools.join(', ')] : null,
12411
+ ].filter(Boolean);
12412
+ let html = rows.map(([k, v]) =>
12413
+ '<div class="mcp-drow"><span class="mcp-dk">' + escapeHtml(k) + '</span><span>' + escapeHtml(String(v)) + '</span></div>'
12414
+ ).join('');
12415
+ if (s.lastError && s.state === 'down') {
12416
+ html += '<div class="mcp-drow"><span class="mcp-dk">Hata</span><span style="color:var(--err)">' + escapeHtml(s.lastError) + '</span></div>';
12417
+ }
12418
+ if (s.toolNames && s.toolNames.length) {
12419
+ html += '<div class="mcp-dk" style="margin-top:10px">Araçlar</div><div class="mcp-tools">' +
12420
+ s.toolNames.map((t) => '<span class="mcp-tool">' + escapeHtml(t) + '</span>').join('') + '</div>';
12421
+ } else if (s.enabled) {
12422
+ html += '<div class="file-empty">Araç listesi için ⟳ Yenile (server ilk kullanımda bağlanır).</div>';
12423
+ }
12424
+ els.mcpDetailBody.innerHTML = html;
12425
+ }
12426
+
12427
+ if (els.mcpBtn) els.mcpBtn.addEventListener('click', () => setMcpMode(!mcpModeOn()));
12428
+ if (els.mcpReload) els.mcpReload.addEventListener('click', () => renderMcpPanel());
12429
+ if (els.mcpSave) els.mcpSave.addEventListener('click', async () => {
12430
+ const r = await beast.mcpConfigSet(els.mcpJson.value || '').catch(() => ({ ok: false, error: 'IPC' }));
12431
+ if (els.mcpMsg) {
12432
+ els.mcpMsg.textContent = r && r.ok ? 'Kaydedildi' : ('Hata: ' + ((r && r.error) || '?'));
12433
+ els.mcpMsg.style.color = r && r.ok ? '' : 'var(--err)';
12434
+ }
12435
+ if (r && r.ok) renderMcpPanel();
12436
+ });
12437
+ if (els.mcpAddBtn) els.mcpAddBtn.addEventListener('click', () => {
12438
+ if (!els.mcpJson) return;
12439
+ try {
12440
+ const obj = JSON.parse(els.mcpJson.value || '{}') || {};
12441
+ obj.servers = obj.servers || {};
12442
+ let i = 1;
12443
+ let name = 'yeni-server';
12444
+ while (obj.servers[name]) name = 'yeni-server' + (++i);
12445
+ obj.servers[name] = { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', 'C:/'], enabled: false };
12446
+ els.mcpJson.value = JSON.stringify(obj, null, 2);
12447
+ els.mcpJson.focus();
12448
+ if (els.mcpMsg) {
12449
+ els.mcpMsg.textContent = 'örnek eklendi — komutu düzenleyip Kaydet';
12450
+ els.mcpMsg.style.color = '';
12451
+ }
12452
+ } catch {}
12453
+ });
12454
+
12285
12455
  /* ---------- ÇALIŞTIRICI v2: butonlar DETERMİNİSTİK ----------
12286
12456
  Proje tipi algılanır (package.json/requirements.txt/pyproject/Cargo.toml/
12287
12457
  go.mod/hugo/jekyll/mkdocs/index.html); Başlat/Dev gerekirse bağımlılıkları
@@ -4489,6 +4489,206 @@ body.sandbox-mode #sandboxRow { display: flex; flex-direction: row; }
4489
4489
  padding: 0 16px;
4490
4490
  text-align: center;
4491
4491
  }
4492
+
4493
+ /* ---------- MCP MODU ---------- */
4494
+ body.mcp-mode #chatScroll,
4495
+ body.mcp-mode #composerWrap,
4496
+ body.mcp-mode #ideRow,
4497
+ body.mcp-mode #studioRow,
4498
+ body.mcp-mode #sandboxRow { display: none; }
4499
+
4500
+ #mcpRow { display: none; flex: 1; min-height: 0; }
4501
+ body.mcp-mode #mcpRow { display: flex; flex-direction: row; }
4502
+
4503
+ #mcpPanel {
4504
+ display: flex;
4505
+ flex-direction: column;
4506
+ min-height: 0;
4507
+ min-width: 280px;
4508
+ flex: 0 0 380px;
4509
+ background: var(--bg);
4510
+ overflow: hidden;
4511
+ }
4512
+ #mcpDetail {
4513
+ display: flex;
4514
+ flex-direction: column;
4515
+ flex: 1;
4516
+ min-width: 0;
4517
+ min-height: 0;
4518
+ background: var(--bg);
4519
+ border-left: 1px solid var(--border);
4520
+ }
4521
+ #mcpHead {
4522
+ flex: none;
4523
+ display: flex;
4524
+ align-items: center;
4525
+ gap: 8px;
4526
+ padding: 9px 12px;
4527
+ border-bottom: 1px solid var(--border);
4528
+ background: var(--panel);
4529
+ }
4530
+ #mcpTitle { font-size: 11px; font-weight: 800; letter-spacing: 1px; color: var(--accent); flex: none; }
4531
+ #mcpHead button {
4532
+ background: none;
4533
+ border: none;
4534
+ color: var(--muted);
4535
+ font-size: 14px;
4536
+ cursor: pointer;
4537
+ padding: 2px 7px;
4538
+ border-radius: 6px;
4539
+ }
4540
+ #mcpHead button:hover { background: var(--panel2); color: var(--text); }
4541
+ #mcpList {
4542
+ flex: 1;
4543
+ min-height: 0;
4544
+ overflow-y: auto;
4545
+ padding: 10px 12px;
4546
+ }
4547
+ #mcpFoot {
4548
+ flex: none;
4549
+ padding: 8px 12px;
4550
+ border-top: 1px solid var(--border);
4551
+ background: var(--panel);
4552
+ }
4553
+ #mcpFoot button {
4554
+ width: 100%;
4555
+ background: var(--panel2);
4556
+ border: 1px solid var(--border);
4557
+ color: var(--text);
4558
+ font-size: 12px;
4559
+ padding: 6px 10px;
4560
+ border-radius: 7px;
4561
+ cursor: pointer;
4562
+ }
4563
+ #mcpFoot button:hover { border-color: var(--accent); }
4564
+
4565
+ .mcp-card {
4566
+ border: 1px solid var(--border);
4567
+ border-radius: 9px;
4568
+ padding: 9px 10px;
4569
+ margin-bottom: 8px;
4570
+ background: var(--panel);
4571
+ cursor: pointer;
4572
+ }
4573
+ .mcp-card:hover { border-color: var(--accent); }
4574
+ .mcp-card.sel { border-color: var(--accent); background: var(--panel2); }
4575
+ .mcp-card .mc-top { display: flex; align-items: center; gap: 7px; }
4576
+ .mcp-card .mc-name { font-weight: 700; font-size: 13px; }
4577
+ .mcp-card .mc-cmd {
4578
+ font-family: Consolas, monospace;
4579
+ font-size: 11px;
4580
+ color: var(--muted);
4581
+ margin-top: 4px;
4582
+ overflow: hidden;
4583
+ text-overflow: ellipsis;
4584
+ white-space: nowrap;
4585
+ }
4586
+ .mcp-card .mc-err {
4587
+ color: var(--err);
4588
+ font-size: 11px;
4589
+ margin-top: 4px;
4590
+ overflow: hidden;
4591
+ text-overflow: ellipsis;
4592
+ white-space: nowrap;
4593
+ }
4594
+ .mcp-card .mc-actions { display: flex; gap: 6px; margin-top: 7px; }
4595
+ .mcp-card .mc-actions button {
4596
+ background: var(--panel2);
4597
+ border: 1px solid var(--border);
4598
+ color: var(--text);
4599
+ font-size: 11px;
4600
+ padding: 3px 9px;
4601
+ border-radius: 6px;
4602
+ cursor: pointer;
4603
+ }
4604
+ .mcp-card .mc-actions button:hover { border-color: var(--accent); }
4605
+
4606
+ .mcp-badge {
4607
+ flex: none;
4608
+ font-size: 9.5px;
4609
+ font-weight: 800;
4610
+ letter-spacing: 0.5px;
4611
+ padding: 1px 6px;
4612
+ border-radius: 4px;
4613
+ border: 1px solid var(--border);
4614
+ color: var(--muted);
4615
+ text-transform: uppercase;
4616
+ }
4617
+ .mcp-badge.up { color: #22c55e; border-color: #22c55e; }
4618
+ .mcp-badge.down { color: var(--err); border-color: var(--err); }
4619
+ .mcp-badge.starting { color: var(--accent); border-color: var(--accent); }
4620
+
4621
+ #mcpDetailHead {
4622
+ flex: none;
4623
+ display: flex;
4624
+ align-items: center;
4625
+ gap: 10px;
4626
+ padding: 9px 14px;
4627
+ border-bottom: 1px solid var(--border);
4628
+ background: var(--panel);
4629
+ }
4630
+ #mcpDetailTitle { font-weight: 700; font-size: 13px; }
4631
+ #mcpDetailState { margin-left: auto; }
4632
+ #mcpDetailBody { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 14px; }
4633
+ .mcp-drow { display: flex; gap: 8px; margin-bottom: 6px; font-size: 12.5px; }
4634
+ .mcp-dk { color: var(--muted); min-width: 76px; flex: none; }
4635
+ .mcp-tools { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
4636
+ .mcp-tool {
4637
+ font-family: Consolas, monospace;
4638
+ font-size: 11px;
4639
+ border: 1px solid var(--border);
4640
+ background: var(--panel2);
4641
+ padding: 2px 7px;
4642
+ border-radius: 6px;
4643
+ }
4644
+ #mcpJsonWrap {
4645
+ flex: none;
4646
+ display: flex;
4647
+ flex-direction: column;
4648
+ max-height: 40%;
4649
+ border-top: 1px solid var(--border);
4650
+ background: var(--panel);
4651
+ }
4652
+ #mcpJsonHead {
4653
+ flex: none;
4654
+ display: flex;
4655
+ align-items: center;
4656
+ gap: 8px;
4657
+ padding: 7px 12px;
4658
+ font-size: 11px;
4659
+ color: var(--muted);
4660
+ }
4661
+ #mcpJsonPath {
4662
+ max-width: 45%;
4663
+ overflow: hidden;
4664
+ text-overflow: ellipsis;
4665
+ white-space: nowrap;
4666
+ font-family: Consolas, monospace;
4667
+ }
4668
+ #mcpSave {
4669
+ background: var(--panel2);
4670
+ border: 1px solid var(--border);
4671
+ color: var(--accent);
4672
+ font-size: 11px;
4673
+ padding: 3px 10px;
4674
+ border-radius: 6px;
4675
+ cursor: pointer;
4676
+ }
4677
+ #mcpSave:hover { border-color: var(--accent); }
4678
+ #mcpJson {
4679
+ flex: 1;
4680
+ min-height: 110px;
4681
+ resize: none;
4682
+ background: var(--bg);
4683
+ border: none;
4684
+ border-top: 1px solid var(--border);
4685
+ color: var(--text);
4686
+ font-family: Consolas, monospace;
4687
+ font-size: 12px;
4688
+ padding: 8px 12px;
4689
+ outline: none;
4690
+ white-space: pre;
4691
+ }
4492
4692
  #sbRunBtns {
4493
4693
  flex: none;
4494
4694
  display: flex;