<?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: connerlambden</title>
    <description>The latest articles on DEV Community by connerlambden (@connerlambden).</description>
    <link>https://dev.to/connerlambden</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3776793%2F2b4714ed-0e1b-407a-a636-4236e644b524.jpeg</url>
      <title>DEV Community: connerlambden</title>
      <link>https://dev.to/connerlambden</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/connerlambden"/>
    <language>en</language>
    <item>
      <title>A 260-line vanilla-JS dashboard for ML stock forecasts (one CORS-open MCP endpoint, zero dependencies)</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Wed, 27 May 2026 16:07:32 +0000</pubDate>
      <link>https://dev.to/connerlambden/a-260-line-vanilla-js-dashboard-for-ml-stock-forecasts-one-cors-open-mcp-endpoint-zero-2mk6</link>
      <guid>https://dev.to/connerlambden/a-260-line-vanilla-js-dashboard-for-ml-stock-forecasts-one-cors-open-mcp-endpoint-zero-2mk6</guid>
      <description>&lt;p&gt;I'm a fan of "smallest thing that could possibly work" demos for APIs. If a tool needs Node + Webpack + a build step + 800 KB of &lt;code&gt;node_modules&lt;/code&gt; before I can see what it does, I quietly close the tab.&lt;/p&gt;

&lt;p&gt;So when I wanted to make a visual surface for &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;Helium MCP's&lt;/a&gt; top-10 volatility candidate ticker stream, I went the other way: a single HTML file, one fetch call, no dependencies, no build, ~260 lines of JS. It is live at:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://connerlambden.github.io/helium-news-explorer/tickers.html" rel="noopener noreferrer"&gt;connerlambden.github.io/helium-news-explorer/tickers.html&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is the architecture and the small handful of choices that made it work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The endpoint
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://heliumtrades.com/mcp_top_strategies/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns a JSON object:&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;"sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"expected_vol_30d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"short_volatility"&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tickers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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;"long_volatility"&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tickers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each ticker entry packs everything I need into one object:&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;"ticker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NVDA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NVIDIA Corporation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latest_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;138.45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price_forecast_days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price_forecast_percent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price_forecast_lower_bound_percent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-12.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price_forecast_upper_bound_percent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;29.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bullish_case"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;p&amp;gt;Blackwell ramp ahead of plan; ...&amp;lt;/p&amp;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;"bearish_case"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;p&amp;gt;Hyperscaler capex digestion risk; ...&amp;lt;/p&amp;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;"analysis_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-05-27"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"page_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's huge: the central forecast number AND the bull/bear narrative AND the uncertainty bounds come from the same model, so the chart you draw and the words you display agree on the same view of the world. No reconciliation step. No data joining. Just &lt;code&gt;fetch&lt;/code&gt;, then render.&lt;/p&gt;

&lt;p&gt;Crucially, Helium's MCP REST endpoints set &lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt;, so the page can fetch directly from the browser — no proxy, no server, no CORS tax.&lt;/p&gt;

&lt;h2&gt;
  
  
  The whole render path
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;…&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://heliumtrades.com/mcp_top_strategies/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;resp&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="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="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div class="columns"&amp;gt;
      &amp;lt;div class="column short"&amp;gt;
        &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;short_volatility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;cardHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class="column long"&amp;gt;
        &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;long_volatility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;cardHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two columns. Five cards each. Template literals as a render engine. That's it. No virtual DOM, no reactivity, no router. The page is static the moment the fetch resolves.&lt;/p&gt;

&lt;h2&gt;
  
  
  The uncertainty cone in 18 lines of SVG
&lt;/h2&gt;

&lt;p&gt;The interesting visual is the per-card &lt;em&gt;uncertainty cone&lt;/em&gt; — a small wedge that gets wider with time, shaded green or red based on the forecast direction, with a line through the center showing the central forecast and a label at the endpoint:&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;function&lt;/span&gt; &lt;span class="nf"&gt;renderCone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;forecastPct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lowerPct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;upperPct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;W&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;260&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;H&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PAD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&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;maxAbs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lowerPct&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upperPct&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                          &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;forecastPct&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yZero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PAD&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;H&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;PAD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&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;pctToY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;yZero&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;maxAbs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;H&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;PAD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&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;xStart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PAD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xEnd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;W&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;PAD&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;yUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pctToY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upperPct&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;yDn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pctToY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lowerPct&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;yFc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pctToY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;forecastPct&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;stroke&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;forecastPct&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#6bff9c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
               &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;forecastPct&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ff6b8a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
               &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#8a93b8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,0.18)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rgba(&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="s2"&gt;`&amp;lt;svg viewBox="0 0 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;W&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;H&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" preserveAspectRatio="none"&amp;gt;
    &amp;lt;polygon points="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xStart&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;yZero&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;xEnd&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;yUp&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;xEnd&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;yDn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
             fill="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" stroke="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"/&amp;gt;
    &amp;lt;line x1="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xStart&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" y1="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;yZero&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" x2="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xEnd&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" y2="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;yFc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
          stroke="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" stroke-width="1.6"/&amp;gt;
    &amp;lt;circle cx="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xEnd&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" cy="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;yFc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" r="3" fill="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"/&amp;gt;
  &amp;lt;/svg&amp;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 cone is just a polygon with three points: &lt;code&gt;(start, 0)&lt;/code&gt;, &lt;code&gt;(end, upper)&lt;/code&gt;, &lt;code&gt;(end, lower)&lt;/code&gt;. The forecast line is a single segment from &lt;code&gt;(start, 0)&lt;/code&gt; to &lt;code&gt;(end, forecast)&lt;/code&gt;. The whole shape collapses to a point at the left edge ("today") and fans out on the right ("today + 37 days").&lt;/p&gt;

&lt;p&gt;I went back and forth on whether to plot the cone in absolute price terms vs. percent terms. Percent won: it makes a $69 KO card and a $1842 MSTR card visually comparable, since both cones are scaled to their own max-abs bound. You see the &lt;em&gt;shape&lt;/em&gt; of uncertainty, not the units.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why no chart library?
&lt;/h2&gt;

&lt;p&gt;Because for 10 small charts with one polygon and one line each, a chart library is more code than the chart itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;D3: 270 KB. Sets up &lt;code&gt;d3.scaleLinear()&lt;/code&gt;, &lt;code&gt;d3.area()&lt;/code&gt;, axes you don't need.&lt;/li&gt;
&lt;li&gt;Chart.js: 200 KB. Needs a canvas, animation loop, plugin system.&lt;/li&gt;
&lt;li&gt;ECharts: 1 MB+.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hand-rolled SVG: 18 lines. The browser already has a SVG renderer. The math is one division per coordinate. The styling lives in the same CSS file as the rest of the page. Less is more.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bull/bear narratives are HTML
&lt;/h2&gt;

&lt;p&gt;Helium returns the cases as &lt;code&gt;&amp;lt;p&amp;gt;...&amp;lt;/p&amp;gt;&lt;/code&gt; strings. Easiest possible strip:&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;function&lt;/span&gt; &lt;span class="nf"&gt;stripHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tmp&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;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&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;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&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="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/g&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="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;Then truncate to ~280 chars with a word-boundary check so you don't cut mid-word:&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;function&lt;/span&gt; &lt;span class="nf"&gt;truncate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&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;s&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;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;n&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;s&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;cut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&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;n&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;lastSp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastIndexOf&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastSp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;cut&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;lastSp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cut&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="s2"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The card links to the full Helium analysis page for the long-form version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failure handling
&lt;/h2&gt;

&lt;p&gt;The one real failure mode is a per-IP daily quota on the free tier (Helium returns HTTP 402 with no CORS headers, which the browser surfaces as a generic &lt;code&gt;TypeError: Failed to fetch&lt;/code&gt;). I handle it the boring honest way:&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="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;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-store&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;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&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;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&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="c1"&gt;// ... render ...&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;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Could not load forecasts: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&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;.
    The Helium REST API enforces a per-IP daily quota for unauthenticated calls.
    Reload tomorrow, or browse the
    &amp;lt;a href="https://github.com/connerlambden/helium-mcp-cookbook"&amp;gt;cookbook&amp;lt;/a&amp;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;A casual visitor will not hit this — each page load is one GET, and the free quota is ~50/day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Companion explorer
&lt;/h2&gt;

&lt;p&gt;The same repo also hosts a &lt;strong&gt;News Bias Explorer&lt;/strong&gt; at the root, built on the same pattern: one fetch to &lt;code&gt;mcp_all_source_biases/&lt;/code&gt;, vanilla-JS render of 216 sources × 37 bias dimensions, ranked bars and scatter plots with a live Pearson correlation. Same architecture, different data surface. &lt;a href="https://connerlambden.github.io/helium-news-explorer/" rel="noopener noreferrer"&gt;connerlambden.github.io/helium-news-explorer&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for the MCP ecosystem
&lt;/h2&gt;

&lt;p&gt;Most MCP server demos are dense Python notebooks or CLI tools. They demonstrate the protocol but not the &lt;em&gt;data&lt;/em&gt;. A casual visitor — a journalist evaluating bias-scoring tools, a retail trader curious about an options model, a researcher looking for a teaching corpus — won't install Python to find out.&lt;/p&gt;

&lt;p&gt;A 21 KB HTML file on GitHub Pages, with no signup and no key, is the lowest-friction path from "I just heard about this server" to "oh, here's what it can do."&lt;/p&gt;

&lt;p&gt;If you're building an MCP server, consider shipping a small zero-dep web surface next to your CLI examples. The marginal cost is one HTML file. The marginal benefit is every browser becoming a demo client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live dashboard&lt;/strong&gt;: &lt;a href="https://connerlambden.github.io/helium-news-explorer/tickers.html" rel="noopener noreferrer"&gt;connerlambden.github.io/helium-news-explorer/tickers.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live news bias explorer&lt;/strong&gt;: &lt;a href="https://connerlambden.github.io/helium-news-explorer/" rel="noopener noreferrer"&gt;connerlambden.github.io/helium-news-explorer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source&lt;/strong&gt;: &lt;a href="https://github.com/connerlambden/helium-news-explorer" rel="noopener noreferrer"&gt;github.com/connerlambden/helium-news-explorer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python recipes for the same API&lt;/strong&gt;: &lt;a href="https://github.com/connerlambden/helium-mcp-cookbook" rel="noopener noreferrer"&gt;github.com/connerlambden/helium-mcp-cookbook&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Helium MCP server&lt;/strong&gt;: &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;github.com/connerlambden/helium-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The forecasts and bias scores are educational. Not investment advice. Track calibration; the model is wrong all the time.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>mcp</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Fear-coding in 160 news sources correlates +0.85 with political extremism — and only -0.08 with political direction</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Wed, 27 May 2026 15:31:35 +0000</pubDate>
      <link>https://dev.to/connerlambden/fear-coding-in-160-news-sources-correlates-085-with-political-extremism-and-only-008-with-45n2</link>
      <guid>https://dev.to/connerlambden/fear-coding-in-160-news-sources-correlates-085-with-political-extremism-and-only-008-with-45n2</guid>
      <description>&lt;p&gt;A common assumption in newsroom and media-literacy discourse is that fear-coded language is correlated with political "side" — that one ideological camp uses more fear language than the other. I wanted to test this empirically, so I pulled a structured per-source bias corpus, kept the sources with at least 100 analyzed articles plus both fear and political scores, and computed two correlations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pearson &lt;strong&gt;r between fear language and political direction&lt;/strong&gt; (left vs right): &lt;strong&gt;−0.081&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Pearson &lt;strong&gt;r between fear language and political extremism&lt;/strong&gt; (|liberal–conservative|, ignoring direction): &lt;strong&gt;+0.854&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's a striking gap. In a sample of 160 sources, fear-coded language barely correlates with political direction — but it correlates &lt;strong&gt;very strongly&lt;/strong&gt; with how &lt;em&gt;far&lt;/em&gt; a source sits from the center, on either side. Fear is a feature of extremism, not of ideology.&lt;/p&gt;

&lt;p&gt;This post walks through the data, the API I used, and the replication code. The whole analysis is under 30 lines of Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data
&lt;/h2&gt;

&lt;p&gt;I used the &lt;code&gt;mcp_all_source_biases&lt;/code&gt; endpoint of the &lt;a href="https://heliumtrades.com/mcp-page/" rel="noopener noreferrer"&gt;Helium MCP server&lt;/a&gt;, which exposes a structured bias profile for every source in its corpus. The endpoint is a plain HTTPS GET — no API key, no signup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://heliumtrades.com/mcp_all_source_biases/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns 216 sources, each with two top-level numeric fields (&lt;code&gt;emotionality_score&lt;/code&gt;, &lt;code&gt;prescriptiveness_score&lt;/code&gt;) plus a nested &lt;code&gt;bias_values&lt;/code&gt; dict. Across the corpus, 37 distinct named dimensions appear in &lt;code&gt;bias_values&lt;/code&gt;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;overall credibility&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fearful bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;liberal conservative bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;opinion bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;oversimplification bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;appeal to authority bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;establishment bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cruelty bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scapegoat bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conspiracy bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;victimization bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ideological bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;political bias&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;written by AI&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and 23 others. Each value is an integer score. Most dimensions are populated for 150+ of the 216 sources.&lt;/p&gt;

&lt;p&gt;For this analysis I filtered to sources with ≥100 analyzed articles plus both a &lt;code&gt;fearful bias&lt;/code&gt; and a &lt;code&gt;liberal conservative bias&lt;/code&gt; score. That left &lt;strong&gt;160 sources&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The analysis
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_all_source_biases/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;bv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bias_values&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;fear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bv&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fearful bias&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bv&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liberal conservative bias&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;articles_analyzed&lt;/span&gt;&lt;span class="sh"&gt;"&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;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;fear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;fear_vals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;pol_vals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pearson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cov&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;mx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pstdev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pstdev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cov&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sx&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;sy&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sources analyzed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r(fear, lib-cons direction) = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;pearson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fear_vals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pol_vals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r(fear, |lib-cons|)          = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;pearson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fear_vals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pol_vals&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output on my run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sources analyzed: 160
r(fear, lib-cons direction) = -0.081
r(fear, |lib-cons|)         = +0.854
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The top-15 most-fear-coded sources, with political context
&lt;/h2&gt;

&lt;p&gt;Let me show the actual sources. Below are the 15 sources with the highest &lt;code&gt;fearful bias&lt;/code&gt; scores, with their &lt;code&gt;liberal conservative bias&lt;/code&gt; and &lt;code&gt;overall credibility&lt;/code&gt; shown alongside.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Fear&lt;/th&gt;
&lt;th&gt;L/C&lt;/th&gt;
&lt;th&gt;Cred&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;World Socialist&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;−33&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;American Thinker&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;+23&lt;/td&gt;
&lt;td&gt;−2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global Research&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;−14&lt;/td&gt;
&lt;td&gt;−11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common Dreams&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;−33&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Activist Post&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;−3&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Federalist&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;+26&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Counterpunch&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;−27&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Canary&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;−24&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Truthout&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;−29&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily Sceptic&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;+14&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway Pundit&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;+24&lt;/td&gt;
&lt;td&gt;−6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily Signal&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;+29&lt;/td&gt;
&lt;td&gt;−2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;newrepublic.com&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;−28&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;American Spectator&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;+20&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;newsbusters.org&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;+20&lt;/td&gt;
&lt;td&gt;−1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice the pattern: the L/C column has values like −33, +23, −14, −33, −3, +26, −27, −24, −29, +14, +24, +29, −28, +20, +20. The values are &lt;em&gt;far from zero in both directions&lt;/em&gt;. Of the 15 sources, 8 are coded as politically left, 7 as politically right. The political direction is roughly balanced; the political &lt;em&gt;magnitude&lt;/em&gt; is huge.&lt;/p&gt;

&lt;p&gt;Compare with the middle-tercile mean. When I split the 160 sources into terciles by political direction:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tercile&lt;/th&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;th&gt;L/C range&lt;/th&gt;
&lt;th&gt;Mean fear&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Left&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;−33..−1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.74&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Center&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;−1..0&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.23&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Right&lt;/td&gt;
&lt;td&gt;54&lt;/td&gt;
&lt;td&gt;0..+29&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.41&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The U-shape is unmistakable. The center-tercile fear mean is less than 40% of either edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what?
&lt;/h2&gt;

&lt;p&gt;This kind of finding is what structured bias measurement is &lt;em&gt;for&lt;/em&gt;. It's the empirical test of a folk-wisdom hypothesis. The folk wisdom predicts a monotonic relationship between fear language and one side of the political spectrum; the data shows a V-shape with the symmetry-breaking factor being political extremism, not political direction.&lt;/p&gt;

&lt;p&gt;A few corollaries that I think are interesting:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Media-literacy curricula that teach "watch out for fear language as a signal of bias" should add: in either direction.&lt;/strong&gt; Treating fear-coding as a signal exclusive to one camp will systematically miss the other camp's instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Newsroom self-audits that compare against ideological peers will see less fear than they expected.&lt;/strong&gt; The right peer-group for comparison is &lt;em&gt;moderation&lt;/em&gt;, not "the other side".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For any structured news intake (LLM agent, RAG pipeline, fact-checking workflow), &lt;code&gt;fearful bias&lt;/code&gt; is partially redundant with &lt;code&gt;|lib-cons|&lt;/code&gt;.&lt;/strong&gt; They share most of their variance. If you're already adjusting for ideological extremism, you're already adjusting for most fear-coding.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A secondary finding while I was there: "written by AI" coverage
&lt;/h2&gt;

&lt;p&gt;The same endpoint exposes a &lt;code&gt;written by AI&lt;/code&gt; dimension. It's only populated for 27 of the 216 sources with ≥100 articles — a sparse signal. The top of the distribution is mostly auto-generated finance summary sites:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;"written by AI"&lt;/th&gt;
&lt;th&gt;Cred&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;quiverquant.com (Opinion)&lt;/td&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;marketbeat.com&lt;/td&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rappler.com&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;studyfinds.com&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fool.com&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;benzinga.com&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;While the bottom (Reuters, CNBC, journal-news, tradingview, news-medical, etc.) sits at 0. Without more methodology detail this is suggestive rather than definitive, but the pattern matches what you'd expect: template-driven finance content scores high, established human-staffed publications score low.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replicate it yourself
&lt;/h2&gt;

&lt;p&gt;The full analysis is 25 lines of Python with &lt;code&gt;requests&lt;/code&gt; as the only dependency. If you want to extend it, the &lt;a href="https://github.com/connerlambden/helium-mcp-cookbook" rel="noopener noreferrer"&gt;helium-mcp-cookbook&lt;/a&gt; repo has a &lt;code&gt;recipes/01_news_bias_dashboard.py&lt;/code&gt; script that does the corpus pull and dimension-ranking for any of the 37 bias dimensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/connerlambden/helium-mcp-cookbook
&lt;span class="nb"&gt;cd &lt;/span&gt;helium-mcp-cookbook
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
python recipes/01_news_bias_dashboard.py &lt;span class="s2"&gt;"fearful bias"&lt;/span&gt; 20
python recipes/01_news_bias_dashboard.py &lt;span class="s2"&gt;"scapegoat bias"&lt;/span&gt; 20
python recipes/01_news_bias_dashboard.py &lt;span class="s2"&gt;"cruelty bias"&lt;/span&gt; 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run the same correlation analysis against any pair of dimensions. The 37-dimension space has 666 ordered pairs; I suspect there are several more publishable findings in there.&lt;/p&gt;

&lt;p&gt;If you'd like the same endpoints inside an LLM client instead of a Python script, the MCP server config is in the &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;main repo README&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;The single most useful thing a structured-bias corpus does is &lt;em&gt;let folk wisdom be tested&lt;/em&gt;. Fear-coding-as-left-coded or fear-coding-as-right-coded is a hypothesis everyone has informally, and now we can ask the data. The data says: it's not about side. It's about distance from the center.&lt;/p&gt;

&lt;p&gt;That's the kind of empirical finding that should travel further than my marketing budget. Replicate the numbers, push back if you disagree, and if you find a different pattern with the same data, write the post — I'd love to read it.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>python</category>
      <category>journalism</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>How to Brier-grade your own ML option-pricing forecasts in 40 lines of Python</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Wed, 27 May 2026 03:33:09 +0000</pubDate>
      <link>https://dev.to/connerlambden/how-to-brier-grade-your-own-ml-option-pricing-forecasts-in-40-lines-of-python-2gb2</link>
      <guid>https://dev.to/connerlambden/how-to-brier-grade-your-own-ml-option-pricing-forecasts-in-40-lines-of-python-2gb2</guid>
      <description>&lt;p&gt;If you ship a probabilistic forecast, the single highest-value habit you can build is &lt;em&gt;logging your forecasts so you can grade them later&lt;/em&gt;. Sabermetrics figured this out forty years ago. Weather forecasting has done it for a century. Most ML model owners still do not do it.&lt;/p&gt;

&lt;p&gt;This post walks through a 40-line Python recipe that logs an ML option-pricing model's per-contract probability-ITM forecast to a CSV, so you can compute the Brier loss after the option expires. The recipe is part of a small open-source cookbook for the &lt;a href="https://heliumtrades.com/mcp-page/" rel="noopener noreferrer"&gt;Helium MCP&lt;/a&gt; REST surface — an MCP server that also exposes its tools as plain HTTPS GETs, which makes it convenient as a teaching substrate even if you do not use MCP.&lt;/p&gt;

&lt;p&gt;You will not need an API key, a signup, or a Python SDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we are doing
&lt;/h2&gt;

&lt;p&gt;For every option contract we care about, we want one row that records:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The contract identifier (symbol, strike, expiration, type)&lt;/li&gt;
&lt;li&gt;The model's predicted fair value&lt;/li&gt;
&lt;li&gt;The model's probability the contract finishes in the money&lt;/li&gt;
&lt;li&gt;The model's data date&lt;/li&gt;
&lt;li&gt;(Filled in later) the market mark at the same timestamp&lt;/li&gt;
&lt;li&gt;(Filled in at expiration) the realized underlying price&lt;/li&gt;
&lt;li&gt;(Computed) whether the contract was actually ITM&lt;/li&gt;
&lt;li&gt;(Computed) the Brier loss for the probability forecast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we Brier-grade later, we get one number per contract. Average across many contracts and we have a directly comparable calibration score — exactly the discipline a baseball win-probability model or a weather precipitation forecast gets graded on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The endpoint
&lt;/h2&gt;

&lt;p&gt;The Helium server exposes its option-pricing tool at this URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://heliumtrades.com/mcp_option_price/
    ?symbol=AAPL&amp;amp;strike=310&amp;amp;expiration=2026-06-26&amp;amp;option_type=call
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plain GET, JSON in / JSON out, no auth header, free tier of 50 calls per IP per day. A live call returns:&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;"symbol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AAPL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"strike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;310.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expiration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-26"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"option_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;"call"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"predicted_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prob_itm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"options_data_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-05-26"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two of those fields are forecasts about the future: &lt;code&gt;predicted_price&lt;/code&gt; (the model's fair value) and &lt;code&gt;prob_itm&lt;/code&gt; (the model's probability the option finishes ITM at expiration). The expiration date in the request is the fixed resolution date. That gives us a clean falsifiable target.&lt;/p&gt;

&lt;h2&gt;
  
  
  The recipe
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Log Helium&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s ML option-price + prob_itm forecasts to a CSV so you can
Brier-grade them at expiration.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_option_price/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;LOG_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calibration_log.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strike&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expiration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;option_type&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;symbol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strike&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;strike&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expiration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;expiration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;option_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;option_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="n"&gt;ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&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="n"&gt;is_new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_new&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;symbol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strike&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expiration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;option_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helium_predicted_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helium_prob_itm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helium_data_date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_mark&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;realized_underlying_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;realized_itm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;brier_loss&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timespec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strike&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expiration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;option_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;data&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;predicted_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;data&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prob_itm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;data&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;options_data_date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Logged &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;strike&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;option_type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;expiration&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;predicted=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;predicted_price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; prob_itm=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prob_itm&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save as &lt;code&gt;track.py&lt;/code&gt;, then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests
python track.py AAPL 310 2026-06-26 call
python track.py AAPL 295 2026-06-26 put
python track.py NVDA 220 2026-07-17 call
&lt;span class="c"&gt;# repeat for any contracts you want to grade later&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script appends one row per contract to &lt;code&gt;calibration_log.csv&lt;/code&gt;. Snapshot the file once a day to capture how the forecast evolves over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grading the forecast after expiration
&lt;/h2&gt;

&lt;p&gt;At expiration, fill in the realized underlying price and compute Brier loss. For a single contract the Brier loss for the prob_itm forecast is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brier_loss = (prob_itm - realized_itm) ** 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;realized_itm&lt;/code&gt; is 1 if the contract finished in the money and 0 otherwise. Score every contract you logged, average the losses, and you have a calibration number you can compare across models, weeks, or strike regimes.&lt;/p&gt;

&lt;p&gt;A quick scorer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calibration_log.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;realized_itm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;realized_underlying_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strike&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;option_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;resolved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;realized_underlying_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;realized_itm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;realized_itm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&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="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;brier_loss&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helium_prob_itm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;realized_itm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Contracts graded: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mean Brier loss: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;brier_loss&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Calibration histogram:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resolved&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helium_prob_itm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;),&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="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;realized_itm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The calibration histogram is the part most people skip. A model with mean Brier loss of 0.18 can still be wildly miscalibrated in specific probability bins (overconfident at extreme ends, say). The histogram tells you &lt;em&gt;where&lt;/em&gt; it is miscalibrated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is useful
&lt;/h2&gt;

&lt;p&gt;Most quant content compares predicted prices to current prices and stops there. That comparison cannot distinguish between "the model is right and the market is wrong" and the reverse — and both are unfalsifiable until expiration. Probability-ITM, on the other hand, has an unambiguous resolution: the underlying either closes above the strike or it does not.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;prob_itm&lt;/code&gt; is the friendliest output to grade. If you want to spend an hour playing with calibration intuition, log forecasts for 50 contracts across a few different expirations, wait for them to resolve, and run the scorer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other recipes in the cookbook
&lt;/h2&gt;

&lt;p&gt;The same pattern — one endpoint, one short script, real output — works for the other tools the Helium server exposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;News-bias dashboard: pull every tracked source's bias profile and rank by &lt;code&gt;overall credibility&lt;/code&gt;, &lt;code&gt;fearful bias&lt;/code&gt;, &lt;code&gt;emotionality_score&lt;/code&gt;, or any other dimension&lt;/li&gt;
&lt;li&gt;Balanced-news synthesis: pull multi-source synthesis on any topic with probability-weighted falsifiable outcomes already baked in&lt;/li&gt;
&lt;li&gt;Source credibility ranking: top-N and bottom-N sources by credibility, with their emotionality and prescriptiveness alongside&lt;/li&gt;
&lt;li&gt;Ticker forecast explorer: pull HTML-stripped bull/bear narrative cases for a watchlist&lt;/li&gt;
&lt;li&gt;Top-strategies explorer: pull the daily short-vol and long-vol candidate lists&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All six recipes are in the open-source cookbook here:&lt;/p&gt;

&lt;p&gt;➡️ &lt;strong&gt;&lt;a href="https://github.com/connerlambden/helium-mcp-cookbook" rel="noopener noreferrer"&gt;github.com/connerlambden/helium-mcp-cookbook&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The cookbook is MIT-licensed. Fork it, modify it, write your own recipes. PRs welcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you want MCP instead of REST
&lt;/h2&gt;

&lt;p&gt;The same ten tools are also exposed as a remote MCP server. If you would rather call them from inside Claude Desktop, Cursor, or any MCP-aware client, the config is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"helium"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://heliumtrades.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a client restart your LLM can call the same tools by name. The Helium repo is at &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;github.com/connerlambden/helium-mcp&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;If your model emits probabilities, you should grade them. The friction-free version is a 40-line script and a CSV. The day you put that habit in place is the day your forecasts start improving — not because the model changes, but because you finally have a feedback signal to learn from.&lt;/p&gt;

</description>
      <category>python</category>
      <category>mcp</category>
      <category>finance</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>I probed my own MCP server — here's what 7 live API calls actually return</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Wed, 27 May 2026 00:28:37 +0000</pubDate>
      <link>https://dev.to/connerlambden/i-probed-my-own-mcp-server-heres-what-7-live-api-calls-actually-return-16o0</link>
      <guid>https://dev.to/connerlambden/i-probed-my-own-mcp-server-heres-what-7-live-api-calls-actually-return-16o0</guid>
      <description>&lt;p&gt;I've been writing about MCP servers for a couple of months now. The most common (fair) reply I get is some version of &lt;em&gt;"cool thesis, but show me what actually comes back when you call it."&lt;/em&gt; This post does exactly that. I sat down today, ran seven real calls against the Helium MCP + REST surface, and pasted the actual JSON below. No screenshots, no curated demos, no "imagine if." The numbers below are timestamped May 26, 2026, the same day I wrote this.&lt;/p&gt;

&lt;p&gt;Helium is a free MCP server + plain REST API that combines two things people normally pay separate vendors for: (1) per-symbol ML-derived options pricing and (2) 31-dimensional structured news-bias scoring across ~5,000 sources. The REST surface is meant to be reachable from a five-line &lt;code&gt;requests.get&lt;/code&gt;. The MCP surface is the same backend with tool-registration metadata on top. There's no signup, no API key, no SDK — just an IP-rate-limited free tier (50/day).&lt;/p&gt;

&lt;p&gt;Let's see what it returns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Probe 1: NVDA ticker (&lt;code&gt;/mcp_ticker/&lt;/code&gt;)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_ticker/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ticker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NVDA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What came back today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Latest price:&lt;/strong&gt; $215.33&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;37-day forecast:&lt;/strong&gt; +6.0% (lower-bound +2%, upper-bound +10%)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Probability-weighted outcomes:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;45% — NVDA above $230 within 45-90 days&lt;/li&gt;
&lt;li&gt;25% — chop in $210-230 over 30-120 days&lt;/li&gt;
&lt;li&gt;20% — drift to $190-210 within 45-120 days&lt;/li&gt;
&lt;li&gt;7% — severe to $180-190 within 60-120 days&lt;/li&gt;
&lt;li&gt;3% — ultra-bearish below $180&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Each probability is supposed to be Brier-scoreable — if the model says "45% above $230 in 45 days," that's a falsifiable claim with a resolution date. You can backtest it against expiration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Probe 2: AAPL options ML pricing (&lt;code&gt;get_option_price&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;This is the one I most wanted to test live. AAPL is at $308.33 today. I asked for the 30-DTE $310 call (close to ATM, June 26 expiration):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_option_price/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;symbol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAPL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strike&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;310&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expiration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-06-26&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;option_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&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="c1"&gt;# {"symbol":"AAPL","strike":310.0,"expiration":"2026-06-26","option_type":"call",
#  "predicted_price":6.53,"prob_itm":0.42,"options_data_date":"2026-05-26"}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The market mark on this contract today is &lt;strong&gt;$7.55&lt;/strong&gt;. Helium's model says fair value is &lt;strong&gt;$6.53&lt;/strong&gt; — i.e., the contract is &lt;em&gt;overpriced by ~$1&lt;/em&gt;, or ~13.5% above what the model thinks it should clear.&lt;/p&gt;

&lt;p&gt;The contract's delta is 0.50 (market-implied probability of finishing in the money is ~50%). Helium's &lt;code&gt;prob_itm&lt;/code&gt; is &lt;strong&gt;0.42&lt;/strong&gt;, meaningfully lower. Two ways to read it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The model thinks IV is too high. (Helium thinks realized vol will undershoot implied — a short-premium-into-strength view.)&lt;/li&gt;
&lt;li&gt;The model is wrong. (Always a live hypothesis.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The point is &lt;em&gt;the disagreement is concrete and testable&lt;/em&gt;. On June 26, this contract resolves. If AAPL closes below $310, the model wins one (or rather, gets a partial credit on the calibration test). The whole point of &lt;code&gt;prob_itm&lt;/code&gt; being explicit is so you can score it. Compare with the put side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# AAPL 295P 6/26  — market mark $3.09
# Helium predicted: $2.36  /  prob_itm 0.23  (market-implied via delta: ~0.24)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The put case is funnier: Helium agrees with market-implied probability to within one percentage point, but disagrees on the &lt;em&gt;price&lt;/em&gt; by ~24%. That can only happen if the model thinks the &lt;strong&gt;payoff conditional on ITM is smaller&lt;/strong&gt; than what market IV would price it. That's a different bet from the call-side bet, and you can see both surfaces from the same endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Probe 3: Top trading strategies (&lt;code&gt;get_top_trading_strategies&lt;/code&gt;)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_top_strategies/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Today's output ranks long-vol and short-vol candidates across the whole equity universe. Top 5 of each:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Short vol (likely overpriced IV)&lt;/th&gt;
&lt;th&gt;Long vol (likely cheap IV)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SWK — Stanley Black &amp;amp; Decker ($78.94)&lt;/td&gt;
&lt;td&gt;DUK — Duke Energy ($125.01)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UVV — Universal ($54.61)&lt;/td&gt;
&lt;td&gt;KD — Kyndryl ($12.04)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ABCL — AbCellera Biologics ($5.20)&lt;/td&gt;
&lt;td&gt;BEN — Franklin Resources ($31.02)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HAS — Hasbro ($87.99)&lt;/td&gt;
&lt;td&gt;SNAP — Snapchat ($5.75)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BEN — Franklin Resources ($31.02)&lt;/td&gt;
&lt;td&gt;OUST — Ouster ($42.70)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that BEN appears on both sides — sometimes the long-vol model and the short-vol model disagree on the same name. That's a feature, not a bug; it signals the kind of name where the term structure is doing something interesting and a calendar/diagonal might be the actual edge.&lt;/p&gt;

&lt;p&gt;Each name also comes back with full bullish-case / bearish-case / probability-weighted outcomes (same shape as the NVDA pull above). One call, top-N ranked candidate list, ready for further filtering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Probe 4: News bias on a source (&lt;code&gt;get_source_bias&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;I picked WSJ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_source_bias/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Wall Street Journal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returned (excerpt of the 31 dimensions):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Articles analyzed:&lt;/strong&gt; 528&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emotionality:&lt;/strong&gt; 7 / 10&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensational:&lt;/strong&gt; 3, &lt;strong&gt;Fearful:&lt;/strong&gt; 4, &lt;strong&gt;Opinion:&lt;/strong&gt; 4, &lt;strong&gt;Political:&lt;/strong&gt; 3&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-establishment ↔ Pro-establishment:&lt;/strong&gt; &lt;strong&gt;+6&lt;/strong&gt; (pro)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dovish ↔ Hawkish:&lt;/strong&gt; &lt;strong&gt;+2&lt;/strong&gt; (hawkish)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Covering responses (defensive framing):&lt;/strong&gt; 6 / 10&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signature phrases:&lt;/strong&gt; "hoover institution fellow", "jerome powell", "spirit airlines"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice how the &lt;em&gt;signature phrases&lt;/em&gt; are doing real work. They're not generic — they're the multi-word expressions that appear at higher frequency than the cross-corpus baseline. That tells you the editorial fingerprint without you having to read 528 articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Probe 5: All source biases at once (&lt;code&gt;get_all_source_biases&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;This is the one I think is genuinely under-appreciated. One call, 216 sources, 113,253 articles' worth of aggregated 31-dim scoring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_all_source_biases/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Returns: {"sources": [216 entries with full bias profiles]}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sorting today's snapshot by a single dimension, here's the bottom-and-top tail of the &lt;strong&gt;Fear&lt;/strong&gt; score (0-30 scale):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Most fearful&lt;/th&gt;
&lt;th&gt;Score (out of 30)&lt;/th&gt;
&lt;th&gt;Articles&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;World Socialist&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;296&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unz&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;178&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;American Thinker&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;139&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global Research&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common Dreams&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;293&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What's interesting is that "most fearful" cuts across the political spectrum — World Socialist (far-left), Unz (far-right), American Thinker (right), Common Dreams (left), Global Research (conspiratorial-left). High fear in framing isn't a partisan signature; it's a &lt;em&gt;style&lt;/em&gt;. You couldn't see that without aggregated source-level scoring.&lt;/p&gt;

&lt;p&gt;By the &lt;strong&gt;Credibility&lt;/strong&gt; dimension instead:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Highest credibility&lt;/th&gt;
&lt;th&gt;Score (out of 50)&lt;/th&gt;
&lt;th&gt;Articles&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AP&lt;/td&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Texas Tribune&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;138&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Science Daily&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;232&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medicalxpress.com&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;133&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;earth.com&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;110&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The corpus is big enough that the rankings are stable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Probe 6: Balanced news synthesis (&lt;code&gt;search_balanced_news&lt;/code&gt;)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_balanced_search/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fed rate cuts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output (excerpt):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"summary": "Fed signals potential rate cuts, affecting markets and mortgage rates.",
"takeaway": "Anticipated rate cuts indicate optimism for easing borrowing costs, but risks of inflation resurgence remain important.",
"context": "Federal Reserve's monetary policy decisions are highly consequential, impacting various economic sectors...",
"evidence": ["Cooling inflation and stable economic indicators...[16]",
             "Anticipation of rate cuts has spurred refinancing activities...[8]"],
"potential_outcomes": [
   "Rate cuts stimulate growth and stabilize housing — economic expansion (70%)",
   "Premature rate cuts reignite inflation — economic instability (30%)"],
"relevant_tickers": "SPY,QQQ,NLY",
"num_sources": 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a multi-source synthesis with &lt;strong&gt;probability-weighted falsifiable outcomes&lt;/strong&gt;, citation indices, relevant tickers tagged out, and the synthesis assembled from 4 sources. One HTTP call. The "70% rate cuts stimulate growth" claim is again Brier-scoreable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Probe 7: One source's tagged bias on a real URL (&lt;code&gt;get_bias_from_url&lt;/code&gt;)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_url_bias/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.bbc.com/news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns: source identification, total social shares (&lt;code&gt;338,183&lt;/code&gt; for the BBC homepage), and per-URL bias metadata when the article has been scored. This one is the cheapest call to do at scale on a backlog of URLs you have lying around — paste a URL in, get a structured score back.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>mcp</category>
      <category>showdev</category>
    </item>
    <item>
      <title>MCP is quietly commoditizing data+model SaaS moats — the structural case</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Tue, 26 May 2026 23:41:03 +0000</pubDate>
      <link>https://dev.to/connerlambden/mcp-is-quietly-commoditizing-datamodel-saas-moats-the-structural-case-3j7p</link>
      <guid>https://dev.to/connerlambden/mcp-is-quietly-commoditizing-datamodel-saas-moats-the-structural-case-3j7p</guid>
      <description>&lt;p&gt;I shipped an MCP server six months ago and spent the last couple of weeks emailing data-engineering and AI-VC newsletter writers about it. The reactions sorted into two piles. Pile A: "cool, another MCP toy." Pile B: "wait, is this actually a structural threat to data+model SaaS moats?"&lt;/p&gt;

&lt;p&gt;Pile B is right. This post is the short version of the argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thesis in one sentence
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;MCP turns the kind of API that used to require a sales cycle, an OAuth dance, an SDK, and a dashboard — into a five-line tool call from inside an LLM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not just a developer-ergonomics improvement. It's a change in the cost structure of distribution for a specific class of B2B product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The class of product I mean
&lt;/h2&gt;

&lt;p&gt;I'm narrowly talking about &lt;strong&gt;"data-plus-model" SaaS&lt;/strong&gt;: companies whose moat is (1) a proprietary dataset (or a process for building one) and (2) a model trained on it, exposed through a paid API and a dashboard. Examples in the wild: most fintech data vendors, sentiment-API vendors, document-extraction APIs, "alternative data" SaaS, news-bias dashboards, options-analytics platforms.&lt;/p&gt;

&lt;p&gt;These products historically distributed through:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An enterprise sales motion (talk to a rep, sign an MSA, get an API key)&lt;/li&gt;
&lt;li&gt;A self-serve dev portal (sign up, copy API key, install our SDK, read docs, build integration)&lt;/li&gt;
&lt;li&gt;A dashboard layer (the actual product surface for non-developers)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All three of those distribution layers are &lt;em&gt;cost&lt;/em&gt;, not &lt;em&gt;value&lt;/em&gt;. They exist because there was no cheaper way to get the model output into the hands of a downstream user.&lt;/p&gt;

&lt;h2&gt;
  
  
  What MCP changes
&lt;/h2&gt;

&lt;p&gt;MCP is a tiny, dull spec: standardize how an LLM client discovers and calls external tools. Trivial in the technical sense. But here's what it does economically:&lt;/p&gt;

&lt;p&gt;It collapses the distribution cost of "data-plus-model output → downstream user" to &lt;strong&gt;approximately zero&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A user asks Claude/Cursor/Windsurf "what's the AI-derived fair value of AAPL $200 calls expiring 6/19?" The LLM, with my MCP server installed, makes one tool call. The data + model output lands in the conversation. &lt;strong&gt;No sales rep, no API key, no SDK, no dashboard&lt;/strong&gt;. The "product surface" is whatever LLM the user is already using.&lt;/p&gt;

&lt;p&gt;That collapse has cascading effects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The dashboard layer becomes optional.&lt;/strong&gt; For users with an LLM open, the LLM is the dashboard. The vendor's expensive UI investment is no longer the primary surface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The dev portal becomes optional.&lt;/strong&gt; "Install the MCP server" is the new "sign up for an API key." It's one paste of a URL into an LLM config.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The sales motion becomes optional.&lt;/strong&gt; A free-tier MCP server with no signup is a perfectly viable surface, because there's no friction to try it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The moat is now whatever moat the underlying data+model has&lt;/strong&gt; — minus the distribution layer that used to be 60-80% of the company's expense.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A concrete example
&lt;/h2&gt;

&lt;p&gt;I run &lt;a href="https://heliumtrades.com/mcp-page/" rel="noopener noreferrer"&gt;Helium&lt;/a&gt;, which exposes per-symbol ML options pricing (fair value, prob_ITM, Greeks) and 31-dim news-bias scoring across 3.2M articles. As an MCP server. And, recently, also as a plain REST API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_option_price/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;symbol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAPL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strike&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expiration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-06-19&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;option_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&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="c1"&gt;# {"predicted_fair_value": 20.64, "prob_itm": 0.52, "greeks": {...}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same backend serves both interfaces. The MCP server is a thin metadata wrapper over the REST endpoints. When an LLM client calls a Helium MCP tool, what actually happens at the network level is identical to what happens when a Python script calls the REST endpoint.&lt;/p&gt;

&lt;p&gt;That's the key technical observation. &lt;strong&gt;MCP and REST are two views into the same data+model.&lt;/strong&gt; MCP is the "embedded in an LLM client" view. REST is the "embedded in a Python script" view. They share the model, the data, the infrastructure, the cost basis. There is no MCP-specific work happening server-side.&lt;/p&gt;

&lt;p&gt;This means a company shipping an MCP server gets the entire AI-assistant-using developer audience as a distribution channel — for free, at zero marginal cost over the REST API they were already serving.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this implies for fintech-data and sentiment-API valuations
&lt;/h2&gt;

&lt;p&gt;If you're an investor or operator in this space, the structural implications are non-trivial:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The "moat" portion of the valuation is now under-supported.&lt;/strong&gt; Companies whose multiple is driven by "API integrations across N enterprise clients" are pricing in a distribution lock-in that MCP partially erodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "data plus model" portion of the valuation is what's actually defensible.&lt;/strong&gt; If your dataset is genuinely hard to build and your model is genuinely better, MCP is &lt;em&gt;neutral-to-positive&lt;/em&gt; for you (it cheapens distribution, but doesn't help competitors who lack the underlying assets).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The marketing motion has to change.&lt;/strong&gt; "Pay $500/mo for our dev portal access" is a hard sell against "free MCP server, no signup, IP-rate-limited 50/day, install in 30 seconds." Even if the paid offering is more featured, the price-anchor moves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A new class of free-tier-only data+model business becomes viable.&lt;/strong&gt; Where the unit economics of paid-tier-dashboard SaaS were marginal, a free-tier-only MCP server backed by ads, sponsorship, or community good-will can work. (Helium is this.)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The counterargument
&lt;/h2&gt;

&lt;p&gt;The standard pushback is that MCP is just a thin shim over what already worked (REST APIs + an SDK), and that nothing has fundamentally changed. I think this misses the &lt;em&gt;audience reach&lt;/em&gt; delta. The audience of "developers willing to install your SDK" is a subset of "developers willing to install your MCP server" which is a subset of "users of Claude/Cursor/Windsurf who can paste a config." Each step up the audience hierarchy is roughly 10x. MCP doesn't replace REST — it makes the same backend reachable by ~100x more users at zero marginal cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to watch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Whether the major LLM clients (Claude Desktop, Cursor, ChatGPT) settle on common MCP registry / discovery patterns. The faster this happens, the more aggressive the "data+model SaaS as MCP" trend becomes.&lt;/li&gt;
&lt;li&gt;Whether established data vendors ship MCP surfaces over their existing REST APIs. (Bloomberg won't; mid-tier vendors will start.)&lt;/li&gt;
&lt;li&gt;Whether free-tier MCP-only data plays start eating mid-tier paid-API revenue. The Helium-style "free, no signup, 50 queries/IP" model is the leading indicator.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;MCP is the cheapest distribution layer ever invented for data+model SaaS. The shape of competition in that segment changes accordingly. If you're a vendor whose moat was distribution, you should be worried. If your moat is the actual data+model, you should be busy shipping an MCP server.&lt;/p&gt;

&lt;p&gt;Helium MCP is open source: &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;https://github.com/connerlambden/helium-mcp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>mcp</category>
      <category>saas</category>
    </item>
    <item>
      <title>MCP servers are just REST APIs in a polite wrapper - here's 5 lines of Python</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Tue, 26 May 2026 22:38:09 +0000</pubDate>
      <link>https://dev.to/connerlambden/mcp-servers-are-just-rest-apis-in-a-polite-wrapper-heres-5-lines-of-python-58pn</link>
      <guid>https://dev.to/connerlambden/mcp-servers-are-just-rest-apis-in-a-polite-wrapper-heres-5-lines-of-python-58pn</guid>
      <description>&lt;p&gt;If you've been watching the MCP (Model Context Protocol) ecosystem from the sidelines, here's a quietly important detail: a lot of MCP servers are also just plain REST APIs underneath. The MCP layer is a polite wrapper that says "Claude, here are tools you can call." But the underlying HTTP endpoints are right there, ready to be called from &lt;code&gt;requests.get(...)&lt;/code&gt; like any other JSON API.&lt;/p&gt;

&lt;p&gt;That matters because &lt;strong&gt;the most interesting MCP servers are useful even if you've never opened Claude Desktop or Cursor.&lt;/strong&gt; You can drop them into a Streamlit app, a Jupyter notebook, a Lambda function, a Discord bot, an Airflow DAG, or a cron job. The MCP integration is gravy on top.&lt;/p&gt;

&lt;p&gt;I'll show this with a concrete example: pulling per-symbol ML option fair values and 31-dimension news-bias scores into pandas in 5 lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;I run &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;Helium MCP&lt;/a&gt;, which started as an MCP server and recently grew a plain REST surface. Both speak the same data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Per-symbol ML options pricing&lt;/strong&gt; - predicted fair value, probability ITM, Greeks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;31-dimension news-bias scoring&lt;/strong&gt; across 3.2M articles and 5,000 sources&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time market data&lt;/strong&gt;, top trading strategies, semantic meme search, source bias profiles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The MCP endpoint is &lt;code&gt;https://heliumtrades.com/mcp&lt;/code&gt;. The REST endpoints live under &lt;code&gt;https://heliumtrades.com/&lt;/code&gt; with paths like &lt;code&gt;/mcp_search/&lt;/code&gt;, &lt;code&gt;/mcp_option_price/&lt;/code&gt;, &lt;code&gt;/mcp_ticker/&lt;/code&gt;, &lt;code&gt;/mcp_url_bias/&lt;/code&gt;. 50 free queries per IP. No signup, no API key needed for the free tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five lines of Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_search/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apple earnings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get back a JSON list of articles with full bias scoring across all 31 dimensions per article: &lt;code&gt;credibility&lt;/code&gt;, &lt;code&gt;sensationalism&lt;/code&gt;, &lt;code&gt;overconfidence&lt;/code&gt;, &lt;code&gt;opinion_vs_fact&lt;/code&gt;, &lt;code&gt;scapegoating&lt;/code&gt;, &lt;code&gt;ai_authorship_probability&lt;/code&gt;, &lt;code&gt;covering_responses&lt;/code&gt;, &lt;code&gt;oversimplification&lt;/code&gt;, and 23 more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading into pandas
&lt;/h2&gt;

&lt;p&gt;This is where it gets fun. The JSON is already flat enough that pandas just works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_search/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;federal reserve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&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="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json_normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credibility&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sensationalism&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;opinion_vs_fact&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can do everything pandas does: groupby source, compute mean credibility, plot a credibility-vs-sensationalism scatter, filter to high-AI-authorship-probability articles, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option fair values, also 5 lines
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_option_price/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;symbol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAPL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strike&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expiration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-06-19&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;option_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&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="c1"&gt;# {'predicted_price': 20.64, 'prob_itm': 0.52, 'delta': 0.55, 'gamma': 0.02, 'vega': 0.41, ...}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get back a model-derived fair value and prob_ITM next to market price. The diff between the two is a (testable, scorable) prediction.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small Streamlit app
&lt;/h2&gt;

&lt;p&gt;Once the API returns JSON, building a Streamlit app is essentially a wrapper exercise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;streamlit&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tariffs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Results&lt;/span&gt;&lt;span class="sh"&gt;"&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="mi"&gt;50&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Go&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://heliumtrades.com/mcp_search/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json_normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&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="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataframe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credibility&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sensationalism&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai_authorship_probability&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar_chart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credibility&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the smallest realistic media-bias dashboard I've ever written. It's about 12 lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits in your stack
&lt;/h2&gt;

&lt;p&gt;The point isn't that this one API is special. The point is that &lt;strong&gt;MCP servers with REST surfaces are a quietly powerful new class of API.&lt;/strong&gt; They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LLM-native by design&lt;/strong&gt; - built so an LLM can call them without a custom integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema-rich&lt;/strong&gt; - the MCP tool spec doubles as auto-generated API documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free-tiered aggressively&lt;/strong&gt; - because the operator wants discoverability in LLM clients&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable from anything HTTP&lt;/strong&gt; - Python, JS, curl, Go, n8n, Zapier, Make&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're a data scientist who's never installed Claude Desktop and never wants to: that's fine. Treat MCP servers as a directory of unusually well-curated free REST APIs and start with the ones that solve a problem you already have.&lt;/p&gt;

&lt;p&gt;For finance and news intelligence specifically, the full Helium MCP REST endpoint list is:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Params&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_search/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;News search across 3.2M articles&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;q&lt;/code&gt;, &lt;code&gt;limit&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_balanced_search/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Multi-perspective news synthesis&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;q&lt;/code&gt;, &lt;code&gt;limit&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_source_bias/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;31-dim bias profile for one source&lt;/td&gt;
&lt;td&gt;&lt;code&gt;source&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_url_bias/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;31-dim bias profile for one article URL&lt;/td&gt;
&lt;td&gt;&lt;code&gt;url&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_all_source_biases/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All scored sources&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_ticker/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Real-time market data for a symbol&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ticker&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_option_price/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ML option fair value + Greeks&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;symbol&lt;/code&gt;, &lt;code&gt;strike&lt;/code&gt;, &lt;code&gt;expiration&lt;/code&gt;, &lt;code&gt;option_type&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_historical_options/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full options chain with ML fair values&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;symbol&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_top_strategies/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AI-ranked options strategies&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;limit&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mcp_meme_search/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Semantic meme search&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;q&lt;/code&gt;, &lt;code&gt;limit&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The MCP server config (for Cursor / Claude Desktop / Windsurf) is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"helium"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://heliumtrades.com/mcp"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But honestly - if Python is your thing - just open a notebook and &lt;code&gt;requests.get&lt;/code&gt;. The whole point of a public REST surface is that you don't have to care about anything else.&lt;/p&gt;

&lt;p&gt;Source, schema, full tool spec: &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;github.com/connerlambden/helium-mcp&lt;/a&gt;. Page: &lt;a href="https://heliumtrades.com/mcp-page/" rel="noopener noreferrer"&gt;heliumtrades.com/mcp-page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you build something with it, I'd love to see it. Open an issue, or send a notebook - happy to feature good demos.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>mcp</category>
      <category>python</category>
    </item>
    <item>
      <title>Detecting AI-authored news at corpus scale from a single MCP call</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Tue, 21 Apr 2026 15:04:16 +0000</pubDate>
      <link>https://dev.to/connerlambden/detecting-ai-authored-news-at-corpus-scale-from-a-single-mcp-call-1n2o</link>
      <guid>https://dev.to/connerlambden/detecting-ai-authored-news-at-corpus-scale-from-a-single-mcp-call-1n2o</guid>
      <description>&lt;p&gt;There's a growing crisis inside news feeds: AI-generated content, slop, and opinion-masked-as-reporting are all appearing faster than human review systems can flag them. Most "AI detection" tools work per-document and return a single binary probability with no supporting evidence. That's not enough for someone who has to actually &lt;em&gt;decide&lt;/em&gt; what to read, publish, or cite.&lt;/p&gt;

&lt;p&gt;I put the opposite approach behind an MCP server - a continuous, corpus-scale, per-article &lt;code&gt;ai_authorship_probability&lt;/code&gt; score, plus 30 other framing dimensions, all queryable in plain English from Claude or Cursor.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core dimension
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;Helium MCP&lt;/a&gt; scores every article it ingests across 3.2M+ articles and 5,000+ sources on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ai_authorship_probability&lt;/code&gt; - explicit model estimate that the article was LLM-generated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;credibility&lt;/code&gt; - sourcing density, named-source ratio, evidence-citation patterns&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sensationalism&lt;/code&gt; - headline-vs-body amplification, superlative density&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;overconfidence&lt;/code&gt; - hedge-language vs declarative-certainty ratio&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;opinion_vs_fact&lt;/code&gt; - opinion language vs declarative-fact language ratio&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;oversimplification&lt;/code&gt; - single-cause reduction of complex causation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;begging_the_question&lt;/code&gt; - conclusion assumed in the framing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scapegoating&lt;/code&gt; - actor-blaming vs structural-explanation patterns&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;covering_responses&lt;/code&gt; - whether the criticized parties get space to respond&lt;/li&gt;
&lt;li&gt;...22 more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point is not that any one score is a verdict. The point is that you can now &lt;em&gt;triangulate&lt;/em&gt;. A high AI-authorship probability paired with low sourcing density and high sensationalism is a very different signal from high AI-authorship in a meticulously-sourced explainer - and a scoring pipeline that only returns one number cannot tell them apart.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In Cursor or Claude Desktop MCP config:&lt;/span&gt;
npx mcp-remote https://heliumtrades.com/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Free. No signup. No API key. Remote server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asking the question
&lt;/h2&gt;

&lt;p&gt;In Claude, I asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using Helium, show me the most AI-suspicious recent articles across the corpus, and cross-reference against their credibility and sensationalism scores.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude called &lt;code&gt;search_articles&lt;/code&gt;, filtered by the top decile of &lt;code&gt;ai_authorship_probability&lt;/code&gt;, joined against per-source metadata, and returned a ranked list with the four relevant scores side-by-side. The top of the list was dominated by low-credibility, high-sensationalism sources - which is what you'd expect. But the &lt;em&gt;more interesting&lt;/em&gt; result was a small cohort in the middle of the pack: high AI-authorship, high credibility, moderate sensationalism. Those are almost certainly human-edited AI drafts - the category that a single-axis detector would miss entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 31 dimensions, not one
&lt;/h2&gt;

&lt;p&gt;The one-number-detector fails in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;False negatives from human editing.&lt;/strong&gt; A human editor can smooth an LLM draft enough to drop a binary detector score below threshold, but framing artifacts (overconfidence pattern, opinion-vs-fact ratio, coverage-of-responses) survive. Multi-dim signal catches them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;False positives from LLM-like human writing.&lt;/strong&gt; Academic-style prose is often flagged as AI-generated by single-axis detectors. But the sourcing-density and citation-evidence axes in a 31-dim score are the difference between a grad student and an LLM - and they show up cleanly in the schema.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Example use cases
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Newsroom standards editors&lt;/strong&gt; - a daily cron job that flags high-AI-authorship articles in your freelance submissions bucket, weighted by credibility score, before an editor ever opens them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fact-checkers&lt;/strong&gt; - when triaging a viral claim, pull the source's recent-window scores on &lt;code&gt;ai_authorship_probability&lt;/code&gt;, &lt;code&gt;credibility&lt;/code&gt;, and &lt;code&gt;overconfidence&lt;/code&gt;. A source that has drifted toward AI authorship and away from sourced evidence is a different trust situation than one that has been stable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Journalism-school instructors&lt;/strong&gt; - assign students to pull 10 articles from a single publication across a decade, graph the &lt;code&gt;ai_authorship_probability&lt;/code&gt; and &lt;code&gt;credibility&lt;/code&gt; trend lines, and write a piece on what changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-safety researchers&lt;/strong&gt; - the full 31-dimension scored corpus is a ready-made dataset for studying how LLM-generated news content is spreading through mainstream feeds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live example
&lt;/h2&gt;

&lt;p&gt;Here's a real query I ran in Claude:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Helium: Show me how AI-authorship probability has moved for tech-news sources over the last year, correlated with credibility.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude used the MCP tools, ran the query across the Helium corpus, and returned a tidy summary showing that several mid-tier aggregator sources have seen a meaningful upward shift in &lt;code&gt;ai_authorship_probability&lt;/code&gt; over the last 12 months, while their &lt;code&gt;credibility&lt;/code&gt; score drifted down. That's a reportable trend. The reporter didn't have to build a scraper, didn't have to maintain a classifier, didn't have to write SQL - they asked a question in English.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do
&lt;/h2&gt;

&lt;p&gt;If you work anywhere near news - as a reader, a writer, an editor, a researcher, or someone building AI-news workflows - try it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx mcp-remote https://heliumtrades.com/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask Claude the question you've been asking Google and failing to get a structured answer from. The 31-dim schema is there, the corpus is populated, and the tool calls are free.&lt;/p&gt;

&lt;p&gt;Full tool list, full schema, full source: &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;github.com/connerlambden/helium-mcp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find the schema missing something important, open an issue or reach out. The axes were picked empirically across 3.2M articles, but the space of things-worth-measuring about a news article is larger than what's in the schema today - and I'd rather know.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>news</category>
      <category>showdev</category>
    </item>
    <item>
      <title>31 dimensions of news bias, queryable from Claude in plain English</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Sun, 19 Apr 2026 22:21:30 +0000</pubDate>
      <link>https://dev.to/connerlambden/31-dimensions-of-news-bias-queryable-from-claude-in-plain-english-1ioo</link>
      <guid>https://dev.to/connerlambden/31-dimensions-of-news-bias-queryable-from-claude-in-plain-english-1ioo</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Most "news bias" tools collapse a story into a single number on a left-right axis. That's useful for a thumbnail, but it's the wrong granularity for almost any real workflow - a newsroom standards editor, a fact-checker triaging a viral claim, a journalism-school instructor teaching framing, an AI safety researcher building a misinformation classifier.&lt;/p&gt;

&lt;p&gt;What those workflows actually need is &lt;strong&gt;structured, multi-dimensional, queryable framing data&lt;/strong&gt;. So I built it and put it behind an MCP server that any AI assistant can call.&lt;/p&gt;

&lt;h2&gt;
  
  
  The schema
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;Helium MCP&lt;/a&gt; scores every article on 31 dimensions. A non-exhaustive sample:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;liberal_conservative&lt;/code&gt; - the standard left-right axis (kept for compatibility)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;credibility&lt;/code&gt; - sourcing density, named-source ratio, evidence-citation pattern&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;opinion_vs_fact&lt;/code&gt; - opinion language vs declarative-fact language ratio&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scapegoating&lt;/code&gt; - actor-blaming patterns vs structural-explanation patterns&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;covering_responses&lt;/code&gt; - whether the article gives space to the people/orgs being criticized&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fearful&lt;/code&gt; - emotional valence, threat language&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sensationalism&lt;/code&gt; - headline-vs-body amplification, superlative density&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;overconfidence&lt;/code&gt; - hedge language vs declarative certainty&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;intelligence&lt;/code&gt; - reading level, conceptual density&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;begging_the_question&lt;/code&gt; - assumes the conclusion in the framing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;oversimplification&lt;/code&gt; - reduces complex causation to single factors&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ai_authorship_probability&lt;/code&gt; - explicit estimate that the article was LLM-generated&lt;/li&gt;
&lt;li&gt;... 19 more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key thing is that every dimension is &lt;strong&gt;operationalized&lt;/strong&gt; - it's not just "vibes" labeling, each one is computed from features in the text.&lt;/p&gt;

&lt;h2&gt;
  
  
  The corpus
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;3.2M+ articles&lt;/li&gt;
&lt;li&gt;5,000+ sources&lt;/li&gt;
&lt;li&gt;Updated continuously&lt;/li&gt;
&lt;li&gt;Sources span global mainstream, US partisan, business press, tech press, regional, and long-tail / hyperlocal&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The MCP interface
&lt;/h2&gt;

&lt;p&gt;Helium MCP exposes this via three main tools you can call from any AI assistant:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;get_source_bias(source)&lt;/code&gt; - aggregate scores across a source's recent corpus&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_bias_from_url(url)&lt;/code&gt; - score a single article on demand&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search_balanced_news(query)&lt;/code&gt; - synthesize multi-source coverage of an event with structured outcomes&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setup (one line)
&lt;/h2&gt;

&lt;p&gt;Add to your &lt;code&gt;mcp.json&lt;/code&gt; in Cursor or Claude Desktop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"helium"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://heliumtrades.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Free, no signup, no API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example
&lt;/h2&gt;

&lt;p&gt;In Claude, I asked: &lt;em&gt;"Show me the bias profile for CNN's recent corpus using Helium."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Real output (445 articles analyzed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Liberal/Conservative:  -2   (slightly left)
Credibility:           15   (moderate-high)
Fearful:                4
Intelligence:          11
Covering Responses:     9   (gives space to the criticized)
Opinion:                5
Overconfidence:         8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value of seeing it as 31 numbers (and not 1) is that you can ask follow-up questions like &lt;em&gt;"For these same articles, are the high-credibility ones more or less likely to be high-overconfidence?"&lt;/em&gt; - and the agent can compute the correlation in-place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use cases this unlocks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For a newsroom standards editor:&lt;/strong&gt; triage incoming wire/syndication content by &lt;code&gt;ai_authorship_probability&lt;/code&gt; before it goes through your editorial pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For a fact-checker:&lt;/strong&gt; rank a list of suspect URLs by &lt;code&gt;credibility&lt;/code&gt; (low) and &lt;code&gt;overconfidence&lt;/code&gt; (high) - the combination is a strong indicator of claims worth investigating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For a journalism instructor:&lt;/strong&gt; show students how the same event was framed across 10 sources, with structured &lt;code&gt;scapegoating&lt;/code&gt; / &lt;code&gt;covering_responses&lt;/code&gt; / &lt;code&gt;opinion_vs_fact&lt;/code&gt; scores attached.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For an AI safety researcher:&lt;/strong&gt; the schema is essentially a deployed multi-criterion eval pipeline applied to news rather than to LLM outputs - useful as an empirical reference for how multi-criterion eval criteria interact with each other in production (Goodhart, distribution shift, taxonomy choice).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For anyone building an AI agent that consumes news:&lt;/strong&gt; structured per-source/per-article framing metadata is the missing primary key for reasoning about source reliability programmatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bigger point
&lt;/h2&gt;

&lt;p&gt;In a world where readers query LLMs more than they visit homepages, the value of an individual article goes down and the value of &lt;strong&gt;structured, queryable, per-article metadata&lt;/strong&gt; goes up. The schema above is one open attempt at what that metadata layer should look like.&lt;/p&gt;

&lt;p&gt;If you have ideas for dimensions that should be added (or critiques of the existing ones), I'd love to hear them - the methodology is open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;This is not a substitute for human editorial judgment. Bias scoring is hard, the schema can be wrong, and there are distribution-shift / Goodhart concerns with any operationalized criterion. Use it as a triage layer, not a verdict.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;https://github.com/connerlambden/helium-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs + live demo: &lt;a href="https://heliumtrades.com/mcp-page/" rel="noopener noreferrer"&gt;https://heliumtrades.com/mcp-page/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Companion piece on the options-pricing side: &lt;a href="https://dev.to/connerlambden/how-i-screen-for-ratio-spread-opportunities-in-30-seconds-with-an-mcp-server-130p"&gt;https://dev.to/connerlambden/how-i-screen-for-ratio-spread-opportunities-in-30-seconds-with-an-mcp-server-130p&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>mcp</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How I screen for ratio spread opportunities in 30 seconds with an MCP server</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Sun, 19 Apr 2026 22:05:52 +0000</pubDate>
      <link>https://dev.to/connerlambden/how-i-screen-for-ratio-spread-opportunities-in-30-seconds-with-an-mcp-server-130p</link>
      <guid>https://dev.to/connerlambden/how-i-screen-for-ratio-spread-opportunities-in-30-seconds-with-an-mcp-server-130p</guid>
      <description>&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;A "ratio spread" in options trading is when you sell N options at one strike and buy M options at another, where N != M. The classic 1x2 put ratio spread (sell 1 ATM put, buy 2 OTM puts) is a favorite of vol traders because it lets you express a view that downside skew is overpriced &lt;em&gt;and&lt;/em&gt; gives you positive convexity if the market really crashes.&lt;/p&gt;

&lt;p&gt;The hard part is finding candidates. Skew mispricings are the kind of thing you used to need a Bloomberg terminal + a custom IV-surface model + an analyst to surface. With a free remote MCP server I built called &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;Helium MCP&lt;/a&gt;, you can do it in 30 seconds inside Claude Desktop or Cursor.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the MCP exposes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;Helium MCP&lt;/a&gt; is a thin wrapper over a per-symbol ML options pricing model. For any contract, it returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;predicted_price&lt;/code&gt; - Helium's model fair value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;prob_itm&lt;/code&gt; - probability of expiring in the money&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;options_data_date&lt;/code&gt; - freshness of the chain snapshot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model is trained per-symbol on each ticker's own historical options data, so it makes different (and sometimes wildly different) calls than a generic Black-Scholes fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup (one line)
&lt;/h2&gt;

&lt;p&gt;Add to your &lt;code&gt;mcp.json&lt;/code&gt; in Cursor or Claude Desktop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"helium"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://heliumtrades.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Free, no signup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding a ratio-spread candidate
&lt;/h2&gt;

&lt;p&gt;Inside Cursor, I asked the agent: &lt;em&gt;"Pull AAPL option prices from Helium for May 15 expiry across $180/$195/$200/$205 strikes."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Real output, just now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get_option_price('AAPL', 200, '2026-05-15', 'call')   -&amp;gt;  $20.64,  prob_itm 0.52
get_option_price('AAPL', 205, '2026-05-15', 'call')   -&amp;gt;  $20.69,  prob_itm 0.52
get_option_price('AAPL', 195, '2026-05-15', 'put')    -&amp;gt;  $0.06,   prob_itm 0.01
get_option_price('AAPL', 180, '2026-05-15', 'put')    -&amp;gt;  $0.02,   prob_itm 0.01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the puts. The model thinks AAPL has effectively 1% probability of finishing below $195 by mid-May. The market is paying actual money for those puts (and a lot more for the deeper OTM ones - that's the skew).&lt;/p&gt;

&lt;p&gt;If you believe the model, &lt;strong&gt;the deep OTM put side is the overpriced side&lt;/strong&gt;. That's a textbook setup for a 1x2 put ratio spread:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sell 1 near-ATM put (collect the rich premium the market is offering for a bearish view)&lt;/li&gt;
&lt;li&gt;Buy 2 deep OTM puts (cheap insurance + tail-side convexity)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the market chops sideways or rallies (the model's base case), all the puts expire worthless and you keep the credit. If the market crashes hard, the 2 long puts catch up to and exceed the 1 short put.&lt;/p&gt;

&lt;h2&gt;
  
  
  The point isn't this specific trade
&lt;/h2&gt;

&lt;p&gt;The point is that &lt;strong&gt;screening this kind of structural mispricing went from "needs an institutional setup" to "ask Claude in plain English"&lt;/strong&gt; the day MCP made it possible to expose model APIs to LLMs.&lt;/p&gt;

&lt;p&gt;The same workflow applies to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calendar spread arbitrage (compare term-structure of Helium IV vs market IV)&lt;/li&gt;
&lt;li&gt;Diagonal spreads (mix the two)&lt;/li&gt;
&lt;li&gt;Volatility compression candidates - Helium MCP has a &lt;code&gt;get_top_trading_strategies&lt;/code&gt; endpoint that returns a daily-ranked long-vol vs short-vol screen with explicit bull/bear cases:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Market IV (~30%) above Helium IV (~26-27%) across maturities - favoring volatility compression. Skew is mostly tail-priced..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The bigger picture
&lt;/h2&gt;

&lt;p&gt;ML option pricing was an institutional moat for two decades. With MCP, the marginal cost of querying an ML option pricing model from inside an LLM is zero. That changes who can run a structured options screen.&lt;/p&gt;

&lt;p&gt;Helium MCP also exposes 31-dimension structured bias scoring across 3.2M+ news articles (5,000+ sources) - useful for the news/narrative side of trading - but that's a topic for another post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;This is not trading advice. Helium's model can be wrong. Per-symbol regression models can overfit. Always size positions appropriately and validate against your own framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;https://github.com/connerlambden/helium-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs + live demo: &lt;a href="https://heliumtrades.com/mcp-page/" rel="noopener noreferrer"&gt;https://heliumtrades.com/mcp-page/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you build something interesting on top of it, I'd love to hear about it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>mcp</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How to Give Your AI Assistant Real-Time Market Intelligence</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Tue, 14 Apr 2026 21:15:15 +0000</pubDate>
      <link>https://dev.to/connerlambden/how-to-give-your-ai-assistant-real-time-market-intelligence-1057</link>
      <guid>https://dev.to/connerlambden/how-to-give-your-ai-assistant-real-time-market-intelligence-1057</guid>
      <description>&lt;p&gt;MCP (Model Context Protocol) lets AI assistants call external tools. I built a remote MCP server called &lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;Helium&lt;/a&gt; that gives any MCP-compatible AI assistant access to real-time financial intelligence — market data, ML-powered options pricing, news bias analysis, and more.&lt;/p&gt;

&lt;p&gt;The interesting part isn't the financial data itself (there are plenty of market APIs). It's what happens when you combine structured financial data with an LLM's reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup (30 seconds)
&lt;/h2&gt;

&lt;p&gt;Add one line to your AI assistant's MCP config:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cursor / Windsurf:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"helium"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"https://heliumtrades.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Claude Desktop:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"helium"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"https://heliumtrades.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;]}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No API key. Nothing to install. Free tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Helium exposes 10 tools through MCP:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Market Intelligence (&lt;code&gt;get_ticker&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Ask "What's the outlook for NVDA?" and get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-generated bull and bear cases&lt;/li&gt;
&lt;li&gt;5 probability-weighted scenarios (e.g., 38% chance of mean-reversion, 25% upside on AI headlines, 10% tail risk on export shock)&lt;/li&gt;
&lt;li&gt;Each scenario includes falsifiability criteria — what would prove it wrong&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. ML Options Pricing (&lt;code&gt;get_top_trading_strategies&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The model computes independent fair values for every listed options contract. For each ticker, it returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strategies ranked by expected value&lt;/li&gt;
&lt;li&gt;Backtested win rates (e.g., short vol calls on AAPL: 61% win rate, avg +$8.40/trade over 39 historical trades)&lt;/li&gt;
&lt;li&gt;Full Greeks for every contract&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single call returns ~355KB of structured data.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Balanced News Synthesis (&lt;code&gt;search_balanced_news&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Aggregates 3.2M+ articles from 5,000+ sources. Instead of one take, it shows where sources agree vs. diverge on any topic.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Multi-Dimensional Bias Scoring (&lt;code&gt;get_all_source_biases&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Scores news sources across 15+ dimensions — not just left/right:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prescriptiveness&lt;/strong&gt;: Does the outlet tell you what to think, or just report?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensationalism&lt;/strong&gt;: Framing intensity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fearful framing&lt;/strong&gt;: How much fear-based language is used&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrity&lt;/strong&gt;: Factual rigor&lt;/li&gt;
&lt;li&gt;Plus: dovish/hawkish, libertarian/authoritarian, and more&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Historical Options Data (&lt;code&gt;get_historical_options_data&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Full historical chains with ML pricing baked in. A single SPY request returns ~30MB of every contract with the model's theoretical value.&lt;/p&gt;

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

&lt;p&gt;The key insight is that MCP eliminates the build step. Instead of building a custom financial app, you add one config line and ask questions in natural language. The AI handles parsing 355KB of structured options data and pulling out what's relevant.&lt;/p&gt;

&lt;p&gt;This pattern — domain-specific intelligence delivered through MCP — is how I think a lot of specialized AI tools will work going forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://heliumtrades.com/mcp-page/" rel="noopener noreferrer"&gt;Full docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://glama.ai/mcp/servers/connerlambden/helium-mcp" rel="noopener noreferrer"&gt;Glama listing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/helium-mcp" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy to answer questions about the implementation or the MCP protocol in general.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Search Scientific Papers from Any AI Tool — Introducing BGPT MCP</title>
      <dc:creator>connerlambden</dc:creator>
      <pubDate>Tue, 17 Feb 2026 04:50:13 +0000</pubDate>
      <link>https://dev.to/connerlambden/search-scientific-papers-from-any-ai-tool-introducing-bgpt-mcp-18f3</link>
      <guid>https://dev.to/connerlambden/search-scientific-papers-from-any-ai-tool-introducing-bgpt-mcp-18f3</guid>
      <description>&lt;p&gt;If you work with scientific literature — whether you're a researcher, bioinformatician, or building AI-powered tools — you know the pain of searching for papers programmatically. PubMed's API is clunky. Semantic Scholar doesn't give you experimental details. And scraping is fragile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BGPT MCP&lt;/strong&gt; solves this by giving any AI tool direct access to a curated database of scientific papers, complete with raw experimental data extracted from full-text studies.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is MCP?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;Model Context Protocol (MCP)&lt;/a&gt; is an open standard that lets AI assistants connect to external tools and data sources. Think of it as "USB-C for AI" — one protocol, many tools.&lt;/p&gt;

&lt;p&gt;If you use &lt;strong&gt;Cursor&lt;/strong&gt;, &lt;strong&gt;Claude Desktop&lt;/strong&gt;, &lt;strong&gt;Cline&lt;/strong&gt;, &lt;strong&gt;Windsurf&lt;/strong&gt;, or any MCP-compatible client, you can connect to BGPT with a single line of config.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does BGPT MCP Do?
&lt;/h2&gt;

&lt;p&gt;BGPT provides a &lt;code&gt;search_papers&lt;/code&gt; tool that searches a curated database of scientific papers. Unlike typical search APIs, BGPT extracts &lt;strong&gt;raw experimental data&lt;/strong&gt; from full-text papers. Each result includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Title, DOI, and authors&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Methods&lt;/strong&gt; — actual experimental procedures used&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Results&lt;/strong&gt; — quantitative findings extracted from the paper&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality scores&lt;/strong&gt; — automated assessment of study rigor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;25+ metadata fields&lt;/strong&gt; — journal, year, sample size, organism, and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the kind of structured data that used to require hours of manual extraction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start (2 minutes)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Cursor IDE
&lt;/h3&gt;

&lt;p&gt;Add this to your MCP settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bgpt"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://bgpt.pro/mcp/sse"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No API keys needed for your first 50 searches.&lt;/p&gt;

&lt;h3&gt;
  
  
  For Claude Desktop
&lt;/h3&gt;

&lt;p&gt;Add to your &lt;code&gt;claude_desktop_config.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;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bgpt"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://bgpt.pro/mcp/sse"&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;h3&gt;
  
  
  For Any MCP Client
&lt;/h3&gt;

&lt;p&gt;BGPT uses Server-Sent Events (SSE) transport. Point your client to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://bgpt.pro/mcp/sse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example Queries
&lt;/h2&gt;

&lt;p&gt;Once connected, just ask your AI assistant naturally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"Search for papers on CRISPR gene editing efficiency in human cells"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Find studies comparing immunotherapy response rates in melanoma"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"What papers exist on transformer models for protein structure prediction?"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AI will call the &lt;code&gt;search_papers&lt;/code&gt; tool and return structured results you can immediately work with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;If you're building research tools, literature review pipelines, or AI agents that need scientific context, BGPT MCP gives you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No infrastructure&lt;/strong&gt; — it's a remote server, nothing to install&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured data&lt;/strong&gt; — not just abstracts, but methods and results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality scores&lt;/strong&gt; — filter for rigorous studies automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works everywhere&lt;/strong&gt; — any MCP-compatible AI tool&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;50 free searches&lt;/strong&gt; per network (no account needed)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$0.01 per result&lt;/strong&gt; after that with an API key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get your API key at &lt;a href="https://bgpt.pro/mcp" rel="noopener noreferrer"&gt;bgpt.pro/mcp&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live page:&lt;/strong&gt; &lt;a href="https://bgpt.pro/mcp" rel="noopener noreferrer"&gt;bgpt.pro/mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/connerlambden/bgpt-mcp" rel="noopener noreferrer"&gt;github.com/connerlambden/bgpt-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Protocol:&lt;/strong&gt; &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;modelcontextprotocol.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;I'd love to hear how you use it. If you're working on research tooling or have feedback, drop a comment below or reach out at &lt;a href="mailto:contact@bgpt.pro"&gt;contact@bgpt.pro&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>science</category>
      <category>research</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
