<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Léa Moreau</title>
    <description>The latest articles on DEV Community by Léa Moreau (@leamoreau).</description>
    <link>https://dev.to/leamoreau</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4023322%2F0c3933d4-8902-4912-a9fd-c5e23aefdf2c.png</url>
      <title>DEV Community: Léa Moreau</title>
      <link>https://dev.to/leamoreau</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leamoreau"/>
    <language>en</language>
    <item>
      <title>Second pack shipped: senior-engineer workflows as Claude Code slash commands</title>
      <dc:creator>Léa Moreau</dc:creator>
      <pubDate>Mon, 13 Jul 2026 16:14:35 +0000</pubDate>
      <link>https://dev.to/leamoreau/second-pack-shipped-senior-engineer-workflows-as-claude-code-slash-commands-3f7m</link>
      <guid>https://dev.to/leamoreau/second-pack-shipped-senior-engineer-workflows-as-claude-code-slash-commands-3f7m</guid>
      <description>&lt;p&gt;I shipped a second small pack this week: 10 Claude Code slash commands, 4 subagents, 3 hook recipes and 2 templates, built from the same discipline as the MCP kit: no fix without a reproduction, no refactor without a test harness, no "optimization" without a measurement.&lt;/p&gt;

&lt;p&gt;Commands like &lt;code&gt;/ship&lt;/code&gt;, &lt;code&gt;/fix-issue&lt;/code&gt;, &lt;code&gt;/refactor-safe&lt;/code&gt;, &lt;code&gt;/test-first&lt;/code&gt; and &lt;code&gt;/security-pass&lt;/code&gt; turn those rules into two-keystroke invocations instead of paragraphs you retype every session. Plain Markdown, no build step, everything editable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10 commands:&lt;/strong&gt; ship, fix-issue, review, refactor-safe, test-first, security-pass, perf-pass, doc-sync, release-notes, onboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4 subagents:&lt;/strong&gt; test-writer, bug-hunter (read-only, zero-false-positive discipline), docs-writer (no-fluff contract), dep-auditor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 hook recipes:&lt;/strong&gt; auto-format on edit, block edits to protected paths (lockfiles, migrations, .env), tests-must-pass-before-stopping.&lt;/p&gt;

&lt;p&gt;$9, one developer / unlimited projects: &lt;a href="https://leamoreau1988.gumroad.com/l/claude-code-power-pack" rel="noopener noreferrer"&gt;https://leamoreau1988.gumroad.com/l/claude-code-power-pack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions about any of the commands in the comments.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>productivity</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Notes on running an MCP server in production</title>
      <dc:creator>Léa Moreau</dc:creator>
      <pubDate>Fri, 10 Jul 2026 10:52:57 +0000</pubDate>
      <link>https://dev.to/leamoreau/notes-on-running-an-mcp-server-in-production-19lc</link>
      <guid>https://dev.to/leamoreau/notes-on-running-an-mcp-server-in-production-19lc</guid>
      <description>&lt;p&gt;Most MCP tutorials stop at a single stdio tool. These notes cover what I had to change once a server of mine had actual users, in the order the problems appeared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging corrupts the protocol if you let it
&lt;/h2&gt;

&lt;p&gt;The stdio transport uses stdout for JSON-RPC frames. A single &lt;code&gt;console.log&lt;/code&gt;, including one buried in a dependency, breaks the stream. The symptom is a client that disconnects for no visible reason, and nothing in the error output points back to the cause.&lt;/p&gt;

&lt;p&gt;The fix is unglamorous. Every log line goes to stderr through a small structured wrapper, and that entire class of bug disappears.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plan for the second transport early
&lt;/h2&gt;

&lt;p&gt;Editor clients (Claude Desktop, Claude Code, Cursor) talk stdio to a local process. Hosting the same server for a team requires Streamable HTTP, and the refactor is painful if the code assumes one global server instance.&lt;/p&gt;

&lt;p&gt;I build everything behind a factory now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;McpServer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;McpServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SERVER_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SERVER_VERSION&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;registerTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;registerResources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;registerPrompts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stdio entrypoint calls it once at startup. The HTTP handler calls it per request and keeps no session state. Request isolation comes from the structure rather than from discipline, and horizontal scaling requires no coordination between replicas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validate configuration at boot
&lt;/h2&gt;

&lt;p&gt;A malformed environment variable should stop the process immediately with a readable message, instead of surfacing hours later as strange behavior. I parse all config with Zod at startup.&lt;/p&gt;

&lt;p&gt;Tool inputs get the same treatment. Declare them as Zod schemas and the SDK validates every call before your handler runs, so handlers only ever receive typed, checked arguments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat a fetch tool as a proxy
&lt;/h2&gt;

&lt;p&gt;A tool that fetches URLs is an HTTP proxy driven by a language model, and the model reads untrusted text all day. Mine enforces four limits: http and https only, an optional hostname allowlist, a byte cap on responses, and a timeout. Without the allowlist, a prompted model can probe your internal network from inside your infrastructure. This is a standard SSRF vector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test against the real server, in memory
&lt;/h2&gt;

&lt;p&gt;The SDK provides &lt;code&gt;InMemoryTransport.createLinkedPair()&lt;/code&gt;. A real client connects to the real server inside the test process, with no sockets and no subprocess management. My suite exercises tools, resources and prompts this way and completes in a few seconds on Node 20, 22 and 24.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update (July 11):&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/skillselion"&gt;@skillselion&lt;/a&gt; points out in the comments that the in-memory pair structurally cannot catch stdout corruption, the exact bug this post opens with, because it bypasses the real stdio framing. He is right. The template now ships a subprocess smoke test next to the in-memory suite: it spawns the actual entrypoint with the SDK's &lt;code&gt;StdioClientTransport&lt;/code&gt; and completes an initialize plus tools/list exchange over a real pipe, so anything that pollutes stdout fails CI instead of disconnecting a user.&lt;/p&gt;

&lt;p&gt;His other two points are covered too. The suite now asserts the serialized &lt;code&gt;tools/list&lt;/code&gt; payload stays under a size budget, since every rich &lt;code&gt;.describe()&lt;/code&gt; string and nested Zod object ends up in what each client downloads at session start. And a raw JSON-RPC test confirms the server correctly echoes back an older &lt;em&gt;supported&lt;/em&gt; protocol version when a client requests one, instead of forcing the latest, which matters for long-lived editor clients that pin older revisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The template
&lt;/h2&gt;

&lt;p&gt;I assembled these pieces into a template I now start every server from: both transports, the guarded fetch tool, the test setup, Docker and CI. It costs $19 and lives &lt;a href="https://leamoreau1988.gumroad.com/l/mcp-quickstart-kit" rel="noopener noreferrer"&gt;on my Gumroad page&lt;/a&gt;. The notes above contain most of the design, so building your own from them is a perfectly reasonable choice too.&lt;/p&gt;

&lt;p&gt;If production has bitten you somewhere I did not list, leave a comment. I am collecting these.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>typescript</category>
      <category>claude</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
