@commandable/mcp 0.1.2 → 0.2.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 (282) hide show
  1. package/{dist/app → .output}/nitro.json +1 -1
  2. package/{dist/app/public/_nuxt/-tOYwuj2.js → .output/public/_nuxt/B04gGCnx.js} +3 -3
  3. package/{dist/app/public/_nuxt/D-43HurL.js → .output/public/_nuxt/B2dAlp_u.js} +8 -8
  4. package/.output/public/_nuxt/Ba0BY0O0.js +1 -0
  5. package/.output/public/_nuxt/BvFUCPqA.js +1 -0
  6. package/{dist/app/public/_nuxt/BdctKXor.js → .output/public/_nuxt/Dm_hd4at.js} +1 -1
  7. package/{dist/app/public/_nuxt/BlP7Uu-5.js → .output/public/_nuxt/S2P9sd4n.js} +1 -1
  8. package/.output/public/_nuxt/builds/latest.json +1 -0
  9. package/.output/public/_nuxt/builds/meta/ee5097c4-b785-4b77-92d6-c16a7396d677.json +1 -0
  10. package/{dist/app/public/_nuxt/CsbkV5Bd.js → .output/public/_nuxt/d2XTSFt9.js} +1 -1
  11. package/{dist/app/server/chunks/build/_id_-DBwSV4AY.mjs → .output/server/chunks/build/_id_-Bnxenh08.mjs} +7 -7
  12. package/{dist/app/server/chunks/build/_id_-DBwSV4AY.mjs.map → .output/server/chunks/build/_id_-Bnxenh08.mjs.map} +1 -1
  13. package/{dist/app → .output}/server/chunks/build/client.precomputed.mjs +1 -1
  14. package/{dist/app/server/chunks/build/fetch-ZbqIFhDG.mjs → .output/server/chunks/build/fetch-BmYZnj75.mjs} +58 -6
  15. package/.output/server/chunks/build/fetch-BmYZnj75.mjs.map +1 -0
  16. package/{dist/app/server/chunks/build/index-C8flTcKI.mjs → .output/server/chunks/build/index-CL-Gkd-Y.mjs} +4 -4
  17. package/.output/server/chunks/build/index-CL-Gkd-Y.mjs.map +1 -0
  18. package/{dist/app → .output}/server/chunks/build/server.mjs +3 -3
  19. package/{dist/app → .output}/server/chunks/nitro/nitro.mjs +417 -204
  20. package/.output/server/chunks/nitro/nitro.mjs.map +1 -0
  21. package/{dist/app → .output}/server/chunks/routes/api/index.get.mjs +1 -1
  22. package/{dist/app → .output}/server/chunks/routes/api/index.post.mjs +1 -1
  23. package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/credentials-config.get.mjs +1 -1
  24. package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/credentials-status.get.mjs +1 -1
  25. package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/credentials.delete.mjs +1 -1
  26. package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/credentials.post.mjs +1 -1
  27. package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/permissions.post.mjs +1 -1
  28. package/.output/server/chunks/routes/api/integrations/_id/tools.delete.mjs +51 -0
  29. package/.output/server/chunks/routes/api/integrations/_id/tools.delete.mjs.map +1 -0
  30. package/.output/server/chunks/routes/api/integrations/_id/tools.get.mjs +57 -0
  31. package/.output/server/chunks/routes/api/integrations/_id/tools.get.mjs.map +1 -0
  32. package/.output/server/chunks/routes/api/integrations/_id/toolsets.get.mjs +53 -0
  33. package/.output/server/chunks/routes/api/integrations/_id/toolsets.get.mjs.map +1 -0
  34. package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/toolsets.post.mjs +1 -1
  35. package/.output/server/chunks/routes/api/integrations/_id_.delete.mjs +55 -0
  36. package/.output/server/chunks/routes/api/integrations/_id_.delete.mjs.map +1 -0
  37. package/{dist/app → .output}/server/chunks/routes/mcp/create.mjs +1 -1
  38. package/{dist/app → .output}/server/chunks/routes/mcp.mjs +1 -1
  39. package/{dist/app → .output}/server/chunks/routes/renderer.mjs +1 -1
  40. package/{dist/app → .output}/server/index.mjs +1 -1
  41. package/{dist/app → .output}/server/package.json +2 -2
  42. package/LICENSE +17 -6
  43. package/README.md +32 -32
  44. package/bin/cli.mjs +552 -0
  45. package/bin/commandable-mcp.mjs +8 -0
  46. package/package.json +30 -40
  47. package/dist/app/public/_nuxt/DU1mG77A.js +0 -1
  48. package/dist/app/public/_nuxt/builds/latest.json +0 -1
  49. package/dist/app/public/_nuxt/builds/meta/b13ec2b2-ddd3-4ead-abd4-4fba9dfc0061.json +0 -1
  50. package/dist/app/public/_nuxt/uS7FY2am.js +0 -1
  51. package/dist/app/server/chunks/build/fetch-ZbqIFhDG.mjs.map +0 -1
  52. package/dist/app/server/chunks/build/index-C8flTcKI.mjs.map +0 -1
  53. package/dist/app/server/chunks/nitro/nitro.mjs.map +0 -1
  54. package/dist/app/server/chunks/routes/api/integrations/_id_.delete.mjs +0 -44
  55. package/dist/app/server/chunks/routes/api/integrations/_id_.delete.mjs.map +0 -1
  56. package/dist/app/server/migrations/pg/0000_initial.sql +0 -74
  57. package/dist/app/server/migrations/pg/meta/_journal.json +0 -13
  58. package/dist/app/server/migrations/sqlite/0000_initial.sql +0 -74
  59. package/dist/app/server/migrations/sqlite/meta/_journal.json +0 -13
  60. package/dist/cli/bin.d.ts +0 -3
  61. package/dist/cli/bin.d.ts.map +0 -1
  62. package/dist/cli/bin.js +0 -7
  63. package/dist/cli/bin.js.map +0 -1
  64. package/dist/cli/credentialManager.d.ts +0 -19
  65. package/dist/cli/credentialManager.d.ts.map +0 -1
  66. package/dist/cli/credentialManager.js +0 -82
  67. package/dist/cli/credentialManager.js.map +0 -1
  68. package/dist/cli/index.d.ts +0 -17
  69. package/dist/cli/index.d.ts.map +0 -1
  70. package/dist/cli/index.js +0 -818
  71. package/dist/cli/index.js.map +0 -1
  72. package/dist/cli/setup.d.ts +0 -3
  73. package/dist/cli/setup.d.ts.map +0 -1
  74. package/dist/cli/setup.js +0 -353
  75. package/dist/cli/setup.js.map +0 -1
  76. package/dist/config/configApply.d.ts +0 -16
  77. package/dist/config/configApply.d.ts.map +0 -1
  78. package/dist/config/configApply.js +0 -77
  79. package/dist/config/configApply.js.map +0 -1
  80. package/dist/config/configLoader.d.ts +0 -9
  81. package/dist/config/configLoader.d.ts.map +0 -1
  82. package/dist/config/configLoader.js +0 -75
  83. package/dist/config/configLoader.js.map +0 -1
  84. package/dist/config/configSchema.d.ts +0 -45
  85. package/dist/config/configSchema.d.ts.map +0 -1
  86. package/dist/config/configSchema.js +0 -23
  87. package/dist/config/configSchema.js.map +0 -1
  88. package/dist/crypto/encryption.d.ts +0 -3
  89. package/dist/crypto/encryption.d.ts.map +0 -1
  90. package/dist/crypto/encryption.js +0 -29
  91. package/dist/crypto/encryption.js.map +0 -1
  92. package/dist/db/client.d.ts +0 -24
  93. package/dist/db/client.d.ts.map +0 -1
  94. package/dist/db/client.js +0 -50
  95. package/dist/db/client.js.map +0 -1
  96. package/dist/db/credentialStore.d.ts +0 -15
  97. package/dist/db/credentialStore.d.ts.map +0 -1
  98. package/dist/db/credentialStore.js +0 -56
  99. package/dist/db/credentialStore.js.map +0 -1
  100. package/dist/db/integrationStore.d.ts +0 -12
  101. package/dist/db/integrationStore.d.ts.map +0 -1
  102. package/dist/db/integrationStore.js +0 -111
  103. package/dist/db/integrationStore.js.map +0 -1
  104. package/dist/db/integrationTypeConfigStore.d.ts +0 -6
  105. package/dist/db/integrationTypeConfigStore.d.ts.map +0 -1
  106. package/dist/db/integrationTypeConfigStore.js +0 -94
  107. package/dist/db/integrationTypeConfigStore.js.map +0 -1
  108. package/dist/db/migrate.d.ts +0 -3
  109. package/dist/db/migrate.d.ts.map +0 -1
  110. package/dist/db/migrate.js +0 -11
  111. package/dist/db/migrate.js.map +0 -1
  112. package/dist/db/migrations/pg/0000_initial.sql +0 -74
  113. package/dist/db/migrations/pg/meta/_journal.json +0 -13
  114. package/dist/db/migrations/sqlite/0000_initial.sql +0 -74
  115. package/dist/db/migrations/sqlite/meta/_journal.json +0 -13
  116. package/dist/db/schema.d.ts +0 -1863
  117. package/dist/db/schema.d.ts.map +0 -1
  118. package/dist/db/schema.js +0 -133
  119. package/dist/db/schema.js.map +0 -1
  120. package/dist/db/toolDefinitionStore.d.ts +0 -6
  121. package/dist/db/toolDefinitionStore.d.ts.map +0 -1
  122. package/dist/db/toolDefinitionStore.js +0 -95
  123. package/dist/db/toolDefinitionStore.js.map +0 -1
  124. package/dist/errors/httpError.d.ts +0 -6
  125. package/dist/errors/httpError.d.ts.map +0 -1
  126. package/dist/errors/httpError.js +0 -11
  127. package/dist/errors/httpError.js.map +0 -1
  128. package/dist/index.d.ts +0 -32
  129. package/dist/index.d.ts.map +0 -1
  130. package/dist/index.js +0 -32
  131. package/dist/index.js.map +0 -1
  132. package/dist/integrations/actionsFactory.d.ts +0 -16
  133. package/dist/integrations/actionsFactory.d.ts.map +0 -1
  134. package/dist/integrations/actionsFactory.js +0 -98
  135. package/dist/integrations/actionsFactory.js.map +0 -1
  136. package/dist/integrations/catalog.d.ts +0 -8
  137. package/dist/integrations/catalog.d.ts.map +0 -1
  138. package/dist/integrations/catalog.js +0 -45
  139. package/dist/integrations/catalog.js.map +0 -1
  140. package/dist/integrations/customToolFactory.d.ts +0 -13
  141. package/dist/integrations/customToolFactory.d.ts.map +0 -1
  142. package/dist/integrations/customToolFactory.js +0 -31
  143. package/dist/integrations/customToolFactory.js.map +0 -1
  144. package/dist/integrations/dataLoader.d.ts +0 -3
  145. package/dist/integrations/dataLoader.d.ts.map +0 -1
  146. package/dist/integrations/dataLoader.js +0 -2
  147. package/dist/integrations/dataLoader.js.map +0 -1
  148. package/dist/integrations/fileIntegrationTypeConfigStore.d.ts +0 -7
  149. package/dist/integrations/fileIntegrationTypeConfigStore.d.ts.map +0 -1
  150. package/dist/integrations/fileIntegrationTypeConfigStore.js +0 -34
  151. package/dist/integrations/fileIntegrationTypeConfigStore.js.map +0 -1
  152. package/dist/integrations/getIntegration.d.ts +0 -14
  153. package/dist/integrations/getIntegration.d.ts.map +0 -1
  154. package/dist/integrations/getIntegration.js +0 -30
  155. package/dist/integrations/getIntegration.js.map +0 -1
  156. package/dist/integrations/googleServiceAccount.d.ts +0 -6
  157. package/dist/integrations/googleServiceAccount.d.ts.map +0 -1
  158. package/dist/integrations/googleServiceAccount.js +0 -54
  159. package/dist/integrations/googleServiceAccount.js.map +0 -1
  160. package/dist/integrations/health.d.ts +0 -20
  161. package/dist/integrations/health.d.ts.map +0 -1
  162. package/dist/integrations/health.js +0 -43
  163. package/dist/integrations/health.js.map +0 -1
  164. package/dist/integrations/integrationTypeConfigLookup.d.ts +0 -12
  165. package/dist/integrations/integrationTypeConfigLookup.d.ts.map +0 -1
  166. package/dist/integrations/integrationTypeConfigLookup.js +0 -11
  167. package/dist/integrations/integrationTypeConfigLookup.js.map +0 -1
  168. package/dist/integrations/providerRegistry.d.ts +0 -2
  169. package/dist/integrations/providerRegistry.d.ts.map +0 -1
  170. package/dist/integrations/providerRegistry.js +0 -72
  171. package/dist/integrations/providerRegistry.js.map +0 -1
  172. package/dist/integrations/proxy.d.ts +0 -19
  173. package/dist/integrations/proxy.d.ts.map +0 -1
  174. package/dist/integrations/proxy.js +0 -377
  175. package/dist/integrations/proxy.js.map +0 -1
  176. package/dist/integrations/sandbox.d.ts +0 -8
  177. package/dist/integrations/sandbox.d.ts.map +0 -1
  178. package/dist/integrations/sandbox.js +0 -221
  179. package/dist/integrations/sandbox.js.map +0 -1
  180. package/dist/integrations/sandboxUtils.d.ts +0 -15
  181. package/dist/integrations/sandboxUtils.d.ts.map +0 -1
  182. package/dist/integrations/sandboxUtils.js +0 -489
  183. package/dist/integrations/sandboxUtils.js.map +0 -1
  184. package/dist/integrations/tools.d.ts +0 -3
  185. package/dist/integrations/tools.d.ts.map +0 -1
  186. package/dist/integrations/tools.js +0 -70
  187. package/dist/integrations/tools.js.map +0 -1
  188. package/dist/mcp/abilityCatalog.d.ts +0 -46
  189. package/dist/mcp/abilityCatalog.d.ts.map +0 -1
  190. package/dist/mcp/abilityCatalog.js +0 -275
  191. package/dist/mcp/abilityCatalog.js.map +0 -1
  192. package/dist/mcp/auth.d.ts +0 -18
  193. package/dist/mcp/auth.d.ts.map +0 -1
  194. package/dist/mcp/auth.js +0 -45
  195. package/dist/mcp/auth.js.map +0 -1
  196. package/dist/mcp/builder_guide.md +0 -441
  197. package/dist/mcp/commandable_readme.md +0 -29
  198. package/dist/mcp/handlers.d.ts +0 -21
  199. package/dist/mcp/handlers.d.ts.map +0 -1
  200. package/dist/mcp/handlers.js +0 -86
  201. package/dist/mcp/handlers.js.map +0 -1
  202. package/dist/mcp/metaTools.d.ts +0 -77
  203. package/dist/mcp/metaTools.d.ts.map +0 -1
  204. package/dist/mcp/metaTools.js +0 -753
  205. package/dist/mcp/metaTools.js.map +0 -1
  206. package/dist/mcp/server.d.ts +0 -25
  207. package/dist/mcp/server.d.ts.map +0 -1
  208. package/dist/mcp/server.js +0 -14
  209. package/dist/mcp/server.js.map +0 -1
  210. package/dist/mcp/sessionState.d.ts +0 -18
  211. package/dist/mcp/sessionState.d.ts.map +0 -1
  212. package/dist/mcp/sessionState.js +0 -65
  213. package/dist/mcp/sessionState.js.map +0 -1
  214. package/dist/mcp/toolAdapter.d.ts +0 -34
  215. package/dist/mcp/toolAdapter.d.ts.map +0 -1
  216. package/dist/mcp/toolAdapter.js +0 -24
  217. package/dist/mcp/toolAdapter.js.map +0 -1
  218. package/dist/types.d.ts +0 -92
  219. package/dist/types.d.ts.map +0 -1
  220. package/dist/types.js +0 -2
  221. package/dist/types.js.map +0 -1
  222. package/dist/version.d.ts +0 -2
  223. package/dist/version.d.ts.map +0 -1
  224. package/dist/version.js +0 -7
  225. package/dist/version.js.map +0 -1
  226. /package/{dist/app → .output}/public/_fonts/57NSSoFy1VLVs2gqly8Ls9awBnZMFyXGrefpmqvdqmc-zJfbBtpgM4cDmcXBsqZNW79_kFnlpPd62b48glgdydA.woff2 +0 -0
  227. /package/{dist/app → .output}/public/_fonts/8VR2wSMN-3U4NbWAVYXlkRV6hA0jFBXP-0RtL3X7fko-x2gYI4qfmkRdxyQQUPaBZdZdgl1TeVrquF_TxHeM4lM.woff2 +0 -0
  228. /package/{dist/app → .output}/public/_fonts/GsKUclqeNLJ96g5AU593ug6yanivOiwjW_7zESNPChw-jHA4tBeM1bjF7LATGUpfBuSTyomIFrWBTzjF7txVYfg.woff2 +0 -0
  229. /package/{dist/app → .output}/public/_fonts/Ld1FnTo3yTIwDyGfTQ5-Fws9AWsCbKfMvgxduXr7JcY-W25bL8NF1fjpLRSOgJb7RoZPHqGQNwMTM7S9tHVoxx8.woff2 +0 -0
  230. /package/{dist/app → .output}/public/_fonts/NdzqRASp2bovDUhQT1IRE_EMqKJ2KYQdTCfFcBvL8yw-KhwZiS86o3fErOe5GGMExHUemmI_dBfaEFxjISZrBd0.woff2 +0 -0
  231. /package/{dist/app → .output}/public/_fonts/iTkrULNFJJkTvihIg1Vqi5IODRH_9btXCioVF5l98I8-AndUyau2HR2felA_ra8V2mutQgschhasE5FD1dXGJX8.woff2 +0 -0
  232. /package/{dist/app → .output}/public/_nuxt/_id_.BKAjWkoP.css +0 -0
  233. /package/{dist/app → .output}/public/_nuxt/entry.Y3mA4bzA.css +0 -0
  234. /package/{dist/app → .output}/public/_nuxt/error-404.C7fg894-.css +0 -0
  235. /package/{dist/app → .output}/public/_nuxt/error-500.DjUK_N2Y.css +0 -0
  236. /package/{dist/app → .output}/public/favicon.ico +0 -0
  237. /package/{dist/app → .output}/server/chunks/_/error-500.mjs +0 -0
  238. /package/{dist/app → .output}/server/chunks/_/error-500.mjs.map +0 -0
  239. /package/{dist/app → .output}/server/chunks/_/icons.mjs +0 -0
  240. /package/{dist/app → .output}/server/chunks/_/icons.mjs.map +0 -0
  241. /package/{dist/app → .output}/server/chunks/_/icons2.mjs +0 -0
  242. /package/{dist/app → .output}/server/chunks/_/icons2.mjs.map +0 -0
  243. /package/{dist/app → .output}/server/chunks/build/IntegrationCredentials-styles.CULcCK6_.mjs +0 -0
  244. /package/{dist/app → .output}/server/chunks/build/IntegrationCredentials-styles.CULcCK6_.mjs.map +0 -0
  245. /package/{dist/app → .output}/server/chunks/build/client.precomputed.mjs.map +0 -0
  246. /package/{dist/app → .output}/server/chunks/build/error-404-D2QibUBT.mjs +0 -0
  247. /package/{dist/app → .output}/server/chunks/build/error-404-D2QibUBT.mjs.map +0 -0
  248. /package/{dist/app → .output}/server/chunks/build/error-404-styles.Bvxdxqjk.mjs +0 -0
  249. /package/{dist/app → .output}/server/chunks/build/error-404-styles.Bvxdxqjk.mjs.map +0 -0
  250. /package/{dist/app → .output}/server/chunks/build/error-500-DYvawybF.mjs +0 -0
  251. /package/{dist/app → .output}/server/chunks/build/error-500-DYvawybF.mjs.map +0 -0
  252. /package/{dist/app → .output}/server/chunks/build/error-500-styles.BnYAAXSg.mjs +0 -0
  253. /package/{dist/app → .output}/server/chunks/build/error-500-styles.BnYAAXSg.mjs.map +0 -0
  254. /package/{dist/app → .output}/server/chunks/build/index-5H-nmhph.mjs +0 -0
  255. /package/{dist/app → .output}/server/chunks/build/index-5H-nmhph.mjs.map +0 -0
  256. /package/{dist/app → .output}/server/chunks/build/server.mjs.map +0 -0
  257. /package/{dist/app → .output}/server/chunks/build/styles.mjs +0 -0
  258. /package/{dist/app → .output}/server/chunks/build/styles.mjs.map +0 -0
  259. /package/{dist/app → .output}/server/chunks/routes/api/_commandable/status.get.mjs +0 -0
  260. /package/{dist/app → .output}/server/chunks/routes/api/_commandable/status.get.mjs.map +0 -0
  261. /package/{dist/app → .output}/server/chunks/routes/api/catalog/_type/tools.get.mjs +0 -0
  262. /package/{dist/app → .output}/server/chunks/routes/api/catalog/_type/tools.get.mjs.map +0 -0
  263. /package/{dist/app → .output}/server/chunks/routes/api/catalog/_type/toolsets.get.mjs +0 -0
  264. /package/{dist/app → .output}/server/chunks/routes/api/catalog/_type/toolsets.get.mjs.map +0 -0
  265. /package/{dist/app → .output}/server/chunks/routes/api/catalog.get.mjs +0 -0
  266. /package/{dist/app → .output}/server/chunks/routes/api/catalog.get.mjs.map +0 -0
  267. /package/{dist/app → .output}/server/chunks/routes/api/index.get.mjs.map +0 -0
  268. /package/{dist/app → .output}/server/chunks/routes/api/index.post.mjs.map +0 -0
  269. /package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/credentials-config.get.mjs.map +0 -0
  270. /package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/credentials-status.get.mjs.map +0 -0
  271. /package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/credentials.delete.mjs.map +0 -0
  272. /package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/credentials.post.mjs.map +0 -0
  273. /package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/permissions.post.mjs.map +0 -0
  274. /package/{dist/app → .output}/server/chunks/routes/api/integrations/_id/toolsets.post.mjs.map +0 -0
  275. /package/{dist/app → .output}/server/chunks/routes/health.get.mjs +0 -0
  276. /package/{dist/app → .output}/server/chunks/routes/health.get.mjs.map +0 -0
  277. /package/{dist/app → .output}/server/chunks/routes/mcp/create.mjs.map +0 -0
  278. /package/{dist/app → .output}/server/chunks/routes/mcp.mjs.map +0 -0
  279. /package/{dist/app → .output}/server/chunks/routes/renderer.mjs.map +0 -0
  280. /package/{dist/app → .output}/server/chunks/virtual/_virtual_spa-template.mjs +0 -0
  281. /package/{dist/app → .output}/server/chunks/virtual/_virtual_spa-template.mjs.map +0 -0
  282. /package/{dist/app → .output}/server/index.mjs.map +0 -0
package/bin/cli.mjs ADDED
@@ -0,0 +1,552 @@
1
+ import crypto from 'node:crypto'
2
+ import { spawn, spawnSync } from 'node:child_process'
3
+ import { existsSync, mkdirSync, openSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
4
+ import { resolve } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+ import { createRequire } from 'node:module'
7
+ import { isCancel, note, select } from '@clack/prompts'
8
+ import picocolors from 'picocolors'
9
+ import {
10
+ SqlCredentialStore,
11
+ applyConfig,
12
+ createApiKey,
13
+ createDbFromEnv,
14
+ ensureSchema,
15
+ generateApiKey,
16
+ getCommandableDir,
17
+ getOrCreateEncryptionSecret,
18
+ loadConfig,
19
+ } from '@commandable/mcp-core'
20
+
21
+ const require = createRequire(import.meta.url)
22
+ const pkg = require('../package.json')
23
+ const COMMANDABLE_VERSION = String(pkg.version || '0.0.0')
24
+ const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url)))
25
+ const serverEntry = resolve(packageRoot, '.output', 'server', 'index.mjs')
26
+ const CLAUDE_CODE_STDIO_ENV_KEYS = [
27
+ 'COMMANDABLE_SPACE_ID',
28
+ 'COMMANDABLE_DATA_DIR',
29
+ 'COMMANDABLE_MCP_SQLITE_PATH',
30
+ 'COMMANDABLE_UI_PORT',
31
+ 'DATABASE_URL',
32
+ 'COMMANDABLE_CONFIG_FILE',
33
+ 'COMMANDABLE_INTEGRATION_DATA_DIR',
34
+ ]
35
+
36
+ function hasFlag(...flags) {
37
+ return flags.some(flag => process.argv.includes(flag))
38
+ }
39
+
40
+ function getFlagValue(flag) {
41
+ const index = process.argv.indexOf(flag)
42
+ if (index === -1)
43
+ return null
44
+ const value = process.argv[index + 1]
45
+ if (!value || value.startsWith('-'))
46
+ return null
47
+ return value
48
+ }
49
+
50
+ function getUiPort() {
51
+ const raw = process.env.COMMANDABLE_UI_PORT
52
+ return raw && /^\d+$/.test(raw) ? Number(raw) : 23432
53
+ }
54
+
55
+ function getBaseUrl() {
56
+ return `http://127.0.0.1:${getUiPort()}`
57
+ }
58
+
59
+ function daemonPidPath() {
60
+ return resolve(getCommandableDir(), 'daemon.pid')
61
+ }
62
+
63
+ function daemonLogPath() {
64
+ return resolve(getCommandableDir(), 'daemon.log')
65
+ }
66
+
67
+ function getSqlitePathForLocalState() {
68
+ const forced = process.env.COMMANDABLE_MCP_SQLITE_PATH
69
+ if (forced && forced.trim().length)
70
+ return resolve(forced.trim())
71
+ return resolve(getCommandableDir(), 'credentials.sqlite')
72
+ }
73
+
74
+ function readDaemonPid() {
75
+ try {
76
+ const raw = readFileSync(daemonPidPath(), 'utf8')
77
+ const lines = raw.split('\n').map(line => line.trim()).filter(Boolean)
78
+ const pid = lines[0] && /^\d+$/.test(lines[0]) ? Number(lines[0]) : null
79
+ const version = lines[1] || null
80
+ return pid ? { pid, version } : null
81
+ }
82
+ catch {
83
+ return null
84
+ }
85
+ }
86
+
87
+ function isProcessAlive(pid) {
88
+ try {
89
+ process.kill(pid, 0)
90
+ return true
91
+ }
92
+ catch {
93
+ return false
94
+ }
95
+ }
96
+
97
+ function stopDaemonProcess() {
98
+ const info = readDaemonPid()
99
+ if (info?.pid) {
100
+ try {
101
+ process.kill(info.pid, 'SIGTERM')
102
+ }
103
+ catch {}
104
+ }
105
+ try {
106
+ unlinkSync(daemonPidPath())
107
+ }
108
+ catch {}
109
+ return { stopped: !!info?.pid, pid: info?.pid ?? null }
110
+ }
111
+
112
+ async function fetchJsonWithTimeout(url, timeoutMs) {
113
+ const controller = new AbortController()
114
+ const timeout = setTimeout(() => controller.abort(), timeoutMs)
115
+ try {
116
+ const response = await fetch(url, { signal: controller.signal })
117
+ const text = await response.text()
118
+ let json = null
119
+ try {
120
+ json = text ? JSON.parse(text) : null
121
+ }
122
+ catch {}
123
+ return { ok: response.ok, status: response.status, json }
124
+ }
125
+ finally {
126
+ clearTimeout(timeout)
127
+ }
128
+ }
129
+
130
+ async function waitForHttp(url, timeoutMs) {
131
+ const started = Date.now()
132
+ while (Date.now() - started < timeoutMs) {
133
+ const probe = await fetchJsonWithTimeout(url, 400).catch(() => null)
134
+ if (probe?.ok)
135
+ return probe
136
+ await new Promise(resolvePromise => setTimeout(resolvePromise, 250))
137
+ }
138
+ return null
139
+ }
140
+
141
+ async function assertLocalServerRunning() {
142
+ const baseUrl = getBaseUrl()
143
+ const probe = await fetchJsonWithTimeout(`${baseUrl}/api/_commandable/status`, 500).catch(() => null)
144
+ if (probe?.ok)
145
+ return probe.json
146
+
147
+ console.error('Commandable local mode requires the server to already be running.')
148
+ console.error('Start it first with: npx -y @commandable/mcp serve')
149
+ process.exit(1)
150
+ }
151
+
152
+ function makeClaudeCodeAddCommand() {
153
+ const envArgs = getClaudeCodeEnvEntries()
154
+ .map(value => `-e ${quoteShellArg(value)}`)
155
+ .join(' ')
156
+ return `claude mcp add commandable${envArgs ? ` ${envArgs}` : ''} -- npx -y @commandable/mcp-connect create-mode`
157
+ }
158
+
159
+ function getClaudeCodeEnvEntries() {
160
+ return CLAUDE_CODE_STDIO_ENV_KEYS
161
+ .map((key) => {
162
+ const value = process.env[key]
163
+ return value && value.trim().length ? `${key}=${value}` : null
164
+ })
165
+ .filter(Boolean)
166
+ }
167
+
168
+ function quoteShellArg(value) {
169
+ if (/^[A-Za-z0-9_./:=@-]+$/.test(value))
170
+ return value
171
+ return `'${value.replace(/'/g, `'\"'\"'`)}'`
172
+ }
173
+
174
+ function makeReadModeConfig() {
175
+ return {
176
+ mcpServers: {
177
+ commandable: {
178
+ command: 'npx',
179
+ args: ['-y', '@commandable/mcp-connect'],
180
+ },
181
+ },
182
+ }
183
+ }
184
+
185
+ function makeHttpConnectionDetails() {
186
+ const url = getFlagValue('--url') || 'https://your-host/mcp'
187
+ const apiKey = getFlagValue('--api-key') || '<api-key>'
188
+ return {
189
+ url,
190
+ headers: {
191
+ Authorization: `Bearer ${apiKey}`,
192
+ },
193
+ }
194
+ }
195
+
196
+ function makeClaudeCodeHttpAddCommand() {
197
+ const details = makeHttpConnectionDetails()
198
+ return `claude mcp add --transport http commandable ${details.url} --header "Authorization: ${details.headers.Authorization}"`
199
+ }
200
+
201
+ function printCreateInstructions(addCommand, instanceLabel) {
202
+ const line = picocolors.dim('─'.repeat(60))
203
+ console.error('')
204
+ console.error(picocolors.white('The current create experience requires an advanced MCP client. We recommend Claude Code.'))
205
+ console.error('')
206
+ console.error(picocolors.bold(`Connect Claude Code to your ${instanceLabel}:`))
207
+ console.error(line)
208
+ console.error(picocolors.cyan('claude mcp remove commandable'))
209
+ console.error(picocolors.cyan(addCommand))
210
+ console.error(line)
211
+ console.error(picocolors.dim('Paste the commands above into your terminal, then restart Claude Code.'))
212
+ console.error(picocolors.dim('Previous Commandable instances keep their own state and can be re-added later.'))
213
+ console.error('')
214
+ }
215
+
216
+ function execClaudeMcpAdd(args) {
217
+ const result = spawnSync('claude', args, { stdio: 'inherit' })
218
+ if (result.error) {
219
+ console.error(`claude ${args.join(' ')}`)
220
+ return
221
+ }
222
+ if (result.status !== 0)
223
+ process.exit(result.status ?? 1)
224
+ }
225
+
226
+ async function startManagementUi({ restart }) {
227
+ const baseUrl = getBaseUrl()
228
+ const existingPid = readDaemonPid()
229
+ if (!restart && existingPid?.pid && isProcessAlive(existingPid.pid)) {
230
+ const probe = await fetchJsonWithTimeout(`${baseUrl}/api/_commandable/status`, 500).catch(() => null)
231
+ if (probe?.ok)
232
+ return { reused: true, baseUrl }
233
+ }
234
+
235
+ if (restart)
236
+ stopDaemonProcess()
237
+
238
+ if (!existsSync(serverEntry)) {
239
+ console.error(`Missing built app server at ${serverEntry}`)
240
+ console.error('Run a package build first.')
241
+ process.exit(1)
242
+ }
243
+
244
+ mkdirSync(getCommandableDir(), { recursive: true })
245
+ const logPath = daemonLogPath()
246
+ const fd = openSync(logPath, 'a')
247
+ const child = spawn(process.execPath, [serverEntry], {
248
+ cwd: packageRoot,
249
+ env: {
250
+ ...process.env,
251
+ HOST: '127.0.0.1',
252
+ PORT: String(getUiPort()),
253
+ COMMANDABLE_UI_PORT: String(getUiPort()),
254
+ COMMANDABLE_VERSION,
255
+ },
256
+ detached: true,
257
+ stdio: ['ignore', fd, fd],
258
+ })
259
+ child.unref()
260
+
261
+ writeFileSync(daemonPidPath(), `${child.pid}\n${COMMANDABLE_VERSION}\n`)
262
+
263
+ const probe = await waitForHttp(`${baseUrl}/api/_commandable/status`, 12000)
264
+ if (!probe?.ok) {
265
+ try {
266
+ process.kill(child.pid, 'SIGTERM')
267
+ }
268
+ catch {}
269
+ try {
270
+ unlinkSync(daemonPidPath())
271
+ }
272
+ catch {}
273
+ console.error(`Commandable management UI failed to start at ${baseUrl}`)
274
+ console.error(`Check the daemon log at ${logPath}`)
275
+ process.exit(1)
276
+ }
277
+
278
+ return { reused: false, baseUrl }
279
+ }
280
+
281
+ async function openEnvState() {
282
+ const db = createDbFromEnv()
283
+ await ensureSchema(db)
284
+ const secret = getOrCreateEncryptionSecret()
285
+ const credentialStore = new SqlCredentialStore(db, secret)
286
+ return {
287
+ db,
288
+ credentialStore,
289
+ close: async () => {
290
+ if (db.dialect === 'sqlite')
291
+ db.close()
292
+ else
293
+ await db.close()
294
+ },
295
+ }
296
+ }
297
+
298
+ async function runServe() {
299
+ const migrateClient = createDbFromEnv()
300
+ await ensureSchema(migrateClient)
301
+ if (migrateClient.dialect === 'sqlite')
302
+ migrateClient.close()
303
+ else
304
+ await migrateClient.close()
305
+
306
+ const ui = await startManagementUi({ restart: hasFlag('--restart') })
307
+ const baseUrl = ui.baseUrl
308
+ console.error(picocolors.green(`Commandable local instance ${ui.reused ? 'ready' : 'running'}.`))
309
+ console.error(`${picocolors.dim('Base URL:')} ${baseUrl}`)
310
+ console.error(`${picocolors.dim('Management UI:')} ${baseUrl}/`)
311
+ console.error(`${picocolors.dim('MCP endpoint:')} ${baseUrl}/mcp`)
312
+ console.error(`${picocolors.dim('Create endpoint:')} ${baseUrl}/mcp/create`)
313
+ console.error(`${picocolors.dim('Data dir:')} ${getCommandableDir()}`)
314
+ console.error(`${picocolors.dim('SQLite:')} ${getSqlitePathForLocalState()}`)
315
+ console.error(`Next: ${picocolors.cyan('npx -y @commandable/mcp create')}`)
316
+ }
317
+
318
+ function runCreate() {
319
+ const transport = (getFlagValue('--transport') || 'stdio').trim().toLowerCase()
320
+ const shouldApply = hasFlag('--apply')
321
+
322
+ if (transport === 'http') {
323
+ const command = makeClaudeCodeHttpAddCommand()
324
+ if (!shouldApply) {
325
+ printCreateInstructions(command, 'HTTP deployment')
326
+ return
327
+ }
328
+ const url = getFlagValue('--url')
329
+ const apiKey = getFlagValue('--api-key')
330
+ if (!url || !apiKey) {
331
+ console.error(`For ${picocolors.cyan('--apply')} with HTTP, pass ${picocolors.cyan('--url')} and ${picocolors.cyan('--api-key')}.`)
332
+ process.exit(1)
333
+ }
334
+ execClaudeMcpAdd(['mcp', 'add', '--transport', 'http', 'commandable', url, '--header', `Authorization: Bearer ${apiKey}`])
335
+ console.error(`${picocolors.green('Done.')} Restart Claude Code.`)
336
+ return
337
+ }
338
+
339
+ return assertLocalServerRunning().then(() => {
340
+ const command = makeClaudeCodeAddCommand()
341
+ if (!shouldApply) {
342
+ printCreateInstructions(command, 'local instance')
343
+ return
344
+ }
345
+ const envArgs = getClaudeCodeEnvEntries().flatMap(value => ['-e', value])
346
+ execClaudeMcpAdd(['mcp', 'add', 'commandable', ...envArgs, '--', 'npx', '-y', '@commandable/mcp-connect', 'create-mode'])
347
+ console.error(`${picocolors.green('Done.')} Restart Claude Code.`)
348
+ })
349
+ }
350
+
351
+ async function runConnect() {
352
+ const transport = (getFlagValue('--transport') || 'stdio').trim().toLowerCase()
353
+ const client = (getFlagValue('--client') || 'claude-desktop').trim().toLowerCase()
354
+ if (client !== 'claude-desktop' && client !== 'cursor') {
355
+ console.error('Invalid --client value. Use claude-desktop or cursor.')
356
+ process.exit(1)
357
+ }
358
+
359
+ if (transport === 'http') {
360
+ console.error(JSON.stringify(makeHttpConnectionDetails(), null, 2))
361
+ return
362
+ }
363
+
364
+ await assertLocalServerRunning()
365
+ console.error(JSON.stringify(makeReadModeConfig(), null, 2))
366
+ }
367
+
368
+ async function runDoctor() {
369
+ const baseUrl = getBaseUrl()
370
+ const pid = readDaemonPid()
371
+ const pidAlive = pid ? isProcessAlive(pid.pid) : false
372
+ const probe = await fetchJsonWithTimeout(`${baseUrl}/api/_commandable/status`, 500).catch(() => null)
373
+ const runningVersion = typeof probe?.json?.version === 'string' && probe.json.version.trim().length
374
+ ? probe.json.version.trim()
375
+ : (pid?.version || null)
376
+ const databaseUrl = process.env.DATABASE_URL
377
+ const sqlitePath = databaseUrl && databaseUrl.trim().length ? null : getSqlitePathForLocalState()
378
+
379
+ console.error(JSON.stringify({
380
+ ok: true,
381
+ installedVersion: COMMANDABLE_VERSION,
382
+ env: {
383
+ COMMANDABLE_SPACE_ID: (process.env.COMMANDABLE_SPACE_ID || 'local').trim() || 'local',
384
+ COMMANDABLE_DATA_DIR: process.env.COMMANDABLE_DATA_DIR || null,
385
+ COMMANDABLE_MCP_SQLITE_PATH: process.env.COMMANDABLE_MCP_SQLITE_PATH || null,
386
+ COMMANDABLE_UI_PORT: getUiPort(),
387
+ DATABASE_URL: databaseUrl && databaseUrl.trim().length ? '[set]' : null,
388
+ },
389
+ localState: {
390
+ dataDir: getCommandableDir(),
391
+ sqlitePath,
392
+ daemonPidPath: daemonPidPath(),
393
+ daemonLogPath: daemonLogPath(),
394
+ encryptionKeyPath: resolve(getCommandableDir(), 'encryption.key'),
395
+ },
396
+ daemon: {
397
+ running: !!(pidAlive && probe?.ok),
398
+ pid: pid ?? null,
399
+ baseUrl,
400
+ runningVersion,
401
+ versionMatch: !!runningVersion && runningVersion === COMMANDABLE_VERSION,
402
+ status: probe?.json ?? null,
403
+ },
404
+ }, null, 2))
405
+ }
406
+
407
+ async function runDestroyLocal() {
408
+ const keepKey = hasFlag('--keep-key')
409
+ if (!hasFlag('--yes')) {
410
+ note(
411
+ [
412
+ picocolors.bold(picocolors.red('This will delete all of your local saved Commandable data.')),
413
+ '',
414
+ `${picocolors.white('•')} saved integrations and credentials`,
415
+ `${picocolors.white('•')} local SQLite state and daemon state`,
416
+ `${picocolors.white('•')} ${keepKey ? 'the encryption key will be kept (--keep-key is set)' : 'the local encryption key'}`,
417
+ '',
418
+ picocolors.yellow('Remote Postgres data will not be deleted.'),
419
+ ].join('\n'),
420
+ picocolors.yellow('Warning'),
421
+ { format: str => str },
422
+ )
423
+ const result = await select({
424
+ message: 'Do you want to continue?',
425
+ options: [
426
+ { value: 'destroy', label: picocolors.red('Yes, destroy local data') },
427
+ { value: 'cancel', label: picocolors.cyan('No, keep local data') },
428
+ ],
429
+ initialValue: 'cancel',
430
+ })
431
+ if (isCancel(result) || result !== 'destroy') {
432
+ console.error(picocolors.yellow('Destroy cancelled.'))
433
+ return
434
+ }
435
+ }
436
+
437
+ const dataDir = getCommandableDir()
438
+ const sqlitePath = getSqlitePathForLocalState()
439
+ const keyPath = resolve(dataDir, 'encryption.key')
440
+ const daemonPath = daemonPidPath()
441
+ const logPath = daemonLogPath()
442
+ const stopped = stopDaemonProcess()
443
+ const removed = []
444
+ const missing = []
445
+
446
+ for (const file of [sqlitePath, daemonPath, logPath, ...(keepKey ? [] : [keyPath])]) {
447
+ if (!existsSync(file)) {
448
+ missing.push(file)
449
+ continue
450
+ }
451
+ unlinkSync(file)
452
+ removed.push(file)
453
+ }
454
+
455
+ console.error(picocolors.green('Local destroy complete.'))
456
+ console.error(`${picocolors.dim('Data dir:')} ${dataDir}`)
457
+ console.error(`${picocolors.dim('Daemon stopped:')} ${stopped.stopped ? 'yes' : 'no'}`)
458
+ if (removed.length)
459
+ console.error(`${picocolors.dim('Removed:')} ${removed.join(', ')}`)
460
+ if (missing.length)
461
+ console.error(`${picocolors.dim('Already absent:')} ${missing.join(', ')}`)
462
+ }
463
+
464
+ async function runApply() {
465
+ const cfgPath = getFlagValue('--config') || process.env.COMMANDABLE_CONFIG_FILE || null
466
+ const { config, path } = loadConfig(cfgPath || undefined)
467
+ const spaceId = process.env.COMMANDABLE_SPACE_ID || config.spaceId || 'local'
468
+ const { db, credentialStore, close } = await openEnvState()
469
+ try {
470
+ const result = await applyConfig({ config, db, credentialStore, defaultSpaceId: spaceId })
471
+ console.error(`${picocolors.green('Config applied.')}`)
472
+ console.error(`${picocolors.dim('File:')} ${path}`)
473
+ console.error(`${picocolors.dim('Space:')} ${result.spaceId}`)
474
+ console.error(`${picocolors.dim('Integrations upserted:')} ${result.integrationsUpserted}`)
475
+ console.error(`${picocolors.dim('Credentials written:')} ${result.credentialsWritten}`)
476
+ console.error(`${picocolors.dim('Credentials unchanged:')} ${result.credentialsUnchanged}`)
477
+ }
478
+ finally {
479
+ await close()
480
+ }
481
+ }
482
+
483
+ async function runCreateApiKey() {
484
+ const name = process.argv[3] && !process.argv[3].startsWith('-') ? String(process.argv[3]) : 'default'
485
+ const rawKey = generateApiKey()
486
+ const id = crypto.randomUUID ? crypto.randomUUID() : crypto.randomBytes(16).toString('hex')
487
+ const { db, close } = await openEnvState()
488
+ try {
489
+ await createApiKey(db, { id, name, rawKey })
490
+ console.error(`${picocolors.green('API key created.')}`)
491
+ console.error(`${picocolors.dim('Name:')} ${name}`)
492
+ console.error(`${picocolors.dim('ID:')} ${id}`)
493
+ console.error(`${picocolors.dim('Key (store this now):')} ${rawKey}`)
494
+ }
495
+ finally {
496
+ await close()
497
+ }
498
+ }
499
+
500
+ function help(exitCode = 0) {
501
+ console.error([
502
+ '',
503
+ picocolors.bold('Commandable MCP'),
504
+ picocolors.dim(`v${COMMANDABLE_VERSION}`),
505
+ '',
506
+ picocolors.bold('Usage'),
507
+ ` ${picocolors.cyan('commandable-mcp serve')} ${picocolors.dim('[--restart]')}`,
508
+ ` ${picocolors.cyan('commandable-mcp create')} ${picocolors.dim('[--transport stdio|http] [--apply] [--url] [--api-key]')}`,
509
+ ` ${picocolors.cyan('commandable-mcp connect')} ${picocolors.dim('[--client claude-desktop|cursor] [--transport stdio|http] [--url] [--api-key]')}`,
510
+ ` ${picocolors.cyan('commandable-mcp doctor')}`,
511
+ ` ${picocolors.cyan('commandable-mcp destroy local')} ${picocolors.dim('[--yes] [--keep-key]')}`,
512
+ ` ${picocolors.cyan('commandable-mcp apply')} ${picocolors.dim('[--config ./commandable.config.yaml]')}`,
513
+ ` ${picocolors.cyan('commandable-mcp create-api-key')} ${picocolors.dim('[name]')}`,
514
+ ` ${picocolors.cyan('commandable-mcp --version')}`,
515
+ '',
516
+ picocolors.bold('Notes'),
517
+ `- ${picocolors.bold('Serve')}: starts or reuses the local Commandable instance.`,
518
+ `- ${picocolors.bold('Create')}: Claude Code authoring flow. Prints or applies ${picocolors.cyan('claude mcp add')}.`,
519
+ `- ${picocolors.bold('Connect')}: prints read-client connection details.`,
520
+ '',
521
+ ].join('\n'))
522
+ process.exit(exitCode)
523
+ }
524
+
525
+ export async function main() {
526
+ const cmd = process.argv[2]
527
+
528
+ if (hasFlag('--version', '-v')) {
529
+ console.error(COMMANDABLE_VERSION)
530
+ process.exit(0)
531
+ }
532
+
533
+ if (hasFlag('--help', '-h'))
534
+ help(0)
535
+
536
+ if (cmd === 'serve')
537
+ return runServe()
538
+ if (cmd === 'create')
539
+ return runCreate()
540
+ if (cmd === 'connect')
541
+ return runConnect()
542
+ if (cmd === 'doctor')
543
+ return runDoctor()
544
+ if (cmd === 'apply')
545
+ return runApply()
546
+ if (cmd === 'create-api-key')
547
+ return runCreateApiKey()
548
+ if (cmd === 'destroy' && (process.argv[3] || '').trim().toLowerCase() === 'local')
549
+ return runDestroyLocal()
550
+
551
+ help(cmd ? 1 : 0)
552
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { main } from './cli.mjs'
4
+
5
+ main().catch((error) => {
6
+ console.error(error)
7
+ process.exit(1)
8
+ })
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@commandable/mcp",
3
- "version": "0.1.2",
4
- "description": "The recursive MCP server. Allows agents to build new MCP servers and tools securely on the fly. One MCP, any app.",
3
+ "version": "0.2.0",
4
+ "description": "Commandable app/server package for local management UI, HTTP endpoints, and human-facing CLI flows.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/commandable/commandable-mcp.git",
9
- "directory": "packages/server"
9
+ "directory": "app"
10
10
  },
11
11
  "homepage": "https://github.com/commandable/commandable-mcp#readme",
12
12
  "bugs": {
@@ -16,53 +16,43 @@
16
16
  "node": ">=18"
17
17
  },
18
18
  "type": "module",
19
- "main": "./dist/index.js",
20
- "types": "./dist/index.d.ts",
21
19
  "bin": {
22
- "commandable-mcp": "./dist/cli/bin.js"
23
- },
24
- "exports": {
25
- ".": {
26
- "types": "./dist/index.d.ts",
27
- "import": "./dist/index.js"
28
- }
20
+ "commandable-mcp": "./bin/commandable-mcp.mjs"
29
21
  },
30
22
  "publishConfig": {
31
23
  "access": "public"
32
24
  },
25
+ "scripts": {
26
+ "build": "nuxt build",
27
+ "dev": "nuxt dev",
28
+ "preview": "nuxt preview",
29
+ "postinstall": "nuxt prepare",
30
+ "lint": "eslint .",
31
+ "test": "echo \"(no app tests)\"",
32
+ "typecheck": "nuxt typecheck",
33
+ "prepack": "npm run build"
34
+ },
33
35
  "dependencies": {
36
+ "@commandable/mcp-core": "0.2.0",
34
37
  "@clack/prompts": "^1.0.1",
35
- "@commandable/integration-data": "0.1.2",
36
- "@modelcontextprotocol/sdk": "^1.27.1",
37
- "better-sqlite3": "^12.4.1",
38
- "drizzle-orm": "^0.44.5",
39
- "fastest-levenshtein": "^1.0.16",
40
- "google-auth-library": "^10.3.0",
41
- "js-yaml": "^4.1.0",
42
- "json-schema": "^0.4.0",
38
+ "@iconify-json/lucide": "^1.2.90",
39
+ "@iconify-json/simple-icons": "^1.2.70",
40
+ "@nuxt/ui": "^4.4.0",
43
41
  "marked": "^17.0.3",
44
- "pg": "^8.16.3",
42
+ "nuxt": "^4.3.1",
45
43
  "picocolors": "^1.1.1",
46
- "turndown": "^7.2.2",
47
- "zod": "^4.1.5"
44
+ "tailwindcss": "^4.1.18"
48
45
  },
49
46
  "devDependencies": {
50
- "@types/better-sqlite3": "^7.6.13",
51
- "@types/js-yaml": "^4.0.9",
52
- "@types/node": "^24.3.0",
53
- "@types/pg": "^8.15.5",
54
- "dotenv": "^17.3.1",
55
- "drizzle-kit": "^0.31.9",
47
+ "@nuxt/eslint": "^1.15.1",
48
+ "eslint": "^10.0.0",
56
49
  "typescript": "^5.9.3",
57
- "vitest": "^3.2.4"
58
- },
59
- "scripts": {
60
- "clean": "node -e \"require('node:fs').rmSync('dist',{ recursive:true, force:true })\"",
61
- "build": "npm run clean && tsc -p tsconfig.json && node -e \"require('node:fs').chmodSync('dist/cli/bin.js', 0o755)\" && node scripts/copy-readme.mjs && node scripts/copy-migrations.mjs",
62
- "dev": "tsc -p tsconfig.json --watch",
63
- "bundle-ui": "yarn workspace commandable-mcp-app build && node scripts/bundle-ui.mjs",
64
- "prepack": "npm run build && npm run bundle-ui",
65
- "db:generate": "drizzle-kit generate",
66
- "test": "vitest run"
67
- }
50
+ "vue-tsc": "^3.2.4"
51
+ },
52
+ "files": [
53
+ ".output",
54
+ "bin",
55
+ "README.md"
56
+ ],
57
+ "packageManager": "yarn@4.12.0"
68
58
  }
@@ -1 +0,0 @@
1
- import{f as z,O as E,F as R,o as a,r as V,w as p,a as n,b as m,G as K,d as v,v as s,I as F,c as r,y as B,B as $,C as j,L as k,K as G,R as J,Q as P,H as S,J as W,e as H,t as w,S as Q,z as X,M as Y,n as q}from"./-tOYwuj2.js";import{u as L,_ as Z,a as ee,d as te,b as oe,c as se}from"./uS7FY2am.js";const ne={class:"space-y-4"},ae={key:0,class:"space-y-2"},le={class:"flex gap-2"},de={key:0,class:"text-xs text-amber-600 dark:text-amber-400"},re={key:1,class:"border border-[var(--ui-border)] rounded-md"},ie={class:"px-3 pb-3 pt-1 space-y-3"},ce={class:"flex justify-end gap-2"},ue=z({__name:"AddIntegrationModal",props:{open:{type:Boolean}},emits:["update:open","created"],async setup(O,{emit:T}){let y,x;const M=O,A=T,f=j({get:()=>M.open,set:c=>A("update:open",c)}),{data:i}=([y,x]=E(()=>L("/api/catalog","$vYIVj-kaX8")),y=await y,x(),y),g=j(()=>(i.value||[]).map(c=>({label:c.type,value:c.type}))),d=k(void 0),u=k(null),l=k([]),t=k([]),h=k(null),b=k(!1);R(f,c=>{c&&(d.value=void 0,u.value=null,l.value=[],t.value=[])}),R(d,()=>{u.value=null,l.value=[],t.value=[]}),R(()=>h.value?.toolsets,c=>{!d.value||!c?.length||l.value.length||(l.value=c.map(o=>o.key))},{deep:!0});async function N(){if(d.value){b.value=!0;try{const o=(h.value?.toolsets||[]).map(e=>e.key).filter(e=>e!=="__all__"),C=o.length&&l.value.length<o.length?l.value.filter(e=>e!=="__all__"):void 0,U=await $fetch("/api/integrations",{method:"POST",body:{type:d.value,maxScope:u.value||void 0,enabledToolsets:C,disabledTools:t.value.length?t.value:void 0}});f.value=!1,A("created",U.id)}finally{b.value=!1}}}return(c,o)=>{const C=ee,U=Z,e=te,I=K,D=G;return a(),V(D,{open:s(f),"onUpdate:open":o[6]||(o[6]=_=>F(f)?f.value=_:null),title:"Add integration",description:"Choose a service to connect."},{body:p(()=>[n("div",ne,[m(U,{label:"Integration type"},{default:p(()=>[m(C,{modelValue:s(d),"onUpdate:modelValue":o[0]||(o[0]=_=>F(d)?d.value=_:null),items:s(g),placeholder:"Select a service...",class:"w-full"},null,8,["modelValue","items"])]),_:1}),s(d)?(a(),r("div",ae,[o[7]||(o[7]=n("div",{class:"text-sm font-medium"}," Access level ",-1)),n("div",le,[n("button",{type:"button",class:B(["px-3 py-1.5 text-sm rounded-md border transition-colors",s(u)!=="read"?"border-green-500 bg-green-50 text-green-700 font-medium dark:bg-green-950 dark:text-green-300":"border-slate-200 text-slate-600 hover:bg-slate-50 dark:border-slate-700 dark:text-slate-400"]),onClick:o[1]||(o[1]=_=>u.value=null)}," Read + Write ",2),n("button",{type:"button",class:B(["px-3 py-1.5 text-sm rounded-md border transition-colors",s(u)==="read"?"border-green-500 bg-green-50 text-green-700 font-medium dark:bg-green-950 dark:text-green-300":"border-slate-200 text-slate-600 hover:bg-slate-50 dark:border-slate-700 dark:text-slate-400"]),onClick:o[2]||(o[2]=_=>u.value="read")}," Read-only ",2)]),s(u)==="read"?(a(),r("p",de," Write/admin tools are greyed out automatically. ")):$("",!0)])):$("",!0),s(d)?(a(),r("details",re,[o[8]||(o[8]=n("summary",{class:"cursor-pointer select-none px-3 py-2 text-sm font-medium"}," Advanced tool controls (optional) ",-1)),n("div",ie,[m(e,{ref_key:"toolsTreeRef",ref:h,"integration-type":s(d),"max-scope":s(u),"enabled-toolsets":s(l),"disabled-tools":s(t),"onUpdate:enabledToolsets":o[3]||(o[3]=_=>l.value=_),"onUpdate:disabledTools":o[4]||(o[4]=_=>t.value=_)},null,8,["integration-type","max-scope","enabled-toolsets","disabled-tools"])])])):$("",!0)])]),footer:p(()=>[n("div",ce,[m(I,{variant:"soft",color:"neutral",onClick:o[5]||(o[5]=_=>f.value=!1)},{default:p(()=>[...o[9]||(o[9]=[v(" Cancel ",-1)])]),_:1}),m(I,{disabled:!s(d)||s(b),loading:s(b),onClick:N},{default:p(()=>[...o[10]||(o[10]=[v(" Add ",-1)])]),_:1},8,["disabled","loading"])])]),_:1},8,["open"])}}}),pe=Object.assign(ue,{__name:"AddIntegrationModal"}),me={class:"flex items-center justify-between gap-4"},_e={key:0,class:"text-sm text-muted py-8 text-center"},ve={key:1,class:"text-sm text-red-600 py-8 text-center"},fe={key:2,class:"py-16 text-center space-y-4"},ye={key:3,class:"space-y-2"},xe={class:"min-w-0 flex-1"},ge={class:"flex items-center gap-2"},be={class:"font-medium truncate"},ke={class:"mt-1 flex items-center gap-2 flex-wrap"},$e={key:1,class:"text-xs text-muted"},Te={key:2,class:"text-xs text-muted"},Ce=z({__name:"index",async setup(O){let T,y;const{data:x,pending:M,error:A,refresh:f}=([T,y]=E(()=>L("/api/integrations","$3JxGA1emOo")),T=await T,y(),T),i=Y({}),g=k(!1);J(async()=>{if(x.value)for(const l of x.value){if(i[l.id]!==void 0)continue;const t=await $fetch(`/api/integrations/${l.id}/credentials-status`).catch(()=>null);i[l.id]=t?.health_status??"disconnected"}});async function d(l,t){await $fetch("/api/integrations",{method:"POST",body:{...l,enabled:t}}),await f()}function u(l){q(`/integrations/${l}`)}return(l,t)=>{const h=K,b=oe,N=se,c=X,o=H,C=pe,U=P;return a(),V(U,{class:"py-10 space-y-6"},{default:p(()=>[n("div",me,[t[5]||(t[5]=n("div",{class:"space-y-1"},[n("h1",{class:"text-2xl font-semibold"}," Integrations "),n("p",{class:"text-sm text-muted"}," Manage your connected services. ")],-1)),m(h,{icon:"i-lucide-plus",onClick:t[0]||(t[0]=e=>g.value=!0)},{default:p(()=>[...t[4]||(t[4]=[v(" Add Integration ",-1)])]),_:1})]),s(M)?(a(),r("div",_e," Loading… ")):s(A)?(a(),r("div",ve," Failed to load integrations. ")):s(x)?.length?(a(),r("div",ye,[(a(!0),r(S,null,W(s(x),e=>(a(),V(o,{key:e.id,to:`/integrations/${e.id}`,class:"flex items-center gap-4 p-4 rounded-lg border border-[var(--ui-border)] hover:bg-[var(--ui-bg-elevated)] transition-colors group"},{default:p(()=>[n("div",xe,[n("div",ge,[n("span",be,w(e.label),1),m(b,{size:"xs",color:"neutral",variant:"subtle"},{default:p(()=>[v(w(e.type),1)]),_:2},1024),e.maxScope==="read"?(a(),V(b,{key:0,size:"xs",color:"warning",variant:"soft"},{default:p(()=>[...t[8]||(t[8]=[v(" Read-only ",-1)])]),_:1})):$("",!0)]),n("div",ke,[s(i)[e.id]!==void 0?(a(),r("span",{key:0,class:B(["inline-flex items-center gap-1 text-xs font-medium px-1.5 py-0.5 rounded",{"bg-green-50 text-green-700 dark:bg-green-950 dark:text-green-400":s(i)[e.id]==="connected","bg-red-50 text-red-700 dark:bg-red-950 dark:text-red-400":s(i)[e.id]==="invalid_credentials"||s(i)[e.id]==="disconnected"}])},[n("span",{class:B(["inline-block w-1.5 h-1.5 rounded-full",{"bg-green-500":s(i)[e.id]==="connected","bg-red-500":s(i)[e.id]==="invalid_credentials"||s(i)[e.id]==="disconnected"}])},null,2),s(i)[e.id]==="connected"?(a(),r(S,{key:0},[v("Connected")],64)):s(i)[e.id]==="invalid_credentials"?(a(),r(S,{key:1},[v("Invalid credentials")],64)):(a(),r(S,{key:2},[v("Not connected")],64))],2)):$("",!0),e.enabledToolsets?.length?(a(),r("span",$e,w(e.enabledToolsets.length)+" toolset"+w(e.enabledToolsets.length===1?"":"s"),1)):$("",!0),e.disabledTools?.length?(a(),r("span",Te,w(e.disabledTools.length)+" tool"+w(e.disabledTools.length===1?"":"s")+" blocked ",1)):$("",!0)])]),n("div",{class:"flex items-center gap-3",onClick:t[2]||(t[2]=Q(()=>{},["prevent","stop"]))},[m(N,{"model-value":e.enabled!==!1,"onUpdate:modelValue":I=>d(e,I)},null,8,["model-value","onUpdate:modelValue"])]),m(c,{name:"i-lucide-chevron-right",class:"text-muted opacity-0 group-hover:opacity-100 transition-opacity shrink-0"})]),_:2},1032,["to"]))),128))])):(a(),r("div",fe,[t[7]||(t[7]=n("div",{class:"text-muted text-sm"}," No integrations yet. ",-1)),m(h,{icon:"i-lucide-plus",variant:"soft",onClick:t[1]||(t[1]=e=>g.value=!0)},{default:p(()=>[...t[6]||(t[6]=[v(" Add your first integration ",-1)])]),_:1})])),m(C,{open:s(g),"onUpdate:open":t[3]||(t[3]=e=>F(g)?g.value=e:null),onCreated:u},null,8,["open"])]),_:1})}}});export{Ce as default};
@@ -1 +0,0 @@
1
- {"id":"b13ec2b2-ddd3-4ead-abd4-4fba9dfc0061","timestamp":1772957882894}
@@ -1 +0,0 @@
1
- {"id":"b13ec2b2-ddd3-4ead-abd4-4fba9dfc0061","timestamp":1772957882894,"prerendered":[]}