OpenOperator

One website, two interfaces: visual for people, structured for agents.

Inspiration

AI agents can already operate websites, but most sites make them work through interfaces designed only for people. The agent has to inspect text, infer the purpose of controls, guess selectors, move through several screens, and recover whenever the layout changes.

That is especially fragile in business operations. A single customer request can cross CRM, fulfillment, policy, billing, and support. The agent may understand the goal perfectly and still struggle to perform a reliable sequence of clicks.

WebMCP suggests a better model: the website can state its capabilities directly. Instead of asking an agent to reverse-engineer the UI, the site provides named, typed tools that invoke its real application logic.

OpenOperator explores that idea through one concrete promise:

The same live application should be naturally usable by a person and precisely operable by their agent.

What it does

OpenOperator is a multi-user small-business operating system with four connected modules:

  • CRM for customers, lifetime value, balances, and internal notes
  • Orders and shipping for line items, fulfillment, tracking, and delay detection
  • Support for customer cases and auditable resolutions
  • Billing for credits, refunds, and explicit human approval

Every signed-in user receives an isolated, durable workspace. There are no seeded customers, mock orders, or shared demo records. People and agents add real records through the visual interface or through WebMCP, and both see the same state immediately.

The page registers 32 WebMCP tools. ChatGPT can create, search, read, connect, update, and delete owned records; calculate whether a shipment is delayed; evaluate the compensation policy; request a credit or refund; add or edit a CRM note; and resolve a ticket.

OpenOperator deliberately withholds one capability from the agent: approving a financial action. Credits and refunds remain pending until the signed-in person approves or rejects them in the visual Billing interface.

The core demo

The main scenario begins with a natural request:

“A customer says their package hasn’t arrived. Figure out what happened and take care of them.”

ChatGPT can then:

  1. Search for the customer.
  2. Load a compact context containing recent orders, shipment state, tickets, notes, and financial history.
  3. Inspect the relevant order and tracking record.
  4. Determine that the shipment is late from its promised date.
  5. Read the compensation policy.
  6. Request an eligible customer credit of up to ₹2,000.
  7. Wait while the person reviews and approves the financial action.
  8. Add an internal CRM note.
  9. Resolve the support ticket with a saved summary and timestamp.

The person can watch the same dashboard update after every tool call. There is no second agent database, hidden automation service, or eventual synchronization step.

Why this is a strong fit for WebMCP

Without WebMCP, this workflow asks an agent to repeatedly interpret a changing visual interface across several sections. With WebMCP, OpenOperator exposes the application’s semantic boundaries directly:

  • get_customer_context returns the cross-domain context an agent actually needs.
  • track_shipment returns structured dates, status, delay state, and delay duration.
  • get_compensation_policy turns a business rule into an explicit read capability.
  • request_customer_credit creates a validated pending action instead of bypassing human judgment.
  • Mutating tools and UI forms invoke the same server dispatcher, so behavior cannot drift between interfaces.
  • Read-only and destructive annotations help the client understand each tool’s intent.

WebMCP is not an accessory in OpenOperator. It defines the product architecture: domain actions are designed once, authorized once, and then offered through the interface best suited to the current participant.

What people and agents can do together

The person does not need to manually collect order IDs, copy tracking details between tabs, interpret a policy, and enter the same resolution in multiple systems. The agent can gather context and prepare the work using structured calls.

The agent does not receive unlimited authority. The person remains in control of consequential financial decisions, can inspect the source-attributed activity history, and can delete any owned resource through the UI.

This produces a collaborative loop that is difficult to achieve with conventional browser automation:

Person states intent
        ↓
Agent gathers structured private context
        ↓
Agent performs safe record work
        ↓
Person reviews consequential decision
        ↓
Agent completes the operational follow-through

How we built it

OpenOperator is hosted as a ChatGPT Site using the Sites-provided TypeScript/Vinext application structure. The implementation combines:

  • Sign in with ChatGPT for authenticated identity
  • document.modelContext.registerTool() for page-owned WebMCP tools
  • A shared same-origin action API used by both the UI and WebMCP
  • Cloudflare D1 for durable relational storage
  • Drizzle schema definitions and a generated SQL migration
  • Server-side ownership, relationship, policy, and input validation

The UI requests /api/data to load the signed-in user’s workspace. Human forms and WebMCP tools send named actions to /api/actions. Both routes require the platform-provided authenticated user. The server dispatcher executes only a fixed action allowlist and binds the stable user ID to every database operation.

Human UI ──────────────┐
                      ├─ authenticated action API ─ validation/policy ─ owner-scoped D1
WebMCP page tools ─────┘                                           └─ activity trail

WebMCP implementation

The client registers 32 tools when document.modelContext.registerTool becomes available. Each definition contains:

  • A stable action-oriented name
  • A description optimized for agent discovery
  • A narrow JSON Schema with additionalProperties: false
  • Required fields and descriptions for every argument
  • readOnlyHint for searches and reads
  • destructiveHint for deletion tools
  • An execute function that calls the authenticated shared action endpoint

The tools cover:

CRM

create_customer, update_customer, search_customers, get_customer, get_customer_context, add_customer_note, update_customer_note, delete_customer_note, delete_customer

Orders and shipping

create_order, search_orders, get_order, update_order, update_order_item, delete_order_item, delete_order, upsert_shipment, track_shipment, delete_shipment, get_compensation_policy

Support

create_support_ticket, update_support_ticket, search_support_tickets, get_support_ticket, resolve_support_ticket, delete_support_ticket

Billing and activity

request_customer_credit, request_order_refund, update_financial_action, get_approval_status, delete_financial_action, delete_activity

The agent can request a credit or refund but cannot approve one. Approval is a separate human-only application action and is intentionally absent from the WebMCP registry.

Order status is explicit and validated across both interfaces: Processing, Confirmed, On hold, Shipped, Delivered, and Cancelled. Shipment status is modeled separately with Label created, In transit, Out for delivery, Delivered, Delivery exception, and Cancelled; fulfillment updates synchronize the parent order lifecycle. The WebMCP schemas expose both lists as enums, so agents can discover valid values before calling a tool.

Live data and multi-user isolation

Nine tables persist users, customers, orders, line items, shipments, tickets, notes, financial actions, and activities.

Every business row has an owner_id. Ownership is not accepted from tool arguments or the browser. The server derives it from the authenticated Sites request and applies it to every insert, search, lookup, update, and deletion.

This matters for agent safety: even if an agent supplies a valid record ID belonging to another account, the owner-scoped query returns no record. Relationship checks also prevent linking one customer to another customer’s order.

Trust, safety, and human authority

OpenOperator treats a structured tool as a doorway into application policy, not a shortcut around it.

  • Credits require a shipment delayed by at least 48 hours.
  • Refunds cannot exceed the stored order total.
  • Duplicate pending or completed delay credits are rejected.
  • Financial requests begin as Pending.
  • Only the signed-in person can approve or reject a request in Billing.
  • Every write records whether it came from a person or “ChatGPT via WebMCP.”
  • Delete tools are owner-scoped and marked destructive.
  • Cascading deletion maintains linked-data consistency.
  • Prepared statements and a fixed dispatcher prevent arbitrary SQL or code execution.

Challenges we ran into

Making WebMCP the architecture, not a feature

The most important design decision was to avoid separate “UI logic” and “agent logic.” Both paths had to call the same operations so that validation, authorization, side effects, and activity records stayed consistent.

Enforcing tenancy for agent-supplied IDs

Typed arguments improve reliability, but an ID is still untrusted input. Every entity helper and SQL predicate therefore combines the record ID with the authenticated owner ID. Connected records are checked again before mutation.

Preserving human authority

Financial actions needed to be useful to an agent without becoming silently executable. We modeled credits and refunds as durable requests with a visible pending state, then kept the final approval action out of WebMCP.

Testing an emerging browser capability

WebMCP availability depends on the testing environment. The app waits briefly for the browser API, reports registration state in the UI, and can be tested in Chrome with chrome://flags/#enable-webmcp-testing enabled.

Accomplishments we are proud of

  • A complete, coherent operations product rather than a single-tool proof of concept
  • 32 authenticated WebMCP tools across four connected business domains
  • One shared action layer for visual and agent interfaces
  • Durable D1 records
  • Server-enforced isolation for every signed-in user
  • Cross-domain context designed specifically for agent reasoning
  • Human-gated credits and refunds
  • Immediate UI refresh after agent mutations
  • Source-attributed audit activity
  • Full create and delete coverage plus validated editing for mutable business records in both UI and WebMCP
  • Detailed, linked record views across every business resource type
  • No embedded LLM, paid AI API, or external agent service

What we learned

The most useful WebMCP tools are not always one-to-one copies of buttons. get_customer_context is valuable because it packages the context needed for a real operational decision, while smaller write tools keep side effects narrow and auditable.

We also learned that agent-native design makes authorization more important, not less important. Structured calls remove ambiguity at the interface layer, but the application still has to validate identity, ownership, relationships, policy, and consequences on the server.

Finally, the best human-agent experience is not full autonomy. It is a thoughtful allocation of work: let the agent handle navigation-like effort, context gathering, and routine mutations, while preserving human control where judgment and financial impact matter.

What’s next

  • Organization workspaces and role-based access
  • Team invitations and granular approval roles
  • CSV imports and exports
  • Real carrier and fulfillment integrations
  • Configurable compensation policies
  • Notifications for pending approvals and delayed shipments
  • Richer tool result schemas and automated conformance tests
  • Cross-site workflows with other WebMCP-enabled applications

Built with

ChatGPT Sites, WebMCP, Sign in with ChatGPT, TypeScript, React/Vinext, Cloudflare D1, Drizzle ORM, HTML, and CSS.

Built With

  • chatgpt-sites
  • codex
  • web-mcp
Share this project:

Updates

Submission history