<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>MCP on Trevor's Blog</title><link>http://mings.in/en/tags/mcp/</link><description>Recent content in MCP on Trevor's Blog</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Mon, 02 Nov 2026 10:50:00 +0800</lastBuildDate><atom:link href="http://mings.in/en/tags/mcp/index.xml" rel="self" type="application/rss+xml"/><item><title>Google Turned Every App Into an MCP Server on Your Phone</title><link>http://mings.in/en/posts/appfunctions/</link><pubDate>Mon, 02 Nov 2026 10:50:00 +0800</pubDate><guid>http://mings.in/en/posts/appfunctions/</guid><description>On Android 16 every app can declare functions like an MCP server. I sent a message from outside my own app with zero screen touches, and dug out the internal|privileged permission gate.</description><content:encoded><![CDATA[<p>MCP spent this year solving the server side: how an agent discovers tools, calls them, and gets structured results back.</p>
<p>On the phone it has been a blank. Your app holds a pile of capabilities, search, send a message, create an event, and an agent can reach none of them. It falls back to screenshots, taps a guessed coordinate, takes another screenshot.</p>
<p>In February Google put something called AppFunctions on the Android Developers Blog. On the twenty-first of last month its SDK shipped 1.0.0-beta01.</p>
<p>I got it running on an emulator, including letting an &ldquo;agent&rdquo; send a message straight through my app&rsquo;s UI.</p>
<h2 id="the-official-framing-is-blunt">The official framing is blunt</h2>
<p>That post was written by Matthew McCullough, VP of Product Management for Android Developer. His wording: AppFunctions let apps declare what they can do the way backends declare capabilities through an MCP cloud server, except execution happens on device.</p>
<p>The same paragraph mentions WebMCP, saying the two are part of one line, one in the browser, one in the system.</p>
<p>So the positioning is clear. This is not another custom intent protocol, it is deliberately shaped like MCP. A detail from the October beta confirms it: they renamed the metadata field from <code>description</code> to <code>instructions</code>, and the stated reason was aligning with MCP naming conventions.</p>
<h2 id="one-appfunction-takes-four-steps">One AppFunction takes four steps</h2>
<p>First, you write a service class in your app that extends <code>AppFunctionService</code>, annotate methods with <code>@AppFunctionDeclaration</code>, and the KDoc becomes the description the model reads. Second, an annotation processor generates an XML at build time carrying every parameter, type, enum constraint, and return shape.</p>
<p>Third, that XML goes into the APK&rsquo;s assets directory and Android reads it to register functions in a global table.</p>
<p>Fourth, an authorized caller gets <code>AppFunctionManager</code>, checks whether the function is enabled, and calls it.</p>
<p><img alt="The four steps from declaration to execution" loading="lazy" src="/images/appfunctions/fig1.png"></p>
<p>I went digging inside the APK and the XML is really there. The sample&rsquo;s <code>assets/chat_app_function_service.xml</code> is twenty-two kilobytes, six functions, every parameter description pulled out of KDoc.</p>
<h2 id="local-test-from-compile-to-an-actual-sent-message">Local test: from compile to an actual sent message</h2>
<p>The sample is ChatApp from the official <code>android/appfunctions</code> repo, Compose plus Hilt, building into a 14.8 MB debug package. Installed on the emulator, it registers six functions on first launch: search contacts, send a message, place a call, search messages, fetch send details, change the wallpaper.</p>
<p>The device listing looks like this, and the same emulator has system apps doing it on their own:</p>
<ul>
<li><code>com.example.chatapp</code>, six, all business functions of that chat app</li>
<li><code>com.android.settings</code>, six, all named <code>getXxxDeviceState</code>, reading battery, storage, notifications</li>
<li><code>com.google.android.permissioncontroller</code>, one, reading permission state</li>
<li><code>com.google.android.apps.wellbeing</code>, one</li>
</ul>
<p>System apps are already using this thing themselves. That is more convincing than any documentation.</p>
<h2 id="one-call-and-what-comes-back">One call, and what comes back</h2>
<p>I called it over ADB, straight past the UI, imitating what an agent would do. Following the function&rsquo;s own instruction that you must search contacts first to get an endpointValue, I searched a contact:</p>
<pre tabindex="0"><code>androidAppfunctionsReturnValue:
  contactDisplayName: Alice Smith
  endpointValue: 1
  contactType: INDIVIDUAL
  endpointDisplayName: alice@example.com
</code></pre><p>With that <code>1</code> in hand, step two sends the message, taking the id plus the body. It returns <code>Message sent to: Alice Smith.</code></p>
<p>Then I opened the app and looked. The message I had passed in, which said in Chinese &ldquo;this one was sent by an agent through AppFunction&rdquo;, was sitting in Alice&rsquo;s conversation.</p>
<p>No screen interaction at any point. No screenshot, no coordinates.</p>
<p><img alt="Two ADB calls on the left, the app one second later on the right" loading="lazy" src="/images/appfunctions/fig3.png"></p>
<h2 id="the-one-thing-to-remember-who-gets-to-call">The one thing to remember: who gets to call</h2>
<p>This is the part I most want you to notice.</p>
<p>For another app to discover and execute your AppFunction, the caller must hold <code>EXECUTE_APP_FUNCTIONS</code>. I pulled the permission definition on the emulator:</p>
<blockquote>
<p>Permission [android.permission.EXECUTE_APP_FUNCTIONS]
sourcePackage=android
prot=internal|privileged</p>
</blockquote>
<p>Internal plus privileged means an ordinary app cannot get it, only the system signature or apps on a privileged allowlist have it. Today that means system assistants like Gemini.</p>
<p>Which makes both camps right. &ldquo;Android apps can finally talk to AI agents&rdquo; is true. &ldquo;This is not open agent access&rdquo; is also true. The functions are publicly declared, and the door is locked.</p>
<p><img alt="The function registry on the emulator, and the internal|privileged gate" loading="lazy" src="/images/appfunctions/fig2.png"></p>
<h2 id="it-is-already-turning-into-policy">It is already turning into policy</h2>
<p>The other thread in the docs is AEP, Google Play&rsquo;s Apps Experience Program.</p>
<p>It carries an explicit guideline called Android MCP, requiring participating apps to implement at least one relevant scenario with AppFunctions and pass its required tests. The scope is spelled out: messaging, notes, calendar, tasks, health, shopping.</p>
<p>Enforcement is March 1, 2027, or three months after self-service registration opens, whichever is later.</p>
<p>In other words, today it is an experimental API, next year it is a Play compliance item. That cadence is worth seeing early.</p>
<h2 id="there-is-also-a-zero-code-path-worth-seeing-side-by-side">There is also a zero-code path, worth seeing side by side</h2>
<p>The same blog post put a second route on the table: UI automation.</p>
<p>The platform operates your interface itself, so the developer&rsquo;s workload is zero. Users long-press the power button on a Galaxy S26 or some Pixel 10 devices and hand a multi-step task to Gemini, starting in the US and Korea with food delivery, groceries, and ride hailing.</p>
<p>Users can watch progress, take over at any point, and get a prompt before sensitive actions like payment.</p>
<p>Side by side, the tradeoff gets clear. AppFunctions gives you control: you decide what to expose, how to describe it, how failures come back. UI automation gives you reach, but you have no part in the definition, and the agent can only tap your UI like a person would.</p>
<p>Google says Android 17 will broaden both. My read is that serious product teams will treat the first as home turf and the second as a fallback.</p>
<h2 id="what-is-not-here-yet-stated-plainly">What is not here yet, stated plainly</h2>
<p>The SDK is beta, not final. The docs mark it experimental preview, the API will move, and October moved a fair amount.</p>
<p>The Gemini integration is a private preview open to trusted testers. The public case that actually works is Samsung Gallery, on the Galaxy S26, expanding to One UI 8.5 soon.</p>
<p>And one honest note: I tried disabling a function over ADB to verify the claim that users can turn them off, and the command timed out after thirty seconds with the function state unchanged. I did not verify that, so it does not belong in the conclusions.</p>
<p><img alt="Eight months from blog post to Play requirement, and what I could and could not verify" loading="lazy" src="/images/appfunctions/fig4.png"></p>
<h2 id="my-read">My read</h2>
<p>What makes this different from the usual &ldquo;AI integration APIs&rdquo; is the shape.</p>
<p>Before, each vendor invented an intent and agents had to adapt one by one. This one is cut from the MCP mold: self-describing, discoverable, with enum constraints, required fields, and error codes.</p>
<p>For people who write apps, the real change is not this year. It arrives when that policy takes effect next year, and the question becomes whether your app can explain its own core capabilities.</p>
<p>A well thought out function declaration does more for an agent than ten pages of help docs.</p>
<p>If your app were only allowed to expose three functions to a system assistant, which three would you pick?</p>
<p>Tell me in the comments. I will pick a few interesting ones and take them apart next time.</p>
]]></content:encoded></item></channel></rss>