We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Purv123/Remidiation-MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""Finite State Machine for scenario execution."""
import time
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Dict, List, Optional
from ..models.scenario import Scenario
class State(Enum):
"""Scenario execution states."""
INIT = "INIT"
PRECHECK = "PRECHECK"
FAULT_INJECT = "FAULT_INJECT"
STABILIZE = "STABILIZE"
ASSISTANT_RCA = "ASSISTANT_RCA"
EVAL_RCA = "EVAL_RCA"
ASSISTANT_REMEDY = "ASSISTANT_REMEDY"
EVAL_REMEDY = "EVAL_REMEDY"
EXECUTE_REMEDY = "EXECUTE_REMEDY"
VERIFY = "VERIFY"
PASS = "PASS"
FAIL = "FAIL"
CLEANUP = "CLEANUP"
@dataclass
class StepResult:
"""Result of a single execution step."""
state: State
success: bool
message: str
score: Optional[float] = None
artifacts: Dict[str, str] = field(default_factory=dict)
metadata: Dict[str, Any] = field(default_factory=dict)
timestamp: float = field(default_factory=time.time)
@dataclass
class ScenarioContext:
"""Execution context for a scenario run."""
run_id: str
scenario: Scenario
bindings: Dict[str, str]
# Execution state
current_state: State = State.INIT
start_time: float = field(default_factory=time.time)
end_time: Optional[float] = None
# Results tracking
step_results: List[StepResult] = field(default_factory=list)
final_state: Optional[State] = None
# Remediation tracking
fault_id: Optional[str] = None
thread_id: Optional[str] = None
interrupt_id: Optional[str] = None
rca_response: Optional[str] = None
remedy_response: Optional[str] = None
def add_result(self, result: StepResult) -> None:
"""Add a step result to context."""
self.step_results.append(result)
self.current_state = result.state
def set_final_state(self, state: State) -> None:
"""Set the final state and end time."""
self.final_state = state
self.end_time = time.time()
@property
def duration(self) -> float:
"""Get execution duration in seconds."""
end = self.end_time or time.time()
return end - self.start_time
@property
def passed(self) -> bool:
"""Check if scenario passed."""
return self.final_state == State.PASS
def to_dict(self) -> Dict[str, Any]:
"""Convert context to dictionary."""
return {
"run_id": self.run_id,
"scenario_id": self.scenario.meta.id,
"start_time": self.start_time,
"end_time": self.end_time,
"duration": self.duration,
"current_state": self.current_state.value,
"final_state": self.final_state.value if self.final_state else None,
"passed": self.passed,
"step_results": [
{
"state": r.state.value,
"success": r.success,
"message": r.message,
"score": r.score,
"timestamp": r.timestamp,
}
for r in self.step_results
],
}
@dataclass
class ScenarioResult:
"""Final result of scenario execution."""
run_id: str
scenario_id: str
passed: bool
final_state: State
duration: float
step_results: List[StepResult]
artifacts: Dict[str, str] = field(default_factory=dict)
message: str = ""
@classmethod
def from_context(cls, context: ScenarioContext) -> "ScenarioResult":
"""Create result from context."""
# Collect all artifacts
artifacts = {}
for step in context.step_results:
artifacts.update(step.artifacts)
return cls(
run_id=context.run_id,
scenario_id=context.scenario.meta.id,
passed=context.passed,
final_state=context.final_state or context.current_state,
duration=context.duration,
step_results=context.step_results,
artifacts=artifacts,
message=f"Scenario {'PASSED' if context.passed else 'FAILED'}",
)
def to_dict(self) -> Dict[str, Any]:
"""Convert result to dictionary."""
return {
"run_id": self.run_id,
"scenario_id": self.scenario_id,
"passed": self.passed,
"final_state": self.final_state.value,
"duration": self.duration,
"message": self.message,
"artifacts": self.artifacts,
"step_results": [
{
"state": r.state.value,
"success": r.success,
"message": r.message,
"score": r.score,
"timestamp": r.timestamp,
}
for r in self.step_results
],
}