<?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: blinkbox</title>
    <description>The latest articles on DEV Community by blinkbox (@blinkboxhq).</description>
    <link>https://dev.to/blinkboxhq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4127504%2Fe9850ebc-71d0-40c3-8316-024aaec7aac8.png</url>
      <title>DEV Community: blinkbox</title>
      <link>https://dev.to/blinkboxhq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blinkboxhq"/>
    <language>en</language>
    <item>
      <title>Every one of these automation bugs showed "Success". Here's the checklist I use now.</title>
      <dc:creator>blinkbox</dc:creator>
      <pubDate>Sat, 19 Sep 2026 08:46:03 +0000</pubDate>
      <link>https://dev.to/blinkboxhq/every-one-of-these-automation-bugs-showed-success-heres-the-checklist-i-use-now-6mh</link>
      <guid>https://dev.to/blinkboxhq/every-one-of-these-automation-bugs-showed-success-heres-the-checklist-i-use-now-6mh</guid>
      <description>&lt;p&gt;I build &lt;a href="https://blinkbox.net" rel="noopener noreferrer"&gt;Blinkbox&lt;/a&gt;, an open-source automation platform (the Zapier / n8n shape). Last week I let Claude Code build a lead-gen pipeline on it over MCP: cron → 3× HTTP → merge → qualify → Google Sheets read → filter → append. Sixteen nodes. Every execution came back green.&lt;/p&gt;

&lt;p&gt;It wrote nothing.&lt;/p&gt;

&lt;p&gt;Not once. The pipeline "succeeded" on every run and the sheet stayed empty, and nothing in the logs said otherwise. Finding out why took a day of dumping node input into a scratch spreadsheet, and I ended up with a list of failure classes that I now check for in every workflow, on any platform. Every single one of them reports success.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. A missing global that makes a node return nothing
&lt;/h2&gt;

&lt;p&gt;The code node used &lt;code&gt;new URL(site).hostname&lt;/code&gt; to extract a domain. The sandbox doesn't have &lt;code&gt;URL&lt;/code&gt;. The node threw, the runtime treated the empty result as a valid output, and everything downstream happily processed zero items.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; the &lt;em&gt;count&lt;/em&gt; of items leaving each code node, not just its status. In a sandbox, assume nothing from the browser or Node is there until you've seen it work — &lt;code&gt;URL&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;Buffer&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The data moved and nobody told the code
&lt;/h2&gt;

&lt;p&gt;After a merge node, my platform puts each branch under &lt;code&gt;$input.merged.&amp;lt;key&amp;gt;&lt;/code&gt;. The generated code read &lt;code&gt;$input.rawA&lt;/code&gt; — the key that existed &lt;em&gt;before&lt;/em&gt; the merge — and got &lt;code&gt;undefined&lt;/code&gt;. &lt;code&gt;undefined&lt;/code&gt; filtered to zero leads, zero leads is a perfectly successful result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; after any node that reshapes data (merge, split, aggregate, loop), log the top-level keys before writing code against them. Docs lie; the runtime doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The destination silently coerced your values
&lt;/h2&gt;

&lt;p&gt;When rows finally landed, the date column came out as &lt;code&gt;46274&lt;/code&gt;. Google Sheets had turned my ISO date into a serial number because the append used "user entered" parsing. Success, wrong data, and it would have poisoned every dedupe that keyed on date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; read back the first row you write and compare it to what you sent. On Sheets, use raw input mode for anything you'll compare later.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A number compared to a string took the wrong branch
&lt;/h2&gt;

&lt;p&gt;The condition node compared &lt;code&gt;newLeads &amp;gt; 0&lt;/code&gt;. The left side was the number &lt;code&gt;9&lt;/code&gt;, the right side the string &lt;code&gt;"0"&lt;/code&gt;. It took the false branch — the "nothing new" path — with 9 new leads sitting in the payload. Green run, correct count, wrong door.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; don't branch on numeric comparisons across nodes. Compute a string flag in code (&lt;code&gt;hasNew: "yes"&lt;/code&gt;) and branch on equality. Boring, but it can't be coerced.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The field was called something else at runtime
&lt;/h2&gt;

&lt;p&gt;The docs for the HTTP node said the response body was &lt;code&gt;body&lt;/code&gt;. At runtime it's &lt;code&gt;data&lt;/code&gt;. &lt;code&gt;$input.body&lt;/code&gt; is &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt; has no length, the qualify step produced an empty list, the run succeeded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; never write against a documented field name until you've printed the real object once. This is the single most common reason an agent-built workflow runs green and does nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. The run reports its own status, not its output
&lt;/h2&gt;

&lt;p&gt;Underneath all five: the platform (mine included) returned "execution completed, 16 nodes" and not what each node produced. An agent — or a tired human — reads that as done. There was no way to notice the payload was empty without going and looking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; end every pipeline with an assertion. It is one line in the last code node: &lt;code&gt;if (rows.length === 0) throw new Error("wrote 0 rows")&lt;/code&gt;. A pipeline that fails loudly when it does nothing is the only kind you can safely leave alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The uncomfortable part
&lt;/h2&gt;

&lt;p&gt;Most of these were my platform's quirks, not the model's fault, and two of them contradicted my own docs. Once I put the real runtime behaviour into a skill file that ships with the MCP server, Claude Code's rebuild ran first try: run 1 wrote 3 fully-contactable leads, run 2 wrote 0 because the dedupe against the sheet works, and it's been on a cron since.&lt;/p&gt;

&lt;p&gt;The next thing I'm shipping is full per-node output in the execution-logs tool, so the agent can see what each node produced instead of trusting a green badge. If your platform of choice doesn't show you that, the assertion node in #6 is the workaround.&lt;/p&gt;

&lt;p&gt;If you want to poke at the real thing: &lt;a href="https://blinkbox.net" rel="noopener noreferrer"&gt;blinkbox.net&lt;/a&gt; (free tier, no card) or self-host from &lt;a href="https://github.com/blinkboxhq/Blinkbox" rel="noopener noreferrer"&gt;github.com/blinkboxhq/Blinkbox&lt;/a&gt;. Rough edges I know about: thin docs, small free tier, and — until that logs change lands — exactly the problem this post is about.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>debugging</category>
      <category>mcp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I exposed my whole automation platform as an MCP server. Here's what Claude Code did with it.</title>
      <dc:creator>blinkbox</dc:creator>
      <pubDate>Wed, 16 Sep 2026 07:32:07 +0000</pubDate>
      <link>https://dev.to/blinkboxhq/i-exposed-my-whole-automation-platform-as-an-mcp-server-heres-what-claude-code-did-with-it-2hl0</link>
      <guid>https://dev.to/blinkboxhq/i-exposed-my-whole-automation-platform-as-an-mcp-server-heres-what-claude-code-did-with-it-2hl0</guid>
      <description>&lt;p&gt;I maintain &lt;a href="https://blinkbox.net" rel="noopener noreferrer"&gt;Blinkbox&lt;/a&gt;, an open-source automation platform — the Zapier / Make / n8n shape: triggers → nodes → actions, ~250 integrations with OAuth (Google, Slack, Notion, Airtable, GitHub, Microsoft), a headless Chromium pool for scraping, sandboxed JS nodes. This post is about one decision: instead of bolting an "AI builder" onto the app, I exposed the entire platform as an MCP server and let Claude Code be the builder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not an in-app AI builder
&lt;/h2&gt;

&lt;p&gt;Every automation tool is shipping a chat box that generates workflows. The problem with a model living inside the app: it only knows what the app tells it, and it can't see your codebase, your notes, or the conversation you were already having. Meanwhile Claude Code, Cursor and ChatGPT already &lt;em&gt;are&lt;/em&gt; the place people describe work. So the platform became a tool the agent calls, not a chat inside the platform.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Transport: Streamable HTTP at &lt;code&gt;https://mcp.blinkbox.net/mcp&lt;/code&gt;, Bearer key (or key-in-URL). Any client that can set a header works — Claude Code, Claude Desktop, Cursor, ChatGPT.&lt;/li&gt;
&lt;li&gt;Tools: list / create / update / run automations, activate / deactivate, list executions, read execution logs, node-catalog lookup (per-node config fields), credentials.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;SKILL.md&lt;/code&gt; that ships next to the server for &lt;code&gt;~/.claude/skills&lt;/code&gt;: the node catalog, expression syntax, execution rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last item mattered more than any tool description. Without it the model guesses field names and burns ~12 tool calls on a simple flow. With it, a working flow is ~4 calls and usually runs first try. Every time Claude guessed a field wrong during development, the correction went into the skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real build, including what broke
&lt;/h2&gt;

&lt;p&gt;I asked Claude Code for:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a daily 8am lead finder: query OpenStreetMap for dentists, vets and hairdressers in a city, keep only places with a website AND email AND phone, dedupe against my Google Sheet, append the new ones.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It built a 16-node flow: &lt;code&gt;cron → 3× HTTP (Nominatim) → merge → qualify (code) → sheet read → filter → condition → append / no-op&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first draft ran green and wrote nothing. Two bugs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It used &lt;code&gt;new URL()&lt;/code&gt; to extract domains. The code sandbox doesn't have &lt;code&gt;URL&lt;/code&gt;, so the node produced nothing and the flow finished "successfully" with zero rows.&lt;/li&gt;
&lt;li&gt;After a &lt;code&gt;merge&lt;/code&gt; node the data lives under &lt;code&gt;$input.merged.&amp;lt;key&amp;gt;&lt;/code&gt;, not &lt;code&gt;$input.&amp;lt;key&amp;gt;&lt;/code&gt;. It read the wrong key and got &lt;code&gt;undefined&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One follow-up message with those two rules and it regenerated the flow. Run 1 wrote 3 fully-contactable leads. Run 2 wrote 0 — the dedupe against the sheet works. It's been on a cron since.&lt;/p&gt;

&lt;p&gt;The only thing I did in the UI was click &lt;strong&gt;Connect&lt;/strong&gt; on Google Sheets once. OAuth stays with the human; everything else is tool calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell anyone building an MCP server for a real system
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ship the knowledge, not just the tools.&lt;/strong&gt; A skill file with your object model and syntax is worth more than clever tool descriptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Success" with an empty payload is how agents fool themselves.&lt;/strong&gt; My flow was all-green and wrote nothing. The next thing I'm adding is full per-node output in the logs tool so the agent can see &lt;em&gt;what&lt;/em&gt; each node produced, not just that it ran.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep OAuth in the UI.&lt;/strong&gt; The agent wires "Google Sheets"; the human clicks Connect. Nobody has convinced me agent-driven OAuth is a good idea yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return the run, not a summary of the run.&lt;/strong&gt; I found both bugs above by dumping node input into a scratch sheet, because the agent couldn't see per-node output itself. That's the gap the logs tool has to close.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hosted, free to start, no card: &lt;a href="https://blinkbox.net" rel="noopener noreferrer"&gt;blinkbox.net&lt;/a&gt; → dashboard → MCP tab → copy the URL and a key → add it to Claude Code / Desktop → drop the skill in &lt;code&gt;~/.claude/skills&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Self-host: &lt;a href="https://github.com/blinkboxhq/Blinkbox" rel="noopener noreferrer"&gt;github.com/blinkboxhq/Blinkbox&lt;/a&gt; (Node 22 + MongoDB + Redis).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Honest rough edges: docs are thin, the hosted free tier is small, and per-node output isn't in the logs tool yet. If you build something with it — or break it — I'd genuinely like to hear how.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>claude</category>
      <category>automation</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
