Skip to main content

dnslib/mcp/
params.rs

1//! MCP parameter DTOs — all tool parameter structs and enums.
2
3use schemars::JsonSchema;
4use serde::Deserialize;
5
6use crate::core::dns::zones::ZoneImportOptions;
7use crate::core::dns::{
8    logs::{LogLevel, LogsOptions},
9    records::{RecordData, RecordSelector},
10};
11
12fn default_true() -> bool {
13    true
14}
15
16// ─── Shared server scope ───────────────────────────────────────────────────
17
18#[derive(Deserialize, JsonSchema)]
19pub struct ServerScopeParams {
20    /// The DNS server ID to run this command against (see dns_list_servers)
21    pub server_id: String,
22}
23
24// ─── Zone params ───────────────────────────────────────────────────────────
25
26#[derive(Deserialize, JsonSchema)]
27pub struct ZoneParams {
28    /// The DNS server ID to run this command against (see dns_list_servers)
29    pub server_id: String,
30    /// The zone name, e.g. "example.com"
31    pub zone: String,
32}
33
34#[derive(Deserialize, JsonSchema)]
35pub struct ListZonesParams {
36    /// The DNS server ID to run this command against (see dns_list_servers)
37    pub server_id: String,
38    /// Page number for pagination (default: 1)
39    pub page_number: Option<u32>,
40    /// Zones per page (default: 50)
41    pub zones_per_page: Option<u32>,
42}
43
44#[derive(Deserialize, JsonSchema)]
45pub struct CreateZoneParams {
46    /// The DNS server ID to run this command against (see dns_list_servers)
47    pub server_id: String,
48    /// Zone name, e.g. "example.com"
49    pub zone: String,
50    /// Zone type: Primary, Secondary, Stub, Forwarder
51    pub zone_type: String,
52}
53
54#[derive(Deserialize, JsonSchema)]
55pub struct ExportZoneFileParams {
56    /// The DNS server ID to run this command against (see dns_list_servers)
57    pub server_id: String,
58    /// Zone name to export, e.g. "example.com"
59    pub zone: String,
60}
61
62#[derive(Deserialize, JsonSchema)]
63pub struct ImportZoneFileParams {
64    /// The DNS server ID to run this command against (see dns_list_servers)
65    pub server_id: String,
66    /// Zone name the file will be imported into (must already exist)
67    pub zone: String,
68    /// Full RFC 1035 zone file content as a string
69    pub content: String,
70    /// Filename shown in API logs (default: zone.txt)
71    pub file_name: Option<String>,
72    #[serde(flatten)]
73    pub options: ZoneImportOptions,
74}
75
76#[derive(Deserialize, JsonSchema)]
77pub struct TransferZoneParams {
78    /// Zone name to transfer, e.g. "example.com"
79    pub zone: String,
80    /// Source server ID.
81    pub from: String,
82    /// Destination server ID.
83    pub to: String,
84    /// Overwrite existing record sets in the destination for imported types (default: true)
85    #[serde(default = "default_true")]
86    pub overwrite: bool,
87    /// Delete all existing records in the destination before importing (default: false)
88    #[serde(default)]
89    pub overwrite_zone: bool,
90}
91
92// ─── Record params ─────────────────────────────────────────────────────────
93
94#[derive(Deserialize, JsonSchema)]
95pub struct ListRecordsParams {
96    /// The DNS server ID to run this command against (see dns_list_servers)
97    pub server_id: String,
98    /// Domain to list records for. Omit to list records for all hosted zones.
99    #[serde(default)]
100    pub domain: Option<String>,
101    /// Zone name (if different from domain)
102    pub zone: Option<String>,
103    /// Also show records for every subdomain of the given domain
104    #[serde(default)]
105    pub all_subdomains: Option<bool>,
106    /// Prefer a locally-resolved private IP over the provider's public A/AAAA value
107    #[serde(default, rename = "useLocalIp", alias = "use_local_ip")]
108    pub use_local_ip: Option<bool>,
109}
110
111#[derive(Deserialize, JsonSchema)]
112pub struct AddRecordParams {
113    /// The DNS server ID to run this command against (see dns_list_servers)
114    pub server_id: String,
115    pub zone: String,
116    pub domain: String,
117    /// TTL in seconds (default: 3600)
118    pub ttl: Option<u32>,
119    /// Typed record data, e.g. {"type":"A","ip":"1.2.3.4"} or
120    /// {"type":"MX","exchange":"mail.example.com","preference":10}
121    pub record: RecordData,
122}
123
124#[derive(Deserialize, JsonSchema)]
125pub struct DeleteRecordParams {
126    /// The DNS server ID to run this command against (see dns_list_servers)
127    pub server_id: String,
128    pub zone: String,
129    pub domain: String,
130    /// Which record(s) to delete. Only the `type` field is required.
131    /// Omitting value fields deletes ALL records of that type for the domain.
132    /// e.g. {"type":"A"} deletes all A records; {"type":"A","ipAddress":"1.2.3.4"} deletes one.
133    pub record: RecordSelector,
134}
135
136#[derive(Deserialize, JsonSchema)]
137pub struct DomainParams {
138    /// The DNS server ID to run this command against (see dns_list_servers)
139    pub server_id: String,
140    pub domain: String,
141}
142
143#[derive(Deserialize, JsonSchema)]
144pub struct StatsParams {
145    /// The DNS server ID to run this command against (see dns_list_servers)
146    pub server_id: String,
147    /// LastHour, LastDay, LastWeek, LastMonth, LastYear (default: LastDay)
148    pub stats_type: Option<String>,
149}
150
151// ─── Logs params ──────────────────────────────────────────────────────────
152
153#[derive(Deserialize, JsonSchema)]
154#[serde(rename_all = "lowercase")]
155pub enum LogLevelParam {
156    Trace,
157    Debug,
158    Info,
159    Warning,
160    Error,
161    Critical,
162}
163
164impl From<LogLevelParam> for LogLevel {
165    fn from(value: LogLevelParam) -> Self {
166        match value {
167            LogLevelParam::Trace => LogLevel::Trace,
168            LogLevelParam::Debug => LogLevel::Debug,
169            LogLevelParam::Info => LogLevel::Info,
170            LogLevelParam::Warning => LogLevel::Warning,
171            LogLevelParam::Error => LogLevel::Error,
172            LogLevelParam::Critical => LogLevel::Critical,
173        }
174    }
175}
176
177#[derive(Deserialize, JsonSchema)]
178pub struct LogsParams {
179    /// The DNS server ID to run this command against (see dns_list_servers)
180    pub server_id: String,
181    /// Maximum number of log lines to return. Provider default is used when omitted.
182    pub lines: Option<u32>,
183    /// Optional provider-specific start timestamp/filter.
184    pub start: Option<String>,
185    /// Optional provider-specific end timestamp/filter.
186    pub end: Option<String>,
187    /// Minimum log level to return.
188    pub level: Option<LogLevelParam>,
189}
190
191impl From<LogsParams> for LogsOptions {
192    fn from(value: LogsParams) -> Self {
193        Self {
194            lines: value.lines,
195            start: value.start,
196            end: value.end,
197            level: value.level.map(Into::into),
198        }
199    }
200}
201
202// ─── Sync params ───────────────────────────────────────────────────────────
203
204#[derive(Deserialize, JsonSchema)]
205pub struct SyncParams {
206    /// Named sync profile from the config file.
207    #[serde(default)]
208    pub profile: Option<String>,
209    /// Source server ID, overriding the profile.
210    #[serde(default)]
211    pub from: Option<String>,
212    /// Destination server ID, overriding the profile.
213    #[serde(default)]
214    pub to: Option<String>,
215    /// Zones to sync, overriding the profile.
216    #[serde(default)]
217    pub zones: Vec<String>,
218    /// IP rewrite entries in SRC=DST form.
219    #[serde(default)]
220    pub map: Vec<String>,
221    /// Write the changes. False/default is dry-run.
222    #[serde(default)]
223    pub apply: bool,
224}
225
226// ─── Resolve params ────────────────────────────────────────────────────────
227
228/// Parameters for `dns_resolve` — the MCP equivalent of `dns query`.
229///
230/// At most one of `server_id` / `at` should be set; if both are omitted
231/// the host's system resolver is used. Transport selection mirrors the
232/// CLI: leave `transports` empty and `all_transports` unset to let the
233/// server pick the first enabled block (precedence: doh → dot → dns →
234/// doq); supply a list of transports to fan out across those; or set
235/// `all_transports = true` (requires `server_id`) to query every
236/// enabled block.
237#[derive(Deserialize, JsonSchema)]
238pub struct ResolveParams {
239    /// Name to resolve (FQDN).
240    pub domain: String,
241
242    /// Record types to look up (default: all supported standard types).
243    /// Standard mnemonics:
244    /// A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, PTR, SOA, ANY.
245    #[serde(default)]
246    pub types: Option<Vec<String>>,
247
248    /// A configured [[servers]] entry to query. Matched case-
249    /// insensitively against `server.id`. Mutually exclusive with `at`.
250    #[serde(default)]
251    pub server_id: Option<String>,
252
253    /// Ad-hoc resolver. `host[:port]` or
254    /// `scheme://host[:port][/path]` (udp/tcp/dns/tls/dot/https/doh/
255    /// quic/doq). Mutually exclusive with `server_id`.
256    #[serde(default)]
257    pub at: Option<String>,
258
259    /// Subset of ["dns","dot","doh","doq"] to query. Empty means
260    /// "single best" (precedence pick) for `server_id`, or the
261    /// scheme-implied transport for `at`. Multiple values fan out.
262    #[serde(default)]
263    pub transports: Option<Vec<String>>,
264
265    /// Equivalent to specifying every transport flag. Requires
266    /// `server_id`. Mutually exclusive with non-empty `transports`.
267    #[serde(default)]
268    pub all_transports: Option<bool>,
269
270    /// Override port for ad-hoc targets only.
271    #[serde(default)]
272    pub port: Option<u16>,
273
274    /// SNI override for ad-hoc DoT/DoH/DoQ.
275    #[serde(default)]
276    pub tls_server_name: Option<String>,
277
278    /// Per-attempt timeout in milliseconds (default 5000).
279    #[serde(default)]
280    pub timeout_ms: Option<u64>,
281}