Skip to main content

objectiveai_sdk/client_objectiveai_mcp/client_request/
payload.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4/// Tagged union of request shapes the client-app layer can push down
5/// the reverse-attach channel.
6///
7/// Currently a single client → API variant: `McpListChanged`. The CLI's
8/// upstream `mcp::Connection` fired
9/// `notifications/{tools,resources}/list_changed` and the API
10/// re-emits it as an SSE event on the matching per-MCP GET stream —
11/// `/objectiveai` or `/{owner}/{name}/{ver}/{mcp}`, routed by
12/// `X-OBJECTIVEAI-RESPONSE-ID`.
13///
14/// The wire envelope's `id` field always belongs to whichever side
15/// originated the request; the receiver's `client_response::Response`
16/// echoes the same `id`.
17#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
18#[schemars(rename = "client_objectiveai_mcp.client_request.Payload")]
19#[serde(tag = "type", rename_all = "snake_case")]
20pub enum Payload {
21    /// The CLI's upstream `mcp::Connection` for `mcp_kind` fired
22    /// `notifications/<kind>/list_changed`. The API dispatches this
23    /// onto its per-`(response_id, McpKind)` broadcast so the
24    /// matching MCP GET-SSE listener sees a standard MCP
25    /// notification frame.
26    #[schemars(title = "McpListChanged")]
27    McpListChanged(McpListChanged),
28
29    /// Run the proxy's aggregated `tools/list` for `response_id` — the
30    /// same operation the proxy's HTTP `tools/list` endpoint performs
31    /// (fan out to every upstream in that session). Session-scoped, so
32    /// no `mcp_kind`; carries the normal MCP `tools/list` params.
33    #[schemars(title = "ListTools")]
34    ListTools {
35        response_id: String,
36        #[serde(flatten)]
37        params: crate::mcp::tool::ListToolsRequest,
38    },
39
40    /// Run the proxy's aggregated `tools/call` for `response_id` (routes
41    /// by tool-name prefix to the owning upstream). Unlike the HTTP
42    /// `tools/call`, this path does NOT consult the queue delegate.
43    #[schemars(title = "CallTool")]
44    CallTool {
45        response_id: String,
46        #[serde(flatten)]
47        params: crate::mcp::tool::CallToolRequestParams,
48    },
49
50    /// Run the proxy's aggregated `resources/list` for `response_id`.
51    #[schemars(title = "ListResources")]
52    ListResources {
53        response_id: String,
54        #[serde(flatten)]
55        params: crate::mcp::resource::ListResourcesRequest,
56    },
57
58    /// Run the proxy's `resources/read` for `response_id` (routes by URI
59    /// prefix to the owning upstream).
60    #[schemars(title = "ReadResource")]
61    ReadResource {
62        response_id: String,
63        #[serde(flatten)]
64        params: crate::mcp::resource::ReadResourceRequestParams,
65    },
66}
67
68/// Payload for [`Payload::McpListChanged`].
69#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
70#[schemars(rename = "client_objectiveai_mcp.client_request.McpListChanged")]
71pub struct McpListChanged {
72    /// Which CLI-hosted MCP server fired the list-changed
73    /// notification. The API uses this to look up the right
74    /// per-MCP SSE broadcast and republish a standard MCP
75    /// notification frame to that upstream's proxy subscriber.
76    pub mcp_kind: super::super::McpKind,
77    /// Which catalog changed.
78    pub kind: McpListChangedKind,
79}
80
81/// Distinguishes `tools/list_changed` from `resources/list_changed`.
82#[derive(
83    Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash,
84)]
85#[schemars(rename = "client_objectiveai_mcp.client_request.McpListChangedKind")]
86#[serde(rename_all = "snake_case")]
87pub enum McpListChangedKind {
88    Tools,
89    Resources,
90}
91
92impl McpListChangedKind {
93    /// JSON-RPC method name MCP uses on the wire for this notification
94    /// kind. Used by the API's GET-SSE handler when it emits the
95    /// translated frame to subscribers.
96    pub fn method(&self) -> &'static str {
97        match self {
98            McpListChangedKind::Tools => "notifications/tools/list_changed",
99            McpListChangedKind::Resources => {
100                "notifications/resources/list_changed"
101            }
102        }
103    }
104}