|
13 | 13 |
|
14 | 14 | # Global semantic layer instance |
15 | 15 | _layer: SemanticLayer | None = None |
16 | | -_apps_enabled: bool = False |
17 | 16 |
|
18 | 17 |
|
19 | 18 | def initialize_layer( |
@@ -391,7 +390,18 @@ def run_query( |
391 | 390 | } |
392 | 391 |
|
393 | 392 |
|
394 | | -@mcp.tool(structured_output=False, meta={"ui": {"resourceUri": "ui://sidemantic/chart"}}) |
| 393 | +@mcp.tool( |
| 394 | + structured_output=False, |
| 395 | + meta={ |
| 396 | + "ui": { |
| 397 | + "resourceUri": "ui://sidemantic/chart", |
| 398 | + "csp": { |
| 399 | + "connectDomains": [], |
| 400 | + "resourceDomains": [], |
| 401 | + }, |
| 402 | + }, |
| 403 | + }, |
| 404 | +) |
395 | 405 | def create_chart( |
396 | 406 | dimensions: list[str] = [], |
397 | 407 | metrics: list[str] = [], |
@@ -433,7 +443,7 @@ def create_chart( |
433 | 443 | png_base64: Base64-encoded PNG image |
434 | 444 | row_count: Number of data points |
435 | 445 | """ |
436 | | - from sidemantic.charts import chart_to_base64_png, chart_to_vega |
| 446 | + from sidemantic.charts import chart_to_vega |
437 | 447 | from sidemantic.charts import create_chart as make_chart |
438 | 448 |
|
439 | 449 | layer = get_layer() |
@@ -478,25 +488,15 @@ def create_chart( |
478 | 488 | height=height, |
479 | 489 | ) |
480 | 490 |
|
481 | | - # Export to both formats |
| 491 | + # Export Vega spec (rendered interactively by MCP Apps widget) |
482 | 492 | vega_spec = chart_to_vega(chart) |
483 | | - png_base64 = chart_to_base64_png(chart) |
484 | 493 |
|
485 | | - result = { |
| 494 | + return { |
486 | 495 | "sql": sql, |
487 | 496 | "vega_spec": vega_spec, |
488 | | - "png_base64": png_base64, |
489 | 497 | "row_count": len(row_dicts), |
490 | 498 | } |
491 | 499 |
|
492 | | - # When apps mode is enabled, include an interactive UI widget |
493 | | - if _apps_enabled: |
494 | | - from sidemantic.apps import create_chart_resource |
495 | | - |
496 | | - return [result, create_chart_resource(vega_spec)] |
497 | | - |
498 | | - return result |
499 | | - |
500 | 500 |
|
501 | 501 | def _generate_chart_title(dimensions: list[str], metrics: list[str]) -> str: |
502 | 502 | """Generate a descriptive title from query parameters.""" |
@@ -699,7 +699,24 @@ def get_semantic_graph() -> dict[str, Any]: |
699 | 699 | return result |
700 | 700 |
|
701 | 701 |
|
702 | | -# --- MCP Resource: Catalog Metadata --- |
| 702 | +# --- MCP Resources --- |
| 703 | + |
| 704 | + |
| 705 | +@mcp.resource( |
| 706 | + "ui://sidemantic/chart", |
| 707 | + mime_type="text/html;profile=mcp-app", |
| 708 | + meta={ |
| 709 | + "ui": { |
| 710 | + "csp": {"connectDomains": [], "resourceDomains": []}, |
| 711 | + }, |
| 712 | + "mcpui.dev/ui-preferred-frame-size": ["100%", "500px"], |
| 713 | + }, |
| 714 | +) |
| 715 | +def chart_widget_resource() -> str: |
| 716 | + """Interactive Vega-Lite chart widget for MCP Apps-compatible hosts.""" |
| 717 | + from sidemantic.apps import _get_widget_template |
| 718 | + |
| 719 | + return _get_widget_template() |
703 | 720 |
|
704 | 721 |
|
705 | 722 | @mcp.resource("semantic://catalog") |
|
0 commit comments