Skip to main content

khive_mcp/tools/
request.rs

1//! Parameter type for the single `request` MCP tool.
2
3use rmcp::schemars;
4use serde::{Deserialize, Serialize};
5
6/// Input for `request` — a DSL string (function-call or JSON form) plus
7/// optional presentation controls (`presentation` and `presentation_per_op`).
8#[derive(Debug, Default, Serialize, Deserialize, schemars::JsonSchema)]
9pub struct RequestParams {
10    /// One or more operations as a function-call DSL or JSON-form string.
11    ///
12    /// Examples:
13    /// - `gtd.next()`
14    /// - `gtd.assign(title="ship", priority="p1")`
15    /// - `create(kind="entity", name="A") | link(source_id=$prev.id, target_id="b", relation="extends")`
16    /// - `[create(kind="entity", entity_kind="concept", name="A"), create(kind="entity", entity_kind="concept", name="B")]`
17    /// - `[{"tool":"gtd.next","args":{}}, {"tool":"gtd.complete","args":{"id":"abc"}}]`
18    ///
19    /// Max 100 operations per batch.
20    #[schemars(
21        description = "Function-call DSL or JSON-form batch. See request tool description."
22    )]
23    pub ops: String,
24
25    /// Presentation mode for the response.
26    ///
27    /// - `"agent"` (default): token-efficient — short UUIDs, compact timestamps,
28    ///   empty fields dropped.
29    /// - `"verbose"`: full canonical shape, no transformation.
30    /// - `"human"`: delegated to CLI layer (same as verbose at runtime level).
31    ///
32    /// When omitted, defaults to `"agent"`.
33    #[serde(default)]
34    #[schemars(description = "Presentation mode: \"agent\" (default), \"verbose\", or \"human\"")]
35    pub presentation: Option<String>,
36
37    /// Per-operation presentation overrides.
38    ///
39    /// When provided, entries override `presentation` per op by index.
40    /// `null` entries fall back to the batch-level `presentation`.
41    ///
42    /// When omitted, all ops use `presentation`.
43    #[serde(default)]
44    #[schemars(description = "Per-op presentation mode override (optional)")]
45    pub presentation_per_op: Option<Vec<Option<String>>>,
46
47    /// File path for result sink.
48    ///
49    /// When set, the full results are written as JSONL to this path and the
50    /// caller receives a self-describing manifest instead of the raw results:
51    /// `{path, rows, per_column_null_counts, schema_fingerprint, checksum}`.
52    ///
53    /// The manifest lets agents detect bulk-export corruption (e.g. 10 000 null
54    /// rows) in one call rather than after a downstream judgment fleet has graded
55    /// blind. Parent directories are created if absent.
56    ///
57    /// The resolved destination MUST stay within the allowed export root
58    /// (default `~/.khive/exports`, overridable via `KHIVE_SAVE_TO_ROOT`).
59    /// Relative paths are joined under the root; absolute paths are accepted
60    /// only if they resolve inside it. Paths containing `..` traversal
61    /// components and symlinked destinations are rejected.
62    ///
63    /// When omitted, results are returned inline (default behaviour).
64    #[serde(default)]
65    #[schemars(
66        description = "File path to sink results as JSONL (returns manifest, not raw results)"
67    )]
68    pub save_to: Option<String>,
69
70    /// Output serialization format for all ops in this request (ADR-078).
71    ///
72    /// - `"json"` (default): compact, lossless JSON.
73    /// - `"auto"`: shape-aware — markdown table for homogeneous record arrays,
74    ///   flat key-value block for single records, compact-JSON fallback.
75    /// - `"table"`: force markdown-table renderer regardless of shape.
76    ///
77    /// Overrides `KHIVE_OUTPUT_FORMAT` and the TOML `default_output_format`.
78    /// When omitted, the server's resolved default (env → toml → builtin `json`) is used.
79    #[serde(default)]
80    #[schemars(description = "Output format: \"json\" (default), \"auto\", or \"table\"")]
81    pub format: Option<String>,
82
83    /// Per-operation output format overrides (ADR-078).
84    ///
85    /// When provided, entries override `format` per op by index.
86    /// `null` entries fall back to the batch-level `format`.
87    ///
88    /// When omitted, all ops use `format`.
89    #[serde(default)]
90    #[schemars(description = "Per-op output format override (optional)")]
91    pub format_per_op: Option<Vec<Option<String>>>,
92
93    /// Caller-supplied correlation id (khive#948), forwarded unchanged onto
94    /// the daemon request frame and echoed back on the response so a
95    /// benchmark harness can join its own pre-send sample to the server-side
96    /// audit row for this request. Purely a correlation label — it never
97    /// changes how a request is dispatched. When omitted, the request
98    /// carries no id and its audit row has no `request_id` key.
99    #[serde(default)]
100    #[schemars(
101        description = "Caller-supplied correlation id, echoed back and stamped into the audit event (optional)"
102    )]
103    pub request_id: Option<u64>,
104}