Skip to content

Commit daee3d7

Browse files
heskewclaude
andcommitted
fix: Migrate rmcp 0.8 → 2.1 to resolve RUSTSEC-2026-0189 (MCP DNS rebinding).
API migration for rmcp 2.x: Content → ContentBlock, non-exhaustive model structs built via constructors instead of literals. rmcp now validates the Host header against a loopback-only allowlist by default — the actual DNS-rebinding defense. New --mcp-allowed-hosts flag extends the allowlist for the documented LAN use case (docs/mcp.md updated). Smoke-tested live: initialize handshake OK on loopback and on an allowed LAN host; unlisted Host rejected with 403. cargo audit is now clean, unblocking the weekly image publish. Closes #8 Closes #7 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 103363a commit daee3d7

7 files changed

Lines changed: 145 additions & 60 deletions

File tree

Cargo.lock

Lines changed: 76 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ dirs = "5.0"
189189
# - server: MCP server implementation
190190
# - macros: #[tool] and #[tool_router] derive macros
191191
# - transport-streamable-http-server: HTTP transport with SSE streaming
192-
rmcp = { version = "0.8", features = ["server", "macros", "transport-streamable-http-server"] }
192+
rmcp = { version = "2", features = ["server", "macros", "transport-streamable-http-server"] }
193193

194194
# schemars: JSON Schema generation. Used by rmcp for tool parameter schemas.
195195
schemars = "1.0"

crates/hone-cli/src/cli.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ pub enum Commands {
9696
/// Example: --mcp-port 3001
9797
#[arg(long)]
9898
mcp_port: Option<u16>,
99+
100+
/// Additional Host header values the MCP server accepts (comma-separated)
101+
///
102+
/// The MCP server only accepts loopback hosts by default to block DNS
103+
/// rebinding attacks. For LAN access, list the hostnames or host:port
104+
/// authorities clients will use. Example: --mcp-allowed-hosts pi-hostname
105+
#[arg(long, value_delimiter = ',')]
106+
mcp_allowed_hosts: Vec<String>,
99107
},
100108

101109
/// Show dashboard summary

crates/hone-cli/src/commands/serve.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub async fn cmd_serve(
1414
no_encrypt: bool,
1515
static_dir: Option<&Path>,
1616
mcp_port: Option<u16>,
17+
mcp_allowed_hosts: Vec<String>,
1718
) -> Result<()> {
1819
println!("🚀 Starting Hone web server...");
1920
println!(" Database: {}", db_path.display());
@@ -121,8 +122,11 @@ pub async fn cmd_serve(
121122
if let Some(mcp) = mcp_port {
122123
let mcp_db = db.clone();
123124
let mcp_host = host.to_string();
125+
let mcp_hosts = mcp_allowed_hosts.clone();
124126
tokio::spawn(async move {
125-
if let Err(e) = hone_server::mcp::start_mcp_server(mcp_db, &mcp_host, mcp).await {
127+
if let Err(e) =
128+
hone_server::mcp::start_mcp_server(mcp_db, &mcp_host, mcp, &mcp_hosts).await
129+
{
126130
eprintln!("MCP server error: {}", e);
127131
}
128132
});

crates/hone-cli/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ async fn main() -> Result<()> {
6464
no_auth,
6565
static_dir,
6666
mcp_port,
67+
mcp_allowed_hosts,
6768
} => {
6869
commands::cmd_serve(
6970
&cli.db,
@@ -73,6 +74,7 @@ async fn main() -> Result<()> {
7374
cli.no_encrypt,
7475
static_dir.as_deref(),
7576
mcp_port,
77+
mcp_allowed_hosts,
7678
)
7779
.await
7880
}

0 commit comments

Comments
 (0)