fa-mcp-sdk 0.4.121 → 0.4.124

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.
Files changed (43) hide show
  1. package/cli-template/.env.example +5 -1
  2. package/cli-template/FA-MCP-SDK-DOC/00-FA-MCP-SDK-index.md +4 -1
  3. package/cli-template/FA-MCP-SDK-DOC/03-configuration.md +1 -1
  4. package/cli-template/FA-MCP-SDK-DOC/06-utilities.md +71 -4
  5. package/cli-template/package.json +1 -1
  6. package/config/_local.yaml +1 -1
  7. package/config/custom-environment-variables.yaml +1 -1
  8. package/config/default.yaml +1 -1
  9. package/config/local.yaml +1 -1
  10. package/config/test.yaml +1 -1
  11. package/dist/core/_types_/config.d.ts +1 -1
  12. package/dist/core/_types_/config.d.ts.map +1 -1
  13. package/dist/core/debug.d.ts +32 -0
  14. package/dist/core/debug.d.ts.map +1 -1
  15. package/dist/core/debug.js +42 -1
  16. package/dist/core/debug.js.map +1 -1
  17. package/dist/core/index.d.ts +2 -1
  18. package/dist/core/index.d.ts.map +1 -1
  19. package/dist/core/index.js +2 -1
  20. package/dist/core/index.js.map +1 -1
  21. package/dist/core/init-mcp-server.d.ts.map +1 -1
  22. package/dist/core/init-mcp-server.js +46 -1
  23. package/dist/core/init-mcp-server.js.map +1 -1
  24. package/dist/core/logger.d.ts.map +1 -1
  25. package/dist/core/logger.js +2 -2
  26. package/dist/core/logger.js.map +1 -1
  27. package/dist/core/mcp/mcp-apps.d.ts.map +1 -1
  28. package/dist/core/mcp/mcp-apps.js +2 -4
  29. package/dist/core/mcp/mcp-apps.js.map +1 -1
  30. package/dist/core/mcp/prompts.d.ts.map +1 -1
  31. package/dist/core/mcp/prompts.js +17 -2
  32. package/dist/core/mcp/prompts.js.map +1 -1
  33. package/dist/core/mcp/resources.d.ts.map +1 -1
  34. package/dist/core/mcp/resources.js +18 -2
  35. package/dist/core/mcp/resources.js.map +1 -1
  36. package/dist/core/web/server-http.d.ts.map +1 -1
  37. package/dist/core/web/server-http.js +4 -0
  38. package/dist/core/web/server-http.js.map +1 -1
  39. package/dist/core/web/static/agent-tester/index.html +116 -120
  40. package/dist/core/web/static/agent-tester/script.js +77 -53
  41. package/dist/core/web/static/agent-tester/styles.css +203 -78
  42. package/package.json +1 -1
  43. package/src/template/tools/handle-tool-call.ts +25 -2
@@ -393,13 +393,10 @@ class McpAgentTester {
393
393
  }
394
394
 
395
395
  initializeElements() {
396
- this.sidebar = document.getElementById('sidebar');
397
- this.sidebarToggle = document.getElementById('sidebarToggle');
398
- this.sidebarToggleMobile = document.getElementById('sidebarToggleMobile');
399
-
400
396
  this.mcpConnectionForm = document.getElementById('mcpConnectionForm');
401
397
  this.serverUrlInput = document.getElementById('serverUrl');
402
398
  this.transportSelect = document.getElementById('transport');
399
+ this.connectionToggleBtn = document.getElementById('connectionToggleBtn');
403
400
 
404
401
  this.serverUrlDropdown = document.getElementById('serverUrlDropdown');
405
402
  this.serverUrlDropdownList = document.getElementById('serverUrlDropdownList');
@@ -410,6 +407,11 @@ class McpAgentTester {
410
407
  this.headersSection = document.getElementById('headersSection');
411
408
  this.dynamicHeaders = document.getElementById('dynamicHeaders');
412
409
 
410
+ // Settings modal (former sidebar)
411
+ this.settingsModal = document.getElementById('settingsModal');
412
+ this.settingsBtn = document.getElementById('settingsBtn');
413
+ this.settingsModalClose = document.getElementById('settingsModalClose');
414
+
413
415
  // LLM settings — collapsed view + modal
414
416
  this.modelDisplay = document.getElementById('modelDisplay');
415
417
  this.llmSettingsBtn = document.getElementById('llmSettingsBtn');
@@ -438,8 +440,6 @@ class McpAgentTester {
438
440
  this.promptModifiedBadge = document.getElementById('promptModifiedBadge');
439
441
  this.originalAgentPrompt = null;
440
442
 
441
- this.connectedServersContainer = document.getElementById('connectedServers');
442
-
443
443
  this.chatMessages = document.getElementById('chatMessages');
444
444
  this.messageInput = document.getElementById('messageInput');
445
445
  this.sendButton = document.getElementById('sendButton');
@@ -479,13 +479,6 @@ class McpAgentTester {
479
479
  }
480
480
 
481
481
  bindEvents() {
482
- if (this.sidebarToggle) {
483
- this.sidebarToggle.addEventListener('click', () => this.toggleSidebar());
484
- }
485
- if (this.sidebarToggleMobile) {
486
- this.sidebarToggleMobile.addEventListener('click', () => this.toggleSidebar());
487
- }
488
-
489
482
  if (this.themeToggle) {
490
483
  this.themeToggle.addEventListener('click', () => this.toggleTheme());
491
484
  }
@@ -551,20 +544,23 @@ class McpAgentTester {
551
544
  sdkVersionBtn.addEventListener('click', (e) => this.toggleSdkVersionTooltip(e));
552
545
  }
553
546
 
554
- document.addEventListener('click', (e) => {
555
- if (
556
- window.innerWidth <= 768 &&
557
- !this.sidebar.contains(e.target) &&
558
- !this.sidebarToggleMobile.contains(e.target) &&
559
- this.sidebar.classList.contains('open')
560
- ) {
561
- this.toggleSidebar();
562
- }
563
- });
564
-
565
- window.addEventListener('resize', () => {
566
- if (window.innerWidth > 768) {
567
- this.sidebar.classList.remove('open');
547
+ // --- Settings modal (former sidebar) ---
548
+ if (this.settingsBtn) {
549
+ this.settingsBtn.addEventListener('click', () => this.openSettingsModal());
550
+ }
551
+ if (this.settingsModalClose) {
552
+ this.settingsModalClose.addEventListener('click', () => this.closeSettingsModal());
553
+ }
554
+ if (this.settingsModal) {
555
+ this.settingsModal.addEventListener('click', (e) => {
556
+ if (e.target === this.settingsModal) {
557
+ this.closeSettingsModal();
558
+ }
559
+ });
560
+ }
561
+ document.addEventListener('keydown', (e) => {
562
+ if (e.key === 'Escape' && this.settingsModal && this.settingsModal.style.display === 'flex') {
563
+ this.closeSettingsModal();
568
564
  }
569
565
  });
570
566
 
@@ -668,8 +664,18 @@ class McpAgentTester {
668
664
  });
669
665
  }
670
666
 
671
- toggleSidebar() {
672
- this.sidebar.classList.toggle('open');
667
+ openSettingsModal() {
668
+ if (!this.settingsModal) {
669
+ return;
670
+ }
671
+ this.settingsModal.style.display = 'flex';
672
+ }
673
+
674
+ closeSettingsModal() {
675
+ if (!this.settingsModal) {
676
+ return;
677
+ }
678
+ this.settingsModal.style.display = 'none';
673
679
  }
674
680
 
675
681
  async loadInitialData() {
@@ -788,6 +794,12 @@ class McpAgentTester {
788
794
  async handleMcpConnection(event) {
789
795
  event.preventDefault();
790
796
 
797
+ // Combined Connect/Disconnect button: disconnect when already connected
798
+ if (this.currentServer && this.currentServer.isConnected) {
799
+ await this.disconnectServer();
800
+ return;
801
+ }
802
+
791
803
  const serverUrl = this.serverUrlInput.value.trim();
792
804
  const transport = this.transportSelect.value;
793
805
 
@@ -1348,35 +1360,42 @@ class McpAgentTester {
1348
1360
 
1349
1361
  renderServerInfo() {
1350
1362
  this.refreshToolList();
1351
- if (!this.currentServer) {
1352
- this.connectedServersContainer.innerHTML = '';
1363
+ this.updateConnectionToggleBtn();
1364
+ }
1365
+
1366
+ updateConnectionToggleBtn() {
1367
+ const btn = this.connectionToggleBtn;
1368
+ if (!btn) {
1353
1369
  return;
1354
1370
  }
1371
+ const iconEl = btn.querySelector('.connect-icon');
1372
+ const countEl = btn.querySelector('.tools-count');
1373
+ const connected = !!(this.currentServer && this.currentServer.isConnected);
1355
1374
 
1356
- const server = this.currentServer;
1357
- const toolCount = server.tools ? server.tools.length : 0;
1358
-
1359
- if (server.isConnected) {
1360
- this.connectedServersContainer.innerHTML = `
1361
- <div class="server-status-row" data-testid="at-server-status-row">
1362
- <span class="server-status connected" data-testid="at-server-status-connected">${toolCount} tools <span class="material-icons-round">check_circle</span> connected</span>
1363
- <button type="button" class="btn btn-danger disconnect-btn" data-testid="at-disconnect-btn"><span class="material-icons-round">link_off</span>Disconnect</button>
1364
- </div>`;
1375
+ if (connected) {
1376
+ const toolCount = Array.isArray(this.currentServer.tools) ? this.currentServer.tools.length : 0;
1377
+ btn.classList.add('connected');
1378
+ btn.classList.remove('disconnected');
1379
+ btn.title = `Disconnect (${toolCount} tools)`;
1380
+ btn.setAttribute('aria-label', 'Disconnect');
1381
+ if (iconEl) {
1382
+ iconEl.textContent = 'stop';
1383
+ }
1384
+ if (countEl) {
1385
+ countEl.textContent = `${toolCount} tools`;
1386
+ }
1365
1387
  } else {
1366
- this.connectedServersContainer.innerHTML = `
1367
- <div class="server-status-row" data-testid="at-server-status-row">
1368
- <span class="server-status disconnected" data-testid="at-server-status-disconnected"><span class="material-icons-round">cancel</span>Disconnected</span>
1369
- <button type="button" class="btn btn-secondary reconnect-btn" data-testid="at-reconnect-btn"><span class="material-icons-round">refresh</span>Reconnect</button>
1370
- </div>`;
1388
+ btn.classList.add('disconnected');
1389
+ btn.classList.remove('connected');
1390
+ btn.title = 'Connect';
1391
+ btn.setAttribute('aria-label', 'Connect');
1392
+ if (iconEl) {
1393
+ iconEl.textContent = 'play_arrow';
1394
+ }
1395
+ if (countEl) {
1396
+ countEl.textContent = '';
1397
+ }
1371
1398
  }
1372
-
1373
- this.connectedServersContainer.querySelector('.disconnect-btn')?.addEventListener('click', () => {
1374
- this.disconnectServer();
1375
- });
1376
-
1377
- this.connectedServersContainer.querySelector('.reconnect-btn')?.addEventListener('click', () => {
1378
- this.handleReconnect();
1379
- });
1380
1399
  }
1381
1400
 
1382
1401
  async disconnectServer() {
@@ -2226,6 +2245,11 @@ class McpAgentTester {
2226
2245
  btn.classList.toggle('active', btn.dataset.tab === tabName);
2227
2246
  });
2228
2247
 
2248
+ const appEl = document.querySelector('.app');
2249
+ if (appEl) {
2250
+ appEl.setAttribute('data-active-tab', tabName);
2251
+ }
2252
+
2229
2253
  if (tabName === 'chat') {
2230
2254
  this.tabPaneChat.style.display = '';
2231
2255
  this.tabPaneChat.classList.add('active');
@@ -138,41 +138,6 @@ body {
138
138
  height: 100vh;
139
139
  }
140
140
 
141
- /* --- Sidebar --- */
142
- .sidebar {
143
- width: 384px;
144
- flex-shrink: 0;
145
- background: var(--bg-sidebar);
146
- border-right: 1px solid var(--border);
147
- display: flex;
148
- flex-direction: column;
149
- transition: transform 0.3s ease;
150
- z-index: 1000;
151
- overflow: hidden;
152
- }
153
-
154
- .sidebar-content {
155
- flex: 1;
156
- padding: 16px;
157
- overflow-y: auto;
158
- }
159
-
160
- .sidebar-toggle {
161
- background: none;
162
- border: none;
163
- color: var(--text-muted);
164
- cursor: pointer;
165
- padding: 8px;
166
- border-radius: 50%;
167
- transition: background-color 0.2s;
168
- display: none;
169
- line-height: 1;
170
- }
171
-
172
- .sidebar-toggle:hover {
173
- background-color: var(--bg-input);
174
- }
175
-
176
141
  /* --- Section Labels --- */
177
142
  .section-label {
178
143
  font-size: 0.68rem;
@@ -204,6 +169,116 @@ body {
204
169
  gap: 12px;
205
170
  }
206
171
 
172
+ /* --- Header connection bar (compact, inline) --- */
173
+ .connection-form.header-connection {
174
+ flex-direction: row;
175
+ align-items: center;
176
+ gap: 6px;
177
+ flex: 1 1 320px;
178
+ min-width: 0;
179
+ margin: 0;
180
+ }
181
+
182
+ .connection-form.header-connection .form-group {
183
+ flex: 1 1 auto;
184
+ min-width: 0;
185
+ gap: 0;
186
+ }
187
+
188
+ .connection-form.header-connection input[type="url"] {
189
+ padding: 6px 32px 6px 10px;
190
+ font-size: 0.8rem;
191
+ width: 100%;
192
+ height: 32px;
193
+ }
194
+
195
+ .connection-form.header-connection .dropdown-toggle .material-icons-round {
196
+ font-size: 18px;
197
+ }
198
+
199
+ .header-transport {
200
+ height: 32px;
201
+ padding: 4px 6px;
202
+ border: 1px solid var(--border-input);
203
+ border-radius: var(--radius);
204
+ background: var(--bg-input);
205
+ color: var(--text);
206
+ font-size: 0.78rem;
207
+ font-family: inherit;
208
+ outline: none;
209
+ flex-shrink: 0;
210
+ cursor: pointer;
211
+ }
212
+
213
+ .header-transport:focus {
214
+ border-color: var(--primary);
215
+ box-shadow: 0 0 0 2px var(--primary-glow);
216
+ }
217
+
218
+ /* --- Combined Connect / Disconnect toggle button --- */
219
+ .btn-connect-toggle {
220
+ display: inline-flex;
221
+ align-items: center;
222
+ justify-content: center;
223
+ gap: 6px;
224
+ height: 32px;
225
+ padding: 0 10px;
226
+ min-width: 36px;
227
+ border: none;
228
+ border-radius: var(--radius);
229
+ cursor: pointer;
230
+ font-weight: 600;
231
+ font-size: 0.8rem;
232
+ font-family: inherit;
233
+ transition: background 0.15s, box-shadow 0.15s, transform 0.05s;
234
+ flex-shrink: 0;
235
+ line-height: 1;
236
+ }
237
+
238
+ .btn-connect-toggle:active {
239
+ transform: scale(0.97);
240
+ }
241
+
242
+ .btn-connect-toggle.disconnected {
243
+ background: var(--success);
244
+ color: #fff;
245
+ box-shadow: 0 2px 6px rgba(34, 197, 94, 0.35);
246
+ }
247
+
248
+ .btn-connect-toggle.disconnected:hover {
249
+ background: #16a34a;
250
+ }
251
+
252
+ .btn-connect-toggle.connected {
253
+ background: var(--success-bg);
254
+ color: var(--success);
255
+ border: 1px solid var(--success-border);
256
+ box-shadow: 0 1px 3px rgba(34, 197, 94, 0.15);
257
+ }
258
+
259
+ .btn-connect-toggle.connected:hover {
260
+ background: rgba(34, 197, 94, 0.16);
261
+ }
262
+
263
+ .btn-connect-toggle .material-icons-round {
264
+ font-size: 18px;
265
+ }
266
+
267
+ .btn-connect-toggle.connected .material-icons-round {
268
+ color: var(--error);
269
+ }
270
+
271
+ .btn-connect-toggle .tools-count {
272
+ display: none;
273
+ font-size: 0.75rem;
274
+ font-weight: 600;
275
+ white-space: nowrap;
276
+ }
277
+
278
+ .btn-connect-toggle.connected .tools-count {
279
+ display: inline;
280
+ }
281
+
207
282
  .form-group {
208
283
  display: flex;
209
284
  flex-direction: column;
@@ -687,29 +762,24 @@ body {
687
762
 
688
763
  /* --- Chat Header --- */
689
764
  .chat-header {
690
- height: 56px;
765
+ min-height: 56px;
691
766
  flex-shrink: 0;
692
767
  display: flex;
693
768
  align-items: center;
694
- justify-content: space-between;
695
- padding: 0 20px;
769
+ flex-wrap: wrap;
770
+ gap: 12px;
771
+ padding: 8px 16px;
696
772
  background: var(--bg-header);
697
773
  border-bottom: 1px solid var(--border);
698
774
  backdrop-filter: blur(8px);
699
775
  z-index: 10;
700
776
  }
701
777
 
702
- .chat-info {
703
- flex: 1;
704
- display: flex;
705
- align-items: center;
706
- gap: 16px;
707
- }
708
-
709
778
  .chat-title {
710
779
  display: flex;
711
780
  align-items: center;
712
781
  gap: 8px;
782
+ flex-shrink: 0;
713
783
  }
714
784
 
715
785
  .chat-title .header-icon {
@@ -778,6 +848,13 @@ body {
778
848
  display: flex;
779
849
  align-items: center;
780
850
  gap: 4px;
851
+ margin-left: auto;
852
+ flex-shrink: 0;
853
+ }
854
+
855
+ /* Hide chat-only controls when not on the Chat tab */
856
+ .app[data-active-tab="tool-tester"] .chat-only {
857
+ display: none !important;
781
858
  }
782
859
 
783
860
  .header-format-select {
@@ -1264,26 +1341,26 @@ body {
1264
1341
 
1265
1342
  /* --- Scrollbar --- */
1266
1343
  .chat-messages::-webkit-scrollbar,
1267
- .sidebar-content::-webkit-scrollbar,
1344
+ .settings-modal-body::-webkit-scrollbar,
1268
1345
  .dropdown-list::-webkit-scrollbar {
1269
1346
  width: 6px;
1270
1347
  }
1271
1348
 
1272
1349
  .chat-messages::-webkit-scrollbar-track,
1273
- .sidebar-content::-webkit-scrollbar-track,
1350
+ .settings-modal-body::-webkit-scrollbar-track,
1274
1351
  .dropdown-list::-webkit-scrollbar-track {
1275
1352
  background: transparent;
1276
1353
  }
1277
1354
 
1278
1355
  .chat-messages::-webkit-scrollbar-thumb,
1279
- .sidebar-content::-webkit-scrollbar-thumb,
1356
+ .settings-modal-body::-webkit-scrollbar-thumb,
1280
1357
  .dropdown-list::-webkit-scrollbar-thumb {
1281
1358
  background: var(--scrollbar-thumb);
1282
1359
  border-radius: 3px;
1283
1360
  }
1284
1361
 
1285
1362
  .chat-messages::-webkit-scrollbar-thumb:hover,
1286
- .sidebar-content::-webkit-scrollbar-thumb:hover,
1363
+ .settings-modal-body::-webkit-scrollbar-thumb:hover,
1287
1364
  .dropdown-list::-webkit-scrollbar-thumb:hover {
1288
1365
  background: var(--scrollbar-hover);
1289
1366
  }
@@ -1330,24 +1407,6 @@ body {
1330
1407
 
1331
1408
  /* --- Responsive --- */
1332
1409
  @media (max-width: 768px) {
1333
- .sidebar {
1334
- position: fixed;
1335
- height: 100vh;
1336
- left: 0;
1337
- top: 0;
1338
- transform: translateX(-100%);
1339
- z-index: 1000;
1340
- box-shadow: var(--shadow-lg);
1341
- }
1342
-
1343
- .sidebar.open {
1344
- transform: translateX(0);
1345
- }
1346
-
1347
- .sidebar-toggle {
1348
- display: flex;
1349
- }
1350
-
1351
1410
  .mobile-only {
1352
1411
  display: flex !important;
1353
1412
  }
@@ -1356,6 +1415,15 @@ body {
1356
1415
  font-size: 1rem;
1357
1416
  }
1358
1417
 
1418
+ .connection-form.header-connection {
1419
+ flex: 1 1 100%;
1420
+ order: 10;
1421
+ }
1422
+
1423
+ .tabs-bar.header-tabs {
1424
+ order: 5;
1425
+ }
1426
+
1359
1427
  .message {
1360
1428
  max-width: 90%;
1361
1429
  }
@@ -1608,6 +1676,59 @@ textarea.prompt-modified {
1608
1676
  color: #f28b82;
1609
1677
  }
1610
1678
 
1679
+ /* ============================================
1680
+ Settings Modal (former sidebar)
1681
+ ============================================ */
1682
+
1683
+ .settings-modal-overlay {
1684
+ position: fixed;
1685
+ inset: 0;
1686
+ background: rgba(0, 0, 0, 0.5);
1687
+ backdrop-filter: blur(4px);
1688
+ z-index: 900;
1689
+ display: flex;
1690
+ align-items: center;
1691
+ justify-content: center;
1692
+ padding: 24px;
1693
+ }
1694
+
1695
+ .settings-modal {
1696
+ background: var(--bg-sidebar);
1697
+ border: 1px solid var(--border);
1698
+ border-radius: var(--radius-lg);
1699
+ width: 100%;
1700
+ max-width: 560px;
1701
+ max-height: 90vh;
1702
+ display: flex;
1703
+ flex-direction: column;
1704
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
1705
+ }
1706
+
1707
+ .settings-modal-header {
1708
+ display: flex;
1709
+ align-items: center;
1710
+ justify-content: space-between;
1711
+ padding: 14px 20px;
1712
+ border-bottom: 1px solid var(--border);
1713
+ }
1714
+
1715
+ .settings-modal-header h3 {
1716
+ font-size: 0.95rem;
1717
+ font-weight: 600;
1718
+ color: var(--text);
1719
+ margin: 0;
1720
+ }
1721
+
1722
+ .settings-modal-body {
1723
+ padding: 16px 20px;
1724
+ overflow-y: auto;
1725
+ flex: 1;
1726
+ }
1727
+
1728
+ .settings-modal-body .config-section:last-child {
1729
+ margin-bottom: 0;
1730
+ }
1731
+
1611
1732
  /* ============================================
1612
1733
  LLM Settings Modal
1613
1734
  ============================================ */
@@ -1867,41 +1988,45 @@ textarea.prompt-modified {
1867
1988
  ============================================ */
1868
1989
  .tabs-bar {
1869
1990
  display: flex;
1870
- gap: 4px;
1871
- padding: 0 16px;
1872
- border-bottom: 1px solid var(--border);
1873
- background: var(--bg-header);
1991
+ gap: 2px;
1874
1992
  flex-shrink: 0;
1875
1993
  }
1876
1994
 
1995
+ .tabs-bar.header-tabs {
1996
+ background: var(--bg-input);
1997
+ border-radius: var(--radius);
1998
+ padding: 2px;
1999
+ }
2000
+
1877
2001
  .tab-btn {
1878
2002
  display: inline-flex;
1879
2003
  align-items: center;
1880
2004
  gap: 6px;
1881
- padding: 10px 16px;
2005
+ padding: 6px 12px;
1882
2006
  background: transparent;
1883
2007
  border: none;
1884
- border-bottom: 2px solid transparent;
2008
+ border-radius: calc(var(--radius) - 2px);
1885
2009
  color: var(--text-secondary);
1886
2010
  cursor: pointer;
1887
- font-size: 0.85rem;
2011
+ font-size: 0.8rem;
1888
2012
  font-weight: 500;
1889
2013
  font-family: inherit;
1890
- transition: color 0.15s, border-color 0.15s, background 0.15s;
2014
+ transition: color 0.15s, background 0.15s;
2015
+ line-height: 1;
1891
2016
  }
1892
2017
 
1893
2018
  .tab-btn:hover {
1894
2019
  color: var(--text);
1895
- background: var(--bg-input);
1896
2020
  }
1897
2021
 
1898
2022
  .tab-btn.active {
1899
2023
  color: var(--primary);
1900
- border-bottom-color: var(--primary);
2024
+ background: var(--bg-surface);
2025
+ box-shadow: var(--shadow-sm);
1901
2026
  }
1902
2027
 
1903
2028
  .tab-btn .material-icons-round {
1904
- font-size: 18px;
2029
+ font-size: 16px;
1905
2030
  }
1906
2031
 
1907
2032
  .tab-pane {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fa-mcp-sdk",
3
3
  "productName": "FA MCP SDK",
4
- "version": "0.4.121",
4
+ "version": "0.4.124",
5
5
  "description": "Core infrastructure and templates for building Model Context Protocol (MCP) servers with TypeScript",
6
6
  "type": "module",
7
7
  "main": "dist/core/index.js",
@@ -1,12 +1,23 @@
1
1
  import chalk from 'chalk';
2
2
 
3
- import { logger as lgr, formatToolResult, ToolExecutionError, TToolHandlerResponse } from '../../core/index.js';
3
+ import {
4
+ debugMcpTool,
5
+ formatToolResult,
6
+ logger as lgr,
7
+ ToolExecutionError,
8
+ TToolHandlerResponse,
9
+ } from '../../core/index.js';
4
10
 
5
11
  const logger = lgr.getSubLogger({ name: chalk.bgGrey('tools') });
6
12
 
7
13
  /**
8
14
  * Template tool handler - customize this for your specific tools
9
15
  * This handles MCP tool execution requests
16
+ *
17
+ * Debug output for tool requests/responses is wired up centrally by the SDK
18
+ * (see `init-mcp-server.ts`) and activated with `DEBUG=mcp:tool`. Other MCP
19
+ * channels have their own switches: `DEBUG=mcp:resource`, `DEBUG=mcp:prompt`,
20
+ * `DEBUG=mcp:notification`. Use `DEBUG=mcp:*` to enable them all at once.
10
21
  */
11
22
  export const handleToolCall = async (params: { name: string; arguments?: any }): Promise<any> => {
12
23
  const { name, arguments: args } = params;
@@ -14,14 +25,26 @@ export const handleToolCall = async (params: { name: string; arguments?: any }):
14
25
  logger.info(`Tool called: ${name}`);
15
26
 
16
27
  try {
28
+ let result: TToolHandlerResponse;
17
29
  // TODO: Implement your tool routing logic here
18
30
  switch (name) {
19
31
  case 'example_tool':
20
- return await handleExampleTool(args);
32
+ result = await handleExampleTool(args);
33
+ break;
21
34
 
22
35
  default:
23
36
  throw new ToolExecutionError(name, `Unknown tool: ${name}`);
24
37
  }
38
+
39
+ // Optional: per-handler debug hook, in addition to the SDK-level wrapper.
40
+ // Useful if you want to inspect intermediate (pre-format) values inside a
41
+ // specific tool — define a new Debug category in `src/lib/debug.ts` and
42
+ // call it here. The example below piggybacks on the built-in switch.
43
+ if (debugMcpTool.enabled) {
44
+ debugMcpTool(`handler[${name}] returned\n${JSON.stringify(result, null, 2)}`);
45
+ }
46
+
47
+ return result;
25
48
  } catch (error: Error | any) {
26
49
  logger.error(`Tool execution failed for ${name}:`, error);
27
50
  error.printed = true;