@oomol-lab/open-connector 1.9.0 → 1.9.1
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.
- package/assets/open-connector/catalog/apps/agentearth.json +441 -0
- package/assets/open-connector/catalog/apps/appgrowing_mcp.json +863 -0
- package/assets/open-connector/catalog/apps/arcmira.json +610 -0
- package/assets/open-connector/catalog/apps/bainiu.json +654 -0
- package/assets/open-connector/catalog/apps/chaport.json +331 -0
- package/assets/open-connector/catalog/apps/cnb.json +1408 -0
- package/assets/open-connector/catalog/apps/crtsh.json +123 -0
- package/assets/open-connector/catalog/apps/eastmoney_miaoxiang.json +406 -0
- package/assets/open-connector/catalog/apps/fastmoss_mcp.json +876 -876
- package/assets/open-connector/catalog/apps/ftshare.json +1162 -0
- package/assets/open-connector/catalog/apps/fusion-api.json +143 -0
- package/assets/open-connector/catalog/apps/fxbaogao.json +308 -0
- package/assets/open-connector/catalog/apps/github.json +38 -3
- package/assets/open-connector/catalog/apps/hrmos_kintai.json +7519 -0
- package/assets/open-connector/catalog/apps/humor_api.json +351 -0
- package/assets/open-connector/catalog/apps/kaonavi.json +1723 -0
- package/assets/open-connector/catalog/apps/linear_mcp.json +882 -22
- package/assets/open-connector/catalog/apps/listinggood.json +362 -0
- package/assets/open-connector/catalog/apps/notion_mcp.json +338 -1
- package/assets/open-connector/catalog/apps/outlook.json +414 -0
- package/assets/open-connector/catalog/apps/porteden.json +1258 -0
- package/assets/open-connector/catalog/apps/qiuxiaoce.json +915 -0
- package/assets/open-connector/catalog/apps/qqmusic.json +1834 -0
- package/assets/open-connector/catalog/apps/rakuraku_seisan.json +217 -0
- package/assets/open-connector/catalog/apps/redfox.json +9661 -897
- package/assets/open-connector/catalog/apps/salesforce.json +4907 -0
- package/assets/open-connector/catalog/apps/sansan.json +4594 -0
- package/assets/open-connector/catalog/apps/smarthr.json +8071 -0
- package/assets/open-connector/catalog/apps/smooth.json +914 -0
- package/assets/open-connector/catalog/apps/tapd.json +727 -0
- package/assets/open-connector/catalog/apps/tencent_meeting_mcp.json +1301 -0
- package/assets/open-connector/catalog/apps/threatfox.json +203 -0
- package/assets/open-connector/catalog/apps/tradebee.json +915 -0
- package/assets/open-connector/catalog/apps/twittrapi.json +4914 -0
- package/assets/open-connector/catalog/apps/urlhaus.json +246 -0
- package/assets/open-connector/catalog/apps/weread.json +1514 -0
- package/assets/open-connector/catalog/apps/whatsapp.json +12 -0
- package/assets/open-connector/catalog/apps/zhiliaobiaoxun.json +812 -0
- package/assets/open-connector/catalog/apps-index.json +1 -1
- package/package.json +2 -1
- package/src/connection-service.js +55 -11
- package/src/core/provider-error-codes.d.ts +9 -0
- package/src/core/provider-error-codes.js +13 -0
- package/src/core/request.d.ts +2 -0
- package/src/core/request.js +11 -2
- package/src/mail/imap-smtp/protocol.js +4 -3
- package/src/oauth/oauth-flow-service.js +1 -0
- package/src/oauth/oauth-token.d.ts +2 -0
- package/src/providers/17track/runtime.js +17 -20
- package/src/providers/action-contracts.generated.d.ts +36 -6
- package/src/providers/agentearth/actions.d.ts +2 -0
- package/src/providers/agentearth/actions.js +100 -0
- package/src/providers/agentearth/executors.d.ts +4 -0
- package/src/providers/agentearth/executors.js +109 -0
- package/src/providers/appgrowing_mcp/actions.d.ts +2 -0
- package/src/providers/appgrowing_mcp/actions.js +175 -0
- package/src/providers/appgrowing_mcp/executors.d.ts +4 -0
- package/src/providers/appgrowing_mcp/executors.js +66 -0
- package/src/providers/arcmira/executors.d.ts +3 -0
- package/src/providers/arcmira/executors.js +8 -0
- package/src/providers/arcmira/runtime.d.ts +6 -0
- package/src/providers/arcmira/runtime.js +41 -0
- package/src/providers/bainiu/actions.d.ts +2 -0
- package/src/providers/bainiu/actions.js +108 -0
- package/src/providers/bainiu/executors.d.ts +4 -0
- package/src/providers/bainiu/executors.js +113 -0
- package/src/providers/baixiao/executors.js +1 -1
- package/src/providers/bing_webmaster/executors.js +1 -1
- package/src/providers/chaport/actions.d.ts +2 -0
- package/src/providers/chaport/actions.js +70 -0
- package/src/providers/chaport/executors.d.ts +4 -0
- package/src/providers/chaport/executors.js +128 -0
- package/src/providers/clickup/runtime.js +49 -52
- package/src/providers/cnb/actions.d.ts +2 -0
- package/src/providers/cnb/actions.js +341 -0
- package/src/providers/cnb/executors.d.ts +4 -0
- package/src/providers/cnb/executors.js +135 -0
- package/src/providers/coupontools/runtime.js +11 -14
- package/src/providers/crtsh/executors.d.ts +3 -0
- package/src/providers/crtsh/executors.js +19 -0
- package/src/providers/crtsh/runtime.d.ts +17 -0
- package/src/providers/crtsh/runtime.js +84 -0
- package/src/providers/eastmoney_miaoxiang/actions.d.ts +2 -0
- package/src/providers/eastmoney_miaoxiang/actions.js +95 -0
- package/src/providers/eastmoney_miaoxiang/executors.d.ts +4 -0
- package/src/providers/eastmoney_miaoxiang/executors.js +81 -0
- package/src/providers/fastmoss_mcp/actions-content.d.ts +2 -0
- package/src/providers/fastmoss_mcp/actions-content.js +140 -0
- package/src/providers/fastmoss_mcp/actions-creator.d.ts +2 -0
- package/src/providers/fastmoss_mcp/actions-creator.js +154 -0
- package/src/providers/fastmoss_mcp/actions-product.d.ts +2 -0
- package/src/providers/fastmoss_mcp/actions-product.js +167 -0
- package/src/providers/fastmoss_mcp/actions-research.d.ts +2 -0
- package/src/providers/fastmoss_mcp/actions-research.js +174 -0
- package/src/providers/fastmoss_mcp/actions-shop.d.ts +2 -0
- package/src/providers/fastmoss_mcp/actions-shop.js +142 -0
- package/src/providers/fastmoss_mcp/actions.js +11 -12
- package/src/providers/fastmoss_mcp/schemas.d.ts +51 -0
- package/src/providers/fastmoss_mcp/schemas.js +52 -0
- package/src/providers/ftshare/actions.d.ts +2 -0
- package/src/providers/ftshare/actions.js +124 -0
- package/src/providers/ftshare/executors.d.ts +4 -0
- package/src/providers/ftshare/executors.js +102 -0
- package/src/providers/fusion-api/operations.js +37 -0
- package/src/providers/fxbaogao/actions.d.ts +2 -0
- package/src/providers/fxbaogao/actions.js +74 -0
- package/src/providers/fxbaogao/executors.d.ts +4 -0
- package/src/providers/fxbaogao/executors.js +155 -0
- package/src/providers/github/app-installation.d.ts +37 -0
- package/src/providers/github/app-installation.js +233 -0
- package/src/providers/github/executors.js +93 -15
- package/src/providers/github/runtime-repository.js +21 -1
- package/src/providers/github/runtime-shared.d.ts +2 -0
- package/src/providers/github/runtime-shared.js +1 -0
- package/src/providers/googledrive/runtime-request.js +3 -3
- package/src/providers/hrmos_kintai/actions.d.ts +2 -0
- package/src/providers/hrmos_kintai/actions.js +139 -0
- package/src/providers/hrmos_kintai/attendance-actions.d.ts +2 -0
- package/src/providers/hrmos_kintai/attendance-actions.js +276 -0
- package/src/providers/hrmos_kintai/business-actions.d.ts +2 -0
- package/src/providers/hrmos_kintai/business-actions.js +143 -0
- package/src/providers/hrmos_kintai/business-schemas.d.ts +4 -0
- package/src/providers/hrmos_kintai/business-schemas.js +320 -0
- package/src/providers/hrmos_kintai/executors.d.ts +4 -0
- package/src/providers/hrmos_kintai/executors.js +61 -0
- package/src/providers/hrmos_kintai/export-actions.d.ts +2 -0
- package/src/providers/hrmos_kintai/export-actions.js +58 -0
- package/src/providers/hrmos_kintai/operations.d.ts +9 -0
- package/src/providers/hrmos_kintai/operations.js +278 -0
- package/src/providers/hrmos_kintai/runtime.d.ts +10 -0
- package/src/providers/hrmos_kintai/runtime.js +217 -0
- package/src/providers/hrmos_kintai/schemas.d.ts +10 -0
- package/src/providers/hrmos_kintai/schemas.js +70 -0
- package/src/providers/humor_api/actions.d.ts +2 -0
- package/src/providers/humor_api/actions.js +96 -0
- package/src/providers/humor_api/executors.d.ts +4 -0
- package/src/providers/humor_api/executors.js +76 -0
- package/src/providers/kaonavi/actions.d.ts +4 -0
- package/src/providers/kaonavi/actions.js +144 -0
- package/src/providers/kaonavi/additional-actions.d.ts +10 -0
- package/src/providers/kaonavi/additional-actions.js +203 -0
- package/src/providers/kaonavi/executors.d.ts +4 -0
- package/src/providers/kaonavi/executors.js +69 -0
- package/src/providers/kaonavi/runtime.d.ts +4 -0
- package/src/providers/kaonavi/runtime.js +69 -0
- package/src/providers/linear_mcp/actions.d.ts +14 -0
- package/src/providers/linear_mcp/actions.js +134 -0
- package/src/providers/linear_mcp/runtime-mcp.d.ts +7 -1
- package/src/providers/linear_mcp/runtime-mcp.js +140 -28
- package/src/providers/linkfox/runtime.js +48 -51
- package/src/providers/listinggood/actions.d.ts +2 -0
- package/src/providers/listinggood/actions.js +95 -0
- package/src/providers/listinggood/executors.d.ts +4 -0
- package/src/providers/listinggood/executors.js +99 -0
- package/src/providers/mcp-tools.d.ts +3 -0
- package/src/providers/mcp-tools.js +5 -4
- package/src/providers/notion_mcp/executors.js +53 -24
- package/src/providers/notion_mcp/mcp-response.d.ts +26 -0
- package/src/providers/notion_mcp/mcp-response.js +95 -0
- package/src/providers/omise/executors.js +1 -1
- package/src/providers/outlook/executors.js +35 -2
- package/src/providers/porteden/actions.d.ts +2 -0
- package/src/providers/porteden/actions.js +162 -0
- package/src/providers/porteden/executors.d.ts +4 -0
- package/src/providers/porteden/executors.js +140 -0
- package/src/providers/provider-runtime.d.ts +3 -2
- package/src/providers/pushover/runtime.js +28 -31
- package/src/providers/qianfan/runtime.js +16 -19
- package/src/providers/qiuxiaoce/actions.d.ts +2 -0
- package/src/providers/qiuxiaoce/actions.js +248 -0
- package/src/providers/qiuxiaoce/executors.d.ts +4 -0
- package/src/providers/qiuxiaoce/executors.js +76 -0
- package/src/providers/qiuxiaoce/routes.d.ts +1 -0
- package/src/providers/qiuxiaoce/routes.js +20 -0
- package/src/providers/qqmusic/actions.d.ts +2 -0
- package/src/providers/qqmusic/actions.js +229 -0
- package/src/providers/qqmusic/executors.d.ts +4 -0
- package/src/providers/qqmusic/executors.js +92 -0
- package/src/providers/qqmusic/report-schema.d.ts +4 -0
- package/src/providers/qqmusic/report-schema.js +119 -0
- package/src/providers/rakuraku_seisan/actions.d.ts +2 -0
- package/src/providers/rakuraku_seisan/actions.js +50 -0
- package/src/providers/rakuraku_seisan/executors.d.ts +4 -0
- package/src/providers/rakuraku_seisan/executors.js +40 -0
- package/src/providers/rakuraku_seisan/runtime.d.ts +8 -0
- package/src/providers/rakuraku_seisan/runtime.js +251 -0
- package/src/providers/redfox/actions-account.d.ts +2 -0
- package/src/providers/redfox/actions-account.js +24 -0
- package/src/providers/redfox/actions-autohome.d.ts +2 -0
- package/src/providers/redfox/actions-autohome.js +51 -0
- package/src/providers/redfox/actions-baijiahao.d.ts +2 -0
- package/src/providers/redfox/actions-baijiahao.js +58 -0
- package/src/providers/redfox/actions-bilibili.d.ts +2 -0
- package/src/providers/redfox/actions-bilibili.js +67 -0
- package/src/providers/redfox/actions-dongchedi.d.ts +2 -0
- package/src/providers/redfox/actions-dongchedi.js +49 -0
- package/src/providers/redfox/actions-douyin.d.ts +2 -0
- package/src/providers/redfox/actions-douyin.js +297 -0
- package/src/providers/redfox/actions-generation.d.ts +2 -0
- package/src/providers/redfox/actions-generation.js +293 -0
- package/src/providers/redfox/actions-instagram.d.ts +2 -0
- package/src/providers/redfox/actions-instagram.js +49 -0
- package/src/providers/redfox/actions-kuaishou.d.ts +2 -0
- package/src/providers/redfox/actions-kuaishou.js +53 -0
- package/src/providers/redfox/actions-search.d.ts +2 -0
- package/src/providers/redfox/actions-search.js +125 -0
- package/src/providers/redfox/actions-tiktok.d.ts +2 -0
- package/src/providers/redfox/actions-tiktok.js +136 -0
- package/src/providers/redfox/actions-tools.d.ts +2 -0
- package/src/providers/redfox/actions-tools.js +151 -0
- package/src/providers/redfox/actions-toutiao.d.ts +2 -0
- package/src/providers/redfox/actions-toutiao.js +68 -0
- package/src/providers/redfox/actions-transcription.d.ts +2 -0
- package/src/providers/redfox/actions-transcription.js +165 -0
- package/src/providers/redfox/actions-wechat-channel.d.ts +2 -0
- package/src/providers/redfox/actions-wechat-channel.js +63 -0
- package/src/providers/redfox/actions-wechat.d.ts +2 -0
- package/src/providers/redfox/actions-wechat.js +302 -0
- package/src/providers/redfox/actions-weibo.d.ts +2 -0
- package/src/providers/redfox/actions-weibo.js +61 -0
- package/src/providers/redfox/actions-x.d.ts +2 -0
- package/src/providers/redfox/actions-x.js +126 -0
- package/src/providers/redfox/actions-xiaohongshu.d.ts +2 -0
- package/src/providers/redfox/actions-xiaohongshu.js +244 -0
- package/src/providers/redfox/actions-yiche.d.ts +2 -0
- package/src/providers/redfox/actions-yiche.js +59 -0
- package/src/providers/redfox/actions-youtube.d.ts +2 -0
- package/src/providers/redfox/actions-youtube.js +64 -0
- package/src/providers/redfox/actions-zhihu.d.ts +2 -0
- package/src/providers/redfox/actions-zhihu.js +26 -0
- package/src/providers/redfox/actions.d.ts +2 -0
- package/src/providers/redfox/actions.js +49 -0
- package/src/providers/redfox/executors.d.ts +2 -14
- package/src/providers/redfox/executors.js +28 -551
- package/src/providers/redfox/routes.d.ts +11 -0
- package/src/providers/redfox/routes.js +329 -0
- package/src/providers/redfox/runtime.d.ts +6 -0
- package/src/providers/redfox/runtime.js +151 -0
- package/src/providers/redfox/schemas.d.ts +9 -0
- package/src/providers/redfox/schemas.js +40 -0
- package/src/providers/registry.generated.js +30 -0
- package/src/providers/salesforce/context.d.ts +16 -0
- package/src/providers/salesforce/context.js +58 -0
- package/src/providers/salesforce/executors.d.ts +5 -0
- package/src/providers/salesforce/executors.js +54 -0
- package/src/providers/salesforce/media.d.ts +9 -0
- package/src/providers/salesforce/media.js +66 -0
- package/src/providers/salesforce/oauth.d.ts +2 -0
- package/src/providers/salesforce/oauth.js +89 -0
- package/src/providers/salesforce/runtime-analytics.d.ts +2 -0
- package/src/providers/salesforce/runtime-analytics.js +60 -0
- package/src/providers/salesforce/runtime-automation.d.ts +2 -0
- package/src/providers/salesforce/runtime-automation.js +64 -0
- package/src/providers/salesforce/runtime-base.d.ts +2 -0
- package/src/providers/salesforce/runtime-base.js +51 -0
- package/src/providers/salesforce/runtime-bulk.d.ts +2 -0
- package/src/providers/salesforce/runtime-bulk.js +98 -0
- package/src/providers/salesforce/runtime-data.d.ts +2 -0
- package/src/providers/salesforce/runtime-data.js +207 -0
- package/src/providers/salesforce/runtime-files.d.ts +2 -0
- package/src/providers/salesforce/runtime-files.js +108 -0
- package/src/providers/salesforce/transport.d.ts +9 -0
- package/src/providers/salesforce/transport.js +65 -0
- package/src/providers/sansan/actions.d.ts +2 -0
- package/src/providers/sansan/actions.js +165 -0
- package/src/providers/sansan/admin-actions.d.ts +2 -0
- package/src/providers/sansan/admin-actions.js +181 -0
- package/src/providers/sansan/admin.d.ts +2 -0
- package/src/providers/sansan/admin.js +42 -0
- package/src/providers/sansan/business-actions.d.ts +2 -0
- package/src/providers/sansan/business-actions.js +160 -0
- package/src/providers/sansan/business.d.ts +2 -0
- package/src/providers/sansan/business.js +51 -0
- package/src/providers/sansan/executors.d.ts +4 -0
- package/src/providers/sansan/executors.js +59 -0
- package/src/providers/sansan/file-schema.d.ts +2 -0
- package/src/providers/sansan/file-schema.js +8 -0
- package/src/providers/sansan/files.d.ts +11 -0
- package/src/providers/sansan/files.js +49 -0
- package/src/providers/sansan/organization-actions.d.ts +2 -0
- package/src/providers/sansan/organization-actions.js +198 -0
- package/src/providers/sansan/organization-columns.d.ts +2 -0
- package/src/providers/sansan/organization-columns.js +33 -0
- package/src/providers/sansan/organization.d.ts +2 -0
- package/src/providers/sansan/organization.js +88 -0
- package/src/providers/sansan/read.d.ts +2 -0
- package/src/providers/sansan/read.js +25 -0
- package/src/providers/sansan/request.d.ts +22 -0
- package/src/providers/sansan/request.js +94 -0
- package/src/providers/sansan/schemas.d.ts +7 -0
- package/src/providers/sansan/schemas.js +72 -0
- package/src/providers/shopee/runtime.d.ts +33 -29
- package/src/providers/shopee/runtime.js +166 -169
- package/src/providers/smarthr/actions.d.ts +2 -0
- package/src/providers/smarthr/actions.js +286 -0
- package/src/providers/smarthr/employee-runtime.d.ts +1 -0
- package/src/providers/smarthr/employee-runtime.js +63 -0
- package/src/providers/smarthr/employee-schema.d.ts +3 -0
- package/src/providers/smarthr/employee-schema.js +222 -0
- package/src/providers/smarthr/executors.d.ts +4 -0
- package/src/providers/smarthr/executors.js +35 -0
- package/src/providers/smarthr/pagination.d.ts +1 -0
- package/src/providers/smarthr/pagination.js +84 -0
- package/src/providers/smarthr/resource-routes.d.ts +16 -0
- package/src/providers/smarthr/resource-routes.js +163 -0
- package/src/providers/smarthr/runtime.d.ts +13 -0
- package/src/providers/smarthr/runtime.js +242 -0
- package/src/providers/smarthr/supplemental-actions.d.ts +2 -0
- package/src/providers/smarthr/supplemental-actions.js +541 -0
- package/src/providers/smooth/actions.d.ts +2 -0
- package/src/providers/smooth/actions.js +138 -0
- package/src/providers/smooth/executors.d.ts +4 -0
- package/src/providers/smooth/executors.js +102 -0
- package/src/providers/tapd/actions.d.ts +8 -0
- package/src/providers/tapd/actions.js +89 -0
- package/src/providers/tapd/executors.d.ts +4 -0
- package/src/providers/tapd/executors.js +137 -0
- package/src/providers/teable/runtime.js +12 -15
- package/src/providers/tencent_meeting_mcp/actions.d.ts +2 -0
- package/src/providers/tencent_meeting_mcp/actions.js +420 -0
- package/src/providers/tencent_meeting_mcp/executors.d.ts +4 -0
- package/src/providers/tencent_meeting_mcp/executors.js +117 -0
- package/src/providers/threatfox/executors.d.ts +4 -0
- package/src/providers/threatfox/executors.js +40 -0
- package/src/providers/threatfox/runtime.d.ts +15 -0
- package/src/providers/threatfox/runtime.js +128 -0
- package/src/providers/ticket_tailor/runtime.js +1 -1
- package/src/providers/ticketmaster/runtime.js +3 -6
- package/src/providers/timelinesai/runtime.js +13 -16
- package/src/providers/tradebee/actions.d.ts +2 -0
- package/src/providers/tradebee/actions.js +176 -0
- package/src/providers/tradebee/executors.d.ts +4 -0
- package/src/providers/tradebee/executors.js +83 -0
- package/src/providers/twittrapi/executors.d.ts +4 -0
- package/src/providers/twittrapi/executors.js +17 -0
- package/src/providers/twittrapi/runtime.d.ts +12 -0
- package/src/providers/twittrapi/runtime.js +203 -0
- package/src/providers/urlhaus/executors.d.ts +4 -0
- package/src/providers/urlhaus/executors.js +40 -0
- package/src/providers/urlhaus/runtime.d.ts +15 -0
- package/src/providers/urlhaus/runtime.js +142 -0
- package/src/providers/wangdian/runtime.js +16 -19
- package/src/providers/weread/actions.d.ts +2 -0
- package/src/providers/weread/actions.js +424 -0
- package/src/providers/weread/executors.d.ts +4 -0
- package/src/providers/weread/executors.js +98 -0
- package/src/providers/whatsapp/runtime.js +6 -1
- package/src/providers/workast/runtime.js +12 -17
- package/src/providers/youzan/runtime.js +21 -24
- package/src/providers/zenkit/runtime.js +13 -19
- package/src/providers/zhiliaobiaoxun/actions.d.ts +2 -0
- package/src/providers/zhiliaobiaoxun/actions.js +138 -0
- package/src/providers/zhiliaobiaoxun/executors.d.ts +4 -0
- package/src/providers/zhiliaobiaoxun/executors.js +78 -0
- package/src/server/api/auth.d.ts +2 -0
- package/src/server/api/auth.js +2 -1
- package/src/server/api/console-catalog-routes.d.ts +17 -0
- package/src/server/api/console-catalog-routes.js +88 -0
- package/src/server/api/console-oauth-routes.d.ts +18 -0
- package/src/server/api/console-oauth-routes.js +298 -0
- package/src/server/api/docs-routes.d.ts +12 -0
- package/src/server/api/docs-routes.js +38 -0
- package/src/server/api/http-utils.d.ts +1 -0
- package/src/server/api/http-utils.js +8 -0
- package/src/server/api/marketplace-routes.d.ts +7 -0
- package/src/server/api/marketplace-routes.js +62 -0
- package/src/server/api/mcp-routes.d.ts +18 -0
- package/src/server/api/mcp-routes.js +37 -0
- package/src/server/api/policy-routes.d.ts +13 -0
- package/src/server/api/policy-routes.js +50 -0
- package/src/server/api/policy-snapshot.d.ts +14 -0
- package/src/server/api/policy-snapshot.js +30 -0
- package/src/server/api/run-log-routes.d.ts +7 -0
- package/src/server/api/run-log-routes.js +70 -0
- package/src/server/api/runtime-api.d.ts +0 -7
- package/src/server/api/runtime-api.js +0 -13
- package/src/server/api/runtime-app-routes.d.ts +10 -0
- package/src/server/api/runtime-app-routes.js +72 -0
- package/src/server/api/runtime-catalog-routes.d.ts +37 -0
- package/src/server/api/runtime-catalog-routes.js +133 -0
- package/src/server/api/runtime-execution-routes.d.ts +16 -0
- package/src/server/api/runtime-execution-routes.js +198 -0
- package/src/server/api/saas-oauth-routes.d.ts +9 -0
- package/src/server/api/saas-oauth-routes.js +27 -0
- package/src/server/api/saas-project-routes.d.ts +7 -0
- package/src/server/api/saas-project-routes.js +16 -0
- package/src/server/api/transit-file-routes.d.ts +9 -0
- package/src/server/api/transit-file-routes.js +49 -0
- package/src/server/api/trigger-routes.d.ts +15 -0
- package/src/server/api/trigger-routes.js +48 -0
- package/src/server/connect-app.d.ts +1 -0
- package/src/server/connect-app.js +3 -1
- package/src/server/connect-server.d.ts +3 -54
- package/src/server/connect-server.js +95 -1148
- package/src/providers/fastmoss_mcp/official-tools.json +0 -2922
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { sha256Hex } from "../../core/aws-sigv4.js";
|
|
2
|
+
import { looseArray, recordOrEmpty, optionalString, optionalNumber } from "../../core/cast.js";
|
|
3
|
+
import { basicAuthorizationHeader, isAbortLikeError, ProviderRequestError, requiredInputString, requiredResponseRecord, runProviderRequest, providerInputError, providerResponseError, } from "../provider-runtime.js";
|
|
4
|
+
export const kaonaviBaseUrl = "https://api.kaonavi.jp/api/v2.0";
|
|
5
|
+
const tokens = new Map();
|
|
6
|
+
export async function readKaonaviResponse(response) {
|
|
7
|
+
const code = response.status === 429 ? "rate_limited" : "provider_error";
|
|
8
|
+
let payload;
|
|
9
|
+
try {
|
|
10
|
+
payload = await response.json();
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
if (isAbortLikeError(error))
|
|
14
|
+
throw error;
|
|
15
|
+
throw new ProviderRequestError(response.ok ? 502 : response.status, "Kaonavi returned a non-JSON response", undefined, code);
|
|
16
|
+
}
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
const messages = looseArray(recordOrEmpty(payload).errors).map(optionalString).filter(Boolean);
|
|
19
|
+
throw new ProviderRequestError(response.status, messages.join("; ") || `Kaonavi request failed (${response.status})`, undefined, code);
|
|
20
|
+
}
|
|
21
|
+
return requiredResponseRecord(payload, "Kaonavi response");
|
|
22
|
+
}
|
|
23
|
+
export async function getKaonaviToken(values, fetcher, signal, fresh = false) {
|
|
24
|
+
const key = requiredInputString(values.consumerKey, "consumerKey");
|
|
25
|
+
const secret = requiredInputString(values.consumerSecret, "consumerSecret");
|
|
26
|
+
if (key.includes(":"))
|
|
27
|
+
throw providerInputError("consumerKey must not contain a colon");
|
|
28
|
+
const cacheKey = sha256Hex(JSON.stringify([key, secret]));
|
|
29
|
+
const existing = fresh ? undefined : tokens.get(cacheKey);
|
|
30
|
+
if (existing) {
|
|
31
|
+
const token = await existing;
|
|
32
|
+
if (token.expiresAt > Date.now())
|
|
33
|
+
return token.value;
|
|
34
|
+
if (tokens.get(cacheKey) !== existing)
|
|
35
|
+
return getKaonaviToken(values, fetcher, signal);
|
|
36
|
+
}
|
|
37
|
+
const pending = runProviderRequest({ label: "Kaonavi token", signal }, async (requestSignal) => {
|
|
38
|
+
const response = await fetcher(`${kaonaviBaseUrl}/token`, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
signal: requestSignal,
|
|
41
|
+
headers: {
|
|
42
|
+
authorization: basicAuthorizationHeader(`${key}:${secret}`),
|
|
43
|
+
"content-type": "application/x-www-form-urlencoded;charset=UTF-8",
|
|
44
|
+
accept: "application/json",
|
|
45
|
+
},
|
|
46
|
+
body: new URLSearchParams({ grant_type: "client_credentials" }).toString(),
|
|
47
|
+
});
|
|
48
|
+
const payload = await readKaonaviResponse(response);
|
|
49
|
+
const value = optionalString(payload.access_token);
|
|
50
|
+
const ttl = optionalNumber(payload.expire_in);
|
|
51
|
+
if (!value?.trim() || ttl === undefined || !Number.isFinite(ttl) || ttl <= 0)
|
|
52
|
+
throw providerResponseError("Kaonavi token response is missing a valid access_token or expire_in");
|
|
53
|
+
return { value, expiresAt: Date.now() + Math.max(0, ttl * 1000 - 60_000) };
|
|
54
|
+
});
|
|
55
|
+
tokens.set(cacheKey, pending);
|
|
56
|
+
if (tokens.size > 1024) {
|
|
57
|
+
const oldest = tokens.keys().next().value;
|
|
58
|
+
if (oldest !== undefined)
|
|
59
|
+
tokens.delete(oldest);
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
return (await pending).value;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (tokens.get(cacheKey) === pending)
|
|
66
|
+
tokens.delete(cacheKey);
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -44,4 +44,18 @@ export interface LinearMcpComment {
|
|
|
44
44
|
updatedAt?: string;
|
|
45
45
|
url?: string;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Typed fields lifted from one Linear MCP record that names a thing: a team, a
|
|
49
|
+
* project, a workflow state or a label. The list tools answer records of
|
|
50
|
+
* different shapes; only the id is required and the rest is best effort.
|
|
51
|
+
*/
|
|
52
|
+
export interface LinearMcpNamedRecord {
|
|
53
|
+
id: string;
|
|
54
|
+
name?: string;
|
|
55
|
+
key?: string;
|
|
56
|
+
type?: string;
|
|
57
|
+
color?: string;
|
|
58
|
+
url?: string;
|
|
59
|
+
state?: string;
|
|
60
|
+
}
|
|
47
61
|
export declare const linearMcpActions: ActionDefinition[];
|
|
@@ -2,6 +2,7 @@ import { s } from "../../core/json-schema.js";
|
|
|
2
2
|
import { defineProviderAction } from "../../core/provider-definition.js";
|
|
3
3
|
const service = "linear_mcp";
|
|
4
4
|
const readScope = ["read"];
|
|
5
|
+
const writeScope = ["write"];
|
|
5
6
|
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
7
|
const userSchema = s.looseObject("The signed-in Linear user.", {
|
|
7
8
|
id: s.nonEmptyString("Linear user ID; the same viewer ID the Linear GraphQL API reports."),
|
|
@@ -41,6 +42,54 @@ const commentSchema = s.looseObject("A Linear issue comment.", {
|
|
|
41
42
|
updatedAt: s.optional(s.string("Last edit time, when returned.")),
|
|
42
43
|
url: s.optional(s.string("Link to the comment in Linear.")),
|
|
43
44
|
});
|
|
45
|
+
const namedRecordSchema = s.looseObject("A team, project, workflow state or label as Linear MCP lists it. Typed fields are lifted when present; the rest is only in the action's raw text.", {
|
|
46
|
+
id: s.nonEmptyString("Record ID as Linear MCP returned it."),
|
|
47
|
+
name: s.optional(s.string("Display name.")),
|
|
48
|
+
key: s.optional(s.string("Team key such as ENG, when the record is a team.")),
|
|
49
|
+
type: s.optional(s.string("Workflow state type such as started or completed, when the record is a state.")),
|
|
50
|
+
color: s.optional(s.string("Color, when the record is a label.")),
|
|
51
|
+
url: s.optional(s.string("Link to the record in Linear, when returned.")),
|
|
52
|
+
state: s.optional(s.string("Project state, when the record is a project.")),
|
|
53
|
+
});
|
|
54
|
+
const issueFields = {
|
|
55
|
+
title: s.nonEmptyString("Issue title."),
|
|
56
|
+
description: s.string("Issue description in Markdown."),
|
|
57
|
+
team: s.nonEmptyString("Team key, name or ID the issue belongs to."),
|
|
58
|
+
assignee: s.string("Assignee as a user ID, name or email, or me for the signed-in user."),
|
|
59
|
+
state: s.string("Workflow state name or ID."),
|
|
60
|
+
priority: s.integer("Priority as Linear numbers it: 0 none, 1 urgent, 2 high, 3 medium, 4 low.", {
|
|
61
|
+
minimum: 0,
|
|
62
|
+
maximum: 4,
|
|
63
|
+
}),
|
|
64
|
+
labels: s.stringArray("Label names or IDs."),
|
|
65
|
+
project: s.string("Project name or ID."),
|
|
66
|
+
dueDate: s.string("Due date as YYYY-MM-DD."),
|
|
67
|
+
parentId: s.string("Parent issue ID or identifier, for a sub-issue."),
|
|
68
|
+
estimate: s.integer("Estimate on the team's scale."),
|
|
69
|
+
};
|
|
70
|
+
const optionalIssueFields = [
|
|
71
|
+
"description",
|
|
72
|
+
"assignee",
|
|
73
|
+
"state",
|
|
74
|
+
"priority",
|
|
75
|
+
"labels",
|
|
76
|
+
"project",
|
|
77
|
+
"dueDate",
|
|
78
|
+
"parentId",
|
|
79
|
+
"estimate",
|
|
80
|
+
];
|
|
81
|
+
const createIssueInputSchema = s.object("Fields forwarded to Linear's MCP save_issue tool without an id, which creates the issue. Keys this schema does not name pass through as given and Linear's server validates them.", issueFields, { optional: optionalIssueFields, additionalProperties: true });
|
|
82
|
+
const updateIssueInputSchema = s.object("Fields forwarded to Linear's MCP save_issue tool with an id, which updates the issue. Only the fields given change; keys this schema does not name pass through as given.", { id: s.nonEmptyString("Issue ID or human identifier such as ENG-123, as returned by list_issues."), ...issueFields }, { optional: ["title", "team", ...optionalIssueFields], additionalProperties: true });
|
|
83
|
+
const createCommentInputSchema = s.object("Fields forwarded to Linear's MCP save_comment tool without an id, which creates the comment.", {
|
|
84
|
+
issueId: s.nonEmptyString("Issue ID or human identifier such as ENG-123."),
|
|
85
|
+
body: s.nonEmptyString("Comment body in Markdown."),
|
|
86
|
+
parentId: s.string("Comment ID to reply to, for a threaded reply."),
|
|
87
|
+
}, { optional: ["parentId"], additionalProperties: true });
|
|
88
|
+
const listProjectsInputSchema = s.object("Filters forwarded to Linear's MCP list_projects tool. Keys this schema does not name pass through as given.", {
|
|
89
|
+
team: s.nonEmptyString("Team key, name or ID whose projects to list."),
|
|
90
|
+
limit: s.integer("Maximum number of projects to return on this page.", { minimum: 1, maximum: 250 }),
|
|
91
|
+
cursor: s.nonEmptyString("Cursor returned by the previous page of the same query."),
|
|
92
|
+
}, { optional: ["team", "limit", "cursor"], additionalProperties: true });
|
|
44
93
|
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
94
|
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
95
|
orderBy: s.string("Sort field, such as updatedAt or createdAt."),
|
|
@@ -99,4 +148,89 @@ export const linearMcpActions = [
|
|
|
99
148
|
raw: rawSchema,
|
|
100
149
|
}),
|
|
101
150
|
}),
|
|
151
|
+
defineProviderAction(service, {
|
|
152
|
+
name: "list_teams",
|
|
153
|
+
operationType: "read",
|
|
154
|
+
description: "List the teams of the connected Linear workspace through Linear's MCP list_teams tool: the keys and IDs the issue tools take as team.",
|
|
155
|
+
requiredScopes: readScope,
|
|
156
|
+
followUpActions: ["linear_mcp.list_issue_statuses", "linear_mcp.list_issue_labels", "linear_mcp.create_issue"],
|
|
157
|
+
inputSchema: s.object({}),
|
|
158
|
+
outputSchema: s.requiredObject("The teams.", {
|
|
159
|
+
teams: s.array("Teams as returned.", namedRecordSchema),
|
|
160
|
+
raw: rawSchema,
|
|
161
|
+
}),
|
|
162
|
+
}),
|
|
163
|
+
defineProviderAction(service, {
|
|
164
|
+
name: "list_projects",
|
|
165
|
+
operationType: "read",
|
|
166
|
+
description: "List Linear projects through Linear's MCP list_projects tool, optionally for one team, with cursor pagination.",
|
|
167
|
+
requiredScopes: readScope,
|
|
168
|
+
inputSchema: listProjectsInputSchema,
|
|
169
|
+
outputSchema: s.requiredObject("One page of projects.", {
|
|
170
|
+
projects: s.array("Projects on this page.", namedRecordSchema),
|
|
171
|
+
hasNextPage: s.boolean("Whether another page follows."),
|
|
172
|
+
cursor: s.nullable(s.string("Cursor for the next page, when one is available.")),
|
|
173
|
+
raw: rawSchema,
|
|
174
|
+
}),
|
|
175
|
+
}),
|
|
176
|
+
defineProviderAction(service, {
|
|
177
|
+
name: "list_issue_statuses",
|
|
178
|
+
operationType: "read",
|
|
179
|
+
description: "List one team's workflow states through Linear's MCP list_issue_statuses tool: the names the issue tools take as state.",
|
|
180
|
+
requiredScopes: readScope,
|
|
181
|
+
inputSchema: s.requiredObject("The team whose workflow states to list.", {
|
|
182
|
+
team: s.nonEmptyString("Team key, name or ID."),
|
|
183
|
+
}),
|
|
184
|
+
outputSchema: s.requiredObject("The workflow states.", {
|
|
185
|
+
statuses: s.array("States as returned.", namedRecordSchema),
|
|
186
|
+
raw: rawSchema,
|
|
187
|
+
}),
|
|
188
|
+
}),
|
|
189
|
+
defineProviderAction(service, {
|
|
190
|
+
name: "list_issue_labels",
|
|
191
|
+
operationType: "read",
|
|
192
|
+
description: "List issue labels through Linear's MCP list_issue_labels tool, for the workspace or one team.",
|
|
193
|
+
requiredScopes: readScope,
|
|
194
|
+
inputSchema: s.object("Optional team filter.", { team: s.nonEmptyString("Team key, name or ID; omitted, the workspace's labels.") }, { optional: ["team"] }),
|
|
195
|
+
outputSchema: s.requiredObject("The labels.", {
|
|
196
|
+
labels: s.array("Labels as returned.", namedRecordSchema),
|
|
197
|
+
raw: rawSchema,
|
|
198
|
+
}),
|
|
199
|
+
}),
|
|
200
|
+
defineProviderAction(service, {
|
|
201
|
+
name: "create_issue",
|
|
202
|
+
operationType: "write",
|
|
203
|
+
description: "Create a Linear issue through Linear's MCP save_issue tool. Needs the write scope on the grant; an id in the input is dropped so this never updates an existing issue.",
|
|
204
|
+
requiredScopes: writeScope,
|
|
205
|
+
followUpActions: ["linear_mcp.get_issue", "linear_mcp.create_comment"],
|
|
206
|
+
inputSchema: createIssueInputSchema,
|
|
207
|
+
outputSchema: s.requiredObject("The created issue.", {
|
|
208
|
+
issue: s.nullable(issueSchema),
|
|
209
|
+
raw: rawSchema,
|
|
210
|
+
}),
|
|
211
|
+
}),
|
|
212
|
+
defineProviderAction(service, {
|
|
213
|
+
name: "update_issue",
|
|
214
|
+
operationType: "write",
|
|
215
|
+
description: "Update a Linear issue through Linear's MCP save_issue tool with its id: the title, description, team, assignee, state, priority, labels, project, due date, parent or estimate. Needs the write scope on the grant.",
|
|
216
|
+
requiredScopes: writeScope,
|
|
217
|
+
followUpActions: ["linear_mcp.get_issue"],
|
|
218
|
+
inputSchema: updateIssueInputSchema,
|
|
219
|
+
outputSchema: s.requiredObject("The updated issue.", {
|
|
220
|
+
issue: s.nullable(issueSchema),
|
|
221
|
+
raw: rawSchema,
|
|
222
|
+
}),
|
|
223
|
+
}),
|
|
224
|
+
defineProviderAction(service, {
|
|
225
|
+
name: "create_comment",
|
|
226
|
+
operationType: "write",
|
|
227
|
+
description: "Comment on a Linear issue through Linear's MCP save_comment tool, optionally as a reply to another comment. Needs the write scope on the grant.",
|
|
228
|
+
requiredScopes: writeScope,
|
|
229
|
+
followUpActions: ["linear_mcp.list_comments"],
|
|
230
|
+
inputSchema: createCommentInputSchema,
|
|
231
|
+
outputSchema: s.requiredObject("The created comment.", {
|
|
232
|
+
comment: s.nullable(commentSchema),
|
|
233
|
+
raw: rawSchema,
|
|
234
|
+
}),
|
|
235
|
+
}),
|
|
102
236
|
];
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { CredentialValidationResult, CredentialValidatorOptions, ResolvedCredential } from "../../core/types.ts";
|
|
2
2
|
import type { OAuthProviderContext, ProviderActionHandlers, ProviderActionSources, ProviderRuntimeHandler } from "../provider-runtime.ts";
|
|
3
3
|
declare const service = "linear_mcp";
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* The Linear MCP tool behind each action. Sign-in requires the four reads the
|
|
6
|
+
* connector was built on (linearMcpSignInTools, the validator); the reference
|
|
7
|
+
* reads and the writes are called as they are and fail on their own when the
|
|
8
|
+
* server does not list them. save_issue and save_comment create without an id
|
|
9
|
+
* and update with one, so two actions share each.
|
|
10
|
+
*/
|
|
5
11
|
export declare const linearMcpToolsByAction: ProviderActionSources<typeof service, string>;
|
|
6
12
|
export declare const linearMcpActionHandlers: ProviderActionHandlers<typeof service, ProviderRuntimeHandler<OAuthProviderContext>>;
|
|
7
13
|
/**
|
|
@@ -4,24 +4,48 @@ import { withMcpClient } from "../mcp-client.js";
|
|
|
4
4
|
import { providerResponseError, providerUserAgent, ProviderRequestError, requiredInputString, runProviderRequest, } from "../provider-runtime.js";
|
|
5
5
|
import { linearMcpEndpoint } from "./endpoints.js";
|
|
6
6
|
const service = "linear_mcp";
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* The Linear MCP tool behind each action. Sign-in requires the four reads the
|
|
9
|
+
* connector was built on (linearMcpSignInTools, the validator); the reference
|
|
10
|
+
* reads and the writes are called as they are and fail on their own when the
|
|
11
|
+
* server does not list them. save_issue and save_comment create without an id
|
|
12
|
+
* and update with one, so two actions share each.
|
|
13
|
+
*/
|
|
8
14
|
export const linearMcpToolsByAction = {
|
|
9
15
|
get_self: "get_user",
|
|
10
16
|
list_issues: "list_issues",
|
|
11
17
|
get_issue: "get_issue",
|
|
12
18
|
list_comments: "list_comments",
|
|
19
|
+
list_teams: "list_teams",
|
|
20
|
+
list_projects: "list_projects",
|
|
21
|
+
list_issue_statuses: "list_issue_statuses",
|
|
22
|
+
list_issue_labels: "list_issue_labels",
|
|
23
|
+
create_issue: "save_issue",
|
|
24
|
+
update_issue: "save_issue",
|
|
25
|
+
create_comment: "save_comment",
|
|
13
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* The tools every grant must serve at sign-in. The writes stay out on purpose: a
|
|
29
|
+
* read-only grant, the default, or an older server may not list them, and a
|
|
30
|
+
* credential must not be refused for a tool its grant could never call.
|
|
31
|
+
*/
|
|
32
|
+
const linearMcpSignInTools = [
|
|
33
|
+
linearMcpToolsByAction.get_self,
|
|
34
|
+
linearMcpToolsByAction.list_issues,
|
|
35
|
+
linearMcpToolsByAction.get_issue,
|
|
36
|
+
linearMcpToolsByAction.list_comments,
|
|
37
|
+
];
|
|
14
38
|
const humanIdentifier = /^[A-Z][A-Z0-9]*-\d+$/;
|
|
15
39
|
const uuidIdentifier = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
16
40
|
const truncationMarker = /\(truncated\b/i;
|
|
17
41
|
const maxToolListPages = 20;
|
|
18
42
|
export const linearMcpActionHandlers = {
|
|
19
43
|
async get_self(_input, context) {
|
|
20
|
-
const result = await callLinearMcpTool(context,
|
|
44
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.get_self, { query: "me" });
|
|
21
45
|
return { user: parseLinearMcpUser(result.payload) ?? null, raw: result.text };
|
|
22
46
|
},
|
|
23
47
|
async list_issues(input, context) {
|
|
24
|
-
const result = await callLinearMcpTool(context,
|
|
48
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.list_issues, compactObject({
|
|
25
49
|
updatedAt: optionalString(input.updatedAt),
|
|
26
50
|
orderBy: optionalString(input.orderBy),
|
|
27
51
|
limit: optionalInteger(input.limit),
|
|
@@ -31,15 +55,72 @@ export const linearMcpActionHandlers = {
|
|
|
31
55
|
},
|
|
32
56
|
async get_issue(input, context) {
|
|
33
57
|
const id = requiredInputString(input.id, "id");
|
|
34
|
-
const result = await callLinearMcpTool(context,
|
|
58
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.get_issue, { id });
|
|
35
59
|
return { issue: parseLinearMcpIssue(result.payload) ?? null, raw: result.text };
|
|
36
60
|
},
|
|
37
61
|
async list_comments(input, context) {
|
|
38
62
|
const issueId = requiredInputString(input.issueId, "issueId");
|
|
39
|
-
const result = await callLinearMcpTool(context,
|
|
63
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.list_comments, { issueId });
|
|
40
64
|
return { comments: parseLinearMcpComments(result.payload), raw: result.text };
|
|
41
65
|
},
|
|
66
|
+
async list_teams(_input, context) {
|
|
67
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.list_teams, {});
|
|
68
|
+
return { teams: parseLinearMcpRecords(result.payload, "teams"), raw: result.text };
|
|
69
|
+
},
|
|
70
|
+
async list_projects(input, context) {
|
|
71
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.list_projects, compactObject(input));
|
|
72
|
+
return {
|
|
73
|
+
projects: parseLinearMcpRecords(result.payload, "projects"),
|
|
74
|
+
...parseLinearMcpPaging(result.payload),
|
|
75
|
+
raw: result.text,
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
async list_issue_statuses(input, context) {
|
|
79
|
+
const team = requiredInputString(input.team, "team");
|
|
80
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.list_issue_statuses, { team });
|
|
81
|
+
return {
|
|
82
|
+
statuses: parseLinearMcpRecords(result.payload, "statuses", "states", "workflowStates"),
|
|
83
|
+
raw: result.text,
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
async list_issue_labels(input, context) {
|
|
87
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.list_issue_labels, compactObject({ team: optionalString(input.team) }));
|
|
88
|
+
return { labels: parseLinearMcpRecords(result.payload, "labels", "issueLabels"), raw: result.text };
|
|
89
|
+
},
|
|
90
|
+
async create_issue(input, context) {
|
|
91
|
+
const title = requiredInputString(input.title, "title");
|
|
92
|
+
const team = requiredInputString(input.team, "team");
|
|
93
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.create_issue, {
|
|
94
|
+
...withoutId(input),
|
|
95
|
+
title,
|
|
96
|
+
team,
|
|
97
|
+
});
|
|
98
|
+
return { issue: parseLinearMcpIssue(result.payload) ?? null, raw: result.text };
|
|
99
|
+
},
|
|
100
|
+
async update_issue(input, context) {
|
|
101
|
+
const id = requiredInputString(input.id, "id");
|
|
102
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.update_issue, {
|
|
103
|
+
...compactObject(input),
|
|
104
|
+
id,
|
|
105
|
+
});
|
|
106
|
+
return { issue: parseLinearMcpIssue(result.payload) ?? null, raw: result.text };
|
|
107
|
+
},
|
|
108
|
+
async create_comment(input, context) {
|
|
109
|
+
const issueId = requiredInputString(input.issueId, "issueId");
|
|
110
|
+
const body = requiredInputString(input.body, "body");
|
|
111
|
+
const result = await callLinearMcpTool(context, linearMcpToolsByAction.create_comment, {
|
|
112
|
+
...withoutId(input),
|
|
113
|
+
issueId,
|
|
114
|
+
body,
|
|
115
|
+
});
|
|
116
|
+
return { comment: parseLinearMcpComments(unwrapComment(result.payload))[0] ?? null, raw: result.text };
|
|
117
|
+
},
|
|
42
118
|
};
|
|
119
|
+
/** The input with any `id` dropped: save_issue and save_comment update when they see one, and a create never does. */
|
|
120
|
+
function withoutId(input) {
|
|
121
|
+
const { id: _id, ...rest } = compactObject(input);
|
|
122
|
+
return rest;
|
|
123
|
+
}
|
|
43
124
|
/**
|
|
44
125
|
* Validate the OAuth grant against the MCP server: every tool the actions map
|
|
45
126
|
* must be listed (a rename shows up here, at sign-in, never mid-poll), then the
|
|
@@ -47,9 +128,9 @@ export const linearMcpActionHandlers = {
|
|
|
47
128
|
*/
|
|
48
129
|
export async function validateLinearMcpCredential(credential, options) {
|
|
49
130
|
const context = { accessToken: credential.accessToken, fetcher: options.fetcher, signal: options.signal };
|
|
50
|
-
return withLinearMcpClient(context,
|
|
131
|
+
return withLinearMcpClient(context, async (client, signal) => {
|
|
51
132
|
const available = await listLinearMcpToolNames(client, signal);
|
|
52
|
-
const missing =
|
|
133
|
+
const missing = linearMcpSignInTools.filter((name) => !available.has(name));
|
|
53
134
|
if (missing.length > 0) {
|
|
54
135
|
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
136
|
}
|
|
@@ -78,8 +159,8 @@ async function listLinearMcpToolNames(client, signal) {
|
|
|
78
159
|
return names;
|
|
79
160
|
}
|
|
80
161
|
/** Call one tool in a fresh MCP session and return its text and parsed payload. */
|
|
81
|
-
function callLinearMcpTool(context,
|
|
82
|
-
return withLinearMcpClient(context,
|
|
162
|
+
function callLinearMcpTool(context, name, args) {
|
|
163
|
+
return withLinearMcpClient(context, async (client, signal) => readLinearMcpToolResult(name, await client.callTool({ name, arguments: args }, { signal })));
|
|
83
164
|
}
|
|
84
165
|
/**
|
|
85
166
|
* Join the text blocks as `text` and read the JSON they carry as `payload`
|
|
@@ -127,9 +208,49 @@ function parseLinearMcpIssuePage(payload) {
|
|
|
127
208
|
const record = optionalRecord(payload);
|
|
128
209
|
const items = Array.isArray(payload) ? payload : looseArray(record?.issues ?? record?.nodes ?? record?.results);
|
|
129
210
|
const issues = items.map(parseLinearMcpIssue).filter((issue) => issue !== undefined);
|
|
211
|
+
return { issues, ...parseLinearMcpPaging(payload) };
|
|
212
|
+
}
|
|
213
|
+
/** The page bounds of a list answer: a cursor under any of its names, and whether another page follows. */
|
|
214
|
+
function parseLinearMcpPaging(payload) {
|
|
215
|
+
const record = optionalRecord(payload);
|
|
130
216
|
const cursor = record ? (pickOptionalString(record, "cursor", "nextCursor", "endCursor") ?? null) : null;
|
|
131
217
|
const hasNextPage = (record && (optionalBoolean(record.hasNextPage) ?? optionalBoolean(record.hasMore))) ?? cursor !== null;
|
|
132
|
-
return {
|
|
218
|
+
return { hasNextPage, cursor };
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* The records of a list answer — the first of the named arrays, the answer
|
|
222
|
+
* itself when it is an array, else `nodes` or `results` — each typed when it
|
|
223
|
+
* carries an id: a team, a project, a workflow state or a label.
|
|
224
|
+
*/
|
|
225
|
+
function parseLinearMcpRecords(payload, ...keys) {
|
|
226
|
+
const record = optionalRecord(payload);
|
|
227
|
+
const named = keys.map((key) => record?.[key]).find((value) => Array.isArray(value));
|
|
228
|
+
const items = Array.isArray(payload) ? payload : looseArray(named ?? record?.nodes ?? record?.results);
|
|
229
|
+
return items.flatMap((item) => {
|
|
230
|
+
const entry = optionalRecord(item);
|
|
231
|
+
const id = entry && pickOptionalString(entry, "id");
|
|
232
|
+
if (!entry || !id)
|
|
233
|
+
return [];
|
|
234
|
+
return [
|
|
235
|
+
{
|
|
236
|
+
id,
|
|
237
|
+
...compactObject({
|
|
238
|
+
name: pickOptionalString(entry, "name", "title"),
|
|
239
|
+
key: pickOptionalString(entry, "key"),
|
|
240
|
+
type: pickOptionalString(entry, "type"),
|
|
241
|
+
color: pickOptionalString(entry, "color"),
|
|
242
|
+
url: pickOptionalString(entry, "url"),
|
|
243
|
+
state: labelOf(entry.state ?? entry.status),
|
|
244
|
+
}),
|
|
245
|
+
},
|
|
246
|
+
];
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/** A save_comment answer as a one-item list for the comments reader: the comment under `comment`, else the answer itself. */
|
|
250
|
+
function unwrapComment(payload) {
|
|
251
|
+
const record = optionalRecord(payload);
|
|
252
|
+
const comment = record && (optionalRecord(record.comment) ?? record);
|
|
253
|
+
return comment ? [comment] : [];
|
|
133
254
|
}
|
|
134
255
|
function parseLinearMcpIssue(value) {
|
|
135
256
|
const record = optionalRecord(value);
|
|
@@ -201,7 +322,7 @@ function parseLabels(value) {
|
|
|
201
322
|
return name ? [name] : [];
|
|
202
323
|
});
|
|
203
324
|
}
|
|
204
|
-
function withLinearMcpClient(context,
|
|
325
|
+
function withLinearMcpClient(context, run) {
|
|
205
326
|
return runProviderRequest({ signal: context.signal, label: "Linear MCP" }, (signal) => withMcpClient({
|
|
206
327
|
endpoint: new URL(linearMcpEndpoint),
|
|
207
328
|
transport: "streamable_http",
|
|
@@ -209,30 +330,21 @@ function withLinearMcpClient(context, phase, run) {
|
|
|
209
330
|
headers: { authorization: `Bearer ${context.accessToken}`, "user-agent": providerUserAgent },
|
|
210
331
|
redirect: "manual",
|
|
211
332
|
signal,
|
|
212
|
-
mapError:
|
|
333
|
+
mapError: mapLinearMcpError,
|
|
213
334
|
}, (client) => run(client, signal)));
|
|
214
335
|
}
|
|
215
|
-
|
|
216
|
-
|
|
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) {
|
|
336
|
+
// Status alone does not establish that reconnecting can resolve a provider failure.
|
|
337
|
+
function mapLinearMcpError(error) {
|
|
221
338
|
if (error instanceof ProviderRequestError)
|
|
222
339
|
return error;
|
|
223
|
-
if (error instanceof UnauthorizedError)
|
|
224
|
-
return
|
|
340
|
+
if (error instanceof UnauthorizedError) {
|
|
341
|
+
return new ProviderRequestError(401, "Linear MCP authorization request failed.", undefined, "provider_error");
|
|
342
|
+
}
|
|
225
343
|
if (error instanceof SdkHttpError) {
|
|
226
|
-
|
|
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);
|
|
344
|
+
return new ProviderRequestError(error.status, `Linear MCP request failed with HTTP ${error.status}.`, undefined, error.status === 429 ? "rate_limited" : "provider_error");
|
|
230
345
|
}
|
|
231
346
|
if (error instanceof ProtocolError) {
|
|
232
|
-
return new ProviderRequestError(502, `Linear MCP
|
|
347
|
+
return new ProviderRequestError(502, `Linear MCP protocol error ${error.code}.`, undefined, "provider_error");
|
|
233
348
|
}
|
|
234
349
|
return error;
|
|
235
350
|
}
|
|
236
|
-
function credentialError(phase) {
|
|
237
|
-
return new ProviderRequestError(phase === "validate" ? 400 : 401, "Linear MCP credential is invalid or expired; reconnect Linear.");
|
|
238
|
-
}
|