<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Discord on Yarang's Tech Lair</title><link>https://blog.agentthread.dev/tags/discord/</link><description>Recent content in Discord on Yarang's Tech Lair</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Sun, 28 Jun 2026 09:00:35 +0900</lastBuildDate><atom:link href="https://blog.agentthread.dev/tags/discord/index.xml" rel="self" type="application/rss+xml"/><item><title>MCP Integration Guide: Integrating Discord MCP with ZeroClaw Runtime</title><link>https://blog.agentthread.dev/post/mcp-integration-guide-integrating-discord-mcp-with-zeroclaw-runtime/</link><pubDate>Sun, 28 Jun 2026 09:00:35 +0900</pubDate><guid>https://blog.agentthread.dev/post/mcp-integration-guide-integrating-discord-mcp-with-zeroclaw-runtime/</guid><description>&lt;p&gt;With the recent release of &lt;strong&gt;ZeroClaw&lt;/strong&gt;, a high-performance Rust agent runtime, we&amp;rsquo;ve been deeply contemplating ways to maximize the efficiency of multi-agent systems. In particular, the complexity of communication protocols encountered during the design of the [Discord Decision MCP] architecture was a decisive factor in adopting MCP (Model Context Protocol) as a standard interface.&lt;/p&gt;
&lt;p&gt;In this post, we will explain how to actually integrate &lt;strong&gt;Discord MCP&lt;/strong&gt; within the ZeroClaw environment, detailing the process of agents receiving and processing Discord messages with concrete code examples.&lt;/p&gt;
&lt;h3 id="1-architecture-design-dual-communication-on-a-single-channel"&gt;1. Architecture Design: Dual Communication on a Single Channel
&lt;/h3&gt;&lt;p&gt;In the previous [Discord MCP] Gateway architecture, the gateway played the role of filtering events and delivering them to agents. However, by directly implementing the MCP client within ZeroClaw, we&amp;rsquo;ve altered the design to eliminate the intermediate layer and reduce latency.&lt;/p&gt;
&lt;p&gt;The core idea is a flow where the &lt;strong&gt;&lt;code&gt;MCP Client&lt;/code&gt;&lt;/strong&gt; transmits Discord events to the ZeroClaw process via &lt;code&gt;stdio&lt;/code&gt;, and then sends the agent&amp;rsquo;s responses back to Discord.&lt;/p&gt;
&lt;h3 id="2-essential-dependencies-and-setup-rust"&gt;2. Essential Dependencies and Setup (Rust)
&lt;/h3&gt;&lt;p&gt;As ZeroClaw is written in Rust, it utilizes the asynchronous runtime &lt;code&gt;tokio&lt;/code&gt; for high concurrency processing and &lt;code&gt;serde&lt;/code&gt; for JSON handling. Communication with the MCP server is assumed to involve exchanging JSON-RPC messages via standard input/output (stdio).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Cargo.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;dependencies&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;tokio&lt;/span&gt; = { &lt;span style="color:#a6e22e"&gt;version&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;features&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;full&amp;#34;&lt;/span&gt;] }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;serde&lt;/span&gt; = { &lt;span style="color:#a6e22e"&gt;version&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;features&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;derive&amp;#34;&lt;/span&gt;] }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;serde_json&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;async-trait&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-mcp-client-implementation"&gt;3. MCP Client Implementation
&lt;/h3&gt;&lt;p&gt;We define a simple client structure to control the Discord MCP server within ZeroClaw. This client uses the &lt;code&gt;tools/call&lt;/code&gt; method, which adheres to the MCP standard, to execute Discord bot functionalities.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;use&lt;/span&gt; serde::{Deserialize, Serialize};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;use&lt;/span&gt; std::process::{Command, Stdio};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;use&lt;/span&gt; std::io::{BufReader, BufWriter, Write};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#[derive(Debug, Serialize, Deserialize)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MCPRequest&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; jsonrpc: String,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id: &lt;span style="color:#66d9ef"&gt;u64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; method: String,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; params: &lt;span style="color:#a6e22e"&gt;serde_json&lt;/span&gt;::Value,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#[derive(Debug, Serialize, Deserialize)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MCPResponse&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; jsonrpc: String,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id: &lt;span style="color:#66d9ef"&gt;u64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result: Option&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;serde_json::Value&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;pub&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DiscordMCPClient&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id: &lt;span style="color:#66d9ef"&gt;u64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;impl&lt;/span&gt; DiscordMCPClient {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;pub&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;new&lt;/span&gt;() -&amp;gt; &lt;span style="color:#a6e22e"&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Self { id: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;/// Executes an MCP tool to send a message to a Discord channel
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;pub&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;send_message&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;mut&lt;/span&gt; self, channel_id: &lt;span style="color:#66d9ef"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;str&lt;/span&gt;, content: &lt;span style="color:#66d9ef"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;str&lt;/span&gt;) -&amp;gt; Result&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;(), Box&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;dyn&lt;/span&gt; std::error::Error&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self.id &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Execute MCP server process (e.g., Python-based Discord MCP server)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;mut&lt;/span&gt; child &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Command::new(&lt;span style="color:#e6db74"&gt;&amp;#34;python3&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .arg(&lt;span style="color:#e6db74"&gt;&amp;#34;discord_mcp_server.py&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .stdin(Stdio::piped())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .stdout(Stdio::piped())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .spawn()&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; stdin &lt;span style="color:#f92672"&gt;=&lt;/span&gt; child.stdin.as_mut().ok(&lt;span style="color:#e6db74"&gt;&amp;#34;Failed to open stdin&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;mut&lt;/span&gt; stdout &lt;span style="color:#f92672"&gt;=&lt;/span&gt; BufReader::new(child.stdout.as_mut().ok(&lt;span style="color:#e6db74"&gt;&amp;#34;Failed to open stdout&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; request &lt;span style="color:#f92672"&gt;=&lt;/span&gt; MCPRequest {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; jsonrpc: &lt;span style="color:#e6db74"&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt;.to_string(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id: &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;.id,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; method: &lt;span style="color:#e6db74"&gt;&amp;#34;tools/call&amp;#34;&lt;/span&gt;.to_string(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; params: &lt;span style="color:#a6e22e"&gt;serde_json&lt;/span&gt;::&lt;span style="color:#a6e22e"&gt;json!&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;send_message&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;arguments&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channel_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;channel_id&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Send request
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; request_json &lt;span style="color:#f92672"&gt;=&lt;/span&gt; serde_json::to_string(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;request)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;writeln!&lt;/span&gt;(stdin, &lt;span style="color:#e6db74"&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;, request_json)&lt;span style="color:#f92672"&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// (In a real implementation, logic to parse the response from an asynchronous reader is needed)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Omitted here for simplicity.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Ok(())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-integration-with-zeroclaw-agents"&gt;4. Integration with ZeroClaw Agents
&lt;/h3&gt;&lt;p&gt;Now, let&amp;rsquo;s use the &lt;code&gt;DiscordMCPClient&lt;/code&gt; created above within ZeroClaw&amp;rsquo;s agent loop. This scenario demonstrates an agent notifying Discord upon completing a specific task.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZeroClawAgent&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; discord_client: &lt;span style="color:#a6e22e"&gt;DiscordMCPClient&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;impl&lt;/span&gt; ZeroClawAgent {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run_task&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;mut&lt;/span&gt; self, task: &lt;span style="color:#66d9ef"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;str&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;println!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;[Agent] Starting task: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, task);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Complex reasoning or file processing logic (omitted)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;format!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Task &amp;#39;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39; completed.&amp;#34;&lt;/span&gt;, task);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Send result to Discord
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;match&lt;/span&gt; self.discord_client.send_message(&lt;span style="color:#e6db74"&gt;&amp;#34;123456789&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;result).&lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Ok(_) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;println!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;[Agent] Successfully sent Discord notification&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Err(e) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;eprintln!&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;[Agent] Sending failed: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, e),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#[tokio::main]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;fn&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;mut&lt;/span&gt; agent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ZeroClawAgent {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; discord_client: &lt;span style="color:#a6e22e"&gt;DiscordMCPClient&lt;/span&gt;::new(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; agent.run_task(&lt;span style="color:#e6db74"&gt;&amp;#34;Analyze server logs&amp;#34;&lt;/span&gt;).&lt;span style="color:#66d9ef"&gt;await&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="5-efficiency-and-security-considerations-architecture-insights"&gt;5. Efficiency and Security Considerations (Architecture Insights)
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Resource Management&lt;/strong&gt;: Similar to the trending &amp;lsquo;Adrafinil&amp;rsquo; on [Hacker News], applying &lt;code&gt;speculative decoding&lt;/code&gt; by disconnecting the Discord MCP connection when the agent is idle and only establishing it when a task is active can save resources.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt;: As highlighted in issues related to [Anonymous GitHub accounts], parameters passed to the MCP server (e.g., API tokens) should be managed via environment variables or fetched from a separate secure storage (Vault). Hardcoding secrets in code is critical.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;: As discussed in communication platform design considerations, it&amp;rsquo;s important to include retry logic in the MCP client, taking into account Discord API&amp;rsquo;s Rate Limits.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="conclusion"&gt;Conclusion
&lt;/h3&gt;&lt;p&gt;Integrating ZeroClaw and Discord MCP goes beyond simply creating a bot; it&amp;rsquo;s a process of building a &lt;strong&gt;standardized interface&lt;/strong&gt; for agents to interact with the external world. Leveraging our experience in building [MCP] blog automation systems, we plan to further develop more sophisticated multi-agent collaboration systems.&lt;/p&gt;</description></item><item><title>Claude Code Discord MCP Plugin - Fixing asdf bun Path Issue</title><link>https://blog.agentthread.dev/post/claude-code-discord-mcp-plugin-fixing-asdf-bun-path-issue/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0900</pubDate><guid>https://blog.agentthread.dev/post/claude-code-discord-mcp-plugin-fixing-asdf-bun-path-issue/</guid><description>&lt;h2 id="problem"&gt;Problem
&lt;/h2&gt;&lt;p&gt;When installing the &lt;code&gt;discord&lt;/code&gt; plugin for Discord channel integration in Claude Code CLI, I encountered the following error:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; discord Plugin · claude-plugins-official · √ enabled
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └ discord MCP · × failed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The plugin was enabled, but the MCP server was in a failed state.&lt;/p&gt;
&lt;h2 id="root-cause"&gt;Root Cause
&lt;/h2&gt;&lt;p&gt;This issue occurs when using &lt;strong&gt;bun installed via asdf&lt;/strong&gt;. Claude Code CLI looks for the &lt;code&gt;bun&lt;/code&gt; command to run the MCP server, but asdf uses shell wrappers, so the actual binary cannot be found in the system-wide path.&lt;/p&gt;
&lt;h2 id="solution"&gt;Solution
&lt;/h2&gt;&lt;p&gt;I resolved this by entering the &lt;strong&gt;absolute path&lt;/strong&gt; to the bun installed via asdf.&lt;/p&gt;
&lt;h3 id="finding-the-absolute-path-of-asdf-installed-bun"&gt;Finding the Absolute Path of asdf-installed bun
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;which bun
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;asdf where bun
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/Users/yarang/.asdf/installs/bun/1.x.x/bin/bun
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="applying-the-configuration"&gt;Applying the Configuration
&lt;/h3&gt;&lt;p&gt;Specify this absolute path as the execution path in the Discord MCP configuration, and the problem will be resolved.&lt;/p&gt;
&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Situation&lt;/th&gt;
					&lt;th&gt;Solution&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;System-wide installed bun&lt;/td&gt;
					&lt;td&gt;Use &lt;code&gt;bun&lt;/code&gt; command&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;asdf-installed bun&lt;/td&gt;
					&lt;td&gt;Enter &lt;strong&gt;absolute path&lt;/strong&gt; directly&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;When using asdf, you must specify the actual binary path, not the shell wrapper, for the MCP server to run properly.&lt;/p&gt;
&lt;h2 id="references"&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/anthropics/discord-plugin" target="_blank" rel="noopener"
 &gt;Claude Code Discord Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://asdf-vm.com/" target="_blank" rel="noopener"
 &gt;asdf Version Manager&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Cloud Monitor] MCP Tool Structure and Pros/Cons Analysis</title><link>https://blog.agentthread.dev/post/2026-03-03-004-cloud-monitor-mcp-tool-structure-analysis/</link><pubDate>Tue, 03 Mar 2026 15:02:49 +0900</pubDate><guid>https://blog.agentthread.dev/post/2026-03-03-004-cloud-monitor-mcp-tool-structure-analysis/</guid><description>&lt;h1 id="server-monitor-mcp-tool-structure-and-proscons-analysis"&gt;[server-monitor] MCP Tool Structure and Pros/Cons Analysis
&lt;/h1&gt;&lt;h2 id="overview"&gt;Overview
&lt;/h2&gt;&lt;p&gt;This document analyzes the structure, advantages, and disadvantages of the MCP (Model Context Protocol) tools implemented in the server-monitor project. A total of 13 MCP tools are provided, categorized into 8 existing Discord MCP tools and 5 new Cloud Monitor MCP tools.&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="#architecture-overview" &gt;Architecture Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#detailed-tool-analysis" &gt;Detailed Tool Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#architecture-structure" &gt;Architecture Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#advantages" &gt;Advantages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#disadvantages-and-improvements" &gt;Disadvantages and Improvements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#conclusion" &gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="architecture-overview"&gt;Architecture Overview
&lt;/h2&gt;&lt;h3 id="fastmcp-based-architecture"&gt;FastMCP-based Architecture
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;graph TB
 subgraph MCP Server
 A[FastMCP Server] --&gt; B[Discord Tools]
 A --&gt; C[Cloud Monitor Tools]
 B --&gt; D[Gateway Service]
 C --&gt; D
 D --&gt; E[Discord API]
 end

 subgraph Cloud Monitor
 F[SSH Monitor] --&gt; G[OCI Servers]
 F --&gt; H[Mac mini]
 G --&gt; I[Ubuntu]
 H --&gt; J[macOS]
 end

 subgraph Discord
 K[Bot] --&gt; L[Channels]
 K --&gt; M[Threads]
 end&lt;/pre&gt;&lt;h3 id="mcp-tool-categories"&gt;MCP Tool Categories
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Category&lt;/th&gt;
					&lt;th&gt;Tool Count&lt;/th&gt;
					&lt;th&gt;Main Functions&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Discord MCP&lt;/td&gt;
					&lt;td&gt;8&lt;/td&gt;
					&lt;td&gt;Message, thread management&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cloud Monitor MCP&lt;/td&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;Server monitoring, metrics collection&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;13&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Integrated monitoring platform&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="detailed-tool-analysis"&gt;Detailed Tool Analysis
&lt;/h2&gt;&lt;h3 id="1-existing-discord-mcp-tools-8"&gt;1. Existing Discord MCP Tools (8)
&lt;/h3&gt;&lt;h4 id="11-message-management-tools"&gt;1.1 Message Management Tools
&lt;/h4&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tool Name&lt;/th&gt;
					&lt;th&gt;Parameters&lt;/th&gt;
					&lt;th&gt;Returns&lt;/th&gt;
					&lt;th&gt;Features&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_send_message&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;channel_id&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, &lt;code&gt;thread_id?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Result message&lt;/td&gt;
					&lt;td&gt;Basic message sending&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_get_messages&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;channel_id&lt;/code&gt;, &lt;code&gt;limit?&lt;/code&gt;, &lt;code&gt;after?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Message list&lt;/td&gt;
					&lt;td&gt;Message retrieval&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_wait_for_message&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;channel_id&lt;/code&gt;, &lt;code&gt;timeout_seconds?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Wait status&lt;/td&gt;
					&lt;td&gt;Async message waiting (SSE not implemented)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="12-thread-management-tools"&gt;1.2 Thread Management Tools
&lt;/h4&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tool Name&lt;/th&gt;
					&lt;th&gt;Parameters&lt;/th&gt;
					&lt;th&gt;Returns&lt;/th&gt;
					&lt;th&gt;Features&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_create_thread&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;channel_id&lt;/code&gt;, &lt;code&gt;message_id&lt;/code&gt;, &lt;code&gt;name?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Thread info&lt;/td&gt;
					&lt;td&gt;Thread creation&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_list_threads&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;channel_id&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Thread list&lt;/td&gt;
					&lt;td&gt;Active thread lookup&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_archive_thread&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;thread_id&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Result message&lt;/td&gt;
					&lt;td&gt;Thread archiving (not implemented)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="13-concurrency-management-tools"&gt;1.3 Concurrency Management Tools
&lt;/h4&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tool Name&lt;/th&gt;
					&lt;th&gt;Parameters&lt;/th&gt;
					&lt;th&gt;Returns&lt;/th&gt;
					&lt;th&gt;Features&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_acquire_thread&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;thread_id&lt;/code&gt;, &lt;code&gt;agent_name&lt;/code&gt;, &lt;code&gt;timeout?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Lock acquisition result&lt;/td&gt;
					&lt;td&gt;Multi-agent lock&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_release_thread&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;thread_id&lt;/code&gt;, &lt;code&gt;agent_name&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Lock release result&lt;/td&gt;
					&lt;td&gt;Agent lock release&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="2-new-cloud-monitor-mcp-tools-5"&gt;2. New Cloud Monitor MCP Tools (5)
&lt;/h3&gt;&lt;h4 id="21-server-management-tools"&gt;2.1 Server Management Tools
&lt;/h4&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tool Name&lt;/th&gt;
					&lt;th&gt;Parameters&lt;/th&gt;
					&lt;th&gt;Returns&lt;/th&gt;
					&lt;th&gt;Features&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;cloud_get_server_status&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;server_name&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Server status info&lt;/td&gt;
					&lt;td&gt;Connection status, OS, metrics&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;cloud_list_servers&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;group?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Server list&lt;/td&gt;
					&lt;td&gt;Group filtering support&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;cloud_list_ssh_config_hosts&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;group?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;SSH host list&lt;/td&gt;
					&lt;td&gt;SSH config auto-parsing&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="22-monitoring-tools"&gt;2.2 Monitoring Tools
&lt;/h4&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tool Name&lt;/th&gt;
					&lt;th&gt;Parameters&lt;/th&gt;
					&lt;th&gt;Returns&lt;/th&gt;
					&lt;th&gt;Features&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;cloud_get_metrics&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;server_name&lt;/code&gt;, &lt;code&gt;metric_types?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Metrics data&lt;/td&gt;
					&lt;td&gt;Optional metric lookup&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;cloud_set_alert&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;metric_type&lt;/code&gt;, &lt;code&gt;level&lt;/code&gt;, &lt;code&gt;threshold&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Setting result&lt;/td&gt;
					&lt;td&gt;Dynamic threshold configuration&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="architecture-structure"&gt;Architecture Structure
&lt;/h2&gt;&lt;h3 id="1-fastmcp-structure"&gt;1. FastMCP Structure
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;graph LR
 subgraph "FastMCP Layer"
 A[@mcp.tool decorator] --&gt; B[Tool Function]
 B --&gt; C[Parameter Validation]
 C --&gt; D[Business Logic]
 D --&gt; E[Result Formatting]
 E --&gt; F[Return Response]
 end

 subgraph "Common Components"
 G[Gateway Request] --&gt; H[HTTP Client]
 I[Config Manager] --&gt; J[Cloud Monitor Config]
 K[Error Handler] --&gt; L[Uniform Error Response]
 end&lt;/pre&gt;&lt;h3 id="2-communication-flow"&gt;2. Communication Flow
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;sequenceDiagram
 participant MCP as MCP Server
 participant GW as Gateway Service
 participant Discord as Discord API
 participant Server as Target Server

 MCP-&gt;&gt;GW: HTTP Request
 GW-&gt;&gt;Discord: API Call
 Discord--&gt;&gt;GW: Response
 GW--&gt;&gt;MCP: JSON Response

 MCP-&gt;&gt;Server: SSH Connection
 Server--&gt;&gt;MCP: Metrics Data
 MCP-&gt;&gt;GW: Alert Message
 GW-&gt;&gt;Discord: Embed Message&lt;/pre&gt;&lt;h3 id="3-data-flow"&gt;3. Data Flow
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Configuration (config.yaml)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Server Info parsing
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SSH Connection
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Metrics Collection
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Threshold Check
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alert Generation
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Discord Notification
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="advantages"&gt;Advantages
&lt;/h2&gt;&lt;h3 id="1-scalability"&gt;1. Scalability
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modular Structure&lt;/strong&gt;: Each tool operates independently and is easy to extend&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plugin Architecture&lt;/strong&gt;: Adding new tools only requires adding decorators&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud Provider Abstraction&lt;/strong&gt;: SSH-based support for various environments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-integration"&gt;2. Integration
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unified Platform&lt;/strong&gt;: Discord and Cloud Monitor managed together on a single MCP server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic Linkage&lt;/strong&gt;: Automatic Discord alerts on server anomalies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consistent Interface&lt;/strong&gt;: All tools follow the same parameter pattern&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-usability"&gt;3. Usability
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Intuitive Tool Names&lt;/strong&gt;: Clear function expression like &lt;code&gt;cloud_get_server_status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional Parameters&lt;/strong&gt;: Most parameters are optional for convenience&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Detailed Error Messages&lt;/strong&gt;: Clearly indicates the cause of failures&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JSON Response&lt;/strong&gt;: Structured data return for easy parsing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-reliability"&gt;4. Reliability
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Timeout Handling&lt;/strong&gt;: Timeout set for all requests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connection Pooling&lt;/strong&gt;: SSH connection reuse for performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exception Handling&lt;/strong&gt;: Comprehensive try-catch blocks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Status Tracking&lt;/strong&gt;: Continuous server status monitoring&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="5-maintainability"&gt;5. Maintainability
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Centralized Configuration&lt;/strong&gt;: Central management via config.yaml&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment Variable Support&lt;/strong&gt;: Sensitive info separated into environment variables&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logging System&lt;/strong&gt;: Detailed logging for easy debugging&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Version Management&lt;/strong&gt;: Clear module version distinction&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="disadvantages-and-improvements"&gt;Disadvantages and Improvements
&lt;/h2&gt;&lt;h3 id="1-performance-related"&gt;1. Performance Related
&lt;/h3&gt;&lt;h4 id="issues"&gt;Issues
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Synchronous Processing&lt;/strong&gt;: Some tools operate sequentially&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connection Latency&lt;/strong&gt;: New connection created each SSH connection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory Usage&lt;/strong&gt;: All processing on single event loop&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="improvements"&gt;Improvements
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Async processing improvement example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;concurrent_monitoring&lt;/span&gt;(servers):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tasks &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [monitor_server(server) &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; server &lt;span style="color:#f92672"&gt;in&lt;/span&gt; servers]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; asyncio&lt;span style="color:#f92672"&gt;.&lt;/span&gt;gather(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;tasks)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Connection pooling introduction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ConnectionPool&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__init__&lt;/span&gt;(self, max_connections&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pool &lt;span style="color:#f92672"&gt;=&lt;/span&gt; asyncio&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Queue(maxsize&lt;span style="color:#f92672"&gt;=&lt;/span&gt;max_connections)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-error-handling-related"&gt;2. Error Handling Related
&lt;/h3&gt;&lt;h4 id="issues-1"&gt;Issues
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Undifferentiated Errors&lt;/strong&gt;: All errors handled the same way&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lack of Recovery Mechanism&lt;/strong&gt;: No auto-recovery logic on failures&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insufficient Detailed Logging&lt;/strong&gt;: Insufficient logs for debugging&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="improvements-1"&gt;Improvements
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Differentiated error handling&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CloudMonitorError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ConnectionError&lt;/span&gt;(CloudMonitorError):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MetricCollectionError&lt;/span&gt;(CloudMonitorError):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Auto-recovery mechanism&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;resilient_monitoring&lt;/span&gt;(server_info, max_retries&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; attempt &lt;span style="color:#f92672"&gt;in&lt;/span&gt; range(max_retries):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; monitor_server(server_info)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;except&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ConnectionError&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; asyncio&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sleep(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt; attempt)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;raise&lt;/span&gt; CloudMonitorError(&lt;span style="color:#e6db74"&gt;&amp;#34;Max retries exceeded&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-functionality-related"&gt;3. Functionality Related
&lt;/h3&gt;&lt;h4 id="issues-2"&gt;Issues
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lack of Metadata&lt;/strong&gt;: Tool descriptions too brief&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insufficient Validation&lt;/strong&gt;: Lack of input value check logic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Batch Processing&lt;/strong&gt;: Cannot process multiple servers simultaneously&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="improvements-2"&gt;Improvements
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Detailed metadata&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@mcp.tool&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;cloud_batch_monitoring&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; description&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Retrieve multiple server statuses at once&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; parameters&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;server_names&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;array&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;List of server names to monitor&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;cloud_batch_monitoring&lt;/span&gt;(server_names: List[str]) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; str:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Batch processing logic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-security-related"&gt;4. Security Related
&lt;/h3&gt;&lt;h4 id="issues-3"&gt;Issues
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Credential Exposure&lt;/strong&gt;: Sensitive info potentially exposed in logs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Access Control&lt;/strong&gt;: Anyone can call tools&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insufficient Input Validation&lt;/strong&gt;: Insufficient defense against malicious input&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="improvements-3"&gt;Improvements
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Access control&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require_role&lt;/span&gt;(required_role):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;decorator&lt;/span&gt;(func):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;wrapper&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;args, &lt;span style="color:#f92672"&gt;**&lt;/span&gt;kwargs):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; has_role(required_role):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;raise&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PermissionError&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Access denied&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; func(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;args, &lt;span style="color:#f92672"&gt;**&lt;/span&gt;kwargs)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; wrapper
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; decorator
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Input validation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@mcp.tool&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;secure_monitoring&lt;/span&gt;(server_name: str):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; is_valid_server_name(server_name):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;raise&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ValueError&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Invalid server name&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="5-usability-related"&gt;5. Usability Related
&lt;/h3&gt;&lt;h4 id="issues-4"&gt;Issues
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lack of Documentation&lt;/strong&gt;: No detailed documentation for tool usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Examples&lt;/strong&gt;: No actual usage examples&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inconsistent Return Values&lt;/strong&gt;: Some tools return JSON, others return strings&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="improvements-4"&gt;Improvements
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Consistent return value format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@mcp.tool&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;cloud_get_server_status_v2&lt;/span&gt;(server_name: str) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; dict:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Retrieve server status.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Args:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; server_name (str): Server name
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Returns:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; dict: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;success&amp;#34;: bool,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;data&amp;#34;: Optional[dict],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;error&amp;#34;: Optional[str],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;timestamp&amp;#34;: str
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;: status,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: datetime&lt;span style="color:#f92672"&gt;.&lt;/span&gt;now()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;isoformat()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;h3 id="1-overall-assessment"&gt;1. Overall Assessment
&lt;/h3&gt;&lt;p&gt;The MCP tools in the server-monitor project have the following strengths:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;✅ Excellent Integration&lt;/strong&gt;: Perfect combination of Discord integration and server monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;✅ Scalable Structure&lt;/strong&gt;: Modular architecture using FastMCP&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;✅ Practicality&lt;/strong&gt;: Provides all functions needed for actual server monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;✅ Ease of Use&lt;/strong&gt;: Intuitive tool names and simple interface&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-improvement-priority"&gt;2. Improvement Priority
&lt;/h3&gt;&lt;p&gt;Improvement plans by priority:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;High&lt;/strong&gt;: Performance improvement (async processing, connection pooling)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Medium&lt;/strong&gt;: Error handling enhancement and auto-recovery mechanisms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low&lt;/strong&gt;: Security enhancement and detailed documentation&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="3-future-direction"&gt;3. Future Direction
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Microservices Architecture&lt;/strong&gt;: Separate each tool into independent services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real-time Monitoring&lt;/strong&gt;: Real-time data collection via WebSocket/SSE&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-scaling&lt;/strong&gt;: Automatic scaling based on server changes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Machine Learning&lt;/strong&gt;: ML model integration for anomaly detection&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-final-assessment"&gt;4. Final Assessment
&lt;/h3&gt;&lt;p&gt;Overall, a well-designed MCP tool system that provides stability and functionality suitable for actual production environments. While there are areas for improvement, the core functionality is highly complete, and it has the potential to develop into an even more powerful monitoring platform through continuous improvements.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Written: 2026-03-03&lt;/em&gt;
&lt;em&gt;Author: server-monitor-team&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Korean Version:&lt;/strong&gt; &lt;a class="link" href="https://blog.agentthread.dev/ko/post/2026-03-03-002-cloud-monitor-mcp-tool-structure-analysis/" &gt;한국어 버전&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[Discord Decision MCP] Architecture Design Document</title><link>https://blog.agentthread.dev/post/discord-decision-mcp-architecture-design-v2/</link><pubDate>Mon, 02 Mar 2026 21:36:30 +0900</pubDate><guid>https://blog.agentthread.dev/post/discord-decision-mcp-architecture-design-v2/</guid><description>&lt;h1 id="discord-decision-mcp--architecture-design-document"&gt;Discord Decision MCP — Architecture Design Document
&lt;/h1&gt;&lt;h2 id="1-project-overview"&gt;1. Project Overview
&lt;/h2&gt;&lt;h3 id="11-purpose"&gt;1.1 Purpose
&lt;/h3&gt;&lt;p&gt;An MCP (Model Context Protocol) server that allows Claude Code, while operating in tmux Teammate mode for autonomous work, to ask questions via Discord when user decisions are needed and resume work after receiving responses.&lt;/p&gt;
&lt;h3 id="12-key-features"&gt;1.2 Key Features
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Feature&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;One Bot per Project&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Each project uses an independent Discord Bot&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Infinite Wait Default&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Wait for user response without timeout (Claude must not proceed unilaterally)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;State Persistence&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Restore waiting state after process restart&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Korean-Friendly&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Korean options, Yes/No response support&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;MCP-Based Communication&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;All Discord communication through MCP Tools&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="13-version-information"&gt;1.3 Version Information
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Version&lt;/strong&gt;: 1.0.0&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python Requirement&lt;/strong&gt;: &amp;gt;= 3.11&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP Framework&lt;/strong&gt;: FastMCP &amp;gt;= 0.1.0&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="2-directory-structure"&gt;2. Directory Structure
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discord&lt;span style="color:#f92672"&gt;-&lt;/span&gt;decision&lt;span style="color:#f92672"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; discord_mcp&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Main package&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; __init__&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; server&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# MCP server entry point&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# Environment variable configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; bot&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Discord API client&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; __init__&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# REST API client (httpx)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└──&lt;/span&gt; gateway&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# WebSocket gateway (receive only)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; decision&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Decision request management&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; __init__&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; manager&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# Decision request lifecycle management&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; poller&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# Discord polling and response waiting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; parser&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# User response parsing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└──&lt;/span&gt; state&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# State persistence (JSON files)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; tools&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# MCP Tools implementation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; __init__&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; ask&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# discord_ask_decision&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; notify&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# discord_notify&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; report&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# discord_report_progress&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; status&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# discord_check_pending&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; inbox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# discord_read_inbox, discord_clear_inbox&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└──&lt;/span&gt; _templates&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# Discord message templates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└──&lt;/span&gt; daemon&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Watcher daemon&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; __init__&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; watcher&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# Discord channel monitoring (discord-watch CLI)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└──&lt;/span&gt; inbox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py &lt;span style="color:#75715e"&gt;# Inbox file management&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; scripts&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Utility scripts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└──&lt;/span&gt; start&lt;span style="color:#f92672"&gt;-&lt;/span&gt;discord&lt;span style="color:#f92672"&gt;-&lt;/span&gt;watch&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; tests&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Test suite&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; __init__&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; test_parser&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;└──&lt;/span&gt; test_state&lt;span style="color:#f92672"&gt;.&lt;/span&gt;py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; CLAUDE&lt;span style="color:#f92672"&gt;.&lt;/span&gt;md &lt;span style="color:#75715e"&gt;# Claude Code project instructions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; README&lt;span style="color:#f92672"&gt;.&lt;/span&gt;md &lt;span style="color:#75715e"&gt;# Project description&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; pyproject&lt;span style="color:#f92672"&gt;.&lt;/span&gt;toml &lt;span style="color:#75715e"&gt;# Project configuration and dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;└──&lt;/span&gt; mcp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;json&lt;span style="color:#f92672"&gt;.&lt;/span&gt;example &lt;span style="color:#75715e"&gt;# MCP configuration example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="3-key-module-descriptions"&gt;3. Key Module Descriptions
&lt;/h2&gt;&lt;h3 id="31-server-entry-point-serverpy"&gt;3.1 Server Entry Point (&lt;code&gt;server.py&lt;/code&gt;)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: FastMCP server creation and MCP Tool registration&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mcp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; FastMCP(name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;discord-decision-mcp&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Tool registration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mcp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tool()(discord_ask_decision)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mcp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tool()(discord_notify)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mcp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tool()(discord_report_progress)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mcp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tool()(discord_check_pending)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mcp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tool()(discord_read_inbox)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mcp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tool()(discord_clear_inbox)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Execution&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discord-mcp &lt;span style="color:#75715e"&gt;# or python -m discord_mcp.server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-configuration-management-configpy"&gt;3.2 Configuration Management (&lt;code&gt;config.py&lt;/code&gt;)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: Load configuration values from environment variables&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Environment Variable&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
					&lt;th&gt;Default&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DISCORD_BOT_TOKEN&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Discord Bot Token (includes &amp;ldquo;Bot &amp;quot; prefix)&lt;/td&gt;
					&lt;td&gt;Required&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DISCORD_CHANNEL_ID&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Default question channel ID&lt;/td&gt;
					&lt;td&gt;Required&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;PROJECT_NAME&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Used for question_id generation&lt;/td&gt;
					&lt;td&gt;&amp;ldquo;project&amp;rdquo;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;PENDING_DIR&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;State file storage path&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;~/.claude/pending_decisions&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;POLL_INTERVAL_SECONDS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Discord polling interval (seconds)&lt;/td&gt;
					&lt;td&gt;5&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="33-discord-api-client-bot"&gt;3.3 Discord API Client (&lt;code&gt;bot/&lt;/code&gt;)
&lt;/h3&gt;&lt;h4 id="331-rest-api-client-clientpy"&gt;3.3.1 REST API Client (&lt;code&gt;client.py&lt;/code&gt;)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: Discord REST API calls (httpx-based)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Methods&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DiscordClient&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;send_message&lt;/span&gt;(channel_id, content, embeds&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get_messages&lt;/span&gt;(channel_id, after&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;, limit&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create_thread&lt;/span&gt;(channel_id, name, first_message)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;archive_thread&lt;/span&gt;(thread_id)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatic rate limit handling (retry on 429 response)&lt;/li&gt;
&lt;li&gt;Singleton pattern (&lt;code&gt;get_client()&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="332-websocket-gateway-gatewaypy"&gt;3.3.2 WebSocket Gateway (&lt;code&gt;gateway.py&lt;/code&gt;)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: Discord Gateway WebSocket connection (receive only)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real-time MESSAGE_CREATE event reception&lt;/li&gt;
&lt;li&gt;Reduces polling delay from 5 seconds to instant&lt;/li&gt;
&lt;li&gt;System works without Gateway (polling fallback)&lt;/li&gt;
&lt;li&gt;Automatic reconnection (Exponential backoff)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GatewayClient&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;() &lt;span style="color:#75715e"&gt;# Start event reception&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stop&lt;/span&gt;() &lt;span style="color:#75715e"&gt;# Close connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="34-decision-request-management-decision"&gt;3.4 Decision Request Management (&lt;code&gt;decision/&lt;/code&gt;)
&lt;/h3&gt;&lt;h4 id="341-decisionmanager-managerpy"&gt;3.4.1 DecisionManager (&lt;code&gt;manager.py&lt;/code&gt;)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: Coordinate the entire lifecycle of decision requests&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DecisionManager&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ask&lt;/span&gt;(question, context, options, timeout_seconds, thread_id) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; PollResult
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;restore_pending&lt;/span&gt;() &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; list[DecisionState]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Flow&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check for duplicate questions&lt;/li&gt;
&lt;li&gt;Create thread (or reuse existing thread)&lt;/li&gt;
&lt;li&gt;Create state file (&lt;code&gt;~/.claude/pending_decisions/{question_id}.json&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Run poller to wait for response&lt;/li&gt;
&lt;li&gt;Mark disconnected state on SIGHUP signal&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="342-decisionpoller-pollerpy"&gt;3.4.2 DecisionPoller (&lt;code&gt;poller.py&lt;/code&gt;)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: Poll Discord channel and wait for response&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DecisionPoller&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;wait&lt;/span&gt;(state: DecisionState) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; PollResult
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Default: infinite wait (&lt;code&gt;timeout_seconds=None&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Real-time waiting status display in tmux pane (ANSI escape)&lt;/li&gt;
&lt;li&gt;Re-question up to 2 times for ambiguous responses&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="343-response-parser-parserpy"&gt;3.4.3 Response Parser (&lt;code&gt;parser.py&lt;/code&gt;)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: Parse user Discord responses&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Supported Patterns&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Option matching: &amp;ldquo;A&amp;rdquo;, &amp;ldquo;a&amp;rdquo;, &amp;ldquo;A번&amp;rdquo;, &amp;ldquo;A로 해줘&amp;rdquo;, &amp;ldquo;1&amp;rdquo;, &amp;ldquo;1번&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Affirmative/Negative: &amp;ldquo;yes&amp;rdquo;, &amp;ldquo;네&amp;rdquo;, &amp;ldquo;예&amp;rdquo;, &amp;ldquo;no&amp;rdquo;, &amp;ldquo;아니요&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Natural language: 15+ characters or 3+ Korean characters&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;parse_response&lt;/span&gt;(text: str, options: list[str]) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; ParseResult
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;build_clarify_message&lt;/span&gt;(&lt;span style="color:#f92672"&gt;...&lt;/span&gt;) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; str &lt;span style="color:#75715e"&gt;# Generate re-question message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="344-state-store-statepy"&gt;3.4.4 State Store (&lt;code&gt;state.py&lt;/code&gt;)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: Persist decision request state to JSON files&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;State File Location&lt;/strong&gt;: &lt;code&gt;~/.claude/pending_decisions/{question_id}.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DecisionState&lt;/span&gt;(BaseModel):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; question_id: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; project: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; question: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; options: list[str]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout_seconds: float &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; thread_id: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message_id: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; asked_at: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status: Literal[&lt;span style="color:#e6db74"&gt;&amp;#34;pending&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;disconnected&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;resolved&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;aborted&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;timeout&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; clarify_attempts: int
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resolved_at: str &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resolution: str &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; selected_option: str &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StateStore&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;save&lt;/span&gt;(state: DecisionState)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;load&lt;/span&gt;(question_id: str) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; DecisionState &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;load_all_pending&lt;/span&gt;() &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; list[DecisionState]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;(question_id, resolution, selected_option)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;is_duplicate&lt;/span&gt;(question: str) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; bool
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="35-mcp-tools-tools"&gt;3.5 MCP Tools (&lt;code&gt;tools/&lt;/code&gt;)
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tool&lt;/th&gt;
					&lt;th&gt;Blocking&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_ask_decision&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;User decision request&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_notify&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Progress notification&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_report_progress&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Task completion report&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_check_pending&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Check pending questions&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_read_inbox&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Inbox message query&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_clear_inbox&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Inbox message deletion&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="36-watcher-daemon-daemon"&gt;3.6 Watcher Daemon (&lt;code&gt;daemon/&lt;/code&gt;)
&lt;/h3&gt;&lt;h4 id="361-discordwatcher-watcherpy"&gt;3.6.1 DiscordWatcher (&lt;code&gt;watcher.py&lt;/code&gt;)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: Monitor Discord channel and record new messages to inbox file&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Execution&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discord-watch --interval &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmux new-session -d -s discord-watch &lt;span style="color:#e6db74"&gt;&amp;#39;uv run discord-watch&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Periodically poll specified channel(s)&lt;/li&gt;
&lt;li&gt;Record new user messages to inbox&lt;/li&gt;
&lt;li&gt;Display status in tmux pane&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="362-inboxstore-inboxpy"&gt;3.6.2 InboxStore (&lt;code&gt;inbox.py&lt;/code&gt;)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Role&lt;/strong&gt;: JSON file-based storage for Discord messages&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inbox File Location&lt;/strong&gt;: &lt;code&gt;~/.claude/discord_inbox.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;InboxMessage&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message_id: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; channel_id: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; thread_id: str &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; author: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; author_id: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; content: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timestamp: str
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read: bool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;InboxStore&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add_message&lt;/span&gt;(msg: InboxMessage)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;get_unread&lt;/span&gt;() &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; list[InboxMessage]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mark_read&lt;/span&gt;(message_id: str)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;clear_read&lt;/span&gt;() &lt;span style="color:#75715e"&gt;# Delete read messages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="4-data-flow-diagrams"&gt;4. Data Flow Diagrams
&lt;/h2&gt;&lt;h3 id="41-decision-request-flow"&gt;4.1 Decision Request Flow
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ Claude Code │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└────────┬────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ discord_ask_decision()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ MCP Server (server.py) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ┌───────────────────────────────┐ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ DecisionManager.ask() │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 1. Duplicate check │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 2. Thread creation │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 3. State file save │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └───────────────┬───────────────┘ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────────┼──────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ DecisionPoller.wait() │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ┌───────────────────────────────┐ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ Polling loop │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 1. tmux status update │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 2. Discord API call │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 3. Response parsing │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 4. Re-question if ambiguous │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └───────────────┬───────────────┘ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────────┼──────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ┌─────────┴─────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼ ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌───────────────────┐ ┌──────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ Discord REST API │ │ Discord Thread │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ (client.py) │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└───────────────────┘ └────────┬─────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ┌────────▼────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ User Response │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └────────┬────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ┌─────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ parser.py │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ - Option match │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ - Ambiguity │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └────────┬────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ┌─────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ store.resolve()│
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └────────┬────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ┌─────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ PollResult │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ Return │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └─────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="42-watcher-daemon-flow"&gt;4.2 Watcher Daemon Flow
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ DiscordWatcher (daemon/watcher.py) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ┌───────────────────────────────────────┐ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 1. Set initial message ID │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 2. Periodic polling (default 10s) │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 3. Detect new messages │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 4. InboxStore.add_message() │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └───────────────────┬───────────────────┘ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────────────┼──────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ~/.claude/discord_inbox.json │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ { │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ &amp;#34;last_message_id&amp;#34;: &amp;#34;...&amp;#34;, │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ &amp;#34;messages&amp;#34;: [ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ { &amp;#34;message_id&amp;#34;: &amp;#34;...&amp;#34;, ... } │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ] │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ } │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────────────┬──────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▲
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ discord_read_inbox()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌──────────────────────┴──────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ Claude Code │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─────────────────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="43-session-restoration-flow"&gt;4.3 Session Restoration Flow
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ Claude Code session start │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────────────┬──────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ discord_check_pending() │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────────────┬──────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ DecisionManager.restore_pending() │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ┌───────────────────────────────────────┐ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 1. ~/.claude/pending_decisions/*.json │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 2. Check Thread via Discord API │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 3. If answered → Auto-resolve │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ 4. If no answer → Restart notification│ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └───────────────────────────────────────┘ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─────────────────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="5-mcp-tools-list"&gt;5. MCP Tools List
&lt;/h2&gt;&lt;h3 id="51-discord_ask_decision"&gt;5.1 discord_ask_decision
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: Send question to Discord Thread and wait for response when user decision is needed (blocking)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Name&lt;/th&gt;
					&lt;th&gt;Type&lt;/th&gt;
					&lt;th&gt;Required&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;question&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;Question content&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;context&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;Current work context&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;options&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string[]&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;List of options (empty array for free response)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;timeout_seconds&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;float&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Wait timeout (null for infinite wait)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;thread_id&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Existing Thread ID (null to create new Thread)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Return Value&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;answer&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;A) Execute now&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;selected_option&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;A) Execute now&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;question_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;project_20260301_abc123&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;timed_out&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;aborted&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="52-discord_notify"&gt;5.2 discord_notify
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: Send progress notification to Discord (non-blocking)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Name&lt;/th&gt;
					&lt;th&gt;Type&lt;/th&gt;
					&lt;th&gt;Required&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;message&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;Notification message&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;level&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;info/warning/success/error (default: info)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;thread_id&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Thread ID to send to (null for default channel)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="53-discord_report_progress"&gt;5.3 discord_report_progress
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: Report task completion or milestone completion (non-blocking)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Name&lt;/th&gt;
					&lt;th&gt;Type&lt;/th&gt;
					&lt;th&gt;Required&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;Report title&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;summary&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;Task result summary&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;details&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string[]&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;List of detail items&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;thread_id&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;string&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Thread ID to send to&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="54-discord_check_pending"&gt;5.4 discord_check_pending
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: Check pending questions at session start (non-blocking)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt;: None&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Return Value&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;has_pending&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;pending_questions&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;question_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;project_20260301_abc123&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;question&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Deploy?&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;thread_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1234567890&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;asked_at&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2026-03-01T10:30:00Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;pending&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="55-discord_read_inbox"&gt;5.5 discord_read_inbox
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: Query messages stored in Inbox (non-blocking)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Name&lt;/th&gt;
					&lt;th&gt;Type&lt;/th&gt;
					&lt;th&gt;Default&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;unread_only&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;boolean&lt;/td&gt;
					&lt;td&gt;true&lt;/td&gt;
					&lt;td&gt;Return only unread messages&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;mark_read&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;boolean&lt;/td&gt;
					&lt;td&gt;false&lt;/td&gt;
					&lt;td&gt;Mark queried messages as read&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="56-discord_clear_inbox"&gt;5.6 discord_clear_inbox
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;: Delete Inbox messages (non-blocking)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Name&lt;/th&gt;
					&lt;th&gt;Type&lt;/th&gt;
					&lt;th&gt;Default&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;read_only&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;boolean&lt;/td&gt;
					&lt;td&gt;true&lt;/td&gt;
					&lt;td&gt;Delete only read messages&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="6-dependency-information"&gt;6. Dependency Information
&lt;/h2&gt;&lt;h3 id="61-core-dependencies"&gt;6.1 Core Dependencies
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Package&lt;/th&gt;
					&lt;th&gt;Version&lt;/th&gt;
					&lt;th&gt;Purpose&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;fastmcp&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt;= 0.1.0&lt;/td&gt;
					&lt;td&gt;MCP server framework&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;httpx&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt;= 0.27.0&lt;/td&gt;
					&lt;td&gt;Async HTTP client&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;websockets&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt;= 12.0&lt;/td&gt;
					&lt;td&gt;WebSocket client&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;python-dotenv&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt;= 1.0.0&lt;/td&gt;
					&lt;td&gt;Environment variable loading&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;pydantic&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt;= 2.0.0&lt;/td&gt;
					&lt;td&gt;Data model validation&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;anyio&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt;= 4.0.0&lt;/td&gt;
					&lt;td&gt;Async execution&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="62-development-dependencies"&gt;6.2 Development Dependencies
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Package&lt;/th&gt;
					&lt;th&gt;Purpose&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;pytest&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Test framework&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;pytest-asyncio&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Async test support&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;pytest-mock&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Mock support&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;respx&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;httpx mocking&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="63-cli-commands"&gt;6.3 CLI Commands
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discord-mcp &lt;span style="color:#75715e"&gt;# Run MCP server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discord-watch &lt;span style="color:#75715e"&gt;# Run watcher daemon&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="7-state-file-format"&gt;7. State File Format
&lt;/h2&gt;&lt;h3 id="71-decision-state-file"&gt;7.1 Decision State File
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt;: &lt;code&gt;~/.claude/pending_decisions/{question_id}.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;question_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;project_20260301_abc123&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;project&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;my-project&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;question&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Run DB migration?&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;v1→v2 schema change&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;options&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;A) Execute now&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;B) Staging first&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;C) Hold&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;timeout_seconds&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;thread_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1234567890&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;message_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;0987654321&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;asked_at&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2026-03-01T10:30:00Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;pending&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;clarify_attempts&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;resolved_at&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;resolution&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;selected_option&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="72-inbox-file"&gt;7.2 Inbox File
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt;: &lt;code&gt;~/.claude/discord_inbox.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;last_message_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1234567890&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;messages&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;message_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1234567890&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;channel_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1234567890&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;thread_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;author_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1234567890&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Message content&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2026-03-01T00:00:00Z&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;read&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="8-architecture-principles"&gt;8. Architecture Principles
&lt;/h2&gt;&lt;h3 id="81-design-principles"&gt;8.1 Design Principles
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Singleton Pattern&lt;/strong&gt;: DiscordClient, StateStore, InboxStore are module-level singletons&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State Persistence&lt;/strong&gt;: All decision request states are persisted to files&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infinite Wait Default&lt;/strong&gt;: Timeout default is None so Claude does not proceed unilaterally&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Re-question Limit&lt;/strong&gt;: Ambiguous responses are re-asked up to 2 times&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate Limit Handling&lt;/strong&gt;: Automatic wait and retry on Discord API 429 responses&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="82-error-handling"&gt;8.2 Error Handling
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Situation&lt;/th&gt;
					&lt;th&gt;Handling&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Discord API 429&lt;/td&gt;
					&lt;td&gt;Automatic wait and retry (max 5 times)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;WebSocket disconnection&lt;/td&gt;
					&lt;td&gt;Reconnect with exponential backoff&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Response parsing failure&lt;/td&gt;
					&lt;td&gt;Re-question up to 2 times then abort&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Timeout occurrence&lt;/td&gt;
					&lt;td&gt;Send abort notification and set aborted state&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Session disconnect (SIGHUP)&lt;/td&gt;
					&lt;td&gt;Save as disconnected state&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Document Version: 1.0.0&lt;/em&gt;
&lt;em&gt;Last Modified: 2026-03-02&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Korean Version:&lt;/strong&gt; &lt;a class="link" href="https://blog.agentthread.dev/ko/post/2026-03-02-002-discord-decision-mcp-architecture-design/" &gt;한국어 버전&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[Discord MCP] Gateway Architecture Design</title><link>https://blog.agentthread.dev/post/discord-gateway-mcp-architecture-design/</link><pubDate>Sun, 01 Mar 2026 01:13:00 +0900</pubDate><guid>https://blog.agentthread.dev/post/discord-gateway-mcp-architecture-design/</guid><description>&lt;p&gt;The Claude Code team designed a Discord Gateway Service for user communication via Discord. This article summarizes the key architecture decisions and user_comm Agent design.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-overall-architecture"&gt;1. Overall Architecture
&lt;/h2&gt;&lt;h3 id="components"&gt;Components
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Layer&lt;/th&gt;
					&lt;th&gt;Component&lt;/th&gt;
					&lt;th&gt;Role&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Discord&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Bot, Channel, Thread&lt;/td&gt;
					&lt;td&gt;User interface&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Gateway&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;WebSocket, REST API, SSE&lt;/td&gt;
					&lt;td&gt;Message routing&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;MCP&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;gcp-mcp, oci-mcp, db-mcp&lt;/td&gt;
					&lt;td&gt;Tool execution&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;user_comm&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Discord Agent&lt;/td&gt;
					&lt;td&gt;User communication&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="message-flow"&gt;Message Flow
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR
 subgraph D[Discord]
 U[User]
 end
 subgraph G[Gateway :8081]
 WS[WebSocket]
 API[REST API]
 SSE[SSE]
 end
 subgraph A[Claude Code Team]
 UC[user_comm]
 GCP[gcp-mcp]
 OCI[oci-mcp]
 DB[db-mcp]
 end

 U --&gt; WS
 WS --&gt; UC
 UC --&gt; API
 API --&gt; GCP
 API --&gt; OCI
 API --&gt; DB
 GCP --&gt; UC
 OCI --&gt; UC
 DB --&gt; UC
 UC --&gt; SSE
 SSE --&gt; U&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="2-user_comm-agent-user-communication-handler"&gt;2. user_comm Agent (User Communication Handler)
&lt;/h2&gt;&lt;h3 id="role-and-responsibilities"&gt;Role and Responsibilities
&lt;/h3&gt;&lt;p&gt;The user_comm Agent is a member of the Claude Code team, communicating with users through Discord channels and collaborating with other agents.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Function&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Input Reception&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Receive Discord messages and route to appropriate agent&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Opinion Request&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Query user opinions at other agents&amp;rsquo; requests&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Notification/Report&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Send system status, warnings, reports&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Team Communication&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Exchange messages with other agents&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="internal-structure"&gt;Internal Structure
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 subgraph UC[user_comm Agent]
 DBot[Discord Bot]
 Agent[UserCommAgent]
 TComm[TeamCommunicator]
 DBot &lt;--&gt; Agent
 Agent &lt;--&gt; TComm
 end
 subgraph DAPI[Discord API]
 M[Messages]
 B[Buttons]
 T[Threads]
 end
 subgraph O[Other Agents]
 GCP[gcp-mcp]
 OCI[oci-mcp]
 AL[alert-mcp]
 end

 DBot &lt;--&gt; M
 DBot &lt;--&gt; B
 DBot &lt;--&gt; T
 TComm --&gt; GCP
 TComm --&gt; OCI
 TComm --&gt; AL&lt;/pre&gt;&lt;h3 id="message-types"&gt;Message Types
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MessageType&lt;/span&gt;(Enum):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TASK_REQUEST &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;task_request&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Task request&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NOTIFICATION &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;notification&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Notification&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; OPINION_REQUEST &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;opinion_request&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Opinion request&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; OPINION_RESPONSE &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;opinion_response&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Opinion response&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; STATUS_REPORT &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;status_report&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Status report&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ERROR &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="key-function-flows"&gt;Key Function Flows
&lt;/h3&gt;&lt;h4 id="input-reception-discord---agent"&gt;Input Reception (Discord -&amp;gt; Agent)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;User: &amp;#34;@gcp-monitor check server status&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; DiscordBot.on_message
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; UserCommAgent._parse_command (target: gcp-monitor)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; TeamCommunicator.send_to_agent
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; Discord: &amp;#34;Request forwarded to gcp-monitor.&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="opinion-request-agent---discord"&gt;Opinion Request (Agent -&amp;gt; Discord)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcp-monitor: &amp;#34;Clean up disk?&amp;#34; -&amp;gt; user_comm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; DiscordBot.ask_opinion (wait for button or reply)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; User response
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; TeamCommunicator.send_to_agent (forward response)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="notificationreport-agent---discord"&gt;Notification/Report (Agent -&amp;gt; Discord)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;oci-monitor: &amp;#34;Disk 92% warning&amp;#34; -&amp;gt; user_comm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; DiscordBot.send_message (Embed format)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="3-lightweight-architecture-without-redis"&gt;3. Lightweight Architecture Without Redis
&lt;/h2&gt;&lt;h3 id="why-remove-redis"&gt;Why Remove Redis?
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Item&lt;/th&gt;
					&lt;th&gt;With Redis&lt;/th&gt;
					&lt;th&gt;With In-Memory&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Thread Lock&lt;/td&gt;
					&lt;td&gt;Redis SET NX&lt;/td&gt;
					&lt;td&gt;Python dict&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Event Distribution&lt;/td&gt;
					&lt;td&gt;Redis Streams&lt;/td&gt;
					&lt;td&gt;Direct SSE&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;State Storage&lt;/td&gt;
					&lt;td&gt;Redis Cache&lt;/td&gt;
					&lt;td&gt;Memory cache&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: In-memory is sufficient for single-instance environments&lt;/p&gt;
&lt;h3 id="gateway-structure"&gt;Gateway Structure
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 subgraph GW[Gateway Service]
 Bot[Discord Bot]
 subgraph C[Core Components]
 Lock[Thread Lock]
 Cache[Message Cache]
 SSEMgr[SSE Manager]
 end
 end
 DAPI[Discord API] &lt;--&gt; Bot
 Bot --&gt; Lock
 Bot --&gt; Cache
 Bot --&gt; SSEMgr
 SSEMgr --&gt; Clients[WebSocket Clients]&lt;/pre&gt;&lt;h3 id="component-details"&gt;Component Details
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Module&lt;/th&gt;
					&lt;th&gt;Role&lt;/th&gt;
					&lt;th&gt;Features&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Discord Bot&lt;/td&gt;
					&lt;td&gt;WebSocket connection&lt;/td&gt;
					&lt;td&gt;Auto-reconnect&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Thread Lock&lt;/td&gt;
					&lt;td&gt;Concurrency control&lt;/td&gt;
					&lt;td&gt;5min timeout&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Message Cache&lt;/td&gt;
					&lt;td&gt;Message storage&lt;/td&gt;
					&lt;td&gt;Max 1000 items&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SSE Manager&lt;/td&gt;
					&lt;td&gt;Real-time delivery&lt;/td&gt;
					&lt;td&gt;Broadcast to all MCPs&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="4-mcp-selection-4-stage-hybrid"&gt;4. MCP Selection: 4-Stage Hybrid
&lt;/h2&gt;&lt;h3 id="selection-priority"&gt;Selection Priority
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style="text-align: center"&gt;Rank&lt;/th&gt;
					&lt;th&gt;Method&lt;/th&gt;
					&lt;th&gt;Example&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;1&lt;/td&gt;
					&lt;td&gt;Slash Command&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/gcp status&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Most explicit&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;2&lt;/td&gt;
					&lt;td&gt;@Mention&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;@gcp-monitor status&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Natural conversation&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;3&lt;/td&gt;
					&lt;td&gt;Keyword Detection&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;gcp server status&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Auto keyword recognition&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: center"&gt;4&lt;/td&gt;
					&lt;td&gt;Channel Assignment&lt;/td&gt;
					&lt;td&gt;#gcp-monitoring&lt;/td&gt;
					&lt;td&gt;Channel default MCP&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="fallback-order"&gt;Fallback Order
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD
 A[Message Received] --&gt; B{Slash Command?}
 B --&gt;|Yes| C[Route to MCP]
 B --&gt;|No| D{Mention?}
 D --&gt;|Yes| C
 D --&gt;|No| E{Keyword?}
 E --&gt;|Yes| C
 E --&gt;|No| F{Channel Default?}
 F --&gt;|Yes| C
 F --&gt;|No| G[Broadcast]&lt;/pre&gt;&lt;h3 id="slash-command-list"&gt;Slash Command List
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Command&lt;/th&gt;
					&lt;th&gt;MCP&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/gcp status [server]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;gcp-mcp&lt;/td&gt;
					&lt;td&gt;GCP server status&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/gcp list&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;gcp-mcp&lt;/td&gt;
					&lt;td&gt;GCP instance list&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/oci status [server]&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;oci-mcp&lt;/td&gt;
					&lt;td&gt;OCI server status&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/oci list&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;oci-mcp&lt;/td&gt;
					&lt;td&gt;OCI instance list&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/db query &amp;lt;sql&amp;gt;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;db-mcp&lt;/td&gt;
					&lt;td&gt;Execute DB query&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/db list&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;db-mcp&lt;/td&gt;
					&lt;td&gt;DB list&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/alert check&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;alert-mcp&lt;/td&gt;
					&lt;td&gt;Check alerts&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="5-thread-lock-rules"&gt;5. Thread Lock Rules
&lt;/h2&gt;&lt;h3 id="lock-behavior"&gt;Lock Behavior
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;sequenceDiagram
 participant M1 as gcp-mcp
 participant GW as Gateway
 participant M2 as oci-mcp
 participant DT as Discord Thread

 Note over M1,DT: Lock Acquisition
 M1-&gt;&gt;+GW: Lock request
 GW--&gt;&gt;-M1: Lock acquired
 M1-&gt;&gt;DT: Send response

 Note over M2,GW: Lock Conflict
 M2-&gt;&gt;GW: Lock request
 GW--&gt;&gt;M2: Lock failed

 Note over M1,GW: 5min timeout
 GW-&gt;&gt;GW: Auto-release lock

 Note over M2,GW: Lock Retry
 M2-&gt;&gt;+GW: Lock request
 GW--&gt;&gt;-M2: Lock acquired&lt;/pre&gt;&lt;h3 id="lock-api"&gt;Lock API
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Method&lt;/th&gt;
					&lt;th&gt;Endpoint&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/api/threads/{id}/acquire&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Acquire lock&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/api/threads/{id}/release&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Release lock&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/api/threads/{id}/lock&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Check lock status&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="requestresponse-example"&gt;Request/Response Example
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Lock Acquire Request&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;POST /api/threads/123456/acquire
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;agent_name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;gcp-mcp&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;timeout&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Lock Acquire Response&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;acquired&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;thread_id&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;123456&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;agent&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;gcp-mcp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="6-mcp-tools-8"&gt;6. MCP Tools (8)
&lt;/h2&gt;&lt;h3 id="tool-list"&gt;Tool List
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Tool&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
					&lt;th&gt;Key Parameters&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_send_message&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Send message&lt;/td&gt;
					&lt;td&gt;channel_id, content&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_get_messages&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Get messages&lt;/td&gt;
					&lt;td&gt;channel_id, limit&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_wait_for_message&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Wait for message&lt;/td&gt;
					&lt;td&gt;channel_id, timeout&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_create_thread&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Create thread&lt;/td&gt;
					&lt;td&gt;channel_id, message_id&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_list_threads&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;List threads&lt;/td&gt;
					&lt;td&gt;channel_id&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_archive_thread&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Archive thread&lt;/td&gt;
					&lt;td&gt;thread_id&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_acquire_thread&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Acquire lock&lt;/td&gt;
					&lt;td&gt;thread_id, agent_name&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_release_thread&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Release lock&lt;/td&gt;
					&lt;td&gt;thread_id, agent_name&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="tool-relationships"&gt;Tool Relationships
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR
 subgraph Lock[Lock Tools]
 Acquire[acquire_thread]
 Release[release_thread]
 end
 subgraph Thread[Thread Tools]
 Create[create_thread]
 List[list_threads]
 Archive[archive_thread]
 end
 subgraph Msg[Message Tools]
 Send[send_message]
 Get[get_messages]
 Wait[wait_for_message]
 end

 Acquire --&gt; Create
 Create --&gt; Send
 Send --&gt; Release&lt;/pre&gt;&lt;h3 id="usage-examples"&gt;Usage Examples
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Send message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discord_send_message(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; channel_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;123456789&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; content&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Server status: OK&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Create thread&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discord_create_thread(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; channel_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;123456789&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;987654321&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Status Check&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Acquire lock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;discord_acquire_thread(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; thread_id&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;111222333&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; agent_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;gcp-mcp&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="7-file-structure"&gt;7. File Structure
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 subgraph P[server_monitor/]
 subgraph Gw[gateway/]
 M1[main.py]
 M2[discord_ws.py]
 M3[thread_lock.py]
 M4[sse.py]
 end
 subgraph Uc[user_comm/]
 A1[agent.py]
 A2[discord_bot.py]
 A3[team_comm.py]
 end
 subgraph Mcp[discord_mcp/]
 S1[server.py]
 end
 subgraph Sh[mcp_shared/]
 MO[monitor/]
 end
 subgraph Doc[docs/]
 D1[MCP_SELECTION_STRATEGY.md]
 D2[MCP_ROUTING_POLICY.md]
 end
 end&lt;/pre&gt;&lt;h3 id="directory-description"&gt;Directory Description
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Path&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;gateway/&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Gateway Service (FastAPI)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;user_comm/&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;User Communication Agent&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;discord_mcp/&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;MCP Server (8 tools)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;mcp_shared/&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Shared MCP tools&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;docs/&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Documentation&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="8-how-to-run"&gt;8. How to Run
&lt;/h2&gt;&lt;h3 id="local-execution"&gt;Local Execution
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Start Gateway Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uvicorn gateway.main:app --host 0.0.0.0 --port &lt;span style="color:#ae81ff"&gt;8081&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Start user_comm Agent (standalone mode)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python main.py --standalone
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Start user_comm Agent (team mode)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python main.py --team server-monitor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Health check&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl http://localhost:8081/health
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Response&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;healthy&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;discord_connected&amp;#34;&lt;/span&gt;: true&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="claude-code-mcp-configuration"&gt;Claude Code MCP Configuration
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ~/.claude/settings.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;discord-gateway&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;python3&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;/path/to/discord_mcp/server.py&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;env&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;GATEWAY_URL&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:8081&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="9-roadmap"&gt;9. Roadmap
&lt;/h2&gt;&lt;h3 id="phase-1-complete"&gt;Phase 1: Complete
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; FastAPI Gateway Service&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Discord WebSocket connection&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Thread Lock (In-Memory)&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; SSE broadcast&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; MCP Server (8 tools)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="phase-2-in-progress"&gt;Phase 2: In Progress
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; user_comm Agent implementation&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Slash command implementation&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Channel default MCP settings&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Keyword auto-detection&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Routing configuration file&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="phase-3-optional"&gt;Phase 3: Optional
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; API authentication (API Key)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Rate Limiting&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Message persistence (SQLite)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;We chose a strategy of starting with a lightweight architecture and expanding when needed.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Item&lt;/th&gt;
					&lt;th&gt;Current&lt;/th&gt;
					&lt;th&gt;Future&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;State Storage&lt;/td&gt;
					&lt;td&gt;In-Memory&lt;/td&gt;
					&lt;td&gt;SQLite (if needed)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Distributed Lock&lt;/td&gt;
					&lt;td&gt;Not used&lt;/td&gt;
					&lt;td&gt;Redis (multi-instance)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Authentication&lt;/td&gt;
					&lt;td&gt;None&lt;/td&gt;
					&lt;td&gt;API Key (if needed)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;User Communication&lt;/td&gt;
					&lt;td&gt;Gateway direct&lt;/td&gt;
					&lt;td&gt;user_comm Agent&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The current structure is sufficient for single instances, and we plan to expand incrementally as traffic grows. The user_comm Agent systematizes user communication and improves collaboration with other agents on the team.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Korean Version:&lt;/strong&gt; &lt;a class="link" href="https://blog.agentthread.dev/ko/post/2026-03-01-013-discord-gateway-mcp-architecture-design/" &gt;한국어 버전&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[Claude Code] Team Agent Communication Architecture</title><link>https://blog.agentthread.dev/post/2026-02-28-002-claude-code-team-agent-communication-architecture/</link><pubDate>Sat, 28 Feb 2026 14:07:38 +0900</pubDate><guid>https://blog.agentthread.dev/post/2026-02-28-002-claude-code-team-agent-communication-architecture/</guid><description>&lt;h1 id="claude-code-team-agent-communication-architecture-design"&gt;Claude Code Team Agent Communication Architecture Design
&lt;/h1&gt;&lt;h2 id="overview"&gt;Overview
&lt;/h2&gt;&lt;p&gt;When multiple AI agents collaborate in Claude Code, an efficient communication method is needed. This article shares the communication architecture designed while building a Discord-integrated server monitoring team.&lt;/p&gt;
&lt;h2 id="problem-definition"&gt;Problem Definition
&lt;/h2&gt;&lt;p&gt;Claude Code has two types of agents:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Python Processes (Daemon)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Discord Gateway, user_comm_daemon, etc.&lt;/li&gt;
&lt;li&gt;Always running, filesystem access available&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LLM Agents (Created as Tasks)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gcp-monitor, oci-monitor, alert-manager, etc.&lt;/li&gt;
&lt;li&gt;Use SendMessage tool, Claude Code native communication&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Communication between these two types was needed.&lt;/p&gt;
&lt;h2 id="considered-approaches"&gt;Considered Approaches
&lt;/h2&gt;&lt;h3 id="1-file-based-message-queue-existing"&gt;1. File-based Message Queue (Existing)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Pros: Simple implementation, no dependencies
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Cons: Latency (~1s), file management required
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-websocket"&gt;2. WebSocket
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Pros: Real-time bidirectional communication
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Cons: Server/client implementation required
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-grpc"&gt;3. gRPC
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Pros: Strong type checking, streaming
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Cons: proto file management, high complexity
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-sqlite-message-hub-adopted"&gt;4. SQLite Message Hub (Adopted)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Pros: Fast (~10ms), transactions, no additional dependencies
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Cons: Works only on a single machine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="final-architecture"&gt;Final Architecture
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ SQLite Message Hub (messages.db) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ~/.claude/teams/{team}/messages.db │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└───────────────────────────┬─────────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ┌───────────────────┼───────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓ ↓ ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌──────────────┐ ┌──────────────┐ ┌──────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ Discord │ │ Python │ │ LLM │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ Gateway │ │ Daemon │ │ Agent │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ (Direct Access)│ │ (Direct Access)│ │ (MCP Tool) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────┘ └──────────────┘ └──────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="sqlite-message-hub-structure"&gt;SQLite Message Hub Structure
&lt;/h2&gt;&lt;h3 id="messages-table"&gt;Messages Table
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; messages (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id INTEGER &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;KEY&lt;/span&gt; AUTOINCREMENT,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message_id TEXT &lt;span style="color:#66d9ef"&gt;UNIQUE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sender TEXT &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; recipient TEXT, &lt;span style="color:#75715e"&gt;-- NULL = broadcast
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message_type TEXT &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; content TEXT &lt;span style="color:#66d9ef"&gt;NOT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; priority TEXT &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;normal&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; metadata TEXT &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;{}&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status TEXT &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pending&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; created_at &lt;span style="color:#66d9ef"&gt;TIMESTAMP&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;CURRENT_TIMESTAMP&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; processed_at &lt;span style="color:#66d9ef"&gt;TIMESTAMP&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; expires_at &lt;span style="color:#66d9ef"&gt;TIMESTAMP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="agent-status-table"&gt;Agent Status Table
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;TABLE&lt;/span&gt; agent_status (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; agent_name TEXT &lt;span style="color:#66d9ef"&gt;PRIMARY&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;KEY&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status TEXT &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;offline&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; last_heartbeat &lt;span style="color:#66d9ef"&gt;TIMESTAMP&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; metadata TEXT &lt;span style="color:#66d9ef"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;{}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="communication-methods"&gt;Communication Methods
&lt;/h2&gt;&lt;h3 id="llm-agent--llm-agent"&gt;LLM Agent ↔ LLM Agent
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;SendMessage&lt;/strong&gt; (Claude Code native)&lt;/li&gt;
&lt;li&gt;Auto-managed, idle notification provided&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="python--llm-agent"&gt;Python ↔ LLM Agent
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SQLite Hub&lt;/strong&gt; + &lt;strong&gt;MCP Tool&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Python accesses SQLite directly&lt;/li&gt;
&lt;li&gt;LLM Agent accesses via MCP Tool&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mcp-server-implementation"&gt;MCP Server Implementation
&lt;/h2&gt;&lt;p&gt;MCP tools for LLM Agents:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@server.list_tools&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;list_tools&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tool(name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;team_send_message&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;...&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tool(name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;team_read_messages&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;...&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tool(name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;team_broadcast&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;...&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tool(name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;team_get_status&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;...&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Tool(name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;team_update_status&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;...&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="message-flow-example"&gt;Message Flow Example
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. Discord user: &amp;#34;Hello&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. Discord Gateway → SQLite: INSERT message
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. user_comm Daemon → SQLite: SELECT pending
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. user_comm → SQLite: INSERT response
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5. Discord Gateway → SQLite: SELECT response
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;6. Discord channel: &amp;#34;Hi there! 👋&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="performance-comparison"&gt;Performance Comparison
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Method&lt;/th&gt;
					&lt;th&gt;Latency&lt;/th&gt;
					&lt;th&gt;Stability&lt;/th&gt;
					&lt;th&gt;Complexity&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;File-based&lt;/td&gt;
					&lt;td&gt;~1000ms&lt;/td&gt;
					&lt;td&gt;Medium&lt;/td&gt;
					&lt;td&gt;Low&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;WebSocket&lt;/td&gt;
					&lt;td&gt;~5ms&lt;/td&gt;
					&lt;td&gt;High&lt;/td&gt;
					&lt;td&gt;Medium&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;~10ms&lt;/td&gt;
					&lt;td&gt;High&lt;/td&gt;
					&lt;td&gt;Low&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;The SQLite Message Hub + MCP Server combination was most suitable for Claude Code team agent communication:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Low Latency&lt;/strong&gt;: 100x faster than file-based&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stability&lt;/strong&gt;: Data integrity guaranteed through transactions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;: Uses Python&amp;rsquo;s built-in sqlite3 without additional dependencies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: Both Python and LLM Agents use the same data source&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="code"&gt;Code
&lt;/h2&gt;&lt;p&gt;Core components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;message_hub.py&lt;/code&gt;: SQLite Message Hub&lt;/li&gt;
&lt;li&gt;&lt;code&gt;team_comm_mcp_server.py&lt;/code&gt;: MCP Server&lt;/li&gt;
&lt;li&gt;&lt;code&gt;discord_gateway.py&lt;/code&gt;: Discord integration gateway&lt;/li&gt;
&lt;li&gt;&lt;code&gt;user_comm_daemon.py&lt;/code&gt;: Message processing daemon&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Korean Version:&lt;/strong&gt; &lt;a class="link" href="https://blog.agentthread.dev/ko/post/2026-02-28-002-claude-code-team-agent-communication-architecture/" &gt;한국어 버전&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>