Files
codex/prs/bolinfest/study/PR-1578-study.md
2025-09-02 15:17:45 -07:00

92 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
**DOs**
- **Validate With Stdlib, Not Regex:** Use a tiny helper that matches /^[a-zA-Z0-9_-]+$/ with ASCII checks.
```rust
fn is_valid_mcp_server_name(name: &str) -> bool {
!name.is_empty() && name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
}
```
- **Validate Before Spawning Tasks:** Prefilter invalid servers, record errors, and skip spawning.
```rust
let mut join_set = JoinSet::new();
let mut errors = ClientStartErrors::new();
for (server_name, cfg) in mcp_servers {
if !is_valid_mcp_server_name(&server_name) {
let err = anyhow::anyhow!(
"invalid server name '{}': must match pattern ^[a-zA-Z0-9_-]+$",
server_name
);
errors.insert(server_name, err);
continue;
}
join_set.spawn(async move {
let McpServerConfig { command, args, env } = cfg;
let client_res = McpClient::new_stdio_client(command, args, env).await;
(server_name, client_res)
});
}
```
- **Initialize Error Collection Early:** Create the error map before any async work to capture prespawn failures.
```rust
let mut errors = ClientStartErrors::new(); // before the for-loop
```
- **Emit Clear, Actionable Errors:** Include the bad name and the exact allowed pattern; inline variables in `format!`.
```rust
let msg = format!(
"invalid server name '{}': must match pattern ^[a-zA-Z0-9_-]+$",
server_name
);
let err = anyhow::anyhow!(msg);
```
- **Keep Validation SingleSourced:** Reuse the same helper everywhere you need this check.
```rust
if !is_valid_mcp_server_name(name) { /* handle error */ }
```
**DONTs**
- **Dont Add Unneeded Dependencies:** Skip `regex`/`regex-lite` (and related helpers) for simple ASCII checks.
```toml
# Cargo.toml — avoid adding a regex dependency just for this
[dependencies]
# regex-lite = "0.1" # ← Dont add for this use case
```
- **Dont Spawn For Invalid Names:** Never launch a client task if validation fails.
```rust
// BAD: spawns even when name is invalid
join_set.spawn(async move { /* ... */ }); // without pre-check
// GOOD: guarded by is_valid_mcp_server_name (see DOs)
```
- **Dont Allow Empty Or Punctuated Names:** Reject empty strings and names with spaces or symbols.
```rust
assert!(is_valid_mcp_server_name("abc-123"));
assert!(is_valid_mcp_server_name("abc_123"));
assert!(!is_valid_mcp_server_name("")); // empty
assert!(!is_valid_mcp_server_name("abc 123")); // space
assert!(!is_valid_mcp_server_name("abc$123")); // symbol
```
- **Dont Emit Vague Errors:** Avoid messages that fail to guide users.
```rust
// BAD
anyhow::bail!("invalid name");
// GOOD
anyhow::bail!(
"invalid server name '{}': must match pattern ^[a-zA-Z0-9_-]+$",
server_name
);
```
- **Dont Duplicate Validation Logic:** Centralize the rule in one helper to prevent drift.
```rust
// BAD: multiple ad-hoc checks scattered around
// GOOD: call is_valid_mcp_server_name(...) everywhere
```