feat: MCP support for agentic CLI providers (#6972)

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Adrian Cole
2026-02-12 07:37:52 +08:00
committed by GitHub
parent c6e27b8f84
commit 8d59c2dced
57 changed files with 1196 additions and 254 deletions
+13 -8
View File
@@ -21,9 +21,8 @@ use goose::model::ModelConfig;
use goose::providers::create;
use goose::recipe::Recipe;
use goose::recipe_deeplink;
use goose::session::extension_data::ExtensionState;
use goose::session::session_manager::SessionType;
use goose::session::{EnabledExtensionsState, Session};
use goose::session::{EnabledExtensionsState, ExtensionState, Session};
use goose::{
agents::{extension::ToolInfo, extension_manager::get_parameter_names},
config::permission::PermissionLevel,
@@ -553,12 +552,18 @@ async fn update_agent_provider(
.with_context_limit(payload.context_limit)
.with_request_params(payload.request_params);
let new_provider = create(&payload.provider, model_config).await.map_err(|e| {
(
StatusCode::BAD_REQUEST,
format!("Failed to create {} provider: {}", &payload.provider, e),
)
})?;
let extensions =
EnabledExtensionsState::for_session(state.session_manager(), &payload.session_id, config)
.await;
let new_provider = create(&payload.provider, model_config, extensions)
.await
.map_err(|e| {
(
StatusCode::BAD_REQUEST,
format!("Failed to create {} provider: {}", &payload.provider, e),
)
})?;
agent
.update_provider(new_provider, &payload.session_id)
@@ -387,7 +387,7 @@ pub async fn get_provider_models(
}
let model_config = ModelConfig::new(&metadata.default_model)?;
let provider = goose::providers::create(&name, model_config).await?;
let provider = goose::providers::create(&name, model_config, Vec::new()).await?;
let models_result = provider.fetch_recommended_models().await;
@@ -747,9 +747,12 @@ pub async fn update_custom_provider(
pub async fn check_provider(
Json(CheckProviderRequest { provider }): Json<CheckProviderRequest>,
) -> Result<(), ErrorResponse> {
create_with_default_model(&provider).await.map_err(|err| {
ErrorResponse::bad_request(format!("Provider '{}' check failed: {}", provider, err))
})?;
// Provider check does not use extensions.
create_with_default_model(&provider, Vec::new())
.await
.map_err(|err| {
ErrorResponse::bad_request(format!("Provider '{}' check failed: {}", provider, err))
})?;
Ok(())
}
@@ -761,7 +764,8 @@ pub async fn check_provider(
pub async fn set_config_provider(
Json(SetProviderRequest { provider, model }): Json<SetProviderRequest>,
) -> Result<(), ErrorResponse> {
create_with_default_model(&provider)
// Provider validation does not use extensions.
create_with_default_model(&provider, Vec::new())
.await
.and_then(|_| {
let config = Config::global();
@@ -807,12 +811,15 @@ pub async fn configure_provider_oauth(
ErrorResponse::bad_request(format!("Failed to create temporary model config: {}", e))
})?;
let provider = create(&provider_name, temp_model).await.map_err(|e| {
ErrorResponse::bad_request(format!(
"Failed to create provider '{}': {}",
provider_name, e
))
})?;
// OAuth configuration does not use extensions.
let provider = create(&provider_name, temp_model, Vec::new())
.await
.map_err(|e| {
ErrorResponse::bad_request(format!(
"Failed to create provider '{}': {}",
provider_name, e
))
})?;
provider.configure_oauth().await.map_err(|e| {
ErrorResponse::bad_request(format!(
+4 -5
View File
@@ -11,7 +11,6 @@ use axum::{
};
use goose::agents::ExtensionConfig;
use goose::recipe::Recipe;
use goose::session::extension_data::ExtensionState;
use goose::session::session_manager::SessionInsights;
use goose::session::{EnabledExtensionsState, Session};
use serde::{Deserialize, Serialize};
@@ -481,10 +480,10 @@ async fn get_session_extensions(
.await
.map_err(|_| StatusCode::NOT_FOUND)?;
// Try to get session-specific extensions, fall back to global config
let extensions = EnabledExtensionsState::from_extension_data(&session.extension_data)
.map(|state| state.extensions)
.unwrap_or_else(goose::config::get_enabled_extensions);
let extensions = EnabledExtensionsState::extensions_or_default(
Some(&session.extension_data),
goose::config::Config::global(),
);
Ok(Json(SessionExtensionsResponse { extensions }))
}