chart data loading

This commit is contained in:
2026-03-24 21:37:49 -04:00
parent f6bd22a8ef
commit c76887ab92
65 changed files with 6350 additions and 713 deletions

View File

@@ -23,6 +23,23 @@ from mcp.server.stdio import stdio_server
from dexorder import EventPublisher, start_lifecycle_manager, get_lifecycle_manager
from dexorder.events import EventType, UserEvent, DeliverySpec
from dexorder.api.workspace_tools import get_workspace_store
# =============================================================================
# Global Data Directory
# =============================================================================
# Default data directory (relative to working directory for local dev)
DEFAULT_DATA_DIR = Path("data")
# Global data directory - set after config is loaded
DATA_DIR: Path = DEFAULT_DATA_DIR
def get_data_dir() -> Path:
"""Get the global data directory."""
return DATA_DIR
# =============================================================================
@@ -60,8 +77,13 @@ class Config:
self.config_data: dict = {}
self.secrets_data: dict = {}
# Data directory (set after config load)
self.data_dir: Path = DEFAULT_DATA_DIR
def load(self) -> None:
"""Load configuration and secrets from YAML files"""
global DATA_DIR
# Load config.yaml if exists
if self.config_path.exists():
with open(self.config_path) as f:
@@ -78,16 +100,40 @@ class Config:
else:
logging.warning(f"Secrets file not found: {self.secrets_path}")
# Set data directory from config or environment
# Priority: env var > config file > default
data_dir_str = os.getenv("DATA_DIR") or self.config_data.get("data_dir")
if data_dir_str:
self.data_dir = Path(data_dir_str)
else:
self.data_dir = DEFAULT_DATA_DIR
# Update global DATA_DIR
DATA_DIR = self.data_dir
# Ensure data directory exists
self.data_dir.mkdir(parents=True, exist_ok=True)
logging.info(f"Data directory: {self.data_dir}")
@property
def workspace_dir(self) -> Path:
"""Workspace directory under DATA_DIR."""
return self.data_dir / "workspace"
# =============================================================================
# MCP Server Setup
# =============================================================================
def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server:
"""Create MCP server with minimal hello world resource"""
"""Create MCP server with resources and workspace tools"""
server = Server(config.mcp_server_name)
# Initialize workspace store
workspace_store = get_workspace_store(config.workspace_dir)
logging.info(f"Workspace store initialized at {config.workspace_dir}")
@server.list_resources()
async def list_resources():
"""List available resources"""
@@ -122,7 +168,89 @@ def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server
else:
raise ValueError(f"Unknown resource: {uri}")
logging.info(f"MCP server '{config.mcp_server_name}' created")
@server.list_tools()
async def list_tools():
"""List available tools including workspace tools"""
return [
{
"name": "workspace_read",
"description": "Read a workspace store from persistent storage",
"inputSchema": {
"type": "object",
"properties": {
"store_name": {
"type": "string",
"description": "Name of the store (e.g., 'chartStore', 'userPreferences')"
}
},
"required": ["store_name"]
}
},
{
"name": "workspace_write",
"description": "Write a workspace store to persistent storage",
"inputSchema": {
"type": "object",
"properties": {
"store_name": {
"type": "string",
"description": "Name of the store"
},
"data": {
"description": "Data to write"
}
},
"required": ["store_name", "data"]
}
},
{
"name": "workspace_patch",
"description": "Apply JSON patch operations to a workspace store",
"inputSchema": {
"type": "object",
"properties": {
"store_name": {
"type": "string",
"description": "Name of the store"
},
"patch": {
"type": "array",
"description": "JSON Patch operations (RFC 6902)",
"items": {
"type": "object",
"properties": {
"op": {"type": "string", "enum": ["add", "remove", "replace", "move", "copy", "test"]},
"path": {"type": "string"},
"value": {}
},
"required": ["op", "path"]
}
}
},
"required": ["store_name", "patch"]
}
}
]
@server.call_tool()
async def handle_tool_call(name: str, arguments: dict):
"""Handle tool calls including workspace tools"""
if name == "workspace_read":
return workspace_store.read(arguments.get("store_name", ""))
elif name == "workspace_write":
return workspace_store.write(
arguments.get("store_name", ""),
arguments.get("data")
)
elif name == "workspace_patch":
return workspace_store.patch(
arguments.get("store_name", ""),
arguments.get("patch", [])
)
else:
raise ValueError(f"Unknown tool: {name}")
logging.info(f"MCP server '{config.mcp_server_name}' created with workspace tools")
return server