I gave an AI agent the keys to a live production app: here's the MCP setup GoodBarber, an app platform, has deployed a hosted remote MCP server that lets AI agents operate live production apps, including scheduling push notifications and publishing articles. The setup uses OAuth for authentication and returns policy blocks on every write to enforce verification, with the server card documenting the full tool inventory. The engineer behind the project shared the hands-on configuration for clients like Claude Code, ChatGPT, and Codex. AI agents are good at writing code. What they mostly cannot do is operate the software you already run in production: publish the article, schedule the push, fulfill the order. Not because the models are incapable, but because most production apps expose no structured surface an agent can act on. MCP fixes exactly that. This post is the hands-on setup I use to let an agent operate a live mobile app: real endpoint, real tool calls, real payloads, and the gotchas I hit. Disclosure up front: I run engineering at GoodBarber, an app platform, so the production app in this post runs on our MCP server. The patterns transfer to any remote MCP server you point an agent at. The server is a hosted remote MCP server. No npx , nothing local to run: https://mcp.goodbarber.dev/mcp/sse The /sse path is historical; the server answers both SSE and Streamable HTTP, so every current client works. Claude Code: claude mcp add --transport sse goodbarber https://mcp.goodbarber.dev/mcp/sse or in .mcp.json : { "mcpServers": { "goodbarber": { "type": "sse", "url": "https://mcp.goodbarber.dev/mcp/sse" } } } Claude claude.ai : Settings, then Connectors, then add a custom connector with that URL. ChatGPT: Settings, then Apps & Connectors, enable Developer mode, create a connector with the same URL. Write actions worked on a free account when I tested it; OpenAI's docs gate some of this by plan, so verify on yours. Codex: add a custom MCP server, transport Streamable HTTP, leave the bearer token field empty. Saving opens the OAuth flow. The first tool use triggers OAuth in the browser: you sign in with the app's account, and the session is scoped to that single app. No API key to paste anywhere. That scoping does a lot of security work later. After OAuth, the client pulls the tool list. What the agent sees is not "the API": it is an operations menu, namespaced by domain. The cms tools cover articles, events, and media. The shop tools cover products, variants, orders, and promo codes. The classic tools cover push, analytics, and memberships. The full inventory is public in the server card, which is the file to read before writing any client code: https://mcp.goodbarber.dev/.well-known/mcp/server-card.json Push is the scariest operation to hand an agent a sent push has no undo , which makes it the best test of a server's design. Me, in the chat: Schedule a push for 6 PM tonight: "Doors open at 7. First 50 people get the poster." The agent calls classic create push broadcast : { "message": "Doors open at 7. First 50 people get the poster.", "send": "at", "send at": "2026-07-29T18:00+02:00" } Three details in this schema are worth noticing: message is capped at 255 characters server-side, so the agent gets a hard error instead of a silently truncated push. send is an enum, now or at ; scheduling requires the timezone-aware send at , and the tool handles the UTC conversion. The agent does no date math. action type is one of open app , external link , or section . "Open the tickets section" resolves to a real section id, not a guessed deeplink.The result comes back confirming the scheduled send, along with something rarer: a policy block. Every write on this server returns mcp policy.verification required: true . The server's own guidance tells the agent to read back what it just wrote before declaring success. There is even a meta tool for this: meta get tool plan takes a tool name and returns the recommended discover, call, verify sequence plus the failure policy. Agents follow instructions embedded in tool results remarkably well; putting that discipline server-side beats hoping every client prompt remembers it. Publish an article CMS . cms create article wants a title and category ids, and category ids come from cms list cms sections first. Discover, then write: { "title": "Matchday guide: what to know before Saturday", "categories": 4821 , "status": "stock", "publishedDate": "2026-08-01T08:00:00+02:00" } status is published , draft , or stock ; a future publishedDate requires stock , which is the scheduled state. Body content is its own resource: cms create article paragraph , one call per paragraph, with cms reorder article paragraphs when the agent restructures. There is also an accessTier field free or premium that hooks straight into the app's paywall. Add a product and a variant shop . shop create product first: { "title": "Home Kit Hoodie 2026", "status": "DRAFT", "collections": 312 } then shop create variant : { "product id": 88410, "price": "49.00000", "stock": 120, "sku": "HK26-M", "option values": { "option id": 17, "value": "M" } } Two things I like here. price is a decimal string, not a float: whoever wrote this schema has met floating-point money. And the variant model is strict: all variants of a product must share the exact same set of option id s, so introducing a Size option on one variant forces you to define it on all of them. That is a real invariant of the commerce domain, enforced at the tool layer. A raw database connection would let your agent violate it silently. Look up and update an order fulfillment . shop list orders filters by status and date range. shop update order shipping moves an order along a one-way state machine, PENDING → FULFILLED → DELIVERED, with optional tracking: { "order id": 55231, "status": "FULFILLED", "shipping tracking num": "6A0301234567", "shipping tracking url": "https://tracking.example.com/6A0301234567" } The status enum only contains FULFILLED and DELIVERED . You cannot un-deliver an order through this surface, however confused the agent gets. Pull the numbers analytics . classic list downloads and classic list page views take plain ISO date ranges and return aggregates. The stats family is read-only by construction; there is nothing to break. My standing Monday ask is one sentence: last week's downloads and page views versus the previous week, flag anything odd. This is what I would look at before connecting an agent to anything in production: shop namespace is simply absent; push not configured, no push tools. The agent cannot call what it cannot see. Corollary if you write client code: never hardcode the tool list, read it at connect time or from the server card. mcp policy block rides on every write result.On top of the server, there is an open-source repo of 44 Skills: markdown recipes in the Claude Skills format, one per workflow create a product with variants, schedule a push campaign, process the morning's orders, and so on . They encode the discover-then-write sequences above so the agent does not rediscover them every session: https://github.com/goodbarber/goodbarber-skills The terms allow rebranding and redistribution; they were written for resellers. The server itself is proprietary. The recipes are the open part. Things I would want to know before recommending this to another engineer: shop create product calls. Bulk import stays a back-office job; the agent shines on the daily delta, not the migration. cms list cms sections , shop list products ; meta get tool plan returns exactly that sequence per tool. send: "at" rather than now , so there is always a review window between the ask and the broadcast.Everyone is racing to make agents build software. The quieter and, I think, more useful shift is agents operating the software you already have. Building is a one-time event. Operating is every day. If you want to poke at a live implementation: the server card https://mcp.goodbarber.dev/.well-known/mcp/server-card.json is public, the Skills repo https://github.com/goodbarber/goodbarber-skills is open, and the non-dev version of this story lives at goodbarber.com/mcp https://www.goodbarber.com/mcp/ .