| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat(integrations): support MCP_OAUTH2 across create/update/get for static, dynamic, and cimd (#7464) ## Describe the problem and your solution Adds full support for MCP_OAUTH2 integrations — the create, update, and get flows now properly handle all three ways an MCP provider's OAuth client can be registered: static (you provide your own client ID/secret), dynamic (Nango registers a client with the provider automatically), and CIMD (Nango publishes a client metadata document the provider fetches). Before this, MCP_OAUTH2 was only fully wired up through the webapp only, the public API and the MCP management tool either silently dropped credentials or didn't enforce the right rules for each registration mode. Now: - Creating a static integration requires both a client ID and secret, you can no longer end up with a half-configured, broken integration by leaving one out. - Creating a dynamic or CIMD integration rejects any client ID/secret you try to pass in, since Nango manages those itself — previously it would silently accept and discard them instead of telling you. - Updating an integration now correctly enforces the same rule: only static integrations can have their credentials rotated; scopes can always be updated regardless of registration mode. - Renaming a CIMD integration keeps its client ID in sync with the rename (it's derived from the integration's ID). If that's not possible — because the Nango instance isn't reachable over a public HTTPS URL — the rename is now rejected outright instead of silently leaving a stale, broken client ID in place. - Fetching an integration's credentials now returns the actual client ID, secret, and scopes for MCP providers instead of always returning null. <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7464?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 26 天前 | |
feat(integrations): support MCP_OAUTH2 across create/update/get for static, dynamic, and cimd (#7464) ## Describe the problem and your solution Adds full support for MCP_OAUTH2 integrations — the create, update, and get flows now properly handle all three ways an MCP provider's OAuth client can be registered: static (you provide your own client ID/secret), dynamic (Nango registers a client with the provider automatically), and CIMD (Nango publishes a client metadata document the provider fetches). Before this, MCP_OAUTH2 was only fully wired up through the webapp only, the public API and the MCP management tool either silently dropped credentials or didn't enforce the right rules for each registration mode. Now: - Creating a static integration requires both a client ID and secret, you can no longer end up with a half-configured, broken integration by leaving one out. - Creating a dynamic or CIMD integration rejects any client ID/secret you try to pass in, since Nango manages those itself — previously it would silently accept and discard them instead of telling you. - Updating an integration now correctly enforces the same rule: only static integrations can have their credentials rotated; scopes can always be updated regardless of registration mode. - Renaming a CIMD integration keeps its client ID in sync with the rename (it's derived from the integration's ID). If that's not possible — because the Nango instance isn't reachable over a public HTTPS URL — the rename is now rejected outright instead of silently leaving a stale, broken client ID in place. - Fetching an integration's credentials now returns the actual client ID, secret, and scopes for MCP providers instead of always returning null. <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7464?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 26 天前 | |
feat(mcp): support static server URL and configurable scopes for MCP_OAUTH2_GENERIC (#7465) ## Describe the problem and your solution - This pr adds configurable OAuth scopes and a static `mcp_server_url` provider override for `MCP_OAUTH2_GENERIC` integrations, with a settings UI to add/remove scopes and a create-form field for setting them upfront. Scope-joining now respects the provider's configured `scope_separator` instead of always using a space, and the settings page correctly gates all editable fields (scopes, client name/URI/logo URI) behind `environment:integrations:update` with proper feedback on failed scope updates. <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7465?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> | 1 个月前 | |
fix(mcp-generic): omit empty client_secret on token refresh (#6921) Public MCP clients were refreshed via simple-oauth2, which always sent client_secret= and broke strict token endpoints like Resend. Use the MCP SDK refresh path instead so the secret is omitted entirely. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/6921?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 2 个月前 | |
fix(oauth2): interpolate connection_config in refresh/token params before refresh (#7807) ## Describe the problem and your solution - interpolate `connection_config` in refresh/token params before refresh <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7807?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> | 10 天前 | |
fix(oauth2): interpolate connection_config in refresh/token params before refresh (#7807) ## Describe the problem and your solution - interpolate `connection_config` in refresh/token params before refresh <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7807?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> | 10 天前 | |
feat: add API endpoint to create/delete/edit function variants (#7791) Adding: - POST /connections/:connectionId/functions/:functionUuid/variants to create a variant - DELETE /connections/:connectionId/functions/:functionUuid/variants/:variant to delete a variant - PATCH connections/:connectionID/functions/:functionID/ - PATCH connections/:connectionID/functions/:functionID/variants/:variant Refactor schedules by consolidating logic and only created schedules for enabled function instances <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7791?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> | 11 天前 | |
fix(syncs): batch schedule search fan-out (#7318) ## Problem The connection Syncs tab returns a 500 for any connection with more than 1000 syncs. `getSyncs` sends one schedule name per sync in a single `POST /v1/schedules/search`, and that route caps `names` at 1000, so the orchestrator answers 400 and `getSyncs` throws. Levity hit this in prod with 1581 syncs on one connection. The connections list fans out the same way but fails soft, silently dropping the "Schedule paused" badge whenever a page of 20 connections totals over 1000 syncs. ## Solution - Chunk inside `Orchestrator.searchSchedules` rather than at each call site, so `getSyncs`, `getConnections` and `manager.service` are all covered and a new caller cannot reintroduce the fan-out. - Move the cap to `maxScheduleNamesPerSearch` so the client and the route schema cannot drift. - Skip the orchestrator call entirely when a connection has no syncs. - Drop the unused `TestOrchestratorService` from the orchestrator's public exports: shared now imports the package at runtime, and the main entry was loading this dead test helper (and its scheduler test-db import) into every consumer. Raising the cap instead only moves the ceiling: the scheduler resolves these names with a single `whereIn`. Fixes [NAN-6818](https://linear.app/nango/issue/NAN-6818) ## Testing - Unit tests cover batch boundaries, merging across batches, a failing later batch, and the empty case. - Verified locally against a seeded connection with 1601 syncs: the tab now returns 200 with all 1601 rows, each carrying `schedule_status`. Probing the orchestrator directly confirms the boundary — 1000 names → 200, 1001 → 400. ## Follow-ups - The tab still fetches every sync with no pagination and re-polls every 5s — [NAN-6819](https://linear.app/nango/issue/NAN-6819). | 1 个月前 | |
feat(integrations): add support for sentry mcp (#7865) ## Describe the problem and your solution - add support for sentry mcp <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7865?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="View guided diff" src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 9 天前 | |
fix(microsoft-admin): stop double-encoding the client_credentials scope (#7712) ## Describe the problem and your solution Connecting a `microsoft-admin` integration fails at the `client_credentials` token exchange whenever the integration has a scope set. Client credentials only accepts `<resource>/.default`, so the scope is always something like `https://graph.microsoft.com/.default`: ``` Microsoft admin token request failed: ... "error":"invalid_scope","error_description":"AADSTS1002012: The provided value for scope https%3A%2F%2Fgraph.microsoft.com%2F.default is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier (application ID URI)." ``` **Cause:** `createMicrosoftAdminToken` and `refreshMicrosoftAdminToken` set `scope: encodeURIComponent(scope)` in a plain-object body and post it with `Content-Type: application/x-www-form-urlencoded`. Axios then form-encodes the object again, so the scope is encoded twice. Microsoft decodes once and is left with the literal string `https%3A%2F%2F…`. ```mermaid flowchart LR subgraph before["Before this PR"] direction LR A1["Scope value<br/>https://…"] --> B1["Nango encodes<br/>https%3A%2F…"] --> C1["Axios encodes<br/>https%253A%252F…"] --> D1["Microsoft sees<br/>https%3A%2F…<br/>AADSTS1002012"] end subgraph after["After this PR"] direction LR A2["Scope value<br/>https://…"] --> B2["Nango leaves it alone"] --> C2["Axios encodes<br/>https%3A%2F…"] --> D2["Microsoft sees<br/>https://…<br/>token issued"] end classDef bad fill:#FAECE7,stroke:#993C1D,color:#712B13 classDef good fill:#E1F5EE,stroke:#0F6E56,color:#085041 class B1,D1 bad class D2 good ``` Every valid client-credentials scope contains `/`, and URLs also contain `:`, so this can't be worked around in the integration config. An unset scope doesn't help either: it becomes the string `"undefined"`. Both the initial token and every refresh are affected. **Fix:** remove the `encodeURIComponent` in both functions and let axios do the only encoding. **Why it may only be showing up now:** these lines haven't changed since `microsoft-admin` was added (#4904), and every axios version from 1.12 to 1.18 double-encodes the same way. Refresh was fixed in #5329, which suggests the flow worked at some point, so Microsoft may have tightened scope validation since. We haven't been able to confirm that. ## Testing instructions - Added `packages/shared/lib/clients/provider.client.unit.test.ts`. It runs a loopback token endpoint and checks that the decoded `scope` form field is exactly `https://graph.microsoft.com/.default` on both token creation and refresh. **It fails on `master`**: it receives `https%3A%2F%2Fgraph.microsoft.com%2F.default`, the same value as in Microsoft's error. It passes with this change. - Checked against Microsoft directly with a real multi-tenant app registration that has admin consent. A `client_credentials` request with the scope encoded once returns a token. The same request with the scope encoded twice, as `master` sends it, returns `AADSTS1002012`. - `tsc -b tsconfig.build.json` is clean, and Prettier passes via lint-staged. To reproduce: create a `microsoft-admin` integration with scopes `https://graph.microsoft.com/.default`, connect with any tenant ID, and approve admin consent. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7712?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: Andre Haikal <andre@askdragonfly.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> | 16 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 26 天前 | ||
| 26 天前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 10 天前 | ||
| 10 天前 | ||
| 11 天前 | ||
| 1 个月前 | ||
| 9 天前 | ||
| 16 天前 |