Files
dss/dss-claude-plugin/core/mcp_extensions.py
Bruno Sarlo 4de266de61
Some checks failed
DSS Project Analysis / dss-context-update (push) Has been cancelled
Revert "chore: Remove dss-claude-plugin directory"
This reverts commit 72cb7319f5.
2025-12-10 15:54:39 -03:00

114 lines
3.8 KiB
Python

"""
MCP Extensions for Context Awareness
Implements the Factory Pattern to wrap existing tools with context
and defines 5 new tools for the Context Compiler.
"""
from typing import Any, Dict, List, Callable
import functools
import json
import os
from .compiler import ContextCompiler
# Singleton compiler instance
COMPILER = ContextCompiler(skins_dir=os.path.join(os.path.dirname(__file__), "skins"))
# --- FACTORY PATTERN: Context Wrapper ---
def with_context(default_manifest_path: str = None):
"""
Decorator that injects the compiled context into the tool's arguments.
Use this to upgrade existing 'token extractor' tools to be 'context aware'.
The manifest path is extracted from kwargs['manifest_path'] if present,
otherwise falls back to the default_manifest_path provided at decoration time.
"""
def decorator(func: Callable):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 1. Get manifest path (runtime kwarg or decorator default)
manifest_path = kwargs.get('manifest_path', default_manifest_path)
if not manifest_path:
raise ValueError("No manifest_path provided to context-aware tool")
# 2. Compile Context
context = COMPILER.compile(manifest_path)
# 3. Inject into kwargs
kwargs['dss_context'] = context
# 4. Execute Tool
return func(*args, **kwargs)
return wrapper
return decorator
# --- 5 NEW MCP TOOLS ---
def get_active_context(manifest_path: str, debug: bool = False, force_refresh: bool = False) -> str:
"""
[Tool 1] Returns the fully resolved JSON context for the project.
Set debug=True to see provenance (which layer defined which token).
Set force_refresh=True to bypass cache (for long-running servers).
"""
context = COMPILER.compile(manifest_path, debug=debug, force_refresh=force_refresh)
return json.dumps(context, indent=2)
def resolve_token(manifest_path: str, token_path: str, force_refresh: bool = False) -> str:
"""
[Tool 2] Resolves a specific token value (e.g. 'colors.primary')
through the cascade.
Set force_refresh=True to bypass cache (for long-running servers).
"""
context = COMPILER.compile(manifest_path, force_refresh=force_refresh)
keys = token_path.split('.')
current = context.get("tokens", {})
for k in keys:
if isinstance(current, dict) and k in current:
current = current[k]
else:
return f"Token not found: {token_path}"
return str(current)
def validate_manifest(manifest_path: str) -> str:
"""
[Tool 3] Validates the ds.config.json against the schema.
"""
# In a full implementation, we would use 'jsonschema' library here.
# For now, we perform a basic structural check via the Compiler's loader.
try:
COMPILER.compile(manifest_path)
return "Valid: Project manifest builds successfully."
except Exception as e:
return f"Invalid: {str(e)}"
def list_skins() -> str:
"""
[Tool 4] Lists all available skins in the registry.
"""
skins_path = COMPILER.skins_dir
if not skins_path.exists():
return "No skins directory found."
skins = [f.stem for f in skins_path.glob("*.json")]
return json.dumps(skins)
def get_compiler_status() -> str:
"""
[Tool 5] Returns the health and configuration of the Context Compiler.
"""
status = {
"status": "active",
"skins_directory": str(COMPILER.skins_dir),
"cached_skins": list(COMPILER.cache.keys()),
"safe_boot_ready": True
}
return json.dumps(status, indent=2)
# Instructions for Main Server File:
# 1. Import these tools
# 2. Register them with the MCP server instance
# 3. Apply @with_context wrapper to legacy tools if dynamic context is needed