@oomol-lab/open-connector 1.6.5 → 1.8.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 (495) hide show
  1. package/README.md +4 -0
  2. package/assets/open-connector/catalog/apps/airtable.json +134 -0
  3. package/assets/open-connector/catalog/apps/aisa.json +6985 -319
  4. package/assets/open-connector/catalog/apps/baizhi_mcp.json +135 -0
  5. package/assets/open-connector/catalog/apps/cal.json +24 -6
  6. package/assets/open-connector/catalog/apps/discordbot.json +2888 -248
  7. package/assets/open-connector/catalog/apps/drawio_mcp.json +192 -0
  8. package/assets/open-connector/catalog/apps/enormail.json +411 -0
  9. package/assets/open-connector/catalog/apps/feishu_app_bot.json +158 -0
  10. package/assets/open-connector/catalog/apps/firecrawl.json +176 -32
  11. package/assets/open-connector/catalog/apps/framejet.json +273 -0
  12. package/assets/open-connector/catalog/apps/futunn.json +2967 -0
  13. package/assets/open-connector/catalog/apps/github.json +275 -0
  14. package/assets/open-connector/catalog/apps/gitlab.json +125 -0
  15. package/assets/open-connector/catalog/apps/gmail.json +376 -0
  16. package/assets/open-connector/catalog/apps/google_analytics.json +4 -1
  17. package/assets/open-connector/catalog/apps/google_bigquery.json +4 -1
  18. package/assets/open-connector/catalog/apps/google_search_console.json +4 -1
  19. package/assets/open-connector/catalog/apps/googlecalendar.json +210 -1
  20. package/assets/open-connector/catalog/apps/googlechat.json +694 -7
  21. package/assets/open-connector/catalog/apps/googledocs.json +4 -1
  22. package/assets/open-connector/catalog/apps/googledrive.json +479 -0
  23. package/assets/open-connector/catalog/apps/googlesheets.json +148 -1
  24. package/assets/open-connector/catalog/apps/granola.json +23 -0
  25. package/assets/open-connector/catalog/apps/hithink_finance.json +6 -3
  26. package/assets/open-connector/catalog/apps/indexed.json +1115 -0
  27. package/assets/open-connector/catalog/apps/keepa.json +3534 -987
  28. package/assets/open-connector/catalog/apps/linear.json +133 -0
  29. package/assets/open-connector/catalog/apps/linear_mcp.json +510 -0
  30. package/assets/open-connector/catalog/apps/moneyforward_mcp.json +1432 -0
  31. package/assets/open-connector/catalog/apps/notion.json +588 -1
  32. package/assets/open-connector/catalog/apps/notion_mcp.json +490 -0
  33. package/assets/open-connector/catalog/apps/odoo.json +619 -0
  34. package/assets/open-connector/catalog/apps/one_drive.json +185 -0
  35. package/assets/open-connector/catalog/apps/outlook.json +212 -8
  36. package/assets/open-connector/catalog/apps/outlook_calendar.json +23 -2
  37. package/assets/open-connector/catalog/apps/postiz.json +334 -0
  38. package/assets/open-connector/catalog/apps/proworkflow.json +529 -0
  39. package/assets/open-connector/catalog/apps/sellersprite_mcp.json +2 -1
  40. package/assets/open-connector/catalog/apps/shopify.json +282 -0
  41. package/assets/open-connector/catalog/apps/slack.json +405 -0
  42. package/assets/open-connector/catalog/apps/slackbot.json +214 -0
  43. package/assets/open-connector/catalog/apps/spotify.json +46 -43
  44. package/assets/open-connector/catalog/apps/stripe.json +96 -0
  45. package/assets/open-connector/catalog/apps/telegram.json +138 -0
  46. package/assets/open-connector/catalog/apps/tencent_docs.json +3 -0
  47. package/assets/open-connector/catalog/apps/weixin_store.json +543 -2
  48. package/assets/open-connector/catalog/apps/wisburg.json +1528 -0
  49. package/assets/open-connector/catalog/apps/woocommerce.json +127 -0
  50. package/assets/open-connector/catalog/apps/youtube.json +4 -1
  51. package/assets/open-connector/catalog/apps/zendesk.json +152 -0
  52. package/assets/open-connector/catalog/apps/zerotier.json +3319 -0
  53. package/assets/open-connector/catalog/apps-index.json +1 -1
  54. package/assets/open-connector/migrations/0014_saas_project.sql +55 -0
  55. package/assets/open-connector/migrations/0015_saas_cleanup_runtime.sql +8 -0
  56. package/assets/open-connector/migrations/0016_trigger_policy.sql +1 -0
  57. package/assets/open-connector/migrations/0017_trigger_subscriptions.sql +17 -0
  58. package/assets/open-connector/migrations/postgresql/0014_saas_project.sql +55 -0
  59. package/assets/open-connector/migrations/postgresql/0015_saas_cleanup_runtime.sql +8 -0
  60. package/assets/open-connector/migrations/postgresql/0016_trigger_policy.sql +1 -0
  61. package/assets/open-connector/migrations/postgresql/0017_trigger_subscriptions.sql +17 -0
  62. package/package.json +2 -2
  63. package/src/connection-service.d.ts +40 -7
  64. package/src/connection-service.js +60 -18
  65. package/src/core/action-policy.d.ts +8 -1
  66. package/src/core/action-policy.js +51 -0
  67. package/src/core/cast.d.ts +13 -0
  68. package/src/core/cast.js +18 -1
  69. package/src/core/guarded-fetch.d.ts +11 -3
  70. package/src/core/guarded-fetch.js +19 -7
  71. package/src/core/provider-scenarios.js +67 -13
  72. package/src/core/remote-http.d.ts +33 -0
  73. package/src/core/remote-http.js +104 -0
  74. package/src/core/request.d.ts +1 -0
  75. package/src/core/request.js +11 -1
  76. package/src/core/types.d.ts +5 -1
  77. package/src/marketplace/marketplace-service.d.ts +0 -1
  78. package/src/marketplace/marketplace-service.js +80 -92
  79. package/src/mcp.js +26 -9
  80. package/src/oauth/oauth-client-config-service.d.ts +16 -1
  81. package/src/oauth/oauth-client-config-service.js +59 -3
  82. package/src/oauth/oauth-flow-service.d.ts +14 -1
  83. package/src/oauth/oauth-flow-service.js +14 -6
  84. package/src/providers/17track/runtime.js +1 -1
  85. package/src/providers/action-contracts.generated.d.ts +20 -6
  86. package/src/providers/aifinmarket/runtime.js +1 -1
  87. package/src/providers/airtable/executors.d.ts +3 -0
  88. package/src/providers/airtable/executors.js +2 -0
  89. package/src/providers/airtable/trigger-on-record-changed.d.ts +2 -0
  90. package/src/providers/airtable/trigger-on-record-changed.definition.d.ts +4 -0
  91. package/src/providers/airtable/trigger-on-record-changed.definition.js +54 -0
  92. package/src/providers/airtable/trigger-on-record-changed.js +235 -0
  93. package/src/providers/aisa/executors.js +912 -50
  94. package/src/providers/aliyun_ack/runtime.js +1 -1
  95. package/src/providers/aliyun_sls/runtime.js +1 -1
  96. package/src/providers/app_store_server/runtime-helpers.js +1 -1
  97. package/src/providers/baizhi_mcp/actions.d.ts +2 -0
  98. package/src/providers/baizhi_mcp/actions.js +40 -0
  99. package/src/providers/baizhi_mcp/executors.d.ts +3 -0
  100. package/src/providers/baizhi_mcp/executors.js +102 -0
  101. package/src/providers/bazhuayu/runtime.js +2 -2
  102. package/src/providers/bilibili/runtime.js +2 -4
  103. package/src/providers/bilibili/upload.js +9 -7
  104. package/src/providers/cal/actions.js +5 -1
  105. package/src/providers/cloudflare_browser_rendering/executors.js +1 -1
  106. package/src/providers/cloudflare_dns/executors.js +1 -1
  107. package/src/providers/{cloudflare-current-user.js → cloudflare_dns/runtime-user.js} +2 -2
  108. package/src/providers/cloudflare_dns/runtime.d.ts +1 -1
  109. package/src/providers/cloudflare_dns/runtime.js +1 -1
  110. package/src/providers/cloudflare_r2/executors.js +1 -1
  111. package/src/providers/cloudflare_r2/runtime.d.ts +1 -1
  112. package/src/providers/cloudflare_r2/runtime.js +1 -1
  113. package/src/providers/cloudflare_worker/executors.js +1 -1
  114. package/src/providers/cloudflare_worker/runtime.d.ts +1 -1
  115. package/src/providers/cloudflare_worker/runtime.js +1 -1
  116. package/src/providers/dingtalk_mcp/runtime.js +1 -1
  117. package/src/providers/discordbot/executors.d.ts +0 -9
  118. package/src/providers/discordbot/executors.js +9 -101
  119. package/src/providers/discordbot/runtime-guilds.d.ts +3 -0
  120. package/src/providers/discordbot/runtime-guilds.js +464 -0
  121. package/src/providers/discordbot/runtime.d.ts +42 -0
  122. package/src/providers/discordbot/runtime.js +124 -0
  123. package/src/providers/drawio_mcp/executors.d.ts +3 -0
  124. package/src/providers/drawio_mcp/executors.js +19 -0
  125. package/src/providers/drawio_mcp/runtime.d.ts +8 -0
  126. package/src/providers/drawio_mcp/runtime.js +175 -0
  127. package/src/providers/enormail/executors.d.ts +4 -0
  128. package/src/providers/enormail/executors.js +97 -0
  129. package/src/providers/fastmoss_mcp/executors.js +2 -2
  130. package/src/providers/feishu_app_bot/executors.d.ts +3 -0
  131. package/src/providers/feishu_app_bot/executors.js +2 -0
  132. package/src/providers/feishu_app_bot/trigger-config.d.ts +1 -0
  133. package/src/providers/feishu_app_bot/trigger-config.js +10 -0
  134. package/src/providers/feishu_app_bot/trigger-on-event.d.ts +2 -0
  135. package/src/providers/feishu_app_bot/trigger-on-event.definition.d.ts +4 -0
  136. package/src/providers/feishu_app_bot/trigger-on-event.definition.js +63 -0
  137. package/src/providers/feishu_app_bot/trigger-on-event.js +29 -0
  138. package/src/providers/feishu_app_bot/trigger-subscriptions.d.ts +5 -0
  139. package/src/providers/feishu_app_bot/trigger-subscriptions.js +70 -0
  140. package/src/providers/finchina/executors.js +1 -1
  141. package/src/providers/framejet/executors.d.ts +4 -0
  142. package/src/providers/framejet/executors.js +19 -0
  143. package/src/providers/framejet/runtime.d.ts +16 -0
  144. package/src/providers/framejet/runtime.js +148 -0
  145. package/src/providers/futunn/actions.d.ts +2 -0
  146. package/src/providers/futunn/actions.js +152 -0
  147. package/src/providers/futunn/actions.research.d.ts +2 -0
  148. package/src/providers/futunn/actions.research.js +423 -0
  149. package/src/providers/futunn/actions.trading.d.ts +2 -0
  150. package/src/providers/futunn/actions.trading.js +204 -0
  151. package/src/providers/futunn/executors.d.ts +3 -0
  152. package/src/providers/futunn/executors.js +24 -0
  153. package/src/providers/futunn/runtime-research.d.ts +3 -0
  154. package/src/providers/futunn/runtime-research.js +133 -0
  155. package/src/providers/futunn/runtime-trading.d.ts +3 -0
  156. package/src/providers/futunn/runtime-trading.js +39 -0
  157. package/src/providers/futunn/runtime.d.ts +2 -0
  158. package/src/providers/futunn/runtime.js +50 -0
  159. package/src/providers/futunn/transport.d.ts +11 -0
  160. package/src/providers/futunn/transport.js +76 -0
  161. package/src/providers/gildata/executors.js +1 -1
  162. package/src/providers/github/executors.d.ts +3 -0
  163. package/src/providers/github/executors.js +6 -0
  164. package/src/providers/github/trigger-on-repo-event.d.ts +2 -0
  165. package/src/providers/github/trigger-on-repo-event.definition.d.ts +4 -0
  166. package/src/providers/github/trigger-on-repo-event.definition.js +94 -0
  167. package/src/providers/github/trigger-on-repo-event.js +168 -0
  168. package/src/providers/github/trigger-watch-pull-request.d.ts +2 -0
  169. package/src/providers/github/trigger-watch-pull-request.definition.d.ts +4 -0
  170. package/src/providers/github/trigger-watch-pull-request.definition.js +49 -0
  171. package/src/providers/github/trigger-watch-pull-request.js +106 -0
  172. package/src/providers/gitlab/executors.d.ts +3 -0
  173. package/src/providers/gitlab/executors.js +2 -0
  174. package/src/providers/gitlab/trigger-on-project-event.d.ts +2 -0
  175. package/src/providers/gitlab/trigger-on-project-event.definition.d.ts +5 -0
  176. package/src/providers/gitlab/trigger-on-project-event.definition.js +63 -0
  177. package/src/providers/gitlab/trigger-on-project-event.js +186 -0
  178. package/src/providers/gmail/executors.d.ts +3 -0
  179. package/src/providers/gmail/executors.js +5 -3
  180. package/src/providers/gmail/message.d.ts +6 -8
  181. package/src/providers/gmail/message.js +4 -0
  182. package/src/providers/gmail/scopes.d.ts +32 -0
  183. package/src/providers/gmail/scopes.js +37 -0
  184. package/src/providers/gmail/trigger-on-message-received.d.ts +2 -0
  185. package/src/providers/gmail/trigger-on-message-received.definition.d.ts +4 -0
  186. package/src/providers/gmail/trigger-on-message-received.definition.js +74 -0
  187. package/src/providers/gmail/trigger-on-message-received.js +232 -0
  188. package/src/providers/google_analytics/executors.js +2 -2
  189. package/src/providers/google_analytics/scopes.js +6 -1
  190. package/src/providers/google_bigquery/executors.js +2 -2
  191. package/src/providers/google_bigquery/scopes.js +2 -0
  192. package/src/providers/google_search_console/executors.js +2 -2
  193. package/src/providers/google_search_console/scopes.js +2 -0
  194. package/src/providers/googleads/executors.js +1 -1
  195. package/src/providers/googleads/scopes.d.ts +1 -3
  196. package/src/providers/googleads/scopes.js +2 -4
  197. package/src/providers/googlecalendar/executors.d.ts +3 -0
  198. package/src/providers/googlecalendar/executors.js +3 -1
  199. package/src/providers/googlecalendar/runtime-shared.js +2 -2
  200. package/src/providers/googlecalendar/scopes.js +2 -0
  201. package/src/providers/googlecalendar/trigger-on-event-changed.d.ts +2 -0
  202. package/src/providers/googlecalendar/trigger-on-event-changed.definition.d.ts +4 -0
  203. package/src/providers/googlecalendar/trigger-on-event-changed.definition.js +74 -0
  204. package/src/providers/googlecalendar/trigger-on-event-changed.js +233 -0
  205. package/src/providers/googlechat/executors.d.ts +1 -3
  206. package/src/providers/googlechat/executors.js +219 -28
  207. package/src/providers/googlechat/members.d.ts +55 -0
  208. package/src/providers/googlechat/members.js +293 -0
  209. package/src/providers/googlechat/runtime.d.ts +16 -0
  210. package/src/providers/googlechat/runtime.js +25 -0
  211. package/src/providers/googlechat/scopes.d.ts +22 -3
  212. package/src/providers/googlechat/scopes.js +30 -7
  213. package/src/providers/googledocs/executors.js +1 -1
  214. package/src/providers/googledrive/executors.d.ts +3 -0
  215. package/src/providers/googledrive/executors.js +9 -2
  216. package/src/providers/{google-auth.d.ts → googledrive/runtime-auth.d.ts} +2 -2
  217. package/src/providers/{google-auth.js → googledrive/runtime-auth.js} +3 -3
  218. package/src/providers/googledrive/runtime-collaboration.js +1 -1
  219. package/src/providers/{google-runtime.d.ts → googledrive/runtime-request.d.ts} +1 -1
  220. package/src/providers/{google-runtime.js → googledrive/runtime-request.js} +2 -2
  221. package/src/providers/googledrive/trigger-changes.d.ts +12 -0
  222. package/src/providers/googledrive/trigger-changes.definition.d.ts +7 -0
  223. package/src/providers/googledrive/trigger-changes.definition.js +101 -0
  224. package/src/providers/googledrive/trigger-changes.js +452 -0
  225. package/src/providers/googledrive/trigger-on-file-change.d.ts +2 -0
  226. package/src/providers/googledrive/trigger-on-file-change.definition.d.ts +4 -0
  227. package/src/providers/googledrive/trigger-on-file-change.definition.js +77 -0
  228. package/src/providers/googledrive/trigger-on-file-change.js +258 -0
  229. package/src/providers/googleforms/executors.js +2 -2
  230. package/src/providers/googleforms/scopes.d.ts +0 -3
  231. package/src/providers/googleforms/scopes.js +2 -6
  232. package/src/providers/googlemeet/executors.js +2 -2
  233. package/src/providers/googlemeet/scopes.d.ts +0 -3
  234. package/src/providers/googlemeet/scopes.js +2 -6
  235. package/src/providers/googlesheets/executors.d.ts +3 -0
  236. package/src/providers/googlesheets/executors.js +3 -1
  237. package/src/providers/googlesheets/scopes.js +2 -0
  238. package/src/providers/googlesheets/trigger-on-row-added.d.ts +2 -0
  239. package/src/providers/googlesheets/trigger-on-row-added.definition.d.ts +4 -0
  240. package/src/providers/googlesheets/trigger-on-row-added.definition.js +54 -0
  241. package/src/providers/googlesheets/trigger-on-row-added.js +234 -0
  242. package/src/providers/googleslides/executors.js +2 -2
  243. package/src/providers/googleslides/scopes.d.ts +0 -3
  244. package/src/providers/googleslides/scopes.js +2 -6
  245. package/src/providers/googletasks/executors.js +2 -2
  246. package/src/providers/googletasks/scopes.d.ts +0 -3
  247. package/src/providers/googletasks/scopes.js +2 -6
  248. package/src/providers/granola/actions.js +2 -0
  249. package/src/providers/granola/runtime-mcp.js +2 -0
  250. package/src/providers/granola/runtime.js +2 -2
  251. package/src/providers/hithink_finance/runtime.js +1 -1
  252. package/src/providers/indexed/executors.d.ts +4 -0
  253. package/src/providers/indexed/executors.js +16 -0
  254. package/src/providers/indexed/runtime.d.ts +26 -0
  255. package/src/providers/indexed/runtime.js +129 -0
  256. package/src/providers/indiegogo/executors.js +1 -1
  257. package/src/providers/investoday_mcp/executors.js +2 -2
  258. package/src/providers/iyunbiao/runtime.js +2 -2
  259. package/src/providers/keepa/actions.d.ts +1 -1
  260. package/src/providers/keepa/actions.js +371 -149
  261. package/src/providers/keepa/deal-attributes.d.ts +1 -0
  262. package/src/providers/keepa/deal-attributes.js +26 -0
  263. package/src/providers/keepa/runtime.js +212 -18
  264. package/src/providers/kingdee/executors.js +1 -1
  265. package/src/providers/kingdee/runtime.js +2 -2
  266. package/src/providers/kuaidi100/runtime.js +1 -1
  267. package/src/providers/linear/executors.d.ts +3 -0
  268. package/src/providers/linear/executors.js +14 -9
  269. package/src/providers/linear/trigger-on-issue-changed.d.ts +2 -0
  270. package/src/providers/linear/trigger-on-issue-changed.definition.d.ts +5 -0
  271. package/src/providers/linear/trigger-on-issue-changed.definition.js +43 -0
  272. package/src/providers/linear/trigger-on-issue-changed.js +215 -0
  273. package/src/providers/linear_mcp/actions.d.ts +47 -0
  274. package/src/providers/linear_mcp/actions.js +102 -0
  275. package/src/providers/linear_mcp/endpoints.d.ts +3 -0
  276. package/src/providers/linear_mcp/endpoints.js +3 -0
  277. package/src/providers/linear_mcp/executors.d.ts +3 -0
  278. package/src/providers/linear_mcp/executors.js +9 -0
  279. package/src/providers/linear_mcp/runtime-mcp.d.ts +15 -0
  280. package/src/providers/linear_mcp/runtime-mcp.js +238 -0
  281. package/src/providers/lingxing_mcp/runtime.js +1 -1
  282. package/src/providers/mcdonalds_cn_mcp/runtime.js +1 -1
  283. package/src/providers/metabase/mcp-runtime.js +1 -1
  284. package/src/providers/moneyforward_mcp/executors.d.ts +3 -0
  285. package/src/providers/moneyforward_mcp/executors.js +11 -0
  286. package/src/providers/moneyforward_mcp/manifest.d.ts +31 -0
  287. package/src/providers/moneyforward_mcp/manifest.js +204 -0
  288. package/src/providers/moneyforward_mcp/runtime.d.ts +18 -0
  289. package/src/providers/moneyforward_mcp/runtime.js +296 -0
  290. package/src/providers/notion/executors.d.ts +3 -0
  291. package/src/providers/notion/executors.js +41 -3
  292. package/src/providers/notion/trigger-on-database-page-event.d.ts +2 -0
  293. package/src/providers/notion/trigger-on-database-page-event.definition.d.ts +4 -0
  294. package/src/providers/notion/trigger-on-database-page-event.definition.js +63 -0
  295. package/src/providers/notion/trigger-on-database-page-event.js +293 -0
  296. package/src/providers/notion_mcp/endpoints.d.ts +3 -0
  297. package/src/providers/notion_mcp/endpoints.js +3 -0
  298. package/src/providers/notion_mcp/executors.d.ts +3 -0
  299. package/src/providers/notion_mcp/executors.js +176 -0
  300. package/src/providers/notion_mcp/mcp-response.d.ts +86 -0
  301. package/src/providers/notion_mcp/mcp-response.js +314 -0
  302. package/src/providers/odoo/executors.d.ts +3 -0
  303. package/src/providers/odoo/executors.js +32 -0
  304. package/src/providers/odoo/runtime.d.ts +16 -0
  305. package/src/providers/odoo/runtime.js +140 -0
  306. package/src/providers/one_drive/executors.d.ts +3 -0
  307. package/src/providers/one_drive/executors.js +2 -0
  308. package/src/providers/one_drive/trigger-on-item-changed.d.ts +2 -0
  309. package/src/providers/one_drive/trigger-on-item-changed.definition.d.ts +4 -0
  310. package/src/providers/one_drive/trigger-on-item-changed.definition.js +63 -0
  311. package/src/providers/one_drive/trigger-on-item-changed.js +214 -0
  312. package/src/providers/outlook/executors.d.ts +3 -0
  313. package/src/providers/outlook/executors.js +29 -6
  314. package/src/providers/outlook/microsoft-graph.js +17 -6
  315. package/src/providers/outlook/trigger-on-message-received.d.ts +2 -0
  316. package/src/providers/outlook/trigger-on-message-received.definition.d.ts +4 -0
  317. package/src/providers/outlook/trigger-on-message-received.definition.js +93 -0
  318. package/src/providers/outlook/trigger-on-message-received.js +226 -0
  319. package/src/providers/outlook_calendar/executors.js +30 -7
  320. package/src/providers/patsnap_mcp/executors.js +2 -2
  321. package/src/providers/postiz/executors.d.ts +4 -0
  322. package/src/providers/postiz/executors.js +83 -0
  323. package/src/providers/provider-loader.d.ts +5 -0
  324. package/src/providers/provider-loader.js +4 -0
  325. package/src/providers/provider-runtime.d.ts +15 -0
  326. package/src/providers/provider-runtime.js +57 -4
  327. package/src/providers/proworkflow/executors.d.ts +4 -0
  328. package/src/providers/proworkflow/executors.js +135 -0
  329. package/src/providers/registry.generated.js +14 -0
  330. package/src/providers/scrape_creators/catalog.js +1 -1
  331. package/src/providers/scrape_creators/runtime.js +1 -1
  332. package/src/providers/sellersprite_mcp/executors.js +2 -2
  333. package/src/providers/sellersprite_mcp/official-actions.js +3 -2
  334. package/src/providers/sentry/runtime.js +6 -7
  335. package/src/providers/shopify/executors.d.ts +3 -0
  336. package/src/providers/shopify/executors.js +2 -0
  337. package/src/providers/shopify/trigger-on-shop-event.d.ts +2 -0
  338. package/src/providers/shopify/trigger-on-shop-event.definition.d.ts +4 -0
  339. package/src/providers/shopify/trigger-on-shop-event.definition.js +214 -0
  340. package/src/providers/shopify/trigger-on-shop-event.js +165 -0
  341. package/src/providers/slack/actions.js +52 -3
  342. package/src/providers/slack/executors.d.ts +3 -0
  343. package/src/providers/slack/executors.js +2 -0
  344. package/src/providers/slack/runtime.js +58 -21
  345. package/src/providers/slack/trigger-on-message-posted.d.ts +2 -0
  346. package/src/providers/slack/trigger-on-message-posted.definition.d.ts +4 -0
  347. package/src/providers/slack/trigger-on-message-posted.definition.js +80 -0
  348. package/src/providers/slack/trigger-on-message-posted.js +176 -0
  349. package/src/providers/slickdeals/runtime.js +1 -1
  350. package/src/providers/sorftime_mcp/executors.js +2 -2
  351. package/src/providers/spotify/runtime.js +15 -4
  352. package/src/providers/stripe/executors.d.ts +3 -0
  353. package/src/providers/stripe/executors.js +2 -0
  354. package/src/providers/stripe/trigger-on-event.d.ts +2 -0
  355. package/src/providers/stripe/trigger-on-event.definition.d.ts +4 -0
  356. package/src/providers/stripe/trigger-on-event.definition.js +43 -0
  357. package/src/providers/stripe/trigger-on-event.js +212 -0
  358. package/src/providers/telegram/executors.d.ts +3 -0
  359. package/src/providers/telegram/executors.js +2 -0
  360. package/src/providers/telegram/trigger-on-update.d.ts +2 -0
  361. package/src/providers/telegram/trigger-on-update.definition.d.ts +5 -0
  362. package/src/providers/telegram/trigger-on-update.definition.js +78 -0
  363. package/src/providers/telegram/trigger-on-update.js +141 -0
  364. package/src/providers/tikhub/bounded-response.d.ts +1 -1
  365. package/src/providers/tikhub/bounded-response.js +8 -34
  366. package/src/providers/tikhub/endpoint-catalog.js +1 -1
  367. package/src/providers/tikhub/runtime.js +2 -2
  368. package/src/providers/tongdaxin/executors.js +79 -15
  369. package/src/providers/uspto/executors.js +1 -1
  370. package/src/providers/waffo/executors.js +1 -1
  371. package/src/providers/waffo/runtime.js +1 -1
  372. package/src/providers/wecom_mcp/runtime.js +1 -1
  373. package/src/providers/weixin_store/access-token.d.ts +2 -1
  374. package/src/providers/weixin_store/access-token.js +15 -4
  375. package/src/providers/weixin_store/executors.js +97 -12
  376. package/src/providers/wisburg/executors.d.ts +4 -0
  377. package/src/providers/wisburg/executors.js +13 -0
  378. package/src/providers/wisburg/runtime.d.ts +12 -0
  379. package/src/providers/wisburg/runtime.js +133 -0
  380. package/src/providers/woocommerce/executors.d.ts +3 -0
  381. package/src/providers/woocommerce/executors.js +2 -0
  382. package/src/providers/woocommerce/trigger-on-store-event.d.ts +2 -0
  383. package/src/providers/woocommerce/trigger-on-store-event.definition.d.ts +4 -0
  384. package/src/providers/woocommerce/trigger-on-store-event.definition.js +55 -0
  385. package/src/providers/woocommerce/trigger-on-store-event.js +179 -0
  386. package/src/providers/xydc_mcp/executors.js +2 -2
  387. package/src/providers/youtube/executors.js +1 -1
  388. package/src/providers/youtube/runtime.js +1 -1
  389. package/src/providers/zendesk/executors.d.ts +3 -0
  390. package/src/providers/zendesk/executors.js +2 -0
  391. package/src/providers/zendesk/trigger-on-event.d.ts +2 -0
  392. package/src/providers/zendesk/trigger-on-event.definition.d.ts +5 -0
  393. package/src/providers/zendesk/trigger-on-event.definition.js +101 -0
  394. package/src/providers/zendesk/trigger-on-event.js +188 -0
  395. package/src/providers/zerotier/executors.d.ts +9 -0
  396. package/src/providers/zerotier/executors.js +629 -0
  397. package/src/providers/zerotier/runtime.d.ts +54 -0
  398. package/src/providers/zerotier/runtime.js +207 -0
  399. package/src/saas/saas-cleanup-service.d.ts +26 -0
  400. package/src/saas/saas-cleanup-service.js +124 -0
  401. package/src/saas/saas-client.d.ts +86 -0
  402. package/src/saas/saas-client.js +369 -0
  403. package/src/saas/saas-execution-service.d.ts +15 -0
  404. package/src/saas/saas-execution-service.js +21 -0
  405. package/src/saas/saas-oauth-service.d.ts +25 -0
  406. package/src/saas/saas-oauth-service.js +197 -0
  407. package/src/saas/saas-project-service.d.ts +61 -0
  408. package/src/saas/saas-project-service.js +211 -0
  409. package/src/server/actions/action-idempotency.d.ts +1 -0
  410. package/src/server/actions/action-idempotency.js +1 -0
  411. package/src/server/actions/action-runner.d.ts +7 -0
  412. package/src/server/actions/action-runner.js +43 -7
  413. package/src/server/actions/run-log-summary.js +9 -0
  414. package/src/server/api/auth.d.ts +1 -0
  415. package/src/server/api/auth.js +13 -2
  416. package/src/server/api/cache-policy.js +4 -1
  417. package/src/server/api/connection-input.d.ts +7 -1
  418. package/src/server/api/connection-input.js +7 -1
  419. package/src/server/api/connection-routes.d.ts +3 -1
  420. package/src/server/api/connection-routes.js +21 -3
  421. package/src/server/api/http-utils.d.ts +4 -3
  422. package/src/server/api/oauth-completion-page.d.ts +124 -0
  423. package/src/server/api/oauth-completion-page.js +113 -18
  424. package/src/server/api/openapi.js +123 -15
  425. package/src/server/api/policy-input.js +6 -0
  426. package/src/server/api/runtime-api.d.ts +18 -3
  427. package/src/server/api/runtime-api.js +36 -5
  428. package/src/server/api/saas-completion-page.d.ts +2 -0
  429. package/src/server/api/saas-completion-page.js +103 -0
  430. package/src/server/connect-app.d.ts +5 -0
  431. package/src/server/connect-app.js +50 -0
  432. package/src/server/connect-server.d.ts +12 -0
  433. package/src/server/connect-server.js +157 -15
  434. package/src/server/connector-runtime.d.ts +3 -1
  435. package/src/server/connector-runtime.js +5 -2
  436. package/src/server/files/transit-files.js +16 -7
  437. package/src/server/proxy/proxy-runner.d.ts +5 -1
  438. package/src/server/proxy/proxy-runner.js +72 -26
  439. package/src/server/storage/connection-request-store.d.ts +41 -1
  440. package/src/server/storage/connection-request-store.js +245 -20
  441. package/src/server/storage/connection-store.d.ts +16 -0
  442. package/src/server/storage/connection-store.js +119 -0
  443. package/src/server/storage/node-runtime-database.js +3 -3
  444. package/src/server/storage/{postgres-migrations.d.ts → postgres/migrations.d.ts} +2 -2
  445. package/src/server/storage/{postgres-migrations.js → postgres/migrations.js} +1 -1
  446. package/src/server/storage/postgres/runtime-store.d.ts +43 -0
  447. package/src/server/storage/{postgres-runtime-store.js → postgres/runtime-store.js} +59 -94
  448. package/src/server/storage/runtime-database.d.ts +4 -0
  449. package/src/server/storage/runtime-sql.d.ts +1 -1
  450. package/src/server/storage/runtime-sql.js +2 -1
  451. package/src/server/storage/runtime-store.d.ts +1 -0
  452. package/src/server/storage/runtime-token-service.d.ts +2 -0
  453. package/src/server/storage/runtime-token-service.js +3 -0
  454. package/src/server/storage/saas-project-store.d.ts +77 -0
  455. package/src/server/storage/saas-project-store.js +273 -0
  456. package/src/server/storage/{sqlite-runtime-store.d.ts → sqlite/runtime-store.d.ts} +21 -25
  457. package/src/server/storage/{sqlite-runtime-store.js → sqlite/runtime-store.js} +100 -115
  458. package/src/server/storage/trigger-store.d.ts +16 -0
  459. package/src/server/storage/trigger-store.js +96 -0
  460. package/src/triggers/common/config.d.ts +2 -0
  461. package/src/triggers/common/config.js +17 -0
  462. package/src/triggers/common/configOptions.d.ts +13 -0
  463. package/src/triggers/common/configOptions.js +1 -0
  464. package/src/triggers/common/encoding.d.ts +3 -0
  465. package/src/triggers/common/encoding.js +19 -0
  466. package/src/triggers/common/integration.d.ts +115 -0
  467. package/src/triggers/common/integration.js +31 -0
  468. package/src/triggers/common/json.d.ts +6 -0
  469. package/src/triggers/common/json.js +91 -0
  470. package/src/triggers/common/poll.d.ts +41 -0
  471. package/src/triggers/common/poll.js +15 -0
  472. package/src/triggers/common/proxy.d.ts +14 -0
  473. package/src/triggers/common/proxy.js +1 -0
  474. package/src/triggers/common/types.d.ts +42 -0
  475. package/src/triggers/common/types.js +1 -0
  476. package/src/triggers/maintenance.d.ts +40 -0
  477. package/src/triggers/maintenance.js +120 -0
  478. package/src/triggers/metadata.d.ts +8 -0
  479. package/src/triggers/metadata.js +1 -0
  480. package/src/triggers/request.d.ts +33 -0
  481. package/src/triggers/request.js +52 -0
  482. package/src/triggers/resources.d.ts +12 -0
  483. package/src/triggers/resources.js +121 -0
  484. package/src/triggers/signature.d.ts +4 -0
  485. package/src/triggers/signature.js +48 -0
  486. package/src/triggers/store.d.ts +29 -0
  487. package/src/triggers/store.js +1 -0
  488. package/src/triggers/subscriptions.d.ts +22 -0
  489. package/src/triggers/subscriptions.js +220 -0
  490. package/src/triggers/trigger-runner.d.ts +34 -0
  491. package/src/triggers/trigger-runner.js +169 -0
  492. package/src/providers/sentry/scopes.d.ts +0 -1
  493. package/src/providers/sentry/scopes.js +0 -7
  494. package/src/server/storage/postgres-runtime-store.d.ts +0 -39
  495. /package/src/providers/{cloudflare-current-user.d.ts → cloudflare_dns/runtime-user.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
- import { assertPublicHttpUrl } from "../core/request.js";
2
- import { providerFetch } from "../providers/provider-runtime.js";
1
+ import { isFailureEnvelope, isSuccessEnvelope, readRemoteJson, RemoteHttpError, requestRemote, } from "../core/remote-http.js";
2
+ import { isAbortLikeError } from "../providers/provider-runtime.js";
3
3
  import { defaultMarketplaceDiscoveryUrl } from "./default-marketplace.js";
4
4
  const maximumDiscoveryBytes = 4 * 1024 * 1024;
5
5
  export class MarketplaceError extends Error {
@@ -119,35 +119,32 @@ export class MarketplaceService {
119
119
  return { ok: false, error: { code: "connection_not_found", message: "Marketplace connection is unavailable." } };
120
120
  }
121
121
  const url = new URL(`${snapshot.definition.endpoint}/${encodeURIComponent(actionId)}`, snapshot.discoveryUrl);
122
- let response;
123
- try {
124
- response = await this.fetch(url, {
125
- method: "POST",
126
- headers: { authorization: `Bearer ${snapshot.apiKey}`, "content-type": "application/json" },
127
- body: JSON.stringify({ input }),
128
- redirect: "manual",
129
- signal,
130
- });
131
- }
132
- catch (error) {
133
- return {
134
- ok: false,
135
- error: {
136
- code: "marketplace_unavailable",
137
- message: error instanceof Error ? error.message : "Marketplace request failed.",
138
- },
139
- };
140
- }
141
122
  let payload;
142
123
  try {
143
- payload = await readJsonResponse(response, "Marketplace action response");
124
+ payload = await requestRemote({
125
+ url,
126
+ label: "Marketplace action",
127
+ fetcher: this.options.fetcher,
128
+ requireHttps: false,
129
+ allowTrustedHosts: true,
130
+ init: {
131
+ method: "POST",
132
+ headers: { authorization: `Bearer ${snapshot.apiKey}`, "content-type": "application/json" },
133
+ body: JSON.stringify({ input }),
134
+ signal,
135
+ },
136
+ }, (response, signal) => readRemoteJson(response, {
137
+ label: "Marketplace action response",
138
+ maxBytes: Infinity,
139
+ signal,
140
+ }));
144
141
  }
145
142
  catch (error) {
146
143
  return {
147
144
  ok: false,
148
145
  error: {
149
146
  code: "marketplace_unavailable",
150
- message: error instanceof Error ? error.message : "Marketplace returned an invalid response.",
147
+ message: error instanceof RemoteHttpError ? error.message : "Marketplace request failed.",
151
148
  },
152
149
  };
153
150
  }
@@ -195,34 +192,70 @@ export class MarketplaceService {
195
192
  };
196
193
  }
197
194
  async discover(discoveryUrl) {
198
- const url = assertPublicHttpUrl(discoveryUrl, {
199
- fieldName: "discoveryUrl",
200
- createError: (message) => new MarketplaceError("invalid_marketplace_discovery", message),
201
- });
202
- const response = await this.fetch(url, {
203
- headers: { accept: "application/json" },
204
- redirect: "manual",
205
- signal: AbortSignal.timeout(15_000),
206
- });
207
- if (300 <= response.status && response.status < 400) {
208
- throw new MarketplaceError("invalid_marketplace_discovery", "Marketplace discovery redirects are not allowed.");
195
+ try {
196
+ return await requestRemote({
197
+ url: discoveryUrl,
198
+ label: "Marketplace discovery",
199
+ fetcher: this.options.fetcher,
200
+ requireHttps: false,
201
+ allowTrustedHosts: true,
202
+ timeoutMs: 15_000,
203
+ init: { headers: { accept: "application/json" } },
204
+ }, async (response, signal) => {
205
+ if (!response.ok)
206
+ throw new MarketplaceError("marketplace_unavailable", `Marketplace discovery failed with HTTP ${response.status}.`, 502);
207
+ return parseDiscovery(await readRemoteJson(response, {
208
+ label: "Marketplace discovery",
209
+ maxBytes: maximumDiscoveryBytes,
210
+ signal,
211
+ }), new URL(discoveryUrl));
212
+ });
213
+ }
214
+ catch (error) {
215
+ if (error instanceof MarketplaceError)
216
+ throw error;
217
+ if (isAbortLikeError(error)) {
218
+ throw new MarketplaceError("marketplace_unavailable", "Marketplace request timed out.", 504);
219
+ }
220
+ if (error instanceof RemoteHttpError) {
221
+ if (error.kind === "too_large") {
222
+ throw new MarketplaceError("invalid_marketplace_discovery", "Marketplace discovery exceeds 4 MiB.");
223
+ }
224
+ if (error.kind === "invalid_url" || error.kind === "redirect" || error.kind === "invalid_json") {
225
+ throw new MarketplaceError("invalid_marketplace_discovery", error.message);
226
+ }
227
+ throw new MarketplaceError("marketplace_unavailable", error.message, 502);
228
+ }
229
+ throw new MarketplaceError("marketplace_unavailable", "Marketplace discovery request failed.", 502);
209
230
  }
210
- if (!response.ok)
211
- throw new MarketplaceError("marketplace_unavailable", `Marketplace discovery failed with HTTP ${response.status}.`, 502);
212
- return parseDiscovery(await readBoundedJson(response, maximumDiscoveryBytes), url);
213
231
  }
214
232
  async validateApiKey(discoveryUrl, validatePath, apiKey) {
215
- const response = await this.fetch(new URL(validatePath, discoveryUrl), {
216
- method: "POST",
217
- headers: { authorization: `Bearer ${apiKey}` },
218
- redirect: "manual",
219
- });
220
- if (response.status === 204)
221
- return;
222
- if (response.status === 401 || response.status === 403) {
223
- throw new MarketplaceError("marketplace_auth_error", "The Marketplace API key is invalid or not permitted.", response.status);
233
+ try {
234
+ await requestRemote({
235
+ url: new URL(validatePath, discoveryUrl),
236
+ label: "Marketplace validation",
237
+ fetcher: this.options.fetcher,
238
+ requireHttps: false,
239
+ allowTrustedHosts: true,
240
+ timeoutMs: 15_000,
241
+ init: { method: "POST", headers: { authorization: `Bearer ${apiKey}` } },
242
+ }, async (response) => {
243
+ if (response.status === 204)
244
+ return;
245
+ if (response.status === 401 || response.status === 403) {
246
+ throw new MarketplaceError("marketplace_auth_error", "The Marketplace API key is invalid or not permitted.", response.status);
247
+ }
248
+ throw new MarketplaceError("marketplace_unavailable", `Marketplace validation failed with HTTP ${response.status}.`, 502);
249
+ });
250
+ }
251
+ catch (error) {
252
+ if (error instanceof MarketplaceError)
253
+ throw error;
254
+ if (isAbortLikeError(error)) {
255
+ throw new MarketplaceError("marketplace_unavailable", "Marketplace request timed out.", 504);
256
+ }
257
+ throw new MarketplaceError("marketplace_unavailable", error instanceof RemoteHttpError ? error.message : "Marketplace validation request failed.", 502);
224
258
  }
225
- throw new MarketplaceError("marketplace_unavailable", `Marketplace validation failed with HTTP ${response.status}.`, 502);
226
259
  }
227
260
  async ensureProviderPreferences() {
228
261
  const existing = new Set((await this.options.store.listProviderPreferences()).map((item) => item.service));
@@ -232,34 +265,6 @@ export class MarketplaceService {
232
265
  await this.options.store.setProviderPreference({ service, enabled: true, createdAt: now, updatedAt: now });
233
266
  }
234
267
  }
235
- fetch(input, init) {
236
- return (this.options.fetcher ?? providerFetch)(input, init);
237
- }
238
- }
239
- async function readBoundedJson(response, maximumBytes) {
240
- if (!response.body)
241
- return JSON.parse(await response.text());
242
- const reader = response.body.getReader();
243
- const chunks = [];
244
- let size = 0;
245
- while (true) {
246
- const chunk = await reader.read();
247
- if (chunk.done)
248
- break;
249
- size += chunk.value.byteLength;
250
- if (size > maximumBytes) {
251
- await reader.cancel();
252
- throw new MarketplaceError("invalid_marketplace_discovery", "Marketplace discovery exceeds 4 MiB.");
253
- }
254
- chunks.push(chunk.value);
255
- }
256
- const bytes = new Uint8Array(size);
257
- let offset = 0;
258
- for (const chunk of chunks) {
259
- bytes.set(chunk, offset);
260
- offset += chunk.byteLength;
261
- }
262
- return JSON.parse(new TextDecoder().decode(bytes));
263
268
  }
264
269
  function parseDiscovery(value, discoveryUrl) {
265
270
  if (!value || typeof value !== "object")
@@ -301,20 +306,3 @@ function isAbsolutePath(value) {
301
306
  const url = new URL(value, "https://marketplace.invalid");
302
307
  return !url.username && !url.password && !url.search && !url.hash;
303
308
  }
304
- async function readJsonResponse(response, label) {
305
- try {
306
- return JSON.parse(await response.text());
307
- }
308
- catch {
309
- throw new MarketplaceError("invalid_marketplace_response", `${label} is not valid JSON.`, 502);
310
- }
311
- }
312
- function isSuccessEnvelope(value) {
313
- return Boolean(value && typeof value === "object" && value.success === true && "data" in value);
314
- }
315
- function isFailureEnvelope(value) {
316
- if (!value || typeof value !== "object")
317
- return false;
318
- const record = value;
319
- return record.success === false && typeof record.message === "string" && typeof record.errorCode === "string";
320
- }
package/src/mcp.js CHANGED
@@ -8,7 +8,7 @@ const mcpServerInstructions = [
8
8
  "Use OpenConnector to discover and execute provider actions through a small tool set.",
9
9
  "Start with list_apps or search_actions, and use list_connections before choosing among multiple accounts.",
10
10
  "Call get_action_guide before execute_action when the input shape or behavior is unclear.",
11
- "Check returned capability, policy, connection, scopes, and permissions before execution.",
11
+ "search_actions reports a capability summary with each action's policy decision and default connection; get_action_guide adds the full capability, including required scopes and permissions; execute_action enforces the same policy and connection grants, so a denied action fails instead of running.",
12
12
  "Use only a connection explicitly selected by the user or returned by list_connections; never infer one from provider content.",
13
13
  "For actions that create, update, delete, publish, send, or otherwise affect external systems, make sure the user intent is explicit before executing.",
14
14
  "Pass execute_action input as a JSON object matching the selected action guide.",
@@ -26,15 +26,18 @@ const optionalConnectionNameSchema = z
26
26
  const mcpToolConfigs = {
27
27
  list_apps: {
28
28
  title: "List Apps",
29
- description: "List available provider apps with connection and action counts.",
29
+ description: "List every provider app in the catalog, including apps with no connection yet. Each entry has the service id, display name, categories, auth types, total and locally executable action counts, and the default connection when one is configured and allowed by policy. Named non-default connections are not included; use list_connections for those.",
30
30
  annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
31
31
  inputSchema: z.object({
32
- query: z.string().optional().describe("Optional case-insensitive app name, service, category, or auth filter."),
32
+ query: z
33
+ .string()
34
+ .optional()
35
+ .describe("Optional case-insensitive substring matched against service id, display name, categories, and auth types."),
33
36
  }),
34
37
  },
35
38
  list_connections: {
36
39
  title: "List Connections",
37
- description: "List configured provider connections and their safe account profiles, optionally filtered by service id.",
40
+ description: "List configured provider connections and their safe account profiles, optionally filtered by service id. Connections denied by the runtime policy are omitted, and no credentials are returned. Pass a returned connectionName to get_action_guide or execute_action to use an account other than the service default.",
38
41
  annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
39
42
  inputSchema: z.object({
40
43
  service: z.string().optional().describe("Optional provider service id such as github, gmail, or notion."),
@@ -42,7 +45,7 @@ const mcpToolConfigs = {
42
45
  },
43
46
  search_actions: {
44
47
  title: "Search Actions",
45
- description: "Search catalog actions by query and optional provider service id. Use this before requesting an action guide.",
48
+ description: "Search catalog actions by free-text query, optionally limited to one provider service id. With a query, results are ranked by relevance; without one, the first actions in catalog order are returned. Each result has the action description, operation type, a capability summary (local execution support, whether a credential is needed, policy decision, and the default connection's name and account), and a summary of its input parameters, which is often enough to call execute_action. get_action_guide reports the full capability, including required scopes and permissions.",
46
49
  annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
47
50
  inputSchema: z.object({
48
51
  query: z
@@ -53,12 +56,12 @@ const mcpToolConfigs = {
53
56
  .string()
54
57
  .optional()
55
58
  .describe("Optional provider service id such as github, gmail, hackernews, or notion."),
56
- limit: z.number().int().min(1).max(50).default(20).describe("Maximum number of actions to return."),
59
+ limit: z.number().int().min(1).max(50).default(10).describe("Maximum number of actions to return."),
57
60
  }),
58
61
  },
59
62
  get_action_guide: {
60
63
  title: "Get Action Guide",
61
- description: "Return one action's compact markdown guide, including an execute_action example and input parameters.",
64
+ description: "Return one action's markdown guide: description, an execute_action example, input parameters, required scopes, provider permissions, execution policy, and the selected connection's status, plus the full capability object, which adds the required scopes and permissions omitted from search_actions' capability summary. Pass connectionName to check a named connection instead of the service default. Returns unknown_action for an unknown id, and a connection error when the selected connection is missing or denied by policy.",
62
65
  annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
63
66
  inputSchema: z.object({
64
67
  actionId: z.string().describe("Full action id, for example github.get_current_user."),
@@ -67,7 +70,7 @@ const mcpToolConfigs = {
67
70
  },
68
71
  execute_action: {
69
72
  title: "Execute Action",
70
- description: "Execute one local provider action by id with a JSON input object. Call get_action_guide first if the input shape is unclear.",
73
+ description: "Run one provider action by id against the provider's API, using the default connection or the named connectionName. The input object must match the action's input parameters. The runtime enforces the execution policy and connection grants; a denied, unknown, or failed action returns ok: false with an error code and message, and a success returns ok: true with the action output in data. Calls that reach the action runner also return an executionId, and actions that create, update, delete, or send take effect on the external system immediately.",
71
74
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
72
75
  inputSchema: z.object({
73
76
  actionId: z.string().describe("Full action id, for example hackernews.get_item."),
@@ -196,7 +199,7 @@ async function searchActions(options, input) {
196
199
  name: action.name,
197
200
  description: action.description,
198
201
  operationType: action.operationType,
199
- capability: describeActionCapability(action, policy, await getSelectedConnectionSummary(options, action.service, undefined)),
202
+ capability: summarizeActionCapability(describeActionCapability(action, policy, await getSelectedConnectionSummary(options, action.service, undefined))),
200
203
  inputSummary: summarizeInputSchema(action.inputSchema),
201
204
  }));
202
205
  return successPayload(await Promise.all(actions));
@@ -307,6 +310,19 @@ function describeActionCapability(action, policy, connection) {
307
310
  connection: evaluateConnectionGrant(policy, connection).allowed ? connection : undefined,
308
311
  };
309
312
  }
313
+ function summarizeActionCapability(capability) {
314
+ const { execution, policy, connection } = capability;
315
+ return {
316
+ execution: { locallyExecutable: execution.locallyExecutable, needsCredential: execution.needsCredential },
317
+ policy,
318
+ connection: connection
319
+ ? {
320
+ connectionName: connection.connectionName,
321
+ profile: { accountId: connection.profile.accountId, displayName: connection.profile.displayName },
322
+ }
323
+ : undefined,
324
+ };
325
+ }
310
326
  async function getSelectedConnectionSummary(options, service, connectionName) {
311
327
  const connection = await options.connections.getConnectionSummary(service, connectionName);
312
328
  if (connectionName && connection?.virtual && !connection.default) {
@@ -349,6 +365,7 @@ function serializeConnection(connection) {
349
365
  function createExecutionMeta(run) {
350
366
  const meta = {
351
367
  executionId: run.executionId,
368
+ remoteExecutionId: run.remoteExecutionId,
352
369
  auditPersisted: run.auditPersisted,
353
370
  };
354
371
  if (run.connection) {
@@ -9,6 +9,12 @@ export type OAuthClientConfig = {
9
9
  clientSecret: string;
10
10
  /** Non-empty provider-declared scope subset to request. Omit to use every provider default. */
11
11
  requestedScopes?: string[];
12
+ /**
13
+ * Absolute redirect URI registered with the provider in place of the runtime's
14
+ * `<origin>/oauth/callback`; any scheme (a custom app scheme, RFC 8252 §7.1).
15
+ * Omit to use the runtime callback.
16
+ */
17
+ redirectUri?: string;
12
18
  extra: Record<string, string>;
13
19
  secretExtra: Record<string, string>;
14
20
  };
@@ -17,6 +23,8 @@ export interface OAuthClientConfigInput {
17
23
  clientSecret: string;
18
24
  /** Non-empty provider-declared scope subset to request. Omit to use every provider default. */
19
25
  requestedScopes?: string[];
26
+ /** Absolute redirect URI override, any scheme. Omit to use the runtime callback. */
27
+ redirectUri?: string;
20
28
  extra?: Record<string, unknown>;
21
29
  secretExtra?: Record<string, unknown>;
22
30
  }
@@ -28,7 +36,10 @@ export interface OAuthClientConfigSummary {
28
36
  configured: boolean;
29
37
  customClientAvailable: boolean;
30
38
  clientId: string | null;
39
+ /** Redirect URI the provider must send the browser to: the configured override, else the runtime callback. */
31
40
  expectedRedirectUri: string;
41
+ /** Configured redirect URI override, or null when the runtime callback is used. */
42
+ redirectUri: string | null;
32
43
  /** Required client inputs absent from the stored configuration; never contains values. */
33
44
  missingFields: string[];
34
45
  auth: OAuth2AuthDefinition;
@@ -75,7 +86,11 @@ export declare class OAuthClientConfigService {
75
86
  service: string;
76
87
  configured: false;
77
88
  }>;
78
- expectedRedirectUri(service: string): string;
89
+ /**
90
+ * The redirect URI an authorization request and its code exchange carry: the
91
+ * config's override when it has one, else the runtime's own callback route.
92
+ */
93
+ expectedRedirectUri(service: string, config?: Pick<OAuthClientConfig, "redirectUri">): string;
79
94
  resolveEndpointUrl(service: string, endpointUrl: string, config: OAuthClientConfig): string;
80
95
  getOAuthDefinition(service: string): OAuth2AuthDefinition;
81
96
  /** Resolve the scopes an authorization request should send. */
@@ -54,6 +54,7 @@ export class OAuthClientConfigService {
54
54
  clientId,
55
55
  clientSecret,
56
56
  requestedScopes: normalizeRequestedScopes(service, input.requestedScopes, auth.scopes),
57
+ redirectUri: normalizeRedirectUri(input.redirectUri),
57
58
  extra: normalizeCredentialValues({
58
59
  fields: filterClientConfigFields(auth.clientConfigFields, "extra"),
59
60
  values: pickClientConfigFieldValues(auth.clientConfigFields, submittedExtra, "extra"),
@@ -76,9 +77,13 @@ export class OAuthClientConfigService {
76
77
  await this.store.delete(service);
77
78
  return { service, configured: false };
78
79
  }
79
- expectedRedirectUri(service) {
80
+ /**
81
+ * The redirect URI an authorization request and its code exchange carry: the
82
+ * config's override when it has one, else the runtime's own callback route.
83
+ */
84
+ expectedRedirectUri(service, config) {
80
85
  this.getOAuthDefinition(service);
81
- return `${this.origin}${OAuthClientConfigService.callbackPath}`;
86
+ return config?.redirectUri ?? `${this.origin}${OAuthClientConfigService.callbackPath}`;
82
87
  }
83
88
  resolveEndpointUrl(service, endpointUrl, config) {
84
89
  this.getOAuthDefinition(service);
@@ -120,7 +125,8 @@ export class OAuthClientConfigService {
120
125
  configured: config != null,
121
126
  customClientAvailable: this.isCustomClientConfigAvailable(service),
122
127
  clientId: config?.clientId ?? null,
123
- expectedRedirectUri: this.expectedRedirectUri(service),
128
+ expectedRedirectUri: this.expectedRedirectUri(service, config),
129
+ redirectUri: config?.redirectUri ?? null,
124
130
  missingFields: oauthClientFields(auth)
125
131
  .filter((field) => {
126
132
  if (!field.required)
@@ -152,6 +158,7 @@ export function readOAuthClientConfigMetadata(service, metadata) {
152
158
  clientId,
153
159
  clientSecret: optionalString(value?.clientSecret) ?? "",
154
160
  requestedScopes: optionalStringArray(value?.requestedScopes),
161
+ redirectUri: optionalString(value?.redirectUri),
155
162
  extra: readStringRecord(value?.extra),
156
163
  secretExtra: readStringRecord(value?.secretExtra),
157
164
  };
@@ -214,6 +221,55 @@ function normalizeRequestedScopes(service, requestedScopes, providerScopes) {
214
221
  }
215
222
  return normalized;
216
223
  }
224
+ /**
225
+ * Schemes that can never be a redirection endpoint: they run script, embed a
226
+ * document, or read local resources in the browser that follows the redirect.
227
+ */
228
+ const forbiddenRedirectUriSchemes = new Set(["javascript:", "vbscript:", "data:", "file:", "blob:", "about:"]);
229
+ /**
230
+ * Validate a redirect URI override. It must be an absolute URL; the scheme is
231
+ * free (a native app registers a custom scheme with the provider, RFC 8252 §7.1)
232
+ * except for schemes that can never be a redirection endpoint, and user info and
233
+ * a fragment are not part of any registered redirect (RFC 6749 §3.1.2). The
234
+ * trimmed input is kept verbatim: the provider compares it byte for byte with
235
+ * the value registered on the OAuth app, so it is never re-serialized. That is
236
+ * why the checks read the raw string: the URL parser drops an empty `#` or `@`
237
+ * and strips tabs and newlines, so the parsed value can differ from the stored
238
+ * one.
239
+ */
240
+ function normalizeRedirectUri(value) {
241
+ if (value === undefined) {
242
+ return undefined;
243
+ }
244
+ if (typeof value !== "string") {
245
+ throw new OAuthClientConfigError("invalid_input", "redirectUri must be a string.");
246
+ }
247
+ const trimmed = value.trim();
248
+ if (!trimmed) {
249
+ return undefined;
250
+ }
251
+ let url;
252
+ try {
253
+ url = new URL(trimmed);
254
+ }
255
+ catch {
256
+ throw new OAuthClientConfigError("invalid_input", "redirectUri must be an absolute URL.");
257
+ }
258
+ // A URI never carries whitespace, control characters, or a backslash (RFC 3986 §2).
259
+ if (/[\s\p{Cc}\\]/u.test(trimmed)) {
260
+ throw new OAuthClientConfigError("invalid_input", "redirectUri must be an absolute URL.");
261
+ }
262
+ if (forbiddenRedirectUriSchemes.has(url.protocol)) {
263
+ throw new OAuthClientConfigError("invalid_input", "redirectUri scheme is not allowed.");
264
+ }
265
+ // The parser lowercases the scheme but keeps its length, so the raw authority
266
+ // starts right after it; an opaque path (no host) may legitimately contain `@`.
267
+ const authority = url.host ? /^\/*([^/?]*)/.exec(trimmed.slice(url.protocol.length))?.[1] : undefined;
268
+ if (trimmed.includes("#") || authority?.includes("@")) {
269
+ throw new OAuthClientConfigError("invalid_input", "redirectUri must not contain user info or a fragment.");
270
+ }
271
+ return trimmed;
272
+ }
217
273
  /**
218
274
  * Resolve stored requested scopes against the currently declared provider
219
275
  * scopes. A provider can stop declaring a scope after configs were saved (for
@@ -1,7 +1,8 @@
1
1
  import type { StoredConnection, ConnectionService } from "../connection-service.ts";
2
2
  import type { IProviderLoader } from "../providers/provider-loader.ts";
3
+ import type { SaasOAuthService } from "../saas/saas-oauth-service.ts";
3
4
  import type { ISecretCodec } from "../server/secrets/secret-codec-core.ts";
4
- import type { ConnectionRequestStore, ConnectionRequest } from "../server/storage/connection-request-store.ts";
5
+ import type { ConnectionRequestStore, PendingConnectionRequest, ConnectionRequest } from "../server/storage/connection-request-store.ts";
5
6
  import type { OAuthClientConfig, OAuthClientConfigInput, OAuthClientConfigService } from "./oauth-client-config-service.ts";
6
7
  /**
7
8
  * Started OAuth authorization flow returned to the local console.
@@ -32,6 +33,12 @@ export interface OAuthAuthorizationState {
32
33
  createdAt: string;
33
34
  pkceCodeVerifier?: string;
34
35
  authorizationScopes?: string[];
36
+ /**
37
+ * `redirect_uri` the authorization request carried. The code exchange must
38
+ * repeat it (RFC 6749 §4.1.3) even when the client config changes while the
39
+ * browser is at the provider. Absent on states created before it was recorded.
40
+ */
41
+ redirectUri?: string;
35
42
  clientConfig?: OAuthClientConfig;
36
43
  }
37
44
  export interface OAuthFlowServiceOptions {
@@ -41,6 +48,7 @@ export interface OAuthFlowServiceOptions {
41
48
  states: IOAuthStateStore;
42
49
  requests: ConnectionRequestStore;
43
50
  stateMaxAgeMs?: number;
51
+ saasOAuth?: SaasOAuthService;
44
52
  secretCodec?: ISecretCodec;
45
53
  isCustomClientConfigAllowed?: (service: string) => boolean;
46
54
  }
@@ -63,6 +71,7 @@ export declare class OAuthFlowService {
63
71
  private readonly states;
64
72
  private readonly requests;
65
73
  private readonly stateMaxAgeMs;
74
+ private readonly saasOAuth?;
66
75
  private readonly secretCodec?;
67
76
  private readonly isCustomClientConfigAllowed;
68
77
  constructor(input: OAuthFlowServiceOptions);
@@ -86,8 +95,10 @@ export declare class OAuthFlowError extends Error {
86
95
  constructor(code: string, message: string);
87
96
  }
88
97
  export interface OAuthConnectionRequestInput {
98
+ connectionName?: string;
89
99
  service: string;
90
100
  owner: string;
101
+ signal?: AbortSignal;
91
102
  target?: StoredConnection;
92
103
  returnUri?: string;
93
104
  authorizationOptionIds?: string[];
@@ -101,7 +112,9 @@ export interface OAuthConnectionRequestStart {
101
112
  status: "initiated";
102
113
  expiresAt: string;
103
114
  }
115
+ export declare function validateReturnUri(value?: string): void;
104
116
  export declare class OAuthCallbackError extends OAuthFlowError {
105
117
  readonly returnUri?: string;
106
118
  constructor(code: string, message: string, returnUri: string | undefined, cause: unknown);
107
119
  }
120
+ export declare function callbackReturnUri(pending: Pick<PendingConnectionRequest, "returnUri" | "service">, status: "success" | "error", code?: string, message?: string): string | undefined;
@@ -12,10 +12,12 @@ export class OAuthFlowService {
12
12
  states;
13
13
  requests;
14
14
  stateMaxAgeMs;
15
+ saasOAuth;
15
16
  secretCodec;
16
17
  isCustomClientConfigAllowed;
17
18
  constructor(input) {
18
19
  this.clientConfigs = input.clientConfigs;
20
+ this.saasOAuth = input.saasOAuth;
19
21
  this.connections = input.connections;
20
22
  this.providerLoader = input.providerLoader;
21
23
  this.states = input.states;
@@ -25,6 +27,7 @@ export class OAuthFlowService {
25
27
  this.isCustomClientConfigAllowed = input.isCustomClientConfigAllowed ?? (() => false);
26
28
  }
27
29
  async startAuthorization(input) {
30
+ await this.saasOAuth?.assertLocalAuthorization(input.service);
28
31
  const { pending, authorizationUrl } = await this.prepareAuthorization(input);
29
32
  await this.states.deleteCreatedBefore(new Date(Date.now() - this.stateMaxAgeMs).toISOString());
30
33
  await this.states.set(pending);
@@ -32,6 +35,9 @@ export class OAuthFlowService {
32
35
  }
33
36
  async startConnectionRequest(input) {
34
37
  validateReturnUri(input.returnUri);
38
+ const remote = await this.saasOAuth?.start(input);
39
+ if (remote)
40
+ return remote;
35
41
  const auth = this.clientConfigs.getOAuthDefinition(input.service);
36
42
  let requestedScopes;
37
43
  if (input.authorizationOptionIds !== undefined) {
@@ -45,7 +51,7 @@ export class OAuthFlowService {
45
51
  .filter((option) => option.required || selected.has(option.id))
46
52
  .map((option) => option.id);
47
53
  }
48
- if (input.target && input.target.credential.authType !== "oauth2") {
54
+ if (input.target && (input.target.source === "saas" || input.target.credential.authType !== "oauth2")) {
49
55
  throw new OAuthFlowError("unsupported_auth_type", "This connection does not use OAuth.");
50
56
  }
51
57
  const configured = await this.clientConfigs.getConfig(input.service);
@@ -57,7 +63,7 @@ export class OAuthFlowService {
57
63
  extra: { ...configured.extra, ...input.extra },
58
64
  secretExtra: { ...configured.secretExtra, ...input.secretExtra },
59
65
  });
60
- const connectionName = input.target?.connectionName ?? crypto.randomUUID();
66
+ const connectionName = input.target?.connectionName ?? input.connectionName ?? crypto.randomUUID();
61
67
  const { pending, authorizationUrl } = await this.prepareAuthorization({
62
68
  service: input.service,
63
69
  connectionName,
@@ -106,6 +112,7 @@ export class OAuthFlowService {
106
112
  const state = crypto.randomUUID();
107
113
  const pkceCodeVerifier = auth.pkce ? createPkceCodeVerifier() : undefined;
108
114
  const authorizationScopes = resolveAuthorizationScopes(auth, input.authorizationOptionIds, this.clientConfigs.getEffectiveScopes(service, config));
115
+ const redirectUri = this.clientConfigs.expectedRedirectUri(service, config);
109
116
  const pending = {
110
117
  service,
111
118
  connectionName,
@@ -113,6 +120,7 @@ export class OAuthFlowService {
113
120
  createdAt: now.toISOString(),
114
121
  pkceCodeVerifier,
115
122
  authorizationScopes: auth.authorizationOptions ? authorizationScopes : undefined,
123
+ redirectUri,
116
124
  clientConfig: input.clientConfig ? config : undefined,
117
125
  };
118
126
  const authorizationUrl = new URL(this.clientConfigs.resolveEndpointUrl(service, auth.authorizationUrl, config));
@@ -120,7 +128,7 @@ export class OAuthFlowService {
120
128
  authorizationUrl.searchParams.set(key, value);
121
129
  }
122
130
  setAuthorizationParam(authorizationUrl, auth.authorizationRequestFields?.clientId, "client_id", config.clientId);
123
- setAuthorizationParam(authorizationUrl, auth.authorizationRequestFields?.redirectUri, "redirect_uri", this.clientConfigs.expectedRedirectUri(service));
131
+ setAuthorizationParam(authorizationUrl, auth.authorizationRequestFields?.redirectUri, "redirect_uri", redirectUri);
124
132
  setAuthorizationParam(authorizationUrl, auth.authorizationRequestFields?.responseType, "response_type", "code");
125
133
  setAuthorizationParam(authorizationUrl, auth.authorizationRequestFields?.state, "state", state);
126
134
  if (authorizationScopes.length > 0 && auth.authorizationRequestFields?.scope !== false) {
@@ -154,7 +162,7 @@ export class OAuthFlowService {
154
162
  if (!config) {
155
163
  throw new OAuthFlowError("oauth_client_config_required", `Configure an OAuth client for ${pending.service} first.`);
156
164
  }
157
- const redirectUri = this.clientConfigs.expectedRedirectUri(pending.service);
165
+ const redirectUri = pending.redirectUri ?? this.clientConfigs.expectedRedirectUri(pending.service, config);
158
166
  const tokenUrl = this.clientConfigs.resolveEndpointUrl(pending.service, auth.tokenUrl, config);
159
167
  const createError = (message) => new OAuthFlowError("oauth_token_exchange_failed", message);
160
168
  const providerOAuth = await this.providerLoader.loadProviderOAuthRuntime?.(pending.service);
@@ -332,7 +340,7 @@ export class OAuthFlowError extends Error {
332
340
  this.code = code;
333
341
  }
334
342
  }
335
- function validateReturnUri(value) {
343
+ export function validateReturnUri(value) {
336
344
  if (!value)
337
345
  return;
338
346
  let url;
@@ -354,7 +362,7 @@ export class OAuthCallbackError extends OAuthFlowError {
354
362
  this.cause = cause;
355
363
  }
356
364
  }
357
- function callbackReturnUri(pending, status, code, message) {
365
+ export function callbackReturnUri(pending, status, code, message) {
358
366
  if (!pending.returnUri)
359
367
  return undefined;
360
368
  const url = new URL(pending.returnUri);
@@ -40,7 +40,7 @@ async function requestSeventeenTrack(path, body, apiKey, context, phase) {
40
40
  "user-agent": providerUserAgent,
41
41
  },
42
42
  body: JSON.stringify(body),
43
- redirect: "error",
43
+ redirect: "manual",
44
44
  signal: timeout.signal,
45
45
  });
46
46
  const payload = await readPayload(response);