fa-mcp-sdk 0.2.146 → 0.2.182

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 (153) hide show
  1. package/README.md +1 -1
  2. package/bin/fa-mcp.js +66 -54
  3. package/cli-template/.env.example +2 -2
  4. package/cli-template/{fa-mcp-sdk-spec.md → FA-MCP-SDK.md} +699 -42
  5. package/cli-template/README.md +2 -2
  6. package/cli-template/package.json +1 -1
  7. package/cli-template/r/TEST HTTP.xml +9 -0
  8. package/cli-template/{run/TEST SSE.run.xml → r/TEST SSE.xml } +2 -2
  9. package/cli-template/{run/TEST STDIO.run.xml → r/TEST STDIO.xml } +2 -2
  10. package/cli-template/r/generate-token.xml +14 -0
  11. package/cli-template/{run/kill-server.run.xml → r/kill-server.xml} +2 -2
  12. package/cli-template/{run/kill-token-gen-server.xml → r/remove-nul.xml} +4 -5
  13. package/{cli-template/config → config}/_local.yaml +28 -14
  14. package/{cli-template/config → config}/custom-environment-variables.yaml +3 -0
  15. package/{cli-template/config → config}/default.yaml +50 -10
  16. package/{cli-template/config → config}/development.yaml +4 -4
  17. package/config/local.yaml +89 -0
  18. package/{cli-template/config → config}/production.yaml +4 -4
  19. package/dist/core/_types_/active-directory-config.d.ts +3 -0
  20. package/dist/core/_types_/active-directory-config.d.ts.map +1 -1
  21. package/dist/core/_types_/config.d.ts +5 -1
  22. package/dist/core/_types_/config.d.ts.map +1 -1
  23. package/dist/core/_types_/types.d.ts +40 -1
  24. package/dist/core/_types_/types.d.ts.map +1 -1
  25. package/dist/core/ad/group-checker.d.ts +13 -0
  26. package/dist/core/ad/group-checker.d.ts.map +1 -0
  27. package/dist/core/ad/group-checker.js +86 -0
  28. package/dist/core/ad/group-checker.js.map +1 -0
  29. package/dist/core/auth/admin-auth.d.ts +16 -0
  30. package/dist/core/auth/admin-auth.d.ts.map +1 -0
  31. package/dist/core/auth/admin-auth.js +159 -0
  32. package/dist/core/auth/admin-auth.js.map +1 -0
  33. package/dist/core/auth/basic.d.ts +6 -0
  34. package/dist/core/auth/basic.d.ts.map +1 -0
  35. package/dist/core/auth/basic.js +26 -0
  36. package/dist/core/auth/basic.js.map +1 -0
  37. package/dist/core/auth/{jwt-validation.d.ts → jwt.d.ts} +4 -3
  38. package/dist/core/auth/jwt.d.ts.map +1 -0
  39. package/dist/core/auth/{jwt-validation.js → jwt.js} +9 -19
  40. package/dist/core/auth/jwt.js.map +1 -0
  41. package/dist/core/auth/middleware.d.ts.map +1 -1
  42. package/dist/core/auth/middleware.js +3 -3
  43. package/dist/core/auth/middleware.js.map +1 -1
  44. package/dist/core/auth/multi-auth.d.ts +14 -6
  45. package/dist/core/auth/multi-auth.d.ts.map +1 -1
  46. package/dist/core/auth/multi-auth.js +151 -141
  47. package/dist/core/auth/multi-auth.js.map +1 -1
  48. package/dist/core/auth/permanent.d.ts +6 -0
  49. package/dist/core/auth/permanent.d.ts.map +1 -0
  50. package/dist/core/auth/permanent.js +15 -0
  51. package/dist/core/auth/permanent.js.map +1 -0
  52. package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.d.ts +1 -1
  53. package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.d.ts.map +1 -1
  54. package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.js +8 -10
  55. package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.js.map +1 -1
  56. package/dist/core/auth/token-generator/ntlm/ntlm-integration.d.ts.map +1 -1
  57. package/dist/core/auth/token-generator/ntlm/ntlm-integration.js +9 -2
  58. package/dist/core/auth/token-generator/ntlm/ntlm-integration.js.map +1 -1
  59. package/dist/core/auth/token-generator/server.d.ts.map +1 -1
  60. package/dist/core/auth/token-generator/server.js +59 -25
  61. package/dist/core/auth/token-generator/server.js.map +1 -1
  62. package/dist/core/auth/types.d.ts +4 -3
  63. package/dist/core/auth/types.d.ts.map +1 -1
  64. package/dist/core/bootstrap/startup-info.d.ts.map +1 -1
  65. package/dist/core/bootstrap/startup-info.js +19 -0
  66. package/dist/core/bootstrap/startup-info.js.map +1 -1
  67. package/dist/core/consul/access-points-updater.js +1 -1
  68. package/dist/core/consul/access-points-updater.js.map +1 -1
  69. package/dist/core/consul/get-consul-api.d.ts +1 -1
  70. package/dist/core/consul/get-consul-api.d.ts.map +1 -1
  71. package/dist/core/consul/get-consul-api.js +1 -1
  72. package/dist/core/consul/get-consul-api.js.map +1 -1
  73. package/dist/core/consul/register.d.ts +1 -1
  74. package/dist/core/consul/register.d.ts.map +1 -1
  75. package/dist/core/index.d.ts +4 -2
  76. package/dist/core/index.d.ts.map +1 -1
  77. package/dist/core/index.js +3 -1
  78. package/dist/core/index.js.map +1 -1
  79. package/dist/core/init-mcp-server.d.ts.map +1 -1
  80. package/dist/core/init-mcp-server.js +1 -1
  81. package/dist/core/init-mcp-server.js.map +1 -1
  82. package/dist/core/utils/testing/McpSseClient.js.map +1 -1
  83. package/dist/core/web/admin-router.d.ts +10 -0
  84. package/dist/core/web/admin-router.d.ts.map +1 -0
  85. package/dist/core/web/admin-router.js +309 -0
  86. package/dist/core/web/admin-router.js.map +1 -0
  87. package/dist/core/web/favicon-svg.d.ts +1 -1
  88. package/dist/core/web/favicon-svg.d.ts.map +1 -1
  89. package/dist/core/web/favicon-svg.js +21 -3
  90. package/dist/core/web/favicon-svg.js.map +1 -1
  91. package/dist/core/web/home-api.d.ts +7 -0
  92. package/dist/core/web/home-api.d.ts.map +1 -0
  93. package/dist/core/web/home-api.js +106 -0
  94. package/dist/core/web/home-api.js.map +1 -0
  95. package/dist/core/web/server-http.d.ts +1 -0
  96. package/dist/core/web/server-http.d.ts.map +1 -1
  97. package/dist/core/web/server-http.js +60 -25
  98. package/dist/core/web/server-http.js.map +1 -1
  99. package/dist/core/web/static/home/index.html +218 -0
  100. package/dist/core/web/static/home/script.js +643 -0
  101. package/dist/core/web/{about-page/css.js → static/styles.css} +435 -105
  102. package/dist/core/web/static/token-gen/index.html +105 -0
  103. package/dist/core/web/static/token-gen/jwt-icon.svg +3 -0
  104. package/dist/core/web/static/token-gen/logout.svg +4 -0
  105. package/dist/core/web/static/token-gen/script.js +553 -0
  106. package/dist/core/web/static/token-gen/user.svg +4 -0
  107. package/dist/core/web/svg-icons.d.ts +7 -0
  108. package/dist/core/web/svg-icons.d.ts.map +1 -0
  109. package/dist/core/web/svg-icons.js +78 -0
  110. package/dist/core/web/svg-icons.js.map +1 -0
  111. package/package.json +7 -3
  112. package/scripts/copy-static.js +31 -0
  113. package/src/template/_types_/custom-config.ts +83 -0
  114. package/src/template/asset/logo.svg +4 -0
  115. package/src/template/start.ts +3 -3
  116. package/src/template/tools/handle-tool-call.ts +2 -1
  117. package/src/tests/mcp/test-http.js +10 -2
  118. package/src/tests/mcp/test-sse.js +10 -2
  119. package/src/tests/mcp/test-stdio.js +1 -2
  120. package/cli-template/run/TEST HTTP.run.xml +0 -5
  121. package/cli-template/run/TEST search.run.xml +0 -11
  122. package/cli-template/run/remove-nul.js.run.xml +0 -5
  123. package/dist/core/auth/jwt-validation.d.ts.map +0 -1
  124. package/dist/core/auth/jwt-validation.js.map +0 -1
  125. package/dist/core/auth/token-generator/html.d.ts +0 -9
  126. package/dist/core/auth/token-generator/html.d.ts.map +0 -1
  127. package/dist/core/auth/token-generator/html.js +0 -862
  128. package/dist/core/auth/token-generator/html.js.map +0 -1
  129. package/dist/core/web/about-page/css.d.ts +0 -2
  130. package/dist/core/web/about-page/css.d.ts.map +0 -1
  131. package/dist/core/web/about-page/css.js.map +0 -1
  132. package/dist/core/web/about-page/render.d.ts +0 -2
  133. package/dist/core/web/about-page/render.d.ts.map +0 -1
  134. package/dist/core/web/about-page/render.js +0 -773
  135. package/dist/core/web/about-page/render.js.map +0 -1
  136. package/src/template/_examples/multi-auth-examples.ts +0 -541
  137. /package/cli-template/{run/== START ==.run.xml → r/== START ==.xml} +0 -0
  138. /package/cli-template/{run/cb.run.xml → r/cb.xml} +0 -0
  139. /package/cli-template/{run/ci.run.xml → r/ci.xml} +0 -0
  140. /package/cli-template/{run/lint.run.xml → r/lint.xml} +0 -0
  141. /package/cli-template/{run/lint_fix.run.xml → r/lint_fix.xml} +0 -0
  142. /package/cli-template/{run/reinstall.run.xml → r/reinstall.xml} +0 -0
  143. /package/{cli-template/config → config}/test.yaml +0 -0
  144. /package/{src/template/asset/favicon.svg → dist/core/web/static/logo.svg} +0 -0
  145. /package/{cli-template/scripts → scripts}/kill-port.js +0 -0
  146. /package/{cli-template/scripts → scripts}/npm/patch_node_modules.js +0 -0
  147. /package/{cli-template/scripts → scripts}/npm/run.js +0 -0
  148. /package/{cli-template/scripts → scripts}/npm/yarn-ci.ps1 +0 -0
  149. /package/{cli-template/scripts → scripts}/npm/yarn-ci.sh +0 -0
  150. /package/{cli-template/scripts → scripts}/npm/yarn-reinstall.ps1 +0 -0
  151. /package/{cli-template/scripts → scripts}/npm/yarn-reinstall.sh +0 -0
  152. /package/{cli-template/scripts → scripts}/pre-commit +0 -0
  153. /package/{cli-template/scripts → scripts}/remove-nul.js +0 -0
@@ -1,773 +0,0 @@
1
- import { getResourcesList } from '../../mcp/resources.js';
2
- import { getPromptsList } from '../../mcp/prompts.js';
3
- import { getMainDBConnectionStatus } from '../../db/pg-db.js';
4
- import { getFaviconSvg } from '../favicon-svg.js';
5
- import { appConfig, getProjectData } from '../../bootstrap/init-config.js';
6
- import { getCss } from './css.js';
7
- import { encodeSvgForDataUri } from '../../utils/utils.js';
8
- const startTime = new Date();
9
- const getUptime = () => {
10
- const uptimeMs = Date.now() - startTime.getTime();
11
- const uptimeSeconds = Math.floor(uptimeMs / 1000);
12
- const hours = Math.floor(uptimeSeconds / 3600);
13
- const minutes = Math.floor((uptimeSeconds % 3600) / 60);
14
- const seconds = uptimeSeconds % 60;
15
- if (hours > 0) {
16
- return `${hours}h ${minutes}m ${seconds}s`;
17
- }
18
- else if (minutes > 0) {
19
- return `${minutes}m ${seconds}s`;
20
- }
21
- else {
22
- return `${seconds}s`;
23
- }
24
- };
25
- export const renderAboutPage = async () => {
26
- const { version, repo } = appConfig;
27
- const serviceTitle = appConfig.productName.replace(/MCP/i, '').replace(/\s{2,}/g, ' ').trim();
28
- const staffSvg = getFaviconSvg();
29
- const iconEncoded = encodeSvgForDataUri(staffSvg);
30
- const { resources } = getResourcesList();
31
- const { prompts } = getPromptsList();
32
- const { tools, httpComponents } = global.__MCP_PROJECT_DATA__;
33
- let swaggerInfo = '';
34
- if (httpComponents?.swagger) {
35
- swaggerInfo = `<!-- Swagger -->
36
- <section class="info-section">
37
- <div class="info-row">
38
- <span class="label">API Reference:</span>
39
- <span class="value">
40
- <a href="/docs" target="_blank" rel="noopener" class="clickable">Swagger</a>
41
- </span>
42
- </div>
43
- </section>`;
44
- }
45
- let dbInfo = '';
46
- if (appConfig.isMainDBUsed) {
47
- const dbStatus = await getMainDBConnectionStatus();
48
- const { host, port, database } = appConfig.db.postgres.dbs.main;
49
- dbInfo = `<!-- Database Info -->
50
- <section class="info-section">
51
- <div class="info-row">
52
- <span class="label">Database:</span>
53
- <div>
54
- <span class="value">${host}:${port}/${database} • </span>
55
- <span class="value ${dbStatus}">${dbStatus}</span>
56
- </div>
57
- </div>
58
- </section>`;
59
- }
60
- const { getConsulUIAddress = (_s) => '', assets } = getProjectData();
61
- const footerData = [];
62
- if (repo) {
63
- footerData.push(`<a href="${repo}" target="_blank" rel="noopener">GitHub Repository</a>`);
64
- }
65
- if (assets?.maintainerHtml) {
66
- footerData.push(assets?.maintainerHtml);
67
- }
68
- let consulInfo = '';
69
- if (appConfig.consul.service.enable) {
70
- const { id } = appConfig.consul.service;
71
- if (id) {
72
- consulInfo = `<!-- Consul Info -->
73
- <section class="info-section">
74
- <div class="info-row">
75
- <span class="label">Consul id:</span>
76
- <span class="value"><a href="${getConsulUIAddress(id)}" target="_blank" rel="noopener" class="clickable">${id}</a></span>
77
- </div>
78
- </section>`;
79
- }
80
- }
81
- const docType = '<!DOCTYPE html>';
82
- // @formatter:off
83
- return docType + `
84
- <html lang="en">
85
- <head>
86
- <meta charset="UTF-8" />
87
- <meta name="viewport" content="width=device-width, initial-scale=1" />
88
- <title>${serviceTitle} MCP Server</title>
89
- <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,${iconEncoded}">
90
- <style>${getCss(appConfig.uiColor.primary)}</style>
91
- </head>
92
- <body>
93
- <div class="simple-container">
94
- <!-- Header -->
95
- <header class="simple-header">
96
- <div class="header-row">
97
- <div class="header-title">
98
- <div class="service-icon">${staffSvg}</div>
99
- <h1><span class="MCPServer">MCP Server</span> ${serviceTitle}</h1>
100
- </div>
101
- </div>
102
- </header>
103
-
104
- <!-- Main Content -->
105
- <main class="simple-main">
106
- <!-- Basic Info -->
107
- <section class="info-section">
108
- <div class="info-row">
109
- <span class="label">Service:</span>
110
- <span class="value">${appConfig.description}</span>
111
- </div>
112
- <div class="info-row">
113
- <span class="label">Version:</span>
114
- <span class="value">${version}</span>
115
- </div>
116
- <div class="info-row">
117
- <span class="label">Tools:</span>
118
- <span class="value clickable" onclick="openModal('tools')">${tools.length} available</span>
119
- </div>
120
- <div class="info-row">
121
- <span class="label">Resources:</span>
122
- <span class="value clickable" onclick="openModal('resources')">${resources.length} available</span>
123
- </div>
124
- <div class="info-row">
125
- <span class="label">Prompts:</span>
126
- <span class="value clickable" onclick="openModal('prompts')">${prompts.length} available</span>
127
- </div>
128
- <div class="info-row">
129
- <span class="label">Uptime:</span>
130
- <span class="value">${getUptime()}</span>
131
- </div>
132
- </section>
133
- ${dbInfo}
134
- <!-- Transport Info -->
135
- <section class="info-section">
136
- <div class="info-row">
137
- <span class="label">HTTP Transport:</span>
138
- <span class="value"><code>GET /sse</code> • <code>POST /mcp</code></span>
139
- </div>
140
- </section>
141
-
142
- ${swaggerInfo}
143
-
144
- ${consulInfo}
145
-
146
- <!-- Health Check -->
147
- <section class="info-section">
148
- <div class="info-row">
149
- <span class="label">Health Check:</span>
150
- <span class="value clickable" onclick="openHealthCheckModal()">Check Server Health</span>
151
- </div>
152
- </section>
153
-
154
- </main>
155
-
156
- <!-- Modal Overlays -->
157
- <!-- Tools Modal -->
158
- <div id="tools-modal" class="modal-overlay" style="display: none;">
159
- <div class="modal-content">
160
- <div class="modal-header">
161
- <h3>Available Tools (${tools.length})</h3>
162
- <button class="modal-close" onclick="closeModal('tools')">&times;</button>
163
- </div>
164
- <div class="modal-body">
165
- <div class="table-container">
166
- <table class="details-table" id="tools-table">
167
- <thead>
168
- <tr>
169
- <th>Name</th>
170
- <th>Description</th>
171
- <th>Actions</th>
172
- </tr>
173
- </thead>
174
- <tbody>
175
- <!-- Content will be dynamically loaded -->
176
- </tbody>
177
- </table>
178
- </div>
179
- </div>
180
- </div>
181
- </div>
182
-
183
- <!-- Resources Modal -->
184
- <div id="resources-modal" class="modal-overlay" style="display: none;">
185
- <div class="modal-content">
186
- <div class="modal-header">
187
- <h3>Available Resources (${resources.length})</h3>
188
- <button class="modal-close" onclick="closeModal('resources')">&times;</button>
189
- </div>
190
- <div class="modal-body">
191
- <div class="table-container">
192
- <table class="details-table" id="resources-table">
193
- <thead>
194
- <tr>
195
- <th>URI</th>
196
- <th>Name</th>
197
- <th>Description</th>
198
- <th>MIME Type</th>
199
- <th>Actions</th>
200
- </tr>
201
- </thead>
202
- <tbody>
203
- <!-- Content will be dynamically loaded -->
204
- </tbody>
205
- </table>
206
- </div>
207
- </div>
208
- </div>
209
- </div>
210
-
211
- <!-- Prompts Modal -->
212
- <div id="prompts-modal" class="modal-overlay" style="display: none;">
213
- <div class="modal-content">
214
- <div class="modal-header">
215
- <h3>Available Prompts (${prompts.length})</h3>
216
- <button class="modal-close" onclick="closeModal('prompts')">&times;</button>
217
- </div>
218
- <div class="modal-body">
219
- <div class="table-container">
220
- <table class="details-table" id="prompts-table">
221
- <thead>
222
- <tr>
223
- <th>Name</th>
224
- <th>Actions</th>
225
- </tr>
226
- </thead>
227
- <tbody>
228
- <!-- Content will be dynamically loaded -->
229
- </tbody>
230
- </table>
231
- </div>
232
- </div>
233
- </div>
234
- </div>
235
-
236
- <!-- Health Check Modal -->
237
- <div id="health-modal" class="modal-overlay" style="display: none;">
238
- <div class="modal-content">
239
- <div class="modal-header">
240
- <h3>Server Health Check</h3>
241
- <button class="modal-close" onclick="closeModal('health')">&times;</button>
242
- </div>
243
- <div class="modal-body">
244
- <div class="loading-cell" id="health-loading">
245
- <div class="loading-spinner"></div>
246
- Checking server health...
247
- </div>
248
- <pre class="json-content" id="health-result" style="display: none;"></pre>
249
- <div class="error-message" id="health-error" style="display: none;"></div>
250
- </div>
251
- </div>
252
- </div>
253
-
254
- <!-- Footer -->
255
- <footer class="simple-footer">
256
- <p>
257
- ${footerData.join(' • ')}
258
- </p>
259
- </footer>
260
- </div>
261
-
262
- <script>
263
- // Store data globally
264
- let toolsData = [];
265
- let resourcesData = [];
266
- let promptsData = [];
267
-
268
- // Initialize data when page loads
269
- document.addEventListener('DOMContentLoaded', function() {
270
- try {
271
- toolsData = ${JSON.stringify(tools)};
272
- resourcesData = ${JSON.stringify(resources)};
273
- promptsData = ${JSON.stringify(prompts)};
274
- } catch (error) {
275
- console.error('Error parsing data:', error);
276
- toolsData = [];
277
- resourcesData = [];
278
- promptsData = [];
279
- }
280
- });
281
-
282
- function openModal(sectionName) {
283
- const modal = document.getElementById(sectionName + '-modal');
284
- const tableBody = document.getElementById(sectionName + '-table').querySelector('tbody');
285
-
286
- // Show loading state
287
- tableBody.innerHTML = '<tr><td colspan="100%" class="loading-cell"><div class="loading-spinner"></div> Loading...</td></tr>';
288
- modal.style.display = 'flex';
289
-
290
- // Load data with small delay to show loading animation
291
- setTimeout(function() {
292
- loadTableData(sectionName);
293
- }, 300);
294
- }
295
-
296
- function closeModal(sectionName) {
297
- const modal = document.getElementById(sectionName + '-modal');
298
- modal.style.display = 'none';
299
- }
300
-
301
- function loadTableData(sectionName) {
302
- const tableBody = document.getElementById(sectionName + '-table').querySelector('tbody');
303
- let data, html;
304
-
305
- switch(sectionName) {
306
- case 'tools':
307
- data = toolsData;
308
- html = generateToolsTableRows(data);
309
- break;
310
- case 'resources':
311
- data = resourcesData;
312
- html = generateResourcesTableRows(data);
313
- break;
314
- case 'prompts':
315
- data = promptsData;
316
- html = generatePromptsTableRows(data);
317
- break;
318
- }
319
-
320
- tableBody.innerHTML = html;
321
- }
322
-
323
- function generateToolsTableRows(tools) {
324
- if (!tools || tools.length === 0) {
325
- return '<tr><td colspan="3" class="loading-cell">No tools available</td></tr>';
326
- }
327
- return tools.map((tool, index) =>
328
- '<tr>' +
329
- '<td><code>' + tool.name + '</code></td>' +
330
- '<td>' + (tool.annotations?.title || tool.description) + '</td>' +
331
- '<td>' +
332
- '<a class="detail-link" id="tools-toggle-' + index + '" onclick="toggleDetails(\\\'tools\\\', ' + index + ')">details</a>' +
333
- '</td>' +
334
- '</tr>' +
335
- '<tr id="tools-detail-' + index + '" class="detail-row" style="display: none;">' +
336
- '<td colspan="3">' +
337
- '<div class="detail-content">' +
338
- '<div class="loading-spinner" style="display: none;"></div>' +
339
- '<pre class="json-content" style="display: none;"></pre>' +
340
- '</div>' +
341
- '</td>' +
342
- '</tr>'
343
- ).join('');
344
- }
345
-
346
- function generateResourcesTableRows(resources) {
347
- if (!resources || resources.length === 0) {
348
- return '<tr><td colspan="5" class="loading-cell">No resources available</td></tr>';
349
- }
350
- return resources.map((resource, index) =>
351
- '<tr>' +
352
- '<td><code>' + resource.uri + '</code></td>' +
353
- '<td>' + resource.name + '</td>' +
354
- '<td>' + resource.description + '</td>' +
355
- '<td><code>' + resource.mimeType + '</code></td>' +
356
- '<td>' +
357
- '<a class="detail-link" id="resources-toggle-details-' + index + '" onclick="toggleResourceDetails(\\\'resources\\\', ' + index + ', \\\'details\\\')">details</a>' +
358
- ' / ' +
359
- '<a class="detail-link" id="resources-toggle-resource-' + index + '" onclick="toggleResourceDetails(\\\'resources\\\', ' + index + ', \\\'resource\\\')">resource</a>' +
360
- '</td>' +
361
- '</tr>' +
362
- '<tr id="resources-detail-' + index + '" class="detail-row" style="display: none;">' +
363
- '<td colspan="5">' +
364
- '<div class="detail-content">' +
365
- '<div class="loading-spinner"></div>' +
366
- '<pre class="json-content" style="display: none;"></pre>' +
367
- '<div class="resource-content" style="display: none;"></div>' +
368
- '</div>' +
369
- '</td>' +
370
- '</tr>'
371
- ).join('');
372
- }
373
-
374
- function generatePromptsTableRows(prompts) {
375
- if (!prompts || prompts.length === 0) {
376
- return '<tr><td colspan="2" class="loading-cell">No prompts available</td></tr>';
377
- }
378
- return prompts.map((prompt, index) =>
379
- '<tr>' +
380
- '<td><code>' + prompt.name + '</code></td>' +
381
- '<td>' +
382
- '<a class="detail-link" id="prompts-toggle-details-' + index + '" onclick="togglePromptDetails(\\\'prompts\\\', ' + index + ', \\\'details\\\')">details</a>' +
383
- ' / ' +
384
- '<a class="detail-link" id="prompts-toggle-prompt-' + index + '" onclick="togglePromptDetails(\\\'prompts\\\', ' + index + ', \\\'prompt\\\')">prompt</a>' +
385
- '</td>' +
386
- '</tr>' +
387
- '<tr id="prompts-detail-' + index + '" class="detail-row" style="display: none;">' +
388
- '<td colspan="2">' +
389
- '<div class="detail-content">' +
390
- '<div class="loading-spinner"></div>' +
391
- '<pre class="json-content" style="display: none;"></pre>' +
392
- '<div class="prompt-content" style="display: none;"></div>' +
393
- '</div>' +
394
- '</td>' +
395
- '</tr>'
396
- ).join('');
397
- }
398
-
399
- function toggleDetails(sectionName, index) {
400
- const detailRow = document.getElementById(sectionName + '-detail-' + index);
401
- const toggleLink = document.getElementById(sectionName + '-toggle-' + index);
402
- const loadingSpinner = detailRow.querySelector('.loading-spinner');
403
- const jsonContent = detailRow.querySelector('.json-content');
404
-
405
- if (detailRow.style.display === 'none') {
406
- // Show the detail row with loading state
407
- detailRow.style.display = 'table-row';
408
- toggleLink.textContent = 'hide';
409
- loadingSpinner.style.display = 'block';
410
- jsonContent.style.display = 'none';
411
-
412
- // Simulate loading delay and show content
413
- setTimeout(() => {
414
- let data;
415
- let textContent;
416
- switch(sectionName) {
417
- case 'tools':
418
- data = {
419
- name: toolsData[index].name,
420
- description: toolsData[index].description,
421
- inputSchema: toolsData[index].inputSchema,
422
- annotations: toolsData[index].annotations
423
- };
424
- textContent = JSON.stringify(data, null, 2);
425
- break;
426
- case 'resources':
427
- data = resourcesData[index].content || resourcesData[index];
428
- textContent = JSON.stringify(data, null, 2);
429
- // Try to parse JSON from contents[0]?.text and add explanation
430
- const text = data.contents?.[0]?.text;
431
- if (text) {
432
- try {
433
- const parsedJson = JSON.parse(text);
434
- data.contents[0].text = parsedJson;
435
- textContent = 'Text field - deserialized data:\\n\\n' + JSON.stringify(data, null, 2);
436
- } catch (e) {
437
- // If parsing fails, keep original data
438
- }
439
- }
440
- break;
441
- case 'prompts':
442
- data = promptsData[index];
443
- textContent = JSON.stringify(data, null, 2)
444
- break;
445
- }
446
-
447
- loadingSpinner.style.display = 'none';
448
- jsonContent.style.display = 'block';
449
- jsonContent.textContent = textContent;
450
- addCopyButton(jsonContent);
451
- }, 500);
452
- } else {
453
- // Hide the detail row
454
- detailRow.style.display = 'none';
455
- toggleLink.textContent = 'details';
456
- }
457
- }
458
-
459
- // Handle prompt details and prompt content display
460
- async function togglePromptDetails(sectionName, index, displayType) {
461
- const detailRow = document.getElementById(sectionName + '-detail-' + index);
462
- const toggleLinkDetails = document.getElementById(sectionName + '-toggle-details-' + index);
463
- const toggleLinkPrompt = document.getElementById(sectionName + '-toggle-prompt-' + index);
464
- const loadingSpinner = detailRow.querySelector('.loading-spinner');
465
- const jsonContent = detailRow.querySelector('.json-content');
466
- const promptContent = detailRow.querySelector('.prompt-content');
467
-
468
- const isCurrentlyHidden = detailRow.style.display === 'none';
469
- const currentToggleLink = displayType === 'details' ? toggleLinkDetails : toggleLinkPrompt;
470
- const otherToggleLink = displayType === 'details' ? toggleLinkPrompt : toggleLinkDetails;
471
-
472
- if (isCurrentlyHidden || currentToggleLink.textContent === displayType) {
473
- // Show the detail row with loading state
474
- detailRow.style.display = 'table-row';
475
- currentToggleLink.textContent = 'hide';
476
- otherToggleLink.textContent = displayType === 'details' ? 'prompt' : 'details';
477
- loadingSpinner.style.display = 'block';
478
- jsonContent.style.display = 'none';
479
- promptContent.style.display = 'none';
480
-
481
- if (displayType === 'details') {
482
- // Show JSON details
483
- setTimeout(() => {
484
- const data = promptsData[index];
485
- const textContent = JSON.stringify(data, null, 2);
486
- loadingSpinner.style.display = 'none';
487
- jsonContent.style.display = 'block';
488
- jsonContent.textContent = textContent;
489
- addCopyButton(jsonContent);
490
- }, 300);
491
- } else {
492
- // Fetch and show prompt content
493
- try {
494
- const promptName = promptsData[index].name;
495
- const response = await fetch('/mcp', {
496
- method: 'POST',
497
- headers: { 'Content-Type': 'application/json' },
498
- body: JSON.stringify({
499
- jsonrpc: '2.0',
500
- id: Date.now(),
501
- method: 'prompts/get',
502
- params: { name: promptName }
503
- })
504
- });
505
-
506
- if (!response.ok) {
507
- let errorData = ''
508
- try {
509
- errorData = await response.text();
510
- } catch {
511
- //
512
- }
513
- errorData = [response.statusText || '', errorData].join('. ')
514
- throw new Error('HTTP ' + response.status + (errorData ? ': ' + errorData : ''));
515
- }
516
-
517
- const result = await response.json();
518
- const messages = result.result?.messages || [];
519
- let promptText = '';
520
-
521
- messages.forEach((msg, i) => {
522
- if (i > 0) promptText += '\\n\\n---\\n\\n';
523
- promptText += 'Role: ' + msg.role + '\\n\\n';
524
- if (typeof msg.content === 'string') {
525
- promptText += msg.content;
526
- } else if (msg.content?.text) {
527
- promptText += msg.content.text;
528
- } else {
529
- promptText += JSON.stringify(msg.content, null, 2);
530
- }
531
- });
532
-
533
- loadingSpinner.style.display = 'none';
534
- promptContent.style.display = 'block';
535
- promptContent.innerHTML = '<pre class="json-content">' + promptText + '</pre>';
536
- addCopyButton(promptContent.querySelector('.json-content'));
537
- } catch (error) {
538
- loadingSpinner.style.display = 'none';
539
- promptContent.style.display = 'block';
540
- promptContent.innerHTML = '<div class="error-message">Failed to load prompt: ' + error.message + '</div>';
541
- }
542
- }
543
- } else {
544
- // Hide the detail row
545
- detailRow.style.display = 'none';
546
- toggleLinkDetails.textContent = 'details';
547
- toggleLinkPrompt.textContent = 'prompt';
548
- }
549
- }
550
-
551
- // Handle resource details and resource content display
552
- async function toggleResourceDetails(sectionName, index, displayType) {
553
- const detailRow = document.getElementById(sectionName + '-detail-' + index);
554
- const toggleLinkDetails = document.getElementById(sectionName + '-toggle-details-' + index);
555
- const toggleLinkResource = document.getElementById(sectionName + '-toggle-resource-' + index);
556
- const loadingSpinner = detailRow.querySelector('.loading-spinner');
557
- const jsonContent = detailRow.querySelector('.json-content');
558
- const resourceContent = detailRow.querySelector('.resource-content');
559
-
560
- const isCurrentlyHidden = detailRow.style.display === 'none';
561
- const currentToggleLink = displayType === 'details' ? toggleLinkDetails : toggleLinkResource;
562
- const otherToggleLink = displayType === 'details' ? toggleLinkResource : toggleLinkDetails;
563
-
564
- if (isCurrentlyHidden || currentToggleLink.textContent === displayType) {
565
- // Show the detail row with loading state
566
- detailRow.style.display = 'table-row';
567
- currentToggleLink.textContent = 'hide';
568
- otherToggleLink.textContent = displayType === 'details' ? 'resource' : 'details';
569
- loadingSpinner.style.display = 'block';
570
- jsonContent.style.display = 'none';
571
- resourceContent.style.display = 'none';
572
-
573
- if (displayType === 'details') {
574
- // Show JSON details
575
- setTimeout(() => {
576
- const data = resourcesData[index];
577
- const textContent = JSON.stringify(data, null, 2);
578
- loadingSpinner.style.display = 'none';
579
- jsonContent.style.display = 'block';
580
- jsonContent.textContent = textContent;
581
- addCopyButton(jsonContent);
582
- }, 300);
583
- } else {
584
- // Fetch and show resource content
585
- try {
586
- const resourceUri = resourcesData[index].uri;
587
- const response = await fetch('/mcp', {
588
- method: 'POST',
589
- headers: { 'Content-Type': 'application/json' },
590
- body: JSON.stringify({
591
- jsonrpc: '2.0',
592
- id: Date.now(),
593
- method: 'resources/read',
594
- params: { uri: resourceUri }
595
- })
596
- });
597
-
598
- if (!response.ok) {
599
- let errorData = ''
600
- try {
601
- errorData = await response.text();
602
- } catch {
603
- //
604
- }
605
- errorData = [response.statusText || '', errorData].join('. ')
606
- throw new Error('HTTP ' + response.status + (errorData ? ': ' + errorData : ''));
607
- }
608
-
609
- const result = await response.json();
610
- const contents = result.result?.contents || [];
611
- let resourceText = '';
612
-
613
- contents.forEach((content, i) => {
614
- if (i > 0) resourceText += '\\n\\n---\\n\\n';
615
- resourceText += 'URI: ' + content.uri + '\\n';
616
- resourceText += 'MIME Type: ' + content.mimeType + '\\n\\n';
617
-
618
- if (content.text) {
619
- let processedText = content.text;
620
-
621
- // Handle JSON content more intelligently
622
- if (content.mimeType === 'application/json') {
623
- if (typeof processedText !== 'string') {
624
- processedText = JSON.stringify(processedText, null, 2);
625
- }
626
- }
627
- resourceText += processedText;
628
- } else if (content.blob) {
629
- resourceText += '[Binary content: ' + content.blob.length + ' bytes]';
630
- } else {
631
- resourceText += JSON.stringify(content, null, 2);
632
- }
633
- });
634
-
635
- loadingSpinner.style.display = 'none';
636
- resourceContent.style.display = 'block';
637
- resourceContent.innerHTML = '<pre class="json-content">' + resourceText + '</pre>';
638
- addCopyButton(resourceContent.querySelector('.json-content'));
639
- } catch (error) {
640
- loadingSpinner.style.display = 'none';
641
- resourceContent.style.display = 'block';
642
- resourceContent.innerHTML = '<div class="error-message">Failed to load resource: ' + error.message + '</div>';
643
- }
644
- }
645
- } else {
646
- // Hide the detail row
647
- detailRow.style.display = 'none';
648
- toggleLinkDetails.textContent = 'details';
649
- toggleLinkResource.textContent = 'resource';
650
- }
651
- }
652
-
653
- // Health Check Modal
654
- async function openHealthCheckModal() {
655
- const modal = document.getElementById('health-modal');
656
- const loading = document.getElementById('health-loading');
657
- const result = document.getElementById('health-result');
658
- const error = document.getElementById('health-error');
659
-
660
- // Show modal with loading state
661
- modal.style.display = 'flex';
662
- loading.style.display = 'block';
663
- result.style.display = 'none';
664
- error.style.display = 'none';
665
-
666
- try {
667
- const response = await fetch('/health');
668
-
669
- if (!response.ok) {
670
- let errorData = ''
671
- try {
672
- errorData = await response.text();
673
- } catch {
674
- //
675
- }
676
- errorData = [response.statusText || '', errorData].join('. ')
677
- throw new Error('HTTP ' + response.status + (errorData ? ': ' + errorData : ''));
678
-
679
- throw new Error('HTTP ' + response.status + ': ' + response.statusText);
680
- }
681
-
682
- const data = await response.json();
683
-
684
- // Hide loading and show result
685
- loading.style.display = 'none';
686
- result.style.display = 'block';
687
- result.textContent = JSON.stringify(data, null, 2);
688
- addCopyButton(result);
689
- } catch (err) {
690
- // Hide loading and show error
691
- loading.style.display = 'none';
692
- error.style.display = 'block';
693
- error.textContent = 'Error: ' + (err.message || 'Failed to fetch health check data');
694
- }
695
- }
696
-
697
- // Copy to clipboard functionality
698
- function addCopyButton(contentElement) {
699
- if (!contentElement || contentElement.hasAttribute('data-copy-added')) {
700
- return;
701
- }
702
-
703
- contentElement.setAttribute('data-copy-added', 'true');
704
-
705
- const copyButton = document.createElement('button');
706
- copyButton.className = 'copy-button';
707
- copyButton.innerHTML = '📋';
708
- copyButton.title = 'Copy to clipboard';
709
- copyButton.setAttribute('aria-label', 'Copy to clipboard');
710
-
711
- const notification = document.createElement('div');
712
- notification.className = 'copy-notification';
713
- notification.textContent = 'Copied';
714
-
715
- contentElement.appendChild(copyButton);
716
- contentElement.appendChild(notification);
717
-
718
- copyButton.addEventListener('click', async function() {
719
- let textToCopy = contentElement.textContent || contentElement.innerText;
720
- textToCopy = textToCopy.replace(/📋Copied/, '')
721
- try {
722
- await navigator.clipboard.writeText(textToCopy);
723
-
724
- // Show notification
725
- notification.classList.add('show');
726
-
727
- // Hide notification after 1 second
728
- setTimeout(() => {
729
- notification.classList.remove('show');
730
- }, 1000);
731
-
732
- } catch (err) {
733
- // Fallback for browsers that don't support clipboard API
734
- const textArea = document.createElement('textarea');
735
- textArea.value = textToCopy;
736
- textArea.style.position = 'fixed';
737
- textArea.style.opacity = '0';
738
- document.body.appendChild(textArea);
739
- textArea.focus();
740
- textArea.select();
741
-
742
- try {
743
- document.execCommand('copy');
744
-
745
- // Show notification
746
- notification.classList.add('show');
747
-
748
- // Hide notification after 1 second
749
- setTimeout(() => {
750
- notification.classList.remove('show');
751
- }, 1000);
752
- } catch (fallbackErr) {
753
- console.error('Failed to copy text:', fallbackErr);
754
- }
755
-
756
- document.body.removeChild(textArea);
757
- }
758
- });
759
- }
760
-
761
- // Close modal when clicking outside
762
- document.addEventListener('click', function(event) {
763
- if (event.target.classList.contains('modal-overlay')) {
764
- const modalId = event.target.id;
765
- const sectionName = modalId.replace('-modal', '');
766
- closeModal(sectionName);
767
- }
768
- });
769
- </script>
770
- </body>
771
- </html>`;
772
- };
773
- //# sourceMappingURL=render.js.map