-
Notifications
You must be signed in to change notification settings - Fork 250
feat: Add MCP elicitation for create project and branch tools #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds user confirmation prompts for database migrations using MCP's elicitation feature. When applying migrations, users will now be presented with the SQL to review and must explicitly confirm before the migration executes.
Key Changes:
- Adds elicitation/create request to prompt users for confirmation before applying migrations
- Passes server instance to database tools to enable elicitation requests
- Maintains backwards compatibility by proceeding without confirmation if elicitation is not supported
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/mcp-server-supabase/src/tools/database-operation-tools.ts | Implements elicitation request for user confirmation with SQL review before migration execution |
| packages/mcp-server-supabase/src/server.ts | Passes server instance to getDatabaseTools to enable elicitation functionality |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }, | ||
| }, | ||
| }, | ||
| // @ts-ignore - elicitation types might not be available |
Copilot
AI
Oct 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using @ts-ignore suppresses all type checking for the next line. Consider using @ts-expect-error instead, which will fail if the error no longer exists, helping track when types become available.
| // @ts-ignore - elicitation types might not be available | |
| // @ts-expect-error - elicitation types might not be available |
|
@mattrossman I've implemented elicitation on |
packages/mcp-server-supabase/src/tools/database-operation-tools.ts
Outdated
Show resolved
Hide resolved
378ec95 to
9d0ff02
Compare
|
@mattrossman Added elicitation request to You can check that the tool VS Code Copilot (Supports Elicitation)
Claude Code (doesn't support elicitation)
|
| export function getAccountTools({ | ||
| account, | ||
| readOnly, | ||
| server, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think this is unused now that it's accessing the server via ToolExecuteContext
| .enum(AWS_REGION_CODES) | ||
| .describe('The region to create the project in.'), | ||
| organization_id: z.string(), | ||
| confirm_cost_id: z |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parameter is what forces the agent to confirm cost prior to running create_project, I think we'd still need this at least for clients who don't support elicitation
- Implemented user confirmation dialog for apply_migration using MCP elicitation protocol - Added graceful fallback for clients that don't support elicitation - Tests pass with fallback behavior in test environment - Maintains backwards compatibility with all MCP clients
ebc5843 to
b739cfe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since elicitations are a major new feature, maybe it'd be best to implement them in just one place first and iterate in future PRs? e.g. this PR could only focus on apply_migration since that is relatively straightforward.
| 'Gets the cost of creating a new project or branch. Never assume organization as costs can be different for each.', | ||
| get_and_confirm_cost: tool({ | ||
| description: async () => { | ||
| const clientCapabilities = server?.getClientCapabilities(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getClientCapabilities() will not be reliable in our stateless http setup. Capabilities are sent on the init message, which will be lost on future messages. @mattrossman is capturing this in the session ID JWT though - do you have have thoughts on how we can inject this back into the server instance every request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SDK lets us populate it via ServerOptions in the server constructor as a fallback if no "initialize" message was received for the instance. That populates ._capabilities which is read in getClientCapabilities()
I figure we'd expose a capabilities option in our createMcpServer / createSupabaseMcpServer functions to forward to those server options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I'm wrong, but isn't server capabilities different from client capabilities? IIUC ServerOptions allows you to set server capabilities that are advertised to the client but not vice versa (_capabilities vs _clientCapabilities)
| get_cost: tool({ | ||
| description: | ||
| 'Gets the cost of creating a new project or branch. Never assume organization as costs can be different for each.', | ||
| get_and_confirm_cost: tool({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was originally thinking:
- If elicitations are supported, hide
get_costandconfirm_costtools, and run the elicitation directly oncreate_projectandcreate_branch - If elicitations are not supported, keep both
get_costandconfirm_costas is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In practice having the elicitation in create_project felt odd to me because you have to approve a create_project tool call before knowing how much the project will cost or that a safety net will follow (Slack context).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattrossman pointed out that users might get confused and might even panic when they see create_project or create_branch running by the user without checking and confirming the cost (even hough that an elicitation request will prompt before creating the project/branch). I do agree with Matt on this because most users will be prompt to accept running create_project or create_branch
| const result = await server.request( | ||
| { | ||
| method: 'elicitation/create', | ||
| params: { | ||
| message: `You are about to apply migration "${name}" to project ${project_id}. This will modify your database schema.\n\nPlease review the SQL:\n\n${query}\n\nDo you want to proceed?`, | ||
| requestedSchema: { | ||
| type: 'object', | ||
| properties: { | ||
| confirm: { | ||
| type: 'boolean', | ||
| title: 'Confirm Migration', | ||
| description: | ||
| 'I have reviewed the SQL and approve this migration', | ||
| }, | ||
| }, | ||
| required: ['confirm'], | ||
| }, | ||
| }, | ||
| }, | ||
| ElicitResultSchema | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to be careful about code flow with elicitations on stateless HTTP. Stateless HTTP is simulating bidirectional communication via requests and responses, but each new request has a brand new state so we need to make sure our mental model matches this in our implementations.
IIUC, elicitations are sent back via HTTP response? If yes, the result of the elicitation will be sent as a brand new request to the server and will never land back at this point in the code flow. Perhaps the best way to confirm this is to develop/test against a remote MCP server instead of stdio.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment suggests elicitations don't work with stateless :/
I'd think it run both requests in parallel (the outer tool call and the inner elicitation) but I guess keeping the tool call long-running w/o streaming isn't great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, looks like a blocker. From what I can piece together from the spec, server initiated requests need to come from the stateful SSE GET route (which we don't implement). The spec does say that POST responses can include server initiated requests, but only when responding with an SSE stream which always has to end with a server response anyways. I could be missing something but to me this means the only way to implement this is via SSE GET route + complex communication between multiple requests.
|
Tested in Cursor and Claude Code, the flow feels good in both. |


Summary
Implements MCP elicitation for the
apply_migrationtool to request user confirmation before applying database migrations.Implementation
Uses a try-catch pattern to gracefully fallback when clients don't support elicitation:
Client Support
Currently supported: VS Code Copilot, Cursor, Postman, VT Code, fast-agent, mcp-use, MCPJam
Not yet supported: Claude Desktop, Claude.ai, GitHub Copilot coding agent
Related
AI-142: Explore MCP Elicitations