fix(mcp): make bind_loopback/serve/HttpServerHandle pub for the e2e test (T10.4)

Widens visibility from pub(crate) to pub so tests/mcp_server_test.rs
(an external integration-test crate, per CLAUDE.md's "cross-service
tests in /tests") can drive the real HTTP transport end-to-end. This
does not weaken the loopback guarantee: bind_loopback still refuses
non-loopback regardless of caller -- only its visibility changed.
This commit is contained in:
iamdoubz
2026-07-07 00:47:55 -05:00
parent e424ecd8d3
commit 71824d44cc
+3 -3
View File
@@ -25,7 +25,7 @@ use tokio_util::sync::CancellationToken;
/// listening socket for MCP (FR-MCP-1, NFR-SEC-5). Kept generic over `host`
/// purely so the refusal path is directly unit-testable; the only production
/// caller (`mcp::server`) always passes `"127.0.0.1"`.
pub(crate) async fn bind_loopback(host: &str, port: u16) -> Result<TcpListener, McpError> {
pub async fn bind_loopback(host: &str, port: u16) -> Result<TcpListener, McpError> {
let ip: IpAddr = host.parse().map_err(|_| McpError::NonLoopback)?;
if !ip.is_loopback() {
return Err(McpError::NonLoopback);
@@ -37,7 +37,7 @@ pub(crate) async fn bind_loopback(host: &str, port: u16) -> Result<TcpListener,
/// A running HTTP server; `stop()` cancels the accept loop and all live
/// connections and waits for cleanup.
pub(crate) struct HttpServerHandle {
pub struct HttpServerHandle {
pub local_addr: SocketAddr,
shutdown: CancellationToken,
join: tokio::task::JoinHandle<()>,
@@ -54,7 +54,7 @@ impl HttpServerHandle {
/// routing) on an already-bound loopback listener. Every request must present
/// `Authorization: Bearer <token>` matching the stored token (constant-time
/// compare, `mcp::token::verify`) or it never reaches `rmcp`.
pub(crate) fn serve(
pub fn serve(
listener: TcpListener,
expected_token: String,
handler: WaMcpHandler,