specrails-desktop 2.16.0 → 2.17.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 (354) hide show
  1. package/client/dist/assets/{ActivityFeedPage-C_clKk8d.js → ActivityFeedPage-BLDMBgwL.js} +1 -1
  2. package/client/dist/assets/AgentsPage-CFaIiyAA.js +86 -0
  3. package/client/dist/assets/{AnalyticsPage-DZkVU3yd.js → AnalyticsPage-DY8ECq2R.js} +1 -1
  4. package/client/dist/assets/{BarChart-Dq1h8eYR.js → BarChart-ouivqe5L.js} +2 -2
  5. package/client/dist/assets/CodePage-DAFtRafz.js +2 -0
  6. package/client/dist/assets/{DesktopAnalyticsPage-CYhXhJoQ.js → DesktopAnalyticsPage-DIMhuuv0.js} +1 -1
  7. package/client/dist/assets/{DocsDialog-CS3Syf61.js → DocsDialog-DBYhv3SM.js} +2 -2
  8. package/client/dist/assets/{DocsPage-l3ZcTO2E.js → DocsPage-DeLRn8W_.js} +2 -2
  9. package/client/dist/assets/{ExportDropdown-DdB2ncYh.js → ExportDropdown-2XwQ08sz.js} +1 -1
  10. package/client/dist/assets/{IntegrationsPage-CJ_Om1zu.js → IntegrationsPage-DB-a4FDV.js} +3 -3
  11. package/client/dist/assets/JobDetailPage-C3lljMiV.js +16 -0
  12. package/client/dist/assets/JobsPage-CzquwJ6G.js +1 -0
  13. package/client/dist/assets/LoopBuilderPage-TkoalfW5.js +7 -0
  14. package/client/dist/assets/LoopsPage-ypooVAQ5.js +1 -0
  15. package/client/dist/assets/{agents-CQlu1nOm.js → agents-4fnKlwcG.js} +1 -1
  16. package/client/dist/assets/{agents-DcoUUFZl.js → agents-B-rVIhuw.js} +1 -1
  17. package/client/dist/assets/{agents-DVYpVGur.js → agents-BRUz6RJs.js} +1 -1
  18. package/client/dist/assets/{agents-DCX9D3-Q.js → agents-CZQvKDIb.js} +1 -1
  19. package/client/dist/assets/{agents-BYjUOrLD.js → agents-CuRY-Zg_.js} +1 -1
  20. package/client/dist/assets/{agents-Jc-CjBDB.js → agents-D7nWnLg6.js} +1 -1
  21. package/client/dist/assets/{agents-CIhRSOna.js → agents-DzhSlNZd.js} +1 -1
  22. package/client/dist/assets/{agents-1lhqEcXH.js → agents-E-42N3b1.js} +1 -1
  23. package/client/dist/assets/{cssMode-DSHXamUH.js → cssMode-BijCvCxs.js} +1 -1
  24. package/client/dist/assets/{dist-js-Ele_sHO7.js → dist-js-D7m9--SN.js} +1 -1
  25. package/client/dist/assets/{dist-js-D27I-bfi.js → dist-js-nZhsq1qo.js} +1 -1
  26. package/client/dist/assets/{editor.main-Cd8qBRAT.js → editor.main-DMIcqwXb.js} +2 -2
  27. package/client/dist/assets/{freemarker2-CkEKTBm2.js → freemarker2-CP2AizpZ.js} +1 -1
  28. package/client/dist/assets/{handlebars-BRGx0JpL.js → handlebars-8ElanPOm.js} +1 -1
  29. package/client/dist/assets/{html-BfRIaGgN.js → html-Mu3b73tG.js} +1 -1
  30. package/client/dist/assets/{htmlMode-BTpSnsDE.js → htmlMode-tHprGCEv.js} +1 -1
  31. package/client/dist/assets/index-CDEQ4aU_.js +144 -0
  32. package/client/dist/assets/{javascript-DMmE2kKN.js → javascript-DlG0apUe.js} +1 -1
  33. package/client/dist/assets/{jsonMode-hYuaUleY.js → jsonMode-Cr0T4SXO.js} +1 -1
  34. package/client/dist/assets/{lib-qdRfWwE1.js → lib-Bu76JzdB.js} +2 -2
  35. package/client/dist/assets/{liquid-C-VbuTr7.js → liquid-QgTgbClC.js} +1 -1
  36. package/client/dist/assets/{lspLanguageFeatures-BALx-vjn.js → lspLanguageFeatures-D-BxkRza.js} +1 -1
  37. package/client/dist/assets/mcp-BSCAtU6Y.js +1 -0
  38. package/client/dist/assets/mcp-Cb6fUaFJ.js +1 -0
  39. package/client/dist/assets/mcp-CyP0quZ7.js +1 -0
  40. package/client/dist/assets/mcp-D-zQCO5E.js +1 -0
  41. package/client/dist/assets/mcp-DCTNWpfB.js +1 -0
  42. package/client/dist/assets/mcp-DEFGJ1OJ.js +1 -0
  43. package/client/dist/assets/mcp-DFG9OEXM.js +1 -0
  44. package/client/dist/assets/mcp-DyERgHA2.js +1 -0
  45. package/client/dist/assets/{mdx-Cs8MNCzn.js → mdx-B2QTaeRe.js} +1 -1
  46. package/client/dist/assets/{monaco.contribution-CIvCAJs4.js → monaco.contribution-CkdGfXCC.js} +2 -2
  47. package/client/dist/assets/{python-CGShLxuI.js → python-BlF0qnMQ.js} +1 -1
  48. package/client/dist/assets/{razor-CvOBQGd5.js → razor--3PSy3lb.js} +1 -1
  49. package/client/dist/assets/setup-BiQ7ut8d.js +1 -0
  50. package/client/dist/assets/setup-BxvjG5Xp.js +1 -0
  51. package/client/dist/assets/setup-CQ-F6Ciq.js +1 -0
  52. package/client/dist/assets/setup-D2JlpJEz.js +1 -0
  53. package/client/dist/assets/setup-DG1R6J6o.js +1 -0
  54. package/client/dist/assets/setup-DuFJZJsm.js +1 -0
  55. package/client/dist/assets/setup-DyJszDqm.js +1 -0
  56. package/client/dist/assets/setup-Ynw19V8w.js +1 -0
  57. package/client/dist/assets/{tsMode-04uOpiiP.js → tsMode-CHfsvcOI.js} +1 -1
  58. package/client/dist/assets/{typescript-CX0CwyIZ.js → typescript-Bjxf6BOp.js} +1 -1
  59. package/client/dist/assets/{upload-DPG87J4t.js → upload-x42OZJr2.js} +1 -1
  60. package/client/dist/assets/{value-BRVOAvhY.js → value-fEDhg5Bd.js} +1 -1
  61. package/client/dist/assets/{workers-yr2u4c3C.js → workers-CAAvSda9.js} +1 -1
  62. package/client/dist/assets/{xml-C0OFlt5X.js → xml-iYCSJ4oL.js} +1 -1
  63. package/client/dist/assets/{yaml-DgabaPs5.js → yaml-DtO-_yDY.js} +1 -1
  64. package/client/dist/index.html +10 -9
  65. package/docs/README.md +2 -0
  66. package/docs/guide/de/integrations/5-mcp-server.md +74 -0
  67. package/docs/guide/en/integrations/5-mcp-server.md +74 -0
  68. package/docs/guide/es/integrations/5-mcp-server.md +74 -0
  69. package/docs/guide/fr/integrations/5-mcp-server.md +74 -0
  70. package/docs/guide/it/integrations/5-mcp-server.md +74 -0
  71. package/docs/guide/ja/integrations/5-mcp-server.md +74 -0
  72. package/docs/guide/pt/integrations/5-mcp-server.md +74 -0
  73. package/docs/guide/zh/integrations/5-mcp-server.md +74 -0
  74. package/docs/mcp.md +249 -0
  75. package/package.json +8 -5
  76. package/server/dist/index.js +30 -0
  77. package/server/dist/mcp/guide.js +82 -0
  78. package/server/dist/mcp/index.js +21 -0
  79. package/server/dist/mcp/mcp-admin-router.js +71 -0
  80. package/server/dist/mcp/mcp-server.js +143 -0
  81. package/server/dist/mcp/mcp-tiers.js +48 -0
  82. package/server/dist/mcp/mcp-token.js +119 -0
  83. package/server/dist/mcp/resources.js +24 -0
  84. package/server/dist/mcp/tools/agents.js +319 -0
  85. package/server/dist/mcp/tools/analytics.js +168 -0
  86. package/server/dist/mcp/tools/app-settings.js +81 -0
  87. package/server/dist/mcp/tools/catalog.js +45 -0
  88. package/server/dist/mcp/tools/chat.js +147 -0
  89. package/server/dist/mcp/tools/code.js +145 -0
  90. package/server/dist/mcp/tools/jira.js +222 -0
  91. package/server/dist/mcp/tools/jobs.js +258 -0
  92. package/server/dist/mcp/tools/loops.js +229 -0
  93. package/server/dist/mcp/tools/meta.js +96 -0
  94. package/server/dist/mcp/tools/plugins.js +83 -0
  95. package/server/dist/mcp/tools/projects.js +62 -0
  96. package/server/dist/mcp/tools/rails.js +181 -0
  97. package/server/dist/mcp/tools/setup.js +187 -0
  98. package/server/dist/mcp/tools/specs.js +327 -0
  99. package/server/dist/mcp/tools/types.js +137 -0
  100. package/server/dist/mcp/tools/watch.js +93 -0
  101. package/server/dist/mobile/mobile-event-bus.js +2 -0
  102. package/server/dist/project-router-tickets.js +2 -2
  103. package/server/dist/rails-router.js +5 -0
  104. package/client/dist/assets/AgentsPage-jcPUtPhP.js +0 -86
  105. package/client/dist/assets/CodePage-BcbZT88K.js +0 -2
  106. package/client/dist/assets/JobDetailPage-D5Cxw0md.js +0 -16
  107. package/client/dist/assets/JobsPage-3v_iX83r.js +0 -1
  108. package/client/dist/assets/LoopBuilderPage-4s_adZy5.js +0 -7
  109. package/client/dist/assets/LoopsPage-DA94-o0j.js +0 -1
  110. package/client/dist/assets/index-meTWPBzY.js +0 -144
  111. package/client/dist/assets/setup-BOmQ4vh2.js +0 -1
  112. package/client/dist/assets/setup-BwO2-kuK.js +0 -1
  113. package/client/dist/assets/setup-CUTNWz-0.js +0 -1
  114. package/client/dist/assets/setup-Cf3hjChU.js +0 -1
  115. package/client/dist/assets/setup-CsuXrbJ2.js +0 -1
  116. package/client/dist/assets/setup-Df4cJOqu.js +0 -1
  117. package/client/dist/assets/setup-Do0fWx6W.js +0 -1
  118. package/client/dist/assets/setup-GlkDhBlJ.js +0 -1
  119. /package/client/dist/assets/{abap-CK68cr9-.js → abap-BFJA_Joo.js} +0 -0
  120. /package/client/dist/assets/{activity-D4dhNEwO.js → activity-BXBMi28x.js} +0 -0
  121. /package/client/dist/assets/{activity-usnNa7FX.js → activity-By6I70Ws.js} +0 -0
  122. /package/client/dist/assets/{activity-BbNkUmW4.js → activity-CfedQaof.js} +0 -0
  123. /package/client/dist/assets/{activity-B2MvEH54.js → activity-D62CDlQz.js} +0 -0
  124. /package/client/dist/assets/{activity-DHjfmAyT.js → activity-DAFuSwnt.js} +0 -0
  125. /package/client/dist/assets/{activity-C7VdmeGb.js → activity-Did0FnrH.js} +0 -0
  126. /package/client/dist/assets/{activity-Di2f50_Z.js → activity-oLgwaVyt.js} +0 -0
  127. /package/client/dist/assets/{addon-image-biWX2UUm.js → addon-image-bPlduuUZ.js} +0 -0
  128. /package/client/dist/assets/{addon-ligatures-D4EiDb5r.js → addon-ligatures-BexpF7xb.js} +0 -0
  129. /package/client/dist/assets/{addon-webgl-CDCIZQ03.js → addon-webgl-Zy4IOieH.js} +0 -0
  130. /package/client/dist/assets/{addspec-BxMn39wn.js → addspec-B2fTENuq.js} +0 -0
  131. /package/client/dist/assets/{addspec-DAveBiCE.js → addspec-BmggyuCD.js} +0 -0
  132. /package/client/dist/assets/{addspec-1HEtmLv1.js → addspec-CFsLeQKV.js} +0 -0
  133. /package/client/dist/assets/{addspec-DfuR6EAl.js → addspec-CkHI5c5H.js} +0 -0
  134. /package/client/dist/assets/{addspec-CO1xv6BL.js → addspec-Cvm06hGe.js} +0 -0
  135. /package/client/dist/assets/{addspec-IozoiiGs.js → addspec-DwoLTocx.js} +0 -0
  136. /package/client/dist/assets/{addspec-CNyAUGz_.js → addspec-gthH-H1g.js} +0 -0
  137. /package/client/dist/assets/{agentstudio-Q0Sq_jTg.js → agentstudio-BtASTJl7.js} +0 -0
  138. /package/client/dist/assets/{agentstudio-9NbsoGXk.js → agentstudio-CIe9C892.js} +0 -0
  139. /package/client/dist/assets/{agentstudio-B-jQgYV-.js → agentstudio-CYGk-jjo.js} +0 -0
  140. /package/client/dist/assets/{agentstudio-Bwa72b1S.js → agentstudio-CwiS3BTp.js} +0 -0
  141. /package/client/dist/assets/{agentstudio-B1y0JWY-.js → agentstudio-D0bQBWpI.js} +0 -0
  142. /package/client/dist/assets/{agentstudio-DCyDW8sy.js → agentstudio-Dq-bZrI3.js} +0 -0
  143. /package/client/dist/assets/{agentstudio-1E-bag77.js → agentstudio-n0pmwz2I.js} +0 -0
  144. /package/client/dist/assets/{aiedit-qTGI_PGs.js → aiedit-1Z-UYKFb.js} +0 -0
  145. /package/client/dist/assets/{aiedit-CGxeml8D.js → aiedit-BAJM9Cch.js} +0 -0
  146. /package/client/dist/assets/{aiedit-CfBNanHE.js → aiedit-CYnsp1Iv.js} +0 -0
  147. /package/client/dist/assets/{aiedit-CvSspQmE.js → aiedit-CZBZAyeK.js} +0 -0
  148. /package/client/dist/assets/{aiedit-kAU7KADg.js → aiedit-CunYxmW0.js} +0 -0
  149. /package/client/dist/assets/{aiedit-DUpe7NxI.js → aiedit-s1T1EMK8.js} +0 -0
  150. /package/client/dist/assets/{aiedit-DSLtsYIu.js → aiedit-uIDh2tlc.js} +0 -0
  151. /package/client/dist/assets/{analytics-DBGO8B6-.js → analytics-B95FiMuD.js} +0 -0
  152. /package/client/dist/assets/{analytics-CgEkAUiP.js → analytics-DPIkvuTS.js} +0 -0
  153. /package/client/dist/assets/{analytics-DDqve9Ma.js → analytics-DPmCEzvJ.js} +0 -0
  154. /package/client/dist/assets/{analytics-D1ElChhs.js → analytics-DRexho82.js} +0 -0
  155. /package/client/dist/assets/{analytics-DEsEAJZL.js → analytics-DVFNjjAv.js} +0 -0
  156. /package/client/dist/assets/{analytics-BDlELxc7.js → analytics-DZKGAUdm.js} +0 -0
  157. /package/client/dist/assets/{analytics-CQqu1yE5.js → analytics-g9ASAR_r.js} +0 -0
  158. /package/client/dist/assets/{apex-BHHyAVNb.js → apex-C1f-z6NO.js} +0 -0
  159. /package/client/dist/assets/{atom-one-dark-DrWoEEbZ.js → atom-one-dark-CT4DolNR.js} +0 -0
  160. /package/client/dist/assets/{attachments-3CuBBRFu.js → attachments--jr2QLGv.js} +0 -0
  161. /package/client/dist/assets/{attachments-pW3zm9nu.js → attachments-BgqfeoOx.js} +0 -0
  162. /package/client/dist/assets/{attachments-BNgH6Tcu.js → attachments-Bj3HHTXV.js} +0 -0
  163. /package/client/dist/assets/{attachments-D5fVsMgb.js → attachments-C3skjFyH.js} +0 -0
  164. /package/client/dist/assets/{attachments-UJtEq892.js → attachments-CnPS8YWu.js} +0 -0
  165. /package/client/dist/assets/{attachments-CppM7de8.js → attachments-DejzxE0C.js} +0 -0
  166. /package/client/dist/assets/{attachments-BLqqPGyy.js → attachments-FFb2xHc_.js} +0 -0
  167. /package/client/dist/assets/{azcli-C56lfIEP.js → azcli-Dr0WBJTP.js} +0 -0
  168. /package/client/dist/assets/{bat-BLamSaf-.js → bat-BKG3k49W.js} +0 -0
  169. /package/client/dist/assets/{bicep-lrOcEItS.js → bicep-DXs2wTcS.js} +0 -0
  170. /package/client/dist/assets/{browser-C91MQBxx.js → browser-BS9t1qMc.js} +0 -0
  171. /package/client/dist/assets/{browser-B7i7Ysc8.js → browser-BpMo-amf.js} +0 -0
  172. /package/client/dist/assets/{browser-DwE289IS.js → browser-CsC3NOZ-.js} +0 -0
  173. /package/client/dist/assets/{browser-C__Vz7KR.js → browser-DS6xnywt.js} +0 -0
  174. /package/client/dist/assets/{browser-DhwTc0ry.js → browser-Dm6F9bqQ.js} +0 -0
  175. /package/client/dist/assets/{browser-EFmPpkvO.js → browser-Dm_Of27q.js} +0 -0
  176. /package/client/dist/assets/{browser-BVQgd1_1.js → browser-U3iouSXn.js} +0 -0
  177. /package/client/dist/assets/{cameligo-BK_p0bgU.js → cameligo-Detknuxp.js} +0 -0
  178. /package/client/dist/assets/{chat-PVakYp92.js → chat-B2tWTbZL.js} +0 -0
  179. /package/client/dist/assets/{chat-BnJPyeUK.js → chat-CXOJHDUZ.js} +0 -0
  180. /package/client/dist/assets/{chat-CE8bx6Rz.js → chat-Cy78lw1n.js} +0 -0
  181. /package/client/dist/assets/{chat-UMl6H55K.js → chat-D78VMi-v.js} +0 -0
  182. /package/client/dist/assets/{chat-BXVx6rb5.js → chat-De1RgOXU.js} +0 -0
  183. /package/client/dist/assets/{chat-C5nJF6L0.js → chat-DyTbH-0F.js} +0 -0
  184. /package/client/dist/assets/{chat-9RcD5Lcn.js → chat-sqZyn0C4.js} +0 -0
  185. /package/client/dist/assets/{clojure-BQ7JOykv.js → clojure-CCu4UNKg.js} +0 -0
  186. /package/client/dist/assets/{clsx-CjLeUJfG.js → clsx-pVRQNNR0.js} +0 -0
  187. /package/client/dist/assets/{code-u9Sg9ohM.js → code-6LokPmIE.js} +0 -0
  188. /package/client/dist/assets/{code-OoLqhjoI.js → code-CLTuhuvM.js} +0 -0
  189. /package/client/dist/assets/{code-Lg4awa35.js → code-CwGlPuwb.js} +0 -0
  190. /package/client/dist/assets/{code-BPMR8_Vp.js → code-DFCDV5e1.js} +0 -0
  191. /package/client/dist/assets/{code-eh4vO2-_.js → code-Djq48g0s.js} +0 -0
  192. /package/client/dist/assets/{code-aCUqkVN_.js → code-Do27r8WG.js} +0 -0
  193. /package/client/dist/assets/{code-BsOBm1Fb.js → code-Drc7f197.js} +0 -0
  194. /package/client/dist/assets/{coffee-BD3DiL5s.js → coffee-Bam7Y9IR.js} +0 -0
  195. /package/client/dist/assets/{commands-B9XEyMj-.js → commands-CxReviyc.js} +0 -0
  196. /package/client/dist/assets/{commands-Ic1DJDxm.js → commands-CzP1qQyD.js} +0 -0
  197. /package/client/dist/assets/{commands-BdI0CtOL.js → commands-DGP46UxM.js} +0 -0
  198. /package/client/dist/assets/{commands-DSX3yJyr.js → commands-DQvoMqa7.js} +0 -0
  199. /package/client/dist/assets/{commands-yNn4IA4C.js → commands-DeKaz04Q.js} +0 -0
  200. /package/client/dist/assets/{commands-BI1Ta-E7.js → commands-DwYhwQsF.js} +0 -0
  201. /package/client/dist/assets/{commands-C2ewlyXo.js → commands-lm6Vlght.js} +0 -0
  202. /package/client/dist/assets/{common-CzCQ0rpW.js → common-B0crwfK0.js} +0 -0
  203. /package/client/dist/assets/{common-CNoRVpnA.js → common-BlqmiTj4.js} +0 -0
  204. /package/client/dist/assets/{common-CcHFVATT.js → common-CIUPtPdu.js} +0 -0
  205. /package/client/dist/assets/{common-LDwESeCX.js → common-C_-0fZsp.js} +0 -0
  206. /package/client/dist/assets/{common-C9VyfY7g.js → common-DH9A-wTo.js} +0 -0
  207. /package/client/dist/assets/{common-Dmpyh323.js → common-DJM41wFl.js} +0 -0
  208. /package/client/dist/assets/{common-ULlk84G4.js → common-SyTaRc_K.js} +0 -0
  209. /package/client/dist/assets/{cpp-splnCwCh.js → cpp-BhOkAe-9.js} +0 -0
  210. /package/client/dist/assets/{csharp-BCpsl-o3.js → csharp-BgHArJNx.js} +0 -0
  211. /package/client/dist/assets/{csp-tkCWrZmb.js → csp-Xzh56_3-.js} +0 -0
  212. /package/client/dist/assets/{css-B_xdnReq.js → css-CD7-RYRS.js} +0 -0
  213. /package/client/dist/assets/{cypher-OL1zq-y3.js → cypher-l2xAdF3X.js} +0 -0
  214. /package/client/dist/assets/{dart-CtTlOkrm.js → dart-CDOWeyzt.js} +0 -0
  215. /package/client/dist/assets/{dashboard-C-dXxut-.js → dashboard-B1rs1wki.js} +0 -0
  216. /package/client/dist/assets/{dashboard-CUjyhohl.js → dashboard-D9QPCmv3.js} +0 -0
  217. /package/client/dist/assets/{dashboard-C52PElPV.js → dashboard-Dxgb47lO.js} +0 -0
  218. /package/client/dist/assets/{dashboard-03EpOoMM.js → dashboard-TuElRCZX.js} +0 -0
  219. /package/client/dist/assets/{dashboard-Ch6H-457.js → dashboard-UWXs9_wy.js} +0 -0
  220. /package/client/dist/assets/{dashboard-zH9quXks.js → dashboard-ajT8usAi.js} +0 -0
  221. /package/client/dist/assets/{dashboard-C2owt3eN.js → dashboard-zwN2xswo.js} +0 -0
  222. /package/client/dist/assets/{dockerfile-DcQ5CNiW.js → dockerfile-Dv8atx7v.js} +0 -0
  223. /package/client/dist/assets/{ecl-DZpiDRt6.js → ecl-DIYTlbD_.js} +0 -0
  224. /package/client/dist/assets/{editor.api2-Cwla1nvV.js → editor.api2-CrNrMVfe.js} +0 -0
  225. /package/client/dist/assets/{elixir-Dzj2lqtK.js → elixir-CR7PLJja.js} +0 -0
  226. /package/client/dist/assets/{explore-4SD1DxR0.js → explore-BYFCCka4.js} +0 -0
  227. /package/client/dist/assets/{explore-xQoaak6e.js → explore-CE0wSNV1.js} +0 -0
  228. /package/client/dist/assets/{explore-CZt4Ncpa.js → explore-CSDcRUNj.js} +0 -0
  229. /package/client/dist/assets/{explore-DQ0XEjed.js → explore-CvM08PpD.js} +0 -0
  230. /package/client/dist/assets/{explore-CCcPXrHg.js → explore-Jkw93usp.js} +0 -0
  231. /package/client/dist/assets/{explore-BxR9q8Hq.js → explore-kK239uoZ.js} +0 -0
  232. /package/client/dist/assets/{explore-B2n8r9Ye.js → explore-mLI5eXks.js} +0 -0
  233. /package/client/dist/assets/{flow9-CFENCHIZ.js → flow9-DCK5-6NG.js} +0 -0
  234. /package/client/dist/assets/{format-command-CMsBTOPN.js → format-command-rVyGPxWE.js} +0 -0
  235. /package/client/dist/assets/{fsharp-D-4bv7FB.js → fsharp-DJ1xiUVU.js} +0 -0
  236. /package/client/dist/assets/{go-djxbTJq7.js → go-BEvbHcbb.js} +0 -0
  237. /package/client/dist/assets/{graphql-DHIFrkZ6.js → graphql-DN1ktXnz.js} +0 -0
  238. /package/client/dist/assets/{hcl-CXVoowNb.js → hcl-DJaIjIEr.js} +0 -0
  239. /package/client/dist/assets/{ini-Crzc5kly.js → ini-PlKfLEnb.js} +0 -0
  240. /package/client/dist/assets/{integrations-A9f08E0o.js → integrations-B8hT0Qf_.js} +0 -0
  241. /package/client/dist/assets/{integrations-DwSVdCpf.js → integrations-Bdk5dMyv.js} +0 -0
  242. /package/client/dist/assets/{integrations-B46ac3sf.js → integrations-CYqz7YFS.js} +0 -0
  243. /package/client/dist/assets/{integrations-9qxUNhPD.js → integrations-Cj_BsXxJ.js} +0 -0
  244. /package/client/dist/assets/{integrations-B17KyA-i.js → integrations-D8M8eJH2.js} +0 -0
  245. /package/client/dist/assets/{integrations-DkBi-Gsh.js → integrations-TJuDBl-9.js} +0 -0
  246. /package/client/dist/assets/{integrations-C7u7SInG.js → integrations-TwQV3sLw.js} +0 -0
  247. /package/client/dist/assets/{java-CYLaJrdE.js → java-3PUwMlx-.js} +0 -0
  248. /package/client/dist/assets/{jira-01H1RfQj.js → jira--rI5PfuE.js} +0 -0
  249. /package/client/dist/assets/{jira-CBU0200d.js → jira-BoRyckbb.js} +0 -0
  250. /package/client/dist/assets/{jira-BpnpUFlb.js → jira-C95FN3yk.js} +0 -0
  251. /package/client/dist/assets/{jira-DzIVvNmy.js → jira-CNUUgTs4.js} +0 -0
  252. /package/client/dist/assets/{jira-Dht8qNck.js → jira-DHFnvEm8.js} +0 -0
  253. /package/client/dist/assets/{jira-4Fin3fu7.js → jira-NhkbrDXe.js} +0 -0
  254. /package/client/dist/assets/{jira-0ldfMByG.js → jira-wiIvGma5.js} +0 -0
  255. /package/client/dist/assets/{jobs-Oz3UtLQn.js → jobs-Bjp7v9aA.js} +0 -0
  256. /package/client/dist/assets/{jobs-jEQidSIb.js → jobs-Bjt5PyVv.js} +0 -0
  257. /package/client/dist/assets/{jobs-BF9raUkL.js → jobs-BmTs4Bn3.js} +0 -0
  258. /package/client/dist/assets/{jobs-DcCONARH.js → jobs-Cchy-18B.js} +0 -0
  259. /package/client/dist/assets/{jobs-DM9owF1j.js → jobs-D2QVTPbz.js} +0 -0
  260. /package/client/dist/assets/{jobs-Bw4hqEro.js → jobs-LK1ImiDH.js} +0 -0
  261. /package/client/dist/assets/{jobs-ym72SIR9.js → jobs-yPz4Dvi-.js} +0 -0
  262. /package/client/dist/assets/{julia-BJ7tUU-T.js → julia-DC6LnY15.js} +0 -0
  263. /package/client/dist/assets/{kotlin-CeWcU3lC.js → kotlin-CoGntbZF.js} +0 -0
  264. /package/client/dist/assets/{less-CviwWNG4.js → less-DCFflTXL.js} +0 -0
  265. /package/client/dist/assets/{lexon-Dt28jqDS.js → lexon-BTOivnjP.js} +0 -0
  266. /package/client/dist/assets/{loops-Fv4Bs-9A.js → loops-BFIcYvpy.js} +0 -0
  267. /package/client/dist/assets/{loops-D_ZxkD4l.js → loops-BU314kSd.js} +0 -0
  268. /package/client/dist/assets/{loops-DE-2cmLw.js → loops-C3OaXou9.js} +0 -0
  269. /package/client/dist/assets/{loops-mcoeFMat.js → loops-Cv6Aeszq.js} +0 -0
  270. /package/client/dist/assets/{loops-B_w7STrw.js → loops-IQe23ef6.js} +0 -0
  271. /package/client/dist/assets/{loops-BYNUJVyD.js → loops-LqZ4MC6J.js} +0 -0
  272. /package/client/dist/assets/{loops-B_gS4Pqu.js → loops-SbkOdciY.js} +0 -0
  273. /package/client/dist/assets/{lua-B6AOaJSi.js → lua-ClKCZMmP.js} +0 -0
  274. /package/client/dist/assets/{m3-VnMkHJcy.js → m3-25hKFWMb.js} +0 -0
  275. /package/client/dist/assets/{markdown-8vKNdvIM.js → markdown-BGAj9q0K.js} +0 -0
  276. /package/client/dist/assets/{mips-DoEcuzan.js → mips-BrVgY2Pf.js} +0 -0
  277. /package/client/dist/assets/{msdax-CNzvHyEp.js → msdax-7EhcRsm8.js} +0 -0
  278. /package/client/dist/assets/{mysql-Buk3vUtL.js → mysql-B5_atCBH.js} +0 -0
  279. /package/client/dist/assets/{nav-_0vAgZ_k.js → nav-B2Cv1vjz.js} +0 -0
  280. /package/client/dist/assets/{nav-Cw3_40fA.js → nav-Br2AivTc.js} +0 -0
  281. /package/client/dist/assets/{nav-DNDJ3H-_.js → nav-CFofO7QO.js} +0 -0
  282. /package/client/dist/assets/{nav-CCz4krPP.js → nav-CyHKTZxn.js} +0 -0
  283. /package/client/dist/assets/{nav-B5W9IMnf.js → nav-DqyLGJmF.js} +0 -0
  284. /package/client/dist/assets/{nav-CrG_mYRr.js → nav-_-siCrRv.js} +0 -0
  285. /package/client/dist/assets/{nav-DbAbG5_k.js → nav-rO4Nqnh-.js} +0 -0
  286. /package/client/dist/assets/{nav-DVp1nEsi.js → nav-zyBhf29M.js} +0 -0
  287. /package/client/dist/assets/{objective-c-DfOmda-5.js → objective-c-CLUvUl9T.js} +0 -0
  288. /package/client/dist/assets/{pascal-DoAA2yjy.js → pascal-BnU1HU42.js} +0 -0
  289. /package/client/dist/assets/{pascaligo-C65Vn1fu.js → pascaligo-dsKvjFzi.js} +0 -0
  290. /package/client/dist/assets/{perl-INlfQ_ro.js → perl-CZne1GYG.js} +0 -0
  291. /package/client/dist/assets/{pgsql-DtwRzglx.js → pgsql-CMa5W_iF.js} +0 -0
  292. /package/client/dist/assets/{php-DfHqVNet.js → php-Cu4mS35J.js} +0 -0
  293. /package/client/dist/assets/{pla-D3dNVRYk.js → pla-B7COwnnm.js} +0 -0
  294. /package/client/dist/assets/{postiats-UKXD1rM4.js → postiats-GLeNtnBQ.js} +0 -0
  295. /package/client/dist/assets/{powerquery-zE3E3O7s.js → powerquery-BqPf3R1W.js} +0 -0
  296. /package/client/dist/assets/{powershell-Df9b3zQl.js → powershell-D9btb5su.js} +0 -0
  297. /package/client/dist/assets/{protobuf-BF0nUVrW.js → protobuf-6GHSuaNm.js} +0 -0
  298. /package/client/dist/assets/{pug-Bj6Yikv_.js → pug-ct6rYKQd.js} +0 -0
  299. /package/client/dist/assets/{qsharp-BI4h-raZ.js → qsharp-CIrAQNPy.js} +0 -0
  300. /package/client/dist/assets/{r-DhpnmaXx.js → r-Bk-a0sON.js} +0 -0
  301. /package/client/dist/assets/{redis-DwYYPr4d.js → redis-C9yfaWYh.js} +0 -0
  302. /package/client/dist/assets/{redshift-D2f3Bc-4.js → redshift-DaOT1jRU.js} +0 -0
  303. /package/client/dist/assets/{restructuredtext-Dkiif6fe.js → restructuredtext-C1t9LQfS.js} +0 -0
  304. /package/client/dist/assets/{ruby-C6hLmHy0.js → ruby-COiPZJjc.js} +0 -0
  305. /package/client/dist/assets/{rust-X8WAGtxB.js → rust--gZOJZzj.js} +0 -0
  306. /package/client/dist/assets/{sb-4M2la0Kr.js → sb-NHf3iazF.js} +0 -0
  307. /package/client/dist/assets/{scala-CaCXz58E.js → scala-D1nO1TBd.js} +0 -0
  308. /package/client/dist/assets/{scheme-CMdjpmP7.js → scheme-Bref42s5.js} +0 -0
  309. /package/client/dist/assets/{scss-QopmvPyp.js → scss-BS9CCLr3.js} +0 -0
  310. /package/client/dist/assets/{settings-DyBxunCh.js → settings-BN4dufu6.js} +0 -0
  311. /package/client/dist/assets/{settings-BN7OusER.js → settings-Bap_q3rt.js} +0 -0
  312. /package/client/dist/assets/{settings-Bi5FFkIw.js → settings-BlYjWMy5.js} +0 -0
  313. /package/client/dist/assets/{settings-iQe5Dim-.js → settings-C7t_uUz4.js} +0 -0
  314. /package/client/dist/assets/{settings-fk-WlnUt.js → settings-CIFrUsKt.js} +0 -0
  315. /package/client/dist/assets/{settings-BA1V6KdK.js → settings-Cbj9VWmI.js} +0 -0
  316. /package/client/dist/assets/{settings-CRJxyTNN.js → settings-D7saHMU8.js} +0 -0
  317. /package/client/dist/assets/{settings-0m2iuTzd.js → settings-DrRjM5e8.js} +0 -0
  318. /package/client/dist/assets/{shell-CDBchS00.js → shell-DT3joMBB.js} +0 -0
  319. /package/client/dist/assets/{solidity-DvBfi5mC.js → solidity-o2Fm9dvg.js} +0 -0
  320. /package/client/dist/assets/{sophia-HSnXR17u.js → sophia-Dj1N6Xqb.js} +0 -0
  321. /package/client/dist/assets/{sparql-DhG_ppup.js → sparql-D2fjpTWm.js} +0 -0
  322. /package/client/dist/assets/{specs-BvsFNKTs.js → specs-C-WXGBqy.js} +0 -0
  323. /package/client/dist/assets/{specs-D4ORogcT.js → specs-C57koADY.js} +0 -0
  324. /package/client/dist/assets/{specs-CnH7dOiF.js → specs-CCXV-eSF.js} +0 -0
  325. /package/client/dist/assets/{specs-CUE3xSFM.js → specs-CYA5Bv7Q.js} +0 -0
  326. /package/client/dist/assets/{specs-C2wW5bq8.js → specs-DFCFg51O.js} +0 -0
  327. /package/client/dist/assets/{specs-C_8j4ELZ.js → specs-Dslng_yW.js} +0 -0
  328. /package/client/dist/assets/{specs-D6Y76Bgi.js → specs-DwRPiJTc.js} +0 -0
  329. /package/client/dist/assets/{specs-Bku8SypT.js → specs-DzlROLy7.js} +0 -0
  330. /package/client/dist/assets/{sql-DHeIS-tf.js → sql-BArhsPUz.js} +0 -0
  331. /package/client/dist/assets/{st-CMWchiRU.js → st-Bd2-tALj.js} +0 -0
  332. /package/client/dist/assets/{swift-CDXvBefj.js → swift-DvEpXBKj.js} +0 -0
  333. /package/client/dist/assets/{systemverilog-0RTukYUE.js → systemverilog-mHEbsnVH.js} +0 -0
  334. /package/client/dist/assets/{tcl-CbBF_Ttl.js → tcl-DePutp1e.js} +0 -0
  335. /package/client/dist/assets/{terminal-CB33IsO1.js → terminal-2S-Wsk6L.js} +0 -0
  336. /package/client/dist/assets/{terminal-Cz_Puz0q.js → terminal-BRQMrU74.js} +0 -0
  337. /package/client/dist/assets/{terminal-DFEH9XTQ.js → terminal-BTiemy98.js} +0 -0
  338. /package/client/dist/assets/{terminal-BTanJIt_.js → terminal-CjQeWfpp.js} +0 -0
  339. /package/client/dist/assets/{terminal-CY_sPfdD.js → terminal-CmP5riTU.js} +0 -0
  340. /package/client/dist/assets/{terminal-BLh00ouM.js → terminal-CnObBCAh.js} +0 -0
  341. /package/client/dist/assets/{terminal-CR6t-Oey.js → terminal-DcPKgKMN.js} +0 -0
  342. /package/client/dist/assets/{terminal-Cj4HzP3p.js → terminal-XciDq6VV.js} +0 -0
  343. /package/client/dist/assets/{tickets-OrJwUxJR.js → tickets-7kl_0jgM.js} +0 -0
  344. /package/client/dist/assets/{tickets-68LH1xp6.js → tickets-BSyaZI8d.js} +0 -0
  345. /package/client/dist/assets/{tickets-blQnNA4N.js → tickets-CcTcvwKS.js} +0 -0
  346. /package/client/dist/assets/{tickets-D6f3GSYn.js → tickets-D75vyZJj.js} +0 -0
  347. /package/client/dist/assets/{tickets-PtHNxQo5.js → tickets-D79ZT2SZ.js} +0 -0
  348. /package/client/dist/assets/{tickets-DBQXMYYA.js → tickets-DbcMWq5L.js} +0 -0
  349. /package/client/dist/assets/{tickets-jxsTrApR.js → tickets-ZA_2iPd1.js} +0 -0
  350. /package/client/dist/assets/{tickets-REr-EQx9.js → tickets-mxd23fWX.js} +0 -0
  351. /package/client/dist/assets/{twig-DCcGd8FE.js → twig-DQ2zIX0b.js} +0 -0
  352. /package/client/dist/assets/{typespec-HTphp-Uh.js → typespec-DPoaiGTJ.js} +0 -0
  353. /package/client/dist/assets/{vb-Cb_yUcVd.js → vb-Jo98wdMr.js} +0 -0
  354. /package/client/dist/assets/{wgsl-DrKU3YXj.js → wgsl-DZc4h_eS.js} +0 -0
package/docs/mcp.md ADDED
@@ -0,0 +1,249 @@
1
+ # The Specrails MCP server
2
+
3
+ Specrails Desktop can expose itself to **any MCP client** — Claude Desktop,
4
+ Claude Code, Cursor, or your own agent — as a local
5
+ [Model Context Protocol](https://modelcontextprotocol.io) server. Turn it on
6
+ and an external LLM can drive the whole dashboard: list your projects, read and
7
+ create specs, launch the AI pipeline, watch jobs settle, inspect analytics, and
8
+ more — through ~18 well-described tools instead of clicking around the UI.
9
+
10
+ > **Just want to get going?** Open **Settings ▸ MCP**, flip **Enable MCP** on,
11
+ > click **Copy client config**, and paste it into your MCP client. By default
12
+ > only **read** actions are allowed; turn on the **Write** / **AI-spawn** /
13
+ > **Destructive** tiers when you want the agent to actually change things or
14
+ > spend money. Everything below is detail for when you need it.
15
+
16
+ This is the **app talking to an outside agent** — the opposite direction from
17
+ the [Serena plugin](running-pipelines.md#plugins) or
18
+ `codex mcp add`, where Specrails *consumes* an MCP server. Here Specrails *is*
19
+ the server.
20
+
21
+ The MCP server is **off by default** and entirely local: it listens only on
22
+ loopback (`127.0.0.1`), is authenticated by a token separate from the app's
23
+ master token, and serves nothing until you explicitly enable it in Settings.
24
+
25
+ ## What the MCP exposes
26
+
27
+ When enabled, the server registers a compact catalog of **domain-facade tools**
28
+ plus a few **meta tools**, a set of read-only **resources**, and a self-contained
29
+ **guide** an LLM can read to learn the platform with no prior knowledge.
30
+
31
+ ### Tools (~18)
32
+
33
+ Each domain is a single tool with an `action` enum, rather than dozens of
34
+ narrow tools — so the catalog stays small and an agent discovers actions by
35
+ reading one description. The tools are:
36
+
37
+ | Tool | What it covers |
38
+ |---|---|
39
+ | `specrails_projects` | List / resolve projects; unregister (destructive) |
40
+ | `specrails_specs` | The spec/ticket backlog: list, get, create, update, delete, drafts, AI generate, AI-edit, Contract Refine, SMASH, per-ticket spend |
41
+ | `specrails_rails` | Assign tickets to a rail, configure it, and launch the pipeline |
42
+ | `specrails_jobs` | Inspect, stream, and stop pipeline jobs |
43
+ | `specrails_chat` | Explore / sidebar chat conversations and turns |
44
+ | `specrails_agents` | Agent profiles and the agents catalog (Claude-only features) |
45
+ | `specrails_plugins` | The per-project plugin marketplace (install / verify / uninstall) |
46
+ | `specrails_jira` | The Jira integration (connect, sync, outbox) |
47
+ | `specrails_loops` | Saved loop workflows |
48
+ | `specrails_code` | The read-only code explorer (tree, file, summaries, provenance) |
49
+ | `specrails_setup` | Add-project setup wizard surface |
50
+ | `specrails_analytics` | Per-project spending analytics + budget |
51
+ | `specrails_settings` | App-level settings |
52
+ | `specrails_watch` | Await the real result of an async (cost-incurring) action |
53
+ | `specrails_guide` | Returns the platform guide — read this first |
54
+ | `specrails_search` | Find the right tool/action for an intent |
55
+ | `specrails_describe` | Full description + input schema for a named tool |
56
+ | `specrails_select_project` | Set an active project so later calls can omit `projectId` |
57
+
58
+ Almost every domain tool is **project-scoped** and takes a `projectId`. Calling
59
+ `specrails_select_project` first lets later calls omit it.
60
+
61
+ ### Resources
62
+
63
+ Read-only state is also exposed as MCP **resources** so a client can fetch it
64
+ without a tool call:
65
+
66
+ - `specrails://guide` — the platform guide (concepts, workflow, invariants).
67
+ - `specrails://projects` — all registered projects.
68
+ - `specrails://projects/{projectId}` — a single project.
69
+
70
+ ### Async results — `specrails_watch`
71
+
72
+ Cost-incurring and streaming actions (launch a rail, generate a spec, send a
73
+ chat turn, AI-edit, Contract Refine, SMASH) **return immediately** with a
74
+ reference (a `jobId` / `requestId`) and emit their **real** result over the
75
+ app's WebSocket bus. An agent gets the actual outcome by calling
76
+ `specrails_watch` with that reference; it waits for the operation to settle and
77
+ returns the final result. Don't assume success from the acceptance alone — this
78
+ is spelled out in `specrails_guide`.
79
+
80
+ ## The four permission tiers
81
+
82
+ Every tool declares one tier. The server refuses any tool whose tier is not
83
+ enabled, and the refusal **names the tier the user must turn on** so the agent
84
+ can relay it rather than retrying blindly. The tiers are **opt-in and
85
+ cumulative** — read is always on, the rest are off until you enable them in
86
+ **Settings ▸ MCP**:
87
+
88
+ | Tier | Default | What it allows |
89
+ |---|---|---|
90
+ | **Read** | Always on | Queries + resources (list specs, read analytics, inspect jobs) |
91
+ | **Write** | Off | Mutating but non-destructive, non-spawn: create/edit specs, change settings, configure a rail |
92
+ | **AI-spawn** | Off | Actions that spawn an AI CLI and **cost money**: launch a rail, generate a spec, send a chat turn |
93
+ | **Destructive** | Off | Delete data, kill processes, or mutate an external system (e.g. unregister a project, `smash_undo`, Jira writes) |
94
+
95
+ The split is deliberate: a client you only half-trust can be left read-only;
96
+ **destructive and cost-incurring actions are opt-in** and never happen by
97
+ accident. A tool's tier is dynamic per action — e.g. `specrails_specs(list)` is
98
+ read while `specrails_specs(delete)` is destructive — so the same tool exposes
99
+ different actions at different trust levels.
100
+
101
+ ## Enabling it
102
+
103
+ 1. Open the app and go to **Settings ▸ MCP**.
104
+ 2. Toggle **Enable MCP**. This boots the embedded transport immediately — no
105
+ app restart. (Behind the scenes it persists `mcp_enabled` and starts serving
106
+ `/api/mcp`.)
107
+ 3. Enable the permission tiers you want (**Write** / **AI-spawn** /
108
+ **Destructive**). Leave them off to keep the agent read-only.
109
+ 4. Click **Copy client config** to grab a ready-to-paste configuration, or
110
+ **Copy token** if your client needs the raw token (for the direct-HTTP path
111
+ below).
112
+
113
+ Toggling the enable switch off again tears down all open MCP sessions
114
+ immediately.
115
+
116
+ ## Connecting a client
117
+
118
+ There are two ways to connect, and **the stdio bridge is the recommended,
119
+ universal one.**
120
+
121
+ ### Option A — the stdio bridge `specrails-mcp` (recommended)
122
+
123
+ Most MCP clients (Claude Desktop, Claude Code, Cursor) speak MCP over **stdio**:
124
+ they launch a command and talk to it on stdin/stdout. Specrails ships a tiny
125
+ relay, **`specrails-mcp`**, bundled with the app. It transparently forwards MCP
126
+ stdio from your client to the embedded HTTP server on loopback — and it reads
127
+ the scoped token from `~/.specrails/mcp.token` **locally**, so the token never
128
+ appears in your client's config file.
129
+
130
+ A typical client config looks like:
131
+
132
+ ```json
133
+ {
134
+ "mcpServers": {
135
+ "specrails": {
136
+ "command": "specrails-mcp"
137
+ }
138
+ }
139
+ }
140
+ ```
141
+
142
+ Use the exact command/path from the panel's **Copy client config** button — it
143
+ fills in the path to the bundled bridge for your platform. No token, no URL, no
144
+ port to manage; the bridge handles all of it. If the Specrails app isn't
145
+ running, the bridge replies with a clear *"Specrails app is not running. Start
146
+ the Specrails Desktop app, then retry."* rather than a cryptic connection error.
147
+
148
+ ### Option B — the direct HTTP URL (remote-HTTP clients)
149
+
150
+ Clients that speak MCP's **streamable-HTTP** transport directly can skip the
151
+ bridge and connect to:
152
+
153
+ ```
154
+ http://127.0.0.1:4200/api/mcp
155
+ ```
156
+
157
+ with the scoped token as a bearer header:
158
+
159
+ ```
160
+ Authorization: Bearer <your mcp token>
161
+ ```
162
+
163
+ Get the token from **Settings ▸ MCP ▸ Copy token** (or read
164
+ `~/.specrails/mcp.token`). The endpoint is **loopback-only** — it rejects any
165
+ request that doesn't originate from `127.0.0.1`, so this path is for local
166
+ HTTP-capable clients, not for exposing Specrails on a network. (`4200` is the
167
+ default app port; if you've changed it, the panel's config reflects the real
168
+ one.)
169
+
170
+ ## Security model
171
+
172
+ - **A scoped token, not the master token.** The MCP surface is authenticated by
173
+ its own token at `~/.specrails/mcp.token` (mode `0600`), completely separate
174
+ from the app's all-powerful master token (`~/.specrails/desktop.token`). The
175
+ master token grants terminals (shell), arbitrary AI-CLI spawns, and project
176
+ admin; handing that to a third-party MCP client would be a security smell. The
177
+ scoped token only reaches the four tiered surfaces above. You can rotate it
178
+ any time with **Regenerate token** in Settings — the old token stops working
179
+ immediately.
180
+ - **Loopback only.** Both the transport (`/api/mcp`) and the admin control plane
181
+ (`/api/mcp-admin`) require the request to come from `127.0.0.1`. There is no
182
+ network ingress; an MCP client must run on the same machine.
183
+ - **Tiers, not blanket access.** Even with a valid token, an agent can only do
184
+ what the enabled tiers allow (read by default). High-risk actions stay opt-in.
185
+ - **The app must be running.** The MCP server is embedded in the desktop app's
186
+ process — there is no standalone daemon. The Tauri shell keeps it alive even
187
+ when you close the main window: closing the window **minimizes to the system
188
+ tray / menu bar** and leaves the embedded server running, so your MCP client
189
+ stays connected. The server stops only when you choose **Exit** from the tray
190
+ menu (or the OS truly quits the app). If the app isn't running, the bridge
191
+ tells you to start it.
192
+
193
+ ## v1 limitations — what is *not* exposed
194
+
195
+ The tool catalog deliberately leaves the highest-risk execution vectors out of
196
+ v1. None of these are reachable over MCP:
197
+
198
+ - **Terminal shell execution.** The built-in terminal panel runs arbitrary
199
+ shell commands; the MCP surface does **not** expose it. An agent cannot run
200
+ shell on your machine through Specrails.
201
+ - **Browser capture.** No browser navigation / screenshot / capture tool.
202
+ - **In-app file write.** The code explorer is **read-only** over MCP — there is
203
+ no source-file overwrite tool (`code_write_file`). An agent can read files and
204
+ AI-generated summaries, but cannot edit your code directly through MCP. (AI
205
+ *rails* still write code — that's the pipeline, gated behind the AI-spawn
206
+ tier — but there is no direct file-overwrite tool.)
207
+ - **The prerequisite installer.** The `uv`/remote-script prerequisite installer
208
+ is not exposed, so an agent cannot trigger remote-script installs.
209
+ - The global Claude marketplace / `~/.claude/settings.json` mutation is also
210
+ out of scope.
211
+
212
+ These boundaries are intentional and may be revisited in a later version.
213
+
214
+ ## Troubleshooting
215
+
216
+ **My client can't connect / "app is not running"** — start the Specrails
217
+ Desktop app. The MCP server is embedded in the app process; it isn't a separate
218
+ daemon. If the window is hidden, the app is still running in the tray/menu bar —
219
+ look for the Specrails icon there. Only the tray **Exit** stops the server.
220
+
221
+ **Every tool is refused with a "permission tier" message** — the action needs a
222
+ tier you haven't enabled. Open **Settings ▸ MCP** and turn on **Write** /
223
+ **AI-spawn** / **Destructive** as appropriate. Read-only actions work with no
224
+ extra tiers.
225
+
226
+ **`401 Unauthorized: invalid MCP token`** (direct-HTTP path) — the bearer token
227
+ is wrong or stale. Re-copy it from **Settings ▸ MCP ▸ Copy token**, or
228
+ **Regenerate token** and update your client. The stdio bridge avoids this
229
+ entirely (it reads the token locally).
230
+
231
+ **The agent assumed a rail succeeded but it didn't** — cost-incurring actions
232
+ return a reference, not a result. The agent must call `specrails_watch` with the
233
+ returned `jobId`/`requestId` to get the real outcome. This is documented in
234
+ `specrails_guide`; point the agent at it.
235
+
236
+ **Connection refused on `:4200`** — that's the default app port. If you changed
237
+ the port in Settings, use the URL from **Copy client config**, which reflects
238
+ the real port. The bridge resolves the port automatically.
239
+
240
+ ## See also
241
+
242
+ - [Running pipelines](running-pipelines.md) — what rails, jobs, and the
243
+ pipeline an MCP client drives actually do.
244
+ - [Creating specs](creating-specs.md) — specs, drafts, SMASH, and Contract
245
+ Refine, all reachable via `specrails_specs`.
246
+ - [Tracking cost](tracking-cost.md) — the analytics an agent reads via
247
+ `specrails_analytics`.
248
+ - [Customising the app](customizing.md) — other settings, including the budget
249
+ the AI-spawn tier respects.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specrails-desktop",
3
- "version": "2.16.0",
3
+ "version": "2.17.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,15 +24,16 @@
24
24
  "dev:server": "tsx watch server/index.ts",
25
25
  "dev:client": "cd client && npm run dev",
26
26
  "dev:desktop": "tauri dev",
27
- "build:server": "node -e \"require('fs').rmSync('server/dist',{recursive:true,force:true})\" && tsc --project tsconfig.json",
27
+ "build:server": "node -e \"require('fs').rmSync('server/dist',{recursive:true,force:true})\" && tsc --project tsconfig.build.json --noCheck",
28
28
  "build:cli": "tsc --project tsconfig.cli.json",
29
29
  "build": "npm run build:server && cd client && npm run build && cd .. && npm run build:cli",
30
30
  "build:sidecar": "node scripts/build-sidecar.mjs",
31
- "build:desktop": "npm run build:server && cd client && npm run build && cd .. && npm run build:sidecar && tauri build",
31
+ "build:mcp-bridge": "node scripts/build-mcp-bridge.mjs",
32
+ "build:desktop": "npm run build:server && cd client && npm run build && cd .. && npm run build:sidecar && npm run build:mcp-bridge && tauri build",
32
33
  "assemble-runtimes": "node scripts/assemble-runtimes-local.mjs",
33
34
  "build:desktop:local": "npm run assemble-runtimes && npm run build:desktop",
34
35
  "generate-icons": "tauri icon src-tauri/icons/icon.svg",
35
- "typecheck": "tsc --noEmit && tsc -p tsconfig.cli.json --noEmit && cd client && tsc --noEmit",
36
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.cli.json --noEmit && tsc -p mcp-bridge/tsconfig.json --noEmit && cd client && tsc --noEmit",
36
37
  "check-core-compat": "tsx scripts/check-core-compat.ts",
37
38
  "test": "vitest run && tsx scripts/check-core-compat.ts",
38
39
  "test:watch": "vitest",
@@ -42,6 +43,7 @@
42
43
  "ci": "npm run typecheck && npm run check-core-compat && npm run test:coverage && cd client && npm run test:coverage"
43
44
  },
44
45
  "dependencies": {
46
+ "@modelcontextprotocol/sdk": "^1.29.0",
45
47
  "@tailwindcss/typography": "^0.5.19",
46
48
  "ajv": "^8.17.1",
47
49
  "better-sqlite3": "^12.8.0",
@@ -57,7 +59,8 @@
57
59
  "selfsigned": "^5.5.0",
58
60
  "tree-kill": "^1.2.2",
59
61
  "werift": "^0.23.0",
60
- "ws": "^8.16.0"
62
+ "ws": "^8.16.0",
63
+ "zod": "^3.25.76"
61
64
  },
62
65
  "devDependencies": {
63
66
  "@tauri-apps/cli": "^2.0.0",
@@ -23,6 +23,7 @@ const terminal_manager_1 = require("./terminal-manager");
23
23
  const terminal_shell_integration_1 = require("./terminal-shell-integration");
24
24
  const feature_flags_1 = require("./feature-flags");
25
25
  const mobile_1 = require("./mobile");
26
+ const mcp_1 = require("./mcp");
26
27
  const browser_playwright_1 = require("./browser-playwright");
27
28
  const telemetry_receiver_1 = require("./telemetry-receiver");
28
29
  const telemetry_compactor_1 = require("./telemetry-compactor");
@@ -150,6 +151,20 @@ app.use(corsMiddleware);
150
151
  // 12mb limit FIRST — once it sets req._body the global parser below no-ops for
151
152
  // these paths. (The actual /otlp router still requires loopback.)
152
153
  app.use('/otlp', express_1.default.json({ limit: '12mb' }));
154
+ // ─── MCP streamable-HTTP transport (design D1) ───────────────────────────────
155
+ // Mounted BEFORE the global express.json so it claims `/api/mcp` with a larger
156
+ // body limit (req._body makes the global parser no-op for this path), and
157
+ // BEFORE `app.use('/api', requireAuth)` so it uses the SCOPED mcp token via
158
+ // requireMcpAuth rather than inheriting the all-powerful master token. The
159
+ // dispatcher delegates to the McpServerManager constructed during Super-mode
160
+ // bootstrap (lazily referenced — it exists by request time).
161
+ app.use('/api/mcp', express_1.default.json({ limit: '4mb' }), auth_1.requireLoopback, mcp_1.requireMcpAuth, (req, res) => {
162
+ if (_mcpManager) {
163
+ void _mcpManager.handleHttp(req, res);
164
+ return;
165
+ }
166
+ res.status(503).json({ jsonrpc: '2.0', error: { code: -32000, message: 'MCP transport not ready' }, id: null });
167
+ });
153
168
  app.use(express_1.default.json({ limit: '1mb' }));
154
169
  const server = http_1.default.createServer(app);
155
170
  const wsServerOptions = {
@@ -219,6 +234,7 @@ let _getProjectCount = () => 0;
219
234
  let _registry = null;
220
235
  /** The mobile companion gateway (off by default); torn down on shutdown. */
221
236
  let _mobileGateway = null;
237
+ let _mcpManager = null;
222
238
  server.on('upgrade', (request, socket, head) => {
223
239
  const urlStr = request.url ?? '/';
224
240
  const auth = authorizeUpgrade(request);
@@ -507,6 +523,19 @@ function applyPtyWsRateLimiting(ws) {
507
523
  if (mobileGateway.isEnabledSetting()) {
508
524
  mobileGateway.start().catch((err) => console.error('[mobile-gateway] boot start failed:', err));
509
525
  }
526
+ // ─── Embedded MCP server (the /api/mcp transport mounted above) ─────────────
527
+ const mcpManager = new mcp_1.McpServerManager({ registry, broadcast, desktopPort: port, version: PKG_VERSION });
528
+ _mcpManager = mcpManager;
529
+ // Loopback + master-token control plane for the Settings ▸ MCP panel.
530
+ app.use('/api/mcp-admin', auth_1.requireLoopback, (0, mcp_1.createMcpAdminRouter)({
531
+ manager: mcpManager,
532
+ desktopDb: registry.desktopDb,
533
+ desktopPort: port,
534
+ broadcast,
535
+ }));
536
+ if (mcpManager.isEnabledSetting()) {
537
+ mcpManager.start().catch((err) => console.error('[mcp] boot start failed:', err));
538
+ }
510
539
  // App-level routes. CRITICAL mount order: the desktop router is mounted at
511
540
  // '/api' BEFORE the project router below so its exact routes (e.g.
512
541
  // GET /api/projects, DELETE /api/projects/:id) are handled here, while
@@ -611,6 +640,7 @@ async function shutdown() {
611
640
  catch { /* ignore */ }
612
641
  try {
613
642
  await _mobileGateway?.stop();
643
+ await _mcpManager?.stop();
614
644
  }
615
645
  catch { /* ignore */ }
616
646
  try {
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ // The platform guide returned by the `specrails_guide` meta tool and the
3
+ // `specrails://guide` resource. This is what lets an external LLM "understand
4
+ // the platform" without prior knowledge. It is intentionally English (the LLM
5
+ // consumes it); human-facing onboarding docs are localized separately.
6
+ //
7
+ // Keep this BYTE-STABLE where possible (no timestamps / live data) so MCP
8
+ // clients that cache resources stay valid.
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.SPECRAILS_GUIDE = void 0;
11
+ exports.SPECRAILS_GUIDE = `# Specrails Desktop — Agent Guide
12
+
13
+ You are operating Specrails Desktop through its MCP server. Specrails is a local
14
+ dashboard + pipeline runner that manages multiple software projects and drives AI
15
+ coding agents (Claude Code, Codex, Gemini) to implement specs.
16
+
17
+ ## Core concepts
18
+
19
+ - **Project**: a registered repository. Almost every tool is project-scoped and
20
+ takes a \`projectId\`. Use \`specrails_select_project\` to set an active project so
21
+ you can omit \`projectId\` on later calls; pass an explicit \`projectId\` to override.
22
+ - **Spec / ticket**: a unit of work in a project's backlog. Statuses: \`draft\`,
23
+ \`todo\`, \`in_progress\`, \`done\`, \`cancelled\`. Priorities: \`critical\`, \`high\`,
24
+ \`medium\`, \`low\`. INVARIANT: priority may be null ONLY when status is \`draft\`.
25
+ - **Rail**: a launch slot that runs the AI pipeline over one or more assigned
26
+ tickets. Modes: \`implement\`, \`batch-implement\`, \`ultracode\`, \`loop\`. Launching a
27
+ rail spawns AI CLI processes that write code, run tests and commit — it costs
28
+ money and runs for minutes.
29
+ - **Job**: one spawned pipeline run. Jobs stream logs/events over the WebSocket
30
+ and settle (completed/failed/canceled). Cost is authoritative for Claude and
31
+ estimated for Codex/Gemini.
32
+ - **Profile**: a per-project agent configuration (which agents, which models,
33
+ routing). Profiles are CLAUDE-ONLY; they are ignored for Codex/Gemini rails.
34
+ - **Provider / engine**: claude, codex, or gemini. A project installs one or
35
+ more. A requested provider must be one of the project's installed providers.
36
+ - **Loop**: a saved, app-driven workflow graph runnable on a rail in \`loop\` mode.
37
+ - **Plugin**: an MCP-based integration installed per project (e.g. serena).
38
+
39
+ ## Async results (IMPORTANT)
40
+
41
+ Cost-incurring / streaming actions (launch a rail, generate a spec, send a chat
42
+ turn, refine an agent, SMASH) return immediately with a reference (jobId /
43
+ requestId) and emit their REAL result over the WebSocket bus. To get the actual
44
+ outcome, call \`specrails_watch\` with the returned reference; it waits for the
45
+ operation to settle and returns the final result. Do not assume success from the
46
+ acceptance alone.
47
+
48
+ ## Permission tiers
49
+
50
+ The server enforces four opt-in tiers, configured by the user in Settings ▸ MCP:
51
+ - **Read** (always on): queries + resources.
52
+ - **Write**: create/edit specs, settings, rail config.
53
+ - **AI-spawn**: actions that spawn an AI CLI and cost money.
54
+ - **Destructive**: delete data, kill processes, mutate external systems.
55
+
56
+ If a tool is refused, the error names the tier the user must enable. Relay that
57
+ to the user rather than retrying blindly.
58
+
59
+ ## Claude-only features
60
+
61
+ Agent profiles, Contract Refine, and SMASH are Claude-only. They are unavailable
62
+ (and rejected) on projects whose selected provider is Codex or Gemini.
63
+
64
+ ## Typical workflow
65
+
66
+ 1. \`specrails_projects(list)\` → pick a project; \`specrails_select_project\`.
67
+ 2. \`specrails_specs(list)\` → inspect the backlog. To ADD a spec from a user
68
+ request, use \`specrails_specs(action:'create')\` — it routes through **Quick
69
+ Add Spec**: the specrails agent generates a structured spec with AI from the
70
+ request, exactly like the app's "Add Spec" button (so MCP-created specs are
71
+ indistinguishable from UI-created ones). It is async — watch the returned ref
72
+ with \`specrails_watch\`. Use \`from_prompt\` only to store a finished spec verbatim.
73
+ 3. \`specrails_rails(set_tickets)\` then \`specrails_rails(launch)\` → run the pipeline;
74
+ \`specrails_watch\` the returned jobId.
75
+ 4. \`specrails_analytics(spending)\` → review cost.
76
+
77
+ ## Resources
78
+
79
+ Read-only state is also exposed as MCP resources: \`specrails://projects\`,
80
+ \`specrails://projects/{id}/tickets\`, \`specrails://projects/{id}/rails\`,
81
+ \`specrails://projects/{id}/analytics\`, and \`specrails://guide\` (this document).
82
+ `;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildToolSpecs = exports.TIER_SETTING_KEY = exports.MCP_ENABLED_KEY = exports.MCP_TIERS = exports.isTierEnabled = exports.isMcpEnabled = exports._resetMcpTokenForTest = exports.loadOrGenerateMcpToken = exports.regenerateMcpToken = exports.getMcpToken = exports.requireMcpAuth = exports.createMcpAdminRouter = exports.McpServerManager = void 0;
4
+ var mcp_server_1 = require("./mcp-server");
5
+ Object.defineProperty(exports, "McpServerManager", { enumerable: true, get: function () { return mcp_server_1.McpServerManager; } });
6
+ var mcp_admin_router_1 = require("./mcp-admin-router");
7
+ Object.defineProperty(exports, "createMcpAdminRouter", { enumerable: true, get: function () { return mcp_admin_router_1.createMcpAdminRouter; } });
8
+ var mcp_token_1 = require("./mcp-token");
9
+ Object.defineProperty(exports, "requireMcpAuth", { enumerable: true, get: function () { return mcp_token_1.requireMcpAuth; } });
10
+ Object.defineProperty(exports, "getMcpToken", { enumerable: true, get: function () { return mcp_token_1.getMcpToken; } });
11
+ Object.defineProperty(exports, "regenerateMcpToken", { enumerable: true, get: function () { return mcp_token_1.regenerateMcpToken; } });
12
+ Object.defineProperty(exports, "loadOrGenerateMcpToken", { enumerable: true, get: function () { return mcp_token_1.loadOrGenerateMcpToken; } });
13
+ Object.defineProperty(exports, "_resetMcpTokenForTest", { enumerable: true, get: function () { return mcp_token_1._resetMcpTokenForTest; } });
14
+ var mcp_tiers_1 = require("./mcp-tiers");
15
+ Object.defineProperty(exports, "isMcpEnabled", { enumerable: true, get: function () { return mcp_tiers_1.isMcpEnabled; } });
16
+ Object.defineProperty(exports, "isTierEnabled", { enumerable: true, get: function () { return mcp_tiers_1.isTierEnabled; } });
17
+ Object.defineProperty(exports, "MCP_TIERS", { enumerable: true, get: function () { return mcp_tiers_1.MCP_TIERS; } });
18
+ Object.defineProperty(exports, "MCP_ENABLED_KEY", { enumerable: true, get: function () { return mcp_tiers_1.MCP_ENABLED_KEY; } });
19
+ Object.defineProperty(exports, "TIER_SETTING_KEY", { enumerable: true, get: function () { return mcp_tiers_1.TIER_SETTING_KEY; } });
20
+ var catalog_1 = require("./tools/catalog");
21
+ Object.defineProperty(exports, "buildToolSpecs", { enumerable: true, get: function () { return catalog_1.buildToolSpecs; } });
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMcpAdminRouter = createMcpAdminRouter;
4
+ const express_1 = require("express");
5
+ const mcp_token_1 = require("./mcp-token");
6
+ const desktop_db_1 = require("../desktop-db");
7
+ const mcp_tiers_1 = require("./mcp-tiers");
8
+ function tierState(db) {
9
+ return {
10
+ write: (0, mcp_tiers_1.isTierEnabled)(db, 'write'),
11
+ aiSpawn: (0, mcp_tiers_1.isTierEnabled)(db, 'ai-spawn'),
12
+ destructive: (0, mcp_tiers_1.isTierEnabled)(db, 'destructive'),
13
+ };
14
+ }
15
+ function redact(token) {
16
+ return token.length > 4 ? `…${token.slice(-4)}` : '…';
17
+ }
18
+ function createMcpAdminRouter(deps) {
19
+ const router = (0, express_1.Router)();
20
+ const { manager, desktopDb, desktopPort } = deps;
21
+ router.get('/status', (_req, res) => {
22
+ res.json({ ...manager.status(), tiers: tierState(desktopDb), tokenHint: redact((0, mcp_token_1.getMcpToken)()) });
23
+ });
24
+ router.post('/enable', async (_req, res) => {
25
+ try {
26
+ res.json(await manager.setEnabled(true));
27
+ }
28
+ catch (err) {
29
+ res.status(409).json({ error: err instanceof Error ? err.message : 'Failed to enable MCP' });
30
+ }
31
+ });
32
+ router.post('/disable', async (_req, res) => {
33
+ res.json(await manager.setEnabled(false));
34
+ });
35
+ // Update the opt-in permission tiers (read is always on, not settable here).
36
+ router.patch('/tiers', (req, res) => {
37
+ const body = (req.body ?? {});
38
+ const fields = [
39
+ ['write', 'write'],
40
+ ['aiSpawn', 'ai-spawn'],
41
+ ['destructive', 'destructive'],
42
+ ];
43
+ for (const [bodyKey, tier] of fields) {
44
+ if (bodyKey in body) {
45
+ if (typeof body[bodyKey] !== 'boolean') {
46
+ res.status(400).json({ error: `${bodyKey} must be a boolean` });
47
+ return;
48
+ }
49
+ (0, desktop_db_1.setDesktopSetting)(desktopDb, mcp_tiers_1.TIER_SETTING_KEY[tier], body[bodyKey] ? 'true' : 'false');
50
+ }
51
+ }
52
+ res.json({ ok: true, tiers: tierState(desktopDb) });
53
+ });
54
+ // The full token — deliberately a separate loopback-only action so it never
55
+ // leaks through a general settings payload. Used by the panel's copy button.
56
+ router.get('/token', (_req, res) => {
57
+ res.json({ token: (0, mcp_token_1.getMcpToken)() });
58
+ });
59
+ router.post('/regenerate-token', (_req, res) => {
60
+ res.json({ token: (0, mcp_token_1.regenerateMcpToken)() });
61
+ });
62
+ // Connection info for the panel to render a ready-to-paste client config.
63
+ router.get('/config', (_req, res) => {
64
+ res.json({
65
+ httpUrl: `http://127.0.0.1:${desktopPort}/api/mcp`,
66
+ bridgeCommand: 'specrails-mcp',
67
+ hasToken: true,
68
+ });
69
+ });
70
+ return router;
71
+ }