elicitDatabaseChoice prompts the user to pick from ambiguous database matches using MCP elicitation. Returns an error if elicitation is unsupported, the user cancels/declines, or the selection is invalid.
(ctx context.Context, req *mcp.CallToolRequest, resolved *resolvedDatabase)
| 201 | // using MCP elicitation. Returns an error if elicitation is unsupported, the user |
| 202 | // cancels/declines, or the selection is invalid. |
| 203 | func (*Server) elicitDatabaseChoice(ctx context.Context, req *mcp.CallToolRequest, resolved *resolvedDatabase) (*resolvedDatabase, error) { |
| 204 | if req == nil || req.Session == nil { |
| 205 | return nil, errors.New("elicitation unsupported: no session") |
| 206 | } |
| 207 | |
| 208 | // Build enum values and a lookup map from display label to resource name. |
| 209 | enumValues := make([]any, 0, len(resolved.candidates)) |
| 210 | resourceByLabel := make(map[string]string, len(resolved.candidates)) |
| 211 | for _, c := range resolved.candidates { |
| 212 | label := fmt.Sprintf("%s (%s, %s)", c.Database, c.Instance, c.Engine) |
| 213 | enumValues = append(enumValues, label) |
| 214 | resourceByLabel[label] = c.Database |
| 215 | } |
| 216 | |
| 217 | result, err := req.Session.Elicit(ctx, &mcp.ElicitParams{ |
| 218 | Mode: "form", |
| 219 | Message: "Multiple databases match. Which one do you want to query?", |
| 220 | RequestedSchema: map[string]any{ |
| 221 | "type": "object", |
| 222 | "properties": map[string]any{ |
| 223 | "database": map[string]any{ |
| 224 | "type": "string", |
| 225 | "enum": enumValues, |
| 226 | "description": "Select the target database", |
| 227 | }, |
| 228 | }, |
| 229 | "required": []string{"database"}, |
| 230 | }, |
| 231 | }) |
| 232 | if err != nil { |
| 233 | return nil, err |
| 234 | } |
| 235 | if result.Action != "accept" { |
| 236 | return nil, errors.Errorf("user %sd database selection", result.Action) |
| 237 | } |
| 238 | |
| 239 | selected, ok := result.Content["database"].(string) |
| 240 | if !ok { |
| 241 | return nil, errors.New("invalid database selection") |
| 242 | } |
| 243 | |
| 244 | resourceName, ok := resourceByLabel[selected] |
| 245 | if !ok { |
| 246 | return nil, errors.Errorf("unknown database selection: %s", selected) |
| 247 | } |
| 248 | |
| 249 | return &resolvedDatabase{ |
| 250 | resourceName: resourceName, |
| 251 | dataSourceID: resolved.dataSourceIDs[resourceName], |
| 252 | engine: resolved.engines[resourceName], |
| 253 | project: resolved.projects[resourceName], |
| 254 | }, nil |
| 255 | } |
| 256 | |
| 257 | // matchExact returns databases whose short name exactly matches the input. |
| 258 | func matchExact(databases []databaseEntry, name string) []databaseEntry { |
no test coverage detected