mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-19 07:04:21 +01:00
Add support in goose configure for streaming http mcp tools (#3256)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -498,8 +498,13 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
|||||||
)
|
)
|
||||||
.item(
|
.item(
|
||||||
"sse",
|
"sse",
|
||||||
"Remote Extension",
|
"Remote Extension (SSE)",
|
||||||
"Connect to a remote extension via SSE",
|
"Connect to a remote extension via Server-Sent Events",
|
||||||
|
)
|
||||||
|
.item(
|
||||||
|
"streamable_http",
|
||||||
|
"Remote Extension (Streaming HTTP)",
|
||||||
|
"Connect to a remote extension via MCP Streaming HTTP",
|
||||||
)
|
)
|
||||||
.interact()?;
|
.interact()?;
|
||||||
|
|
||||||
@@ -767,6 +772,133 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
cliclack::outro(format!("Added {} extension", style(name).green()))?;
|
cliclack::outro(format!("Added {} extension", style(name).green()))?;
|
||||||
}
|
}
|
||||||
|
"streamable_http" => {
|
||||||
|
let extensions = ExtensionConfigManager::get_all_names()?;
|
||||||
|
let name: String = cliclack::input("What would you like to call this extension?")
|
||||||
|
.placeholder("my-remote-extension")
|
||||||
|
.validate(move |input: &String| {
|
||||||
|
if input.is_empty() {
|
||||||
|
Err("Please enter a name")
|
||||||
|
} else if extensions.contains(input) {
|
||||||
|
Err("An extension with this name already exists")
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
let uri: String = cliclack::input("What is the Streaming HTTP endpoint URI?")
|
||||||
|
.placeholder("http://localhost:8000/messages")
|
||||||
|
.validate(|input: &String| {
|
||||||
|
if input.is_empty() {
|
||||||
|
Err("Please enter a URI")
|
||||||
|
} else if !(input.starts_with("http://") || input.starts_with("https://")) {
|
||||||
|
Err("URI should start with http:// or https://")
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
let timeout: u64 = cliclack::input("Please set the timeout for this tool (in secs):")
|
||||||
|
.placeholder(&goose::config::DEFAULT_EXTENSION_TIMEOUT.to_string())
|
||||||
|
.validate(|input: &String| match input.parse::<u64>() {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(_) => Err("Please enter a valid timeout"),
|
||||||
|
})
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
let add_desc = cliclack::confirm("Would you like to add a description?").interact()?;
|
||||||
|
|
||||||
|
let description = if add_desc {
|
||||||
|
let desc = cliclack::input("Enter a description for this extension:")
|
||||||
|
.placeholder("Description")
|
||||||
|
.validate(|input: &String| {
|
||||||
|
if input.trim().is_empty() {
|
||||||
|
Err("Please enter a valid description")
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.interact()?;
|
||||||
|
Some(desc)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let add_headers =
|
||||||
|
cliclack::confirm("Would you like to add custom headers?").interact()?;
|
||||||
|
|
||||||
|
let mut headers = HashMap::new();
|
||||||
|
if add_headers {
|
||||||
|
loop {
|
||||||
|
let key: String = cliclack::input("Header name:")
|
||||||
|
.placeholder("Authorization")
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
let value: String = cliclack::input("Header value:")
|
||||||
|
.placeholder("Bearer token123")
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
headers.insert(key, value);
|
||||||
|
|
||||||
|
if !cliclack::confirm("Add another header?").interact()? {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let add_env = false; // No env prompt for Streaming HTTP
|
||||||
|
|
||||||
|
let mut envs = HashMap::new();
|
||||||
|
let mut env_keys = Vec::new();
|
||||||
|
let config = Config::global();
|
||||||
|
|
||||||
|
if add_env {
|
||||||
|
loop {
|
||||||
|
let key: String = cliclack::input("Environment variable name:")
|
||||||
|
.placeholder("API_KEY")
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
let value: String = cliclack::password("Environment variable value:")
|
||||||
|
.mask('▪')
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
// Try to store in keychain
|
||||||
|
let keychain_key = key.to_string();
|
||||||
|
match config.set_secret(&keychain_key, Value::String(value.clone())) {
|
||||||
|
Ok(_) => {
|
||||||
|
// Successfully stored in keychain, add to env_keys
|
||||||
|
env_keys.push(keychain_key);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// Failed to store in keychain, store directly in envs
|
||||||
|
envs.insert(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cliclack::confirm("Add another environment variable?").interact()? {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtensionConfigManager::set(ExtensionEntry {
|
||||||
|
enabled: true,
|
||||||
|
config: ExtensionConfig::StreamableHttp {
|
||||||
|
name: name.clone(),
|
||||||
|
uri,
|
||||||
|
envs: Envs::new(envs),
|
||||||
|
env_keys,
|
||||||
|
headers,
|
||||||
|
description,
|
||||||
|
timeout: Some(timeout),
|
||||||
|
bundled: None,
|
||||||
|
},
|
||||||
|
})?;
|
||||||
|
|
||||||
|
cliclack::outro(format!("Added {} extension", style(name).green()))?;
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user