chart data loading
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user