We've built the fastest way to create a one-click remote MCP server by mistake Appwrite deployed a remote MCP server for its open-source email client to production in under a minute after asking a coding agent to build one, with Claude connected and triaging the inbox a minute later. The server required no manual client ID, API key or config-file setup because the OAuth 2.1 authorization server, protected resource metadata (RFC 9728), dynamic client registration (RFC 7591) and sign-in/consent screen were already part of the Appwrite project, which the company had built to test unshipped email triggers for Appwrite Functions. Appwrite argues the bottleneck for remote MCP servers is that hosting, data and auth normally live at different vendors, not any single specification. We've built the fastest way to create a one-click remote MCP server by mistake We built an email client on Appwrite to test a new feature, then asked an agent for a remote MCP server with OAuth 2.1. It was in production in under a minute. We were not trying to build an MCP platform. We were testing a feature that hasn't shipped yet: email triggers for Appwrite Functions , where an incoming email executes your function the same way an HTTP request or a cron schedule does. To test it honestly, we needed something that receives real mail, so we built an email client. It got out of hand in the good way. Inbox, threads, full-text search, attachments, labels, rules, snooze, send later, vacation replies, two-factor sign-in, and a mobile layout. All of it runs on one Appwrite project, and it is open source https://github.com/appwrite/email . Then we did what we now do with everything we build: we pointed our agents at it. We asked a coding agent to give the mail app a remote MCP server so Claude could read and triage the inbox. Less than a minute later, the MCP server was deployed to production. A minute after that, Claude was connected and archiving newsletters. The connection took one click, one sign-in we already had, and one consent screen. Nobody copied a client ID, generated an API key, or edited a config file. The mail app's landing page uses that exchange as its example. One sentence from the user turns into four tool calls: find the unread mail, archive the newsletters, read the thread, and reply in it. The agent writing code quickly was not the surprise. Agents write code quickly. The surprise was that there was nothing left to set up . Every piece a production remote MCP server needs was already sitting in the project, wired to everything else. What a remote MCP server actually needs what-a-remote-mcp-server-actually-needs A local MCP server is a process on your laptop that trusts whoever started it. A remote MCP server is a public service that strangers' AI tools call on behalf of your users, so the MCP authorization specification https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization puts a full OAuth 2.1 deployment in front of it. To ship one, you need: - A public HTTPS endpoint that speaks MCP over Streamable HTTP. - Protected resource metadata RFC 9728 https://datatracker.ietf.org/doc/html/rfc9728 , plus a 401 with a WWW-Authenticate header pointing to it, so clients can discover who issues tokens for you. - An OAuth 2.1 authorization server with PKCE, discovery metadata RFC 8414 https://datatracker.ietf.org/doc/html/rfc8414 , and resource indicators RFC 8707 https://datatracker.ietf.org/doc/html/rfc8707 so a token minted for your MCP server is useless anywhere else. - A way for clients nobody registered to introduce themselves , through dynamic client registration RFC 7591 https://datatracker.ietf.org/doc/html/rfc7591 or client ID metadata documents. Thousands of AI tools exist, and none of their developers will fill in a form on your developer portal first. - A sign-in and consent screen inside your product, for your users, in your design. - Token verification and scope checks on every call, followed by data access as that user and only that user. - Revocation , so users can see what they connected and take it back. None of these pieces is exotic. Each one is a known specification with good libraries. What makes remote MCP slow to ship is not any single piece. It is that the pieces normally live at different companies . Why hosting, data, and auth rarely live together why-hosting-data-and-auth-rarely-live-together Look at how most products are deployed today. The frontend sits on a hosting provider. The data sits on a database provider. Identity sits on an auth provider. Each vendor is very good at its slice, and each one draws its product boundary exactly where its slice ends. Remote MCP cuts straight across those boundaries. The endpoint is a hosting problem. The token is an identity problem. The tools are a data problem. And the consent screen is all three: it is a page you host, for a user someone else authenticates, approving access to data a third party stores. Stitched across vendors, the work moves into the seams: - Your MCP endpoint has to trust tokens issued by your auth vendor, so you configure issuers, audiences, and key rotation between two dashboards. - The sub in that token is an ID in the auth vendor's system. Your rows are owned by an ID in your database. You write the mapping and keep it in sync. - The consent screen has to run on your domain, call the auth vendor's grant APIs, and read your database to explain what is being requested. - Redirect URIs, CORS, and secrets now span three products and three sets of environment variables. To be fair, several auth providers now ship MCP authorization, and it works. But their tokens still prove who the user is in one system while the data lives in another, and the bridge between the two is still yours to write and operate. In an Appwrite project, there is no bridge. The user who signs in to the mail app, the sub in the access token Claude presents, and the owner on the database rows are the same user ID in the same project . The consent page is a route on the same Site https://appwrite.io/docs/products/sites . The MCP endpoint runs in the same project, either as a Function https://appwrite.io/docs/products/functions or as a server route on that same Site, reading the same tables with the same permission model. That is not a clever integration. It is what happens when hosting, data, and auth share one roof, and it only became an MCP story when we released the OAuth2 server https://appwrite.io/blog/post/announcing-oauth2-server , which lets an Appwrite project act as an OAuth 2.1 and OpenID Connect provider. How the mail app's MCP server works how-the-mail-apps-mcp-server-works Here is the whole app, one row per Appwrite product: | Product | What the mail app uses it for | |---|---| | Auth | Email and password, email codes, TOTP two-factor, sessions, and the OAuth2 server that signs in MCP and API clients | | Functions | inbox the email trigger , api sending and account actions , public REST API and remote MCP server , maintenance a cron for send-later and snooze | | Databases | Mailboxes, messages, drafts, contacts, labels, and API keys in TablesDB, with row-level permissions and a full-text index | | Storage | An encrypted attachments bucket with antivirus scanning | | Messaging | Outbound mail to external addresses | | Realtime | New mail and state changes synced across tabs | | Sites | The web app, including the OAuth consent screen at /oauth/consent | The MCP server is the public function, served from its own domain. A Function is one option, not a requirement. An MCP server is a handful of HTTP routes, so it runs just as well as a server route on an Appwrite Site https://appwrite.io/docs/products/sites rendered with SSR, next to the consent page and on the app's own domain. We used a Function so the MCP server deploys and scales on its own. Pick a Site route when you want the app and its MCP server to ship as one deployment. Everything below works the same either way. In the same change, the agent added the consent route to the Site and a developer page that gives users the server URL, an install path for each major client, and the scope every tool needs: That page is the entire setup guide a user needs. Here is every step of the handshake behind it, as curl sees it. The examples use a placeholder domain. The 401 that starts everything the-401-that-starts-everything An MCP client that calls the server without a token gets a 401 , and the WWW-Authenticate header tells it where to look next: curl -i -X POST https://mail-api.example.com/mcp \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' HTTP/2 401 www-authenticate: Bearer resource metadata="https://mail-api.example.com/.well-known/oauth-protected-resource/mcp" x-appwrite-traffic-type: function The client finds the authorization server the-client-finds-the-authorization-server The protected resource metadata names the project's OAuth2 server and the scopes this server understands: { "resource": "https://mail-api.example.com/mcp", "authorization servers": "https://fra.cloud.appwrite.io/v1/oauth2/