quash-mcp 0.2.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.
Potentially problematic release.
This version of quash-mcp might be problematic. Click here for more details.
- quash_mcp/__init__.py +1 -0
- quash_mcp/__main__.py +10 -0
- quash_mcp/backend_client.py +203 -0
- quash_mcp/server.py +399 -0
- quash_mcp/state.py +137 -0
- quash_mcp/tools/__init__.py +9 -0
- quash_mcp/tools/build.py +739 -0
- quash_mcp/tools/build_old.py +185 -0
- quash_mcp/tools/configure.py +140 -0
- quash_mcp/tools/connect.py +153 -0
- quash_mcp/tools/execute.py +177 -0
- quash_mcp/tools/runsuite.py +209 -0
- quash_mcp/tools/usage.py +31 -0
- quash_mcp-0.2.0.dist-info/METADATA +271 -0
- quash_mcp-0.2.0.dist-info/RECORD +17 -0
- quash_mcp-0.2.0.dist-info/WHEEL +4 -0
- quash_mcp-0.2.0.dist-info/entry_points.txt +2 -0
quash_mcp/state.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session state manager for Quash MCP Server.
|
|
3
|
+
Maintains configuration and device state throughout a session.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional, Dict, Any
|
|
10
|
+
from dataclasses import dataclass, field, asdict
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class SessionState:
|
|
15
|
+
"""Manages session state for the MCP server."""
|
|
16
|
+
|
|
17
|
+
# Device information
|
|
18
|
+
device_serial: Optional[str] = None
|
|
19
|
+
device_info: Optional[Dict[str, str]] = None
|
|
20
|
+
portal_ready: bool = False
|
|
21
|
+
|
|
22
|
+
# Agent configuration
|
|
23
|
+
config: Dict[str, Any] = field(default_factory=lambda: {
|
|
24
|
+
"model": "anthropic/claude-sonnet-4",
|
|
25
|
+
"temperature": 0.2,
|
|
26
|
+
"max_steps": 15,
|
|
27
|
+
"vision": False,
|
|
28
|
+
"reasoning": False,
|
|
29
|
+
"reflection": False,
|
|
30
|
+
"debug": False,
|
|
31
|
+
"api_key": None # Stores quash_api_key
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
# Latest suite execution
|
|
35
|
+
latest_suite: Optional[Dict[str, Any]] = None
|
|
36
|
+
|
|
37
|
+
# Storage path for persistent config
|
|
38
|
+
_config_path: Path = field(default_factory=lambda: Path.home() / ".mahoraga" / "config.json")
|
|
39
|
+
|
|
40
|
+
def __post_init__(self):
|
|
41
|
+
"""Load saved configuration after initialization"""
|
|
42
|
+
self._load_config()
|
|
43
|
+
|
|
44
|
+
def reset(self):
|
|
45
|
+
"""Reset all state to defaults."""
|
|
46
|
+
self.device_serial = None
|
|
47
|
+
self.device_info = None
|
|
48
|
+
self.portal_ready = False
|
|
49
|
+
self.config = {
|
|
50
|
+
"model": "anthropic/claude-sonnet-4",
|
|
51
|
+
"temperature": 0.2,
|
|
52
|
+
"max_steps": 15,
|
|
53
|
+
"vision": False,
|
|
54
|
+
"reasoning": False,
|
|
55
|
+
"reflection": False,
|
|
56
|
+
"debug": False,
|
|
57
|
+
"api_key": None
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
def is_device_connected(self) -> bool:
|
|
61
|
+
"""Check if a device is connected."""
|
|
62
|
+
return self.device_serial is not None
|
|
63
|
+
|
|
64
|
+
def is_configured(self) -> bool:
|
|
65
|
+
"""Check if configuration is set (at minimum mahoraga API key)."""
|
|
66
|
+
return self.config.get("api_key") is not None
|
|
67
|
+
|
|
68
|
+
def is_ready(self) -> bool:
|
|
69
|
+
"""Check if system is ready for execution."""
|
|
70
|
+
return self.is_device_connected() and self.is_configured()
|
|
71
|
+
|
|
72
|
+
def update_config(self, **kwargs):
|
|
73
|
+
"""Update configuration with provided parameters."""
|
|
74
|
+
for key, value in kwargs.items():
|
|
75
|
+
if key in self.config:
|
|
76
|
+
self.config[key] = value
|
|
77
|
+
# Save to disk after updating
|
|
78
|
+
self._save_config()
|
|
79
|
+
|
|
80
|
+
def get_config_summary(self) -> Dict[str, Any]:
|
|
81
|
+
"""Get configuration summary without exposing sensitive data."""
|
|
82
|
+
summary = self.config.copy()
|
|
83
|
+
if summary.get("api_key"):
|
|
84
|
+
summary["api_key_set"] = True
|
|
85
|
+
summary["api_key"] = "***"
|
|
86
|
+
else:
|
|
87
|
+
summary["api_key_set"] = False
|
|
88
|
+
summary["api_key"] = None
|
|
89
|
+
return summary
|
|
90
|
+
|
|
91
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
92
|
+
"""Convert state to dictionary."""
|
|
93
|
+
return {
|
|
94
|
+
"device_serial": self.device_serial,
|
|
95
|
+
"device_info": self.device_info,
|
|
96
|
+
"portal_ready": self.portal_ready,
|
|
97
|
+
"config": self.get_config_summary()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
def _load_config(self):
|
|
101
|
+
"""Load configuration from disk if it exists"""
|
|
102
|
+
try:
|
|
103
|
+
if self._config_path.exists():
|
|
104
|
+
with open(self._config_path, 'r') as f:
|
|
105
|
+
saved_config = json.load(f)
|
|
106
|
+
# Only load mahoraga API key (other settings are session-specific)
|
|
107
|
+
if "api_key" in saved_config and saved_config["api_key"]:
|
|
108
|
+
self.config["api_key"] = saved_config["api_key"]
|
|
109
|
+
except Exception:
|
|
110
|
+
pass # Fail silently if can't load
|
|
111
|
+
|
|
112
|
+
def _save_config(self):
|
|
113
|
+
"""Save configuration to disk"""
|
|
114
|
+
try:
|
|
115
|
+
self._config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
116
|
+
# Only save mahoraga API key (other settings are session-specific)
|
|
117
|
+
config_to_save = {
|
|
118
|
+
"api_key": self.config.get("api_key")
|
|
119
|
+
}
|
|
120
|
+
with open(self._config_path, 'w') as f:
|
|
121
|
+
json.dump(config_to_save, f)
|
|
122
|
+
except Exception:
|
|
123
|
+
pass # Fail silently if can't save
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# Global session state instance
|
|
127
|
+
_session_state = SessionState()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def get_state() -> SessionState:
|
|
131
|
+
"""Get the global session state instance."""
|
|
132
|
+
return _session_state
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def reset_state():
|
|
136
|
+
"""Reset the global session state."""
|
|
137
|
+
_session_state.reset()
|