<?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: Sneha M K</title>
    <description>The latest articles on DEV Community by Sneha M K (@thesnehamk).</description>
    <link>https://dev.to/thesnehamk</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%2F627436%2F5e9dbb92-0a4e-4fd1-a93c-d4ad06525a81.jpeg</url>
      <title>DEV Community: Sneha M K</title>
      <link>https://dev.to/thesnehamk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thesnehamk"/>
    <language>en</language>
    <item>
      <title>Claude Can't Say "Done" Until the Code Is Safe: A Security Verification Loop for Claude Code</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Mon, 28 Sep 2026 18:34:47 +0000</pubDate>
      <link>https://dev.to/thesnehamk/claude-cant-say-done-until-the-code-is-safe-a-security-verification-loop-for-claude-code-pdk</link>
      <guid>https://dev.to/thesnehamk/claude-cant-say-done-until-the-code-is-safe-a-security-verification-loop-for-claude-code-pdk</guid>
      <description>&lt;p&gt;I asked Claude Code to add an AI chat feature. It worked. It also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hardcoded my API key,&lt;/li&gt;
&lt;li&gt;rendered the model's reply with innerHTML,&lt;/li&gt;
&lt;li&gt;and ran eval() on it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it said, "All done!" 🙃&lt;/p&gt;

&lt;p&gt;Anthropic's Claude Code team recently wrote about verification loops: Claude checks its own work and loops back to fix problems before responding. Most examples verify that tests pass. Nobody was verifying that the code was safe. So I built that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9emti5j96kq0mp5icatk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9emti5j96kq0mp5icatk.gif" alt=" " width="760" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Claude Code hooks run your scripts at fixed moments. The Stop hook fires when Claude is about to finish. If the hook exits with code 2, Claude isn't allowed to stop, and whatever you print to stderr is sent back to it as feedback.&lt;/p&gt;

&lt;p&gt;That's the whole loop:&lt;/p&gt;

&lt;p&gt;Claude says &lt;code&gt;done → hook scans the diff → exit 2 with findings → Claude fixes → hook passes → done.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Step 1: register the hook&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.claude/settings.json&lt;/code&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;"hooks"&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;"Stop"&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;"hooks"&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;"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;"command"&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="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$CLAUDE_PROJECT_DIR&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/.claude/hooks/security-verify.mjs"&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;
  
  
  Step 2: the rules
&lt;/h2&gt;

&lt;p&gt;The hook scans only the lines Claude changed (&lt;strong&gt;git diff HEAD -U0&lt;/strong&gt; plus new files), so old code never blocks you. Five rules, each aimed at a mistake AI code actually makes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RULES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hardcoded-secret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;/sk-&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;ant-|proj-&lt;/span&gt;&lt;span class="se"&gt;)?[\w&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;]{20,}&lt;/span&gt;&lt;span class="sr"&gt;|AKIA&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9A-Z&lt;/span&gt;&lt;span class="se"&gt;]{16}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secret-in-client-bundle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;NEXT_PUBLIC_|VITE_&lt;/span&gt;&lt;span class="se"&gt;)\w&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;KEY|SECRET&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;|dangerouslyAllowBrowser:&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*true/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;llm-output-as-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;/innerHTML|dangerouslySetInnerHTML/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b(&lt;/span&gt;&lt;span class="sr"&gt;reply|response|completion&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unsafe-html-sink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;isDynamicHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// static strings are allowed&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dynamic-code-exec&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;eval&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;|new&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+Function&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&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;p&gt;&lt;code&gt;llm-output-as-html&lt;/code&gt; is the one I care most about. Suppose a prompt injection gets into your model's reply; &lt;code&gt;innerHTML = reply&lt;/code&gt;hands the attacker XSS. Model output is untrusted input, always.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: block, with a way out
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;changedLines&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;findings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// clean: Claude may finish&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;attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;MAX_ATTEMPTS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                        &lt;span class="c1"&gt;// stuck: hand over to the human&lt;/span&gt;
  &lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.claude/security-report.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`security-verify blocked completion:\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;report&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                                      &lt;span class="c1"&gt;// Claude must keep working&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attempt cap matters. A Stop hook that always exits 2 can loop forever. I count attempts per session and, after 3 tries, stop blocking and write a report for a human instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: teach Claude how to fix it
&lt;/h2&gt;

&lt;p&gt;The hook says what is wrong. A skill in .claude/skills/security-verify/SKILL.md says how to fix it: move keys behind a server route, use textContent or DOMPurify.sanitize(), use JSON.parse instead of eval. It also tells Claude not to just rephrase code to dodge the regex.&lt;/p&gt;

&lt;p&gt;False positive? Claude can add // verify-ignore:  on that line, and it has to tell you why. The opt-out is visible in review, not silent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;On my test repo, the first "done" was blocked with 5 findings. Claude moved the API call to a server route, switched to textContent and JSON.parse, the hook passed, and its final message told me to rotate the key that had already appeared in the diff.&lt;/p&gt;

&lt;p&gt;That last part is the real win: I didn't have to remember to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limits
&lt;/h2&gt;

&lt;p&gt;These are pattern rules, not a full security audit. They catch the common AI mistakes cheaply on every single turn. Keep your real SAST, code review, and secret scanning in CI too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/thesnehamk/discovering-ai/tree/main/claude-code-security-verify." rel="noopener noreferrer"&gt;📦 Get the drop-in &lt;code&gt;.claude&lt;/code&gt;folder (hook + settings + skill, zero dependencies):&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ai</category>
      <category>claudecode</category>
      <category>security</category>
    </item>
    <item>
      <title>How Does a Vector Database Work?</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Fri, 25 Sep 2026 11:19:50 +0000</pubDate>
      <link>https://dev.to/thesnehamk/how-does-a-vector-database-work-mai</link>
      <guid>https://dev.to/thesnehamk/how-does-a-vector-database-work-mai</guid>
      <description>&lt;p&gt;Most explanations of vector databases turn into a wall of math. Here's the one-minute version instead.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl3pp68ryw8hf5olu85jp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl3pp68ryw8hf5olu85jp.gif" alt=" " width="760" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea, in one sentence
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;A vector database doesn't store words — it stores meaning, as a list of numbers, so it can find things that are similar in meaning even when they don't share a single keyword.&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's happening in the animation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Every document gets embedded. An embedding model reads "The cat sat on the mat," "Dogs are loyal pets," "Paris is in France," and "I love pizza" — and turns each one into a vector (a point in space).&lt;/li&gt;
&lt;li&gt;Similar meanings land near each other. The cat and dog sentences — both about pets — end up close together. Paris and pizza end up far away, because they mean something completely different. No shared keywords required.&lt;/li&gt;
&lt;li&gt;A new query gets embedded the same way. Someone asks "Tell me about puppies." It goes through the exact same embedding model.&lt;/li&gt;
&lt;li&gt;Similarity search compares the query to every stored vector, then narrows down to the nearest one.&lt;/li&gt;
&lt;li&gt;The database returns the original content behind that nearest vector — in this case, "Dogs are loyal pets" — even though the query never said "dogs," "loyal," or "pets."&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Keyword search asks: does this text contain the same words? Vector search asks: does this text mean the same thing?&lt;/p&gt;

&lt;p&gt;That single shift is why vector databases power semantic search, recommendation systems, and RAG (retrieval-augmented generation) pipelines for LLMs — they let you retrieve by meaning, not by string matching.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vectordatabase</category>
      <category>rag</category>
      <category>semanticsearch</category>
    </item>
    <item>
      <title>MCP vs. API Explained: Do We Still Need APIs After MCP?Proven With Runnable Code</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Fri, 25 Sep 2026 06:44:58 +0000</pubDate>
      <link>https://dev.to/thesnehamk/mcp-vs-api-three-claims-proven-with-runnable-code-cga</link>
      <guid>https://dev.to/thesnehamk/mcp-vs-api-three-claims-proven-with-runnable-code-cga</guid>
      <description>&lt;p&gt;The original post argued that MCP doesn't replace APIs- it sits on top of them, at a real token cost, with a real attack surface. Here's that argument turned into three small, runnable TypeScript projects instead of assertions.&lt;/p&gt;

&lt;p&gt;The original &lt;a href="https://dev.to/thesnehamk/mcp-vs-api-explained-do-we-still-need-apis-after-mcp-2kkk"&gt;"MCP vs. API Explained"&lt;/a&gt; post made three claims that are easy to state and easy to hand-wave past: that MCP is an adapter over an API rather than a replacement for one, that eager tool-schema loading burns a measured amount of context, and that a known class of vulnerability shows up in a meaningful fraction of MCP tool handlers. This is the follow-up where each of those claims gets a small, self-contained, &lt;code&gt;npm install &amp;amp;&amp;amp; run&lt;/code&gt;- able project instead of a citation and a shrug. All three are validated against the real &lt;code&gt;@modelcontextprotocol/sdk&lt;/code&gt; and the official MCP Inspector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claim 1: "MCP doesn't replace APIs — it sits on top of them"
&lt;/h2&gt;

&lt;p&gt;The proof here is architectural: one business-logic function, two interfaces, zero duplicated logic. The shared function lives in weatherService.ts and knows nothing about REST or MCP:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;WeatherResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;observedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;lookupUpstream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;void&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;WEATHER_API_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// would be used here in a real HTTP call&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;FIXTURE_DATA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CityNotFoundError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`No weather data for "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;". Try one of: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FIXTURE_DATA&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&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;CityNotFoundError&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;WeatherResult&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="nf"&gt;lookupUpstream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&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;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CityNotFoundError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&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="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;temperatureC&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="nx"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;condition&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="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;observedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&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;p&gt;The REST interface is exactly what you'd expect — Express, a query param, status codes:&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="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;/weather&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="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;city&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;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&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="p"&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&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;Query parameter 'city' is required.&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;try&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="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&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;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;CityNotFoundError&lt;/span&gt;&lt;span class="p"&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&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;Unexpected server error.&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MCP interface calls the identical getWeather() — the entire adapter is a name, a Zod schema, and error-shape translation:&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;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;weather-mcp-demo&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;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get_weather&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get Weather&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Get the current weather for a city.\n\nArgs:\n  - city (string, required): city name, e.g. "Delhi"\n\nReturns the temperature (Celsius), condition, and observation time.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputSchema&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="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&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="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;City name, e.g. 'Delhi'&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="na"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;readOnlyHint&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="na"&gt;destructiveHint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;idempotentHint&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="na"&gt;openWorldHint&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="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;city&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;try&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&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;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&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;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;CityNotFoundError&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;isError&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="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="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;p&gt;Run both and diff what changed: nothing about the lookup, the fixture data, or the error cases. Only the calling contract — an HTTP query param vs. a JSON-Schema-described tool call — and where credentials live (WEATHER_API_KEY stays server-side in both, never reaching the REST client or the model). That's the whole claim, made mechanically checkable instead of asserted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;01-same-backend-two-interfaces
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build
npm run api        &lt;span class="c"&gt;# curl "http://localhost:3000/weather?city=Delhi"&lt;/span&gt;
npm run mcp:inspect &lt;span class="c"&gt;# or: npx @modelcontextprotocol/inspector --cli node dist/mcp/server.js \&lt;/span&gt;
                    &lt;span class="c"&gt;#     --method tools/call --tool-name get_weather --tool-arg city=Delhi`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Claim 2: eager tool-schema loading has a real, measurable token cost
&lt;/h2&gt;

&lt;p&gt;The original post cited two numbers from other sources — a GitHub MCP server reportedly burning ~50K tokens just initializing, and a 100+ tool database server measured wasting up to 81% of context before a single query runs. This benchmark doesn't reproduce those exact servers; it reproduces the mechanism, with a real tokenizer, on a comparably shaped synthetic tool pool, so the gap is measured rather than quoted secondhand:&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;const&lt;/span&gt; &lt;span class="nx"&gt;POOL_SIZES&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&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;TASK_TOOLS_NEEDED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// a single task typically only needs a handful of tools&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tokenCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ToolSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;encode&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;schema&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// gpt-tokenizer, cl100k_base&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;eagerCost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ToolSchema&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;number&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;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;tokenCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;lazyCost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ToolSchema&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;tasksNeeded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&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;metaCost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tokenCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;searchToolsMetaSchema&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;neededCost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tasksNeeded&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;tokenCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&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;metaCost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;neededCost&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;Eager sends every tool's full JSON Schema up front, every turn, regardless of relevance — the pattern the original post described as common practice. Lazy sends one small search_tools meta-schema initially, and only fetches full schemas for the ~3 tools a given task actually needs — the "progressive/lazy tool disclosure" pattern raised in that post's comments as the practical fix. Running it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;02-context-cost-benchmark
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run benchmark
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At 100 tools in the pool, eager disclosure spends every one of those tools' schemas before a single user query runs; lazy disclosure spends the meta-schema plus ~3 real schemas — a 96% reduction in this synthetic pool. That's the same order of magnitude as the independently measured 81% figure the original post cited for a real 100+ tool server, using a different tool set and a different tokenizer — which is the point: the mechanism (cost scales linearly with server size under eager loading, and stays roughly flat under lazy loading) isn't specific to one vendor's server; it's structural to how the two disclosure strategies behave as a tool pool grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claim 3: "independent testing found command injection flaws in 43% of tested MCP implementations"
&lt;/h2&gt;

&lt;p&gt;This is the one worth actually seeing broken and fixed, because the vulnerable version is the kind of code that looks completely reasonable at a glance:&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;searchLogsVulnerable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&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;// VULNERABLE LINE: `pattern` is concatenated straight into a shell&lt;/span&gt;
  &lt;span class="c1"&gt;// command string. A pattern like `ERROR"; echo INJECTED; echo "`&lt;/span&gt;
  &lt;span class="c1"&gt;// closes the intended quoted argument early and runs `echo INJECTED.`&lt;/span&gt;
  &lt;span class="c1"&gt;// as its own command, with the tool's own process privileges.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`grep "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pattern&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;FIXTURE_LOG&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="kd"&gt;const&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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;execAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&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;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&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 critical detail the comment calls out: the caller here is a model, not a human typing a known-safe string into a terminal. "The pattern will usually be reasonable" was never a real safety property, and it's an even worse one when the input can come from a tool result upstream, a prompt-injected instruction, or a plain model mistake — any of which can hand &lt;code&gt;pattern&lt;/code&gt; arbitrary shell syntax, because &lt;code&gt;exec()&lt;/code&gt; runs its argument through &lt;code&gt;/bin/sh -c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fix is two independent layers, either of which alone would have stopped this:&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;const&lt;/span&gt; &lt;span class="nx"&gt;SafePatternSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&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;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[\w&lt;/span&gt;&lt;span class="sr"&gt; .-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&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;pattern may only contain letters, numbers, spaces, dots, hyphens, and underscores&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;searchLogsHardened&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&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;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SafePatternSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&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;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InvalidPatternError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;invalid pattern&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="c1"&gt;// Argument array, not a command string: grep never sees a shell, so&lt;/span&gt;
  &lt;span class="c1"&gt;// there's no shell syntax for a malicious pattern to break out into,&lt;/span&gt;
  &lt;span class="c1"&gt;// even hypothetically.&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;stdout&lt;/span&gt; &lt;span class="p"&gt;}&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;execFileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grep&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="nx"&gt;parsed&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="nx"&gt;FIXTURE_LOG&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&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;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&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;Layer one is a strict allowlist regex that rejects shell metacharacters before they reach a process call. Layer two is structural rather than a filter: &lt;code&gt;execFile()&lt;/code&gt; with an argument array never invokes a shell at all, so even a gap in the regex has no shell syntax available to exploit — the pattern string is passed to &lt;code&gt;grep&lt;/code&gt; as inert data, not parsed as command syntax. The repo's test harness runs an actual injection payload &lt;code&gt;(ERROR" /dev/null; echo INJECTED_BY_ATTACKER; echo ")&lt;/code&gt; against both versions live: the vulnerable one executes the injected echo, the hardened one rejects the input outright via the regex before &lt;code&gt;execFile&lt;/code&gt; is ever called.&lt;/p&gt;

&lt;p&gt;One more thing surfaced building this demo, worth calling out because it's a distinct bug class from injection: the original &lt;code&gt;exec()&lt;/code&gt; call had no timeout, and a pattern that makes &lt;code&gt;grep&lt;/code&gt; hang — reading from stdin instead of the fixture file, for instance — blocks the handler indefinitely. Both versions in the repo now set an explicit &lt;code&gt;timeout: 3000&lt;/code&gt;, which is a denial-of-service mitigation, not a security fix for the injection itself. It's worth having both, and worth knowing they're not the same guarantee.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;03-security-patterns
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why this is a companion piece, not a rewrite
&lt;/h2&gt;

&lt;p&gt;None of these three demos change the conclusion of the original post — they were built specifically to test whether that conclusion survives contact with actual code, and it does. MCP genuinely is a thin adapter over the same business logic an API already exposes; eager tool-schema loading genuinely does scale badly with server size in a way lazy disclosure avoids; and the injection vulnerability class genuinely does come from an unremarkable-looking line of string interpolation that a regex and an argument array both independently close off. If you're building an MCP server, the practical takeaway isn't "avoid MCP" — it's "assume your tool handlers face the same untrusted-input discipline as a public API endpoint, because the caller is a model, not a person who reads your intended usage and stays inside it."&lt;/p&gt;

&lt;p&gt;If you really need a complete demo code, I am happy to share the GitHub link&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>github</category>
      <category>api</category>
      <category>development</category>
    </item>
    <item>
      <title>Meet Jev: The AI That Refuses to Chat With You (On Purpose)</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Thu, 24 Sep 2026 07:14:38 +0000</pubDate>
      <link>https://dev.to/thesnehamk/meet-jev-the-ai-that-refuses-to-chat-with-you-on-purpose-3d8a</link>
      <guid>https://dev.to/thesnehamk/meet-jev-the-ai-that-refuses-to-chat-with-you-on-purpose-3d8a</guid>
      <description>&lt;p&gt;Every AI model you've heard of talks. This one was built to never say a word — and that's exactly why developers are excited about it.&lt;/p&gt;

&lt;p&gt;Here's a question you've probably never had to ask before: what if an AI model just... didn't write anything? No essays, no explanations, no friendly chatbot replies. Just a fast, confident decision, and nothing else. That's Jev — a new model from a startup called TypeSafe AI, built by someone who helped create ChatGPT itself. And the whole point of it is that it does less than ChatGPT, on purpose, so it can do that one thing much faster and much more reliably.&lt;/p&gt;

&lt;p&gt;What Jev actually does&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8ej95xgaynjczvjf5w3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8ej95xgaynjczvjf5w3h.png" alt=" " width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think about all the tiny decisions software makes behind the scenes every day: is this email spam or not, which support queue should this ticket go to, does this comment break the community rules, how likely is this customer to churn. Right now, a lot of companies handle these by calling a full AI chatbot — the same kind of model you'd use to write an essay — just to get back a one-word answer buried inside a paragraph.&lt;/p&gt;

&lt;p&gt;Jev skips the paragraph. You give it some information and a set of possible answers, and it hands back one of those answers directly, plus a percentage telling you how confident it actually is. No essay, no chit-chat, no extra words to sift through. Just: here's the answer, and here's how sure I am.&lt;/p&gt;

&lt;p&gt;How it's different from ChatGPT, Claude, or Gemini&lt;/p&gt;

&lt;p&gt;The AI chatbots you already know are built to hold a conversation — they think through a response one word at a time, the way you might think through a sentence as you speak it. That's great for writing and explaining things, but it's slow and expensive when all you actually needed was a single yes-or-no answer.&lt;/p&gt;

&lt;p&gt;Jev works completely differently: instead of writing word by word, it produces its whole answer at once, already locked into a fixed format you defined ahead of time — like a multiple-choice answer instead of an open essay question. Because it can only ever pick from the choices you gave it, it literally can't make something up or go off-script the way a chatbot sometimes does. And because it skips the whole "write it out one word at a time" process, it's reportedly dozens of times faster and a fraction of the cost for this kind of task.&lt;/p&gt;

&lt;p&gt;The trade-off is real, though: Jev can't write you an email, a story, or a thoughtful explanation. It only knows how to choose, score, or rate — nothing more. It's not a smaller, weaker version of ChatGPT. It's a completely different tool built for a completely different job.&lt;/p&gt;

&lt;p&gt;Why this could actually matter&lt;/p&gt;

&lt;p&gt;Right now, a huge number of AI-powered products are quietly using an expensive, slow chatbot to make small, repeated decisions it was never really designed for — like using a sports car to deliver a single envelope down the street. If a purpose-built tool like Jev can genuinely do that specific job faster, cheaper, and more predictably, the likely shift isn't "Jev replaces ChatGPT." It's that apps start using both: a fast, no-nonsense decision-maker like Jev handling the constant background judgment calls, and a full conversational model like ChatGPT or Claude stepping in only when something actually needs to be written, explained, or reasoned through in depth.&lt;/p&gt;

&lt;p&gt;For everyday users, that split would mostly be invisible — you'd just notice AI-powered apps getting snappier and cheaper to run, without any drop in quality. For developers and companies, it's a meaningfully different way to think about building with AI: not "which chatbot should I use everywhere," but "which decisions actually need a conversation, and which ones just need an answer."&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>jev</category>
      <category>challenge</category>
    </item>
    <item>
      <title>CLOSEDQUORUM: The Malware That Lets Four AI Models Vote on How to Attack You</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Wed, 23 Sep 2026 07:55:06 +0000</pubDate>
      <link>https://dev.to/thesnehamk/closedquorum-the-malware-that-lets-four-ai-models-vote-on-how-to-attack-you-g1d</link>
      <guid>https://dev.to/thesnehamk/closedquorum-the-malware-that-lets-four-ai-models-vote-on-how-to-attack-you-g1d</guid>
      <description>&lt;p&gt;Cisco Talos just documented the first Windows malware that doesn't wait for a human to tell it what to do next, it asks a panel of language models instead, and goes with majority rule.&lt;/p&gt;

&lt;p&gt;Most malware still works the way it always has: a human operator sits on a command-and-control server, decides what the infected machine should do, and sends the instruction. That loop has a built-in speed limit, because it's bounded by a person's attention span, working hours, and how many infected machines one operator can babysit at once. CLOSEDQUORUM, disclosed by Cisco Talos in September 2026, is the first publicly documented case of malware that removes that limit — not by getting smarter code, but by handing the decision-making itself to AI.&lt;/p&gt;

&lt;p&gt;What it actually is&lt;/p&gt;

&lt;p&gt;CLOSEDQUORUM is a Go-based Windows implant. Once it lands on a machine, it doesn't check in with an attacker-controlled server for orders the way traditional command-and-control malware does. Instead, it gathers context about the host it's sitting on and asks four different large language models — DeepSeek, Qwen, Mistral, and Google Gemini — to independently vote on what it should do next, choosing from a fixed menu of options: steal credentials, inject code into another process, establish persistence, or move laterally to another machine.&lt;/p&gt;

&lt;p&gt;Each model responds independently in a strict, predefined JSON format. Whichever action gets the most votes is the one that runs. If the vote ties, DeepSeek's answer wins by default, followed by Qwen, then Mistral — an oddly bureaucratic detail for something built to compromise a machine, but it's a real design choice: the malware needs a deterministic way to resolve disagreement among four models that don't always agree.&lt;/p&gt;

&lt;p&gt;What it does once it decides&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fis0cx3iykh4qtdqabmgq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fis0cx3iykh4qtdqabmgq.png" alt=" " width="800" height="984"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The steal option dumps LSASS memory (a classic technique for harvesting Windows credentials), pulls saved passwords out of Chrome, Edge, and Firefox, and grabs cryptocurrency wallet data. The inject option uses process hollowing or Early Bird APC injection — both established techniques for running malicious code inside the memory space of a legitimate, already-trusted process, so it doesn't show up as a suspicious new executable. The persist option runs modules meant to survive a reboot. The move option, for lateral movement to other machines on the network, was present in the code Talos analyzed but non-functional — worth noting, because it means the "fully autonomous attack" is currently bounded to a single compromised host, not yet a self-propagating worm.&lt;/p&gt;

&lt;p&gt;Whatever gets stolen is exfiltrated through a Discord webhook, encrypted, and dropped into a channel the operator controls. That's also where the human comes back into the picture: someone still has to build the malware, configure each copy with their own API keys and webhook at compile time, deploy it, and eventually sit down and decrypt the results. The AI runs the tactical decision loop. It doesn't run the business.&lt;/p&gt;

&lt;p&gt;Why this is a real architectural shift, not just a buzzword&lt;/p&gt;

&lt;p&gt;The meaningful change isn't "malware used AI" — attackers have used AI to write phishing emails and obfuscate code for a couple of years now. It's that the decision of what to do next during an active compromise — traditionally the single most human-dependent part of an intrusion — has been delegated to a model. As one security analyst covering the disclosure put it, human operators are bound by attention, working hours, and cognitive load; a panel of models voting in a loop isn't. That's the entire value proposition of the design: not smarter attacks, just attacks that don't need a human awake and paying attention to keep moving.&lt;/p&gt;

&lt;p&gt;It's also, refreshingly, not invincible. The malware depends on live API access to four external LLM providers — which means rate limits, an outage at any one provider, or a malformed model response can stall or crash the decision loop entirely. That dependency is also the best lead defenders have.&lt;/p&gt;

&lt;p&gt;What it means for the people whose job is stopping this&lt;/p&gt;

&lt;p&gt;For defenders, the practical shift is what you look for. Blocking known malicious domains doesn't help much here, because the malware is calling legitimate, widely-used AI APIs — the same ones your own developers might be using. The signal isn't that a process is talking to DeepSeek or Gemini; plenty of legitimate software does that. The signal is a process talking to several AI providers in the same session while also touching LSASS, injecting into a suspended process, or creating a new WMI persistence entry. Individually, none of those things is remarkable. Together, in that combination, they're not something a normal application does. That pushes detection further toward behavioral analysis — watching what a process does across several actions — and further away from static signatures or domain blocklists, which is a genuinely harder discipline to build a SOC around, and not one every team is currently staffed for.&lt;/p&gt;

&lt;p&gt;For the offensive side, the barrier that's lowering isn't "can I write malware" — this still required real skill to build. It's "can I run a sophisticated, adaptive intrusion without personally staying online to steer it." That's the same labor-multiplying effect AI has had everywhere else, applied to a place most people didn't expect it yet: it doesn't require a more skilled attacker, it requires less continuous attention from the attacker that exists. A single operator can plausibly run more simultaneous compromises, for longer, with less hands-on-keyboard time per victim.&lt;/p&gt;

&lt;p&gt;Neither side of this replaces a person outright. It changes what the person is for. The attacker stops being a tactician making moment-to-moment decisions and becomes someone who builds, deploys, and periodically checks in — supervision, not execution. The defender who used to write detection rules against known indicators has to increasingly write detection logic against behavioral patterns of a decision-maker, human or otherwise. That's a heavier, more analytical skill than a lot of current SOC tooling was built to support, and it's a fair bet that the security teams who adapt their detection philosophy first — rather than waiting for a signature to exist for "AI-directed malware" — are the ones who'll actually catch the next version of this before it finishes its job.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>"I Was Too Embarrassed to Ask What RAG Means, So I Wrote This Instead"</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Tue, 22 Sep 2026 10:56:12 +0000</pubDate>
      <link>https://dev.to/thesnehamk/i-was-too-embarrassed-to-ask-what-rag-means-so-i-wrote-this-instead-20ec</link>
      <guid>https://dev.to/thesnehamk/i-was-too-embarrassed-to-ask-what-rag-means-so-i-wrote-this-instead-20ec</guid>
      <description>&lt;p&gt;Stop Googling "What Is RAG?": The No-Jargon Guide to Every AI Term You Keep Hearing&lt;/p&gt;

&lt;p&gt;LLM, RAG, AI Agents, LangChain, LangGraph, and a dozen other buzzwords — explained the way you'd explain them to a friend over coffee, not in a computer science lecture.&lt;/p&gt;

&lt;p&gt;You don't need to be an engineer to feel like everyone around you suddenly speaks a different language. Coworkers say "we're building an agent." Your nephew mentions "vibe coding." A LinkedIn post insists your company needs "RAG" or you're "falling behind." Nobody stops to explain what any of it actually means, because everyone's too worried about looking like the only person in the room who doesn't already know.&lt;/p&gt;

&lt;p&gt;You're not behind. Most of this vocabulary is barely two or three years old. Here's the whole thing, broken down in plain English, with real-life comparisons instead of technical ones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9troel9853efa5wkjveu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9troel9853efa5wkjveu.png" alt=" " width="800" height="653"&gt;&lt;/a&gt;&lt;br&gt;
The absolute basics&lt;/p&gt;

&lt;p&gt;Artificial Intelligence (AI) is just the umbrella term for any computer program that does something we'd normally call "smart" — recognizing your face in a photo, recommending a show, answering a question. It's not one specific technology. It's a category, the same way "vehicle" covers everything from a bicycle to a jet.&lt;/p&gt;

&lt;p&gt;Machine Learning (ML) is how most modern AI actually gets built: instead of a programmer writing out every rule by hand, you show the computer thousands (or billions) of examples, and it figures out the pattern itself. Think of teaching a kid what a dog looks like by showing them a hundred photos of dogs, instead of trying to write a rulebook that defines "dog" in words.&lt;/p&gt;

&lt;p&gt;Generative AI is the specific branch that got everyone's attention starting around 2022 — AI that doesn't just analyze things, it creates new things: text, images, music, video, code. ChatGPT, Claude, and image tools like Midjourney all fall under this umbrella.&lt;/p&gt;

&lt;p&gt;The thing everyone's actually talking about: the model itself&lt;/p&gt;

&lt;p&gt;LLM (Large Language Model) is the technology behind chatbots like ChatGPT and Claude. It's a program trained on an enormous amount of text — books, websites, articles — that learned to predict what word comes next in a sentence. Do that well enough, at a big enough scale, and you get something that can hold a conversation, write an essay, or explain a recipe. It's less "the computer understands you" and more "the world's most well-read autocomplete," and that description matters, because it explains both what these tools are great at and where they trip up.&lt;/p&gt;

&lt;p&gt;Multimodal AI just means a model that isn't limited to text — it can also look at a photo you upload, listen to audio, or watch a video and talk about what it sees or hears, all in the same conversation.&lt;/p&gt;

&lt;p&gt;Tokens and the Context Window — a "token" is roughly a chunk of a word (the AI doesn't read whole sentences the way you do; it breaks everything into small pieces first). The "context window" is simply how much text the AI can hold in its head at once during a conversation — like short-term memory. A bigger context window means you can paste in a longer document, or have a longer back-and-forth, before it starts "forgetting" the beginning.&lt;/p&gt;

&lt;p&gt;Why AI sometimes confidently makes stuff up&lt;/p&gt;

&lt;p&gt;Hallucination is the polite technical name for when an AI states something completely false with total, cheerful confidence — inventing a fake statistic, a book that doesn't exist, or a court case that was never filed. It happens because the AI is built to predict plausible-sounding text, not to fact-check itself against reality, so a wrong answer and a right one can come out sounding equally sure of themselves.&lt;/p&gt;

&lt;p&gt;Prompt is simply what you type to the AI — your question or instruction. Prompt Engineering is the (increasingly less magical) skill of phrasing that instruction well enough to get a better answer — being specific, giving examples, telling it what tone or format you want.&lt;/p&gt;

&lt;p&gt;Fine-Tuning is taking a general-purpose AI model and giving it extra, focused training on a specific topic or style — like taking a well-rounded new employee and putting them through two weeks of training specific to your company, rather than hiring someone from scratch.&lt;/p&gt;

&lt;p&gt;Giving AI access to information it wasn't originally trained on&lt;/p&gt;

&lt;p&gt;RAG (Retrieval-Augmented Generation) solves a real problem: an AI's knowledge is frozen at the point it was trained, and it's never seen your company's private documents, your personal notes, or this morning's news. RAG lets the AI search through a specific set of documents first, and then answer your question using what it just found — instead of only relying on what it memorized months or years ago. Think of the difference between a brilliant friend answering purely from memory, versus that same friend quickly looking something up before answering you.&lt;/p&gt;

&lt;p&gt;Vector Database is the specific kind of search tool that makes RAG possible — a way of storing information so the AI can search by meaning rather than exact keywords. Ask "how do I get my money back" and it can still find a document titled "Refund Policy," even though the words don't match.&lt;/p&gt;

&lt;p&gt;AI that does things, not just talks&lt;/p&gt;

&lt;p&gt;AI Agents (sometimes called Agentic AI) are the current biggest trend, and the idea is simple even though the engineering isn't: instead of an AI that just answers a question, an agent is an AI that can take multiple steps on its own to actually accomplish something — searching the web, filling out a form, checking a calendar, booking something — deciding what to do next based on what happened in the previous step, closer to a capable assistant than a chatbot.&lt;/p&gt;

&lt;p&gt;LangChain and LangGraph are two of the most popular toolkits developers use to actually build those agents. You don't need to know how they work under the hood any more than you need to know how a car engine works to understand what a car does — but if you ever hear a developer mention them, LangChain is the toolkit for building an AI application's basic pieces, and LangGraph is the toolkit for making an agent that can handle multiple steps, loops, and decisions reliably without falling over.&lt;/p&gt;

&lt;p&gt;MCP (Model Context Protocol) is a newer standard that lets an AI assistant safely connect to outside tools and services — your calendar, a database, a company's software — in a consistent way, so developers don't have to build a completely custom connection for every single tool an AI might need to use.&lt;/p&gt;

&lt;p&gt;The buzzwords floating around right now&lt;/p&gt;

&lt;p&gt;Vibe Coding is building software by describing what you want in plain English and letting an AI write the actual code — no traditional programming required. It's become popular enough that people with zero coding background are now building simple apps this way.&lt;/p&gt;

&lt;p&gt;AI Slop is the slightly unkind but accurate term for the flood of low-effort, mass-produced AI-generated articles, images, and videos clogging up the internet — content made quickly and cheaply, with nobody checking whether it's actually good or true.&lt;/p&gt;

&lt;p&gt;AGI (Artificial General Intelligence) is the theoretical, not-yet-real future point where an AI could do essentially any intellectual task a human can, across any subject, as well as a human — as opposed to today's AI, which is extremely good at specific things but doesn't have that kind of general, flexible understanding of the world.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>llm</category>
      <category>rag</category>
    </item>
    <item>
      <title>How LangChain, LangGraph, LangSmith fits together</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Mon, 21 Sep 2026 14:03:46 +0000</pubDate>
      <link>https://dev.to/thesnehamk/how-langchain-langgraph-langsmith-fits-together-1fd1</link>
      <guid>https://dev.to/thesnehamk/how-langchain-langgraph-langsmith-fits-together-1fd1</guid>
      <description>&lt;p&gt;LangChain, LangGraph, LangSmith: Three Names, One Confusing Naming Convention&lt;/p&gt;

&lt;p&gt;They all start with "Lang," they're all made by the same company, and they solve three completely different problems. Here's what each one actually does.&lt;/p&gt;

&lt;p&gt;If you've started building anything with LLMs in the last year, you've run into this wall: someone's tutorial uses LangChain, someone else's uses LangGraph, a third person swears you need LangSmith before you ship anything to production — and all three names sound close enough that it's genuinely unclear whether you need one of them, all three, or whether two of them are just old and new names for the same thing.&lt;/p&gt;

&lt;p&gt;They're not. They're three separate tools that happen to come from the same company (LangChain, the company) and are designed to be used together, but each one solves a distinct problem. Once you see the split, the confusion mostly disappears.&lt;/p&gt;

&lt;p&gt;LangChain: the building-blocks layer&lt;/p&gt;

&lt;p&gt;LangChain is the original library, and it's still what most people mean when they say "I'm using LangChain." It provides the components you need to build an LLM application: standardized interfaces for calling different models, prompt templates, retrievers for pulling in outside data, tool definitions, memory for conversation history, and a large library of pre-built integrations (vector stores, document loaders, APIs) so you're not writing that plumbing yourself.&lt;/p&gt;

&lt;p&gt;It composes these pieces using something called LCEL (LangChain Expression Language), which lets you chain components together into a pipeline — hence the name. This is the right layer for straightforward applications: a chatbot, a basic RAG system, a summarizer. If your logic is mostly "take input, run it through a sequence of steps, return output," LangChain by itself covers you well.&lt;/p&gt;

&lt;p&gt;LangGraph: the orchestration layer&lt;/p&gt;

&lt;p&gt;LangGraph exists because real agents don't behave like a straight pipeline. They loop. They branch based on what happened in a previous step. They sometimes need to pause and wait for a human to approve something before continuing. They need to survive a crash without losing track of where they were. A linear chain can't represent any of that cleanly.&lt;/p&gt;

&lt;p&gt;LangGraph models an agent as a StateGraph: nodes (each one a step — either a deterministic function or an LLM call) connected by edges, with a persistent state object that flows through the whole graph and gets checkpointed as execution proceeds. That checkpointing is the headline feature: LangGraph 1.0, released in late 2025, made "your agent should survive a server restart" a real, built-in guarantee rather than something every team had to hand-roll — execution state persists automatically, so a crash mid-run doesn't mean starting over from scratch.&lt;/p&gt;

&lt;p&gt;Officially, LangChain describes LangGraph as a "low-level orchestration framework and runtime for building, managing, and deploying long-running, stateful agents." You can use it without LangChain at all — it's a separate, independent library — though in practice most teams use LangChain's components (a model call, a retriever, a tool) inside LangGraph's nodes. LangGraph is now trusted in production by companies including Klarna, Replit, and Elastic, specifically for its durable execution and human-in-the-loop support.&lt;/p&gt;

&lt;p&gt;LangSmith: the observability layer&lt;/p&gt;

&lt;p&gt;LangSmith is the one people skip until something breaks in production, and then wish they'd set up on day one. It's not a framework for building anything — it's a platform for watching what your agent actually does once it's running.&lt;/p&gt;

&lt;p&gt;Every run — every LLM call, every tool invocation, every branch the graph took — gets captured as a trace, so you can see exactly which step produced a bad output, how much it cost in tokens, and how long each part took. Beyond tracing, LangSmith adds evaluation (including LLM-as-judge scoring against test datasets), monitoring dashboards for error rates and latency in production, and automated clustering to surface failure patterns you wouldn't spot by reading logs one at a time. It's framework-agnostic — it works with OpenAI or Anthropic SDKs directly, not just LangChain apps — and it's used in production by companies like Expedia, Autodesk, Workday, and Coinbase.&lt;/p&gt;

&lt;p&gt;The one-line version an engineer on this stack put well: LangChain for building, LangGraph for orchestrating, LangSmith for observing. They're not competing products. They're three different concerns that happen to show up in almost every serious agent project, built by the same team so they plug into each other with minimal glue code.&lt;/p&gt;

&lt;p&gt;So which one do you actually need?&lt;/p&gt;

&lt;p&gt;If you're prototyping something simple — a single-pass RAG chatbot, a basic summarization tool — LangChain on its own is probably enough. Reach for LangGraph once your logic needs loops, conditional branches, multi-step planning, or has to survive running for minutes or hours without losing state; it's the difference between "call the model once" and "run an agent." And add LangSmith the moment you're putting anything in front of real users or real cost — not because it's mandatory to get something working, but because debugging a multi-step agent with print statements is exactly as painful as it sounds, and the failure patterns that matter (a tool silently returning bad data three steps before the final answer) are close to invisible without tracing.&lt;/p&gt;

&lt;p&gt;Most production agent stacks in 2026 end up using all three, and that's by design, not an accident of confusing branding: you build with LangChain, you orchestrate with LangGraph, and you keep your eyes open with LangSmith.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>MCP vs. API Explained: Do We Still Need APIs After MCP?</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Sat, 19 Sep 2026 16:55:23 +0000</pubDate>
      <link>https://dev.to/thesnehamk/mcp-vs-api-explained-do-we-still-need-apis-after-mcp-2kkk</link>
      <guid>https://dev.to/thesnehamk/mcp-vs-api-explained-do-we-still-need-apis-after-mcp-2kkk</guid>
      <description>&lt;p&gt;No. MCP doesn't replace APIs — it sits on top of them. An MCP server is, almost always, a thin adapter that calls a REST/GraphQL/gRPC API underneath and translates it into a shape an LLM can safely discover and call. If you're building anything that isn't talking to an AI model, you still reach for a normal API. If an AI agent is the caller, MCP is very likely the better interface. Here's the actual technical breakdown.&lt;/p&gt;

&lt;p&gt;The confusion is understandable&lt;/p&gt;

&lt;p&gt;Since Anthropic open-sourced the Model Context Protocol in November 2024, it's been described as "USB-C for AI applications," gotten adopted by OpenAI, Google DeepMind, and Microsoft, and spawned a whole ecosystem — over 5,500 servers listed on the PulseMCP registry, with remote MCP server deployments up roughly 4x since May 2025 alone. When something grows that fast, "does this replace X" questions are inevitable. So let's actually answer it, at the protocol level.&lt;/p&gt;

&lt;p&gt;What an API is, quickly&lt;/p&gt;

&lt;p&gt;An API (usually REST these days) is a contract: a set of HTTP endpoints, request/response shapes, and auth mechanisms that let one piece of software call another. You read the docs, you write code that constructs a request to a known URL with known parameters, you parse a known response shape. The caller is a human developer writing deterministic code that will run the same way every time.&lt;/p&gt;

&lt;p&gt;GET &lt;a href="https://api.weatherapi.com/v1/current.json?key=API_KEY&amp;amp;q=Delhi" rel="noopener noreferrer"&gt;https://api.weatherapi.com/v1/current.json?key=API_KEY&amp;amp;q=Delhi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it. You know exactly what you're calling, you handle the API key yourself, and the code either runs correctly or throws an error you wrote a handler for.&lt;/p&gt;

&lt;p&gt;What MCP actually is&lt;/p&gt;

&lt;p&gt;MCP is a client-server protocol, communicating over JSON-RPC 2.0, built specifically for the case where the caller is an LLM, not a human writing deterministic code. It defines three roles:&lt;/p&gt;

&lt;p&gt;Host — the AI application itself (Claude, an IDE, your own agent runtime)&lt;br&gt;
Client — created by the host, one per server it talks to&lt;br&gt;
Server — exposes tools (callable functions), resources (readable content), and prompts (reusable templates), each described in natural language plus a JSON Schema so a model can understand what it does without a human reading documentation first&lt;/p&gt;

&lt;p&gt;Wrap that same weather lookup as an MCP tool and it looks like this:&lt;/p&gt;

&lt;p&gt;python&lt;br&gt;
from mcp. server.fastmcp import FastMCP&lt;/p&gt;

&lt;p&gt;mcp = FastMCP("weather")&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool()&lt;br&gt;
def get_weather(city: str) -&amp;gt; str:&lt;br&gt;
    """Get the current weather for a city."""&lt;br&gt;
    # The API key and request-building logic live here,&lt;br&gt;
    # never in the model's context&lt;br&gt;
    return fetch_weather_api(city)&lt;/p&gt;

&lt;p&gt;Nothing magic happened to the weather API. It's the same HTTP call. What changed is who's allowed to see what: the model gets a name, a description, and a schema — not a raw API key it could leak, misuse, or hallucinate the wrong parameters for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flnjvy0r2704mubpriyi1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flnjvy0r2704mubpriyi1.png" alt=" " width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The actual differences, side by side&lt;br&gt;
    Traditional API MCP&lt;br&gt;
Built for   A developer who reads docs and writes fixed code    An LLM that discovers capabilities at runtime&lt;br&gt;
Discovery   Manual — you read documentation   Automatic — tools/list returns every tool's name, description, and schema&lt;br&gt;
Interface shape Varies wildly per API (REST, GraphQL, SOAP, gRPC…)    Uniform — every MCP server speaks the same JSON-RPC patterns&lt;br&gt;
Credentials Caller handles auth directly (API keys, OAuth tokens)   Server holds credentials; the model never sees them&lt;br&gt;
Execution model Caller writes exact, deterministic logic    Model chooses which tool to call and with what arguments, non-deterministically&lt;br&gt;
Governance  Rate limiting, auth at the endpoint Per-tool validation, input restriction, logging built into the pattern&lt;br&gt;
Transport   Usually plain HTTP, cacheable, CDN-friendly JSON-RPC over stdio or HTTP; historically stateful (changing — more below)&lt;/p&gt;

&lt;p&gt;The short version: REST optimizes for a human who already knows what they want to call. MCP optimizes for a model that has to figure out what's available and how to call it correctly, safely, on the fly.&lt;/p&gt;

&lt;p&gt;MCP is evolving fast — worth knowing where it stands right now&lt;/p&gt;

&lt;p&gt;The spec isn't frozen. The 2026-07-28 release made the protocol stateless at the wire level — the old initialize/initialized handshake and sticky Mcp-Session-Id are gone, so requests can now route to any server instance behind a normal load balancer instead of pinning to one. That release also added an extensions framework with formal governance, MCP Apps (servers shipping actual interactive HTML UI rendered in a sandboxed iframe, not just text), and six authorization updates aligning MCP with OAuth 2.0 and OIDC. This is a protocol still actively fixing its own early design mistakes, not a finished spec everyone's just implementing.&lt;/p&gt;

&lt;p&gt;The part worth being honest about&lt;/p&gt;

&lt;p&gt;MCP has real, documented problems in production right now, and a dev audience deserves the unvarnished version, not just the pitch:&lt;/p&gt;

&lt;p&gt;Context bloat. Some implementations dump entire tool schemas into the model's context on every turn regardless of relevance — one reported GitHub MCP server burns roughly 50,000 tokens just initializing, and a database server with over a hundred tools has been measured wasting up to 81% of the available context window before a single user query runs.&lt;/p&gt;

&lt;p&gt;Security. Independent testing found command injection flaws in 43% of tested MCP implementations, and scans have turned up close to 2,000 internet-exposed MCP servers with zero authentication. There have been real CVEs — a 9.6-severity flaw in mcp-remote, an RCE in Anthropic's own Inspector tool. The protocol's original design conflating the resource server and authorization server didn't help.&lt;/p&gt;

&lt;p&gt;Reliability. Because early MCP was stateful, a crashed server could take down an entire session rather than failing one request — production implementations from major vendors have reportedly hung or cascaded on basic scenarios.&lt;/p&gt;

&lt;p&gt;None of that means "don't use MCP." It means treat it like the young, fast-moving protocol it is: pin versions, scope tool permissions tightly, don't expose an MCP server to the internet without real auth, and don't reach for it reflexively where a normal API call would do the job with far less surface area.&lt;/p&gt;

&lt;p&gt;So: when do you actually reach for which?&lt;/p&gt;

&lt;p&gt;Keep building a regular API when:&lt;/p&gt;

&lt;p&gt;The caller is deterministic code you or another team controls&lt;br&gt;
You need HTTP-layer performance — caching, CDNs, load balancers, the whole stack that REST gets for free&lt;br&gt;
You're shipping a public developer platform with SDKs and docs (developers still want to read docs and write typed clients, not rely on a model choosing tools for them)&lt;br&gt;
Service-to-service communication inside your own backend&lt;/p&gt;

&lt;p&gt;Add an MCP server on top when:&lt;/p&gt;

&lt;p&gt;The caller is an LLM or an agent that needs to decide, at runtime, which capability to use&lt;br&gt;
You want that capability discoverable without a human reading your docs first&lt;br&gt;
You need the model to have restricted, auditable access to a system rather than a raw credential&lt;br&gt;
You're building for Claude, Claude Code, an IDE assistant, or any other MCP host, and want your service to show up as a first-class tool there&lt;/p&gt;

&lt;p&gt;In practice, almost every real MCP server you'll build or use is a wrapper: REST (or a DB driver, or a filesystem call) underneath, MCP as the adapter layer that makes it legible to a model. You're not choosing one or the other. You're deciding whether you need the adapter — and the answer is yes exactly when an AI agent, not a human developer, is the one making the call.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>llm</category>
      <category>mcp</category>
    </item>
    <item>
      <title>How do you handle errors consistently across a Node.js API?</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Wed, 18 Feb 2026 07:51:27 +0000</pubDate>
      <link>https://dev.to/thesnehamk/how-do-you-handle-errors-consistently-across-a-nodejs-api-m8n</link>
      <guid>https://dev.to/thesnehamk/how-do-you-handle-errors-consistently-across-a-nodejs-api-m8n</guid>
      <description>&lt;p&gt;Define a base AppError class with a status code and error code, then subclass it for specific errors (NotFoundError, ValidationError, UnauthorizedError). Register a global error-handling middleware in Express (or exception filter in NestJS) that catches everything, logs it, and returns a consistent error response shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`class AppError extends Error {
  constructor(
    public message: string,
    public statusCode: number,
    public code: string
  ) { super(message); }
}

// Global handler
app.use((err, req, res, next) =&amp;gt; {
  if (err instanceof AppError) {
    return res.status(err.statusCode).json({ error: err.code, message: err.message });
  }
  // Unexpected error
  logger.error(err);
  res.status(500).json({ error: 'INTERNAL_ERROR' });
});`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>typescript</category>
      <category>node</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>How does Tab Order work in the DOM?</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Sun, 01 Feb 2026 19:01:13 +0000</pubDate>
      <link>https://dev.to/thesnehamk/how-does-tab-order-work-in-the-dom-1k37</link>
      <guid>https://dev.to/thesnehamk/how-does-tab-order-work-in-the-dom-1k37</guid>
      <description>&lt;p&gt;&lt;strong&gt;Tab order in the DOM follows these rules:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Default behavior&lt;/strong&gt; — Elements are focused in the order they appear in the HTML source (top to bottom, left to right). Only "focusable" elements participate by default: links (&lt;a href=""&gt;), buttons, form inputs, textareas, selects, and elements with a contenteditable attribute.&lt;/a&gt;&lt;/p&gt;
&lt;a href=""&gt;

&lt;p&gt;The &lt;strong&gt;tabindex&lt;/strong&gt; attribute overrides this in three ways:&lt;/p&gt;

&lt;p&gt;The tabindex="0" attribute makes any element focusable and positions it in the natural DOM order. Useful for custom interactive elements like a div acting as a button.&lt;/p&gt;

&lt;p&gt;Positive values (tabindex="1", tabindex="2", etc.) jump that element ahead of the natural order — elements with lower positive numbers come first, then the rest of the DOM flows normally after all positive-indexed elements are done. This is almost always a bad idea in practice because it creates a jarring, unpredictable experience for keyboard users.&lt;/p&gt;

&lt;/a&gt;&lt;p&gt;&lt;a href=""&gt;&lt;/a&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n3tw679cf45vesx3tyu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n3tw679cf45vesx3tyu.png" alt=" " width="721" height="860"&gt;&lt;/a&gt;&lt;br&gt;
tabindex="-1" makes an element focusable programmatically (via .focus() in JS) but removes it from the sequential tab order entirely. Handy for things like modals or dynamically shown panels that need to receive focus on demand but shouldn't be reachable via Tab key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A quick mental model:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, all elements with positive tabindex values, sorted ascending.&lt;br&gt;
Then, everything else in DOM source order (including tabindex="0" elements).&lt;br&gt;
Elements with tabindex="-1" are skipped entirely during tabbing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;if an element is hidden (display: none or visibility: hidden) or disabled, it's automatically removed from the tab order regardless of its tabindex value.&lt;/em&gt;&lt;/p&gt;



</description>
      <category>webdev</category>
      <category>taborder</category>
      <category>eventdriven</category>
      <category>react</category>
    </item>
    <item>
      <title>Why do keys matter in React, and how do they improve performance?</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Fri, 30 Jan 2026 16:04:10 +0000</pubDate>
      <link>https://dev.to/thesnehamk/why-do-keys-matter-in-react-and-how-do-they-improve-performance-4d1m</link>
      <guid>https://dev.to/thesnehamk/why-do-keys-matter-in-react-and-how-do-they-improve-performance-4d1m</guid>
      <description>&lt;p&gt;&lt;em&gt;Keys give React a stable identity for list elements, allowing the reconciliation algorithm to correctly match elements between renders. This minimizes DOM updates, preserves component state, and improves performance, especially in dynamic lists.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What problem do keys&amp;nbsp;solve?&lt;/strong&gt;&lt;br&gt;
React uses a diffing (reconciliation) algorithm to compare:&lt;br&gt;
Previous Virtual DOM&lt;br&gt;
Next Virtual DOM&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without keys, React:&lt;/strong&gt;&lt;br&gt;
Compares elements by index&lt;br&gt;
May assume elements changed even when they didn't&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With keys, React:&lt;/strong&gt;&lt;br&gt;
Tracks elements by stable identity&lt;br&gt;
Reuses existing DOM nodes when possible&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do keys improve performance?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Prevent unnecessary DOM updates&lt;br&gt;
DOM operations are expensive&lt;br&gt;
Keys allow DOM reuse&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Preserve component state&lt;br&gt;
Without keys → input loses focus/value&lt;br&gt;
With keys → state preserved&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;3&amp;nbsp;. Enable efficient recording&lt;br&gt;
Drag &amp;amp; drop lists&lt;br&gt;
Sorting&lt;br&gt;
Filtering&lt;/p&gt;

&lt;p&gt;&lt;em&gt;React moves nodes instead of destroying &amp;amp; recreating them&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>interview</category>
      <category>programming</category>
    </item>
    <item>
      <title>Date filter for HTML Table</title>
      <dc:creator>Sneha M K</dc:creator>
      <pubDate>Fri, 11 Jun 2021 05:48:28 +0000</pubDate>
      <link>https://dev.to/thesnehamk/date-filter-for-html-table-1meg</link>
      <guid>https://dev.to/thesnehamk/date-filter-for-html-table-1meg</guid>
      <description>&lt;p&gt;Following HTML table has Start Date and End Date in different columns and if we need to filter the rows between these dates with the help of a date picker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;table class="table table-striped mt32 customers-list" id="tableData"&amp;gt;
    &amp;lt;thead&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;th width=40%&amp;gt; Name&amp;lt;/th&amp;gt;
            &amp;lt;th&amp;gt;Internal Name&amp;lt;/th&amp;gt;
            &amp;lt;th&amp;gt;Offer Code&amp;lt;/th&amp;gt;
            &amp;lt;th width=30%&amp;gt;Start Date&amp;lt;/th&amp;gt;
            &amp;lt;th width=30%&amp;gt;End Date&amp;lt;/th&amp;gt;
        &amp;lt;/tr&amp;gt;
    &amp;lt;/thead&amp;gt;
    &amp;lt;tbody&amp;gt;
        &amp;lt;tr id="maintr"&amp;gt;
            &amp;lt;td&amp;gt; Amazon Spring ADP 2020 -$5 Amazon GC &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; PRDOFR168_livePERD &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; SPRINGADPAMZ5GC2020 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; 22-JAN-20 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; 30-APR-20 &amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;tr id="maintr"&amp;gt;
            &amp;lt;td&amp;gt; Indy Car Giveaway 2020 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; PRDOFR170 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; INDYCARSWEEP2020 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; 22-JAN-20 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; 15-APR-20 &amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;tr id="maintr"&amp;gt;
            &amp;lt;td&amp;gt; Indy Car Giveaway 2020 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; PRDOFR170_livePERD &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; INDYCARSWEEP2020 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; 22-JAN-20 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; 15-APR-20 &amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;tr id="maintr"&amp;gt;
            &amp;lt;td&amp;gt; Test Offer 2 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; DEVOFR190 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; 29-JAN-20 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;tr id="maintr"&amp;gt;
            &amp;lt;td&amp;gt; Test Offer 3 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; DEVOFR193 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; 29-JAN-20 &amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt; &amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
    &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Script to filter date on 3 and 4 column&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchbyDate&lt;/span&gt; &lt;span class="o"&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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;startDateArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;endDateArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myTab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tableData&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;InputStartDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date_input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;InputEndDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date_input2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// LOOP THROUGH EACH ROW OF THE TABLE AFTER HEADER.&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;myTab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// GET THE CELLS COLLECTION OF THE CURRENT ROW.&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;objCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myTab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;t1&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objCells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;startDateArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;t2&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objCells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;endDateArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;startDate&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;InputStartDate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;endDate&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;InputEndDate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;startDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;endDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myTable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tableData&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tr&lt;/span&gt;&lt;span class="dl"&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;startDate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;endDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Select Valid Date. Now please Refresh this page to continue to run code.&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;endDateArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&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;var&lt;/span&gt; &lt;span class="nx"&gt;temp1&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startDateArr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;temp2&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endDateArr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&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;startDate&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;InputEndDate&lt;/span&gt;&lt;span class="p"&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;startDate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;temp1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;startDate&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;temp1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&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="k"&gt;else&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;InputStartDate&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;endDate&lt;/span&gt;&lt;span class="p"&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;endDate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;temp2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;endDate&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;temp2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&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="k"&gt;else&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;startDate&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;endDate&lt;/span&gt;&lt;span class="p"&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;startDate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;temp1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;startDate&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;temp1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;endDate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;temp2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;endDate&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;temp2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&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="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;



</description>
      <category>javascript</category>
      <category>html</category>
      <category>css</category>
    </item>
  </channel>
</rss>
