use crate::mcp::auth::McpCredential;
use crate::{
McpElicitationPolicy, McpProtocolMode, McpServerAuthMode, McpToolCallResult, McpToolDefinition,
};
use async_trait::async_trait;
use everruns_contracts::ConnectionRequired;
use serde_json::Value;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub enum McpEndpoint {
Http {
url: String,
headers: HashMap<String, String>,
},
#[cfg(feature = "mcp-stdio")]
Stdio {
command: String,
args: Vec<String>,
env: HashMap<String, String>,
},
}
#[derive(Debug, Clone)]
pub struct McpConnection {
pub name: String,
pub endpoint: McpEndpoint,
pub auth_mode: McpServerAuthMode,
pub protocol_mode: McpProtocolMode,
pub elicitation_policy: McpElicitationPolicy,
pub oauth_provider_id: Option<String>,
pub pending_oauth_provider: Option<ConnectionRequired>,
pub secret_bindings: HashMap<String, Vec<McpSecretBinding>>,
}
#[derive(Clone)]
pub struct McpSecretBinding {
pub parameter_name: String,
pub value: Option<String>,
pub setup_url: String,
pub label: String,
}
impl std::fmt::Debug for McpSecretBinding {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("McpSecretBinding")
.field("parameter_name", &self.parameter_name)
.field("configured", &self.value.is_some())
.field("setup_url", &self.setup_url)
.field("label", &self.label)
.finish()
}
}
impl McpConnection {
pub fn http(name: impl Into<String>, url: impl Into<String>) -> Self {
Self {
name: name.into(),
endpoint: McpEndpoint::Http {
url: url.into(),
headers: HashMap::new(),
},
auth_mode: McpServerAuthMode::None,
protocol_mode: McpProtocolMode::Auto,
elicitation_policy: McpElicitationPolicy::Url,
oauth_provider_id: None,
pending_oauth_provider: None,
secret_bindings: HashMap::new(),
}
}
pub fn with_protocol_mode(mut self, mode: McpProtocolMode) -> Self {
self.protocol_mode = mode;
self
}
pub fn with_elicitation_policy(mut self, policy: McpElicitationPolicy) -> Self {
self.elicitation_policy = policy;
self
}
}
#[async_trait]
pub trait McpTransport: Send + Sync {
async fn list_tools(
&self,
connection: &McpConnection,
credential: Option<&McpCredential>,
) -> anyhow::Result<Vec<McpToolDefinition>>;
async fn call_tool(
&self,
connection: &McpConnection,
tool_name: &str,
arguments: Value,
credential: Option<&McpCredential>,
) -> anyhow::Result<McpToolCallResult>;
}