atlas-chat 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- atlas/__init__.py +40 -0
- atlas/application/__init__.py +7 -0
- atlas/application/chat/__init__.py +7 -0
- atlas/application/chat/agent/__init__.py +10 -0
- atlas/application/chat/agent/act_loop.py +179 -0
- atlas/application/chat/agent/factory.py +142 -0
- atlas/application/chat/agent/protocols.py +46 -0
- atlas/application/chat/agent/react_loop.py +338 -0
- atlas/application/chat/agent/think_act_loop.py +171 -0
- atlas/application/chat/approval_manager.py +151 -0
- atlas/application/chat/elicitation_manager.py +191 -0
- atlas/application/chat/events/__init__.py +1 -0
- atlas/application/chat/events/agent_event_relay.py +112 -0
- atlas/application/chat/modes/__init__.py +1 -0
- atlas/application/chat/modes/agent.py +125 -0
- atlas/application/chat/modes/plain.py +74 -0
- atlas/application/chat/modes/rag.py +81 -0
- atlas/application/chat/modes/tools.py +179 -0
- atlas/application/chat/orchestrator.py +213 -0
- atlas/application/chat/policies/__init__.py +1 -0
- atlas/application/chat/policies/tool_authorization.py +99 -0
- atlas/application/chat/preprocessors/__init__.py +1 -0
- atlas/application/chat/preprocessors/message_builder.py +92 -0
- atlas/application/chat/preprocessors/prompt_override_service.py +104 -0
- atlas/application/chat/service.py +454 -0
- atlas/application/chat/utilities/__init__.py +6 -0
- atlas/application/chat/utilities/error_handler.py +367 -0
- atlas/application/chat/utilities/event_notifier.py +546 -0
- atlas/application/chat/utilities/file_processor.py +613 -0
- atlas/application/chat/utilities/tool_executor.py +789 -0
- atlas/atlas_chat_cli.py +347 -0
- atlas/atlas_client.py +238 -0
- atlas/core/__init__.py +0 -0
- atlas/core/auth.py +205 -0
- atlas/core/authorization_manager.py +27 -0
- atlas/core/capabilities.py +123 -0
- atlas/core/compliance.py +215 -0
- atlas/core/domain_whitelist.py +147 -0
- atlas/core/domain_whitelist_middleware.py +82 -0
- atlas/core/http_client.py +28 -0
- atlas/core/log_sanitizer.py +102 -0
- atlas/core/metrics_logger.py +59 -0
- atlas/core/middleware.py +131 -0
- atlas/core/otel_config.py +242 -0
- atlas/core/prompt_risk.py +200 -0
- atlas/core/rate_limit.py +0 -0
- atlas/core/rate_limit_middleware.py +64 -0
- atlas/core/security_headers_middleware.py +51 -0
- atlas/domain/__init__.py +37 -0
- atlas/domain/chat/__init__.py +1 -0
- atlas/domain/chat/dtos.py +85 -0
- atlas/domain/errors.py +96 -0
- atlas/domain/messages/__init__.py +12 -0
- atlas/domain/messages/models.py +160 -0
- atlas/domain/rag_mcp_service.py +664 -0
- atlas/domain/sessions/__init__.py +7 -0
- atlas/domain/sessions/models.py +36 -0
- atlas/domain/unified_rag_service.py +371 -0
- atlas/infrastructure/__init__.py +10 -0
- atlas/infrastructure/app_factory.py +135 -0
- atlas/infrastructure/events/__init__.py +1 -0
- atlas/infrastructure/events/cli_event_publisher.py +140 -0
- atlas/infrastructure/events/websocket_publisher.py +140 -0
- atlas/infrastructure/sessions/in_memory_repository.py +56 -0
- atlas/infrastructure/transport/__init__.py +7 -0
- atlas/infrastructure/transport/websocket_connection_adapter.py +33 -0
- atlas/init_cli.py +226 -0
- atlas/interfaces/__init__.py +15 -0
- atlas/interfaces/events.py +134 -0
- atlas/interfaces/llm.py +54 -0
- atlas/interfaces/rag.py +40 -0
- atlas/interfaces/sessions.py +75 -0
- atlas/interfaces/tools.py +57 -0
- atlas/interfaces/transport.py +24 -0
- atlas/main.py +564 -0
- atlas/mcp/api_key_demo/README.md +76 -0
- atlas/mcp/api_key_demo/main.py +172 -0
- atlas/mcp/api_key_demo/run.sh +56 -0
- atlas/mcp/basictable/main.py +147 -0
- atlas/mcp/calculator/main.py +149 -0
- atlas/mcp/code-executor/execution_engine.py +98 -0
- atlas/mcp/code-executor/execution_environment.py +95 -0
- atlas/mcp/code-executor/main.py +528 -0
- atlas/mcp/code-executor/result_processing.py +276 -0
- atlas/mcp/code-executor/script_generation.py +195 -0
- atlas/mcp/code-executor/security_checker.py +140 -0
- atlas/mcp/corporate_cars/main.py +437 -0
- atlas/mcp/csv_reporter/main.py +545 -0
- atlas/mcp/duckduckgo/main.py +182 -0
- atlas/mcp/elicitation_demo/README.md +171 -0
- atlas/mcp/elicitation_demo/main.py +262 -0
- atlas/mcp/env-demo/README.md +158 -0
- atlas/mcp/env-demo/main.py +199 -0
- atlas/mcp/file_size_test/main.py +284 -0
- atlas/mcp/filesystem/main.py +348 -0
- atlas/mcp/image_demo/main.py +113 -0
- atlas/mcp/image_demo/requirements.txt +4 -0
- atlas/mcp/logging_demo/README.md +72 -0
- atlas/mcp/logging_demo/main.py +103 -0
- atlas/mcp/many_tools_demo/main.py +50 -0
- atlas/mcp/order_database/__init__.py +0 -0
- atlas/mcp/order_database/main.py +369 -0
- atlas/mcp/order_database/signal_data.csv +1001 -0
- atlas/mcp/pdfbasic/main.py +394 -0
- atlas/mcp/pptx_generator/main.py +760 -0
- atlas/mcp/pptx_generator/requirements.txt +13 -0
- atlas/mcp/pptx_generator/run_test.sh +1 -0
- atlas/mcp/pptx_generator/test_pptx_generator_security.py +169 -0
- atlas/mcp/progress_demo/main.py +167 -0
- atlas/mcp/progress_updates_demo/QUICKSTART.md +273 -0
- atlas/mcp/progress_updates_demo/README.md +120 -0
- atlas/mcp/progress_updates_demo/main.py +497 -0
- atlas/mcp/prompts/main.py +222 -0
- atlas/mcp/public_demo/main.py +189 -0
- atlas/mcp/sampling_demo/README.md +169 -0
- atlas/mcp/sampling_demo/main.py +234 -0
- atlas/mcp/thinking/main.py +77 -0
- atlas/mcp/tool_planner/main.py +240 -0
- atlas/mcp/ui-demo/badmesh.png +0 -0
- atlas/mcp/ui-demo/main.py +383 -0
- atlas/mcp/ui-demo/templates/button_demo.html +32 -0
- atlas/mcp/ui-demo/templates/data_visualization.html +32 -0
- atlas/mcp/ui-demo/templates/form_demo.html +28 -0
- atlas/mcp/username-override-demo/README.md +320 -0
- atlas/mcp/username-override-demo/main.py +308 -0
- atlas/modules/__init__.py +0 -0
- atlas/modules/config/__init__.py +34 -0
- atlas/modules/config/cli.py +231 -0
- atlas/modules/config/config_manager.py +1096 -0
- atlas/modules/file_storage/__init__.py +22 -0
- atlas/modules/file_storage/cli.py +330 -0
- atlas/modules/file_storage/content_extractor.py +290 -0
- atlas/modules/file_storage/manager.py +295 -0
- atlas/modules/file_storage/mock_s3_client.py +402 -0
- atlas/modules/file_storage/s3_client.py +417 -0
- atlas/modules/llm/__init__.py +19 -0
- atlas/modules/llm/caller.py +287 -0
- atlas/modules/llm/litellm_caller.py +675 -0
- atlas/modules/llm/models.py +19 -0
- atlas/modules/mcp_tools/__init__.py +17 -0
- atlas/modules/mcp_tools/client.py +2123 -0
- atlas/modules/mcp_tools/token_storage.py +556 -0
- atlas/modules/prompts/prompt_provider.py +130 -0
- atlas/modules/rag/__init__.py +24 -0
- atlas/modules/rag/atlas_rag_client.py +336 -0
- atlas/modules/rag/client.py +129 -0
- atlas/routes/admin_routes.py +865 -0
- atlas/routes/config_routes.py +484 -0
- atlas/routes/feedback_routes.py +361 -0
- atlas/routes/files_routes.py +274 -0
- atlas/routes/health_routes.py +40 -0
- atlas/routes/mcp_auth_routes.py +223 -0
- atlas/server_cli.py +164 -0
- atlas/tests/conftest.py +20 -0
- atlas/tests/integration/test_mcp_auth_integration.py +152 -0
- atlas/tests/manual_test_sampling.py +87 -0
- atlas/tests/modules/mcp_tools/test_client_auth.py +226 -0
- atlas/tests/modules/mcp_tools/test_client_env.py +191 -0
- atlas/tests/test_admin_mcp_server_management_routes.py +141 -0
- atlas/tests/test_agent_roa.py +135 -0
- atlas/tests/test_app_factory_smoke.py +47 -0
- atlas/tests/test_approval_manager.py +439 -0
- atlas/tests/test_atlas_client.py +188 -0
- atlas/tests/test_atlas_rag_client.py +447 -0
- atlas/tests/test_atlas_rag_integration.py +224 -0
- atlas/tests/test_attach_file_flow.py +287 -0
- atlas/tests/test_auth_utils.py +165 -0
- atlas/tests/test_backend_public_url.py +185 -0
- atlas/tests/test_banner_logging.py +287 -0
- atlas/tests/test_capability_tokens_and_injection.py +203 -0
- atlas/tests/test_compliance_level.py +54 -0
- atlas/tests/test_compliance_manager.py +253 -0
- atlas/tests/test_config_manager.py +617 -0
- atlas/tests/test_config_manager_paths.py +12 -0
- atlas/tests/test_core_auth.py +18 -0
- atlas/tests/test_core_utils.py +190 -0
- atlas/tests/test_docker_env_sync.py +202 -0
- atlas/tests/test_domain_errors.py +329 -0
- atlas/tests/test_domain_whitelist.py +359 -0
- atlas/tests/test_elicitation_manager.py +408 -0
- atlas/tests/test_elicitation_routing.py +296 -0
- atlas/tests/test_env_demo_server.py +88 -0
- atlas/tests/test_error_classification.py +113 -0
- atlas/tests/test_error_flow_integration.py +116 -0
- atlas/tests/test_feedback_routes.py +333 -0
- atlas/tests/test_file_content_extraction.py +1134 -0
- atlas/tests/test_file_extraction_routes.py +158 -0
- atlas/tests/test_file_library.py +107 -0
- atlas/tests/test_file_manager_unit.py +18 -0
- atlas/tests/test_health_route.py +49 -0
- atlas/tests/test_http_client_stub.py +8 -0
- atlas/tests/test_imports_smoke.py +30 -0
- atlas/tests/test_interfaces_llm_response.py +9 -0
- atlas/tests/test_issue_access_denied_fix.py +136 -0
- atlas/tests/test_llm_env_expansion.py +836 -0
- atlas/tests/test_log_level_sensitive_data.py +285 -0
- atlas/tests/test_mcp_auth_routes.py +341 -0
- atlas/tests/test_mcp_client_auth.py +331 -0
- atlas/tests/test_mcp_data_injection.py +270 -0
- atlas/tests/test_mcp_get_authorized_servers.py +95 -0
- atlas/tests/test_mcp_hot_reload.py +512 -0
- atlas/tests/test_mcp_image_content.py +424 -0
- atlas/tests/test_mcp_logging.py +172 -0
- atlas/tests/test_mcp_progress_updates.py +313 -0
- atlas/tests/test_mcp_prompt_override_system_prompt.py +102 -0
- atlas/tests/test_mcp_prompts_server.py +39 -0
- atlas/tests/test_mcp_tool_result_parsing.py +296 -0
- atlas/tests/test_metrics_logger.py +56 -0
- atlas/tests/test_middleware_auth.py +379 -0
- atlas/tests/test_prompt_risk_and_acl.py +141 -0
- atlas/tests/test_rag_mcp_aggregator.py +204 -0
- atlas/tests/test_rag_mcp_service.py +224 -0
- atlas/tests/test_rate_limit_middleware.py +45 -0
- atlas/tests/test_routes_config_smoke.py +60 -0
- atlas/tests/test_routes_files_download_token.py +41 -0
- atlas/tests/test_routes_files_health.py +18 -0
- atlas/tests/test_runtime_imports.py +53 -0
- atlas/tests/test_sampling_integration.py +482 -0
- atlas/tests/test_security_admin_routes.py +61 -0
- atlas/tests/test_security_capability_tokens.py +65 -0
- atlas/tests/test_security_file_stats_scope.py +21 -0
- atlas/tests/test_security_header_injection.py +191 -0
- atlas/tests/test_security_headers_and_filename.py +63 -0
- atlas/tests/test_shared_session_repository.py +101 -0
- atlas/tests/test_system_prompt_loading.py +181 -0
- atlas/tests/test_token_storage.py +505 -0
- atlas/tests/test_tool_approval_config.py +93 -0
- atlas/tests/test_tool_approval_utils.py +356 -0
- atlas/tests/test_tool_authorization_group_filtering.py +223 -0
- atlas/tests/test_tool_details_in_config.py +108 -0
- atlas/tests/test_tool_planner.py +300 -0
- atlas/tests/test_unified_rag_service.py +398 -0
- atlas/tests/test_username_override_in_approval.py +258 -0
- atlas/tests/test_websocket_auth_header.py +168 -0
- atlas/version.py +6 -0
- atlas_chat-0.1.0.data/data/.env.example +253 -0
- atlas_chat-0.1.0.data/data/config/defaults/compliance-levels.json +44 -0
- atlas_chat-0.1.0.data/data/config/defaults/domain-whitelist.json +123 -0
- atlas_chat-0.1.0.data/data/config/defaults/file-extractors.json +74 -0
- atlas_chat-0.1.0.data/data/config/defaults/help-config.json +198 -0
- atlas_chat-0.1.0.data/data/config/defaults/llmconfig-buggy.yml +11 -0
- atlas_chat-0.1.0.data/data/config/defaults/llmconfig.yml +19 -0
- atlas_chat-0.1.0.data/data/config/defaults/mcp.json +138 -0
- atlas_chat-0.1.0.data/data/config/defaults/rag-sources.json +17 -0
- atlas_chat-0.1.0.data/data/config/defaults/splash-config.json +16 -0
- atlas_chat-0.1.0.dist-info/METADATA +236 -0
- atlas_chat-0.1.0.dist-info/RECORD +250 -0
- atlas_chat-0.1.0.dist-info/WHEEL +5 -0
- atlas_chat-0.1.0.dist-info/entry_points.txt +4 -0
- atlas_chat-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Progress Updates Demo MCP Server
|
|
2
|
+
|
|
3
|
+
This MCP server demonstrates the enhanced progress reporting capabilities that allow MCP servers to send viewable updates to the frontend during tool execution.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
This demo shows three types of enhanced progress updates:
|
|
8
|
+
|
|
9
|
+
1. **Canvas Updates**: Display HTML visualizations in the canvas panel during execution
|
|
10
|
+
2. **System Messages**: Send rich messages that appear in chat history
|
|
11
|
+
3. **Progress Artifacts**: Share file artifacts progressively as they're generated
|
|
12
|
+
|
|
13
|
+
## Tools
|
|
14
|
+
|
|
15
|
+
### `task_with_canvas_updates`
|
|
16
|
+
|
|
17
|
+
Demonstrates sending HTML progress visualizations to the canvas during execution.
|
|
18
|
+
|
|
19
|
+
**Parameters:**
|
|
20
|
+
- `task_name` (str): Name of the task (default: "demo")
|
|
21
|
+
- `steps` (int): Number of steps to process (default: 5)
|
|
22
|
+
- `interval_seconds` (int): Delay between steps (default: 2)
|
|
23
|
+
|
|
24
|
+
### `task_with_system_messages`
|
|
25
|
+
|
|
26
|
+
Demonstrates sending rich system messages to chat history during execution.
|
|
27
|
+
|
|
28
|
+
**Parameters:**
|
|
29
|
+
- `task_name` (str): Name of the analysis task (default: "analysis")
|
|
30
|
+
- `stages` (int): Number of stages to process (default: 4)
|
|
31
|
+
- `interval_seconds` (int): Delay between stages (default: 2)
|
|
32
|
+
|
|
33
|
+
### `task_with_artifacts`
|
|
34
|
+
|
|
35
|
+
Demonstrates sending file artifacts progressively during execution.
|
|
36
|
+
|
|
37
|
+
**Parameters:**
|
|
38
|
+
- `task_name` (str): Name of the processing task (default: "data_processing")
|
|
39
|
+
- `files_to_generate` (int): Number of intermediate files (default: 3)
|
|
40
|
+
- `interval_seconds` (int): Delay between file generation (default: 2)
|
|
41
|
+
|
|
42
|
+
## How It Works
|
|
43
|
+
|
|
44
|
+
MCP servers can send structured progress updates by encoding JSON data in the progress message field with the prefix `"MCP_UPDATE:"`.
|
|
45
|
+
|
|
46
|
+
### Supported Update Types
|
|
47
|
+
|
|
48
|
+
#### 1. Canvas Update
|
|
49
|
+
```python
|
|
50
|
+
update_payload = {
|
|
51
|
+
"type": "canvas_update",
|
|
52
|
+
"content": "<html>...</html>", # HTML content to display
|
|
53
|
+
"progress_message": "Processing..." # Optional progress text
|
|
54
|
+
}
|
|
55
|
+
await ctx.report_progress(
|
|
56
|
+
progress=step,
|
|
57
|
+
total=total_steps,
|
|
58
|
+
message=f"MCP_UPDATE:{json.dumps(update_payload)}"
|
|
59
|
+
)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### 2. System Message
|
|
63
|
+
```python
|
|
64
|
+
update_payload = {
|
|
65
|
+
"type": "system_message",
|
|
66
|
+
"message": "Data validation complete!",
|
|
67
|
+
"subtype": "success", # or "info", "warning", "error"
|
|
68
|
+
"progress_message": "Validating data..."
|
|
69
|
+
}
|
|
70
|
+
await ctx.report_progress(
|
|
71
|
+
progress=step,
|
|
72
|
+
total=total_steps,
|
|
73
|
+
message=f"MCP_UPDATE:{json.dumps(update_payload)}"
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### 3. Artifacts
|
|
78
|
+
```python
|
|
79
|
+
update_payload = {
|
|
80
|
+
"type": "artifacts",
|
|
81
|
+
"artifacts": [
|
|
82
|
+
{
|
|
83
|
+
"name": "result.html",
|
|
84
|
+
"b64": base64_encoded_content,
|
|
85
|
+
"mime": "text/html",
|
|
86
|
+
"size": content_size,
|
|
87
|
+
"description": "Intermediate result",
|
|
88
|
+
"viewer": "html"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"display": {
|
|
92
|
+
"open_canvas": True,
|
|
93
|
+
"primary_file": "result.html",
|
|
94
|
+
"mode": "replace"
|
|
95
|
+
},
|
|
96
|
+
"progress_message": "Generated result..."
|
|
97
|
+
}
|
|
98
|
+
await ctx.report_progress(
|
|
99
|
+
progress=step,
|
|
100
|
+
total=total_steps,
|
|
101
|
+
message=f"MCP_UPDATE:{json.dumps(update_payload)}"
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Usage
|
|
106
|
+
|
|
107
|
+
Try these example prompts:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
Show me a task with canvas updates
|
|
111
|
+
Run task_with_system_messages
|
|
112
|
+
Generate artifacts progressively
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Benefits
|
|
116
|
+
|
|
117
|
+
- **Better UX**: Users see real-time progress with visual feedback
|
|
118
|
+
- **Reduced perceived latency**: Long-running tasks feel more responsive
|
|
119
|
+
- **More informative**: Rich context about what's happening at each stage
|
|
120
|
+
- **Flexible**: Can display any HTML content, images, or file artifacts
|
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Progress Updates Demo MCP Server using FastMCP.
|
|
4
|
+
|
|
5
|
+
This server demonstrates the enhanced progress reporting capabilities
|
|
6
|
+
that allow MCP servers to send viewable updates to the frontend during
|
|
7
|
+
tool execution, including:
|
|
8
|
+
- Canvas updates (plots, HTML, images)
|
|
9
|
+
- Rich system messages
|
|
10
|
+
- Progress artifacts
|
|
11
|
+
|
|
12
|
+
To use these features from an MCP server, send special formatted messages
|
|
13
|
+
via ctx.report_progress() with the message field containing:
|
|
14
|
+
"MCP_UPDATE:{json_payload}"
|
|
15
|
+
|
|
16
|
+
Supported update types:
|
|
17
|
+
- canvas_update: Display HTML/images in canvas during execution
|
|
18
|
+
- system_message: Add rich messages to chat history
|
|
19
|
+
- artifacts: Send file artifacts during execution
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import asyncio
|
|
25
|
+
import base64
|
|
26
|
+
import json
|
|
27
|
+
from typing import Any, Dict
|
|
28
|
+
|
|
29
|
+
from fastmcp import Context, FastMCP
|
|
30
|
+
|
|
31
|
+
# Initialize the MCP server
|
|
32
|
+
mcp = FastMCP("Progress Updates Demo")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def create_progress_html(step: int, total: int, message: str) -> str:
|
|
36
|
+
"""Create an HTML progress visualization."""
|
|
37
|
+
percentage = int((step / total) * 100)
|
|
38
|
+
return f"""
|
|
39
|
+
<!DOCTYPE html>
|
|
40
|
+
<html>
|
|
41
|
+
<head>
|
|
42
|
+
<style>
|
|
43
|
+
body {{
|
|
44
|
+
font-family: Arial, sans-serif;
|
|
45
|
+
padding: 20px;
|
|
46
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
47
|
+
color: white;
|
|
48
|
+
}}
|
|
49
|
+
.progress-container {{
|
|
50
|
+
background: rgba(255, 255, 255, 0.2);
|
|
51
|
+
border-radius: 10px;
|
|
52
|
+
padding: 20px;
|
|
53
|
+
backdrop-filter: blur(10px);
|
|
54
|
+
}}
|
|
55
|
+
.progress-bar {{
|
|
56
|
+
width: 100%;
|
|
57
|
+
height: 30px;
|
|
58
|
+
background: rgba(255, 255, 255, 0.3);
|
|
59
|
+
border-radius: 15px;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
margin: 10px 0;
|
|
62
|
+
}}
|
|
63
|
+
.progress-fill {{
|
|
64
|
+
height: 100%;
|
|
65
|
+
background: linear-gradient(90deg, #4CAF50, #8BC34A);
|
|
66
|
+
width: {percentage}%;
|
|
67
|
+
transition: width 0.3s ease;
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
color: white;
|
|
72
|
+
font-weight: bold;
|
|
73
|
+
}}
|
|
74
|
+
h1 {{
|
|
75
|
+
margin: 0 0 10px 0;
|
|
76
|
+
}}
|
|
77
|
+
.step-info {{
|
|
78
|
+
font-size: 18px;
|
|
79
|
+
margin: 10px 0;
|
|
80
|
+
}}
|
|
81
|
+
</style>
|
|
82
|
+
</head>
|
|
83
|
+
<body>
|
|
84
|
+
<div class="progress-container">
|
|
85
|
+
<h1>Task Progress</h1>
|
|
86
|
+
<div class="step-info">Step {step} of {total}</div>
|
|
87
|
+
<div class="progress-bar">
|
|
88
|
+
<div class="progress-fill">{percentage}%</div>
|
|
89
|
+
</div>
|
|
90
|
+
<p>{message}</p>
|
|
91
|
+
</div>
|
|
92
|
+
</body>
|
|
93
|
+
</html>
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def create_chart_html(data: Dict[str, int]) -> str:
|
|
98
|
+
"""Create a simple bar chart HTML."""
|
|
99
|
+
max_value = max(data.values()) if data else 1
|
|
100
|
+
bars = ""
|
|
101
|
+
for label, value in data.items():
|
|
102
|
+
percentage = int((value / max_value) * 100)
|
|
103
|
+
bars += f"""
|
|
104
|
+
<div class="bar-container">
|
|
105
|
+
<div class="bar-label">{label}</div>
|
|
106
|
+
<div class="bar-wrapper">
|
|
107
|
+
<div class="bar-fill" style="width: {percentage}%">
|
|
108
|
+
<span class="bar-value">{value}</span>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
return f"""
|
|
115
|
+
<!DOCTYPE html>
|
|
116
|
+
<html>
|
|
117
|
+
<head>
|
|
118
|
+
<style>
|
|
119
|
+
body {{
|
|
120
|
+
font-family: Arial, sans-serif;
|
|
121
|
+
padding: 20px;
|
|
122
|
+
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
|
123
|
+
}}
|
|
124
|
+
.chart-container {{
|
|
125
|
+
background: white;
|
|
126
|
+
border-radius: 10px;
|
|
127
|
+
padding: 20px;
|
|
128
|
+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
129
|
+
}}
|
|
130
|
+
h2 {{
|
|
131
|
+
color: #333;
|
|
132
|
+
margin-top: 0;
|
|
133
|
+
}}
|
|
134
|
+
.bar-container {{
|
|
135
|
+
margin: 15px 0;
|
|
136
|
+
}}
|
|
137
|
+
.bar-label {{
|
|
138
|
+
font-weight: bold;
|
|
139
|
+
margin-bottom: 5px;
|
|
140
|
+
color: #555;
|
|
141
|
+
}}
|
|
142
|
+
.bar-wrapper {{
|
|
143
|
+
background: #e0e0e0;
|
|
144
|
+
border-radius: 5px;
|
|
145
|
+
overflow: hidden;
|
|
146
|
+
height: 30px;
|
|
147
|
+
}}
|
|
148
|
+
.bar-fill {{
|
|
149
|
+
background: linear-gradient(90deg, #667eea, #764ba2);
|
|
150
|
+
height: 100%;
|
|
151
|
+
display: flex;
|
|
152
|
+
align-items: center;
|
|
153
|
+
justify-content: flex-end;
|
|
154
|
+
padding-right: 10px;
|
|
155
|
+
transition: width 0.5s ease;
|
|
156
|
+
}}
|
|
157
|
+
.bar-value {{
|
|
158
|
+
color: white;
|
|
159
|
+
font-weight: bold;
|
|
160
|
+
}}
|
|
161
|
+
</style>
|
|
162
|
+
</head>
|
|
163
|
+
<body>
|
|
164
|
+
<div class="chart-container">
|
|
165
|
+
<h2>Processing Results</h2>
|
|
166
|
+
{bars}
|
|
167
|
+
</div>
|
|
168
|
+
</body>
|
|
169
|
+
</html>
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@mcp.tool
|
|
174
|
+
async def task_with_canvas_updates(
|
|
175
|
+
task_name: str = "demo",
|
|
176
|
+
steps: int = 5,
|
|
177
|
+
interval_seconds: int = 2,
|
|
178
|
+
ctx: Context | None = None,
|
|
179
|
+
) -> Dict[str, Any]:
|
|
180
|
+
"""
|
|
181
|
+
Execute a long-running task with visual progress updates in the canvas.
|
|
182
|
+
|
|
183
|
+
This tool demonstrates how MCP servers can send canvas updates during
|
|
184
|
+
execution, allowing users to see real-time visual progress indicators.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
task_name: Name of the task to execute
|
|
188
|
+
steps: Number of steps to process (default: 5)
|
|
189
|
+
interval_seconds: Delay between steps (default: 2)
|
|
190
|
+
ctx: MCP context for progress reporting
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Task completion summary with final results
|
|
194
|
+
"""
|
|
195
|
+
total = max(1, int(steps))
|
|
196
|
+
interval = max(1, int(interval_seconds))
|
|
197
|
+
|
|
198
|
+
# Initial progress
|
|
199
|
+
if ctx:
|
|
200
|
+
await ctx.report_progress(
|
|
201
|
+
progress=0,
|
|
202
|
+
total=total,
|
|
203
|
+
message=f"Starting {task_name}..."
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# Process each step and send visual updates as artifacts
|
|
207
|
+
for step in range(1, total + 1):
|
|
208
|
+
await asyncio.sleep(interval)
|
|
209
|
+
|
|
210
|
+
# Create progress visualization HTML
|
|
211
|
+
html_content = create_progress_html(step, total, f"Processing {task_name}: Step {step}")
|
|
212
|
+
|
|
213
|
+
# Send progress HTML as an artifact so it uses the HTML viewer
|
|
214
|
+
if ctx:
|
|
215
|
+
artifact_html = base64.b64encode(html_content.encode("utf-8")).decode("utf-8")
|
|
216
|
+
update_payload = {
|
|
217
|
+
"type": "artifacts",
|
|
218
|
+
"artifacts": [
|
|
219
|
+
{
|
|
220
|
+
"name": f"progress_step_{step}.html",
|
|
221
|
+
"b64": artifact_html,
|
|
222
|
+
"mime": "text/html",
|
|
223
|
+
"size": len(html_content),
|
|
224
|
+
"description": f"Progress for {task_name} step {step}/{total}",
|
|
225
|
+
"viewer": "html",
|
|
226
|
+
}
|
|
227
|
+
],
|
|
228
|
+
"display": {
|
|
229
|
+
"open_canvas": True,
|
|
230
|
+
"primary_file": f"progress_step_{step}.html",
|
|
231
|
+
"mode": "replace",
|
|
232
|
+
},
|
|
233
|
+
"progress_message": f"{task_name}: Step {step}/{total}",
|
|
234
|
+
}
|
|
235
|
+
await ctx.report_progress(
|
|
236
|
+
progress=step,
|
|
237
|
+
total=total,
|
|
238
|
+
message=f"MCP_UPDATE:{json.dumps(update_payload)}",
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Final result with chart
|
|
242
|
+
result_data = {
|
|
243
|
+
"Items Processed": total * 10,
|
|
244
|
+
"Errors Found": 2,
|
|
245
|
+
"Warnings": 5,
|
|
246
|
+
"Success Rate": 95
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
chart_html = create_chart_html(result_data)
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
"results": {
|
|
253
|
+
"task": task_name,
|
|
254
|
+
"status": "completed",
|
|
255
|
+
"steps_completed": total,
|
|
256
|
+
"summary": result_data
|
|
257
|
+
},
|
|
258
|
+
"artifacts": [
|
|
259
|
+
{
|
|
260
|
+
"name": "final_results.html",
|
|
261
|
+
"b64": base64.b64encode(chart_html.encode('utf-8')).decode('utf-8'),
|
|
262
|
+
"mime": "text/html",
|
|
263
|
+
"size": len(chart_html),
|
|
264
|
+
"description": "Final processing results chart",
|
|
265
|
+
"viewer": "html"
|
|
266
|
+
}
|
|
267
|
+
],
|
|
268
|
+
"display": {
|
|
269
|
+
"open_canvas": True,
|
|
270
|
+
"primary_file": "final_results.html",
|
|
271
|
+
"mode": "replace",
|
|
272
|
+
"viewer_hint": "html"
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
@mcp.tool
|
|
278
|
+
async def task_with_system_messages(
|
|
279
|
+
task_name: str = "analysis",
|
|
280
|
+
stages: int = 4,
|
|
281
|
+
interval_seconds: int = 2,
|
|
282
|
+
ctx: Context | None = None,
|
|
283
|
+
) -> Dict[str, Any]:
|
|
284
|
+
"""
|
|
285
|
+
Execute a task with rich system messages displayed in chat history.
|
|
286
|
+
|
|
287
|
+
This tool demonstrates how MCP servers can send rich system messages
|
|
288
|
+
that appear as new items in the chat history during tool execution.
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
task_name: Name of the analysis task
|
|
292
|
+
stages: Number of stages to process (default: 4)
|
|
293
|
+
interval_seconds: Delay between stages (default: 2)
|
|
294
|
+
ctx: MCP context for progress reporting
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
Analysis completion summary
|
|
298
|
+
"""
|
|
299
|
+
stage_names = [
|
|
300
|
+
"Data Collection",
|
|
301
|
+
"Data Validation",
|
|
302
|
+
"Analysis",
|
|
303
|
+
"Report Generation"
|
|
304
|
+
][:stages]
|
|
305
|
+
|
|
306
|
+
total = len(stage_names)
|
|
307
|
+
|
|
308
|
+
# Initial progress
|
|
309
|
+
if ctx:
|
|
310
|
+
await ctx.report_progress(
|
|
311
|
+
progress=0,
|
|
312
|
+
total=total,
|
|
313
|
+
message=f"Starting {task_name}..."
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
# Process each stage and send system messages
|
|
317
|
+
for i, stage in enumerate(stage_names, 1):
|
|
318
|
+
await asyncio.sleep(interval_seconds)
|
|
319
|
+
|
|
320
|
+
# Send system message
|
|
321
|
+
if ctx:
|
|
322
|
+
update_payload = {
|
|
323
|
+
"type": "system_message",
|
|
324
|
+
"message": f"**{stage}** - Stage {i}/{total} completed successfully",
|
|
325
|
+
"subtype": "success",
|
|
326
|
+
"progress_message": f"{task_name}: {stage}"
|
|
327
|
+
}
|
|
328
|
+
await ctx.report_progress(
|
|
329
|
+
progress=i,
|
|
330
|
+
total=total,
|
|
331
|
+
message=f"MCP_UPDATE:{json.dumps(update_payload)}"
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
return {
|
|
335
|
+
"results": {
|
|
336
|
+
"task": task_name,
|
|
337
|
+
"status": "completed",
|
|
338
|
+
"stages_completed": total,
|
|
339
|
+
"completion_message": f"All {total} stages completed successfully"
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@mcp.tool
|
|
345
|
+
async def task_with_artifacts(
|
|
346
|
+
task_name: str = "data_processing",
|
|
347
|
+
files_to_generate: int = 3,
|
|
348
|
+
interval_seconds: int = 2,
|
|
349
|
+
ctx: Context | None = None,
|
|
350
|
+
) -> Dict[str, Any]:
|
|
351
|
+
"""
|
|
352
|
+
Execute a task that generates and displays artifacts progressively.
|
|
353
|
+
|
|
354
|
+
This tool demonstrates how MCP servers can send file artifacts during
|
|
355
|
+
execution, allowing users to see intermediate results as they're generated.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
task_name: Name of the processing task
|
|
359
|
+
files_to_generate: Number of intermediate files to create (default: 3)
|
|
360
|
+
interval_seconds: Delay between file generation (default: 2)
|
|
361
|
+
ctx: MCP context for progress reporting
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
Processing completion summary
|
|
365
|
+
"""
|
|
366
|
+
total = max(1, int(files_to_generate))
|
|
367
|
+
interval = max(1, int(interval_seconds))
|
|
368
|
+
|
|
369
|
+
# Initial progress
|
|
370
|
+
if ctx:
|
|
371
|
+
await ctx.report_progress(
|
|
372
|
+
progress=0,
|
|
373
|
+
total=total,
|
|
374
|
+
message=f"Starting {task_name}..."
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
# Generate intermediate files
|
|
378
|
+
for file_num in range(1, total + 1):
|
|
379
|
+
await asyncio.sleep(interval)
|
|
380
|
+
|
|
381
|
+
# Create intermediate result HTML
|
|
382
|
+
intermediate_html = f"""
|
|
383
|
+
<!DOCTYPE html>
|
|
384
|
+
<html>
|
|
385
|
+
<head>
|
|
386
|
+
<style>
|
|
387
|
+
body {{
|
|
388
|
+
font-family: Arial, sans-serif;
|
|
389
|
+
padding: 20px;
|
|
390
|
+
background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%);
|
|
391
|
+
}}
|
|
392
|
+
.result {{
|
|
393
|
+
background: white;
|
|
394
|
+
border-radius: 10px;
|
|
395
|
+
padding: 20px;
|
|
396
|
+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
397
|
+
}}
|
|
398
|
+
h2 {{ color: #333; margin-top: 0; }}
|
|
399
|
+
.data {{ color: #666; font-size: 18px; }}
|
|
400
|
+
</style>
|
|
401
|
+
</head>
|
|
402
|
+
<body>
|
|
403
|
+
<div class="result">
|
|
404
|
+
<h2>Intermediate Result {file_num}</h2>
|
|
405
|
+
<p class="data">Generated at step {file_num} of {total}</p>
|
|
406
|
+
<p class="data">Processing status: In Progress</p>
|
|
407
|
+
</div>
|
|
408
|
+
</body>
|
|
409
|
+
</html>
|
|
410
|
+
"""
|
|
411
|
+
|
|
412
|
+
# Send artifact via structured progress message
|
|
413
|
+
if ctx:
|
|
414
|
+
artifact_data = {
|
|
415
|
+
"type": "artifacts",
|
|
416
|
+
"artifacts": [
|
|
417
|
+
{
|
|
418
|
+
"name": f"intermediate_result_{file_num}.html",
|
|
419
|
+
"b64": base64.b64encode(intermediate_html.encode('utf-8')).decode('utf-8'),
|
|
420
|
+
"mime": "text/html",
|
|
421
|
+
"size": len(intermediate_html),
|
|
422
|
+
"description": f"Intermediate result {file_num}",
|
|
423
|
+
"viewer": "html"
|
|
424
|
+
}
|
|
425
|
+
],
|
|
426
|
+
"display": {
|
|
427
|
+
"open_canvas": True,
|
|
428
|
+
"primary_file": f"intermediate_result_{file_num}.html",
|
|
429
|
+
"mode": "replace"
|
|
430
|
+
},
|
|
431
|
+
"progress_message": f"Generated file {file_num}/{total}"
|
|
432
|
+
}
|
|
433
|
+
await ctx.report_progress(
|
|
434
|
+
progress=file_num,
|
|
435
|
+
total=total,
|
|
436
|
+
message=f"MCP_UPDATE:{json.dumps(artifact_data)}"
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
# Final result
|
|
440
|
+
final_html = """
|
|
441
|
+
<!DOCTYPE html>
|
|
442
|
+
<html>
|
|
443
|
+
<head>
|
|
444
|
+
<style>
|
|
445
|
+
body {
|
|
446
|
+
font-family: Arial, sans-serif;
|
|
447
|
+
padding: 20px;
|
|
448
|
+
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
|
|
449
|
+
}
|
|
450
|
+
.final-result {
|
|
451
|
+
background: white;
|
|
452
|
+
border-radius: 10px;
|
|
453
|
+
padding: 30px;
|
|
454
|
+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
455
|
+
text-align: center;
|
|
456
|
+
}
|
|
457
|
+
h1 { color: #4CAF50; }
|
|
458
|
+
.success-icon { font-size: 64px; }
|
|
459
|
+
</style>
|
|
460
|
+
</head>
|
|
461
|
+
<body>
|
|
462
|
+
<div class="final-result">
|
|
463
|
+
<div class="success-icon">✓</div>
|
|
464
|
+
<h1>Processing Complete!</h1>
|
|
465
|
+
<p>All files have been generated successfully.</p>
|
|
466
|
+
</div>
|
|
467
|
+
</body>
|
|
468
|
+
</html>
|
|
469
|
+
"""
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
"results": {
|
|
473
|
+
"task": task_name,
|
|
474
|
+
"status": "completed",
|
|
475
|
+
"files_generated": total
|
|
476
|
+
},
|
|
477
|
+
"artifacts": [
|
|
478
|
+
{
|
|
479
|
+
"name": "final_result.html",
|
|
480
|
+
"b64": base64.b64encode(final_html.encode('utf-8')).decode('utf-8'),
|
|
481
|
+
"mime": "text/html",
|
|
482
|
+
"size": len(final_html),
|
|
483
|
+
"description": "Final processing result",
|
|
484
|
+
"viewer": "html"
|
|
485
|
+
}
|
|
486
|
+
],
|
|
487
|
+
"display": {
|
|
488
|
+
"open_canvas": True,
|
|
489
|
+
"primary_file": "final_result.html",
|
|
490
|
+
"mode": "replace",
|
|
491
|
+
"viewer_hint": "html"
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
if __name__ == "__main__":
|
|
497
|
+
mcp.run()
|