Skip to main content

tenx_mcp/
schema.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6// JSON-RPC types
7
8/// Refers to any valid JSON-RPC object that can be decoded off the wire, or
9/// encoded to be sent.
10#[derive(Debug, Clone, Serialize, Deserialize)]
11#[serde(untagged)]
12pub enum JSONRPCMessage {
13    Request(JSONRPCRequest),
14    Notification(JSONRPCNotification),
15    BatchRequest(JSONRPCBatchRequest),
16    Response(JSONRPCResponse),
17    Error(JSONRPCError),
18    BatchResponse(JSONRPCBatchResponse),
19}
20
21/// A JSON-RPC batch request, as described in https://www.jsonrpc.org/specification#batch.
22pub type JSONRPCBatchRequest = Vec<JSONRPCRequestOrNotification>;
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25#[serde(untagged)]
26pub enum JSONRPCRequestOrNotification {
27    Request(JSONRPCRequest),
28    Notification(JSONRPCNotification),
29}
30
31/// A JSON-RPC batch response, as described in https://www.jsonrpc.org/specification#batch.
32pub type JSONRPCBatchResponse = Vec<JSONRPCResponseOrError>;
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35#[serde(untagged)]
36pub enum JSONRPCResponseOrError {
37    Response(JSONRPCResponse),
38    Error(JSONRPCError),
39}
40
41pub const LATEST_PROTOCOL_VERSION: &str = "2025-03-26";
42pub const JSONRPC_VERSION: &str = "2.0";
43
44/// A progress token, used to associate progress notifications with the original
45/// request.
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(untagged)]
48pub enum ProgressToken {
49    String(String),
50    Number(i64),
51}
52
53/// An opaque token used to represent a cursor for pagination.
54pub type Cursor = String;
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct Request {
58    pub method: String,
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub params: Option<RequestParams>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct RequestParams {
65    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
66    pub meta: Option<RequestMeta>,
67    #[serde(flatten)]
68    pub other: HashMap<String, Value>,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct RequestMeta {
73    /// If specified, the caller is requesting out-of-band progress
74    /// notifications for this request (as represented by
75    /// notifications/progress). The value of this parameter is an opaque token
76    /// that will be attached to any subsequent notifications. The receiver is
77    /// not obligated to provide these notifications.
78    #[serde(rename = "progressToken", skip_serializing_if = "Option::is_none")]
79    pub progress_token: Option<ProgressToken>,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct Notification {
84    pub method: String,
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub params: Option<NotificationParams>,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct NotificationParams {
91    /// This parameter name is reserved by MCP to allow clients and servers to
92    /// attach additional metadata to their notifications.
93    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
94    pub meta: Option<HashMap<String, Value>>,
95    #[serde(flatten)]
96    pub other: HashMap<String, Value>,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct Result {
101    /// This result property is reserved by the protocol to allow clients and
102    /// servers to attach additional metadata to their responses.
103    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
104    pub meta: Option<HashMap<String, Value>>,
105    #[serde(flatten)]
106    pub other: HashMap<String, Value>,
107}
108
109/// A uniquely identifying ID for a request in JSON-RPC.
110#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
111#[serde(untagged)]
112pub enum RequestId {
113    String(String),
114    Number(i64),
115}
116
117/// A request that expects a response.
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct JSONRPCRequest {
120    pub jsonrpc: String,
121    pub id: RequestId,
122    #[serde(flatten)]
123    pub request: Request,
124}
125
126/// A notification which does not expect a response.
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct JSONRPCNotification {
129    pub jsonrpc: String,
130    #[serde(flatten)]
131    pub notification: Notification,
132}
133
134/// A successful (non-error) response to a request.
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct JSONRPCResponse {
137    pub jsonrpc: String,
138    pub id: RequestId,
139    pub result: Result,
140}
141
142// Standard JSON-RPC error codes
143pub const PARSE_ERROR: i32 = -32700;
144pub const INVALID_REQUEST: i32 = -32600;
145pub const METHOD_NOT_FOUND: i32 = -32601;
146pub const INVALID_PARAMS: i32 = -32602;
147pub const INTERNAL_ERROR: i32 = -32603;
148
149/// A response to a request that indicates an error occurred.
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct JSONRPCError {
152    pub jsonrpc: String,
153    pub id: RequestId,
154    pub error: ErrorObject,
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct ErrorObject {
159    /// The error type that occurred.
160    pub code: i32,
161    /// A short description of the error. The message SHOULD be limited to a
162    /// concise single sentence.
163    pub message: String,
164    /// Additional information about the error. The value of this member is
165    /// defined by the sender (e.g. detailed error information, nested
166    /// errors etc.).
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub data: Option<Value>,
169}
170
171// Empty result
172/// A response that indicates success but carries no data.
173pub type EmptyResult = Result;
174
175// Cancellation
176/// This notification can be sent by either side to indicate that it is
177/// cancelling a previously-issued request.
178///
179/// The request SHOULD still be in-flight, but due to communication latency, it
180/// is always possible that this notification MAY arrive after the request has
181/// already finished.
182///
183/// This notification indicates that the result will be unused, so any
184/// associated processing SHOULD cease.
185///
186/// A client MUST NOT attempt to cancel its `initialize` request.
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct CancelledNotification {
189    pub method: String,
190    pub params: CancelledParams,
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct CancelledParams {
195    /// The ID of the request to cancel.
196    ///
197    /// This MUST correspond to the ID of a request previously issued in the
198    /// same direction.
199    #[serde(rename = "requestId")]
200    pub request_id: RequestId,
201    /// An optional string describing the reason for the cancellation. This MAY
202    /// be logged or presented to the user.
203    #[serde(skip_serializing_if = "Option::is_none")]
204    pub reason: Option<String>,
205}
206
207// Initialization
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct InitializeParams {
211    /// The latest version of the Model Context Protocol that the client
212    /// supports. The client MAY decide to support older versions as well.
213    #[serde(rename = "protocolVersion")]
214    pub protocol_version: String,
215    pub capabilities: ClientCapabilities,
216    #[serde(rename = "clientInfo")]
217    pub client_info: Implementation,
218}
219
220/// After receiving an initialize request from the client, the server sends this
221/// response.
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct InitializeResult {
224    /// The version of the Model Context Protocol that the server wants to use.
225    /// This may not match the version that the client requested. If the
226    /// client cannot support this version, it MUST disconnect.
227    #[serde(rename = "protocolVersion")]
228    pub protocol_version: String,
229    pub capabilities: ServerCapabilities,
230    #[serde(rename = "serverInfo")]
231    pub server_info: Implementation,
232    /// Instructions describing how to use the server and its features.
233    ///
234    /// This can be used by clients to improve the LLM's understanding of
235    /// available tools, resources, etc. It can be thought of like a "hint"
236    /// to the model. For example, this information MAY be added to the
237    /// system prompt.
238    #[serde(skip_serializing_if = "Option::is_none")]
239    pub instructions: Option<String>,
240    #[serde(flatten)]
241    pub result: Result,
242}
243
244/// This notification is sent from the client to the server after initialization
245/// has finished.
246#[derive(Debug, Clone, Serialize, Deserialize)]
247pub struct InitializedNotification {
248    pub method: String,
249}
250
251/// Capabilities a client may support. Known capabilities are defined here, in
252/// this schema, but this is not a closed set: any client can define its own,
253/// additional capabilities.
254#[derive(Debug, Clone, Serialize, Deserialize, Default)]
255pub struct ClientCapabilities {
256    /// Experimental, non-standard capabilities that the client supports.
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub experimental: Option<HashMap<String, Value>>,
259    /// Present if the client supports listing roots.
260    #[serde(skip_serializing_if = "Option::is_none")]
261    pub roots: Option<RootsCapability>,
262    /// Present if the client supports sampling from an LLM.
263    #[serde(skip_serializing_if = "Option::is_none")]
264    pub sampling: Option<Value>,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct RootsCapability {
269    /// Whether the client supports notifications for changes to the roots list.
270    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
271    pub list_changed: Option<bool>,
272}
273
274/// Capabilities that a server may support. Known capabilities are defined here,
275/// in this schema, but this is not a closed set: any server can define its own,
276/// additional capabilities.
277#[derive(Debug, Clone, Serialize, Deserialize, Default)]
278pub struct ServerCapabilities {
279    /// Experimental, non-standard capabilities that the server supports.
280    #[serde(skip_serializing_if = "Option::is_none")]
281    pub experimental: Option<HashMap<String, Value>>,
282    /// Present if the server supports sending log messages to the client.
283    #[serde(skip_serializing_if = "Option::is_none")]
284    pub logging: Option<Value>,
285    /// Present if the server supports argument autocompletion suggestions.
286    #[serde(skip_serializing_if = "Option::is_none")]
287    pub completions: Option<Value>,
288    /// Present if the server offers any prompt templates.
289    #[serde(skip_serializing_if = "Option::is_none")]
290    pub prompts: Option<PromptsCapability>,
291    /// Present if the server offers any resources to read.
292    #[serde(skip_serializing_if = "Option::is_none")]
293    pub resources: Option<ResourcesCapability>,
294    /// Present if the server offers any tools to call.
295    #[serde(skip_serializing_if = "Option::is_none")]
296    pub tools: Option<ToolsCapability>,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct PromptsCapability {
301    /// Whether this server supports notifications for changes to the prompt
302    /// list.
303    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
304    pub list_changed: Option<bool>,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize)]
308pub struct ResourcesCapability {
309    /// Whether this server supports subscribing to resource updates.
310    #[serde(skip_serializing_if = "Option::is_none")]
311    pub subscribe: Option<bool>,
312    /// Whether this server supports notifications for changes to the resource
313    /// list.
314    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
315    pub list_changed: Option<bool>,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct ToolsCapability {
320    /// Whether this server supports notifications for changes to the tool list.
321    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
322    pub list_changed: Option<bool>,
323}
324
325/// Describes the name and version of an MCP implementation.
326#[derive(Debug, Clone, Serialize, Deserialize)]
327pub struct Implementation {
328    pub name: String,
329    pub version: String,
330}
331
332// Ping
333
334// Progress notifications
335/// An out-of-band notification used to inform the receiver of a progress update
336/// for a long-running request.
337#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct ProgressNotification {
339    pub method: String,
340    pub params: ProgressParams,
341}
342
343#[derive(Debug, Clone, Serialize, Deserialize)]
344pub struct ProgressParams {
345    /// The progress token which was given in the initial request, used to
346    /// associate this notification with the request that is proceeding.
347    #[serde(rename = "progressToken")]
348    pub progress_token: ProgressToken,
349    /// The progress thus far. This should increase every time progress is made,
350    /// even if the total is unknown.
351    pub progress: f64,
352    /// Total number of items to process (or total progress required), if known.
353    #[serde(skip_serializing_if = "Option::is_none")]
354    pub total: Option<f64>,
355    /// An optional message describing the current progress.
356    #[serde(skip_serializing_if = "Option::is_none")]
357    pub message: Option<String>,
358}
359
360// Pagination
361#[derive(Debug, Clone, Serialize, Deserialize)]
362pub struct PaginatedRequest {
363    #[serde(flatten)]
364    pub request: Request,
365}
366
367#[derive(Debug, Clone, Serialize, Deserialize)]
368pub struct PaginatedParams {
369    /// An opaque token representing the current pagination position.
370    /// If provided, the server should return results starting after this
371    /// cursor.
372    #[serde(skip_serializing_if = "Option::is_none")]
373    pub cursor: Option<Cursor>,
374    #[serde(flatten)]
375    pub other: HashMap<String, Value>,
376}
377
378#[derive(Debug, Clone, Serialize, Deserialize)]
379pub struct PaginatedResult {
380    /// An opaque token representing the pagination position after the last
381    /// returned result. If present, there may be more results available.
382    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
383    pub next_cursor: Option<Cursor>,
384    #[serde(flatten)]
385    pub result: Result,
386}
387
388// Resources
389
390/// The server's response to a resources/list request from the client.
391#[derive(Debug, Clone, Serialize, Deserialize)]
392pub struct ListResourcesResult {
393    pub resources: Vec<Resource>,
394    #[serde(flatten)]
395    pub paginated: PaginatedResult,
396}
397
398/// The server's response to a resources/templates/list request from the client.
399#[derive(Debug, Clone, Serialize, Deserialize)]
400pub struct ListResourceTemplatesResult {
401    #[serde(rename = "resourceTemplates")]
402    pub resource_templates: Vec<ResourceTemplate>,
403    #[serde(flatten)]
404    pub paginated: PaginatedResult,
405}
406
407#[derive(Debug, Clone, Serialize, Deserialize)]
408pub struct ReadResourceParams {
409    /// The URI of the resource to read. The URI can use any protocol; it is up
410    /// to the server how to interpret it.
411    pub uri: String,
412}
413
414/// The server's response to a resources/read request from the client.
415#[derive(Debug, Clone, Serialize, Deserialize)]
416pub struct ReadResourceResult {
417    pub contents: Vec<ResourceContents>,
418    #[serde(flatten)]
419    pub result: Result,
420}
421
422/// An optional notification from the server to the client, informing it that
423/// the list of resources it can read from has changed. This may be issued by
424/// servers without any previous subscription from the client.
425#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct ResourceListChangedNotification {
427    pub method: String,
428}
429
430/// A notification from the server to the client, informing it that a resource
431/// has changed and may need to be read again. This should only be sent if the
432/// client previously sent a resources/subscribe request.
433#[derive(Debug, Clone, Serialize, Deserialize)]
434pub struct ResourceUpdatedNotification {
435    pub method: String,
436    pub params: ResourceUpdatedParams,
437}
438
439#[derive(Debug, Clone, Serialize, Deserialize)]
440pub struct ResourceUpdatedParams {
441    /// The URI of the resource that has been updated. This might be a
442    /// sub-resource of the one that the client actually subscribed to.
443    pub uri: String,
444}
445
446/// A known resource that the server is capable of reading.
447#[derive(Debug, Clone, Serialize, Deserialize)]
448pub struct Resource {
449    /// The URI of this resource.
450    pub uri: String,
451    /// A human-readable name for this resource.
452    ///
453    /// This can be used by clients to populate UI elements.
454    pub name: String,
455    /// A description of what this resource represents.
456    ///
457    /// This can be used by clients to improve the LLM's understanding of
458    /// available resources. It can be thought of like a "hint" to the
459    /// model.
460    #[serde(skip_serializing_if = "Option::is_none")]
461    pub description: Option<String>,
462    /// The MIME type of this resource, if known.
463    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
464    pub mime_type: Option<String>,
465    /// Optional annotations for the client.
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub annotations: Option<Annotations>,
468    /// The size of the raw resource content, in bytes (i.e., before base64
469    /// encoding or any tokenization), if known.
470    ///
471    /// This can be used by Hosts to display file sizes and estimate context
472    /// window usage.
473    #[serde(skip_serializing_if = "Option::is_none")]
474    pub size: Option<i64>,
475}
476
477/// A template description for resources available on the server.
478#[derive(Debug, Clone, Serialize, Deserialize)]
479pub struct ResourceTemplate {
480    /// A URI template (according to RFC 6570) that can be used to construct
481    /// resource URIs.
482    #[serde(rename = "uriTemplate")]
483    pub uri_template: String,
484    /// A human-readable name for the type of resource this template refers to.
485    ///
486    /// This can be used by clients to populate UI elements.
487    pub name: String,
488    /// A description of what this template is for.
489    ///
490    /// This can be used by clients to improve the LLM's understanding of
491    /// available resources. It can be thought of like a "hint" to the
492    /// model.
493    #[serde(skip_serializing_if = "Option::is_none")]
494    pub description: Option<String>,
495    /// The MIME type for all resources that match this template. This should
496    /// only be included if all resources matching this template have the
497    /// same type.
498    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
499    pub mime_type: Option<String>,
500    /// Optional annotations for the client.
501    #[serde(skip_serializing_if = "Option::is_none")]
502    pub annotations: Option<Annotations>,
503}
504
505/// The contents of a specific resource or sub-resource.
506#[derive(Debug, Clone, Serialize, Deserialize)]
507#[serde(untagged)]
508pub enum ResourceContents {
509    Text(TextResourceContents),
510    Blob(BlobResourceContents),
511}
512
513#[derive(Debug, Clone, Serialize, Deserialize)]
514pub struct TextResourceContents {
515    /// The URI of this resource.
516    pub uri: String,
517    /// The MIME type of this resource, if known.
518    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
519    pub mime_type: Option<String>,
520    /// The text of the item. This must only be set if the item can actually be
521    /// represented as text (not binary data).
522    pub text: String,
523}
524
525#[derive(Debug, Clone, Serialize, Deserialize)]
526pub struct BlobResourceContents {
527    /// The URI of this resource.
528    pub uri: String,
529    /// The MIME type of this resource, if known.
530    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
531    pub mime_type: Option<String>,
532    /// A base64-encoded string representing the binary data of the item.
533    pub blob: String,
534}
535
536// Prompts
537
538/// The server's response to a prompts/list request from the client.
539#[derive(Debug, Clone, Serialize, Deserialize)]
540pub struct ListPromptsResult {
541    pub prompts: Vec<Prompt>,
542    #[serde(flatten)]
543    pub paginated: PaginatedResult,
544}
545
546/// The server's response to a prompts/get request from the client.
547#[derive(Debug, Clone, Serialize, Deserialize)]
548pub struct GetPromptResult {
549    /// An optional description for the prompt.
550    #[serde(skip_serializing_if = "Option::is_none")]
551    pub description: Option<String>,
552    pub messages: Vec<PromptMessage>,
553    #[serde(flatten)]
554    pub result: Result,
555}
556
557/// A prompt or prompt template that the server offers.
558#[derive(Debug, Clone, Serialize, Deserialize)]
559pub struct Prompt {
560    /// The name of the prompt or prompt template.
561    pub name: String,
562    /// An optional description of what this prompt provides
563    #[serde(skip_serializing_if = "Option::is_none")]
564    pub description: Option<String>,
565    /// A list of arguments to use for templating the prompt.
566    #[serde(skip_serializing_if = "Option::is_none")]
567    pub arguments: Option<Vec<PromptArgument>>,
568}
569
570/// Describes an argument that a prompt can accept.
571#[derive(Debug, Clone, Serialize, Deserialize)]
572pub struct PromptArgument {
573    /// The name of the argument.
574    pub name: String,
575    /// A human-readable description of the argument.
576    #[serde(skip_serializing_if = "Option::is_none")]
577    pub description: Option<String>,
578    /// Whether this argument must be provided.
579    #[serde(skip_serializing_if = "Option::is_none")]
580    pub required: Option<bool>,
581}
582
583/// The sender or recipient of messages and data in a conversation.
584#[derive(Debug, Clone, Serialize, Deserialize)]
585#[serde(rename_all = "lowercase")]
586pub enum Role {
587    User,
588    Assistant,
589}
590
591/// Describes a message returned as part of a prompt.
592///
593/// This is similar to `SamplingMessage`, but also supports the embedding of
594/// resources from the MCP server.
595#[derive(Debug, Clone, Serialize, Deserialize)]
596pub struct PromptMessage {
597    pub role: Role,
598    pub content: Content,
599}
600
601#[derive(Debug, Clone, Serialize, Deserialize)]
602#[serde(tag = "type", rename_all = "lowercase")]
603pub enum Content {
604    Text(TextContent),
605    Image(ImageContent),
606    Audio(AudioContent),
607    Resource(EmbeddedResource),
608}
609
610/// The contents of a resource, embedded into a prompt or tool call result.
611///
612/// It is up to the client how best to render embedded resources for the benefit
613/// of the LLM and/or the user.
614#[derive(Debug, Clone, Serialize, Deserialize)]
615pub struct EmbeddedResource {
616    pub resource: ResourceContents,
617    /// Optional annotations for the client.
618    #[serde(skip_serializing_if = "Option::is_none")]
619    pub annotations: Option<Annotations>,
620}
621
622/// An optional notification from the server to the client, informing it that
623/// the list of prompts it offers has changed. This may be issued by servers
624/// without any previous subscription from the client.
625#[derive(Debug, Clone, Serialize, Deserialize)]
626pub struct PromptListChangedNotification {
627    pub method: String,
628}
629
630// Tools
631
632/// The server's response to a tools/list request from the client.
633#[derive(Debug, Clone, Serialize, Deserialize)]
634pub struct ListToolsResult {
635    pub tools: Vec<Tool>,
636    #[serde(flatten)]
637    pub paginated: PaginatedResult,
638}
639
640/// The server's response to a tool call.
641///
642/// Any errors that originate from the tool SHOULD be reported inside the result
643/// object, with `isError` set to true, _not_ as an MCP protocol-level error
644/// response. Otherwise, the LLM would not be able to see that an error occurred
645/// and self-correct.
646///
647/// However, any errors in _finding_ the tool, an error indicating that the
648/// server does not support tool calls, or any other exceptional conditions,
649/// should be reported as an MCP error response.
650#[derive(Debug, Clone, Serialize, Deserialize)]
651pub struct CallToolResult {
652    pub content: Vec<Content>,
653    /// Whether the tool call ended in an error.
654    ///
655    /// If not set, this is assumed to be false (the call was successful).
656    #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
657    pub is_error: Option<bool>,
658    #[serde(flatten)]
659    pub result: Result,
660}
661
662/// An optional notification from the server to the client, informing it that
663/// the list of tools it offers has changed. This may be issued by servers
664/// without any previous subscription from the client.
665#[derive(Debug, Clone, Serialize, Deserialize)]
666pub struct ToolListChangedNotification {
667    pub method: String,
668}
669
670/// Additional properties describing a Tool to clients.
671///
672/// NOTE: all properties in ToolAnnotations are **hints**.
673/// They are not guaranteed to provide a faithful description of
674/// tool behavior (including descriptive properties like `title`).
675///
676/// Clients should never make tool use decisions based on ToolAnnotations
677/// received from untrusted servers.
678#[derive(Debug, Clone, Serialize, Deserialize)]
679pub struct ToolAnnotations {
680    /// A human-readable title for the tool.
681    #[serde(skip_serializing_if = "Option::is_none")]
682    pub title: Option<String>,
683    /// If true, the tool does not modify its environment.
684    ///
685    /// Default: false
686    #[serde(rename = "readOnlyHint", skip_serializing_if = "Option::is_none")]
687    pub read_only_hint: Option<bool>,
688    /// If true, the tool may perform destructive updates to its environment.
689    /// If false, the tool performs only additive updates.
690    ///
691    /// (This property is meaningful only when `readOnlyHint == false`)
692    ///
693    /// Default: true
694    #[serde(rename = "destructiveHint", skip_serializing_if = "Option::is_none")]
695    pub destructive_hint: Option<bool>,
696    /// If true, calling the tool repeatedly with the same arguments
697    /// will have no additional effect on the its environment.
698    ///
699    /// (This property is meaningful only when `readOnlyHint == false`)
700    ///
701    /// Default: false
702    #[serde(rename = "idempotentHint", skip_serializing_if = "Option::is_none")]
703    pub idempotent_hint: Option<bool>,
704    /// If true, this tool may interact with an "open world" of external
705    /// entities. If false, the tool's domain of interaction is closed.
706    /// For example, the world of a web search tool is open, whereas that
707    /// of a memory tool is not.
708    ///
709    /// Default: true
710    #[serde(rename = "openWorldHint", skip_serializing_if = "Option::is_none")]
711    pub open_world_hint: Option<bool>,
712}
713
714/// Parameters for calling a tool.
715#[derive(Debug, Clone, Serialize, Deserialize)]
716pub struct CallToolParams {
717    /// The name of the tool to call.
718    pub name: String,
719    /// Arguments to pass to the tool.
720    #[serde(skip_serializing_if = "Option::is_none")]
721    pub arguments: Option<HashMap<String, Value>>,
722}
723
724/// Parameters for getting a prompt.
725#[derive(Debug, Clone, Serialize, Deserialize)]
726pub struct GetPromptParams {
727    /// The name of the prompt to get.
728    pub name: String,
729    /// Arguments to use for templating the prompt.
730    #[serde(skip_serializing_if = "Option::is_none")]
731    pub arguments: Option<HashMap<String, Value>>,
732}
733
734/// Definition for a tool the client can call.
735#[derive(Debug, Clone, Serialize, Deserialize)]
736pub struct Tool {
737    /// The name of the tool.
738    pub name: String,
739    /// A human-readable description of the tool.
740    ///
741    /// This can be used by clients to improve the LLM's understanding of
742    /// available tools. It can be thought of like a "hint" to the model.
743    #[serde(skip_serializing_if = "Option::is_none")]
744    pub description: Option<String>,
745    /// A JSON Schema object defining the expected parameters for the tool.
746    #[serde(rename = "inputSchema")]
747    pub input_schema: ToolInputSchema,
748    /// Optional additional tool information.
749    #[serde(skip_serializing_if = "Option::is_none")]
750    pub annotations: Option<ToolAnnotations>,
751}
752
753#[derive(Debug, Clone, Serialize, Deserialize)]
754pub struct ToolInputSchema {
755    #[serde(rename = "type")]
756    pub schema_type: String,
757    #[serde(skip_serializing_if = "Option::is_none")]
758    pub properties: Option<HashMap<String, Value>>,
759    #[serde(skip_serializing_if = "Option::is_none")]
760    pub required: Option<Vec<String>>,
761}
762
763// Logging
764
765/// Notification of a log message passed from server to client. If no
766/// logging/setLevel request has been sent from the client, the server MAY
767/// decide which messages to send automatically.
768#[derive(Debug, Clone, Serialize, Deserialize)]
769pub struct LoggingMessageNotification {
770    pub method: String,
771    pub params: LoggingMessageParams,
772}
773
774#[derive(Debug, Clone, Serialize, Deserialize)]
775pub struct LoggingMessageParams {
776    /// The severity of this log message.
777    pub level: LoggingLevel,
778    /// An optional name of the logger issuing this message.
779    #[serde(skip_serializing_if = "Option::is_none")]
780    pub logger: Option<String>,
781    /// The data to be logged, such as a string message or an object. Any JSON
782    /// serializable type is allowed here.
783    pub data: Value,
784}
785
786/// The severity of a log message.
787///
788/// These map to syslog message severities, as specified in RFC-5424:
789/// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1
790#[derive(Debug, Clone, Serialize, Deserialize)]
791#[serde(rename_all = "lowercase")]
792pub enum LoggingLevel {
793    Debug,
794    Info,
795    Notice,
796    Warning,
797    Error,
798    Critical,
799    Alert,
800    Emergency,
801}
802
803// Sampling
804/// A request from the server to sample an LLM via the client. The client has
805/// full discretion over which model to select. The client should also inform
806/// the user before beginning sampling, to allow them to inspect the request
807/// (human in the loop) and decide whether to approve it.
808#[derive(Debug, Clone, Serialize, Deserialize)]
809pub struct CreateMessageRequest {
810    pub method: String,
811    pub params: CreateMessageParams,
812}
813
814#[derive(Debug, Clone, Serialize, Deserialize)]
815pub struct CreateMessageParams {
816    pub messages: Vec<SamplingMessage>,
817    /// The server's preferences for which model to select. The client MAY
818    /// ignore these preferences.
819    #[serde(rename = "modelPreferences", skip_serializing_if = "Option::is_none")]
820    pub model_preferences: Option<ModelPreferences>,
821    /// An optional system prompt the server wants to use for sampling. The
822    /// client MAY modify or omit this prompt.
823    #[serde(rename = "systemPrompt", skip_serializing_if = "Option::is_none")]
824    pub system_prompt: Option<String>,
825    /// A request to include context from one or more MCP servers (including the
826    /// caller), to be attached to the prompt. The client MAY ignore this
827    /// request.
828    #[serde(rename = "includeContext", skip_serializing_if = "Option::is_none")]
829    pub include_context: Option<IncludeContext>,
830    #[serde(skip_serializing_if = "Option::is_none")]
831    pub temperature: Option<f64>,
832    /// The maximum number of tokens to sample, as requested by the server. The
833    /// client MAY choose to sample fewer tokens than requested.
834    #[serde(rename = "maxTokens")]
835    pub max_tokens: i64,
836    #[serde(rename = "stopSequences", skip_serializing_if = "Option::is_none")]
837    pub stop_sequences: Option<Vec<String>>,
838    /// Optional metadata to pass through to the LLM provider. The format of
839    /// this metadata is provider-specific.
840    #[serde(skip_serializing_if = "Option::is_none")]
841    pub metadata: Option<Value>,
842}
843
844#[derive(Debug, Clone, Serialize, Deserialize)]
845#[serde(rename_all = "camelCase")]
846pub enum IncludeContext {
847    None,
848    ThisServer,
849    AllServers,
850}
851
852/// The client's response to a sampling/create_message request from the server.
853/// The client should inform the user before returning the sampled message, to
854/// allow them to inspect the response (human in the loop) and decide whether to
855/// allow the server to see it.
856#[derive(Debug, Clone, Serialize, Deserialize)]
857pub struct CreateMessageResult {
858    pub role: Role,
859    pub content: SamplingContent,
860    /// The name of the model that generated the message.
861    pub model: String,
862    /// The reason why sampling stopped, if known.
863    #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
864    pub stop_reason: Option<StopReason>,
865    #[serde(flatten)]
866    pub result: Result,
867}
868
869#[derive(Debug, Clone, Serialize, Deserialize)]
870#[serde(rename_all = "camelCase")]
871pub enum StopReason {
872    EndTurn,
873    StopSequence,
874    MaxTokens,
875    #[serde(untagged)]
876    Other(String),
877}
878
879/// Describes a message issued to or received from an LLM API.
880#[derive(Debug, Clone, Serialize, Deserialize)]
881pub struct SamplingMessage {
882    pub role: Role,
883    pub content: SamplingContent,
884}
885
886#[derive(Debug, Clone, Serialize, Deserialize)]
887#[serde(tag = "type", rename_all = "lowercase")]
888pub enum SamplingContent {
889    Text(TextContent),
890    Image(ImageContent),
891    Audio(AudioContent),
892}
893
894/// Optional annotations for the client. The client can use annotations to
895/// inform how objects are used or displayed
896#[derive(Debug, Clone, Serialize, Deserialize)]
897pub struct Annotations {
898    /// Describes who the intended customer of this object or data is.
899    ///
900    /// It can include multiple entries to indicate content useful for multiple
901    /// audiences (e.g., `["user", "assistant"]`).
902    #[serde(skip_serializing_if = "Option::is_none")]
903    pub audience: Option<Vec<Role>>,
904    /// Describes how important this data is for operating the server.
905    ///
906    /// A value of 1 means "most important," and indicates that the data is
907    /// effectively required, while 0 means "least important," and indicates
908    /// that the data is entirely optional.
909    #[serde(skip_serializing_if = "Option::is_none")]
910    pub priority: Option<f64>,
911}
912
913/// Text provided to or from an LLM.
914#[derive(Debug, Clone, Serialize, Deserialize)]
915pub struct TextContent {
916    /// The text content of the message.
917    pub text: String,
918    /// Optional annotations for the client.
919    #[serde(skip_serializing_if = "Option::is_none")]
920    pub annotations: Option<Annotations>,
921}
922
923/// An image provided to or from an LLM.
924#[derive(Debug, Clone, Serialize, Deserialize)]
925pub struct ImageContent {
926    /// The base64-encoded image data.
927    pub data: String,
928    /// The MIME type of the image. Different providers may support different
929    /// image types.
930    #[serde(rename = "mimeType")]
931    pub mime_type: String,
932    /// Optional annotations for the client.
933    #[serde(skip_serializing_if = "Option::is_none")]
934    pub annotations: Option<Annotations>,
935}
936
937/// Audio provided to or from an LLM.
938#[derive(Debug, Clone, Serialize, Deserialize)]
939pub struct AudioContent {
940    /// The base64-encoded audio data.
941    pub data: String,
942    /// The MIME type of the audio. Different providers may support different
943    /// audio types.
944    #[serde(rename = "mimeType")]
945    pub mime_type: String,
946    /// Optional annotations for the client.
947    #[serde(skip_serializing_if = "Option::is_none")]
948    pub annotations: Option<Annotations>,
949}
950
951/// The server's preferences for model selection, requested of the client during
952/// sampling.
953///
954/// Because LLMs can vary along multiple dimensions, choosing the "best" model
955/// is rarely straightforward.  Different models excel in different areas—some
956/// are faster but less capable, others are more capable but more expensive, and
957/// so on. This interface allows servers to express their priorities across
958/// multiple dimensions to help clients make an appropriate selection for their
959/// use case.
960///
961/// These preferences are always advisory. The client MAY ignore them. It is
962/// also up to the client to decide how to interpret these preferences and how
963/// to balance them against other considerations.
964#[derive(Debug, Clone, Serialize, Deserialize)]
965pub struct ModelPreferences {
966    /// Optional hints to use for model selection.
967    ///
968    /// If multiple hints are specified, the client MUST evaluate them in order
969    /// (such that the first match is taken).
970    ///
971    /// The client SHOULD prioritize these hints over the numeric priorities,
972    /// but MAY still use the priorities to select from ambiguous matches.
973    #[serde(skip_serializing_if = "Option::is_none")]
974    pub hints: Option<Vec<ModelHint>>,
975    /// How much to prioritize cost when selecting a model. A value of 0 means
976    /// cost is not important, while a value of 1 means cost is the most
977    /// important factor.
978    #[serde(rename = "costPriority", skip_serializing_if = "Option::is_none")]
979    pub cost_priority: Option<f64>,
980    /// How much to prioritize sampling speed (latency) when selecting a model.
981    /// A value of 0 means speed is not important, while a value of 1 means
982    /// speed is the most important factor.
983    #[serde(rename = "speedPriority", skip_serializing_if = "Option::is_none")]
984    pub speed_priority: Option<f64>,
985    /// How much to prioritize intelligence and capabilities when selecting a
986    /// model. A value of 0 means intelligence is not important, while a value
987    /// of 1 means intelligence is the most important factor.
988    #[serde(
989        rename = "intelligencePriority",
990        skip_serializing_if = "Option::is_none"
991    )]
992    pub intelligence_priority: Option<f64>,
993}
994
995/// Hints to use for model selection.
996///
997/// Keys not declared here are currently left unspecified by the spec and are up
998/// to the client to interpret.
999#[derive(Debug, Clone, Serialize, Deserialize)]
1000pub struct ModelHint {
1001    /// A hint for a model name.
1002    ///
1003    /// The client SHOULD treat this as a substring of a model name; for
1004    /// example:
1005    ///  - `claude-3-5-sonnet` should match `claude-3-5-sonnet-20241022`
1006    ///  - `sonnet` should match `claude-3-5-sonnet-20241022`,
1007    ///    `claude-3-sonnet-20240229`, etc.
1008    ///  - `claude` should match any Claude model
1009    ///
1010    /// The client MAY also map the string to a different provider's model name
1011    /// or a different model family, as long as it fills a similar niche;
1012    /// for example:
1013    ///  - `gemini-1.5-flash` could match `claude-3-haiku-20240307`
1014    #[serde(skip_serializing_if = "Option::is_none")]
1015    pub name: Option<String>,
1016}
1017
1018// Autocomplete
1019
1020#[derive(Debug, Clone, Serialize, Deserialize)]
1021pub struct ArgumentInfo {
1022    /// The name of the argument
1023    pub name: String,
1024    /// The value of the argument to use for completion matching.
1025    pub value: String,
1026}
1027
1028#[derive(Debug, Clone, Serialize, Deserialize)]
1029#[serde(tag = "type")]
1030pub enum Reference {
1031    #[serde(rename = "ref/resource")]
1032    Resource(ResourceReference),
1033    #[serde(rename = "ref/prompt")]
1034    Prompt(PromptReference),
1035}
1036
1037/// A reference to a resource or resource template definition.
1038#[derive(Debug, Clone, Serialize, Deserialize)]
1039pub struct ResourceReference {
1040    /// The URI or URI template of the resource.
1041    pub uri: String,
1042}
1043
1044/// Identifies a prompt.
1045#[derive(Debug, Clone, Serialize, Deserialize)]
1046pub struct PromptReference {
1047    /// The name of the prompt or prompt template
1048    pub name: String,
1049}
1050
1051/// The server's response to a completion/complete request
1052#[derive(Debug, Clone, Serialize, Deserialize)]
1053pub struct CompleteResult {
1054    pub completion: CompletionInfo,
1055    #[serde(flatten)]
1056    pub result: Result,
1057}
1058
1059#[derive(Debug, Clone, Serialize, Deserialize)]
1060pub struct CompletionInfo {
1061    /// An array of completion values. Must not exceed 100 items.
1062    pub values: Vec<String>,
1063    /// The total number of completion options available. This can exceed the
1064    /// number of values actually sent in the response.
1065    #[serde(skip_serializing_if = "Option::is_none")]
1066    pub total: Option<i64>,
1067    /// Indicates whether there are additional completion options beyond those
1068    /// provided in the current response, even if the exact total is
1069    /// unknown.
1070    #[serde(rename = "hasMore", skip_serializing_if = "Option::is_none")]
1071    pub has_more: Option<bool>,
1072}
1073
1074// Roots
1075
1076/// The client's response to a roots/list request from the server.
1077/// This result contains an array of Root objects, each representing a root
1078/// directory or file that the server can operate on.
1079#[derive(Debug, Clone, Serialize, Deserialize)]
1080pub struct ListRootsResult {
1081    pub roots: Vec<Root>,
1082    #[serde(flatten)]
1083    pub result: Result,
1084}
1085
1086/// Represents a root directory or file that the server can operate on.
1087#[derive(Debug, Clone, Serialize, Deserialize)]
1088pub struct Root {
1089    /// The URI identifying the root. This *must* start with file:// for now.
1090    /// This restriction may be relaxed in future versions of the protocol to
1091    /// allow other URI schemes.
1092    pub uri: String,
1093    /// An optional name for the root. This can be used to provide a
1094    /// human-readable identifier for the root, which may be useful for
1095    /// display purposes or for referencing the root in other parts of the
1096    /// application.
1097    #[serde(skip_serializing_if = "Option::is_none")]
1098    pub name: Option<String>,
1099}
1100
1101/// A notification from the client to the server, informing it that the list of
1102/// roots has changed. This notification should be sent whenever the client
1103/// adds, removes, or modifies any root. The server should then request an
1104/// updated list of roots using the ListRootsRequest.
1105#[derive(Debug, Clone, Serialize, Deserialize)]
1106pub struct RootsListChangedNotification {
1107    pub method: String,
1108}
1109
1110// Client messages
1111#[derive(Debug, Clone, Serialize, Deserialize)]
1112#[serde(tag = "method")]
1113pub enum ClientRequest {
1114    #[serde(rename = "ping")]
1115    Ping,
1116    #[serde(rename = "initialize")]
1117    Initialize {
1118        #[serde(rename = "protocolVersion")]
1119        protocol_version: String,
1120        capabilities: ClientCapabilities,
1121        #[serde(rename = "clientInfo")]
1122        client_info: Implementation,
1123    },
1124    #[serde(rename = "completion/complete")]
1125    Complete {
1126        #[serde(rename = "ref")]
1127        reference: Reference,
1128        /// The argument's information
1129        argument: ArgumentInfo,
1130    },
1131    #[serde(rename = "logging/setLevel")]
1132    SetLevel {
1133        /// The level of logging that the client wants to receive from the
1134        /// server.
1135        level: LoggingLevel,
1136    },
1137    #[serde(rename = "prompts/get")]
1138    GetPrompt {
1139        /// The name of the prompt or prompt template.
1140        name: String,
1141        /// Arguments to use for templating the prompt.
1142        #[serde(skip_serializing_if = "Option::is_none")]
1143        arguments: Option<HashMap<String, String>>,
1144    },
1145    #[serde(rename = "prompts/list")]
1146    ListPrompts,
1147    #[serde(rename = "resources/list")]
1148    ListResources,
1149    #[serde(rename = "resources/templates/list")]
1150    ListResourceTemplates,
1151    #[serde(rename = "resources/read")]
1152    ReadResource {
1153        /// The URI of the resource to read.
1154        uri: String,
1155    },
1156    #[serde(rename = "resources/subscribe")]
1157    Subscribe {
1158        /// The URI of the resource to subscribe to.
1159        uri: String,
1160    },
1161    #[serde(rename = "resources/unsubscribe")]
1162    Unsubscribe {
1163        /// The URI of the resource to unsubscribe from.
1164        uri: String,
1165    },
1166    #[serde(rename = "tools/call")]
1167    CallTool {
1168        name: String,
1169        #[serde(skip_serializing_if = "Option::is_none")]
1170        arguments: Option<HashMap<String, Value>>,
1171    },
1172    #[serde(rename = "tools/list")]
1173    ListTools,
1174}
1175
1176impl ClientRequest {
1177    /// Get the method name for this request
1178    pub fn method(&self) -> &'static str {
1179        match self {
1180            ClientRequest::Ping => "ping",
1181            ClientRequest::Initialize { .. } => "initialize",
1182            ClientRequest::Complete { .. } => "completion/complete",
1183            ClientRequest::SetLevel { .. } => "logging/setLevel",
1184            ClientRequest::GetPrompt { .. } => "prompts/get",
1185            ClientRequest::ListPrompts => "prompts/list",
1186            ClientRequest::ListResources => "resources/list",
1187            ClientRequest::ListResourceTemplates => "resources/templates/list",
1188            ClientRequest::ReadResource { .. } => "resources/read",
1189            ClientRequest::Subscribe { .. } => "resources/subscribe",
1190            ClientRequest::Unsubscribe { .. } => "resources/unsubscribe",
1191            ClientRequest::CallTool { .. } => "tools/call",
1192            ClientRequest::ListTools => "tools/list",
1193        }
1194    }
1195}
1196
1197#[derive(Debug, Clone, Serialize, Deserialize)]
1198#[serde(tag = "method")]
1199pub enum ClientNotification {
1200    #[serde(rename = "notifications/cancelled")]
1201    Cancelled {
1202        /// The ID of the request to cancel.
1203        #[serde(rename = "requestId")]
1204        request_id: RequestId,
1205        /// An optional string describing the reason for the cancellation.
1206        #[serde(skip_serializing_if = "Option::is_none")]
1207        reason: Option<String>,
1208    },
1209    #[serde(rename = "notifications/progress")]
1210    Progress {
1211        /// The progress token which was given in the initial request.
1212        #[serde(rename = "progressToken")]
1213        progress_token: ProgressToken,
1214        /// The progress thus far.
1215        progress: f64,
1216        /// Total number of items to process, if known.
1217        #[serde(skip_serializing_if = "Option::is_none")]
1218        total: Option<f64>,
1219        /// An optional message describing the current progress.
1220        #[serde(skip_serializing_if = "Option::is_none")]
1221        message: Option<String>,
1222    },
1223    #[serde(rename = "notifications/initialized")]
1224    Initialized,
1225    #[serde(rename = "notifications/roots/list_changed")]
1226    RootsListChanged,
1227}
1228
1229#[derive(Debug, Clone, Serialize, Deserialize)]
1230#[serde(untagged)]
1231pub enum ClientResult {
1232    Empty(EmptyResult),
1233    CreateMessage(CreateMessageResult),
1234    ListRoots(ListRootsResult),
1235}
1236
1237// Server messages
1238#[derive(Debug, Clone, Serialize, Deserialize)]
1239#[serde(tag = "method")]
1240pub enum ServerRequest {
1241    #[serde(rename = "ping")]
1242    Ping,
1243    #[serde(rename = "sampling/createMessage")]
1244    CreateMessage(Box<CreateMessageParams>),
1245    #[serde(rename = "roots/list")]
1246    ListRoots,
1247}
1248
1249#[derive(Debug, Clone, Serialize, Deserialize)]
1250#[serde(tag = "method")]
1251pub enum ServerNotification {
1252    #[serde(rename = "notifications/cancelled")]
1253    Cancelled {
1254        /// The ID of the request to cancel.
1255        #[serde(rename = "requestId")]
1256        request_id: RequestId,
1257        /// An optional string describing the reason for the cancellation.
1258        #[serde(skip_serializing_if = "Option::is_none")]
1259        reason: Option<String>,
1260    },
1261    #[serde(rename = "notifications/progress")]
1262    Progress {
1263        /// The progress token which was given in the initial request.
1264        #[serde(rename = "progressToken")]
1265        progress_token: ProgressToken,
1266        /// The progress thus far.
1267        progress: f64,
1268        /// Total number of items to process, if known.
1269        #[serde(skip_serializing_if = "Option::is_none")]
1270        total: Option<f64>,
1271        /// An optional message describing the current progress.
1272        #[serde(skip_serializing_if = "Option::is_none")]
1273        message: Option<String>,
1274    },
1275    #[serde(rename = "notifications/message")]
1276    LoggingMessage {
1277        /// The severity of this log message.
1278        level: LoggingLevel,
1279        /// An optional name of the logger issuing this message.
1280        #[serde(skip_serializing_if = "Option::is_none")]
1281        logger: Option<String>,
1282        /// The data to be logged.
1283        data: Value,
1284    },
1285    #[serde(rename = "notifications/resources/updated")]
1286    ResourceUpdated {
1287        /// The URI of the resource that has been updated.
1288        uri: String,
1289    },
1290    #[serde(rename = "notifications/resources/list_changed")]
1291    ResourceListChanged,
1292    #[serde(rename = "notifications/tools/list_changed")]
1293    ToolListChanged,
1294    #[serde(rename = "notifications/prompts/list_changed")]
1295    PromptListChanged,
1296}
1297
1298#[derive(Debug, Clone, Serialize, Deserialize)]
1299#[serde(untagged)]
1300pub enum ServerResult {
1301    Empty(EmptyResult),
1302    Initialize(InitializeResult),
1303    Complete(CompleteResult),
1304    GetPrompt(GetPromptResult),
1305    ListPrompts(ListPromptsResult),
1306    ListResourceTemplates(ListResourceTemplatesResult),
1307    ListResources(ListResourcesResult),
1308    ReadResource(ReadResourceResult),
1309    CallTool(CallToolResult),
1310    ListTools(ListToolsResult),
1311}