@@ -3,7 +3,7 @@ use crate::acp::fs::AcpTools;
33use crate :: acp:: tools:: AcpAwareToolMeta ;
44use crate :: acp:: { PermissionDecision , ACP_CURRENT_MODEL } ;
55use crate :: agents:: extension:: { Envs , PLATFORM_EXTENSIONS } ;
6- use crate :: agents:: mcp_client:: McpClientTrait ;
6+ use crate :: agents:: mcp_client:: { GooseMcpHostInfo , McpClientTrait } ;
77use crate :: agents:: platform_extensions:: developer:: DeveloperClient ;
88use crate :: agents:: { Agent , AgentConfig , ExtensionConfig , GoosePlatform , SessionConfig } ;
99use crate :: config:: base:: CONFIG_YAML_NAME ;
@@ -59,6 +59,7 @@ use sacp::{
5959 Agent as SacpAgent , ByteStreams , Client , ConnectionTo , Dispatch , HandleDispatchFrom , Handled ,
6060 Responder ,
6161} ;
62+ use serde:: Deserialize ;
6263use std:: collections:: HashMap ;
6364use std:: sync:: Arc ;
6465use strum:: { EnumMessage , VariantNames } ;
@@ -182,13 +183,15 @@ pub struct GooseAcpAgent {
182183 builtins : Vec < String > ,
183184 client_fs_capabilities : OnceCell < FileSystemCapabilities > ,
184185 client_terminal : OnceCell < bool > ,
186+ client_mcp_host_info : OnceCell < GooseMcpHostInfo > ,
185187 config_dir : std:: path:: PathBuf ,
186188 session_manager : Arc < SessionManager > ,
187189 thread_manager : Arc < crate :: session:: ThreadManager > ,
188190 permission_manager : Arc < PermissionManager > ,
189191 goose_mode : GooseMode ,
190192 disable_session_naming : bool ,
191193 provider_inventory : ProviderInventoryService ,
194+ goose_platform : GoosePlatform ,
192195}
193196
194197/// Shorten a session/thread id for perf log correlation.
@@ -253,6 +256,52 @@ fn extract_timeout_from_meta(meta: &Option<Meta>) -> Option<u64> {
253256 . and_then ( |v| v. as_u64 ( ) )
254257}
255258
259+ #[ derive( Debug , Default , Deserialize ) ]
260+ struct GooseClientMetaEnvelope {
261+ #[ serde( default ) ]
262+ goose : Option < GooseClientMeta > ,
263+ }
264+
265+ #[ derive( Debug , Default , Deserialize ) ]
266+ struct GooseClientMeta {
267+ #[ serde( rename = "mcpHostCapabilities" , default ) ]
268+ mcp_host_capabilities : Option < GooseMcpHostCapabilities > ,
269+ }
270+
271+ #[ derive( Debug , Default , Deserialize ) ]
272+ struct GooseMcpHostCapabilities {
273+ #[ serde( default ) ]
274+ extensions : Option < rmcp:: model:: ExtensionCapabilities > ,
275+ }
276+
277+ fn extract_goose_client_meta ( meta : & Meta ) -> Option < GooseClientMetaEnvelope > {
278+ serde_json:: from_value ( serde_json:: Value :: Object ( meta. clone ( ) ) ) . ok ( )
279+ }
280+
281+ fn extract_client_mcp_host_info ( args : & InitializeRequest ) -> GooseMcpHostInfo {
282+ let host_capabilities = args
283+ . client_capabilities
284+ . meta
285+ . as_ref ( )
286+ . and_then ( extract_goose_client_meta)
287+ . and_then ( |meta| meta. goose )
288+ . and_then ( |goose| goose. mcp_host_capabilities ) ;
289+ let explicit_extensions = host_capabilities
290+ . as_ref ( )
291+ . and_then ( |capabilities| capabilities. extensions . as_ref ( ) )
292+ . is_some ( ) ;
293+ let extensions = host_capabilities
294+ . and_then ( |capabilities| capabilities. extensions )
295+ . unwrap_or_default ( ) ;
296+
297+ GooseMcpHostInfo {
298+ explicit_extensions,
299+ extensions,
300+ client_name : args. client_info . as_ref ( ) . map ( |info| info. name . clone ( ) ) ,
301+ client_version : args. client_info . as_ref ( ) . map ( |info| info. version . clone ( ) ) ,
302+ }
303+ }
304+
256305fn mcp_server_to_extension_config ( mcp_server : McpServer ) -> Result < ExtensionConfig , String > {
257306 match mcp_server {
258307 McpServer :: Stdio ( stdio) => {
@@ -795,6 +844,7 @@ impl GooseAcpAgent {
795844 config_dir : std:: path:: PathBuf ,
796845 goose_mode : GooseMode ,
797846 disable_session_naming : bool ,
847+ goose_platform : GoosePlatform ,
798848 ) -> Result < Self > {
799849 let session_manager = Arc :: new ( SessionManager :: new ( data_dir) ) ;
800850 let thread_manager = Arc :: new ( crate :: session:: ThreadManager :: new (
@@ -809,13 +859,15 @@ impl GooseAcpAgent {
809859 builtins,
810860 client_fs_capabilities : OnceCell :: new ( ) ,
811861 client_terminal : OnceCell :: new ( ) ,
862+ client_mcp_host_info : OnceCell :: new ( ) ,
812863 config_dir,
813864 session_manager,
814865 thread_manager,
815866 permission_manager,
816867 goose_mode,
817868 disable_session_naming,
818869 provider_inventory,
870+ goose_platform,
819871 } )
820872 }
821873
@@ -986,12 +1038,14 @@ impl GooseAcpAgent {
9861038 . cloned ( )
9871039 . unwrap_or_default ( ) ;
9881040 let client_terminal = self . client_terminal . get ( ) . copied ( ) . unwrap_or ( false ) ;
1041+ let client_mcp_host_info = self . client_mcp_host_info . get ( ) . cloned ( ) ;
9891042 let provider_factory = Arc :: clone ( & self . provider_factory ) ;
9901043 let disable_session_naming = self . disable_session_naming ;
1044+ let goose_platform = self . goose_platform . clone ( ) ;
9911045
9921046 tokio:: spawn ( async move {
9931047 let t_setup = std:: time:: Instant :: now ( ) ;
994-
1048+ debug ! ( target : "perf" , sid = %sid , "perf: agent_setup start (background)" ) ;
9951049 // Shared config — read once, used by both phases.
9961050 let config = match Config :: new ( config_dir. join ( CONFIG_YAML_NAME ) , "goose" ) {
9971051 Ok ( c) => c,
@@ -1005,14 +1059,17 @@ impl GooseAcpAgent {
10051059
10061060 // ── Phase 1: create agent + init provider (fast, ~55ms) ──────
10071061 let phase1: Result < Arc < Agent > , String > = async {
1008- let agent = Arc :: new ( Agent :: with_config ( AgentConfig :: new (
1009- session_manager,
1010- permission_manager,
1011- None ,
1012- goose_mode,
1013- disable_session_naming,
1014- GoosePlatform :: GooseCli ,
1015- ) ) ) ;
1062+ let agent = Arc :: new ( Agent :: with_config (
1063+ AgentConfig :: new (
1064+ session_manager,
1065+ permission_manager,
1066+ None ,
1067+ goose_mode,
1068+ disable_session_naming,
1069+ goose_platform,
1070+ )
1071+ . with_mcp_host_info ( client_mcp_host_info) ,
1072+ ) ) ;
10161073
10171074 // Init provider — reuse the pre-resolved name + model when
10181075 // available (already computed in on_new_session), otherwise
@@ -1627,6 +1684,9 @@ impl GooseAcpAgent {
16271684 . client_fs_capabilities
16281685 . set ( args. client_capabilities . fs . clone ( ) ) ;
16291686 let _ = self . client_terminal . set ( args. client_capabilities . terminal ) ;
1687+ let _ = self
1688+ . client_mcp_host_info
1689+ . set ( extract_client_mcp_host_info ( & args) ) ;
16301690
16311691 let capabilities = AgentCapabilities :: new ( )
16321692 . load_session ( true )
@@ -3962,6 +4022,7 @@ pub async fn run(builtins: Vec<String>) -> Result<()> {
39624022 builtins,
39634023 data_dir : Paths :: data_dir ( ) ,
39644024 config_dir : Paths :: config_dir ( ) ,
4025+ goose_platform : GoosePlatform :: GooseCli ,
39654026 } ,
39664027 ) ;
39674028 let agent = server. create_agent ( ) . await ?;
0 commit comments