Skip to content

Commit d9f7764

Browse files
committed
fix(cli): include path in mcp config parse errors
1 parent 7954d02 commit d9f7764

3 files changed

Lines changed: 29 additions & 15 deletions

File tree

src/cortex-cli/src/agent_cmd/tests.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
#[cfg(test)]
44
mod tests {
55
use crate::agent_cmd::cli::{CopyArgs, ExportArgs};
6-
use crate::agent_cmd::loader::{
7-
load_builtin_agents, parse_frontmatter, read_file_with_encoding,
8-
};
6+
use crate::agent_cmd::loader::{load_builtin_agents, parse_frontmatter};
97
use crate::agent_cmd::types::AgentMode;
8+
use crate::utils::file::read_file_with_encoding;
109

1110
#[test]
1211
fn test_read_file_with_utf8() {

src/cortex-cli/src/mcp_cmd/config.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
66
use anyhow::{Context, Result};
77
use cortex_engine::config::find_cortex_home;
8+
use std::path::Path;
9+
10+
/// Parse MCP config TOML with the file path included in parse errors.
11+
pub(crate) fn parse_config_content(content: &str, config_path: &Path) -> Result<toml::Value> {
12+
toml::from_str(content)
13+
.with_context(|| format!("failed to parse config: {}", config_path.display()))
14+
}
815

916
/// Load the config file as a toml::Value.
1017
pub(crate) fn load_config() -> Result<Option<toml::Value>> {
@@ -19,7 +26,7 @@ pub(crate) fn load_config() -> Result<Option<toml::Value>> {
1926
let content = std::fs::read_to_string(&config_path)
2027
.with_context(|| format!("failed to read config: {}", config_path.display()))?;
2128

22-
let config: toml::Value = toml::from_str(&content).with_context(|| "failed to parse config")?;
29+
let config = parse_config_content(&content, &config_path)?;
2330

2431
Ok(Some(config))
2532
}
@@ -87,4 +94,17 @@ mod tests {
8794
assert!(result.is_ok());
8895
assert!(result.unwrap().is_none());
8996
}
97+
98+
#[test]
99+
fn test_parse_config_content_error_includes_path() {
100+
let config_path = std::path::PathBuf::from("custom-cortex-home/config.toml");
101+
let err = parse_config_content("invalid = [unclosed", &config_path)
102+
.expect_err("invalid TOML should fail");
103+
let message = err.to_string();
104+
105+
assert!(
106+
message.contains("failed to parse config: custom-cortex-home/config.toml"),
107+
"error should include config path, got: {message}"
108+
);
109+
}
90110
}

src/cortex-cli/src/mcp_cmd/handlers.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use cortex_engine::config::find_cortex_home;
88
use std::io::{self, BufRead, Write};
99

1010
use super::auth::{get_auth_status_for_display, remove_auth_silent};
11-
use super::config::{get_mcp_server, get_mcp_servers};
11+
use super::config::{get_mcp_server, get_mcp_servers, parse_config_content};
1212
use super::types::{
1313
AddArgs, AddMcpSseArgs, AddMcpStreamableHttpArgs, AddMcpTransportArgs, DisableArgs, EnableArgs,
1414
GetArgs, ListArgs, RemoveArgs, RenameArgs,
@@ -301,8 +301,7 @@ pub(crate) async fn run_add(args: AddArgs) -> Result<()> {
301301
if config_path.exists() {
302302
let content = std::fs::read_to_string(&config_path)
303303
.with_context(|| format!("failed to read config: {}", config_path.display()))?;
304-
let mut config: toml::Value =
305-
toml::from_str(&content).with_context(|| "failed to parse config")?;
304+
let mut config = parse_config_content(&content, &config_path)?;
306305

307306
if let Some(mcp_servers) = config.get_mut("mcp_servers").and_then(|v| v.as_table_mut())
308307
{
@@ -576,8 +575,7 @@ pub(crate) async fn run_remove(args: RemoveArgs) -> Result<()> {
576575
.with_context(|| format!("failed to read config: {}", config_path.display()))?;
577576

578577
// Parse the TOML and remove the server section
579-
let mut config: toml::Value =
580-
toml::from_str(&content).with_context(|| "failed to parse config")?;
578+
let mut config = parse_config_content(&content, &config_path)?;
581579

582580
if let Some(mcp_servers) = config.get_mut("mcp_servers").and_then(|v| v.as_table_mut()) {
583581
mcp_servers.remove(&name);
@@ -622,8 +620,7 @@ pub(crate) async fn run_enable(args: EnableArgs) -> Result<()> {
622620
let content = std::fs::read_to_string(&config_path)
623621
.with_context(|| format!("failed to read config: {}", config_path.display()))?;
624622

625-
let mut config: toml::Value =
626-
toml::from_str(&content).with_context(|| "failed to parse config")?;
623+
let mut config = parse_config_content(&content, &config_path)?;
627624

628625
if let Some(mcp_servers) = config.get_mut("mcp_servers").and_then(|v| v.as_table_mut())
629626
&& let Some(server) = mcp_servers.get_mut(&args.name)
@@ -674,8 +671,7 @@ pub(crate) async fn run_disable(args: DisableArgs) -> Result<()> {
674671
let content = std::fs::read_to_string(&config_path)
675672
.with_context(|| format!("failed to read config: {}", config_path.display()))?;
676673

677-
let mut config: toml::Value =
678-
toml::from_str(&content).with_context(|| "failed to parse config")?;
674+
let mut config = parse_config_content(&content, &config_path)?;
679675

680676
if let Some(mcp_servers) = config.get_mut("mcp_servers").and_then(|v| v.as_table_mut())
681677
&& let Some(server) = mcp_servers.get_mut(&args.name)
@@ -740,8 +736,7 @@ pub(crate) async fn run_rename(args: RenameArgs) -> Result<()> {
740736
let content = std::fs::read_to_string(&config_path)
741737
.with_context(|| format!("failed to read config: {}", config_path.display()))?;
742738

743-
let mut config: toml::Value =
744-
toml::from_str(&content).with_context(|| "failed to parse config")?;
739+
let mut config = parse_config_content(&content, &config_path)?;
745740

746741
if let Some(mcp_servers) = config.get_mut("mcp_servers").and_then(|v| v.as_table_mut())
747742
&& let Some(server_config) = mcp_servers.remove(&args.old_name)

0 commit comments

Comments
 (0)