<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>MCP on Code is cheap, let&#39;s talk</title>
    <link>https://blog.ferstar.org/en/tags/mcp/</link>
    <description>Code is cheap, let&#39;s talk</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>© 2026 ferstar · [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)</copyright>
    <lastBuildDate>Mon, 31 Aug 2026 23:41:00 +0800</lastBuildDate>
    <ttl>60</ttl><atom:link href="https://blog.ferstar.org/en/tags/mcp/index.xml" rel="self" type="application/rss+xml" /><image>
      <url>https://blog.ferstar.org/site-logo.png</url>
      <title>Code is cheap, let&#39;s talk</title>
      <link>https://blog.ferstar.org/</link>
    </image>
    
    <item>
      <title>Optional Plugins Must Not Block the Core Session: MCP Startup Isolation and Graceful Degradation</title>
      <link>https://blog.ferstar.org/en/posts/mcp-server-startup-isolation-and-graceful-degradation/</link>
      <pubDate>Mon, 31 Aug 2026 23:41:00 +0800</pubDate>
      
      <guid isPermaLink="true">https://blog.ferstar.org/en/posts/mcp-server-startup-isolation-and-graceful-degradation/</guid>
      <description>A single timeout or crash across configured MCP servers can fatally crash an entire agent session during startup; design service-level criticality contracts, concurrent startup sandboxes, and dynamic tool filtering; achieve resilient fault isolation and seamless degradation for non-essential external tools.</description><content:encoded><![CDATA[<blockquote><p>I am not a native English speaker; this article was translated by AI.</p>
</blockquote><p>With the Model Context Protocol (MCP) becoming widely adopted, attaching multiple local or remote MCP servers to an agent runtime is standard practice.</p>
<p>In real workloads, however, running multiple MCP servers quickly exposes a fragility issue:</p>
<blockquote><p><strong>You have five MCP servers in your configuration. Four core local tools for filesystem and terminal work are healthy, but an optional third-party translation or web search server times out or fails due to a local dependency mismatch.</strong></p>
<p><strong>The entire agent runtime panics during initialization. You cannot even ask basic questions or edit local files.</strong></p>
</blockquote><p>A non-essential auxiliary plugin crash shouldn’t take down the entire core session.</p>
<p>To resolve this, we introduced concurrent startup isolation and graceful degradation for MCP services.</p>
<pre class="not-prose mermaid">
flowchart TD
  subgraph Config[MCP Service Criticality]
    C1[Critical: Local Filesystem & Terminal]
    C2[Optional: Remote Knowledge & Search]
  end

  subgraph Startup[Concurrent Isolation Sandbox]
    C1 --> T1[Tokio Task 1: Critical Service, Strict Validation]
    C2 --> T2[Tokio Task 2: Isolated 3s Timeout]
    C2 --> T3[Tokio Task 3: Isolated 3s Timeout]
  end

  subgraph Outcome[Aggregation & Dynamic Degradation]
    T1 -->|Success| R[Dynamic Tool Registry]
    T2 -->|Timeout / Error| D[Log Diagnostic Warning, Don't Block]
    T3 -->|Success| R
    D -.->|Filter Unavailable Tools| R
    R --> S[Session Launches Cleanly / UI Notice: Degraded Mode]
  end

  Config --> Startup
</pre>

<hr>

<h2 class="relative group">1. What Was Wrong With the Legacy Flow?
    <div id="1-what-was-wrong-with-the-legacy-flow" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#1-what-was-wrong-with-the-legacy-flow" aria-label="Anchor">#</a>
    </span>
    
</h2>
<p>Many MCP clients initialize servers via a simple sequential loop:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">// Fragile serial loop
</span></span></span><span class="line"><span class="cl"><span class="k">for</span><span class="w"> </span><span class="n">server_config</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">mcp_servers</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// If any connect or list_tools call fails, the entire setup returns Err
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">McpClient</span>::<span class="n">connect</span><span class="p">(</span><span class="o">&</span><span class="n">server_config</span><span class="p">).</span><span class="k">await</span><span class="o">?</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">tools</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">client</span><span class="p">.</span><span class="n">list_tools</span><span class="p">().</span><span class="k">await</span><span class="o">?</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">registered_tools</span><span class="p">.</span><span class="n">extend</span><span class="p">(</span><span class="n">tools</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p>The flaws are obvious:</p>
<ol>
<li><strong>Cumulative startup latency</strong>: Total startup time is the sum of every server’s handshake. A single slow server stalling for 5 seconds delays the whole agent by 5 seconds.</li>
<li><strong>Missing fault isolation</strong>: Core filesystem tools and auxiliary search tools share the same lifecycle. An external timeout escalates into a fatal crash.</li>
</ol>
<hr>

<h2 class="relative group">2. The Solution
    <div id="2-the-solution" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#2-the-solution" aria-label="Anchor">#</a>
    </span>
    
</h2>
<p>The revised flow focuses on three changes:</p>

<h3 class="relative group">1. Explicitly Distinguish Critical from Optional Services
    <div id="1-explicitly-distinguish-critical-from-optional-services" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#1-explicitly-distinguish-critical-from-optional-services" aria-label="Anchor">#</a>
    </span>
    
</h3>
<p>We added a criticality flag to the configuration schema:</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">"mcpServers"</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">"filesystem"</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">"command"</span><span class="p">:</span> <span class="s2">"agent-mcp-fs"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">"required"</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nt">"web_search"</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">"command"</span><span class="p">:</span> <span class="s2">"uvx"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">"args"</span><span class="p">:</span> <span class="p">[</span><span class="s2">"mcp-server-duckduckgo"</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="nt">"required"</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">"timeout_ms"</span><span class="p">:</span> <span class="mi">3000</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<ul>
<li><code>required: true</code> (Critical): Tools the agent cannot function without. Failures will cleanly abort with a clear error.</li>
<li><code>required: false</code> (Optional, Default): Auxiliary enhancements. Failures trigger circuit-breaking without affecting the main session.</li>
</ul>

<h3 class="relative group">2. Concurrent Probing with Isolated Timeouts
    <div id="2-concurrent-probing-with-isolated-timeouts" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#2-concurrent-probing-with-isolated-timeouts" aria-label="Anchor">#</a>
    </span>
    
</h3>
<p>Using Tokio, each MCP server is probed in a dedicated asynchronous task (<code>tokio::spawn</code>) wrapped in a <code>tokio::time::timeout</code>:</p>
<ul>
<li>All servers handshake concurrently. Cold startup latency is bounded by the slowest individual server rather than their cumulative sum.</li>
<li>If an optional server fails to connect within 3 seconds or crashes, the error is caught and marked as <code>Degraded</code> rather than bubbling up.</li>
</ul>

<h3 class="relative group">3. Dynamic Tool Filtering and UI Awareness
    <div id="3-dynamic-tool-filtering-and-ui-awareness" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#3-dynamic-tool-filtering-and-ui-awareness" aria-label="Anchor">#</a>
    </span>
    
</h3>
<p>Once all probing tasks settle:</p>
<ol>
<li>Successfully initialized tools are registered into the session context.</li>
<li>Tools from degraded servers are filtered out, preventing the model from hallucinating broken calls.</li>
<li>A lightweight notification informs the frontend which optional plugin failed, while keeping the main chat fully operational.</li>
</ol>
<hr>

<h2 class="relative group">3. Takeaway
    <div id="3-takeaway" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#3-takeaway" aria-label="Anchor">#</a>
    </span>
    
</h2>
<p>With startup isolation in place, even if network access is spotty or an MCP plugin config is broken, the agent’s core capabilities launch in sub-seconds.</p>
<p>Plugin systems that depend on external environments must design for failure. An issue in an optional feature should never break core tool availability.</p>
]]></content:encoded>
      
    </item>
    
  </channel>
</rss>
