<?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: Angel Jose VARGAS GUTIERREZ</title>
    <description>The latest articles on DEV Community by Angel Jose VARGAS GUTIERREZ (@angel_josevargasgutierr).</description>
    <link>https://dev.to/angel_josevargasgutierr</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3282608%2Fc8b1e47e-305e-4bab-92ec-27be708f6ff0.png</url>
      <title>DEV Community: Angel Jose VARGAS GUTIERREZ</title>
      <link>https://dev.to/angel_josevargasgutierr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/angel_josevargasgutierr"/>
    <language>en</language>
    <item>
      <title>Análisis Exhaustivo: Despliegue de Servidores MCP en Google Cloud Run</title>
      <dc:creator>Angel Jose VARGAS GUTIERREZ</dc:creator>
      <pubDate>Mon, 01 Dec 2025 08:24:44 +0000</pubDate>
      <link>https://dev.to/angel_josevargasgutierr/analisis-exhaustivo-despliegue-de-servidores-mcp-en-google-cloud-run-1po1</link>
      <guid>https://dev.to/angel_josevargasgutierr/analisis-exhaustivo-despliegue-de-servidores-mcp-en-google-cloud-run-1po1</guid>
      <description>&lt;p&gt;description: Problemas técnicos reales al desplegar servidores MCP en Cloud Run&lt;/p&gt;

&lt;h2&gt;
  
  
  tags: mcp, cloudrun, serverless, review
&lt;/h2&gt;

&lt;h1&gt;
  
  
  Análisis Crítico: Servidores MCP en Google Cloud Run
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🎯 Contexto
&lt;/h2&gt;

&lt;p&gt;Revisé un tutorial sobre desplegar servidores MCP (Model Context Protocol) en Google Cloud Run. Encontré varios problemas técnicos críticos que impiden su funcionamiento real.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 Problema #1: Transporte Incompatible
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Error Fatal&lt;/strong&gt;: El tutorial usa &lt;code&gt;StdioServerTransport&lt;/code&gt; en Cloud Run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Por qué falla&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Run requiere HTTP/HTTPS&lt;/li&gt;
&lt;li&gt;StdioServerTransport usa stdin/stdout&lt;/li&gt;
&lt;li&gt;Resultado: servidor no funcional&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✅ Solución&lt;/strong&gt;:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SSEServerTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@modelcontextprotocol/sdk/server/sse.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&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;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8080&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;Server&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;weather-mcp-server&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/sse&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;transport&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;SSEServerTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/messages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&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;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/messages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Manejar mensajes MCP&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚨 Problema #2: package.json Incompleto
&lt;/h2&gt;

&lt;p&gt;El tutorial menciona &lt;code&gt;npm run build&lt;/code&gt; pero nunca lo define.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Solución&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp-server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node dist/server.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@modelcontextprotocol/sdk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.5.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"express"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.18.2"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5.3.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@types/node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^20.10.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚨 Problema #3: Configuración Cliente Incorrecta
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: Usa &lt;code&gt;curl&lt;/code&gt; como comando MCP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"weather"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"curl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Desktop necesita un proceso stdio, no HTTP directo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Solución: Proxy Local&lt;/strong&gt;&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="c1"&gt;// mcp-proxy.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;process&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MCP_SERVER_URL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&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="s2"&gt;/messages`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&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;&lt;strong&gt;Configuración&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"weather"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/mcp-proxy.js"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"MCP_SERVER_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-server.run.app"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚨 Problema #4: Sin Seguridad
&lt;/h2&gt;

&lt;p&gt;Tutorial menciona autenticación pero no la implementa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ API Keys&lt;/strong&gt;:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;authenticateAPIKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&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;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-api-key&lt;/span&gt;&lt;span class="dl"&gt;"&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;validKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;API_KEYS&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;validKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;))&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/sse&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authenticateAPIKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/messages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authenticateAPIKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚨 Problema #5: Dockerfile Básico
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Versión Optimizada&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:18-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json tsconfig.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; src/ ./src/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18-alpine&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;addgroup &lt;span class="nt"&gt;-g&lt;/span&gt; 1001 nodejs &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; adduser &lt;span class="nt"&gt;-S&lt;/span&gt; nodejs &lt;span class="nt"&gt;-u&lt;/span&gt; 1001
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/dist ./dist&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="nt"&gt;--only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; nodejs&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "dist/server.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  💰 Costos Reales
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cloud Run Pricing&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100K requests/mes&lt;/li&gt;
&lt;li&gt;200ms promedio&lt;/li&gt;
&lt;li&gt;512MB memoria&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Costo&lt;/strong&gt;: ~$0.55/mes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free tier cubre&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2M requests/mes&lt;/li&gt;
&lt;li&gt;360K vCPU-segundos&lt;/li&gt;
&lt;li&gt;180K GiB-segundos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Para desarrollo: $0&lt;/strong&gt; 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Tests Esenciales
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vitest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MCP Server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lista herramientas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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;handleRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tools/list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;maneja errores&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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;handleRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tools/call&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&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;h2&gt;
  
  
  🎯 Caso de Uso: Firestore
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Firestore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@google-cloud/firestore&lt;/span&gt;&lt;span class="dl"&gt;"&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;db&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;Firestore&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;setRequestHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CallToolRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;query_db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&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;snapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
      &lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;};&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;h2&gt;
  
  
  📊 Valoración
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problemas&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Transporte incompatible&lt;/li&gt;
&lt;li&gt;❌ Config cliente incorrecta&lt;/li&gt;
&lt;li&gt;❌ Sin seguridad implementada&lt;/li&gt;
&lt;li&gt;❌ Scripts faltantes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fortalezas&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Buena estructura&lt;/li&gt;
&lt;li&gt;✅ Ejemplo claro&lt;/li&gt;
&lt;li&gt;✅ Menciona best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Puntuación: 6.5/10&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Con correcciones: &lt;strong&gt;9/10&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⏱️ Tiempo Real
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Básico funcional&lt;/strong&gt;: 30-45 min&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production-ready&lt;/strong&gt;: 2-4 horas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Completo con CI/CD&lt;/strong&gt;: 1-2 días&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La promesa de "10 minutos" es muy optimista.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Recursos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;MCP Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/run/docs" rel="noopener noreferrer"&gt;Cloud Run Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💭 Conclusión
&lt;/h2&gt;

&lt;p&gt;El tutorial tiene buenas intenciones pero fallas técnicas críticas. Con las correcciones aquí propuestas, puede convertirse en un recurso valioso para la comunidad MCP.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>architecture</category>
      <category>devops</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Jest Testing Framework: Complete Guide with Real-World Examples</title>
      <dc:creator>Angel Jose VARGAS GUTIERREZ</dc:creator>
      <pubDate>Wed, 02 Jul 2025 19:33:55 +0000</pubDate>
      <link>https://dev.to/angel_josevargasgutierr/jest-testing-framework-complete-guide-with-real-world-examples-3n30</link>
      <guid>https://dev.to/angel_josevargasgutierr/jest-testing-framework-complete-guide-with-real-world-examples-3n30</guid>
      <description>&lt;p&gt;functional repository with examples: &lt;br&gt;
&lt;a href="https://github.com/AngelVargasGutierrez/JavaScript_EJemplos" rel="noopener noreferrer"&gt;https://github.com/AngelVargasGutierrez/JavaScript_EJemplos&lt;/a&gt;&lt;br&gt;
Introduction&lt;br&gt;
Jest is a delightful JavaScript testing framework developed by Facebook (now Meta) that focuses on simplicity and developer experience. It's the go-to testing solution for React applications and works seamlessly with any JavaScript project. Jest provides zero-configuration setup, built-in assertion library, mocking capabilities, and code coverage reports out of the box.&lt;br&gt;
Why Choose Jest?&lt;/p&gt;

&lt;p&gt;Zero Configuration: Works immediately without complex setup&lt;br&gt;
Snapshot Testing: Captures component output for regression testing&lt;br&gt;
Built-in Mocking: Powerful mocking system for dependencies&lt;br&gt;
Parallel Testing: Runs tests in parallel for faster execution&lt;br&gt;
Code Coverage: Built-in coverage reports without additional tools&lt;br&gt;
Watch Mode: Automatically runs tests when files change&lt;/p&gt;

&lt;p&gt;Installation &amp;amp; Setup&lt;br&gt;
Basic Installation&lt;br&gt;
bash# Using npm&lt;br&gt;
npm install --save-dev jest&lt;/p&gt;

&lt;h1&gt;
  
  
  Using yarn
&lt;/h1&gt;

&lt;p&gt;yarn add --dev jest&lt;/p&gt;

&lt;h1&gt;
  
  
  For TypeScript support
&lt;/h1&gt;

&lt;p&gt;npm install --save-dev jest @types/jest ts-jest&lt;br&gt;
Package.json Configuration&lt;br&gt;
json{&lt;br&gt;
  "name": "jest-testing-demo",&lt;br&gt;
  "version": "1.0.0",&lt;br&gt;
  "scripts": {&lt;br&gt;
    "test": "jest",&lt;br&gt;
    "test:watch": "jest --watch",&lt;br&gt;
    "test:coverage": "jest --coverage"&lt;br&gt;
  },&lt;br&gt;
  "jest": {&lt;br&gt;
    "testEnvironment": "node",&lt;br&gt;
    "collectCoverageFrom": [&lt;br&gt;
      "src/&lt;strong&gt;/*.{js,jsx}",&lt;br&gt;
      "!src/index.js"&lt;br&gt;
    ]&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
Jest Configuration File (jest.config.js)&lt;br&gt;
javascriptmodule.exports = {&lt;br&gt;
  testEnvironment: 'node',&lt;br&gt;
  roots: ['/src'],&lt;br&gt;
  testMatch: [&lt;br&gt;
    '&lt;/strong&gt;/&lt;strong&gt;tests&lt;/strong&gt;/&lt;strong&gt;/*.+(ts|tsx|js)',&lt;br&gt;
    '&lt;/strong&gt;/&lt;em&gt;.(test|spec).+(ts|tsx|js)'&lt;br&gt;
  ],&lt;br&gt;
  transform: {&lt;br&gt;
    '^.+\.(ts|tsx)$': 'ts-jest'&lt;br&gt;
  },&lt;br&gt;
  collectCoverageFrom: [&lt;br&gt;
    'src/&lt;/em&gt;&lt;em&gt;/&lt;/em&gt;.{js,ts}',&lt;br&gt;
    '!src/*&lt;em&gt;/&lt;/em&gt;.d.ts'&lt;br&gt;
  ],&lt;br&gt;
  coverageReporters: ['text', 'lcov', 'html']&lt;br&gt;
};&lt;br&gt;
Real-World Examples&lt;br&gt;
Example 1: Basic Unit Testing&lt;br&gt;
Let's create a calculator module and test it:&lt;br&gt;
javascript// src/calculator.js&lt;br&gt;
class Calculator {&lt;br&gt;
  add(a, b) {&lt;br&gt;
    return a + b;&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;subtract(a, b) {&lt;br&gt;
    return a - b;&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;multiply(a, b) {&lt;br&gt;
    return a * b;&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;divide(a, b) {&lt;br&gt;
    if (b === 0) {&lt;br&gt;
      throw new Error('Division by zero is not allowed');&lt;br&gt;
    }&lt;br&gt;
    return a / b;&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;power(base, exponent) {&lt;br&gt;
    return Math.pow(base, exponent);&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;module.exports = Calculator;&lt;br&gt;
javascript// src/&lt;strong&gt;tests&lt;/strong&gt;/calculator.test.js&lt;br&gt;
const Calculator = require('../calculator');&lt;/p&gt;

&lt;p&gt;describe('Calculator', () =&amp;gt; {&lt;br&gt;
  let calculator;&lt;/p&gt;

&lt;p&gt;beforeEach(() =&amp;gt; {&lt;br&gt;
    calculator = new Calculator();&lt;br&gt;
  });&lt;/p&gt;

&lt;p&gt;describe('Addition', () =&amp;gt; {&lt;br&gt;
    test('should add two positive numbers', () =&amp;gt; {&lt;br&gt;
      expect(calculator.add(2, 3)).toBe(5);&lt;br&gt;
    });&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test('should add negative numbers', () =&amp;gt; {
  expect(calculator.add(-2, -3)).toBe(-5);
});

test('should add zero', () =&amp;gt; {
  expect(calculator.add(5, 0)).toBe(5);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;describe('Division', () =&amp;gt; {&lt;br&gt;
    test('should divide two numbers', () =&amp;gt; {&lt;br&gt;
      expect(calculator.divide(10, 2)).toBe(5);&lt;br&gt;
    });&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test('should throw error when dividing by zero', () =&amp;gt; {
  expect(() =&amp;gt; calculator.divide(10, 0)).toThrow('Division by zero is not allowed');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;describe('Power', () =&amp;gt; {&lt;br&gt;
    test('should calculate power correctly', () =&amp;gt; {&lt;br&gt;
      expect(calculator.power(2, 3)).toBe(8);&lt;br&gt;
      expect(calculator.power(5, 0)).toBe(1);&lt;br&gt;
    });&lt;br&gt;
  });&lt;br&gt;
});&lt;br&gt;
Example 2: Asynchronous Testing&lt;br&gt;
javascript// src/userService.js&lt;br&gt;
const axios = require('axios');&lt;/p&gt;

&lt;p&gt;class UserService {&lt;br&gt;
  constructor(apiUrl = '&lt;a href="https://jsonplaceholder.typicode.com'" rel="noopener noreferrer"&gt;https://jsonplaceholder.typicode.com'&lt;/a&gt;) {&lt;br&gt;
    this.apiUrl = apiUrl;&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;async getUser(id) {&lt;br&gt;
    try {&lt;br&gt;
      const response = await axios.get(&lt;code&gt;${this.apiUrl}/users/${id}&lt;/code&gt;);&lt;br&gt;
      return response.data;&lt;br&gt;
    } catch (error) {&lt;br&gt;
      throw new Error(&lt;code&gt;Failed to fetch user: ${error.message}&lt;/code&gt;);&lt;br&gt;
    }&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;async createUser(userData) {&lt;br&gt;
    try {&lt;br&gt;
      const response = await axios.post(&lt;code&gt;${this.apiUrl}/users&lt;/code&gt;, userData);&lt;br&gt;
      return response.data;&lt;br&gt;
    } catch (error) {&lt;br&gt;
      throw new Error(&lt;code&gt;Failed to create user: ${error.message}&lt;/code&gt;);&lt;br&gt;
    }&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;validateEmail(email) {&lt;br&gt;
    const emailRegex = /^[^\s@]+@[^\s@]+.[^\s@]+$/;&lt;br&gt;
    return emailRegex.test(email);&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;module.exports = UserService;&lt;br&gt;
javascript// src/&lt;strong&gt;tests&lt;/strong&gt;/userService.test.js&lt;br&gt;
const axios = require('axios');&lt;br&gt;
const UserService = require('../userService');&lt;/p&gt;

&lt;p&gt;// Mock axios&lt;br&gt;
jest.mock('axios');&lt;br&gt;
const mockedAxios = axios;&lt;/p&gt;

&lt;p&gt;describe('UserService', () =&amp;gt; {&lt;br&gt;
  let userService;&lt;/p&gt;

&lt;p&gt;beforeEach(() =&amp;gt; {&lt;br&gt;
    userService = new UserService();&lt;br&gt;
    jest.clearAllMocks();&lt;br&gt;
  });&lt;/p&gt;

&lt;p&gt;describe('getUser', () =&amp;gt; {&lt;br&gt;
    test('should fetch user successfully', async () =&amp;gt; {&lt;br&gt;
      const userData = { id: 1, name: 'John Doe', email: '&lt;a href="mailto:john@example.com"&gt;john@example.com&lt;/a&gt;' };&lt;br&gt;
      mockedAxios.get.mockResolvedValue({ data: userData });&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const result = await userService.getUser(1);

  expect(mockedAxios.get).toHaveBeenCalledWith('https://jsonplaceholder.typicode.com/users/1');
  expect(result).toEqual(userData);
});

test('should handle fetch error', async () =&amp;gt; {
  mockedAxios.get.mockRejectedValue(new Error('Network error'));

  await expect(userService.getUser(1)).rejects.toThrow('Failed to fetch user: Network error');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;describe('createUser', () =&amp;gt; {&lt;br&gt;
    test('should create user successfully', async () =&amp;gt; {&lt;br&gt;
      const newUser = { name: 'Jane Doe', email: '&lt;a href="mailto:jane@example.com"&gt;jane@example.com&lt;/a&gt;' };&lt;br&gt;
      const createdUser = { id: 2, ...newUser };&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  mockedAxios.post.mockResolvedValue({ data: createdUser });

  const result = await userService.createUser(newUser);

  expect(mockedAxios.post).toHaveBeenCalledWith('https://jsonplaceholder.typicode.com/users', newUser);
  expect(result).toEqual(createdUser);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;describe('validateEmail', () =&amp;gt; {&lt;br&gt;
    test('should validate correct email addresses', () =&amp;gt; {&lt;br&gt;
      expect(userService.validateEmail('&lt;a href="mailto:test@example.com"&gt;test@example.com&lt;/a&gt;')).toBe(true);&lt;br&gt;
      expect(userService.validateEmail('&lt;a href="mailto:user.name@domain.co.uk"&gt;user.name@domain.co.uk&lt;/a&gt;')).toBe(true);&lt;br&gt;
    });&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test('should reject invalid email addresses', () =&amp;gt; {
  expect(userService.validateEmail('invalid-email')).toBe(false);
  expect(userService.validateEmail('test@')).toBe(false);
  expect(userService.validateEmail('@example.com')).toBe(false);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;br&gt;
});&lt;br&gt;
Example 3: React Component Testing&lt;br&gt;
javascript// src/components/TodoItem.jsx&lt;br&gt;
import React from 'react';&lt;/p&gt;

&lt;p&gt;const TodoItem = ({ todo, onToggle, onDelete }) =&amp;gt; {&lt;br&gt;
  return (&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
      
        type="checkbox"&lt;br&gt;
        checked={todo.completed}&lt;br&gt;
        onChange={() =&amp;gt; onToggle(todo.id)}&lt;br&gt;
        data-testid="todo-checkbox"&lt;br&gt;
      /&amp;gt;&lt;br&gt;
      &lt;span&gt;&lt;br&gt;
        {todo.text}&lt;br&gt;
      &lt;/span&gt;&lt;br&gt;
      
        onClick={() =&amp;gt; onDelete(todo.id)}&lt;br&gt;
        className="delete-btn"&lt;br&gt;
        data-testid="delete-button"&lt;br&gt;
      &amp;gt;&lt;br&gt;
        Delete&lt;br&gt;
      &lt;br&gt;
    &lt;br&gt;
  );&lt;br&gt;
};

&lt;p&gt;export default TodoItem;&lt;br&gt;
javascript// src/components/&lt;strong&gt;tests&lt;/strong&gt;/TodoItem.test.jsx&lt;br&gt;
import React from 'react';&lt;br&gt;
import { render, fireEvent, screen } from '@testing-library/react';&lt;br&gt;
import '@testing-library/jest-dom';&lt;br&gt;
import TodoItem from '../TodoItem';&lt;/p&gt;

&lt;p&gt;describe('TodoItem', () =&amp;gt; {&lt;br&gt;
  const mockTodo = {&lt;br&gt;
    id: 1,&lt;br&gt;
    text: 'Test todo item',&lt;br&gt;
    completed: false&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;const mockOnToggle = jest.fn();&lt;br&gt;
  const mockOnDelete = jest.fn();&lt;/p&gt;

&lt;p&gt;beforeEach(() =&amp;gt; {&lt;br&gt;
    jest.clearAllMocks();&lt;br&gt;
  });&lt;/p&gt;

&lt;p&gt;test('renders todo item correctly', () =&amp;gt; {&lt;br&gt;
    render(&lt;br&gt;
      
        todo={mockTodo} &lt;br&gt;
        onToggle={mockOnToggle} &lt;br&gt;
        onDelete={mockOnDelete} &lt;br&gt;
      /&amp;gt;&lt;br&gt;
    );&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expect(screen.getByTestId('todo-text')).toHaveTextContent('Test todo item');
expect(screen.getByTestId('todo-checkbox')).not.toBeChecked();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;test('calls onToggle when checkbox is clicked', () =&amp;gt; {&lt;br&gt;
    render(&lt;br&gt;
      
        todo={mockTodo} &lt;br&gt;
        onToggle={mockOnToggle} &lt;br&gt;
        onDelete={mockOnDelete} &lt;br&gt;
      /&amp;gt;&lt;br&gt;
    );&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fireEvent.click(screen.getByTestId('todo-checkbox'));
expect(mockOnToggle).toHaveBeenCalledWith(1);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;test('calls onDelete when delete button is clicked', () =&amp;gt; {&lt;br&gt;
    render(&lt;br&gt;
      
        todo={mockTodo} &lt;br&gt;
        onToggle={mockOnToggle} &lt;br&gt;
        onDelete={mockOnDelete} &lt;br&gt;
      /&amp;gt;&lt;br&gt;
    );&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fireEvent.click(screen.getByTestId('delete-button'));
expect(mockOnDelete).toHaveBeenCalledWith(1);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;test('applies completed class when todo is completed', () =&amp;gt; {&lt;br&gt;
    const completedTodo = { ...mockTodo, completed: true };&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;render(
  &amp;lt;TodoItem 
    todo={completedTodo} 
    onToggle={mockOnToggle} 
    onDelete={mockOnDelete} 
  /&amp;gt;
);

expect(screen.getByTestId('todo-checkbox')).toBeChecked();
expect(screen.getByRole('checkbox').closest('.todo-item')).toHaveClass('completed');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;br&gt;
});&lt;br&gt;
Example 4: Snapshot Testing&lt;br&gt;
javascript// src/components/&lt;strong&gt;tests&lt;/strong&gt;/TodoItem.snapshot.test.jsx&lt;br&gt;
import React from 'react';&lt;br&gt;
import { render } from '@testing-library/react';&lt;br&gt;
import TodoItem from '../TodoItem';&lt;/p&gt;

&lt;p&gt;describe('TodoItem Snapshots', () =&amp;gt; {&lt;br&gt;
  test('should match snapshot for incomplete todo', () =&amp;gt; {&lt;br&gt;
    const todo = { id: 1, text: 'Buy groceries', completed: false };&lt;br&gt;
    const { container } = render(&lt;br&gt;
      &lt;br&gt;
    );&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expect(container.firstChild).toMatchSnapshot();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;test('should match snapshot for completed todo', () =&amp;gt; {&lt;br&gt;
    const todo = { id: 2, text: 'Walk the dog', completed: true };&lt;br&gt;
    const { container } = render(&lt;br&gt;
      &lt;br&gt;
    );&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expect(container.firstChild).toMatchSnapshot();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;br&gt;
});&lt;br&gt;
Comparative Analysis&lt;br&gt;
Pros of Jest&lt;br&gt;
✅ Zero Configuration: Works out of the box with minimal setup&lt;br&gt;
✅ Built-in Assertions: No need for additional assertion libraries&lt;br&gt;
✅ Powerful Mocking: Comprehensive mocking system for modules and functions&lt;br&gt;
✅ Snapshot Testing: Excellent for UI regression testing&lt;br&gt;
✅ Code Coverage: Built-in coverage reports&lt;br&gt;
✅ Parallel Execution: Fast test execution&lt;br&gt;
✅ Watch Mode: Great developer experience&lt;br&gt;
✅ Large Community: Extensive documentation and community support&lt;br&gt;
Cons of Jest&lt;br&gt;
❌ Memory Usage: Can be memory-intensive for large test suites&lt;br&gt;
❌ Slow Startup: Initial startup can be slow for large projects&lt;br&gt;
❌ Limited Browser Testing: Primarily designed for Node.js environment&lt;br&gt;
❌ Snapshot Brittleness: Snapshots can be fragile and require maintenance&lt;br&gt;
When to Use Jest vs Alternatives&lt;br&gt;
Use Jest When:&lt;/p&gt;

&lt;p&gt;Building React applications&lt;br&gt;
Need zero-configuration setup&lt;br&gt;
Want built-in mocking and coverage&lt;br&gt;
Working with Node.js projects&lt;br&gt;
Team prefers all-in-one solution&lt;/p&gt;

&lt;p&gt;Consider Alternatives When:&lt;/p&gt;

&lt;p&gt;Vitest: For Vite-based projects (faster execution)&lt;br&gt;
Mocha + Chai: Need more flexibility in assertion styles&lt;br&gt;
Cypress/Playwright: For end-to-end testing&lt;br&gt;
Jasmine: For simpler projects without advanced features&lt;/p&gt;

&lt;p&gt;Repository Examples&lt;br&gt;
🔗 Demo Repository: jest-testing-examples&lt;br&gt;
Repository Structure:&lt;br&gt;
jjest-testing-examples/&lt;br&gt;
├── src/&lt;br&gt;
│   ├── calculator.js&lt;br&gt;
│   ├── userService.js&lt;br&gt;
│   ├── components/&lt;br&gt;
│   │   └── TodoItem.jsx&lt;br&gt;
│   └── &lt;strong&gt;tests&lt;/strong&gt;/&lt;br&gt;
│       ├── calculator.test.js&lt;br&gt;
│       ├── userService.test.js&lt;br&gt;
│       └── components/&lt;br&gt;
│           ├── TodoItem.test.jsx&lt;br&gt;
│           └── TodoItem.snapshot.test.jsx&lt;br&gt;
├── package.json&lt;br&gt;
├── jest.config.js&lt;br&gt;
├── babel.config.js&lt;br&gt;
├── README.md&lt;br&gt;
└── node_modules/&lt;br&gt;
Key Features Demonstrated:&lt;/p&gt;

&lt;p&gt;Unit testing with various assertion types&lt;br&gt;
Asynchronous testing with mocks&lt;br&gt;
React component testing with Testing Library&lt;br&gt;
Snapshot testing for UI components&lt;br&gt;
Code coverage configuration&lt;br&gt;
Multiple test environments&lt;/p&gt;

&lt;p&gt;Running the Examples:&lt;br&gt;
bashgit clone &lt;a href="https://github.com/AngelVargasGutierrez/JavaScript_EJemplos" rel="noopener noreferrer"&gt;https://github.com/AngelVargasGutierrez/JavaScript_EJemplos&lt;/a&gt;&lt;br&gt;
cd jest-testing-examples&lt;br&gt;
npm install&lt;br&gt;
npm test                    # Run all tests&lt;br&gt;
npm run test:watch         # Run tests in watch mode&lt;br&gt;
npm run test:coverage      # Run tests with coverage report&lt;br&gt;
Best Practices and Advanced Techniques&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Organize Tests with Describe Blocks
javascriptdescribe('UserService', () =&amp;gt; {
describe('Authentication', () =&amp;gt; {
test('should login with valid credentials', () =&amp;gt; {
  // test implementation
});
});&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;describe('Data Fetching', () =&amp;gt; {&lt;br&gt;
    test('should fetch user data', () =&amp;gt; {&lt;br&gt;
      // test implementation&lt;br&gt;
    });&lt;br&gt;
  });&lt;br&gt;
});&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use Setup and Teardown Hooks
javascriptdescribe('Database Operations', () =&amp;gt; {
beforeAll(async () =&amp;gt; {
// Setup database connection
await connectToDatabase();
});&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;afterAll(async () =&amp;gt; {&lt;br&gt;
    // Close database connection&lt;br&gt;
    await disconnectFromDatabase();&lt;br&gt;
  });&lt;/p&gt;

&lt;p&gt;beforeEach(() =&amp;gt; {&lt;br&gt;
    // Reset test data before each test&lt;br&gt;
    resetTestData();&lt;br&gt;
  });&lt;/p&gt;

&lt;p&gt;afterEach(() =&amp;gt; {&lt;br&gt;
    // Clean up after each test&lt;br&gt;
    clearTestData();&lt;br&gt;
  });&lt;br&gt;
});&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Custom Matchers
javascript// Custom matcher
expect.extend({
toBeWithinRange(received, floor, ceiling) {
const pass = received &amp;gt;= floor &amp;amp;&amp;amp; received &amp;lt;= ceiling;
if (pass) {
  return {
    message: () =&amp;gt; &lt;code&gt;expected ${received} not to be within range ${floor} - ${ceiling}&lt;/code&gt;,
    pass: true,
  };
} else {
  return {
    message: () =&amp;gt; &lt;code&gt;expected ${received} to be within range ${floor} - ${ceiling}&lt;/code&gt;,
    pass: false,
  };
}
},
});&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;// Usage&lt;br&gt;
test('random number should be within range', () =&amp;gt; {&lt;br&gt;
  expect(Math.random() * 100).toBeWithinRange(0, 100);&lt;br&gt;
});&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Testing Error Boundaries (React)
javascriptimport React from 'react';
import { render, screen } from '@testing-library/react';
import ErrorBoundary from '../ErrorBoundary';&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;const ThrowError = ({ shouldThrow }) =&amp;gt; {&lt;br&gt;
  if (shouldThrow) {&lt;br&gt;
    throw new Error('Test error');&lt;br&gt;
  }&lt;br&gt;
  return &lt;/p&gt;No error;&lt;br&gt;
};

&lt;p&gt;test('should catch and display error', () =&amp;gt; {&lt;br&gt;
  const spy = jest.spyOn(console, 'error').mockImplementation(() =&amp;gt; {});&lt;/p&gt;

&lt;p&gt;render(&lt;br&gt;
    &lt;br&gt;
      &lt;br&gt;
    &lt;br&gt;
  );&lt;/p&gt;

&lt;p&gt;expect(screen.getByText(/something went wrong/i)).toBeInTheDocument();&lt;br&gt;
  spy.mockRestore();&lt;br&gt;
});&lt;br&gt;
Performance Optimization Tips&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use --maxWorkers for CI/CD
json{
"scripts": {
"test:ci": "jest --maxWorkers=2 --coverage"
}
}&lt;/li&gt;
&lt;li&gt;Selective Test Running
bash# Run specific test file
jest calculator.test.js&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Run tests matching pattern
&lt;/h1&gt;

&lt;p&gt;jest --testNamePattern="should add"&lt;/p&gt;

&lt;h1&gt;
  
  
  Run only changed files
&lt;/h1&gt;

&lt;p&gt;jest --onlyChanged&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mock Heavy Dependencies
javascript// Mock expensive operations
jest.mock('../heavyCalculation', () =&amp;gt; ({
complexCalculation: jest.fn(() =&amp;gt; 'mocked result')
}));
Conclusion
Jest stands out as a comprehensive testing framework that balances simplicity with powerful features. Its zero-configuration approach makes it ideal for quick project setup, while its extensive feature set supports complex testing scenarios. The built-in mocking, snapshot testing, and code coverage capabilities make it particularly valuable for React applications and Node.js projects.
Key Takeaways:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Start Simple: Begin with basic unit tests and gradually add complexity&lt;br&gt;
Mock Wisely: Use mocks for external dependencies but avoid over-mocking&lt;br&gt;
Test Behavior: Focus on testing what your code does, not how it does it&lt;br&gt;
Maintain Snapshots: Regular review and update of snapshot tests&lt;br&gt;
Leverage Watch Mode: Use watch mode during development for faster feedback&lt;/p&gt;

&lt;p&gt;Recommendations:&lt;/p&gt;

&lt;p&gt;For Beginners: Start with Jest due to its excellent documentation and community&lt;br&gt;
For React Projects: Jest + Testing Library is the industry standard&lt;br&gt;
For Performance-Critical Projects: Consider Vitest as a faster alternative&lt;br&gt;
For Complex E2E Scenarios: Combine Jest with Cypress or Playwright&lt;/p&gt;

&lt;p&gt;Jest continues to evolve with the JavaScript ecosystem, making it a reliable choice for modern testing needs. Whether you're building a simple utility library or a complex React application, Jest provides the tools necessary to ensure code quality and reliability.&lt;/p&gt;

&lt;p&gt;Happy Testing! 🧪✨&lt;br&gt;
For more examples and advanced techniques, check out the demo repository and feel free to contribute your own testing scenarios.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
