← ./articles-ja

rmcpのStreamableHttpServerConfigはstruct literalではなくbuilderで作る

Rustの #[non_exhaustive] は邪魔な制約ではありません。API contractの一部です。

rmcpStreamableHttpServerConfig はnon-exhaustive structです。別crateからstruct literalで作ろうとすると、compilerが止めます。正しい方法は、用意されたbuilder-style methodを使うことです。

症状: struct literalでconfigを作れない

壊れる形です。

let config = StreamableHttpServerConfig {
    allowed_hosts: vec!["localhost".to_string()],
};

non-exhaustive structでは、downstream crateが全fieldを知っている前提で構築できません。将来fieldが増えても、builder経由のcodeを壊しにくくするためです。

compilerと戦わず、公開された構築手段を使います。

defaultとwith_allowed_hostsを使う

default() とbuilder methodを使います。

use rmcp::transport::streamable_http_server::tower::StreamableHttpServerConfig;

let config = StreamableHttpServerConfig::default()
    .with_allowed_hosts(["localhost", "127.0.0.1", "::1"]);

crateが想定しているconfiguration surfaceに乗る形です。

DNS rebinding対策を明示する

allowed hostsは単なる便利設定ではありません。HTTP serverのDNS rebinding protectionに関わります。

defaultがloopbackに制限しているとしても、call siteで明示するとreviewしやすくなります。

let allowed_hosts = ["localhost", "127.0.0.1", "::1"];

let config = StreamableHttpServerConfig::default()
    .with_allowed_hosts(allowed_hosts);

library defaultに隠すより、security boundaryが読みやすくなります。

hostを安易に広げない

注意する値です。

  • 0.0.0.0
  • LAN IP
  • wildcard host
  • reverse proxyのhost rewrite
  • public tunnel

MCP serverをlocal-onlyにするなら、allowlistもそう示すべきです。loopback外へ公開するなら、authenticationとnetwork boundaryを別途設計します。

MCP serverではconfigもsecurity code

MCP toolはlocal file、project state、log、privileged actionを扱うことがあります。transport configのミスで、local integrationがnetwork endpointになります。

誰が接続できるかを決める設定は、security codeです。

検証チェック

  • clean checkoutでcompileする
  • non-exhaustive configをstruct literalで作っていない
  • allowed hostsを明示している
  • localhost127.0.0.1、許可していないhostをテストする
  • serverがloopback-onlyかdocumentする
  • local MCP serverをtunnel公開する前に別途security reviewする

参考