## I have read the
[CONTRIBUTING.md](<https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md>)
file.
YES
## What kind of change does this PR introduce?
Feature / refactor.
## What is the current behavior?
The dashboard assistant runs `@supabase/mcp-server-supabase` in-process
over an in-memory transport (`lib/ai/supabase-mcp.ts`).
## What is the new behavior?
The assistant connects to the **remote MCP server** over HTTP
(`@ai-sdk/mcp`), forwarding the dashboard session token as a bearer. URL
comes from `NEXT_PUBLIC_MCP_URL` with a local-dev fallback;
platform-only, and Nimbus works via the same env var.
* **Tool model unchanged:** UI-controlled `execute_sql` (with
`needsApproval`) and `deploy_edge_function` still come from Studio; the
allowlist (`TOOL_CATEGORY_MAP`) remains the gate keeping the remote's
write tools away from the assistant (`read_only` is defense-in-depth).
* **Attribution:** sends `x-source-name: supabase-studio` (+
`x-source-version`) → logged as `source_name`/`client_name`.
* **Connection lifecycle:** the HTTP client is closed via the request's
`AbortSignal` (tools execute later during streaming); `signal` is
required on `getTools`/`getMcpTools`.
* **Resilience:** a remote-MCP failure degrades to the remaining tools
instead of failing the assistant.
* **Drift protection:** relied-upon tools are typed against `keyof
typeof supabaseMcpToolSchemas`, so a package bump that renames/removes
one fails `pnpm typecheck`; a runtime check also warns if the deployed
server returns fewer tools.
* Adds unit tests for the above.
## Additional context
* Verified end-to-end against a local remote MCP server with a dashboard
token: `initialize` 200, tools listed, a tool executed, client closed
cleanly.
* The remote MCP (mgmt-api) already accepts dashboard session tokens
(GoTrue-JWT auth path) — no backend change needed. `NEXT_PUBLIC_MCP_URL`
must point at each env's `/mcp`.
* `@supabase/mcp-server-supabase` is kept — still used by the
self-hosted `/api/mcp` routes.
Closes
[AI-137](https://linear.app/supabase/issue/AI-137/switch-dashboard-assistant-to-remote-mcp)
## Rollout
* **Rollout:** merges with `USE_REMOTE_MCP` off (in-process); flip it to
`true` per environment (staging → prod → Nimbus) once each one's
prerequisites land.
* **Rollback:** unset `USE_REMOTE_MCP` and redeploy to fall back to the
in-process client — no revert needed.
## Summary by CodeRabbit
* **Bug Fixes**
* Improved AI request handling so tool loading and generation clean up
properly when a request is cancelled or the browser connection closes.
* Added safer fallback behavior when remote tool loading fails, so AI
features can continue with available tools instead of stopping entirely.
* Updated remote tool access to use the current project reference and
preserve the correct access headers.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* AI tools now connect more reliably to remote services and stop cleanly
when requests end or are canceled.
* Tool loading is more resilient, continuing with available tools if
remote access is unavailable.
* **Bug Fixes**
* Improved cleanup to prevent lingering connections during SQL
generation and policy workflows.
* Added safer handling for remote tool changes and invalid responses.
* **Tests**
* Expanded automated coverage for remote tool setup, cancellation, and
fallback behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
**Changes**
- Extracted tracing conditional to an `isTracingAllowed` helper with
unit tests (the function is simple but sensitive hence the extra testing
precaution)
- Disables Braintrust tracing for projects in EU database regions
(region prefix `eu-`) to address GDPR data residency concerns
- Disables Braintrust tracing for orgs whose owners have signed the
previous DPA, as a stopgap during the 30-day notice period for the
updated DPA that adds Braintrust as a subprocessor
- Refactored `org-ai-details.ts` → `ai-details.ts`, splitting
`getOrgAIDetails` into separate org and project helpers to cleanly scope
the EU-region check at the project level
DPA check uses the newly added `/documents/dpa-signed` endpoint from
https://github.com/supabase/platform/pull/31060. This PR includes
regenerated `api.d.ts` and `platform.d.ts` from running `pnpm codegen`
in `packages/api-types` to get type safety on this new endpoint.
Note tracing is still yet to be activated in production, this is a
preparatory step.
**To verify**
Send a chat message and check for the `x-braintrust-span-id` response
header on `POST /api/ai/sql/generate-v4` — it should be absent for
DPA-signed orgs or EU-region projects, and present otherwise.
<img width="3594" height="1992" alt="CleanShot 2026-04-03 at 14 28
58@2x"
src="https://github.com/user-attachments/assets/4c91d7ad-2604-4531-a78e-dedf41632fa5"
/>
If you have access to the Braintrust dashboard, you can also verify
whether logs are produced or not in the Assistant project there.
Closes AI-570
Closes AI-569
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Tracks organization DPA signing and detects EU-region projects
* Assistant tracing now follows a combined compliance policy (HIPAA
addon, DPA, project sensitivity, region)
* Added helpers to fetch org and project AI details
* **Documentation**
* Expanded API docs with additional examples and clarified parameter
descriptions
* Added response schemas for subscription preview and document status
* **Tests**
* Added/updated tests covering DPA/region behavior and tracing policy
enforcement
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
We're exploring support for newer models like
[gpt-5.4-nano](https://openai.com/index/introducing-gpt-5-4-mini-and-nano/)
in Assistant. This model doesn't support the `'minimal'` reasoning
effort level we use for gpt-5-mini which leads to vague errors.
<img width="595" height="263" alt="CleanShot 2026-03-18 at 17 13 05@2x"
src="https://github.com/user-attachments/assets/cf7c2370-322d-4a8a-be55-23e680db0aa0"
/>
Also, we've [previously
discussed](https://supabase.slack.com/archives/C0161K73J1J/p1771544464850199?thread_ts=1771493920.775699&cid=C0161K73J1J)
that reasoning adds unnecessary latency to otherwise simple AI
completion endpoints like `title-v2`. We want more control of reasoning
level independent of model/endpoint.
This PR aims to solve both problems by:
- making reasoning effort configurable on a per-request basis
- adding compile-time guardrails to prevent selecting an incompatible
reasoning level for models
- adding a `DEFAULT_COMPLETION_MODEL` with minimal reasoning that we can
update with newer models that support disabling reasoning (independent
of Assistant chat model reasoning)
Other improvements to our model config logic:
- Fixes bug in `onboarding/design.ts` and `assistant.eval.ts` where
`providerOptions` was being dropped
- `getModel()` now returns a bundled `modelParams` object (spread into
AI SDK calls) so `providerOptions` can't be accidentally omitted (this
[has happened
before](https://supabase.slack.com/archives/C0161K73J1J/p1771518443534309?thread_ts=1771493920.775699&cid=C0161K73J1J))
- Introduces an `ASSISTANT_MODELS` registry as a single source of truth
for assistant model config, eliminating hardcoded model IDs across the
codebase
- Aligns free/pro model conditional logic with `assistant.advance_model`
entitlement naming conventions instead of the `isLimited` pattern
- Adds `console.error` logging of Assistant stream errors so we can
interpret reasoning effort compatibility errors in the future (instead
of just opaque "Sorry, I'm having trouble responding right now" card)
- Removes unnecessary type casts and generally making the model config
logic stricter
- Removes pre-existing dead code: `anthropic` provider variant in
`GetModelParams` / `PROVIDERS` registry that was never implemented in
`getModel()`
Now if you try to select an unsupported reasoning level you get a type
error:
<img width="1306" height="320" alt="CleanShot 2026-03-20 at 14 37 24@2x"
src="https://github.com/user-attachments/assets/a6ac234b-5ea5-4d81-8e01-ac4be34a0800"
/>
And if for some reason an invalid reasoning level slips through, you now
get a server-side error surfacing the issue:
<img width="1268" height="204" alt="CleanShot 2026-03-20 at 14 58 14@2x"
src="https://github.com/user-attachments/assets/aadc1b7a-9495-475f-9741-39979bd27cd7"
/>
I've tested gpt-5 and gpt-5-mini are still working on the staging
preview and verified the models were selected properly in Braintrust
logs. Both models are available on my Pro test account, and my Free test
account shows the Pro upgrade CTA.
Closes AI-446
Closes AI-551
`reasoningEffort: 'minimal'` was
[configured](https://github.com/supabase/supabase/blob/d5cc70560d/apps/studio/lib/ai/model.utils.ts#L55-L59)
in the provider registry but `getModel()` returns it as a separate value
that callers must destructure and forward — and 7 of 8 endpoints weren't
doing so. This meant `gpt-5-mini` (a reasoning model) was running at
default reasoning effort for every call.
This PR destructures `providerOptions` from `getModel()` and passes it
to `generateObject`/`generateText` in all affected endpoints.
## Benchmark (local, median of 5 runs)
| Endpoint | Before (s) | After (s) | Speedup |
|----------|-----------|----------|---------|
| title-v2 | 7.0 | 1.9 | 3.7x |
| cron-v2 | 2.3 | 0.9 | 2.6x |
| filter-v1 | 5.8 | 2.2 | 2.6x |
| feedback/classify | 3.5 | 0.9 | 3.9x |
| feedback/rate | 2.9 | 0.9 | 3.2x |
`code/complete` and `policy` also received the fix but aren't
benchmarked here as they require a live DB connection and use multi-step
tool calls (separate latency concern tracked in AI-419).
To test the SQL naming, visit the SQL Editor in sidebar, add some SQL
like:
```sql
create table todos (
id serial primary key,
task text not null,
completed boolean default false
);
```
Right click on the snippet, "Rename" and "Rename with Supabase AI"
Closes AI-443