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