<?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: SnapTools</title>
    <description>The latest articles on DEV Community by SnapTools (@gulugulu).</description>
    <link>https://dev.to/gulugulu</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%2F3854413%2F57528983-cd1f-401a-87f2-ab992dac6bb7.jpg</url>
      <title>DEV Community: SnapTools</title>
      <link>https://dev.to/gulugulu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gulugulu"/>
    <language>en</language>
    <item>
      <title>WebMCP in practice: testing music, CSVs, and page edits</title>
      <dc:creator>SnapTools</dc:creator>
      <pubDate>Fri, 23 Oct 2026 08:48:26 +0000</pubDate>
      <link>https://dev.to/gulugulu/webmcp-in-practice-testing-music-csvs-and-page-edits-3424</link>
      <guid>https://dev.to/gulugulu/webmcp-in-practice-testing-music-csvs-and-page-edits-3424</guid>
      <description>&lt;p&gt;The model said it had written a melody and “read it back to verify.” The call log told a slightly different story: one read, then one write. There was no second read.&lt;/p&gt;

&lt;p&gt;The write operation returned the saved score, so the model did have the result in context. But its explanation described an extra step that never happened.&lt;/p&gt;

&lt;p&gt;That small discrepancy is a good example of why I built &lt;strong&gt;WebMCP DevTools&lt;/strong&gt;, a Chrome extension for inspecting page tools and their execution. I want to compare what an agent says with what an application actually did.&lt;/p&gt;

&lt;p&gt;To explore that, I made an &lt;a href="https://2019-02-18.github.io/webmcp-demo/english.html" rel="noopener noreferrer"&gt;English-language workshop&lt;/a&gt; with three small workspaces: a music editor, an expense dataset, and an invitation-page editor. This post walks through a fresh run using the real DeepSeek API and the tools registered by those pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the webpage contributes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/docs/ai/webmcp" rel="noopener noreferrer"&gt;WebMCP is a proposed web standard&lt;/a&gt; for exposing structured tools from webpages. A tool has a name, a description, an input schema, and an implementation supplied by the page.&lt;/p&gt;

&lt;p&gt;In this workshop, the useful state already exists in the browser: the current score, the current query, and the current invitation revision. A tool reads or modifies that state. The interface then renders the result, and a person can keep working on it.&lt;/p&gt;

&lt;p&gt;The site needs to implement these capabilities. An extension cannot manufacture a reliable business API for every page you visit. Browser support is still evolving, too.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. A melody you can keep editing
&lt;/h2&gt;

&lt;p&gt;Here is the request I used:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Write an original eight-bar birthday-style melody in C major, 3/4, 108 BPM, with piano and a soft bass part. Title it A Little Birthday Waltz. Use varied note lengths and end on C.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The model called &lt;code&gt;music_get_state&lt;/code&gt;, then &lt;code&gt;music_set_song&lt;/code&gt;. It produced 29 piano notes and eight bass notes: 37 notes across 24 beats, about 13.33 seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F28tota2d2kdttoz87xll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F28tota2d2kdttoz87xll.png" alt="An English music workbench showing the generated two-track score" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each note has a pitch, start time, duration, and velocity. That makes the result editable data. I can change the bass volume while the piece is playing, modify the score, or export a MIDI file for another application.&lt;/p&gt;

&lt;p&gt;This is symbolic music composition. There is no audio model generating a finished recording. The browser synthesizes the score, and the model is responsible for choosing the notes.&lt;/p&gt;

&lt;p&gt;The test checked that playback entered its playing state, that the position advanced after a volume change, and that MIDI export produced a file with the expected header. It did not evaluate whether the music sounds good. The &lt;a href="https://2019-02-18.github.io/img/webmcp-english-20261023/birthday-waltz.mid" rel="noopener noreferrer"&gt;exported MIDI&lt;/a&gt; is available if you want to listen.&lt;/p&gt;

&lt;p&gt;About that “read-back” claim: the saved score came back in the write response. A separate test read later confirmed it. Keeping the trace made that distinction visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A total with evidence behind it
&lt;/h2&gt;

&lt;p&gt;The expense sample has nine records, including one missing amount. I asked for October spending by category, excluding missing amounts rather than treating them as zero.&lt;/p&gt;

&lt;p&gt;The model read the dataset and called &lt;code&gt;data_query&lt;/code&gt; with this input:&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;"aggregate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"groupBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Category"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metric"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amount"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"filters"&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="nl"&gt;"column"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contains"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&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-10"&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;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsr60f7bg16kkrh39ap6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsr60f7bg16kkrh39ap6x.png" alt="October expense totals alongside the English CSV source records" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The page calculated &lt;strong&gt;$275&lt;/strong&gt; from six usable records. Seven records matched October; one was excluded because its amount was missing.&lt;/p&gt;

&lt;p&gt;Food accounted for $168: $48 on physical CSV row 4 and $120 on row 6. The pending food receipt on row 10 was excluded. Row 1 is the header.&lt;/p&gt;

&lt;p&gt;That is a useful division of work. The model chooses the query and explains the result. The application computes it and returns the source rows. If I disagree with the explanation, I can inspect the data rather than rerun a conversation and hope for a better answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. A page edit with a revision check
&lt;/h2&gt;

&lt;p&gt;For the website example, I asked for &lt;strong&gt;Alex's Birthday Picnic&lt;/strong&gt;, on October 31, 2026 at 2 PM in Riverside Park, with a warm orange accent.&lt;/p&gt;

&lt;p&gt;This time the model made three calls: &lt;code&gt;site_get_state&lt;/code&gt;, &lt;code&gt;site_update&lt;/code&gt;, and another &lt;code&gt;site_get_state&lt;/code&gt;. The invitation moved from revision 1 to revision 2.&lt;/p&gt;

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

&lt;p&gt;The update requires &lt;code&gt;expectedRevision&lt;/code&gt;. If someone changes the page after the agent reads it, a stale update is rejected. The agent must read the current state before trying again.&lt;/p&gt;

&lt;p&gt;This is a small safeguard, but it matters when a person and an agent share an editor. A valid JSON object can still be based on outdated assumptions.&lt;/p&gt;

&lt;p&gt;The test automation also filled the preview's RSVP form with “Sam” and two guests, checked its confirmation, and exported the HTML. Those actions were performed by the test automation, not by DeepSeek. The form is a local demonstration; it does not submit registrations to a server or send invitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the extension fits
&lt;/h2&gt;

&lt;p&gt;You can &lt;a href="https://chromewebstore.google.com/detail/webmcp-devtools/cgfogfkcfjdgpekdndcihajfjkaekjcl" rel="noopener noreferrer"&gt;install WebMCP DevTools from the Chrome Web Store&lt;/a&gt;. Open its side panel on a WebMCP-enabled page to inspect the available tools and run them with your own inputs.&lt;/p&gt;

&lt;p&gt;While building these examples, I wanted a place to inspect tool descriptions and schemas, execute known inputs, and review results and errors. Those are the core jobs of WebMCP DevTools. It also provides an AI panel for connecting a model provider.&lt;/p&gt;

&lt;p&gt;My debugging order is to test a tool with known arguments first, then let a model choose the calls. That separates an application bug from a poor tool description, an invalid argument, or an incorrect explanation.&lt;/p&gt;

&lt;p&gt;The extension and the workshop are separate projects. The workshop supplies the application state and tool implementations; a client discovers and invokes them. The same tools can be exercised by other compatible clients.&lt;/p&gt;

&lt;p&gt;For this English run, a small test harness connected DeepSeek to the browser's native WebMCP tools through browser automation. It did &lt;strong&gt;not&lt;/strong&gt; run inside the extension's chat panel. The screenshots show actual page states; after a UI fix, recorded model arguments were replayed to capture the final interface. They are not mock conversations or translated screenshots.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this run establishes
&lt;/h2&gt;

&lt;p&gt;There were &lt;strong&gt;seven model-issued tool calls&lt;/strong&gt; across the three tasks: two for music, two for data, and three for the website. All seven returned successfully. Separate checks covered playback, volume changes, exports, the RSVP form, and overflow at mobile width. The project test suite passed 27 tests, including stale-write rejection and preserving the old score after an invalid edit.&lt;/p&gt;

&lt;p&gt;This is a small functional test, not a benchmark. The model's extra “read-back” claim is a reminder that a successful tool response and an accurate explanation are different things.&lt;/p&gt;

&lt;p&gt;The design idea I want to keep exploring is straightforward: let the page own its validation and state, give the agent well-defined operations, and leave the result somewhere a person can inspect and continue editing.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://chromewebstore.google.com/detail/webmcp-devtools/cgfogfkcfjdgpekdndcihajfjkaekjcl" rel="noopener noreferrer"&gt;Install WebMCP DevTools&lt;/a&gt; from the Chrome Web Store.&lt;/li&gt;
&lt;li&gt;Open the &lt;a href="https://2019-02-18.github.io/webmcp-demo/english.html" rel="noopener noreferrer"&gt;English workshop&lt;/a&gt; in a compatible Chrome setup.&lt;/li&gt;
&lt;li&gt;Click the extension icon to open the side panel, inspect a tool's schema, and run it with known arguments before trying a model-driven workflow.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can use the &lt;a href="https://2019-02-18.github.io/webmcp-demo/english.html" rel="noopener noreferrer"&gt;workshop's manual controls&lt;/a&gt; without a model account. Native tool access requires a compatible browser setup; &lt;a href="https://developer.chrome.com/docs/ai/webmcp" rel="noopener noreferrer"&gt;Chrome's documentation&lt;/a&gt; explains the current requirements. AI clients use your own provider credentials, and prompts, tool definitions, and returned data go to that provider. The workshop itself does not ask for an API key. Export your work before reloading the tab.&lt;/p&gt;

&lt;p&gt;For implementation context, the extension source is &lt;a href="https://github.com/2019-02-18/WebMCP-DevTools" rel="noopener noreferrer"&gt;WebMCP DevTools on GitHub&lt;/a&gt;. The English workshop is a focused companion demo, not a translation of every page in the larger Playground.&lt;/p&gt;

&lt;p&gt;If you are adding tools to an existing application, I would be interested in how you handle edits based on stale state. Do you reject them, merge them, or ask the user to review a proposal?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: AI assisted with implementation, testing, and drafting this article. The examples use real DeepSeek API responses and recorded browser tool executions. The seven-call count refers only to the new English run.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built a Chrome Extension That Lets You Inspect CSS Without Opening DevTools</title>
      <dc:creator>SnapTools</dc:creator>
      <pubDate>Wed, 01 Apr 2026 01:13:23 +0000</pubDate>
      <link>https://dev.to/gulugulu/i-built-a-chrome-extension-that-lets-you-inspect-css-without-opening-devtools-4ak1</link>
      <guid>https://dev.to/gulugulu/i-built-a-chrome-extension-that-lets-you-inspect-css-without-opening-devtools-4ak1</guid>
      <description>&lt;p&gt;Every front-end developer knows the drill: right-click → Inspect → scroll through a mountain of inherited styles in the DevTools panel just to find the CSS of one button.&lt;/p&gt;

&lt;p&gt;I got tired of it. So I built &lt;strong&gt;SnapCSS&lt;/strong&gt; — a Chrome extension that lets you see the CSS of any element on any page with a single click.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Click the SnapCSS icon in your toolbar to activate inspect mode&lt;/li&gt;
&lt;li&gt;Hover over any element — it gets highlighted instantly&lt;/li&gt;
&lt;li&gt;Click the element — a clean floating panel shows you the full, cleaned CSS&lt;/li&gt;
&lt;li&gt;One-click copy to your clipboard&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. No DevTools, no noise, no digging through inherited rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;DevTools is powerful, but it's overkill when all you want is "what's the font-size, padding, and background of this button?" As a front-end developer, I do this dozens of times a day — checking how other sites style their components, debugging spacing issues, or just grabbing a quick reference.&lt;/p&gt;

&lt;p&gt;SnapCSS strips away the complexity and gives you exactly what you need: the computed CSS of the element you clicked, formatted and ready to copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes It Different from Similar Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight&lt;/strong&gt; — only 61.4 KB, no bloat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean output&lt;/strong&gt; — shows cleaned, relevant CSS instead of dumping every inherited property&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beautiful floating panel&lt;/strong&gt; — stays on the page, doesn't take you to a separate view&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero data collection&lt;/strong&gt; — no analytics, no tracking, your browsing stays private&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install It
&lt;/h2&gt;

&lt;p&gt;SnapCSS is free on the Chrome Web Store:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://chromewebstore.google.com/detail/snapcss/kcacjomlfcnflimmcnegppmejdebdcon" rel="noopener noreferrer"&gt;&lt;strong&gt;Install SnapCSS&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, a rating on the Chrome Web Store would mean a lot — it helps other developers discover it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I'm currently working on another extension called &lt;strong&gt;WebMCP DevTools&lt;/strong&gt; for debugging the new WebMCP protocol (the standard that lets AI agents interact with websites). It's currently in review on the Chrome Web Store.&lt;/p&gt;

&lt;p&gt;If you have feedback or feature requests for SnapCSS, drop a comment below — I'd love to hear what you think.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>chrome</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
