diff --git a/.env.example b/.env.example index 4861345..9cde796 100644 --- a/.env.example +++ b/.env.example @@ -85,7 +85,7 @@ FEATURE_SPLASH_SCREEN_ENABLED=false # Startup splash screen for displaying poli # Useful for testing or managing multiple configurations. ############################################# # SPLASH_CONFIG_FILE=splash-config.json # Splash screen configuration file name -# MCP_CONFIG_FILE=mcp.json # MCP servers configuration file name +# MCP_CONFIG_FILE=mcp.json # MCP servers configuration file name # LLM_CONFIG_FILE=llmconfig.yml # LLM models configuration file name # HELP_CONFIG_FILE=help-config.json # Help page configuration file name @@ -133,4 +133,9 @@ USE_MOCK_S3=true # S3_USE_SSL=false -SECURITY_CSP_VALUE="default-src 'self'; img-src 'self' data: blob:; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'; frame-src 'self' blob: data:; frame-ancestors 'self'" +# Content Security Policy (CSP) configuration +# IMPORTANT: To allow external URLs in iframes (for MCP tools that use iframe display), +# add the URLs to the frame-src directive. Example: +# SECURITY_CSP_VALUE="... frame-src 'self' blob: data: https://example.com https://dashboard.example.com; ..." +# HERE the www.sandia.gov is added as an allowed iframe source. +SECURITY_CSP_VALUE="default-src 'self'; img-src 'self' data: blob:; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'; frame-src 'self' blob: data: https://www.sandia.gov; frame-ancestors 'self'" diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2869fc8..eb145a6 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -36,8 +36,9 @@ frontend/ React 19 + Vite + Tailwind; state via contexts (Chat/WS/Marketplace) ## MCP + RAG conventions - MCP servers live in mcp.json (tools/prompts) and mcp-rag.json (RAG-only inventory). Fields: groups, transport|type, url|command/cwd, compliance_level. - Transport detection order: explicit transport → command (stdio) → URL protocol (http/sse) → type fallback. -- Tool names exposed to LLM are fully-qualified: server_toolName. “canvas_canvas” is a pseudo-tool always available. +- Tool names exposed to LLM are fully-qualified: server_toolName. "canvas_canvas" is a pseudo-tool always available. - RAG over MCP tools expected: rag_discover_resources, rag_get_raw_results, optional rag_get_synthesized_results. RAG resources and servers may include complianceLevel. +- When testing or developing MCP-related features, example configurations can be found in config/mcp-example-configs/ with individual mcp-{servername}.json files for testing individual servers. ## Compliance levels (explicit allowlist) - Definitions in config/(overrides|defaults)/compliance-levels.json. core/compliance.py loads, normalizes aliases, and enforces allowed_with. @@ -72,4 +73,4 @@ Common pitfalls: “uv not found” → install uv; frontend not loading → npm # Style -No emojis please \ No newline at end of file +No emojis please diff --git a/CLAUDE.md b/CLAUDE.md index 3608881..33d27e4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -256,6 +256,8 @@ MCP servers defined in `config/defaults/mcp.json`. The backend: 3. Exposes tools to LLM via `ToolManagerProtocol` 4. Supports group-based access control +When testing or developing MCP-related features, example configurations can be found in config/mcp-example-configs/ with individual mcp-{servername}.json files for testing individual servers. + ### Agent Modes Three agent loop strategies implement different reasoning patterns: - **ReAct** (`backend/application/chat/agent/react_loop.py`): Reason-Act-Observe cycle, good for tool-heavy tasks with structured reasoning diff --git a/GEMINI.md b/GEMINI.md index 45380c4..9934910 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -58,8 +58,10 @@ python main.py # NEVER use uvicorn --reload (causes problems) - **No Emojis**: No emojis should ever be added in this repo. - **Linting**: Run `ruff check backend/` for Python and `npm run lint` for the frontend before committing. +When testing or developing MCP-related features, example configurations can be found in config/mcp-example-configs/ with individual mcp-{servername}.json files for testing individual servers. -Also read. + +Also read. /workspaces/atlas-ui-3/.github/copilot-instructions.md -and CLAUDE.md \ No newline at end of file +and CLAUDE.md diff --git a/backend/application/chat/utilities/file_utils.py b/backend/application/chat/utilities/file_utils.py index 001455e..ca89e17 100644 --- a/backend/application/chat/utilities/file_utils.py +++ b/backend/application/chat/utilities/file_utils.py @@ -84,29 +84,40 @@ async def process_tool_artifacts( ) -> Dict[str, Any]: """ Process v2 MCP artifacts produced by a tool and return updated session context. - + Pure function that handles tool files without side effects on input context. """ - if not tool_result.artifacts or not file_manager: - return session_context + # Check if there's an iframe display configuration (no artifacts needed) + has_iframe_display = ( + tool_result.display_config and + isinstance(tool_result.display_config, dict) and + tool_result.display_config.get("type") == "iframe" and + tool_result.display_config.get("url") + ) - user_email = session_context.get("user_email") - if not user_email: + # Early return only if no artifacts AND no iframe display, or no file_manager + if (not tool_result.artifacts and not has_iframe_display) or not file_manager: return session_context # Work with a copy to avoid mutations updated_context = dict(session_context) - - # Process v2 artifacts - updated_context = await ingest_v2_artifacts( - session_context=updated_context, - tool_result=tool_result, - user_email=user_email, - file_manager=file_manager, - update_callback=update_callback - ) + + # Process v2 artifacts (only if we have artifacts) + if tool_result.artifacts: + user_email = session_context.get("user_email") + if not user_email: + return session_context + + updated_context = await ingest_v2_artifacts( + session_context=updated_context, + tool_result=tool_result, + user_email=user_email, + file_manager=file_manager, + update_callback=update_callback + ) # Handle canvas file notifications with v2 display config + # This handles both artifact-based displays and iframe-only displays await notify_canvas_files_v2( session_context=updated_context, tool_result=tool_result, @@ -368,17 +379,47 @@ async def notify_canvas_files_v2( ) -> None: """ Send v2 canvas files notification with display configuration. - + Pure function with no side effects on session context. """ - if not update_callback or not tool_result.artifacts: + if not update_callback: return - + + # Check if there's an iframe display configuration (no artifacts needed) + has_iframe_display = ( + tool_result.display_config and + isinstance(tool_result.display_config, dict) and + tool_result.display_config.get("type") == "iframe" and + tool_result.display_config.get("url") + ) + + # If no artifacts and no iframe display, nothing to show + if not tool_result.artifacts and not has_iframe_display: + return + try: # Get uploaded file references from session context uploaded_refs = session_context.get("files", {}) artifact_names = [artifact.get("name") for artifact in tool_result.artifacts if artifact.get("name")] - + + # Handle iframe-only display (no artifacts) + if has_iframe_display and not artifact_names: + canvas_update = { + "type": "intermediate_update", + "update_type": "canvas_files", + "data": { + "files": [], + "display": tool_result.display_config + } + } + logger.info( + "Emitting canvas_files event for iframe display: url=%s, title=%s", + tool_result.display_config.get("url"), + tool_result.display_config.get("title", "Embedded Content"), + ) + await update_callback(canvas_update) + return + if uploaded_refs and artifact_names: canvas_files = [] for fname in artifact_names: diff --git a/backend/mcp/ui-demo/main.py b/backend/mcp/ui-demo/main.py index 77fba12..506606b 100644 --- a/backend/mcp/ui-demo/main.py +++ b/backend/mcp/ui-demo/main.py @@ -31,64 +31,64 @@ def load_template(template_name: str) -> str: with open(template_path, "r") as f: return f.read() -@mcp.tool -def create_button_demo() -> Dict[str, Any]: - """ - Generate interactive HTML demonstrations showcasing advanced UI customization and dynamic interface capabilities. - - This UI prototyping tool creates sophisticated interactive demonstrations: - - **Interactive UI Components:** - - Custom HTML button interfaces with advanced styling - - Dynamic interaction patterns and user feedback systems - - Professional design templates with modern aesthetics - - Responsive layouts optimized for different screen sizes - - **UI Customization Features:** - - Advanced CSS styling with modern design patterns - - Interactive JavaScript functionality for user engagement - - Professional color schemes and typography - - Accessibility-compliant interface elements - - **Demonstration Capabilities:** - - Real-time UI modification examples - - Interactive component behavior showcases - - Design pattern implementation demonstrations - - User experience optimization examples - - **Technical Implementation:** - - Clean HTML5 structure with semantic elements - - Modern CSS3 styling with flexbox and grid layouts - - Vanilla JavaScript for cross-browser compatibility - - Base64 encoding for seamless artifact delivery - - **Use Cases:** - - UI design prototyping and concept validation - - Client demonstration and stakeholder presentations - - Design system documentation and examples - - Interactive tutorial and training materials - - A/B testing interface variations - - User experience research and testing - - **Professional Features:** - - Production-ready code quality and structure - - Cross-browser compatibility and standards compliance - - Performance-optimized implementation - - Maintainable and extensible code architecture - - **Integration Capabilities:** - - Canvas viewer integration for immediate preview - - Downloadable HTML for offline use and sharing - - Framework-agnostic implementation - - Easy customization and extension - - Returns: - Dictionary containing: - - results: Demo creation summary and success confirmation - - artifacts: Interactive HTML demonstration as downloadable content - - display: Optimized canvas viewer configuration for immediate preview - - Interactive elements ready for user testing and evaluation - Or error message if HTML generation or template loading fails +@mcp.tool +def create_button_demo() -> Dict[str, Any]: + """ + Generate interactive HTML demonstrations showcasing advanced UI customization and dynamic interface capabilities. + + This UI prototyping tool creates sophisticated interactive demonstrations: + + **Interactive UI Components:** + - Custom HTML button interfaces with advanced styling + - Dynamic interaction patterns and user feedback systems + - Professional design templates with modern aesthetics + - Responsive layouts optimized for different screen sizes + + **UI Customization Features:** + - Advanced CSS styling with modern design patterns + - Interactive JavaScript functionality for user engagement + - Professional color schemes and typography + - Accessibility-compliant interface elements + + **Demonstration Capabilities:** + - Real-time UI modification examples + - Interactive component behavior showcases + - Design pattern implementation demonstrations + - User experience optimization examples + + **Technical Implementation:** + - Clean HTML5 structure with semantic elements + - Modern CSS3 styling with flexbox and grid layouts + - Vanilla JavaScript for cross-browser compatibility + - Base64 encoding for seamless artifact delivery + + **Use Cases:** + - UI design prototyping and concept validation + - Client demonstration and stakeholder presentations + - Design system documentation and examples + - Interactive tutorial and training materials + - A/B testing interface variations + - User experience research and testing + + **Professional Features:** + - Production-ready code quality and structure + - Cross-browser compatibility and standards compliance + - Performance-optimized implementation + - Maintainable and extensible code architecture + + **Integration Capabilities:** + - Canvas viewer integration for immediate preview + - Downloadable HTML for offline use and sharing + - Framework-agnostic implementation + - Easy customization and extension + + Returns: + Dictionary containing: + - results: Demo creation summary and success confirmation + - artifacts: Interactive HTML demonstration as downloadable content + - display: Optimized canvas viewer configuration for immediate preview + - Interactive elements ready for user testing and evaluation + Or error message if HTML generation or template loading fails """ # Load the HTML template html_content = load_template("button_demo.html") @@ -255,5 +255,129 @@ def get_image() -> Dict[str, Any]: } } +@mcp.tool +def create_iframe_demo() -> Dict[str, Any]: + """ + Create a demo showing how to embed external content using iframes. + + This demonstrates the v2 MCP iframe capability for embedding interactive + external content like dashboards, visualizations, or web applications. + + IMPORTANT - CSP Configuration Required: + To display external URLs in iframes, the SECURITY_CSP_VALUE environment + variable must include the iframe URL in the frame-src directive. + + Example for https://www.sandia.gov/: + SECURITY_CSP_VALUE="... frame-src 'self' blob: data: https://www.sandia.gov/; ..." + + Without proper CSP configuration, the browser will block the iframe. + + Returns: + Dictionary with iframe display configuration + """ + return { + "results": { + "content": "Iframe demo created! An external webpage will be displayed in the canvas panel.", + "iframe_url": "https://www.sandia.gov/" + }, + "artifacts": [], + "display": { + "open_canvas": True, + "type": "iframe", + "url": "https://www.sandia.gov/", + "title": "Example Website", + "sandbox": "allow-scripts allow-same-origin", + "mode": "replace" + } + } + +@mcp.tool +def create_html_with_iframe() -> Dict[str, Any]: + """ + Create an HTML artifact that includes an embedded iframe. + + This demonstrates how MCP tools can return HTML content with embedded + iframes that will be properly rendered in the canvas panel. + + IMPORTANT - CSP Configuration Required: + To display external URLs in iframes, the SECURITY_CSP_VALUE environment + variable must include the iframe URL in the frame-src directive. + + Example for https://www.sandia.gov/: + SECURITY_CSP_VALUE="... frame-src 'self' blob: data: https://www.sandia.gov/; ..." + + Without proper CSP configuration, the browser will block the iframe. + + Returns: + Dictionary with HTML artifact containing an iframe + """ + html_content = """ + +
+ + + +This HTML artifact includes an embedded iframe showing external content:
+