| 231 | } |
| 232 | |
| 233 | func (s *Server) handleGetSchema(ctx context.Context, req *mcp.CallToolRequest, input SchemaInput) (*mcp.CallToolResult, any, error) { |
| 234 | if input.Database == "" { |
| 235 | return nil, nil, errors.New("database is required") |
| 236 | } |
| 237 | |
| 238 | include, err := resolveIncludeLevel(input) |
| 239 | if err != nil { |
| 240 | return nil, nil, err |
| 241 | } |
| 242 | |
| 243 | resolved, resolveResult := s.resolveSchemaTarget(ctx, req, input) |
| 244 | if resolveResult != nil { |
| 245 | return resolveResult, nil, nil |
| 246 | } |
| 247 | |
| 248 | // On engines that don't expose named schemas (MySQL, TiDB, ClickHouse, etc.), |
| 249 | // drop the schema filter and note the drop. The backend applies `schema == "..."` |
| 250 | // as an exact match, so passing a non-empty hint like "public" on MySQL would |
| 251 | // filter out every table. Results are still returned; the note tells the caller |
| 252 | // why the parameter was ignored. |
| 253 | var warnings []string |
| 254 | schemaHint := input.Schema |
| 255 | if schemaHint != "" && !engineSupportsSchemas(resolved.engine) { |
| 256 | warnings = append(warnings, fmt.Sprintf("schema parameter ignored — %s does not use named schemas", resolved.engine)) |
| 257 | schemaHint = "" |
| 258 | } |
| 259 | |
| 260 | // Fetch metadata with server-side filter + limit. |
| 261 | fetchCtx, fetchCancel := context.WithTimeout(ctx, schemaFetchTimeout) |
| 262 | defer fetchCancel() |
| 263 | |
| 264 | metadata, err := s.fetchMetadata(fetchCtx, resolved.resourceName, buildMetadataFilter(schemaHint, input.Table), limitForInclude(include, input.Table)) |
| 265 | if err != nil { |
| 266 | return formatToolError(err), nil, nil |
| 267 | } |
| 268 | |
| 269 | if input.Table != "" { |
| 270 | result, output := s.renderTableResult(fetchCtx, resolved, input, schemaHint, metadata, include, warnings) |
| 271 | return result, output, nil |
| 272 | } |
| 273 | result, output := renderSchemasResult(resolved, metadata, include, warnings) |
| 274 | return result, output, nil |
| 275 | } |
| 276 | |
| 277 | // resolveIncludeLevel normalizes and validates the `include` parameter. |
| 278 | // When empty, it defaults to "details" if a table was requested and "summary" otherwise. |