<?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: Auten</title>
    <description>The latest articles on DEV Community by Auten (@autenai).</description>
    <link>https://dev.to/autenai</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%2F4169823%2F870c6944-5f24-4cdb-ae88-7a2bcfb6a52a.png</url>
      <title>DEV Community: Auten</title>
      <link>https://dev.to/autenai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/autenai"/>
    <language>en</language>
    <item>
      <title>Your computer-use agent's clicks do nothing in admin windows on Windows</title>
      <dc:creator>Auten</dc:creator>
      <pubDate>Tue, 27 Oct 2026 06:57:59 +0000</pubDate>
      <link>https://dev.to/autenai/your-computer-use-agents-clicks-do-nothing-in-admin-windows-on-windows-1m9d</link>
      <guid>https://dev.to/autenai/your-computer-use-agents-clicks-do-nothing-in-admin-windows-on-windows-1m9d</guid>
      <description>&lt;p&gt;Your agent drives Windows fine all day. Then it reaches Task Manager, an elevated terminal, Registry Editor or an installer, and everything stops working at once: the element list comes back empty, the click tool returns "ok", and nothing on screen moves. The screenshot still shows the window perfectly.&lt;/p&gt;

&lt;p&gt;That is not the model and usually not a bug in your MCP server. It is User Interface Privilege Isolation (UIPI), and like most Windows security boundaries it fails silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What UIPI blocks
&lt;/h2&gt;

&lt;p&gt;Every Windows process runs at an integrity level. A normal process, including one started by an account that is in the Administrators group, runs at &lt;strong&gt;Medium&lt;/strong&gt;: UAC filters the admin rights out of the token. Anything started with "Run as administrator" runs at &lt;strong&gt;High&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;UIPI stops a lower-integrity process from driving a higher-integrity one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Synthetic input.&lt;/strong&gt; &lt;code&gt;SendInput&lt;/code&gt; into a higher-integrity window is dropped. Microsoft's own docs for &lt;code&gt;SendInput&lt;/code&gt; say that neither the return value nor &lt;code&gt;GetLastError&lt;/code&gt; tells you the failure was caused by UIPI. Your tool reports success because, as far as the API is concerned, it was one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Window messages.&lt;/strong&gt; &lt;code&gt;PostMessage&lt;/code&gt; / &lt;code&gt;SendMessage&lt;/code&gt; of most messages to an elevated window are blocked too, so the "click via message" fallback many tools use fails the same way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Automation.&lt;/strong&gt; A Medium client cannot read the UI tree of an elevated app, so element discovery returns nothing. This is the symptom that usually shows up first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What still works: capturing the screen. A Medium process can take a screenshot of an elevated window, which is why the agent can describe the window it cannot touch.&lt;/p&gt;

&lt;p&gt;A public bug report on another open-source agent shows the exact pattern: screenshots fine, 0 elements, &lt;code&gt;click&lt;/code&gt; returns &lt;code&gt;ok: true&lt;/code&gt; with no effect, agent at Medium, target elevated. It is not specific to any one tool. Every desktop agent that does not run elevated hits it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check it in thirty seconds
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The agent side.&lt;/strong&gt; In the terminal or app that launches your agent:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;whoami&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/groups&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mandatory"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Medium Mandatory Level&lt;/code&gt; = normal. &lt;code&gt;High Mandatory Level&lt;/code&gt; = elevated.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The target side.&lt;/strong&gt; Task Manager &amp;gt; Details, right-click a column header &amp;gt; Select columns &amp;gt; &lt;strong&gt;Elevated&lt;/strong&gt;. Any target with "Yes" there is out of reach for a Medium agent.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the agent is Medium and the target is elevated, you have found the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixes, in the order we would try them
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don't elevate the target.&lt;/strong&gt; Most of the time it does not need it. The usual culprit is a terminal or IDE that was set to always run as administrator (Properties &amp;gt; Compatibility, or a shortcut's Advanced settings). Turn that off and the agent can drive it again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the agent host elevated, on purpose.&lt;/strong&gt; Start the terminal or MCP client with "Run as administrator" so the agent runs at High too. Be honest with yourself about what this means: everything the agent does now runs with admin rights. Do it for the one task that needs it, not as your default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;uiAccess, if you ship the tool.&lt;/strong&gt; An app whose manifest sets &lt;code&gt;uiAccess="true"&lt;/code&gt; may drive higher-integrity windows, but only if it is signed with a trusted certificate and installed in a protected location such as Program Files. That is how screen readers do it. It is not something you switch on for a script in your home folder.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What none of these fix: &lt;strong&gt;UAC prompts.&lt;/strong&gt; The "Do you want to allow this app to make changes" dialog appears on the secure desktop, which no ordinary process can see or click. That is by design. An agent should stop and ask you there, not try to work around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short pre-flight before you blame the model
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Screenshot fine, element list empty, clicks "ok" but ignored -&amp;gt; check elevation first.&lt;/li&gt;
&lt;li&gt;Agent at Medium, target "Elevated: Yes" -&amp;gt; un-elevate the target, or elevate the agent for that one task.&lt;/li&gt;
&lt;li&gt;A UAC prompt is up -&amp;gt; the agent cannot answer it. You do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why we care
&lt;/h2&gt;

&lt;p&gt;We build Auten, an MCP server that gives Claude Code, Codex, Cursor or any MCP client hands on a real screen: your computer (Mac, Windows, Linux) and your Android phone (beta). On Windows it installs per user without admin rights, so by default it runs at Medium integrity and this rule applies to it exactly like to every other non-elevated tool. Setup is at &lt;a href="https://auten.ai/mcp?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;auten.ai/mcp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have hit a Windows case where an agent sees a window but cannot touch it and elevation was not the cause, describe it in the comments. We collect these.&lt;/p&gt;

</description>
      <category>windows</category>
      <category>ai</category>
      <category>mcp</category>
      <category>automation</category>
    </item>
    <item>
      <title>Your AI agent can't see your Android phone: adb 'unauthorized', 'offline' and 5 other causes</title>
      <dc:creator>Auten</dc:creator>
      <pubDate>Fri, 23 Oct 2026 06:15:47 +0000</pubDate>
      <link>https://dev.to/autenai/your-ai-agent-cant-see-your-android-phone-adb-unauthorized-offline-and-5-other-causes-31di</link>
      <guid>https://dev.to/autenai/your-ai-agent-cant-see-your-android-phone-adb-unauthorized-offline-and-5-other-causes-31di</guid>
      <description>&lt;p&gt;Every tool that lets an AI agent drive an Android phone over USB sits on the same thing: &lt;code&gt;adb&lt;/code&gt;. When the agent says "no device found", the agent is almost never the problem. The phone and the computer have not agreed to talk yet.&lt;/p&gt;

&lt;p&gt;Run this first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb devices &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whatever it prints tells you which of the causes below you have.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;code&gt;unauthorized&lt;/code&gt;: the phone never approved this computer
&lt;/h2&gt;

&lt;p&gt;The phone lists the computer's RSA key as untrusted. Usually the "Allow USB debugging?" prompt was dismissed, or it appeared while the screen was locked and you never saw it.&lt;/p&gt;

&lt;p&gt;Fix:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlock the phone, unplug, plug back in, and tap Allow with "Always allow from this computer" ticked.&lt;/li&gt;
&lt;li&gt;No prompt at all? In Developer options tap "Revoke USB debugging authorizations", toggle USB debugging off and on, then &lt;code&gt;adb kill-server &amp;amp;&amp;amp; adb start-server&lt;/code&gt; and replug.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent-specific version of this one: adb keeps its key in &lt;code&gt;~/.android/adbkey&lt;/code&gt;. If your agent or MCP client runs adb under a different user or a different &lt;code&gt;HOME&lt;/code&gt; (a service, a sandbox, a container), it has a different key, and the phone sees a brand-new computer. It works in your terminal and says &lt;code&gt;unauthorized&lt;/code&gt; from the agent. Approve the prompt once more from that context, or point both at the same key.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Nothing listed: the cable or the driver
&lt;/h2&gt;

&lt;p&gt;An empty list means USB itself is not carrying data to adb.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Charge-only cables are common, especially the short ones that came with a power bank. Try a cable you have used for file transfer.&lt;/li&gt;
&lt;li&gt;Windows needs a USB driver for many phones (Google USB Driver for Pixel, the vendor's driver for Samsung and others). Device Manager shows the phone with a warning icon when it is missing.&lt;/li&gt;
&lt;li&gt;Use a port on the computer, not a hub or a monitor's USB port, while you debug.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Linux: &lt;code&gt;no permissions (... are your udev rules wrong?)&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Your user may not open the USB device. Install the community udev rules (&lt;code&gt;android-sdk-platform-tools-common&lt;/code&gt; or &lt;code&gt;android-udev-rules&lt;/code&gt;, depending on the distro), make sure your user is in the &lt;code&gt;plugdev&lt;/code&gt; group, log out and back in, replug.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Two adb versions fighting each other
&lt;/h2&gt;

&lt;p&gt;You see &lt;code&gt;adb server version (41) doesn't match this client (39); killing...&lt;/code&gt; and the device flickers between online and gone.&lt;/p&gt;

&lt;p&gt;Android Studio, Homebrew, scrcpy builds and some agent tools each ship their own adb. Whichever starts the server first wins, the next one kills it. An agent started from an app often has a different PATH than your shell, so it picks a different adb than the one you tested with.&lt;/p&gt;

&lt;p&gt;Fix: keep one platform-tools install, put it first on PATH, and give tools the absolute path where they let you.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;code&gt;offline&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The device is connected but adb cannot complete the handshake. Usually an old adb against a newer Android, or a server stuck from an earlier session.&lt;/p&gt;

&lt;p&gt;Fix: update platform-tools, &lt;code&gt;adb kill-server&lt;/code&gt;, replug, unlock the phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;code&gt;more than one device/emulator&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A running emulator counts as a device, and so does a second phone on the same machine. adb refuses to guess.&lt;/p&gt;

&lt;p&gt;Fix: pick one with &lt;code&gt;adb -s &amp;lt;serial&amp;gt; ...&lt;/code&gt; or set &lt;code&gt;ANDROID_SERIAL=&amp;lt;serial&amp;gt;&lt;/code&gt; in the environment the agent runs in.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. It connects, but taps and screenshots fail
&lt;/h2&gt;

&lt;p&gt;adb itself works, the phone blocks what the agent wants to do with it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Xiaomi, Redmi, POCO (MIUI / HyperOS): input from adb needs an extra toggle, "USB debugging (Security settings)", below the normal one. Without it taps fail with an &lt;code&gt;INJECT_EVENTS&lt;/code&gt; permission error.&lt;/li&gt;
&lt;li&gt;Samsung (One UI 6 and later): Auto Blocker blocks commands over the USB cable. Turn it off while you use the phone with an agent.&lt;/li&gt;
&lt;li&gt;Banking and some streaming apps mark their windows as secure. Screenshots of those come back black. That is the app protecting itself, not a bug you can fix.&lt;/li&gt;
&lt;li&gt;A locked or sleeping screen stops everything. "Stay awake" in Developer options keeps it on while charging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One more that bites a week later
&lt;/h2&gt;

&lt;p&gt;On Android 11 and later, the phone drops a computer's authorization if it has not connected for about seven days. Everything worked last week, today it is &lt;code&gt;unauthorized&lt;/code&gt; again. Developer options has "Disable adb authorization timeout" if that keeps happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  A 30-second checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;adb devices -l&lt;/code&gt; shows &lt;code&gt;device&lt;/code&gt;, not &lt;code&gt;unauthorized&lt;/code&gt; or &lt;code&gt;offline&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Data cable, direct port, driver on Windows, udev rules on Linux?&lt;/li&gt;
&lt;li&gt;One adb on the PATH the agent actually uses?&lt;/li&gt;
&lt;li&gt;One device, or a serial set?&lt;/li&gt;
&lt;li&gt;Xiaomi security toggle on, Samsung Auto Blocker off?&lt;/li&gt;
&lt;li&gt;Screen unlocked and awake?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why we wrote this
&lt;/h2&gt;

&lt;p&gt;We build Auten, an MCP server that gives Claude Code, Codex, Cursor or any MCP client hands on a real screen: your computer, and your Android phone over USB (beta). The phone side goes through the same adb authorization as every other tool, so these are the failures we see first. They apply to any adb-based setup, not just ours. Setup notes: &lt;a href="https://auten.ai/mcp?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;https://auten.ai/mcp?utm_source=devto&amp;amp;utm_medium=social&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hit a cause that is not on the list? Put it in the comments with the phone model and we will add it.&lt;/p&gt;

</description>
      <category>android</category>
      <category>adb</category>
      <category>ai</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Claude Code's computer-use server is missing from /mcp: options on Linux, Windows and Team plans</title>
      <dc:creator>Auten</dc:creator>
      <pubDate>Tue, 20 Oct 2026 06:15:09 +0000</pubDate>
      <link>https://dev.to/autenai/claude-codes-computer-use-server-is-missing-from-mcp-options-on-linux-windows-and-team-plans-9jg</link>
      <guid>https://dev.to/autenai/claude-codes-computer-use-server-is-missing-from-mcp-options-on-linux-windows-and-team-plans-9jg</guid>
      <description>&lt;p&gt;Claude Code can now drive a GUI: open an app, click through it, screenshot the result. A lot of people try to turn it on and find the &lt;code&gt;computer-use&lt;/code&gt; server simply is not in &lt;code&gt;/mcp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is usually not a bug. The built-in feature has a narrow eligibility list. Here is what it is, and what you can do when you are outside it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who gets built-in computer use in the CLI
&lt;/h2&gt;

&lt;p&gt;From Anthropic's own docs page (code.claude.com/docs/en/computer-use), as of October 2026, the CLI version needs all of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS.&lt;/strong&gt; The CLI version is not available on Linux or Windows. On Windows there is computer use in the Desktop app instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Pro or Max plan.&lt;/strong&gt; Not Team or Enterprise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A claude.ai login.&lt;/strong&gt; Not via Amazon Bedrock, Google Cloud or Microsoft Foundry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An interactive session.&lt;/strong&gt; Not in non-interactive mode with &lt;code&gt;-p&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If one of those is false, the server does not show up. Run &lt;code&gt;/status&lt;/code&gt; to check your plan and login.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you are outside that list
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;On Windows:&lt;/strong&gt; try computer use in the Claude Desktop app. The docs say it shares the CLI's engine and is switched on in Settings; check its own requirements page for your plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On Linux, on a Team or Enterprise seat, via a cloud provider, or in another client&lt;/strong&gt; (Codex CLI, Cursor's in-editor Agent, Gemini CLI): Claude Code's built-in option is not there. What does work is a computer-use &lt;strong&gt;MCP server&lt;/strong&gt;. MCP is client-side, so it does not care about your plan or which provider serves the model. Claude Code just sees more tools.&lt;/p&gt;

&lt;p&gt;There are several open-source ones: per-platform Linux tools (X11, and Wayland-first ones built on AT-SPI), Windows UI Automation tools and ADB tools for Android, plus cross-platform computer-use MCP servers that cover macOS, Linux and Windows in one install. There are also open-source wrappers that let a CLI agent borrow another vendor's desktop computer-use runtime on macOS and Linux X11. Pick by what you need to drive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one we build
&lt;/h2&gt;

&lt;p&gt;Disclosure: we make Auten, so weigh this accordingly.&lt;/p&gt;

&lt;p&gt;Auten is an MCP server that gives your agent hands on a real screen: macOS, Windows 10/11 and Linux (X11), plus an Android phone over USB (beta). It reads the accessibility tree, clicks, types and reads text, so it works in apps that have no API.&lt;/p&gt;

&lt;p&gt;Setup on Linux or macOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://auten.ai/install | bash
claude mcp add &lt;span class="nt"&gt;-s&lt;/span&gt; user auten &lt;span class="nt"&gt;--&lt;/span&gt; auten mcp-bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Linux the installer asks for &lt;code&gt;sudo&lt;/code&gt; once to apt-install the accessibility and input tools; on macOS it needs no admin rights.&lt;/p&gt;

&lt;p&gt;On Windows (PowerShell, no admin rights):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;irm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://auten.ai/install.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mcp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;auten&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;npx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;autenai/mcp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check with &lt;code&gt;/mcp&lt;/code&gt; and ask in plain words: "Open the settings app and turn on dark mode."&lt;/p&gt;

&lt;p&gt;Two things that differ from the built-in tool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It learns.&lt;/strong&gt; Once a task works, you save it as a skill with parameters. Next time it replays without an AI call, so repeat runs are faster and cost no tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passwords stay local.&lt;/strong&gt; Saved logins are typed on your machine; the model never sees them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Honest limits: Linux means X11 today, not Wayland. The phone part is beta. It is not open source (the launcher and docs are). There is a free tier of 30 minutes a month, no card.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick decision
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You are on&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macOS, Pro/Max, claude.ai login, interactive&lt;/td&gt;
&lt;td&gt;Built-in computer use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows, eligible for Desktop computer use&lt;/td&gt;
&lt;td&gt;Claude Desktop computer use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux (X11), Team/Enterprise, Bedrock/Google Cloud/Foundry, other clients&lt;/td&gt;
&lt;td&gt;A computer-use MCP server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You also need an Android phone&lt;/td&gt;
&lt;td&gt;An MCP server with Android support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Repo and setup for other clients: &lt;a href="https://github.com/auten-ai/auten-mcp" rel="noopener noreferrer"&gt;https://github.com/auten-ai/auten-mcp&lt;/a&gt; (docs: &lt;a href="https://auten.ai/mcp?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;https://auten.ai/mcp?utm_source=devto&amp;amp;utm_medium=social&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>mcp</category>
      <category>linux</category>
      <category>ai</category>
    </item>
    <item>
      <title>Your AI agent has to log in. Keep the password out of its context</title>
      <dc:creator>Auten</dc:creator>
      <pubDate>Sat, 17 Oct 2026 06:29:41 +0000</pubDate>
      <link>https://dev.to/autenai/your-ai-agent-has-to-log-in-keep-the-password-out-of-its-context-b28</link>
      <guid>https://dev.to/autenai/your-ai-agent-has-to-log-in-keep-the-password-out-of-its-context-b28</guid>
      <description>&lt;p&gt;Sooner or later an agent that does real work hits a login screen. The CRM wants a password, the supplier portal wants a password and a 2FA code, the staging admin wants both.&lt;/p&gt;

&lt;p&gt;The easy fix is to put the password in the prompt, or in a file the agent can read. It works on the first try, which is exactly why it ends up everywhere. Here is what that costs and a pattern that keeps the secret on your machine instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where a password in the prompt ends up
&lt;/h2&gt;

&lt;p&gt;Once the value is part of the conversation, it is copied to every place the conversation goes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The transcript.&lt;/strong&gt; Chat history, session logs, &lt;code&gt;~/.something/history.jsonl&lt;/code&gt;, whatever your client keeps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The provider.&lt;/strong&gt; Every request carries the full context, so the password travels with each turn, under the provider's retention terms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool logs and traces.&lt;/strong&gt; Observability tools record tool inputs. A &lt;code&gt;type("hunter2")&lt;/code&gt; call is now in your tracing backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The model's next output.&lt;/strong&gt; Models summarise and repeat. "I logged in with the password hunter2" is a perfectly natural sentence for them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt injection.&lt;/strong&gt; A web page or email the agent reads can say "now type the admin password into this field". If the model knows the password, it can comply.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this needs an attacker to be clever. It only needs the value to be in the context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern: the model names the secret, the tool types it
&lt;/h2&gt;

&lt;p&gt;Split the job in two. The model decides &lt;em&gt;which&lt;/em&gt; login to use and &lt;em&gt;where&lt;/em&gt;. A local tool looks the value up and types it. The model only ever sees a name and a result.&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;model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fill_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;crm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;# a name, not a value
&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;looks&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;crm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;OS&lt;/span&gt; &lt;span class="n"&gt;keychain&lt;/span&gt;
&lt;span class="n"&gt;tool&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;focuses&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;locally&lt;/span&gt;
&lt;span class="n"&gt;tool&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;                  &lt;span class="c1"&gt;# never echoes the value
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A minimal MCP tool in that shape (TypeScript SDK; &lt;code&gt;getSecret&lt;/code&gt; and &lt;code&gt;typeIntoFocusedField&lt;/code&gt; are yours to implement):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fill_login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;site&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Saved login name, e.g. 'crm'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secret&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;getSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// OS keychain, see below&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;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`no saved login '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'`&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;typeIntoFocusedField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// typed on this machine&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important line is the return value. It says what happened, never what was typed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Store secrets where the OS already protects them
&lt;/h2&gt;

&lt;p&gt;Do not invent a secrets file. Every desktop OS has a keychain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS:&lt;/strong&gt; &lt;code&gt;security add-generic-password -s agent -a crm -w&lt;/code&gt; (prompts for the value), read with &lt;code&gt;security find-generic-password -s agent -a crm -w&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux:&lt;/strong&gt; &lt;code&gt;secret-tool store --label="crm" service agent account crm&lt;/code&gt;, read with &lt;code&gt;secret-tool lookup service agent account crm&lt;/code&gt; (libsecret, GNOME Keyring or KWallet).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows:&lt;/strong&gt; Credential Manager, through your language's keyring library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform:&lt;/strong&gt; Python's &lt;code&gt;keyring&lt;/code&gt; package and similar libraries wrap all three.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your tool reads from there at the moment it types. Nothing lands in a dotfile the agent could &lt;code&gt;cat&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small rules that close the remaining gaps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type, don't paste.&lt;/strong&gt; Pasting goes through the clipboard, and clipboard managers keep history. Send keystrokes into the focused field instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redact your own logs.&lt;/strong&gt; If your tool layer logs inputs, make sure the typed value is replaced with &lt;code&gt;***&lt;/code&gt; before it is written.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pin each login to where it belongs.&lt;/strong&gt; Record the site or app a login was first used on, and refuse to type it anywhere else. A look-alike page that asks the agent to "log in again" then gets nothing. Only the user, not the model, should be able to change the pin. A secret typed into the wrong field is still leaked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat 2FA codes the same way.&lt;/strong&gt; Generate or read the code in the tool, type it, return "filled". The model does not need to see it either.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep reading tools blind to fields.&lt;/strong&gt; If the agent can screenshot or read the screen, password fields should come back masked, which most toolkits already do. Do not add a "read value" tool that undoes it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why we care
&lt;/h2&gt;

&lt;p&gt;We build Auten, an MCP server that gives Claude Code, Codex, Cursor or any MCP client hands on a real screen: your computer (Mac, Windows, Linux) and your Android phone over USB (beta). Logins work this way: passwords stay on your computer and are typed locally, so the model never sees them. Each saved login is pinned to the site or app it was first used on; on a different origin Auten refuses and types nothing. A reader asked us about exactly that gap on dev.to, and we shipped it the same evening. If you want to try it: auten.ai.&lt;/p&gt;

&lt;p&gt;How do you handle credentials in your agent setups today? Env vars, a vault, or "it's in the prompt for now"? Tell us in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>mcp</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>Your computer-use agent clicks 20 pixels off: screenshots vs the accessibility tree</title>
      <dc:creator>Auten</dc:creator>
      <pubDate>Wed, 14 Oct 2026 06:04:35 +0000</pubDate>
      <link>https://dev.to/autenai/your-computer-use-agent-clicks-20-pixels-off-screenshots-vs-the-accessibility-tree-4dcg</link>
      <guid>https://dev.to/autenai/your-computer-use-agent-clicks-20-pixels-off-screenshots-vs-the-accessibility-tree-4dcg</guid>
      <description>&lt;p&gt;Every computer-use agent has to answer one question before it can click anything: what is on the screen right now?&lt;/p&gt;

&lt;p&gt;There are two ways to answer it. Send the model a screenshot and let it find the button in the pixels. Or ask the operating system, which already knows: every serious UI toolkit publishes an accessibility tree for screen readers, with the role, name, state and position of each control.&lt;/p&gt;

&lt;p&gt;Most demos use screenshots because they work everywhere. In practice you want both, in a specific order. Here is how each one behaves, how to look at the tree yourself, and where each breaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the accessibility tree gives you
&lt;/h2&gt;

&lt;p&gt;A screenshot is a grid of pixels. The tree is a list of facts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;button  "Export"        enabled   @ (812, 64)
textbox "File name"     focused   value "report-q3"
menuitem "CSV"          @ (830, 140)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That changes three things for an agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It clicks the element, not a guessed coordinate.&lt;/strong&gt; The agent says "press the Export button" and the OS hands back exactly where it is. No off-by-20-pixels misses on a crowded toolbar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It knows state.&lt;/strong&gt; Disabled, checked, focused, expanded, the current value of a field. From a screenshot the model has to infer a greyed-out button from a slightly lighter shade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is cheap to send.&lt;/strong&gt; A screen with 40 controls is a few dozen short lines of text. A screenshot costs roughly &lt;code&gt;width x height / 750&lt;/code&gt; tokens on Claude (per Anthropic's vision docs), so about 1,600 tokens for a 1092x1092 image, every single step. Text is also something the model can search and quote precisely.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where the tree is empty or lies
&lt;/h2&gt;

&lt;p&gt;The tree is only as good as the app's accessibility work. The usual gaps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Canvas apps.&lt;/strong&gt; Design tools' canvases, games, maps, charting widgets. The window is one big element with nothing inside.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote screens.&lt;/strong&gt; A VNC, RDP or Citrix window is just a video. The tree stops at the window frame.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Electron and Chromium, until asked.&lt;/strong&gt; Chromium builds its full web accessibility tree only when it detects an assistive technology. On macOS, Electron apps expose it once a client sets &lt;code&gt;AXManualAccessibility&lt;/code&gt;; Chrome itself has &lt;code&gt;--force-renderer-accessibility&lt;/code&gt;. Before that, you see a shell with almost no children.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom-drawn controls&lt;/strong&gt; with no names. You get &lt;code&gt;button ""&lt;/code&gt; twelve times in a row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale positions&lt;/strong&gt; during animations and scrolling. Read the tree, then act fast, or read it again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why screenshots stay in the toolbox: they work on anything that draws pixels.&lt;/p&gt;

&lt;h2&gt;
  
  
  The screenshot trap: coordinates and scaling
&lt;/h2&gt;

&lt;p&gt;If you do click from screenshots, the most common silent failure is scaling, not the model's eyesight.&lt;/p&gt;

&lt;p&gt;On a Retina Mac the screenshot is in physical pixels and clicks are in logical points (half). On Windows, display scaling of 125% or 150% does the same thing. And many agents downscale the screenshot before sending it to the model, so the model's coordinates are in a third coordinate space.&lt;/p&gt;

&lt;p&gt;Symptoms: clicks land up-left or down-right of the target, consistently, by a fixed ratio. Fix: keep one conversion function from "image the model saw" to "screen points" and run every click through it. Test it by clicking the four corners of a known window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Look at the tree yourself
&lt;/h2&gt;

&lt;p&gt;Before you decide which approach your agent needs for an app, spend two minutes with the platform inspector:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS:&lt;/strong&gt; Accessibility Inspector (Xcode, Open Developer Tool). Hover anything to see role, title and frame.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows:&lt;/strong&gt; Accessibility Insights for Windows, or &lt;code&gt;Inspect.exe&lt;/code&gt; from the Windows SDK. Both read UI Automation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux:&lt;/strong&gt; Accerciser, which reads AT-SPI. Most of this assumes X11; Wayland deliberately limits what other programs can see and inject.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Android:&lt;/strong&gt; &lt;code&gt;adb shell uiautomator dump /sdcard/view.xml &amp;amp;&amp;amp; adb pull /sdcard/view.xml&lt;/code&gt;. You get the view hierarchy with text, resource ids and bounds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the inspector shows named buttons and fields, a tree-first agent will be fast and accurate there. If it shows one big pane, plan for screenshots and OCR.&lt;/p&gt;

&lt;h2&gt;
  
  
  The order that works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tree first.&lt;/strong&gt; List the interactive elements with names, roles and positions. Let the model pick one by id.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text next.&lt;/strong&gt; When the tree has no labels, OCR the window and match on visible text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screenshot last.&lt;/strong&gt; For canvases, icons without names, or "is this the right page?" checks, send the image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify after acting.&lt;/strong&gt; Re-read the tree or the text after each important step. Do not assume the click worked.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keeping the screenshot as the fallback instead of the default makes most steps cheaper and more precise, and you still cover the apps that draw everything themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we care
&lt;/h2&gt;

&lt;p&gt;We build Auten, an MCP server that gives Claude Code, Codex, Cursor or any MCP client hands on a real screen: your computer (Mac, Windows, Linux) and your Android phone over USB (beta). It works in exactly this order: the agent gets a numbered list of real buttons and fields from the accessibility tree, and OCR and screenshots are there when an app has no accessibility info. If you want to try it: auten.ai.&lt;/p&gt;

&lt;p&gt;Which apps have the worst accessibility trees you have had to automate? Tell us in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>a11y</category>
      <category>automation</category>
    </item>
    <item>
      <title>Your MCP server works in the terminal but not in Claude Desktop or Cursor: 8 causes</title>
      <dc:creator>Auten</dc:creator>
      <pubDate>Sun, 11 Oct 2026 06:23:24 +0000</pubDate>
      <link>https://dev.to/autenai/your-mcp-server-works-in-the-terminal-but-not-in-claude-desktop-or-cursor-7-causes-16o7</link>
      <guid>https://dev.to/autenai/your-mcp-server-works-in-the-terminal-but-not-in-claude-desktop-or-cursor-7-causes-16o7</guid>
      <description>&lt;p&gt;You run your MCP server by hand, it starts, nothing crashes. You add it to Claude Desktop, Cursor or another client and it shows up red, "failed", or connects and then no tool works.&lt;/p&gt;

&lt;p&gt;Almost always the server is fine. The difference is the environment the client launches it in. These are the causes we keep hitting, roughly in order of how often.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Something writes to stdout
&lt;/h2&gt;

&lt;p&gt;With the stdio transport, stdout IS the protocol. Every byte on it must be a JSON-RPC message. One &lt;code&gt;console.log("server started")&lt;/code&gt;, a banner from a library, or a deprecation warning printed to stdout, and the client fails to parse the stream.&lt;/p&gt;

&lt;p&gt;Fix: send all logs to stderr (&lt;code&gt;console.error&lt;/code&gt; in Node, &lt;code&gt;print(..., file=sys.stderr)&lt;/code&gt; in Python, the &lt;code&gt;logging&lt;/code&gt; module defaults to stderr). Clients usually capture stderr into their log file, so you lose nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The client does not have your shell's PATH
&lt;/h2&gt;

&lt;p&gt;On macOS, an app started from the Dock or Finder does not read &lt;code&gt;.zshrc&lt;/code&gt; or &lt;code&gt;.bash_profile&lt;/code&gt;. It gets the minimal launchd PATH, &lt;code&gt;/usr/bin:/bin:/usr/sbin:/sbin&lt;/code&gt;. If &lt;code&gt;node&lt;/code&gt; came from Homebrew (&lt;code&gt;/opt/homebrew/bin&lt;/code&gt;) or nvm (&lt;code&gt;~/.nvm/versions/...&lt;/code&gt;), the client cannot find &lt;code&gt;npx&lt;/code&gt; or &lt;code&gt;node&lt;/code&gt;, and you get &lt;code&gt;spawn npx ENOENT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Fix, pick one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the absolute path as the command: run &lt;code&gt;which npx&lt;/code&gt; in your terminal and paste the result.&lt;/li&gt;
&lt;li&gt;Set PATH explicitly in the server's &lt;code&gt;env&lt;/code&gt; block in the client config.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With nvm, the absolute path also pins the Node version, which avoids cause 6.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Your environment variables are not there either
&lt;/h2&gt;

&lt;p&gt;The same applies to API keys and settings you exported in your shell. The server process only gets what the client passes it.&lt;/p&gt;

&lt;p&gt;Fix: put them in the &lt;code&gt;env&lt;/code&gt; block of that server's config entry, not in your shell profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. npx is waiting or still downloading
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;npx some-package&lt;/code&gt; on a machine that does not have it cached first downloads it. Without &lt;code&gt;-y&lt;/code&gt; it can stop to ask "Ok to proceed?", and nobody is there to answer. Even with &lt;code&gt;-y&lt;/code&gt;, a slow first download can outlast the client's startup timeout, so the first launch fails and the second one works.&lt;/p&gt;

&lt;p&gt;Fix: always &lt;code&gt;npx -y&lt;/code&gt;, and run the exact command once in a terminal so the package is cached before the client starts it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Relative paths and the working directory
&lt;/h2&gt;

&lt;p&gt;Clients do not promise a working directory. On macOS it is often &lt;code&gt;/&lt;/code&gt;. A server that opens &lt;code&gt;./config.json&lt;/code&gt; or writes &lt;code&gt;./data.db&lt;/code&gt; works from your project folder and fails everywhere else.&lt;/p&gt;

&lt;p&gt;Fix: absolute paths in args, or resolve paths relative to the script file, not the current directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. A different Node or Python than you think
&lt;/h2&gt;

&lt;p&gt;Your terminal uses the version from nvm, pyenv or a virtualenv. The client may hit the system one, or an old Homebrew one. Syntax errors at import time or "unsupported engine" warnings in the log are the sign.&lt;/p&gt;

&lt;p&gt;Fix: point the command at the exact interpreter (&lt;code&gt;/path/to/venv/bin/python&lt;/code&gt;, the nvm &lt;code&gt;node&lt;/code&gt;), not a bare &lt;code&gt;python&lt;/code&gt; or &lt;code&gt;node&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Windows: npx is not an executable
&lt;/h2&gt;

&lt;p&gt;On Windows &lt;code&gt;npx&lt;/code&gt; is &lt;code&gt;npx.cmd&lt;/code&gt;, a batch file, and some clients spawn the command without a shell, so &lt;code&gt;"command": "npx"&lt;/code&gt; fails.&lt;/p&gt;

&lt;p&gt;Fix: launch it through cmd:&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;"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;"cmd"&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;"/c"&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="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;"your-mcp-package"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. It is configured for a different project (Claude Code)
&lt;/h2&gt;

&lt;p&gt;Added from the comments, thanks to &lt;a class="mentioned-user" href="https://dev.to/heyitsjakub"&gt;@heyitsjakub&lt;/a&gt;. &lt;code&gt;claude mcp add&lt;/code&gt; uses the local scope by default: the server is registered for the project you ran it in, and nowhere else. Open another project and it looks like the server vanished, while the config is fine.&lt;/p&gt;

&lt;p&gt;Fix: run &lt;code&gt;claude mcp list&lt;/code&gt; inside the project where it is missing. For every project, add it with &lt;code&gt;--scope user&lt;/code&gt;. To share it with your team, use &lt;code&gt;--scope project&lt;/code&gt;, which writes a &lt;code&gt;.mcp.json&lt;/code&gt; at the repo root (Claude Code asks each person to approve it once). Cursor has the same split: &lt;code&gt;~/.cursor/mcp.json&lt;/code&gt; for all projects, &lt;code&gt;.cursor/mcp.json&lt;/code&gt; for one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to look first
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claude Desktop logs:&lt;/strong&gt; &lt;code&gt;~/Library/Logs/Claude/&lt;/code&gt; on macOS (&lt;code&gt;mcp.log&lt;/code&gt; plus one &lt;code&gt;mcp-server-&amp;lt;name&amp;gt;.log&lt;/code&gt; per server), &lt;code&gt;%APPDATA%\Claude\logs&lt;/code&gt; on Windows. Your stderr ends up there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code:&lt;/strong&gt; &lt;code&gt;claude mcp list&lt;/code&gt; shows which servers connect, and &lt;code&gt;/mcp&lt;/code&gt; inside a session shows their status.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Inspector:&lt;/strong&gt; &lt;code&gt;npx @modelcontextprotocol/inspector &amp;lt;your command&amp;gt; &amp;lt;args&amp;gt;&lt;/code&gt; starts the server the way a client would and lets you call each tool by hand. If it works there and not in the client, the problem is the client's environment (causes 2 to 6).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restart for real.&lt;/strong&gt; Most clients read the config only at startup. On macOS that means Cmd+Q, not closing the window.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A 30-second checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nothing but JSON-RPC on stdout?&lt;/li&gt;
&lt;li&gt;Command is an absolute path, or PATH is set in &lt;code&gt;env&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;API keys in the config's &lt;code&gt;env&lt;/code&gt;, not only in your shell?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npx -y&lt;/code&gt;, and the package already cached?&lt;/li&gt;
&lt;li&gt;No relative paths?&lt;/li&gt;
&lt;li&gt;The interpreter the client runs is the one you tested with?&lt;/li&gt;
&lt;li&gt;On Windows, &lt;code&gt;cmd /c npx&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;In Claude Code, added in the right scope?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why we wrote this
&lt;/h2&gt;

&lt;p&gt;We build Auten, an MCP server that gives Claude Code, Codex, Cursor or any MCP client hands on a real screen: your computer and your Android phone (beta). It is launched with &lt;code&gt;npx -y @autenai/mcp&lt;/code&gt;, so every item on this list is a support question we have either hit ourselves or expect to.&lt;/p&gt;

&lt;p&gt;Hit another cause? Put it in the comments and we will add it.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>debugging</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why your computer-use agent silently does nothing on macOS</title>
      <dc:creator>Auten</dc:creator>
      <pubDate>Fri, 09 Oct 2026 09:29:11 +0000</pubDate>
      <link>https://dev.to/autenai/why-your-computer-use-agent-silently-does-nothing-on-macos-4jee</link>
      <guid>https://dev.to/autenai/why-your-computer-use-agent-silently-does-nothing-on-macos-4jee</guid>
      <description>&lt;p&gt;You wire a computer-use MCP server into Claude Code, Cursor or Codex, ask it to click a button, and the tool call comes back "ok". Nothing on screen moves. Or the screenshot it reasons over is just your wallpaper.&lt;/p&gt;

&lt;p&gt;Nine times out of ten this is not the model and not the MCP server. It is macOS privacy permissions (TCC), and the frustrating part is that most of the failures are silent. This is the checklist we wish we had on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two permissions, two different failures
&lt;/h2&gt;

&lt;p&gt;A screen-driving agent needs two separate grants in System Settings &amp;gt; Privacy &amp;amp; Security:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessibility&lt;/strong&gt; lets a process read other apps' UI trees (buttons, fields, labels) and post synthetic mouse and keyboard events.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Without it, Accessibility API calls fail with &lt;code&gt;kAXErrorAPIDisabled&lt;/code&gt; (-25211). Many tools swallow that and return an empty element list.&lt;/li&gt;
&lt;li&gt;Synthetic events posted with &lt;code&gt;CGEventPost&lt;/code&gt; are dropped without any error. The click "succeeds" and nothing happens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Screen Recording&lt;/strong&gt; lets a process capture other apps' pixels.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Without it, a capture typically shows the desktop and menu bar, but not the contents of other apps' windows. A vision model then confidently describes an empty desktop.&lt;/li&gt;
&lt;li&gt;Less obvious: window titles of other apps (&lt;code&gt;kCGWindowName&lt;/code&gt; from &lt;code&gt;CGWindowListCopyWindowInfo&lt;/code&gt;) are withheld too, so "find the window called Invoice" fails even if you never take a screenshot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your agent can list elements but its screenshots look empty, you are missing Screen Recording. If it can see everything but clicks do nothing, you are missing Accessibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  The grant usually belongs to the app hosting your agent
&lt;/h2&gt;

&lt;p&gt;This is the part that costs people an afternoon. macOS attributes a permission request to the "responsible" app, which for a command-line tool is usually the GUI app that launched it, not the binary itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP server started by Claude Code in Terminal or iTerm: the grant Terminal (or iTerm) has is what counts.&lt;/li&gt;
&lt;li&gt;Started by Cursor, VS Code or a desktop chat client: that app's grant counts.&lt;/li&gt;
&lt;li&gt;Started by &lt;code&gt;launchd&lt;/code&gt; (a LaunchAgent): the process itself is responsible, so the grant has to be on the exact binary in &lt;code&gt;ProgramArguments&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So "I gave node Accessibility and it still fails" is normal: node was never the responsible process. Grant the host app, restart it fully (quit, not just close the window), and try again. Permission changes are not picked up by already running processes.&lt;/p&gt;

&lt;p&gt;The flip side is worth saying plainly: granting Accessibility to Terminal means everything you run from Terminal can drive your Mac. If that bothers you, run the agent from a dedicated terminal app you use only for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check what your agent actually has
&lt;/h2&gt;

&lt;p&gt;Run this from the same app that launches your agent, so it inherits the same responsible process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/tcc-check.swift &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
import ApplicationServices
import CoreGraphics
print("Accessibility:   ", AXIsProcessTrusted())
print("Screen Recording:", CGPreflightScreenCaptureAccess())
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;swift /tmp/tcc-check.swift
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both functions only check, they never show a prompt. &lt;code&gt;false&lt;/code&gt; on either line explains most "it does nothing" reports. (Needs the Xcode command line tools for &lt;code&gt;swift&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;To watch macOS decide in real time while your agent tries to act:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;log stream &lt;span class="nt"&gt;--debug&lt;/span&gt; &lt;span class="nt"&gt;--predicate&lt;/span&gt; &lt;span class="s1"&gt;'subsystem == "com.apple.TCC"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The log shows which process TCC evaluated and whether it was allowed, which settles the "who is responsible" question without guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The toggle is on, and it still fails
&lt;/h2&gt;

&lt;p&gt;Three causes we keep running into:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The binary changed.&lt;/strong&gt; A grant is tied to the code signature. For an ad-hoc signed binary that means its exact hash, so every rebuild, or a package-manager upgrade that replaces the binary, silently invalidates the grant while the switch in Settings still shows "on". Fix: remove the entry with the minus button and add it again, or sign your own tools with a stable identity (a free Apple Development certificate is enough).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale entries.&lt;/strong&gt; Reset one service for one app and let it ask again:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   tccutil reset Accessibility com.apple.Terminal
   tccutil reset ScreenCapture com.apple.Terminal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the bundle id of whichever app hosts your agent.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A pending system prompt.&lt;/strong&gt; Recent macOS versions periodically ask you to reconfirm screen access for some apps. An unattended agent cannot answer that dialog, so if captures suddenly go blank after weeks of working, look at the screen for a waiting prompt first.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A short pre-flight before you blame the model
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Which app launches the agent? That app needs both grants.&lt;/li&gt;
&lt;li&gt;Fully quit and reopen it after granting.&lt;/li&gt;
&lt;li&gt;Run the Swift check from that app: both &lt;code&gt;true&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Screenshots empty -&amp;gt; Screen Recording. Clicks ignored -&amp;gt; Accessibility.&lt;/li&gt;
&lt;li&gt;Toggle on but failing after an update -&amp;gt; remove and re-add the entry.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why we care
&lt;/h2&gt;

&lt;p&gt;We build Auten, an MCP server that gives Claude Code, Codex, Cursor or any MCP client hands on a real screen: your computer and your Android phone (beta). On macOS, its installer runs a permissions setup step and &lt;code&gt;auten status&lt;/code&gt; shows what is connected and what is missing, because silent permission failures were the first thing that broke for us too.&lt;/p&gt;

&lt;p&gt;If you are hitting a TCC case not covered here, describe it in the comments. We collect these.&lt;/p&gt;

</description>
      <category>macos</category>
      <category>ai</category>
      <category>mcp</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I gave Claude Code hands: it drives my real Mac and Android phone</title>
      <dc:creator>Auten</dc:creator>
      <pubDate>Wed, 07 Oct 2026 21:07:32 +0000</pubDate>
      <link>https://dev.to/autenai/i-gave-claude-code-hands-it-drives-my-real-mac-and-android-phone-2e18</link>
      <guid>https://dev.to/autenai/i-gave-claude-code-hands-it-drives-my-real-mac-and-android-phone-2e18</guid>
      <description>&lt;p&gt;Most "AI agents" stop at text. They plan, they explain, they hand you a snippet to run yourself.&lt;br&gt;
Auten is an MCP server that closes that last gap: it gives your agent a real screen to work on —&lt;br&gt;
your computer (Mac, Windows, Linux) and your Android phone — so it clicks, types, and reads the&lt;br&gt;
screen like a person sitting at the machine. Even in apps with no API.&lt;/p&gt;

&lt;p&gt;I wired it into Claude Code. Here is what that actually looks like.&lt;/p&gt;
&lt;h2&gt;
  
  
  One line to install
&lt;/h2&gt;

&lt;p&gt;Auten ships as an MCP server on npm, so any MCP client can use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add auten &lt;span class="nt"&gt;--&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; @autenai/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it for Claude Code. Cursor, Codex, and other MCP clients use the same package with their&lt;br&gt;
own config. Nothing else to run on the machine — the piece on the device is thin (hands and eyes),&lt;br&gt;
the brain is your agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving it a goal, not a script
&lt;/h2&gt;

&lt;p&gt;The thing that surprised me: you do not script coordinates or write selectors. You give the agent a&lt;br&gt;
goal, and it reads the accessibility tree to find what it needs.&lt;/p&gt;

&lt;p&gt;A real task I ran: &lt;em&gt;"open System Settings and turn on Night Shift from sunset to sunrise."&lt;/em&gt; The agent&lt;br&gt;
listed the on-screen elements, clicked into Displays, found the Night Shift button by its label,&lt;br&gt;
opened the schedule dropdown, and picked the option. When I asked it to do the same on my phone —&lt;br&gt;
&lt;em&gt;"turn on battery saver"&lt;/em&gt; — it drove the Android Settings app the same way.&lt;/p&gt;

&lt;p&gt;No API exists for either of those. It worked because Auten operates the real UI, not an integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parts that make it usable, not just a demo
&lt;/h2&gt;

&lt;p&gt;A computer-use agent is only useful if it is repeatable, cheap, and safe. Three things do that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learns a task once, replays with no AI call.&lt;/strong&gt; Record a task once and Auten saves it as a skill
with parameters. Next time Auten replays it deterministically — seconds, no model tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-heals when the UI shifts.&lt;/strong&gt; When a button moves or a layout changes and a saved skill
breaks, it repairs the step from where it failed instead of dying.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets stay local.&lt;/strong&gt; Passwords and keys are typed on your machine through a local login path;
the agent never sees the value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where it is honest about limits
&lt;/h2&gt;

&lt;p&gt;This is early. It is genuinely good at UI navigation, form filling, and multi-step tasks across apps,&lt;br&gt;
and it is best when you let it confirm the result after each important step rather than firing blind.&lt;br&gt;
It is not magic — give it a clear goal, check the outcome, and it compounds: the second run of any&lt;br&gt;
task you teach it is deterministic.&lt;/p&gt;

&lt;p&gt;If you are building agents that should do real work instead of just chatting, this is the missing&lt;br&gt;
hand. Try it: &lt;a href="https://auten.ai/mcp" rel="noopener noreferrer"&gt;auten.ai/mcp&lt;/a&gt;&lt;/p&gt;

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