<?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: Junaid Shahid</title>
    <description>The latest articles on DEV Community by Junaid Shahid (@junaidshahid-dev).</description>
    <link>https://dev.to/junaidshahid-dev</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%2F4071296%2Ffb8e98b2-aa51-4208-a7ab-0fa98c382ebb.jpg</url>
      <title>DEV Community: Junaid Shahid</title>
      <link>https://dev.to/junaidshahid-dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/junaidshahid-dev"/>
    <language>en</language>
    <item>
      <title>My AI Agent Found a 5-Sigma Result on Day One. I Deleted It.</title>
      <dc:creator>Junaid Shahid</dc:creator>
      <pubDate>Mon, 10 Aug 2026 12:28:32 +0000</pubDate>
      <link>https://dev.to/junaidshahid-dev/my-ai-agent-found-a-5-sigma-result-on-day-one-i-deleted-it-1nn4</link>
      <guid>https://dev.to/junaidshahid-dev/my-ai-agent-found-a-5-sigma-result-on-day-one-i-deleted-it-1nn4</guid>
      <description>&lt;p&gt;I build with coding agents every day. The failure mode people warn you about — the agent hallucinating an API that doesn't exist — is the easy one. Your code won't run, you notice in seconds, you move on.&lt;/p&gt;

&lt;p&gt;The failure mode that costs you weeks is the opposite: the agent produces something that looks rigorous and isn't.&lt;/p&gt;

&lt;p&gt;Here are two of those, from my own work, and what I changed afterwards.&lt;/p&gt;

&lt;p&gt;The first one was easy to catch&lt;br&gt;
I'd built an autonomous research agent: it proposes hypotheses, tests them against historical data, scores them with pre-registered statistics, and buries the ones that fail.&lt;/p&gt;

&lt;p&gt;On its very first run it surfaced a result about six times stronger than anything months of manual work had found. Five sigma.&lt;/p&gt;

&lt;p&gt;My reaction wasn't excitement, it was suspicion — and the guardrails agreed. The agent had been given access to a data field it shouldn't have had at that point in the loop. It was reading the future. A lookahead bug, not a discovery. Fixed the leak, the "edge" collapsed into noise, and I deleted it the same day.&lt;/p&gt;

&lt;p&gt;That one was easy because the result was too good. Five sigma in that domain doesn't happen. The number itself was the tell.&lt;/p&gt;

&lt;p&gt;The second one nearly got me&lt;br&gt;
Months later, a much more modest result. Small, plausible, the kind of number you'd actually believe.&lt;/p&gt;

&lt;p&gt;I put it through everything I had:&lt;/p&gt;

&lt;p&gt;permutation controls — shuffle the labels, confirm the result disappears. It did.&lt;br&gt;
a holdout split — held-out data never touched during development. It held.&lt;br&gt;
tick-level validation — replayed at the finest granularity available, rather than trusting the coarser bars. It survived that too.&lt;br&gt;
Three independent checks, all passed. I was ready to act on it.&lt;/p&gt;

&lt;p&gt;It was still an artifact. The execution loop had a bug: when an order failed to fill, the loop rewound and retried it under conditions that had already been revealed. Every fill was slightly luckier than reality allowed. Small enough per trade to look plausible, consistent enough across thousands of trades to look like an edge.&lt;/p&gt;

&lt;p&gt;None of my three checks could catch it, because all three ran on top of the same loop. The permutation test shuffled labels and re-ran the same broken loop. The holdout split fed new data into the same broken loop. The tick validation replayed at finer resolution — through the same broken loop.&lt;/p&gt;

&lt;p&gt;I'd built the validation with the agent, in the same session, against the same mental model. The validation inherited the blind spot. I retracted the result publicly and wrote up the mechanism.&lt;/p&gt;

&lt;p&gt;What I actually changed&lt;br&gt;
Not "trust the agent less." That's not operational advice — it doesn't tell you what to do on Monday.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Pre-register the pass criteria before anything runs. Write down the exact thresholds that would make the result real, and what would make you bury it, before you see a number. Once you have an exciting result, every judgement call bends toward keeping it. This is the single highest-value habit and it costs ten minutes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify at a different layer than the one that produced the result. My three checks all sat on top of the execution loop, so none could see a bug inside it. Now, if an agent builds the pipeline, the verification has to touch reality somewhere the pipeline doesn't — different data path, different tool, different assumptions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Treat a surprisingly good result as a bug report. It usually is. The prior on "I found something everyone missed" is far lower than the prior on "my measurement is broken." Spend the first hour trying to kill it, not extend it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish the retraction. This is the one people skip. I've since published a result that weakened my own headline number — a metadata heuristic I'd been using over-predicted failures 4:1 against real verification. Publishing that made the original work more credible, not less, because it showed the number had survived someone genuinely attacking it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The general version&lt;br&gt;
Coding agents are extremely good at producing work that has the shape of rigour. Tests that pass because they assert the current behaviour. Validation that confirms what the pipeline already assumed. Benchmarks measuring the thing that's easy to measure.&lt;/p&gt;

&lt;p&gt;None of that is the agent being dishonest. It's optimising toward the target you handed it, and a plausible-looking result is what you asked for.&lt;/p&gt;

&lt;p&gt;So the useful question isn't "did the agent get it right?" It's:&lt;/p&gt;

&lt;p&gt;What would this look like if it were wrong, and would my checks be able to tell?&lt;/p&gt;

&lt;p&gt;If every check runs through the same code path, the answer is no — and you won't find out until it costs you something.&lt;/p&gt;

&lt;p&gt;The tools and write-ups from this work are open source at github.com/junaidshahid-dev, including the retraction and the false positives I found in my own auditing tool.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>deeplearning</category>
      <category>testing</category>
    </item>
    <item>
      <title>I Installed 300 MCP Servers From PyPI. About 43% Don't Start.</title>
      <dc:creator>Junaid Shahid</dc:creator>
      <pubDate>Mon, 10 Aug 2026 12:26:55 +0000</pubDate>
      <link>https://dev.to/junaidshahid-dev/i-installed-300-mcp-servers-from-pypi-about-43-dont-start-1d3b</link>
      <guid>https://dev.to/junaidshahid-dev/i-installed-300-mcp-servers-from-pypi-about-43-dont-start-1d3b</guid>
      <description>&lt;p&gt;I kept hitting import errors installing MCP servers. Not obscure ones — reference servers from companies whose names you know. After the third, I stopped debugging and started measuring.&lt;/p&gt;

&lt;p&gt;The headline: roughly 43% of Python MCP servers on PyPI don't run on a fresh machine. The cause is one character.&lt;/p&gt;

&lt;p&gt;Here is the method, because the number means nothing without it.&lt;/p&gt;

&lt;p&gt;The trigger&lt;br&gt;
The MCP Python SDK shipped 2.0 and removed several APIs. Any package that declares the SDK with a lower bound and no ceiling —&lt;/p&gt;

&lt;p&gt;mcp&amp;gt;=1.0.0&lt;br&gt;
— now resolves to 2.x on a clean install and dies on import. The maintainer's own machine has a working 1.x cached, so pip install never upgrades anything and the bug is invisible to the one person able to fix it. It only breaks for new users.&lt;/p&gt;

&lt;p&gt;Stage 1: how many packages are exposed?&lt;br&gt;
PyPI carries about 18,000 packages with "mcp" in the name. I took a seeded random sample of 300 (seed 20260806, so anyone can reproduce the exact draw). Of those, 212 were genuine Python MCP servers rather than clients, docs or forks.&lt;/p&gt;

&lt;p&gt;183 of the 212 — 86.3% — declare the MCP SDK with no upper bound.&lt;/p&gt;

&lt;p&gt;That is exposure, not breakage. A package can declare an unbounded dependency and still work fine, because it migrated its code and never tightened the pin. Metadata alone cannot tell you. So stage 1 is necessary and not sufficient, and reporting 86% as a failure rate would have been wrong.&lt;/p&gt;

&lt;p&gt;Stage 2: install them and see&lt;br&gt;
I drew 30 of those 183 at random and installed each in a genuinely fresh virtualenv — never reused, because a cached SDK is the entire reason this bug hides. Then I found each package's console entry points and ran them with stdin closed.&lt;/p&gt;

&lt;p&gt;immediate traceback → broken&lt;br&gt;
exits quietly on EOF, or blocks waiting for input → starts fine&lt;br&gt;
Two failed to install at all. Of the 28 that installed, 14 failed to start.&lt;/p&gt;

&lt;p&gt;Combined with stage 1, that puts roughly 43% of Python MCP servers on PyPI in a broken state on a fresh machine, 95% CI 26–61%. The interval is wide because 30 installs is a small sample, and I would rather publish the interval than a tidy number.&lt;/p&gt;

&lt;p&gt;Three errors, one cause&lt;br&gt;
ModuleNotFoundError: No module named 'mcp.server.fastmcp'&lt;br&gt;
ImportError: cannot import name 'McpError'&lt;br&gt;
AttributeError: 'Server' object has no attribute 'list_tools'&lt;br&gt;
All three are the same event: code written against 1.x, running on an SDK that removed those APIs.&lt;/p&gt;

&lt;p&gt;The part I didn't expect&lt;br&gt;
I assumed the failures would be abandoned weekend projects. They weren't.&lt;/p&gt;

&lt;p&gt;Separately from the random sample, I tested 23 established servers — widely used ones, including reference implementations from major companies. 18 of 21 that installed failed to start: 86%, against 50% for randomly drawn packages.&lt;/p&gt;

&lt;p&gt;Better-known packages were worse. The likely reason is age. They were written early, against 1.x, and nobody has installed them from scratch since. Popularity doesn't protect you here; it correlates with having been written before the breaking change.&lt;/p&gt;

&lt;p&gt;The trap I fell into myself&lt;br&gt;
Having found that unbounded pins predict breakage, the obvious next move is to skip the installs and just read everyone's metadata. It's free and instant.&lt;/p&gt;

&lt;p&gt;It doesn't work. I took four organisation-owned repos whose pins flagged them as broken and verified them properly in clean virtualenvs. Only one actually failed. Two started fine despite unbounded pins, and one failed to install for an unrelated reason.&lt;/p&gt;

&lt;p&gt;The metadata heuristic over-predicts about 4:1. That is why the tool does real installs, and why I'm publishing this against my own headline number rather than quietly keeping the tidier version.&lt;/p&gt;

&lt;p&gt;The fix&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mcp&amp;gt;=1.0.0&lt;/li&gt;
&lt;li&gt;mcp&amp;gt;=1.0.0,&amp;lt;2
I verified this on every server that failed: pinning below 2.0 restored startup in all of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you maintain a Python package that depends on the MCP SDK, the check takes about four seconds and cannot be done on your dev machine:&lt;/p&gt;

&lt;p&gt;python -m venv /tmp/checkme&lt;br&gt;
/tmp/checkme/bin/pip install your-package-name&lt;br&gt;
/tmp/checkme/bin/your-entry-point&lt;br&gt;
A brand new virtualenv, not the one you already have.&lt;/p&gt;

&lt;p&gt;Limitations&lt;br&gt;
The install stage is n=30. Hence the 26–61% interval. The metadata stage is n=212 and much tighter.&lt;br&gt;
Tested on Windows with Python 3.13. Resolution can differ across platforms.&lt;br&gt;
"Starts without a traceback" is a low bar. It does not mean the server is correct — only that it runs.&lt;br&gt;
Packages under a separate coordinated-disclosure process were excluded from published results.&lt;br&gt;
Tools and data&lt;br&gt;
Everything is open: the sampler, the verifier, the raw JSON results, and the seed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/junaidshahid-dev/mcp-probe" rel="noopener noreferrer"&gt;https://github.com/junaidshahid-dev/mcp-probe&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That repo also lists five false positives I found in my own tool and fixed, because a scanner that fails well-built packages is worse than no scanner at all.&lt;/p&gt;

&lt;p&gt;If you maintain an MCP server, go and run the clean-venv check. It takes four seconds and it is not something you can see from where you're standing.&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>ai</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
