@softtechai/quickmcp 1.0.16 → 1.1.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.
Files changed (417) hide show
  1. package/dist/auth/auth-utils.d.ts +130 -0
  2. package/dist/auth/auth-utils.d.ts.map +1 -0
  3. package/dist/auth/auth-utils.js +600 -0
  4. package/dist/auth/auth-utils.js.map +1 -0
  5. package/dist/auth/jwks-provider.d.ts +9 -0
  6. package/dist/auth/jwks-provider.d.ts.map +1 -0
  7. package/dist/auth/jwks-provider.js +56 -0
  8. package/dist/auth/jwks-provider.js.map +1 -0
  9. package/dist/auth/token-utils.d.ts +40 -0
  10. package/dist/auth/token-utils.d.ts.map +1 -0
  11. package/dist/auth/token-utils.js +162 -0
  12. package/dist/auth/token-utils.js.map +1 -0
  13. package/dist/client/MCPClient.js +5 -4
  14. package/dist/client/MCPClient.js.map +1 -1
  15. package/dist/config/auth-config.d.ts +16 -0
  16. package/dist/config/auth-config.d.ts.map +1 -0
  17. package/dist/config/auth-config.js +107 -0
  18. package/dist/config/auth-config.js.map +1 -0
  19. package/dist/constant/constant.d.ts +20 -0
  20. package/dist/constant/constant.d.ts.map +1 -0
  21. package/dist/constant/constant.js +24 -0
  22. package/dist/constant/constant.js.map +1 -0
  23. package/dist/database/async-datastore.d.ts +6 -0
  24. package/dist/database/async-datastore.d.ts.map +1 -0
  25. package/dist/database/async-datastore.js +15 -0
  26. package/dist/database/async-datastore.js.map +1 -0
  27. package/dist/database/database-utils.d.ts +6 -0
  28. package/dist/database/database-utils.d.ts.map +1 -0
  29. package/dist/database/database-utils.js +29 -0
  30. package/dist/database/database-utils.js.map +1 -0
  31. package/dist/database/datastore.d.ts +164 -0
  32. package/dist/database/datastore.d.ts.map +1 -0
  33. package/dist/{parsers/types/index.js → database/datastore.js} +1 -0
  34. package/dist/database/datastore.js.map +1 -0
  35. package/dist/database/factory.d.ts +4 -0
  36. package/dist/database/factory.d.ts.map +1 -0
  37. package/dist/database/factory.js +32 -0
  38. package/dist/database/factory.js.map +1 -0
  39. package/dist/database/jdbc-manager.d.ts +49 -0
  40. package/dist/database/jdbc-manager.d.ts.map +1 -0
  41. package/dist/database/jdbc-manager.js +50 -0
  42. package/dist/database/jdbc-manager.js.map +1 -0
  43. package/dist/database/sqlite-manager.d.ts +46 -44
  44. package/dist/database/sqlite-manager.d.ts.map +1 -1
  45. package/dist/database/sqlite-manager.js +492 -42
  46. package/dist/database/sqlite-manager.js.map +1 -1
  47. package/dist/database/supabase-manager.d.ts +58 -0
  48. package/dist/database/supabase-manager.d.ts.map +1 -0
  49. package/dist/database/supabase-manager.js +432 -0
  50. package/dist/database/supabase-manager.js.map +1 -0
  51. package/dist/generators/MCPServerGenerator.d.ts +103 -20
  52. package/dist/generators/MCPServerGenerator.d.ts.map +1 -1
  53. package/dist/generators/MCPServerGenerator.js +6930 -128
  54. package/dist/generators/MCPServerGenerator.js.map +1 -1
  55. package/dist/index.d.ts +0 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +8 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/integrated-mcp-server-new.d.ts +14 -2
  60. package/dist/integrated-mcp-server-new.d.ts.map +1 -1
  61. package/dist/integrated-mcp-server-new.js +270 -180
  62. package/dist/integrated-mcp-server-new.js.map +1 -1
  63. package/dist/mcp-core/McpCoreService.d.ts +63 -0
  64. package/dist/mcp-core/McpCoreService.d.ts.map +1 -0
  65. package/dist/mcp-core/McpCoreService.js +492 -0
  66. package/dist/mcp-core/McpCoreService.js.map +1 -0
  67. package/dist/parsers/CsvParser.d.ts +1 -1
  68. package/dist/parsers/CsvParser.d.ts.map +1 -1
  69. package/dist/parsers/CsvParser.js +3 -2
  70. package/dist/parsers/CsvParser.js.map +1 -1
  71. package/dist/parsers/DatabaseParser.d.ts.map +1 -1
  72. package/dist/parsers/DatabaseParser.js +9 -8
  73. package/dist/parsers/DatabaseParser.js.map +1 -1
  74. package/dist/parsers/ExcelParser.d.ts +15 -0
  75. package/dist/parsers/ExcelParser.d.ts.map +1 -1
  76. package/dist/parsers/ExcelParser.js +287 -21
  77. package/dist/parsers/ExcelParser.js.map +1 -1
  78. package/dist/parsers/WebPageParser.d.ts +5 -0
  79. package/dist/parsers/WebPageParser.d.ts.map +1 -0
  80. package/dist/parsers/WebPageParser.js +35 -0
  81. package/dist/parsers/WebPageParser.js.map +1 -0
  82. package/dist/parsers/index.d.ts +3 -2
  83. package/dist/parsers/index.d.ts.map +1 -1
  84. package/dist/parsers/index.js +19 -16
  85. package/dist/parsers/index.js.map +1 -1
  86. package/dist/server/api/askApi.d.ts +41 -0
  87. package/dist/server/api/askApi.d.ts.map +1 -0
  88. package/dist/server/api/askApi.js +479 -0
  89. package/dist/server/api/askApi.js.map +1 -0
  90. package/dist/server/api/authApi.d.ts +101 -0
  91. package/dist/server/api/authApi.d.ts.map +1 -0
  92. package/dist/server/api/authApi.js +1472 -0
  93. package/dist/server/api/authApi.js.map +1 -0
  94. package/dist/server/api/authProperty.d.ts +18 -0
  95. package/dist/server/api/authProperty.d.ts.map +1 -0
  96. package/dist/server/api/authProperty.js +41 -0
  97. package/dist/server/api/authProperty.js.map +1 -0
  98. package/dist/server/api/configApi.d.ts +15 -0
  99. package/dist/server/api/configApi.d.ts.map +1 -0
  100. package/dist/server/api/configApi.js +42 -0
  101. package/dist/server/api/configApi.js.map +1 -0
  102. package/dist/server/api/databaseApi.d.ts +14 -0
  103. package/dist/server/api/databaseApi.d.ts.map +1 -0
  104. package/dist/server/api/databaseApi.js +111 -0
  105. package/dist/server/api/databaseApi.js.map +1 -0
  106. package/dist/server/api/directoryApi.d.ts +9 -0
  107. package/dist/server/api/directoryApi.d.ts.map +1 -0
  108. package/dist/server/api/directoryApi.js +103 -0
  109. package/dist/server/api/directoryApi.js.map +1 -0
  110. package/dist/server/api/generateApi.d.ts +24 -0
  111. package/dist/server/api/generateApi.d.ts.map +1 -0
  112. package/dist/server/api/generateApi.js +457 -0
  113. package/dist/server/api/generateApi.js.map +1 -0
  114. package/dist/server/api/healthApi.d.ts +9 -0
  115. package/dist/server/api/healthApi.d.ts.map +1 -0
  116. package/dist/server/api/healthApi.js +15 -0
  117. package/dist/server/api/healthApi.js.map +1 -0
  118. package/dist/server/api/indexApi.d.ts +21 -0
  119. package/dist/server/api/indexApi.d.ts.map +1 -0
  120. package/dist/server/api/indexApi.js +61 -0
  121. package/dist/server/api/indexApi.js.map +1 -0
  122. package/dist/server/api/logsApi.d.ts +12 -0
  123. package/dist/server/api/logsApi.d.ts.map +1 -0
  124. package/dist/server/api/logsApi.js +37 -0
  125. package/dist/server/api/logsApi.js.map +1 -0
  126. package/dist/server/api/mcpApi.d.ts +20 -0
  127. package/dist/server/api/mcpApi.d.ts.map +1 -0
  128. package/dist/server/api/mcpApi.js +120 -0
  129. package/dist/server/api/mcpApi.js.map +1 -0
  130. package/dist/server/api/nameApi.d.ts +21 -0
  131. package/dist/server/api/nameApi.d.ts.map +1 -0
  132. package/dist/server/api/nameApi.js +42 -0
  133. package/dist/server/api/nameApi.js.map +1 -0
  134. package/dist/server/api/parseApi.d.ts +9 -0
  135. package/dist/server/api/parseApi.d.ts.map +1 -0
  136. package/dist/server/api/parseApi.js +3245 -0
  137. package/dist/server/api/parseApi.js.map +1 -0
  138. package/dist/server/api/serverApi.d.ts +44 -0
  139. package/dist/server/api/serverApi.d.ts.map +1 -0
  140. package/dist/server/api/serverApi.js +417 -0
  141. package/dist/server/api/serverApi.js.map +1 -0
  142. package/dist/{dynamic-mcp-executor.d.ts → server/dynamic-mcp-executor.d.ts} +4 -5
  143. package/dist/server/dynamic-mcp-executor.d.ts.map +1 -0
  144. package/dist/server/dynamic-mcp-executor.js +62 -0
  145. package/dist/server/dynamic-mcp-executor.js.map +1 -0
  146. package/dist/server/port-utils.d.ts +14 -0
  147. package/dist/server/port-utils.d.ts.map +1 -0
  148. package/dist/server/port-utils.js +31 -0
  149. package/dist/server/port-utils.js.map +1 -0
  150. package/dist/server/server-utils.d.ts +13 -0
  151. package/dist/server/server-utils.d.ts.map +1 -0
  152. package/dist/server/server-utils.js +72 -0
  153. package/dist/server/server-utils.js.map +1 -0
  154. package/dist/{web → server}/server.d.ts +1 -0
  155. package/dist/server/server.d.ts.map +1 -0
  156. package/dist/server/server.js +535 -0
  157. package/dist/server/server.js.map +1 -0
  158. package/dist/server/tool-executer.d.ts +101 -0
  159. package/dist/server/tool-executer.d.ts.map +1 -0
  160. package/dist/server/tool-executer.js +6198 -0
  161. package/dist/server/tool-executer.js.map +1 -0
  162. package/dist/types/index.d.ts +1197 -4
  163. package/dist/types/index.d.ts.map +1 -1
  164. package/dist/types/index.js +1028 -0
  165. package/dist/types/index.js.map +1 -1
  166. package/dist/upload/upload-utils.d.ts +4 -0
  167. package/dist/upload/upload-utils.d.ts.map +1 -0
  168. package/dist/upload/upload-utils.js +29 -0
  169. package/dist/upload/upload-utils.js.map +1 -0
  170. package/dist/utils/deployment-util.d.ts +14 -0
  171. package/dist/utils/deployment-util.d.ts.map +1 -0
  172. package/dist/utils/deployment-util.js +46 -0
  173. package/dist/utils/deployment-util.js.map +1 -0
  174. package/dist/utils/logger.d.ts +15 -0
  175. package/dist/utils/logger.d.ts.map +1 -0
  176. package/dist/utils/logger.js +56 -0
  177. package/dist/utils/logger.js.map +1 -0
  178. package/package.json +18 -6
  179. package/quickmcp-direct-stdio.js +176 -187
  180. package/src/web/public/app.js +15370 -1471
  181. package/src/web/public/authorization.html +868 -0
  182. package/src/web/public/database-tables.html +283 -547
  183. package/src/web/public/how-to-use.html +446 -462
  184. package/src/web/public/how-to-use.js +4 -4
  185. package/src/web/public/images/app/activepieces.png +0 -0
  186. package/src/web/public/images/app/airtable.png +0 -0
  187. package/src/web/public/images/app/androidstudio.png +0 -0
  188. package/src/web/public/images/app/antigravity.png +0 -0
  189. package/src/web/public/images/app/applenotes.png +0 -0
  190. package/src/web/public/images/app/applereminders.png +0 -0
  191. package/src/web/public/images/app/asana.png +0 -0
  192. package/src/web/public/images/app/azureai.png +0 -0
  193. package/src/web/public/images/app/bash.png +0 -0
  194. package/src/web/public/images/app/bearnotes.png +0 -0
  195. package/src/web/public/images/app/bitbucket.png +0 -0
  196. package/src/web/public/images/app/claude.png +0 -0
  197. package/src/web/public/images/app/cli.png +0 -0
  198. package/src/web/public/images/app/clickup.png +0 -0
  199. package/src/web/public/images/app/cohere.png +0 -0
  200. package/src/web/public/images/app/confluence.png +0 -0
  201. package/src/web/public/images/app/confluence2.png +0 -0
  202. package/src/web/public/images/app/curl.png +0 -0
  203. package/src/web/public/images/app/curl_mini.png +0 -0
  204. package/src/web/public/images/app/cursor.png +0 -0
  205. package/src/web/public/images/app/db2.png +0 -0
  206. package/src/web/public/images/app/deepseek.png +0 -0
  207. package/src/web/public/images/app/discord.png +0 -0
  208. package/src/web/public/images/app/docker.png +0 -0
  209. package/src/web/public/images/app/dockerhub.png +0 -0
  210. package/src/web/public/images/app/dropbox.png +0 -0
  211. package/src/web/public/images/app/elasticsearch.png +0 -0
  212. package/src/web/public/images/app/facebook.png +0 -0
  213. package/src/web/public/images/app/falai.png +0 -0
  214. package/src/web/public/images/app/fireworks.png +0 -0
  215. package/src/web/public/images/app/gdrive.png +0 -0
  216. package/src/web/public/images/app/gemini.png +0 -0
  217. package/src/web/public/images/app/github.png +0 -0
  218. package/src/web/public/images/app/githubcopilot.png +0 -0
  219. package/src/web/public/images/app/gitlab.png +0 -0
  220. package/src/web/public/images/app/gmail.png +0 -0
  221. package/src/web/public/images/app/googlecalender.png +0 -0
  222. package/src/web/public/images/app/googledocs.png +0 -0
  223. package/src/web/public/images/app/googlesheets.png +0 -0
  224. package/src/web/public/images/app/gradle.png +0 -0
  225. package/src/web/public/images/app/grafana.png +0 -0
  226. package/src/web/public/images/app/graphql.png +0 -0
  227. package/src/web/public/images/app/grok.png +0 -0
  228. package/src/web/public/images/app/groq.png +0 -0
  229. package/src/web/public/images/app/hazelcast.png +0 -0
  230. package/src/web/public/images/app/huggingface.png +0 -0
  231. package/src/web/public/images/app/imessage.png +0 -0
  232. package/src/web/public/images/app/instagram.png +0 -0
  233. package/src/web/public/images/app/intellij.png +0 -0
  234. package/src/web/public/images/app/jenkins.png +0 -0
  235. package/src/web/public/images/app/jira.png +0 -0
  236. package/src/web/public/images/app/kafka.png +0 -0
  237. package/src/web/public/images/app/kubernetes.png +0 -0
  238. package/src/web/public/images/app/linear.png +0 -0
  239. package/src/web/public/images/app/linkedin.png +0 -0
  240. package/src/web/public/images/app/llama.png +0 -0
  241. package/src/web/public/images/app/make.png +0 -0
  242. package/src/web/public/images/app/maven.png +0 -0
  243. package/src/web/public/images/app/mcp.png +0 -0
  244. package/src/web/public/images/app/microsoftteams.png +0 -0
  245. package/src/web/public/images/app/mistral.png +0 -0
  246. package/src/web/public/images/app/monday.png +0 -0
  247. package/src/web/public/images/app/mongodb.png +0 -0
  248. package/src/web/public/images/app/mssql.png +0 -0
  249. package/src/web/public/images/app/mysql.png +0 -0
  250. package/src/web/public/images/app/n8n.png +0 -0
  251. package/src/web/public/images/app/notion.png +0 -0
  252. package/src/web/public/images/app/npm.png +0 -0
  253. package/src/web/public/images/app/nuget.png +0 -0
  254. package/src/web/public/images/app/obsidian.png +0 -0
  255. package/src/web/public/images/app/openai.png +0 -0
  256. package/src/web/public/images/app/openrouter.png +0 -0
  257. package/src/web/public/images/app/opensearch.png +0 -0
  258. package/src/web/public/images/app/openshift.png +0 -0
  259. package/src/web/public/images/app/oracle.png +0 -0
  260. package/src/web/public/images/app/perplexity.png +0 -0
  261. package/src/web/public/images/app/pipedream.png +0 -0
  262. package/src/web/public/images/app/postgresql.png +0 -0
  263. package/src/web/public/images/app/powershell.png +0 -0
  264. package/src/web/public/images/app/prometheus.png +0 -0
  265. package/src/web/public/images/app/reddit.png +0 -0
  266. package/src/web/public/images/app/redis.png +0 -0
  267. package/src/web/public/images/app/rss.png +0 -0
  268. package/src/web/public/images/app/signal.png +0 -0
  269. package/src/web/public/images/app/slack.png +0 -0
  270. package/src/web/public/images/app/soap.png +0 -0
  271. package/src/web/public/images/app/sqlite.png +0 -0
  272. package/src/web/public/images/app/supabase.png +0 -0
  273. package/src/web/public/images/app/telegram.png +0 -0
  274. package/src/web/public/images/app/things3.png +0 -0
  275. package/src/web/public/images/app/threads.png +0 -0
  276. package/src/web/public/images/app/tiktok.png +0 -0
  277. package/src/web/public/images/app/together.png +0 -0
  278. package/src/web/public/images/app/trello.png +0 -0
  279. package/src/web/public/images/app/vscode.png +0 -0
  280. package/src/web/public/images/app/webhook.png +0 -0
  281. package/src/web/public/images/app/webpage.png +0 -0
  282. package/src/web/public/images/app/whatsappbusiness.png +0 -0
  283. package/src/web/public/images/app/windsorf.png +0 -0
  284. package/src/web/public/images/app/x.png +0 -0
  285. package/src/web/public/images/app/youtube.png +0 -0
  286. package/src/web/public/images/app/zapier.png +0 -0
  287. package/src/web/public/images/app/zededitor.png +0 -0
  288. package/src/web/public/images/app/zoom.png +0 -0
  289. package/src/web/public/images/avatar-anon.svg +4 -0
  290. package/src/web/public/images/favicon.png +0 -0
  291. package/src/web/public/images/install/chatgpt-web/step0.png +0 -0
  292. package/src/web/public/images/install/chatgpt-web/step1.png +0 -0
  293. package/src/web/public/images/install/chatgpt-web/step2.png +0 -0
  294. package/src/web/public/images/install/chatgpt-web/step3.png +0 -0
  295. package/src/web/public/images/install/chatgpt-web/step4.png +0 -0
  296. package/src/web/public/images/install/chatgpt-web/step5.png +0 -0
  297. package/src/web/public/images/readme/1-generate-servers.png +0 -0
  298. package/src/web/public/images/readme/2-database-connection.png +0 -0
  299. package/src/web/public/images/readme/2-file-upload.png +0 -0
  300. package/src/web/public/images/readme/3-data-preview.png +0 -0
  301. package/src/web/public/images/readme/4-data-preview2.png +0 -0
  302. package/src/web/public/images/readme/5-server-configuration.png +0 -0
  303. package/src/web/public/images/readme/6-server-generated-modal.png +0 -0
  304. package/src/web/public/images/readme/7-generated-servers.png +0 -0
  305. package/src/web/public/images/readme/8-generated-servers-view-details.png +0 -0
  306. package/src/web/public/images/readme/Screenshot 2025-10-09 at 20.23.51.png +0 -0
  307. package/src/web/public/images/readme/Screenshot 2025-10-09 at 20.24.59.png +0 -0
  308. package/src/web/public/images/readme/Screenshot 2025-10-09 at 20.25.05.png +0 -0
  309. package/src/web/public/images/readme/Screenshot 2025-10-09 at 20.25.14.png +0 -0
  310. package/src/web/public/images/readme/Screenshot 2025-10-09 at 20.25.21.png +0 -0
  311. package/src/web/public/images/readme/Screenshot 2025-10-09 at 20.25.36.png +0 -0
  312. package/src/web/public/index.html +4685 -488
  313. package/src/web/public/landing.html +1638 -0
  314. package/src/web/public/logger.js +31 -0
  315. package/src/web/public/login.html +372 -0
  316. package/src/web/public/manage-servers.html +121 -188
  317. package/src/web/public/pricing.html +537 -0
  318. package/src/web/public/quick-ask.html +133 -0
  319. package/src/web/public/quickmcp-styles.css +708 -0
  320. package/src/web/public/roles.html +177 -0
  321. package/src/web/public/shared.js +736 -3
  322. package/src/web/public/sidebar.js +414 -0
  323. package/src/web/public/test-servers.html +605 -221
  324. package/src/web/public/users.html +191 -0
  325. package/dist/client/MCPClientUnified.d.ts +0 -31
  326. package/dist/client/MCPClientUnified.d.ts.map +0 -1
  327. package/dist/client/MCPClientUnified.js +0 -275
  328. package/dist/client/MCPClientUnified.js.map +0 -1
  329. package/dist/client/MCPTestRunnerUnified.d.ts +0 -48
  330. package/dist/client/MCPTestRunnerUnified.d.ts.map +0 -1
  331. package/dist/client/MCPTestRunnerUnified.js +0 -183
  332. package/dist/client/MCPTestRunnerUnified.js.map +0 -1
  333. package/dist/database/json-manager.d.ts +0 -55
  334. package/dist/database/json-manager.d.ts.map +0 -1
  335. package/dist/database/json-manager.js +0 -128
  336. package/dist/database/json-manager.js.map +0 -1
  337. package/dist/dynamic-mcp-executor.d.ts.map +0 -1
  338. package/dist/dynamic-mcp-executor.js +0 -274
  339. package/dist/dynamic-mcp-executor.js.map +0 -1
  340. package/dist/generators/MCPServerGenerator-new.d.ts +0 -37
  341. package/dist/generators/MCPServerGenerator-new.d.ts.map +0 -1
  342. package/dist/generators/MCPServerGenerator-new.js +0 -287
  343. package/dist/generators/MCPServerGenerator-new.js.map +0 -1
  344. package/dist/generators/database/sqlite-manager.d.ts +0 -52
  345. package/dist/generators/database/sqlite-manager.js +0 -143
  346. package/dist/generators/generators/MCPServerGenerator.d.ts +0 -37
  347. package/dist/generators/generators/MCPServerGenerator.js +0 -396
  348. package/dist/integrated-mcp-server.d.ts +0 -25
  349. package/dist/integrated-mcp-server.d.ts.map +0 -1
  350. package/dist/integrated-mcp-server.js +0 -541
  351. package/dist/integrated-mcp-server.js.map +0 -1
  352. package/dist/mcp-inspector-server.d.ts +0 -3
  353. package/dist/mcp-inspector-server.d.ts.map +0 -1
  354. package/dist/mcp-inspector-server.js +0 -119
  355. package/dist/mcp-inspector-server.js.map +0 -1
  356. package/dist/mcp-sdk-server.d.ts +0 -3
  357. package/dist/mcp-sdk-server.d.ts.map +0 -1
  358. package/dist/mcp-sdk-server.js +0 -90
  359. package/dist/mcp-sdk-server.js.map +0 -1
  360. package/dist/mcp-server.d.ts +0 -3
  361. package/dist/mcp-server.d.ts.map +0 -1
  362. package/dist/mcp-server.js +0 -300
  363. package/dist/mcp-server.js.map +0 -1
  364. package/dist/parsers/parsers/ExcelParser.js +0 -118
  365. package/dist/quickmcp-unified-bridge.d.ts +0 -13
  366. package/dist/quickmcp-unified-bridge.d.ts.map +0 -1
  367. package/dist/quickmcp-unified-bridge.js +0 -176
  368. package/dist/quickmcp-unified-bridge.js.map +0 -1
  369. package/dist/sqlite-manager.js +0 -145
  370. package/dist/test-app.d.ts +0 -2
  371. package/dist/test-app.d.ts.map +0 -1
  372. package/dist/test-app.js +0 -119
  373. package/dist/test-app.js.map +0 -1
  374. package/dist/transport/base-transport.d.ts +0 -21
  375. package/dist/transport/base-transport.d.ts.map +0 -1
  376. package/dist/transport/base-transport.js +0 -16
  377. package/dist/transport/base-transport.js.map +0 -1
  378. package/dist/transport/index.d.ts +0 -10
  379. package/dist/transport/index.d.ts.map +0 -1
  380. package/dist/transport/index.js +0 -12
  381. package/dist/transport/index.js.map +0 -1
  382. package/dist/transport/sse-transport.d.ts +0 -13
  383. package/dist/transport/sse-transport.d.ts.map +0 -1
  384. package/dist/transport/sse-transport.js +0 -106
  385. package/dist/transport/sse-transport.js.map +0 -1
  386. package/dist/transport/stdio-transport.d.ts +0 -8
  387. package/dist/transport/stdio-transport.d.ts.map +0 -1
  388. package/dist/transport/stdio-transport.js +0 -53
  389. package/dist/transport/stdio-transport.js.map +0 -1
  390. package/dist/transport/streamable-http-transport.d.ts +0 -15
  391. package/dist/transport/streamable-http-transport.d.ts.map +0 -1
  392. package/dist/transport/streamable-http-transport.js +0 -151
  393. package/dist/transport/streamable-http-transport.js.map +0 -1
  394. package/dist/web/client/MCPClient.js +0 -348
  395. package/dist/web/client/MCPTestRunner.js +0 -317
  396. package/dist/web/database/json-manager.js +0 -124
  397. package/dist/web/database/sqlite-manager.js +0 -146
  398. package/dist/web/dynamic-mcp-executor.js +0 -443
  399. package/dist/web/generators/MCPServerGenerator-new.js +0 -284
  400. package/dist/web/generators/MCPServerGenerator.js +0 -566
  401. package/dist/web/integrated-mcp-server-new.js +0 -394
  402. package/dist/web/parsers/CsvParser.js +0 -144
  403. package/dist/web/parsers/DatabaseParser.js +0 -637
  404. package/dist/web/parsers/ExcelParser.js +0 -180
  405. package/dist/web/parsers/index.js +0 -152
  406. package/dist/web/server.d.ts.map +0 -1
  407. package/dist/web/server.js +0 -790
  408. package/dist/web/server.js.map +0 -1
  409. package/dist/web/types/index.js +0 -2
  410. package/dist/web/web/server.js +0 -860
  411. package/src/web/public/modern-styles.css +0 -946
  412. package/src/web/public/shared-styles.css +0 -2091
  413. /package/src/web/public/images/{1-claude-quickmcp-stdio.png → readme/1-claude-quickmcp-stdio.png} +0 -0
  414. /package/src/web/public/images/{2-claude-tools.png → readme/2-claude-tools.png} +0 -0
  415. /package/src/web/public/images/{3-claude-developer-settings.png → readme/3-claude-developer-settings.png} +0 -0
  416. /package/src/web/public/images/{4-claude-config.png → readme/4-claude-config.png} +0 -0
  417. /package/src/web/public/images/{5-claude-config-edit.png → readme/5-claude-config-edit.png} +0 -0
@@ -0,0 +1,868 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="h-full">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>QuickMCP - Authorization</title>
7
+
8
+ <link rel="icon" type="image/png" href="/images/favicon.png">
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
11
+ <link rel="stylesheet" href="quickmcp-styles.css">
12
+ </head>
13
+ <body class="h-screen flex flex-col bg-gradient-to-br from-slate-50 to-slate-100 overflow-hidden text-slate-900">
14
+ <header class="backdrop-blur-sm bg-white/80 border-b border-slate-200/60 shadow-sm relative z-50 h-16 flex-shrink-0 flex items-center justify-between px-6 py-3">
15
+ <div class="flex items-center gap-3">
16
+ <div class="w-9 h-9 rounded-lg bg-blue-600 text-white flex items-center justify-center shadow-lg shadow-blue-500/25">
17
+ <i class="fas fa-rocket text-lg"></i>
18
+ </div>
19
+ <div>
20
+ <h1 class="text-xl font-bold gradient-text leading-tight">QuickMCP</h1>
21
+ <p class="text-xs text-slate-500 font-medium">Authorization</p>
22
+ </div>
23
+ </div>
24
+ <div class="flex items-center gap-3">
25
+ <div class="w-8 h-8 rounded-full bg-gradient-to-tr from-blue-500 to-purple-500 text-white flex items-center justify-center text-sm font-bold shadow-md" data-user-avatar>G</div>
26
+ <button id="openSidebar" class="lg:hidden p-2 rounded-lg hover:bg-slate-100 transition-colors text-slate-500">
27
+ <i class="fas fa-bars"></i>
28
+ </button>
29
+ </div>
30
+ </header>
31
+
32
+ <div class="app-main-layout flex flex-1 overflow-x-hidden">
33
+ <div id="sidebar" class="w-72 bg-white/95 backdrop-blur-sm border-r border-slate-200/60 flex flex-col flex-shrink-0 z-[60] fixed inset-y-0 left-0 transform -translate-x-full lg:translate-x-0 lg:top-0 lg:h-screen transition-transform duration-300 ease-in-out h-full pt-16 lg:pt-0"></div>
34
+ <div id="sidebarOverlay" class="fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-30 lg:hidden opacity-0 invisible transition-all duration-300"></div>
35
+
36
+ <main class="flex-1 overflow-y-auto p-8">
37
+ <div class="max-w-6xl mx-auto space-y-6">
38
+ <div class="text-center mb-10">
39
+ <h2 class="text-3xl font-bold text-slate-900">MCP Authorization</h2>
40
+ <p id="authSummary" class="text-slate-600 mt-1"></p>
41
+ </div>
42
+
43
+ <section class="card p-0 overflow-hidden">
44
+ <div class="border-b border-slate-200 bg-slate-50/80">
45
+ <div class="px-5 pt-4">
46
+ <nav class="flex items-end gap-1" aria-label="Authorization tabs">
47
+ <button id="tabToken" class="px-4 py-2.5 rounded-t-lg text-sm font-semibold border border-slate-200 border-b-white bg-white text-slate-900 -mb-px">Token</button>
48
+ <button id="tabPolicy" class="px-4 py-2.5 rounded-t-lg text-sm font-semibold border border-transparent text-slate-600 hover:text-blue-700 hover:bg-white/70">Policy</button>
49
+ </nav>
50
+ </div>
51
+ </div>
52
+
53
+ <div id="tokenTabPanel" class="p-5 space-y-6">
54
+ <section class="card p-6 space-y-5">
55
+ <div class="flex items-center justify-between">
56
+ <h3 class="text-lg font-semibold text-slate-900">Generate Token</h3>
57
+ <button id="generateTokenBtn" class="bg-blue-600 hover:bg-blue-700 text-white rounded-lg px-4 py-2 text-sm font-medium">Generate Token</button>
58
+ </div>
59
+
60
+ <div>
61
+ <label class="block text-sm text-slate-700 mb-1">Token Name</label>
62
+ <div class="relative">
63
+ <i class="fas fa-tag absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs"></i>
64
+ <input id="tokenName" class="input w-full pl-9" placeholder="e.g. Claude Desktop, Cursor, Windsurf" maxlength="120" required>
65
+ </div>
66
+ </div>
67
+
68
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
69
+ <div>
70
+ <label class="block text-sm text-slate-700 mb-1">User</label>
71
+ <div class="relative">
72
+ <i class="fas fa-user absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs"></i>
73
+ <select id="subjectUserSelect" class="input w-full pl-9 pr-9 appearance-none bg-white border-slate-200 hover:border-slate-300 focus:border-blue-400 shadow-sm"></select>
74
+ <i class="fas fa-chevron-down absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs pointer-events-none"></i>
75
+ </div>
76
+ </div>
77
+ <div>
78
+ <label class="block text-sm text-slate-700 mb-1">Token Expiration</label>
79
+ <div class="relative">
80
+ <i class="fas fa-clock absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs"></i>
81
+ <select id="tokenTtlPreset" class="input w-full pl-9 pr-9 appearance-none bg-white border-slate-200 hover:border-slate-300 focus:border-blue-400 shadow-sm">
82
+ <option value="never" selected>Never expires</option>
83
+ <option value="1m">1 minute</option>
84
+ <option value="5m">5 minutes</option>
85
+ <option value="15m">15 minutes</option>
86
+ <option value="30m">30 minutes</option>
87
+ <option value="1h">1 hour</option>
88
+ <option value="4h">4 hours</option>
89
+ <option value="12h">12 hours</option>
90
+ <option value="24h">24 hours</option>
91
+ <option value="1w">1 week</option>
92
+ <option value="2w">2 weeks</option>
93
+ <option value="1mo">1 month</option>
94
+ <option value="3mo">3 months</option>
95
+ <option value="6mo">6 months</option>
96
+ </select>
97
+ <i class="fas fa-chevron-down absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs pointer-events-none"></i>
98
+ </div>
99
+ </div>
100
+ </div>
101
+
102
+ <div id="treeSection">
103
+ <h4 class="font-medium text-slate-900 mb-2">MCP Access Tree</h4>
104
+ <p class="text-xs text-slate-500 mb-2">Use 3-state policy for each item: Inherit, Allow, Deny.</p>
105
+ <div id="mcpTree" class="max-h-[28rem] overflow-auto border border-slate-200 rounded-lg p-3 space-y-3 bg-white"></div>
106
+ </div>
107
+
108
+ <div class="relative">
109
+ <textarea id="generatedToken" rows="4" class="input w-full font-mono text-xs resize-none pr-12 pt-3" placeholder="Generated token will appear here." readonly></textarea>
110
+ <button
111
+ id="copyTokenBtn"
112
+ type="button"
113
+ class="absolute right-3 top-3 h-8 w-8 rounded-md border border-slate-200 text-slate-600 hover:border-blue-400 hover:text-blue-600 disabled:opacity-50 disabled:cursor-not-allowed"
114
+ title="Copy token"
115
+ aria-label="Copy token"
116
+ disabled
117
+ >
118
+ <i class="fas fa-copy text-sm"></i>
119
+ </button>
120
+ </div>
121
+ <p id="tokenMeta" class="text-xs text-slate-500"></p>
122
+ </section>
123
+
124
+ <section class="card p-6">
125
+ <div class="flex items-center justify-between mb-4">
126
+ <h3 class="text-lg font-semibold text-slate-900">Existing Tokens</h3>
127
+ <button id="refreshTokensBtn" class="px-3 py-2 rounded-lg border border-slate-200 text-slate-700 hover:border-blue-400 hover:text-blue-600 text-sm">Refresh</button>
128
+ </div>
129
+ <div id="tokenTableWrap" class="overflow-x-auto"></div>
130
+ </section>
131
+ </div>
132
+
133
+ <div id="policyTabPanel" class="p-5 space-y-6 hidden">
134
+ <section class="card p-6 space-y-5">
135
+ <div class="flex items-center justify-between">
136
+ <h3 class="text-lg font-semibold text-slate-900">Token Requirement Policy</h3>
137
+ <button id="saveTokenPolicyBtn" class="bg-blue-600 hover:bg-blue-700 text-white rounded-lg px-4 py-2 text-sm font-medium">Save Policy</button>
138
+ </div>
139
+ <p class="text-xs text-slate-500">Configure where token is required: Application, User, MCP Server, and Tool level.</p>
140
+ <div id="tokenPolicyTree" class="max-h-[28rem] overflow-auto border border-slate-200 rounded-lg p-3 space-y-3 bg-white"></div>
141
+ </section>
142
+ </div>
143
+ </div>
144
+ </section>
145
+ </div>
146
+ </main>
147
+ </div>
148
+
149
+ <div id="tokenModalOverlay" class="fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-[70] hidden"></div>
150
+ <div id="tokenModal" class="fixed inset-0 z-[80] hidden flex items-center justify-center p-4">
151
+ <div class="w-full max-w-2xl bg-white rounded-xl border border-slate-200 shadow-2xl">
152
+ <div class="px-5 py-4 border-b border-slate-200 flex items-center justify-between">
153
+ <h3 class="text-base font-semibold text-slate-900">Token</h3>
154
+ <button id="closeTokenModalBtn" class="h-8 w-8 inline-flex items-center justify-center rounded-md border border-slate-200 text-slate-600 hover:border-slate-300 hover:text-slate-800" title="Close">
155
+ <i class="fas fa-times text-sm"></i>
156
+ </button>
157
+ </div>
158
+ <div class="p-5 space-y-3">
159
+ <div class="relative">
160
+ <textarea id="tokenModalValue" rows="5" class="input w-full font-mono text-xs resize-none pr-24 pt-3" readonly></textarea>
161
+ <div class="absolute right-3 top-3 flex items-center gap-2">
162
+ <button id="toggleTokenMaskBtn" class="h-8 w-8 rounded-md border border-slate-200 text-slate-600 hover:border-blue-400 hover:text-blue-600" title="Show / Hide Token">
163
+ <i id="toggleTokenMaskIcon" class="fas fa-eye text-sm"></i>
164
+ </button>
165
+ <button id="copyTokenModalBtn" class="h-8 w-8 rounded-md border border-slate-200 text-slate-600 hover:border-blue-400 hover:text-blue-600" title="Copy Token">
166
+ <i class="fas fa-copy text-sm"></i>
167
+ </button>
168
+ </div>
169
+ </div>
170
+ <p id="tokenModalMeta" class="text-xs text-slate-500"></p>
171
+ </div>
172
+ </div>
173
+ </div>
174
+
175
+ <script src="logger.js"></script>
176
+ <script src="shared.js"></script>
177
+ <script src="sidebar.js"></script>
178
+ <script>
179
+ let authContext = { users: [], servers: [] };
180
+ let tokenPolicyState = {
181
+ globalRequireMcpToken: true,
182
+ userRules: {},
183
+ serverRules: {},
184
+ toolRules: {}
185
+ };
186
+ let tokenModalRawValue = '';
187
+ let tokenModalMasked = true;
188
+ let isSaasMode = false;
189
+
190
+ function byId(id) { return document.getElementById(id); }
191
+ function setAuthorizationTab(tab) {
192
+ if (isSaasMode && tab === 'policy') {
193
+ tab = 'token';
194
+ }
195
+ const isToken = tab === 'token';
196
+ byId('tokenTabPanel')?.classList.toggle('hidden', !isToken);
197
+ byId('policyTabPanel')?.classList.toggle('hidden', isToken);
198
+
199
+ const tabToken = byId('tabToken');
200
+ const tabPolicy = byId('tabPolicy');
201
+ if (tabToken) {
202
+ tabToken.className = isToken
203
+ ? 'px-4 py-2.5 rounded-t-lg text-sm font-semibold border border-slate-200 border-b-white bg-white text-slate-900 -mb-px'
204
+ : 'px-4 py-2.5 rounded-t-lg text-sm font-semibold border border-transparent text-slate-600 hover:text-blue-700 hover:bg-white/70';
205
+ }
206
+ if (tabPolicy && !isSaasMode) {
207
+ tabPolicy.className = !isToken
208
+ ? 'px-4 py-2.5 rounded-t-lg text-sm font-semibold border border-slate-200 border-b-white bg-white text-slate-900 -mb-px'
209
+ : 'px-4 py-2.5 rounded-t-lg text-sm font-semibold border border-transparent text-slate-600 hover:text-blue-700 hover:bg-white/70';
210
+ }
211
+ }
212
+
213
+ function applyAuthorizationMode(configData) {
214
+ const deployMode = String(configData?.deployMode || '').trim().toUpperCase();
215
+ isSaasMode = configData?.isSaasMode === true;
216
+ const tabPolicy = byId('tabPolicy');
217
+ const policyPanel = byId('policyTabPanel');
218
+ if (isSaasMode) {
219
+ tabPolicy?.classList.add('hidden');
220
+ policyPanel?.classList.add('hidden');
221
+ setAuthorizationTab('token');
222
+ } else {
223
+ tabPolicy?.classList.remove('hidden');
224
+ }
225
+ }
226
+
227
+ function refreshCopyButtonState() {
228
+ const btn = byId('copyTokenBtn');
229
+ const token = byId('generatedToken').value.trim();
230
+ btn.disabled = token.length === 0;
231
+ }
232
+
233
+ function normalizeTriStateValue(value) {
234
+ if (value === 'allow') return true;
235
+ if (value === 'deny') return false;
236
+ return null;
237
+ }
238
+
239
+ function maskTokenValue(token) {
240
+ const value = String(token || '');
241
+ if (!value) return '';
242
+ if (value.length <= 8) return '•'.repeat(value.length);
243
+ return `${value.slice(0, 4)}${'•'.repeat(Math.max(8, value.length - 8))}${value.slice(-4)}`;
244
+ }
245
+
246
+ function renderTokenModalValue() {
247
+ byId('tokenModalValue').value = tokenModalMasked ? maskTokenValue(tokenModalRawValue) : tokenModalRawValue;
248
+ byId('toggleTokenMaskIcon').className = tokenModalMasked ? 'fas fa-eye text-sm' : 'fas fa-eye-slash text-sm';
249
+ }
250
+
251
+ function openTokenModal(token, metaText = '') {
252
+ tokenModalRawValue = String(token || '');
253
+ tokenModalMasked = true;
254
+ renderTokenModalValue();
255
+ byId('tokenModalMeta').textContent = metaText || '';
256
+ byId('tokenModalOverlay').classList.remove('hidden');
257
+ byId('tokenModal').classList.remove('hidden');
258
+ }
259
+
260
+ function closeTokenModal() {
261
+ byId('tokenModalOverlay').classList.add('hidden');
262
+ byId('tokenModal').classList.add('hidden');
263
+ }
264
+
265
+ function collectTriStateRules(selector, attrName) {
266
+ const out = {};
267
+ document.querySelectorAll(selector).forEach((el) => {
268
+ const id = el.getAttribute(attrName);
269
+ if (!id) return;
270
+ out[id] = normalizeTriStateValue(el.value);
271
+ });
272
+ return out;
273
+ }
274
+
275
+ function triFromValue(value) {
276
+ if (value === 'allow') return true;
277
+ if (value === 'deny') return false;
278
+ return null;
279
+ }
280
+
281
+ function resolveTriValue(...values) {
282
+ for (const value of values) {
283
+ if (value === true || value === false) return value;
284
+ }
285
+ return null;
286
+ }
287
+
288
+ function serverOwnerFromId(serverId) {
289
+ const idx = String(serverId || '').indexOf('__');
290
+ if (idx <= 0) return '';
291
+ return String(serverId).slice(0, idx);
292
+ }
293
+
294
+ function getMcpDisplayName(server) {
295
+ const id = String(server?.id || '');
296
+ const rawName = String(server?.name || id || '');
297
+ const owner = serverOwnerFromId(id);
298
+ if (owner && rawName.startsWith(`${owner}__`)) return rawName.slice(owner.length + 2);
299
+ if (rawName.includes('__')) return rawName.split('__').slice(-1)[0];
300
+ return rawName;
301
+ }
302
+
303
+ function getMcpTypeIcon(type) {
304
+ const t = String(type || '').toLowerCase();
305
+ if (['mysql', 'postgresql', 'postgres', 'mssql', 'oracle', 'sqlite', 'mongodb', 'database'].includes(t)) return 'fa-database';
306
+ if (t === 'webpage' || t === 'webhook') return 'fa-rocket';
307
+ if (['rest', 'graphql', 'soap', 'rss', 'curl'].includes(t)) return 'fa-globe';
308
+ if (['docker', 'kubernetes', 'openshift', 'elasticsearch', 'opensearch', 'prometheus', 'grafana'].includes(t)) return 'fa-cubes';
309
+ if (['slack', 'discord', 'telegram', 'whatsappbusiness', 'x', 'facebook', 'instagram', 'tiktok', 'linkedin', 'reddit', 'youtube', 'threads'].includes(t)) return 'fa-comments';
310
+ if (['openai', 'claude', 'gemini', 'grok', 'falai', 'huggingface', 'llama', 'deepseek', 'azureopenai', 'mistral', 'cohere', 'perplexity', 'together', 'fireworks', 'groq', 'openrouter'].includes(t)) return 'fa-brain';
311
+ if (t === 'ftp' || t === 'localfs') return 'fa-folder-open';
312
+ return 'fa-server';
313
+ }
314
+
315
+ function renderUsers() {
316
+ const select = byId('subjectUserSelect');
317
+ const prev = select.value;
318
+ const options = (authContext.users || []).map((u) => `<option value="${u.username}">${u.username} (${u.role})</option>`);
319
+ select.innerHTML = options.join('');
320
+ if (prev && Array.from(select.options).some((o) => o.value === prev)) {
321
+ select.value = prev;
322
+ }
323
+ }
324
+
325
+ function renderTree() {
326
+ const root = byId('mcpTree');
327
+ const selectedSubjectUser = byId('subjectUserSelect').value || '';
328
+ const users = authContext.users || [];
329
+ const servers = authContext.servers || [];
330
+ const grouped = users.map((u) => ({
331
+ username: u.username,
332
+ role: u.role,
333
+ servers: servers.filter((s) => serverOwnerFromId(s.id) === u.username)
334
+ }));
335
+ const matchedCount = grouped.reduce((acc, item) => acc + (item.servers || []).length, 0);
336
+ if (matchedCount === 0 && selectedSubjectUser) {
337
+ const idx = grouped.findIndex((g) => g.username === selectedSubjectUser);
338
+ if (idx >= 0) grouped[idx].servers = servers;
339
+ }
340
+
341
+ root.innerHTML = `
342
+ <div class="border border-slate-200 rounded-lg bg-slate-50/50">
343
+ <div class="px-3 py-2 border-b border-slate-200 text-sm font-semibold text-slate-800 flex items-center gap-2">
344
+ <select id="rootMcpRule" class="h-7 text-xs border border-slate-300 rounded px-1 bg-white">
345
+ <option value="inherit" selected>Inherit</option>
346
+ <option value="allow">Allow</option>
347
+ <option value="deny">Deny</option>
348
+ </select>
349
+ <span class="flex items-center gap-2">
350
+ <i class="fas fa-sitemap text-slate-500"></i>
351
+ <span>MCP Servers</span>
352
+ </span>
353
+ </div>
354
+ <div class="p-2 space-y-2">
355
+ ${grouped.map((g) => `
356
+ <details class="border border-slate-200 rounded-md bg-white" open>
357
+ <summary class="cursor-pointer px-3 py-2 text-sm font-medium text-slate-800 flex items-center gap-2">
358
+ <select data-user-rule="${g.username}" class="h-7 text-xs border border-slate-300 rounded px-1 bg-white">
359
+ <option value="inherit" selected>Inherit</option>
360
+ <option value="allow">Allow</option>
361
+ <option value="deny">Deny</option>
362
+ </select>
363
+ <span class="flex items-center gap-2">
364
+ <i class="fas fa-user text-slate-500"></i>
365
+ <span>${g.username}</span>
366
+ <span class="text-[11px] text-slate-500">(${g.role})</span>
367
+ </span>
368
+ </summary>
369
+ <div class="px-3 pb-3 space-y-2">
370
+ ${(g.servers || []).map((s) => `
371
+ <details class="border border-slate-200 rounded-md bg-slate-50/50">
372
+ <summary class="cursor-pointer px-3 py-2 text-sm font-medium text-slate-800 flex items-center gap-2">
373
+ <select data-server-rule="${s.id}" data-owner="${g.username}" class="h-7 text-xs border border-slate-300 rounded px-1 bg-white mr-1">
374
+ <option value="inherit" selected>Inherit</option>
375
+ <option value="allow">Allow</option>
376
+ <option value="deny">Deny</option>
377
+ </select>
378
+ <span class="inline-flex items-center gap-2">
379
+ <i class="fas ${getMcpTypeIcon(s.type)} text-slate-500"></i>
380
+ <span>${getMcpDisplayName(s)}</span>
381
+ </span>
382
+ </summary>
383
+ <div class="px-3 pb-3 grid grid-cols-1 md:grid-cols-2 gap-3">
384
+ <div>
385
+ <div class="text-xs font-semibold text-slate-600 mb-2">Tools</div>
386
+ <div class="space-y-1 max-h-40 overflow-auto">
387
+ ${(s.tools || []).map((id) => `
388
+ <label class="inline-flex items-center gap-2 text-xs text-slate-700 w-full justify-between">
389
+ <span class="font-mono truncate">${id.split('__').slice(-1)[0]}</span>
390
+ <select data-tool-rule="${id}" data-server-id="${s.id}" class="h-6 text-[11px] border border-slate-300 rounded px-1 bg-white">
391
+ <option value="inherit" selected>Inherit</option>
392
+ <option value="allow">Allow</option>
393
+ <option value="deny">Deny</option>
394
+ </select>
395
+ </label>
396
+ `).join('') || '<p class="text-xs text-slate-400">No tools</p>'}
397
+ </div>
398
+ </div>
399
+ <div>
400
+ <div class="text-xs font-semibold text-slate-600 mb-2">Resources</div>
401
+ <div class="space-y-1 max-h-40 overflow-auto">
402
+ ${(s.resources || []).map((id) => `
403
+ <label class="inline-flex items-center gap-2 text-xs text-slate-700 w-full justify-between">
404
+ <span class="font-mono truncate">${id.split('__').slice(-1)[0]}</span>
405
+ <select data-resource-rule="${id}" data-server-id="${s.id}" class="h-6 text-[11px] border border-slate-300 rounded px-1 bg-white">
406
+ <option value="inherit" selected>Inherit</option>
407
+ <option value="allow">Allow</option>
408
+ <option value="deny">Deny</option>
409
+ </select>
410
+ </label>
411
+ `).join('') || '<p class="text-xs text-slate-400">No resources</p>'}
412
+ </div>
413
+ </div>
414
+ </div>
415
+ </details>
416
+ `).join('') || '<p class="text-xs text-slate-400 px-1 py-2">No servers for this user</p>'}
417
+ </div>
418
+ </details>
419
+ `).join('')}
420
+ </div>
421
+ </div>
422
+ `;
423
+
424
+ root.querySelectorAll('select[data-user-rule]').forEach((el) => {
425
+ el.addEventListener('change', (event) => {
426
+ const username = event.target.getAttribute('data-user-rule');
427
+ const value = event.target.value;
428
+ root.querySelectorAll(`select[data-server-rule][data-owner="${username}"]`).forEach((item) => {
429
+ if (item.value === 'inherit') item.value = value;
430
+ });
431
+ });
432
+ });
433
+
434
+ root.querySelectorAll('select[data-server-rule]').forEach((el) => {
435
+ el.addEventListener('change', (event) => {
436
+ const serverId = event.target.getAttribute('data-server-rule');
437
+ const value = event.target.value;
438
+ root.querySelectorAll(`select[data-tool-rule][data-server-id="${serverId}"], select[data-resource-rule][data-server-id="${serverId}"]`).forEach((item) => {
439
+ if (item.value === 'inherit') item.value = value;
440
+ });
441
+ });
442
+ });
443
+
444
+ const rootRule = byId('rootMcpRule');
445
+ if (rootRule) {
446
+ rootRule.addEventListener('change', (event) => {
447
+ const value = event.target.value;
448
+ root.querySelectorAll('select[data-user-rule], select[data-server-rule], select[data-tool-rule], select[data-resource-rule]').forEach((item) => {
449
+ if (item.value === 'inherit') item.value = value;
450
+ });
451
+ });
452
+ }
453
+ }
454
+
455
+ function computeEffectiveRules() {
456
+ const tree = byId('mcpTree');
457
+ const rootRule = triFromValue(byId('rootMcpRule')?.value || 'inherit');
458
+ const userRuleMap = {};
459
+
460
+ tree.querySelectorAll('select[data-user-rule]').forEach((el) => {
461
+ const username = el.getAttribute('data-user-rule');
462
+ if (!username) return;
463
+ userRuleMap[username] = triFromValue(el.value);
464
+ });
465
+
466
+ const serverRules = {};
467
+ tree.querySelectorAll('select[data-server-rule]').forEach((el) => {
468
+ const serverId = el.getAttribute('data-server-rule');
469
+ if (!serverId) return;
470
+ const owner = el.getAttribute('data-owner') || serverOwnerFromId(serverId);
471
+ const local = triFromValue(el.value);
472
+ serverRules[serverId] = resolveTriValue(local, userRuleMap[owner], rootRule);
473
+ });
474
+
475
+ const toolRules = {};
476
+ tree.querySelectorAll('select[data-tool-rule]').forEach((el) => {
477
+ const id = el.getAttribute('data-tool-rule');
478
+ if (!id) return;
479
+ const serverId = el.getAttribute('data-server-id') || '';
480
+ const owner = serverOwnerFromId(serverId);
481
+ const local = triFromValue(el.value);
482
+ toolRules[id] = resolveTriValue(local, serverRules[serverId], userRuleMap[owner], rootRule);
483
+ });
484
+
485
+ const resourceRules = {};
486
+ tree.querySelectorAll('select[data-resource-rule]').forEach((el) => {
487
+ const id = el.getAttribute('data-resource-rule');
488
+ if (!id) return;
489
+ const serverId = el.getAttribute('data-server-id') || '';
490
+ const owner = serverOwnerFromId(serverId);
491
+ const local = triFromValue(el.value);
492
+ resourceRules[id] = resolveTriValue(local, serverRules[serverId], userRuleMap[owner], rootRule);
493
+ });
494
+
495
+ return { serverRules, toolRules, resourceRules };
496
+ }
497
+
498
+ function renderServers() {
499
+ renderTree();
500
+ }
501
+
502
+ function policyValueToSelect(value) {
503
+ if (value === true) return 'require';
504
+ if (value === false) return 'no-token';
505
+ return 'inherit';
506
+ }
507
+
508
+ function selectToPolicyValue(value) {
509
+ if (value === 'require') return true;
510
+ if (value === 'no-token') return false;
511
+ return null;
512
+ }
513
+
514
+ function renderTokenPolicyTree() {
515
+ const root = byId('tokenPolicyTree');
516
+ const users = authContext.users || [];
517
+ const servers = authContext.servers || [];
518
+ const grouped = users.map((u) => ({
519
+ username: u.username,
520
+ role: u.role,
521
+ servers: servers.filter((s) => serverOwnerFromId(s.id) === u.username)
522
+ }));
523
+
524
+ root.innerHTML = `
525
+ <div class="border border-slate-200 rounded-lg bg-slate-50/50">
526
+ <div class="px-3 py-2 border-b border-slate-200 text-sm font-semibold text-slate-800 flex items-center gap-2">
527
+ <select id="policyRootRule" class="h-7 text-xs border border-slate-300 rounded px-1 bg-white">
528
+ <option value="require" ${tokenPolicyState.globalRequireMcpToken ? 'selected' : ''}>Require Token</option>
529
+ <option value="no-token" ${tokenPolicyState.globalRequireMcpToken ? '' : 'selected'}>No Token</option>
530
+ </select>
531
+ <span class="flex items-center gap-2">
532
+ <i class="fas fa-globe text-slate-500"></i>
533
+ <span>Application (All MCP)</span>
534
+ </span>
535
+ </div>
536
+ <div class="p-2 space-y-2">
537
+ ${grouped.map((g) => `
538
+ <details class="border border-slate-200 rounded-md bg-white" open>
539
+ <summary class="cursor-pointer px-3 py-2 text-sm font-medium text-slate-800 flex items-center gap-2">
540
+ <select data-policy-user="${g.username}" class="h-7 text-xs border border-slate-300 rounded px-1 bg-white">
541
+ <option value="inherit" ${policyValueToSelect(tokenPolicyState.userRules[g.username]) === 'inherit' ? 'selected' : ''}>Inherit</option>
542
+ <option value="require" ${policyValueToSelect(tokenPolicyState.userRules[g.username]) === 'require' ? 'selected' : ''}>Require Token</option>
543
+ <option value="no-token" ${policyValueToSelect(tokenPolicyState.userRules[g.username]) === 'no-token' ? 'selected' : ''}>No Token</option>
544
+ </select>
545
+ <span class="flex items-center gap-2">
546
+ <i class="fas fa-user text-slate-500"></i>
547
+ <span>${g.username}</span>
548
+ <span class="text-[11px] text-slate-500">(${g.role})</span>
549
+ </span>
550
+ </summary>
551
+ <div class="px-3 pb-3 space-y-2">
552
+ ${(g.servers || []).map((s) => `
553
+ <details class="border border-slate-200 rounded-md bg-slate-50/50">
554
+ <summary class="cursor-pointer px-3 py-2 text-sm font-medium text-slate-800 flex items-center gap-2">
555
+ <select data-policy-server="${s.id}" data-owner="${g.username}" class="h-7 text-xs border border-slate-300 rounded px-1 bg-white mr-1">
556
+ <option value="inherit" ${policyValueToSelect(tokenPolicyState.serverRules[s.id]) === 'inherit' ? 'selected' : ''}>Inherit</option>
557
+ <option value="require" ${policyValueToSelect(tokenPolicyState.serverRules[s.id]) === 'require' ? 'selected' : ''}>Require Token</option>
558
+ <option value="no-token" ${policyValueToSelect(tokenPolicyState.serverRules[s.id]) === 'no-token' ? 'selected' : ''}>No Token</option>
559
+ </select>
560
+ <span class="inline-flex items-center gap-2">
561
+ <i class="fas ${getMcpTypeIcon(s.type)} text-slate-500"></i>
562
+ <span>${getMcpDisplayName(s)}</span>
563
+ </span>
564
+ </summary>
565
+ <div class="px-3 pb-3">
566
+ <div class="text-xs font-semibold text-slate-600 mb-2">Tools</div>
567
+ <div class="space-y-1 max-h-40 overflow-auto">
568
+ ${(s.tools || []).map((id) => `
569
+ <label class="inline-flex items-center gap-2 text-xs text-slate-700 w-full justify-between">
570
+ <span class="font-mono truncate">${id.split('__').slice(-1)[0]}</span>
571
+ <select data-policy-tool="${id}" data-server-id="${s.id}" class="h-6 text-[11px] border border-slate-300 rounded px-1 bg-white">
572
+ <option value="inherit" ${policyValueToSelect(tokenPolicyState.toolRules[id]) === 'inherit' ? 'selected' : ''}>Inherit</option>
573
+ <option value="require" ${policyValueToSelect(tokenPolicyState.toolRules[id]) === 'require' ? 'selected' : ''}>Require Token</option>
574
+ <option value="no-token" ${policyValueToSelect(tokenPolicyState.toolRules[id]) === 'no-token' ? 'selected' : ''}>No Token</option>
575
+ </select>
576
+ </label>
577
+ `).join('') || '<p class="text-xs text-slate-400">No tools</p>'}
578
+ </div>
579
+ </div>
580
+ </details>
581
+ `).join('') || '<p class="text-xs text-slate-400 px-1 py-2">No servers for this user</p>'}
582
+ </div>
583
+ </details>
584
+ `).join('')}
585
+ </div>
586
+ </div>
587
+ `;
588
+
589
+ root.querySelectorAll('select[data-policy-user]').forEach((el) => {
590
+ el.addEventListener('change', (event) => {
591
+ const username = event.target.getAttribute('data-policy-user');
592
+ const value = event.target.value;
593
+ root.querySelectorAll(`select[data-policy-server][data-owner="${username}"]`).forEach((item) => {
594
+ if (item.value === 'inherit') item.value = value;
595
+ });
596
+ });
597
+ });
598
+
599
+ root.querySelectorAll('select[data-policy-server]').forEach((el) => {
600
+ el.addEventListener('change', (event) => {
601
+ const serverId = event.target.getAttribute('data-policy-server');
602
+ const value = event.target.value;
603
+ root.querySelectorAll(`select[data-policy-tool][data-server-id="${serverId}"]`).forEach((item) => {
604
+ if (item.value === 'inherit') item.value = value;
605
+ });
606
+ });
607
+ });
608
+ }
609
+
610
+ function collectTokenPolicyPayload() {
611
+ const userRules = {};
612
+ const serverRules = {};
613
+ const toolRules = {};
614
+ const globalRequireMcpToken = byId('policyRootRule')?.value !== 'no-token';
615
+
616
+ byId('tokenPolicyTree').querySelectorAll('select[data-policy-user]').forEach((el) => {
617
+ const id = el.getAttribute('data-policy-user');
618
+ if (!id) return;
619
+ userRules[id] = selectToPolicyValue(el.value);
620
+ });
621
+ byId('tokenPolicyTree').querySelectorAll('select[data-policy-server]').forEach((el) => {
622
+ const id = el.getAttribute('data-policy-server');
623
+ if (!id) return;
624
+ serverRules[id] = selectToPolicyValue(el.value);
625
+ });
626
+ byId('tokenPolicyTree').querySelectorAll('select[data-policy-tool]').forEach((el) => {
627
+ const id = el.getAttribute('data-policy-tool');
628
+ if (!id) return;
629
+ toolRules[id] = selectToPolicyValue(el.value);
630
+ });
631
+
632
+ return { globalRequireMcpToken, userRules, serverRules, toolRules };
633
+ }
634
+
635
+ async function loadTokenPolicy() {
636
+ const res = await fetch('/api/authorization/token-policy');
637
+ if (!res.ok) throw new Error('Failed to load token policy');
638
+ const payload = await res.json();
639
+ tokenPolicyState = {
640
+ globalRequireMcpToken: payload?.data?.globalRequireMcpToken !== false,
641
+ userRules: payload?.data?.userRules || {},
642
+ serverRules: payload?.data?.serverRules || {},
643
+ toolRules: payload?.data?.toolRules || {}
644
+ };
645
+ renderTokenPolicyTree();
646
+ }
647
+
648
+ async function saveTokenPolicy() {
649
+ const body = collectTokenPolicyPayload();
650
+ const res = await fetch('/api/authorization/token-policy', {
651
+ method: 'POST',
652
+ headers: { 'Content-Type': 'application/json' },
653
+ body: JSON.stringify(body)
654
+ });
655
+ const payload = await res.json().catch(() => ({}));
656
+ if (!res.ok) throw new Error(payload?.error || 'Failed to save token policy');
657
+ tokenPolicyState = {
658
+ globalRequireMcpToken: payload?.data?.globalRequireMcpToken !== false,
659
+ userRules: payload?.data?.userRules || {},
660
+ serverRules: payload?.data?.serverRules || {},
661
+ toolRules: payload?.data?.toolRules || {}
662
+ };
663
+ renderTokenPolicyTree();
664
+ }
665
+
666
+ async function loadConfig() {
667
+ const res = await fetch('/api/authorization/config');
668
+ if (!res.ok) throw new Error('Failed to load config');
669
+ const payload = await res.json();
670
+ const data = payload?.data || {};
671
+ applyAuthorizationMode(data);
672
+ byId('authSummary').textContent = data.mcpTokenRequired
673
+ ? 'Create and manage access tokens to control which users can see and run MCP servers, tools, and resources.'
674
+ : 'You can optionally create access tokens to control who can use MCP servers, tools, and resources.';
675
+ }
676
+
677
+ async function loadContext() {
678
+ const res = await fetch('/api/authorization/context');
679
+ if (!res.ok) throw new Error('Failed to load context');
680
+ const payload = await res.json();
681
+ authContext = payload?.data || { users: [], servers: [] };
682
+ renderUsers();
683
+ renderServers();
684
+ }
685
+
686
+ async function loadTokens() {
687
+ const root = byId('tokenTableWrap');
688
+ root.innerHTML = '<p class="text-sm text-slate-500">Loading tokens...</p>';
689
+ const res = await fetch('/api/authorization/tokens');
690
+ if (!res.ok) throw new Error('Failed to load tokens');
691
+ const payload = await res.json();
692
+ const tokens = payload?.data?.tokens || [];
693
+ if (!tokens.length) {
694
+ root.innerHTML = '<p class="text-sm text-slate-500">No tokens found.</p>';
695
+ return;
696
+ }
697
+
698
+ root.innerHTML = `
699
+ <table class="min-w-full text-sm">
700
+ <thead><tr class="text-left border-b border-slate-200">
701
+ <th class="py-2 pr-4 font-semibold text-slate-700">Token Name</th>
702
+ <th class="py-2 pr-4 font-semibold text-slate-700">User</th>
703
+ <th class="py-2 pr-4 font-semibold text-slate-700">Created</th>
704
+ <th class="py-2 pr-4 font-semibold text-slate-700">Expires</th>
705
+ <th class="py-2 pr-4 font-semibold text-slate-700">Status</th>
706
+ <th class="py-2 pr-4 font-semibold text-slate-700">Action</th>
707
+ </tr></thead>
708
+ <tbody>
709
+ ${tokens.map((t) => `
710
+ <tr class="border-b border-slate-100">
711
+ <td class="py-2 pr-4">${t.tokenName || ''}</td>
712
+ <td class="py-2 pr-4">${t.subjectUsername}</td>
713
+ <td class="py-2 pr-4 text-slate-600">${t.createdAt || '-'}</td>
714
+ <td class="py-2 pr-4 text-slate-600">${t.neverExpires ? 'Never' : (t.expiresAt || '-')}</td>
715
+ <td class="py-2 pr-4">
716
+ <span class="px-2 py-1 rounded-full text-xs font-semibold ${t.revokedAt ? 'bg-red-100 text-red-700' : 'bg-emerald-100 text-emerald-700'}">${t.revokedAt ? 'Revoked' : 'Active'}</span>
717
+ </td>
718
+ <td class="py-2 pr-4 space-x-2">
719
+ <button class="show-token-btn px-2 py-1 rounded border border-slate-200 hover:border-blue-400 text-xs" data-id="${t.id}">Show Token</button>
720
+ ${t.revokedAt ? '' : `<button class="revoke-token-btn px-2 py-1 rounded border border-red-200 text-red-700 hover:bg-red-50 text-xs" data-id="${t.id}">Revoke</button>`}
721
+ </td>
722
+ </tr>
723
+ `).join('')}
724
+ </tbody>
725
+ </table>
726
+ `;
727
+
728
+ root.querySelectorAll('.show-token-btn').forEach((btn) => {
729
+ btn.addEventListener('click', async (event) => {
730
+ const id = event.target.getAttribute('data-id');
731
+ const resp = await fetch(`/api/authorization/tokens/${encodeURIComponent(id)}`);
732
+ if (!resp.ok) throw new Error('Failed to load token');
733
+ const tokenPayload = await resp.json();
734
+ const data = tokenPayload?.data || {};
735
+ openTokenModal(
736
+ data.token || '',
737
+ data.neverExpires ? 'Never expires' : `Expires: ${data.expiresAt || '-'}`
738
+ );
739
+ });
740
+ });
741
+
742
+ root.querySelectorAll('.revoke-token-btn').forEach((btn) => {
743
+ btn.addEventListener('click', async (event) => {
744
+ const id = event.target.getAttribute('data-id');
745
+ const resp = await fetch(`/api/authorization/tokens/${encodeURIComponent(id)}`, { method: 'DELETE' });
746
+ if (!resp.ok) throw new Error('Failed to revoke token');
747
+ await loadTokens();
748
+ window.utils?.showToast?.('Token revoked', 'success');
749
+ });
750
+ });
751
+ }
752
+
753
+ async function generateToken() {
754
+ const subjectUsername = byId('subjectUserSelect').value;
755
+ const tokenName = byId('tokenName').value.trim();
756
+ if (!tokenName) {
757
+ throw new Error('Token name is required');
758
+ }
759
+ const ttlPreset = byId('tokenTtlPreset').value;
760
+ const neverExpires = ttlPreset === 'never';
761
+ const presetToHours = {
762
+ '1m': 1 / 60,
763
+ '5m': 5 / 60,
764
+ '15m': 15 / 60,
765
+ '30m': 30 / 60,
766
+ '1h': 1,
767
+ '4h': 4,
768
+ '12h': 12,
769
+ '24h': 24,
770
+ '1w': 24 * 7,
771
+ '2w': 24 * 14,
772
+ '1mo': 24 * 30,
773
+ '3mo': 24 * 90,
774
+ '6mo': 24 * 180
775
+ };
776
+ const ttlHours = neverExpires ? null : (presetToHours[ttlPreset] || 24 * 30);
777
+ const { serverRules, toolRules, resourceRules } = computeEffectiveRules();
778
+
779
+ const res = await fetch('/api/authorization/mcp-token', {
780
+ method: 'POST',
781
+ headers: { 'Content-Type': 'application/json' },
782
+ body: JSON.stringify({
783
+ tokenName,
784
+ subjectUsername,
785
+ neverExpires,
786
+ ttlHours,
787
+ serverRules,
788
+ toolRules,
789
+ resourceRules
790
+ })
791
+ });
792
+ const payload = await res.json().catch(() => ({}));
793
+ if (!res.ok) throw new Error(payload?.error || 'Failed to generate token');
794
+
795
+ byId('generatedToken').value = payload?.data?.token || '';
796
+ byId('tokenMeta').textContent = payload?.data?.neverExpires
797
+ ? 'Never expires'
798
+ : `Expires: ${payload?.data?.expiresAt || '-'}`;
799
+ refreshCopyButtonState();
800
+ await loadTokens();
801
+ }
802
+
803
+ byId('generateTokenBtn').addEventListener('click', () => {
804
+ generateToken().catch((error) => window.utils?.showToast?.(error.message || 'Failed to generate token', 'error'));
805
+ });
806
+ byId('refreshTokensBtn').addEventListener('click', () => {
807
+ loadTokens().catch((error) => window.utils?.showToast?.(error.message || 'Failed to load tokens', 'error'));
808
+ });
809
+ byId('saveTokenPolicyBtn').addEventListener('click', () => {
810
+ saveTokenPolicy()
811
+ .then(() => window.utils?.showToast?.('Token policy saved', 'success'))
812
+ .catch((error) => window.utils?.showToast?.(error.message || 'Failed to save token policy', 'error'));
813
+ });
814
+ byId('tabToken').addEventListener('click', () => setAuthorizationTab('token'));
815
+ byId('tabPolicy')?.addEventListener('click', () => {
816
+ if (isSaasMode) return;
817
+ setAuthorizationTab('policy');
818
+ });
819
+ byId('subjectUserSelect').addEventListener('change', renderTree);
820
+ byId('copyTokenBtn').addEventListener('click', async () => {
821
+ const token = byId('generatedToken').value.trim();
822
+ if (!token) return;
823
+ try {
824
+ await navigator.clipboard.writeText(token);
825
+ window.utils?.showToast?.('Token copied', 'success');
826
+ } catch (_) {
827
+ window.utils?.showToast?.('Failed to copy token', 'error');
828
+ }
829
+ });
830
+ byId('closeTokenModalBtn').addEventListener('click', closeTokenModal);
831
+ byId('tokenModalOverlay').addEventListener('click', closeTokenModal);
832
+ byId('toggleTokenMaskBtn').addEventListener('click', () => {
833
+ tokenModalMasked = !tokenModalMasked;
834
+ renderTokenModalValue();
835
+ });
836
+ byId('copyTokenModalBtn').addEventListener('click', async () => {
837
+ const token = tokenModalRawValue.trim();
838
+ if (!token) return;
839
+ try {
840
+ await navigator.clipboard.writeText(token);
841
+ window.utils?.showToast?.('Token copied', 'success');
842
+ } catch (_) {
843
+ window.utils?.showToast?.('Failed to copy token', 'error');
844
+ }
845
+ });
846
+ document.addEventListener('keydown', (event) => {
847
+ if (event.key === 'Escape' && !byId('tokenModal').classList.contains('hidden')) {
848
+ closeTokenModal();
849
+ }
850
+ });
851
+
852
+ document.addEventListener('DOMContentLoaded', async () => {
853
+ try {
854
+ setAuthorizationTab('token');
855
+ await loadConfig();
856
+ await loadContext();
857
+ if (!isSaasMode) {
858
+ await loadTokenPolicy();
859
+ }
860
+ await loadTokens();
861
+ refreshCopyButtonState();
862
+ } catch (error) {
863
+ window.utils?.showToast?.(error.message || 'Authorization page failed to load', 'error');
864
+ }
865
+ });
866
+ </script>
867
+ </body>
868
+ </html>