@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
@@ -0,0 +1,215 @@
1
+ import { isJsonObject } from "../../triggers/common/json.js";
2
+ import { eventsPollOutputs, PermanentPollError, PollConnectionError, TransientPollError, } from "../../triggers/common/poll.js";
3
+ import { snapshot, uuidPattern } from "./trigger-on-issue-changed.definition.js";
4
+ const uuid = new RegExp(uuidPattern);
5
+ const overlapMs = 60_000;
6
+ const pageSize = 50;
7
+ export const linearIssueChanged = {
8
+ buildOutputs: eventsPollOutputs,
9
+ snapshot,
10
+ configOptions: options,
11
+ async poll(context) {
12
+ const teamId = typeof context.config.teamId == "string" ? context.config.teamId.toLowerCase() : context.config.teamId;
13
+ const stateIds = context.config.stateIds;
14
+ if (typeof teamId != "string" ||
15
+ !uuid.test(teamId) ||
16
+ !Array.isArray(stateIds) ||
17
+ stateIds.length > 50 ||
18
+ stateIds.some((name) => typeof name != "string" || !uuid.test(name)))
19
+ throw new PermanentPollError("Linear Issue configuration is invalid.");
20
+ if (context.checkpoint == null) {
21
+ const data = await query(context, "query LinearTeam($teamId: String!) { team(id: $teamId) { id } }", { teamId });
22
+ requireTeam(data.team, teamId);
23
+ const startedAt = context.now.toISOString();
24
+ return { checkpoint: { startedAt, since: startedAt }, events: [] };
25
+ }
26
+ const checkpoint = readCheckpoint(context.checkpoint);
27
+ const until = checkpoint.until ?? new Date(Math.max(context.now.getTime(), Date.parse(checkpoint.since))).toISOString();
28
+ const since = new Date(Math.max(Date.parse(checkpoint.startedAt), Date.parse(checkpoint.since) - overlapMs)).toISOString();
29
+ const data = await query(context, `query LinearIssueChanges($teamId: String!, $filter: IssueFilter!, $after: String) {
30
+ team(id: $teamId) {
31
+ id
32
+ issues(first: ${pageSize}, after: $after, orderBy: updatedAt, includeArchived: true, filter: $filter) {
33
+ nodes { id identifier title url createdAt updatedAt state { id name type } }
34
+ pageInfo { hasNextPage endCursor }
35
+ }
36
+ }
37
+ }`, {
38
+ teamId,
39
+ after: checkpoint.after ?? null,
40
+ filter: {
41
+ updatedAt: { gte: since, lte: until },
42
+ ...(stateIds.length == 0 ? {} : { state: { id: { in: stateIds } } }),
43
+ },
44
+ });
45
+ const team = requireTeam(data.team, teamId);
46
+ const page = team.issues;
47
+ if (!isJsonObject(page) ||
48
+ !Array.isArray(page.nodes) ||
49
+ page.nodes.length > pageSize ||
50
+ !isJsonObject(page.pageInfo) ||
51
+ typeof page.pageInfo.hasNextPage != "boolean") {
52
+ throw new TransientPollError("Linear returned an invalid Issue page.");
53
+ }
54
+ const { hasNextPage, endCursor } = page.pageInfo;
55
+ if (hasNextPage &&
56
+ (typeof endCursor != "string" ||
57
+ endCursor.length == 0 ||
58
+ endCursor.length > 4096 ||
59
+ endCursor == checkpoint.after ||
60
+ page.nodes.length == 0)) {
61
+ throw new TransientPollError("Linear returned an invalid continuation cursor.");
62
+ }
63
+ const events = page.nodes.map((value) => {
64
+ if (!isJsonObject(value) ||
65
+ typeof value.id != "string" ||
66
+ !uuid.test(value.id) ||
67
+ typeof value.identifier != "string" ||
68
+ value.identifier.length == 0 ||
69
+ typeof value.title != "string" ||
70
+ typeof value.url != "string" ||
71
+ !timestamp(value.createdAt) ||
72
+ !timestamp(value.updatedAt) ||
73
+ Date.parse(value.createdAt) > Date.parse(value.updatedAt) ||
74
+ Date.parse(value.updatedAt) < Date.parse(since) ||
75
+ Date.parse(value.updatedAt) > Date.parse(until) ||
76
+ !isJsonObject(value.state) ||
77
+ typeof value.state.id != "string" ||
78
+ !uuid.test(value.state.id) ||
79
+ typeof value.state.name != "string" ||
80
+ typeof value.state.type != "string" ||
81
+ (stateIds.length > 0 && !stateIds.includes(value.state.id)))
82
+ throw new TransientPollError("Linear returned an invalid Issue.");
83
+ return {
84
+ dedupeKey: `${value.id}:${value.updatedAt}`,
85
+ payload: {
86
+ id: value.id,
87
+ identifier: value.identifier,
88
+ title: value.title,
89
+ url: value.url,
90
+ teamId,
91
+ createdAt: value.createdAt,
92
+ updatedAt: value.updatedAt,
93
+ state: { id: value.state.id, name: value.state.name, type: value.state.type },
94
+ },
95
+ };
96
+ });
97
+ return {
98
+ checkpoint: hasNextPage
99
+ ? { ...checkpoint, until, after: endCursor }
100
+ : { startedAt: checkpoint.startedAt, since: until },
101
+ events,
102
+ hasMore: hasNextPage,
103
+ };
104
+ },
105
+ };
106
+ function readCheckpoint(value) {
107
+ if (!isJsonObject(value) ||
108
+ !timestamp(value.startedAt) ||
109
+ !timestamp(value.since) ||
110
+ Date.parse(value.since) < Date.parse(value.startedAt) ||
111
+ (value.until != null && (!timestamp(value.until) || Date.parse(value.until) < Date.parse(value.since))) ||
112
+ (value.after != null &&
113
+ (typeof value.after != "string" || value.after.length == 0 || value.after.length > 4096 || value.until == null)))
114
+ throw new PermanentPollError("Linear Issue checkpoint is invalid.");
115
+ return {
116
+ startedAt: value.startedAt,
117
+ since: value.since,
118
+ ...(typeof value.until == "string" ? { until: value.until } : {}),
119
+ ...(typeof value.after == "string" ? { after: value.after } : {}),
120
+ };
121
+ }
122
+ function timestamp(value) {
123
+ return (typeof value == "string" &&
124
+ value.length <= 40 &&
125
+ /^\d{4}-\d{2}-\d{2}T/.test(value) &&
126
+ Number.isFinite(Date.parse(value)));
127
+ }
128
+ function requireTeam(value, teamId) {
129
+ if (value === null)
130
+ throw new PermanentPollError("The Linear team is unavailable or not accessible to this Connection.");
131
+ if (!isJsonObject(value) || value.id !== teamId)
132
+ throw new TransientPollError("Linear returned an invalid Team.");
133
+ return value;
134
+ }
135
+ async function query(context, document, variables) {
136
+ context.signal?.throwIfAborted();
137
+ const result = await context.connector.execute({ endpoint: "/graphql", method: "POST", body: { query: document, variables } }, context.signal);
138
+ context.signal?.throwIfAborted();
139
+ if (result.status == 401 || result.status == 403)
140
+ throw new PollConnectionError("Linear Issue access requires authorization.");
141
+ if (result.status == 429)
142
+ throw new TransientPollError("Linear Issue checks were rate limited.");
143
+ const body = result.data;
144
+ if (isJsonObject(body) && Array.isArray(body.errors) && body.errors.length > 0) {
145
+ const codes = new Set(body.errors.flatMap((error) => isJsonObject(error) && isJsonObject(error.extensions) ? [error.extensions.code] : []));
146
+ if (codes.has("UNAUTHENTICATED") || codes.has("FORBIDDEN") || codes.has("AUTHENTICATION_ERROR")) {
147
+ throw new PollConnectionError("Linear Issue access requires authorization.");
148
+ }
149
+ if (codes.has("RATELIMITED"))
150
+ throw new TransientPollError("Linear Issue checks were rate limited.");
151
+ if (codes.has("GRAPHQL_VALIDATION_FAILED") || codes.has("BAD_USER_INPUT"))
152
+ throw new PermanentPollError("Linear rejected the Issue query configuration.");
153
+ throw new TransientPollError("Linear Issue query failed; progress was retained.");
154
+ }
155
+ if (result.status != 200 ||
156
+ !isJsonObject(body) ||
157
+ !isJsonObject(body.data) ||
158
+ (body.errors != null && !Array.isArray(body.errors))) {
159
+ throw new TransientPollError(`Linear returned an invalid query response (HTTP ${result.status}).`);
160
+ }
161
+ return body.data;
162
+ }
163
+ async function options(context) {
164
+ const { field, config } = context;
165
+ if (field != "teamId" && field != "stateIds")
166
+ throw new PermanentPollError("Unknown Linear configuration field.");
167
+ if (field == "stateIds" && (typeof config.teamId != "string" || !uuid.test(config.teamId)))
168
+ throw new PermanentPollError("Select a Linear Team first.");
169
+ const choices = [];
170
+ const cursors = new Set();
171
+ let after = null;
172
+ for (let page = 0; page < 10; page++) {
173
+ const data = await query(context, field == "teamId"
174
+ ? "query LinearTeams($after: String) { teams(first: 100, after: $after) { nodes { id name key } pageInfo { hasNextPage endCursor } } }"
175
+ : "query LinearStates($teamId: String!, $after: String) { team(id: $teamId) { id states(first: 100, after: $after) { nodes { id name color position } pageInfo { hasNextPage endCursor } } } }", { after, ...(field == "teamId" ? {} : { teamId: config.teamId }) });
176
+ const values = field == "teamId" ? data.teams : requireTeam(data.team, String(config.teamId)).states;
177
+ if (!isJsonObject(values) ||
178
+ !Array.isArray(values.nodes) ||
179
+ values.nodes.length > 100 ||
180
+ !isJsonObject(values.pageInfo) ||
181
+ typeof values.pageInfo.hasNextPage != "boolean") {
182
+ throw new TransientPollError("Linear returned invalid configuration options.");
183
+ }
184
+ for (const item of values.nodes) {
185
+ if (!isJsonObject(item) ||
186
+ typeof item.id != "string" ||
187
+ !uuid.test(item.id) ||
188
+ typeof item.name != "string" ||
189
+ item.name.length == 0 ||
190
+ (field == "teamId"
191
+ ? typeof item.key != "string"
192
+ : typeof item.color != "string" || !/^#[0-9a-fA-F]{6}$/.test(item.color))) {
193
+ throw new TransientPollError("Linear returned an invalid configuration option.");
194
+ }
195
+ choices.push({
196
+ value: item.id,
197
+ label: field == "teamId" ? `${item.name} (${item.key})` : item.name,
198
+ ...(field == "stateIds" ? { color: String(item.color) } : {}),
199
+ });
200
+ }
201
+ if (!values.pageInfo.hasNextPage)
202
+ return choices;
203
+ const cursor = values.pageInfo.endCursor;
204
+ if (typeof cursor != "string" ||
205
+ cursor.length == 0 ||
206
+ cursor.length > 4096 ||
207
+ cursors.has(cursor) ||
208
+ values.nodes.length == 0) {
209
+ throw new TransientPollError("Linear returned an invalid options cursor.");
210
+ }
211
+ cursors.add(cursor);
212
+ after = cursor;
213
+ }
214
+ throw new PermanentPollError("The Linear options list exceeds the supported limit of 1000 entries.");
215
+ }
@@ -0,0 +1,47 @@
1
+ import type { ActionDefinition } from "../../core/types.ts";
2
+ /** The signed-in Linear user as the MCP get_user tool reports it. */
3
+ export interface LinearMcpUser {
4
+ id: string;
5
+ email?: string;
6
+ displayName?: string;
7
+ name?: string;
8
+ }
9
+ /**
10
+ * Typed fields lifted from one Linear MCP issue record. Linear publishes no
11
+ * output schema for its MCP tools, so every field but `id` is best effort and
12
+ * the untouched text travels beside it as `raw`.
13
+ */
14
+ export interface LinearMcpIssue {
15
+ id: string;
16
+ identifier?: string;
17
+ uuid?: string;
18
+ title?: string;
19
+ description?: string;
20
+ descriptionTruncated?: boolean;
21
+ url?: string;
22
+ state?: string;
23
+ priority?: unknown;
24
+ assignee?: string;
25
+ assigneeId?: string;
26
+ creator?: string;
27
+ creatorId?: string;
28
+ team?: string;
29
+ project?: string;
30
+ labels?: string[];
31
+ createdAt?: string;
32
+ updatedAt?: string;
33
+ archivedAt?: string;
34
+ completedAt?: string;
35
+ dueDate?: string;
36
+ }
37
+ /** Typed fields lifted from one Linear MCP comment record. */
38
+ export interface LinearMcpComment {
39
+ id: string;
40
+ body?: string;
41
+ user?: string;
42
+ userId?: string;
43
+ createdAt?: string;
44
+ updatedAt?: string;
45
+ url?: string;
46
+ }
47
+ export declare const linearMcpActions: ActionDefinition[];
@@ -0,0 +1,102 @@
1
+ import { s } from "../../core/json-schema.js";
2
+ import { defineProviderAction } from "../../core/provider-definition.js";
3
+ const service = "linear_mcp";
4
+ const readScope = ["read"];
5
+ const rawSchema = s.string("The untouched text Linear's MCP tool returned. Read it when a typed field is missing: Linear can change its MCP output shape without notice.");
6
+ const userSchema = s.looseObject("The signed-in Linear user.", {
7
+ id: s.nonEmptyString("Linear user ID; the same viewer ID the Linear GraphQL API reports."),
8
+ email: s.optional(s.string("The user's email address, when returned.")),
9
+ displayName: s.optional(s.string("The user's display name, when returned.")),
10
+ name: s.optional(s.string("The user's full name, when returned.")),
11
+ });
12
+ const issueSchema = s.looseObject("A Linear issue. Typed fields are lifted from the MCP record when present; fields not listed here are only in the action's raw text.", {
13
+ id: s.nonEmptyString("Issue ID as Linear MCP returned it. This may be the human identifier such as ENG-123 rather than the UUID; see identifier and uuid."),
14
+ identifier: s.optional(s.string("Human identifier such as ENG-123, when known.")),
15
+ uuid: s.optional(s.string("Issue UUID, when known.")),
16
+ title: s.optional(s.string("Issue title.")),
17
+ description: s.optional(s.string("Issue description in Markdown. Linear MCP may clip it in lists; see descriptionTruncated.")),
18
+ descriptionTruncated: s.optional(s.boolean("Whether the description carries Linear's truncation marker. Call get_issue for the full text.")),
19
+ url: s.optional(s.string("Link to the issue in Linear.")),
20
+ state: s.optional(s.string("Workflow state name.")),
21
+ priority: s.optional(s.unknown("Priority as returned: a number or a label.")),
22
+ assignee: s.optional(s.string("Assignee name, when assigned.")),
23
+ assigneeId: s.optional(s.string("Assignee user ID, when the record carries one.")),
24
+ creator: s.optional(s.string("Creator name, when returned.")),
25
+ creatorId: s.optional(s.string("Creator user ID, when the record carries one.")),
26
+ team: s.optional(s.string("Team name or key.")),
27
+ project: s.optional(s.string("Project name, when the issue belongs to one.")),
28
+ labels: s.optional(s.stringArray("Label names.")),
29
+ createdAt: s.optional(s.string("Creation time as returned by Linear.")),
30
+ updatedAt: s.optional(s.string("Last update time as returned by Linear.")),
31
+ archivedAt: s.optional(s.string("Archive time, when archived.")),
32
+ completedAt: s.optional(s.string("Completion time, when completed.")),
33
+ dueDate: s.optional(s.string("Due date, when set.")),
34
+ });
35
+ const commentSchema = s.looseObject("A Linear issue comment.", {
36
+ id: s.nonEmptyString("Comment ID."),
37
+ body: s.optional(s.string("Comment body in Markdown.")),
38
+ user: s.optional(s.string("Author name, when returned.")),
39
+ userId: s.optional(s.string("Author user ID, when the record carries one.")),
40
+ createdAt: s.optional(s.string("Creation time as returned by Linear.")),
41
+ updatedAt: s.optional(s.string("Last edit time, when returned.")),
42
+ url: s.optional(s.string("Link to the comment in Linear.")),
43
+ });
44
+ const listIssuesInputSchema = s.object("Filters forwarded to Linear's MCP list_issues tool. Which filters the tool honours is decided by Linear's server; unknown values are rejected there.", {
45
+ updatedAt: s.string("Only issues updated at or after this time, as the tool accepts it (an ISO 8601 timestamp or a relative duration such as -P1D)."),
46
+ orderBy: s.string("Sort field, such as updatedAt or createdAt."),
47
+ limit: s.integer("Maximum number of issues to return on this page.", { minimum: 1, maximum: 250 }),
48
+ cursor: s.nonEmptyString("Cursor returned by the previous page of the same query."),
49
+ }, { optional: ["updatedAt", "orderBy", "limit", "cursor"] });
50
+ export const linearMcpActions = [
51
+ defineProviderAction(service, {
52
+ name: "get_self",
53
+ operationType: "read",
54
+ description: "Get the signed-in Linear user through Linear's MCP get_user tool.",
55
+ requiredScopes: readScope,
56
+ inputSchema: s.object({}),
57
+ outputSchema: s.requiredObject("The signed-in user.", {
58
+ user: s.nullable(userSchema),
59
+ raw: rawSchema,
60
+ }),
61
+ }),
62
+ defineProviderAction(service, {
63
+ name: "list_issues",
64
+ operationType: "read",
65
+ description: "List Linear issues through Linear's MCP list_issues tool with optional updated-since, ordering, limit, and cursor pagination. Descriptions may be clipped; call get_issue for the full text.",
66
+ requiredScopes: readScope,
67
+ followUpActions: ["linear_mcp.get_issue", "linear_mcp.list_comments"],
68
+ inputSchema: listIssuesInputSchema,
69
+ outputSchema: s.requiredObject("One page of issues.", {
70
+ issues: s.array("Issues on this page.", issueSchema),
71
+ hasNextPage: s.boolean("Whether another page follows."),
72
+ cursor: s.nullable(s.string("Cursor for the next page, when one is available.")),
73
+ raw: rawSchema,
74
+ }),
75
+ }),
76
+ defineProviderAction(service, {
77
+ name: "get_issue",
78
+ operationType: "read",
79
+ description: "Get one Linear issue with its full description through Linear's MCP get_issue tool.",
80
+ requiredScopes: readScope,
81
+ inputSchema: s.requiredObject("The issue to read.", {
82
+ id: s.nonEmptyString("Issue ID or human identifier such as ENG-123, as returned by list_issues."),
83
+ }),
84
+ outputSchema: s.requiredObject("The requested issue.", {
85
+ issue: s.nullable(issueSchema),
86
+ raw: rawSchema,
87
+ }),
88
+ }),
89
+ defineProviderAction(service, {
90
+ name: "list_comments",
91
+ operationType: "read",
92
+ description: "List the comments on one Linear issue through Linear's MCP list_comments tool.",
93
+ requiredScopes: readScope,
94
+ inputSchema: s.requiredObject("The issue whose comments to read.", {
95
+ issueId: s.nonEmptyString("Issue ID or human identifier such as ENG-123."),
96
+ }),
97
+ outputSchema: s.requiredObject("Comments on the issue.", {
98
+ comments: s.array("Comments as returned, oldest first when Linear orders them.", commentSchema),
99
+ raw: rawSchema,
100
+ }),
101
+ }),
102
+ ];
@@ -0,0 +1,3 @@
1
+ /** Linear's official remote MCP server (RFC 8707 resource) and its OAuth authorization server. */
2
+ export declare const linearMcpEndpoint = "https://mcp.linear.app/mcp";
3
+ export declare const linearMcpIssuer = "https://mcp.linear.app";
@@ -0,0 +1,3 @@
1
+ /** Linear's official remote MCP server (RFC 8707 resource) and its OAuth authorization server. */
2
+ export const linearMcpEndpoint = "https://mcp.linear.app/mcp";
3
+ export const linearMcpIssuer = "https://mcp.linear.app";
@@ -0,0 +1,3 @@
1
+ import type { CredentialValidators, ProviderExecutors } from "../../core/types.ts";
2
+ export declare const executors: ProviderExecutors;
3
+ export declare const credentialValidators: CredentialValidators;
@@ -0,0 +1,9 @@
1
+ import { defineOAuthProviderExecutors } from "../provider-runtime.js";
2
+ import { linearMcpActionHandlers, validateLinearMcpCredential } from "./runtime-mcp.js";
3
+ const service = "linear_mcp";
4
+ export const executors = defineOAuthProviderExecutors(service, linearMcpActionHandlers, {
5
+ skipDnsValidation: true,
6
+ });
7
+ export const credentialValidators = {
8
+ oauth2: validateLinearMcpCredential,
9
+ };
@@ -0,0 +1,15 @@
1
+ import type { CredentialValidationResult, CredentialValidatorOptions, ResolvedCredential } from "../../core/types.ts";
2
+ import type { OAuthProviderContext, ProviderActionHandlers, ProviderActionSources, ProviderRuntimeHandler } from "../provider-runtime.ts";
3
+ declare const service = "linear_mcp";
4
+ /** The Linear MCP tool behind each action. Sign-in requires every one of them (see the validator). */
5
+ export declare const linearMcpToolsByAction: ProviderActionSources<typeof service, string>;
6
+ export declare const linearMcpActionHandlers: ProviderActionHandlers<typeof service, ProviderRuntimeHandler<OAuthProviderContext>>;
7
+ /**
8
+ * Validate the OAuth grant against the MCP server: every tool the actions map
9
+ * must be listed (a rename shows up here, at sign-in, never mid-poll), then the
10
+ * self tool supplies the profile with the same viewer ID the GraphQL API reports.
11
+ */
12
+ export declare function validateLinearMcpCredential(credential: Extract<ResolvedCredential, {
13
+ authType: "oauth2";
14
+ }>, options: CredentialValidatorOptions): Promise<CredentialValidationResult>;
15
+ export {};
@@ -0,0 +1,238 @@
1
+ import { ProtocolError, SdkHttpError, UnauthorizedError } from "@modelcontextprotocol/client";
2
+ import { compactObject, looseArray, optionalBoolean, optionalInteger, optionalRawString, optionalRecord, optionalString, pickOptionalString, } from "../../core/cast.js";
3
+ import { withMcpClient } from "../mcp-client.js";
4
+ import { providerResponseError, providerUserAgent, ProviderRequestError, requiredInputString, runProviderRequest, } from "../provider-runtime.js";
5
+ import { linearMcpEndpoint } from "./endpoints.js";
6
+ const service = "linear_mcp";
7
+ /** The Linear MCP tool behind each action. Sign-in requires every one of them (see the validator). */
8
+ export const linearMcpToolsByAction = {
9
+ get_self: "get_user",
10
+ list_issues: "list_issues",
11
+ get_issue: "get_issue",
12
+ list_comments: "list_comments",
13
+ };
14
+ const humanIdentifier = /^[A-Z][A-Z0-9]*-\d+$/;
15
+ const uuidIdentifier = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
16
+ const truncationMarker = /\(truncated\b/i;
17
+ const maxToolListPages = 20;
18
+ export const linearMcpActionHandlers = {
19
+ async get_self(_input, context) {
20
+ const result = await callLinearMcpTool(context, "execute", linearMcpToolsByAction.get_self, { query: "me" });
21
+ return { user: parseLinearMcpUser(result.payload) ?? null, raw: result.text };
22
+ },
23
+ async list_issues(input, context) {
24
+ const result = await callLinearMcpTool(context, "execute", linearMcpToolsByAction.list_issues, compactObject({
25
+ updatedAt: optionalString(input.updatedAt),
26
+ orderBy: optionalString(input.orderBy),
27
+ limit: optionalInteger(input.limit),
28
+ cursor: optionalString(input.cursor),
29
+ }));
30
+ return { ...parseLinearMcpIssuePage(result.payload), raw: result.text };
31
+ },
32
+ async get_issue(input, context) {
33
+ const id = requiredInputString(input.id, "id");
34
+ const result = await callLinearMcpTool(context, "execute", linearMcpToolsByAction.get_issue, { id });
35
+ return { issue: parseLinearMcpIssue(result.payload) ?? null, raw: result.text };
36
+ },
37
+ async list_comments(input, context) {
38
+ const issueId = requiredInputString(input.issueId, "issueId");
39
+ const result = await callLinearMcpTool(context, "execute", linearMcpToolsByAction.list_comments, { issueId });
40
+ return { comments: parseLinearMcpComments(result.payload), raw: result.text };
41
+ },
42
+ };
43
+ /**
44
+ * Validate the OAuth grant against the MCP server: every tool the actions map
45
+ * must be listed (a rename shows up here, at sign-in, never mid-poll), then the
46
+ * self tool supplies the profile with the same viewer ID the GraphQL API reports.
47
+ */
48
+ export async function validateLinearMcpCredential(credential, options) {
49
+ const context = { accessToken: credential.accessToken, fetcher: options.fetcher, signal: options.signal };
50
+ return withLinearMcpClient(context, "validate", async (client, signal) => {
51
+ const available = await listLinearMcpToolNames(client, signal);
52
+ const missing = Object.values(linearMcpToolsByAction).filter((name) => !available.has(name));
53
+ if (missing.length > 0) {
54
+ throw new ProviderRequestError(502, `Linear MCP did not expose the ${missing.join(", ")} tool${missing.length > 1 ? "s" : ""} this connector needs; Linear may have renamed ${missing.length > 1 ? "them" : "it"}.`);
55
+ }
56
+ const result = readLinearMcpToolResult(linearMcpToolsByAction.get_self, await client.callTool({ name: linearMcpToolsByAction.get_self, arguments: { query: "me" } }, { signal }));
57
+ const user = parseLinearMcpUser(result.payload);
58
+ if (!user)
59
+ throw providerResponseError("Linear MCP did not return the signed-in user.");
60
+ return {
61
+ profile: { accountId: user.id, displayName: user.displayName ?? user.name ?? user.email ?? user.id },
62
+ grantedScopes: optionalString(credential.metadata.scope)?.split(" ") ?? [],
63
+ metadata: { mcpEndpoint: linearMcpEndpoint, discoveredToolCount: available.size },
64
+ };
65
+ });
66
+ }
67
+ async function listLinearMcpToolNames(client, signal) {
68
+ const names = new Set();
69
+ let cursor;
70
+ for (let page = 0; page < maxToolListPages; page += 1) {
71
+ const listed = await client.listTools(cursor ? { cursor } : {}, { signal });
72
+ for (const tool of listed.tools)
73
+ names.add(tool.name);
74
+ cursor = optionalString(listed.nextCursor);
75
+ if (!cursor)
76
+ break;
77
+ }
78
+ return names;
79
+ }
80
+ /** Call one tool in a fresh MCP session and return its text and parsed payload. */
81
+ function callLinearMcpTool(context, phase, name, args) {
82
+ return withLinearMcpClient(context, phase, async (client, signal) => readLinearMcpToolResult(name, await client.callTool({ name, arguments: args }, { signal })));
83
+ }
84
+ /**
85
+ * Join the text blocks as `text` and read the JSON they carry as `payload`
86
+ * (structured content wins when the server sends it). Text that is not JSON
87
+ * is not an error: the typed fields stay empty and `raw` still reaches the caller.
88
+ */
89
+ function readLinearMcpToolResult(name, result) {
90
+ if ("toolResult" in result) {
91
+ return { text: JSON.stringify(result.toolResult), payload: result.toolResult };
92
+ }
93
+ if (result.isError)
94
+ throw new ProviderRequestError(502, `Linear MCP tool ${name} failed.`, result);
95
+ const text = looseArray(result.content)
96
+ .map((block) => optionalRecord(block))
97
+ .filter((block) => block?.type === "text")
98
+ .map((block) => optionalRawString(block?.text) ?? "")
99
+ .join("\n");
100
+ return { text, payload: optionalRecord(result.structuredContent) ?? parseJsonText(text) };
101
+ }
102
+ function parseJsonText(text) {
103
+ const trimmed = text.trim();
104
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("["))
105
+ return undefined;
106
+ try {
107
+ return JSON.parse(trimmed);
108
+ }
109
+ catch {
110
+ return undefined;
111
+ }
112
+ }
113
+ function parseLinearMcpUser(payload) {
114
+ const record = optionalRecord(payload);
115
+ const user = record && (optionalRecord(record.user) ?? optionalRecord(record.viewer) ?? record);
116
+ const id = user && pickOptionalString(user, "id", "uuid");
117
+ if (!user || !id)
118
+ return undefined;
119
+ return {
120
+ id,
121
+ email: pickOptionalString(user, "email"),
122
+ displayName: pickOptionalString(user, "displayName", "display_name"),
123
+ name: pickOptionalString(user, "name"),
124
+ };
125
+ }
126
+ function parseLinearMcpIssuePage(payload) {
127
+ const record = optionalRecord(payload);
128
+ const items = Array.isArray(payload) ? payload : looseArray(record?.issues ?? record?.nodes ?? record?.results);
129
+ const issues = items.map(parseLinearMcpIssue).filter((issue) => issue !== undefined);
130
+ const cursor = record ? (pickOptionalString(record, "cursor", "nextCursor", "endCursor") ?? null) : null;
131
+ const hasNextPage = (record && (optionalBoolean(record.hasNextPage) ?? optionalBoolean(record.hasMore))) ?? cursor !== null;
132
+ return { issues, hasNextPage, cursor };
133
+ }
134
+ function parseLinearMcpIssue(value) {
135
+ const record = optionalRecord(value);
136
+ const issue = record && (optionalRecord(record.issue) ?? record);
137
+ const id = issue && pickOptionalString(issue, "id", "identifier", "uuid");
138
+ if (!issue || !id)
139
+ return undefined;
140
+ const description = optionalRawString(issue.description);
141
+ const assignee = optionalRecord(issue.assignee);
142
+ const creator = optionalRecord(issue.creator);
143
+ return {
144
+ id,
145
+ identifier: pickOptionalString(issue, "identifier") ?? (humanIdentifier.test(id) ? id : undefined),
146
+ uuid: pickOptionalString(issue, "uuid") ?? (uuidIdentifier.test(id) ? id : undefined),
147
+ title: optionalRawString(issue.title),
148
+ description,
149
+ descriptionTruncated: description === undefined ? undefined : truncationMarker.test(description),
150
+ url: pickOptionalString(issue, "url"),
151
+ state: labelOf(issue.state ?? issue.status),
152
+ priority: issue.priority,
153
+ assignee: labelOf(issue.assignee),
154
+ assigneeId: assignee && pickOptionalString(assignee, "id"),
155
+ creator: labelOf(issue.creator),
156
+ creatorId: creator && pickOptionalString(creator, "id"),
157
+ team: labelOf(issue.team),
158
+ project: labelOf(issue.project),
159
+ labels: parseLabels(issue.labels),
160
+ createdAt: pickOptionalString(issue, "createdAt", "created_at"),
161
+ updatedAt: pickOptionalString(issue, "updatedAt", "updated_at"),
162
+ archivedAt: pickOptionalString(issue, "archivedAt", "archived_at"),
163
+ completedAt: pickOptionalString(issue, "completedAt", "completed_at"),
164
+ dueDate: pickOptionalString(issue, "dueDate", "due_date"),
165
+ };
166
+ }
167
+ function parseLinearMcpComments(payload) {
168
+ const record = optionalRecord(payload);
169
+ const items = Array.isArray(payload) ? payload : looseArray(record?.comments ?? record?.nodes);
170
+ return items.flatMap((item) => {
171
+ const comment = optionalRecord(item);
172
+ const id = comment && pickOptionalString(comment, "id");
173
+ if (!comment || !id)
174
+ return [];
175
+ const user = optionalRecord(comment.user);
176
+ return [
177
+ {
178
+ id,
179
+ body: optionalRawString(comment.body),
180
+ user: labelOf(comment.user),
181
+ userId: user && pickOptionalString(user, "id"),
182
+ createdAt: pickOptionalString(comment, "createdAt", "created_at"),
183
+ updatedAt: pickOptionalString(comment, "updatedAt", "updated_at"),
184
+ url: pickOptionalString(comment, "url"),
185
+ },
186
+ ];
187
+ });
188
+ }
189
+ /** A name for a value Linear may return as a string or as an object such as `{ id, name }`. */
190
+ function labelOf(value) {
191
+ const record = optionalRecord(value);
192
+ if (record)
193
+ return pickOptionalString(record, "name", "displayName", "title", "key", "id");
194
+ return optionalString(value);
195
+ }
196
+ function parseLabels(value) {
197
+ if (!Array.isArray(value))
198
+ return undefined;
199
+ return value.flatMap((label) => {
200
+ const name = labelOf(label);
201
+ return name ? [name] : [];
202
+ });
203
+ }
204
+ function withLinearMcpClient(context, phase, run) {
205
+ return runProviderRequest({ signal: context.signal, label: "Linear MCP" }, (signal) => withMcpClient({
206
+ endpoint: new URL(linearMcpEndpoint),
207
+ transport: "streamable_http",
208
+ fetcher: context.fetcher,
209
+ headers: { authorization: `Bearer ${context.accessToken}`, "user-agent": providerUserAgent },
210
+ redirect: "manual",
211
+ signal,
212
+ mapError: (error) => mapLinearMcpError(error, phase),
213
+ }, (client) => run(client, signal)));
214
+ }
215
+ /**
216
+ * A rejected token is a bad credential (400) while validating and an expired
217
+ * authorization (401) while executing; other SDK failures keep a 4xx status or
218
+ * become 502. Aborts and unknown errors pass through for the request wrapper.
219
+ */
220
+ function mapLinearMcpError(error, phase) {
221
+ if (error instanceof ProviderRequestError)
222
+ return error;
223
+ if (error instanceof UnauthorizedError)
224
+ return credentialError(phase);
225
+ if (error instanceof SdkHttpError) {
226
+ const status = error.status;
227
+ if (status === 401 || status === 403)
228
+ return credentialError(phase);
229
+ return new ProviderRequestError(400 <= status && status < 500 ? status : 502, `Linear MCP request failed: ${error.message}`, error);
230
+ }
231
+ if (error instanceof ProtocolError) {
232
+ return new ProviderRequestError(502, `Linear MCP request failed: ${error.message}`, error);
233
+ }
234
+ return error;
235
+ }
236
+ function credentialError(phase) {
237
+ return new ProviderRequestError(phase === "validate" ? 400 : 401, "Linear MCP credential is invalid or expired; reconnect Linear.");
238
+ }
@@ -174,7 +174,7 @@ async function withLingxingMcpClient(context, run) {
174
174
  transport: "streamable_http",
175
175
  fetcher: createLingxingRateLimitedFetch(context.fetcher, hashLingxingRateLimitKey(context)),
176
176
  headers,
177
- redirect: "error",
177
+ redirect: "manual",
178
178
  signal: context.signal,
179
179
  mapError: mapLingxingMcpError,
180
180
  }, run);
@@ -65,7 +65,7 @@ async function withMcdonaldsCnMcpClient(context, run) {
65
65
  transport: "streamable_http",
66
66
  fetcher: context.fetcher,
67
67
  headers,
68
- redirect: "error",
68
+ redirect: "manual",
69
69
  signal: context.signal,
70
70
  protocolVersion: "legacy",
71
71
  mapError: mapMcdonaldsCnMcpError,