1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
use libmcp::ReplayContract;
use serde_json::{Value, json};
use crate::mcp::output::with_common_presentation;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum DispatchTarget {
Host,
Worker,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) struct ToolSpec {
pub(crate) name: &'static str,
pub(crate) description: &'static str,
pub(crate) dispatch: DispatchTarget,
pub(crate) replay: ReplayContract,
}
impl ToolSpec {
fn annotation_json(self) -> Value {
json!({
"title": self.name,
"readOnlyHint": true,
"destructiveHint": false,
"phoneOpus": {
"dispatch": match self.dispatch {
DispatchTarget::Host => "host",
DispatchTarget::Worker => "worker",
},
"replayContract": match self.replay {
ReplayContract::Convergent => "convergent",
ReplayContract::ProbeRequired => "probe_required",
ReplayContract::NeverReplay => "never_replay",
},
}
})
}
}
const TOOL_SPECS: &[ToolSpec] = &[
ToolSpec {
name: "consult",
description: "Run a consult against the system Claude Code install using a read-only built-in toolset, optionally resume a prior Claude session by session_id, optionally queue the consult in the background, and return the response or job handle.",
dispatch: DispatchTarget::Worker,
replay: ReplayContract::NeverReplay,
},
ToolSpec {
name: "consult_job",
description: "Read the status of one background consult job by job_id. When the job has finished, the final Claude response or failure is included.",
dispatch: DispatchTarget::Host,
replay: ReplayContract::Convergent,
},
ToolSpec {
name: "consult_jobs",
description: "List recent background consult jobs. Defaults to render=porcelain; use render=json for structured output.",
dispatch: DispatchTarget::Host,
replay: ReplayContract::Convergent,
},
ToolSpec {
name: "health_snapshot",
description: "Read host lifecycle, worker generation, rollout state, and latest fault. Defaults to render=porcelain; use render=json for structured output.",
dispatch: DispatchTarget::Host,
replay: ReplayContract::Convergent,
},
ToolSpec {
name: "telemetry_snapshot",
description: "Read aggregate request and recovery telemetry for this session. Defaults to render=porcelain; use render=json for structured output.",
dispatch: DispatchTarget::Host,
replay: ReplayContract::Convergent,
},
];
pub(crate) fn tool_spec(name: &str) -> Option<ToolSpec> {
TOOL_SPECS.iter().copied().find(|spec| spec.name == name)
}
pub(crate) fn tool_definitions() -> Vec<Value> {
TOOL_SPECS
.iter()
.map(|spec| {
json!({
"name": spec.name,
"description": spec.description,
"inputSchema": tool_schema(spec.name),
"annotations": spec.annotation_json(),
})
})
.collect()
}
fn tool_schema(name: &str) -> Value {
match name {
"consult" => with_common_presentation(json!({
"type": "object",
"properties": {
"prompt": {
"type": "string",
"description": "Prompt to send to Claude Code."
},
"cwd": {
"type": "string",
"description": "Optional working directory for the Claude Code session. Relative paths resolve against the MCP host working directory."
},
"max_turns": {
"type": "integer",
"minimum": 1,
"description": "Optional maximum number of Claude agent turns before stopping."
},
"session_id": {
"type": "string",
"description": "Optional Claude session handle returned by a previous consult call. When set, phone_opus resumes that conversation instead of starting a fresh one."
},
"background": {
"type": "boolean",
"description": "When true, queue the consult as a background job and return immediately with a job handle. The default is false, which keeps consult synchronous."
}
},
"required": ["prompt"]
})),
"consult_job" => with_common_presentation(json!({
"type": "object",
"properties": {
"job_id": {
"type": "string",
"description": "Background consult job handle returned by consult with background=true."
}
},
"required": ["job_id"]
})),
"consult_jobs" => with_common_presentation(json!({
"type": "object",
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"description": "Maximum number of recent background jobs to return. Defaults to 10."
}
}
})),
"health_snapshot" | "telemetry_snapshot" => with_common_presentation(json!({
"type": "object",
"properties": {}
})),
_ => Value::Null,
}
}
|