git_paw/mcp/tools/
session.rs1use std::collections::BTreeMap;
9
10use rmcp::handler::server::wrapper::Json;
11use rmcp::{schemars, tool, tool_router};
12use serde::Serialize;
13
14use crate::mcp::query;
15use crate::mcp::server::GitPawMcpServer;
16
17#[derive(Serialize, schemars::JsonSchema)]
19pub struct SessionStatusResponse {
20 pub session: Option<query::session::SessionSnapshot>,
22}
23
24#[derive(Serialize, schemars::JsonSchema)]
26pub struct SessionSummary {
27 pub name: String,
29 pub status: String,
31 pub agent_count: usize,
33 pub agents_by_status: BTreeMap<String, usize>,
35}
36
37#[derive(Serialize, schemars::JsonSchema)]
39pub struct SummaryResponse {
40 pub summary: Option<SessionSummary>,
42}
43
44#[derive(Serialize, schemars::JsonSchema)]
46pub struct LearningsResponse {
47 pub sections: Vec<query::learnings::LearningSection>,
49}
50
51#[tool_router(router = session_router, vis = "pub(crate)")]
52impl GitPawMcpServer {
53 #[tool(
55 description = "Return the active session snapshot: name, mode, status, agent count, broker \
56 URL, pause state, and per-agent status (live from the broker when reachable). \
57 { \"session\": null } when no session is active."
58 )]
59 pub(crate) fn get_session_status(&self) -> Json<SessionStatusResponse> {
60 Json(SessionStatusResponse {
61 session: query::session::session_status(&self.ctx),
62 })
63 }
64
65 #[tool(
67 description = "Return a compact summary of the current session (name, status, agent count, \
68 and per-status agent counts), or { \"summary\": null } when none is active."
69 )]
70 pub(crate) fn get_session_summary(&self) -> Json<SummaryResponse> {
71 let summary = query::session::session_status(&self.ctx).map(|s| {
72 let mut by_status: BTreeMap<String, usize> = BTreeMap::new();
73 for a in &s.agents {
74 if !a.status.is_empty() {
75 *by_status.entry(a.status.clone()).or_default() += 1;
76 }
77 }
78 SessionSummary {
79 name: s.name,
80 status: s.status,
81 agent_count: s.agent_count,
82 agents_by_status: by_status,
83 }
84 });
85 Json(SummaryResponse { summary })
86 }
87
88 #[tool(
90 description = "Parse .git-paw/session-learnings.md into structured sections, each with a \
91 category and its entries. Returns the canonical sections as empty arrays \
92 when no learnings file exists."
93 )]
94 pub(crate) fn get_learnings(&self) -> Json<LearningsResponse> {
95 Json(LearningsResponse {
96 sections: query::learnings::learnings(&self.ctx),
97 })
98 }
99}