Skip to main content
Glama

OpenDoor

Make your existing website agent-ready. OpenDoor exposes your site's features to Claude, ChatGPT and custom AI agents through the Model Context Protocol (MCP). Users stay in control: they approve each agent, choose what it may do, set limits, and can revoke it at any time. Every call is logged.

You keep your app, your login and your business logic. You describe what agents may do, and OpenDoor handles the rest:

You write

OpenDoor provides

A list of actions that call your existing functions

An MCP server at /mcp (Streamable HTTP) and a matching REST API at /agent/v1/actions

Scopes (permissions) and optional limits

OAuth 2.1 for agents: discovery, dynamic client registration, PKCE, refresh rotation

getUser(req) from your existing session

A consent screen, plus a "Connected agents" dashboard with tokens, permissions, revoke and an activity log

Per-call permission checks, input validation, confirmation for risky steps, rate limits, an audit log, and llms.txt

Quick start (Express)

npm install @abhishekvardanbotta/opendoor
import { openDoor, action, z } from "@abhishekvardanbotta/opendoor";

const door = openDoor({
  name: "Acme Store",
  db: pool,                                    // pg Pool or PGlite; OpenDoor adds its own opendoor_* tables
  getUser: (req) => req.user,                  // your existing sign-in → { id, name?, email? } or null
  loginUrl: (next) => `/login?next=${encodeURIComponent(next)}`,
  scopes: {
    "orders:read": { label: "View your orders", description: "Order history and status." },
    "checkout:create": { label: "Place orders", description: "Buy with your saved card.", risk: "high" },
  },
  limits: { spend: { label: "Per-order spending limit", scope: "checkout:create", format: "usd_cents" } },
  actions: [
    action({
      name: "orders.list", scope: "orders:read", readOnly: true,
      description: "List the user's recent orders.",
      run: (ctx) => orders.listForUser(ctx.user.id),
    }),
    action({
      name: "checkout.create", scope: "checkout:create", confirm: true,
      description: "Buy everything in the cart.",
      input: z.object({ coupon: z.string().optional() }),
      run: async (ctx, { coupon }) => {
        const total = await cart.total(ctx.user.id, coupon);
        ctx.enforceLimit("spend", total);        // the user's per-agent cap
        return checkout.place(ctx.user.id, { coupon });
      },
    }),
  ],
});

app.use(door.router);   // after your session middleware

Users connect agents at /opendoor. In Claude or ChatGPT, adding https://your-site.com/mcp as a custom connector sends them through your consent screen.

Check the setup:

npx @abhishekvardanbotta/opendoor check https://your-site.com

Related MCP server: SandBase

Concepts

Actions are the things an agent may do. Each has a dotted name (orders.get), one required scope, a zod input schema, and a run(ctx, input) that calls your existing code as ctx.user. Optional flags:

  • readOnly, destructive and idempotent become hints for MCP clients.

  • confirm: true requires the agent to pass confirm: true, after asking the user.

  • summarize(result, input) sets the one-line text shown in the activity log.

Throw an error with a string code and a status below 500 to return a clean error to the agent. Any other error becomes INTERNAL_ERROR, and its details stay on your server.

Scopes are the permissions users grant, with a label, a description and risk: "low" | "medium" | "high". High-risk scopes are unticked by default on consent screens. Agents only see tools for the scopes they hold, and every call is checked again.

Limits are numeric caps the user sets for each agent, such as a spending limit, a number of messages per day, or a maximum discount. Enforce them inside your action with ctx.enforceLimit(key, amount), or read ctx.limits[key].

Grants are one user's approval of one agent. Scopes and limits are read on every request, so edits and revocations apply immediately. Agents connect by:

  • OAuth. Hosted assistants such as Claude, ChatGPT and Cursor register themselves; their client_id becomes the Agent ID.

  • Token. For scripts and custom agents, the user registers an Agent ID and gets a bearer token. Only its SHA-256 hash is stored.

Options

Option

Default

name

required

Shown on consent screens and to agents

db

required

Anything with query(text, params) → { rows }

getUser(req)

required

Current signed-in user, or null

scopes, actions

required

See above

findUser(id)

—

Fills in ctx.user (name, email) for agent calls

loginUrl(next)

—

Where the built-in pages send signed-out users

limits

{}

{ key: { label, scope, format: "usd_cents" | "number" } }

publicUrl

taken from the request

Public HTTPS origin, a string or (req) => string

consentPath, dashboardPath, appUrl

built-in pages

Use your own UI on top of the JSON API

pages

true

false disables the built-in pages

basePath

/opendoor

Where the pages and /api live

toolNames

"underscore"

MCP names orders_get. Claude and ChatGPT reject dots; "dotted" keeps them

rateLimit

{ perMinute: 60 }

Per agent connection

accessTokenTtl, refreshTokenTtl

1 h, 30 d

OAuth token lifetimes, in seconds

instructions

generated

MCP server instructions for agents

Build your own UI. {basePath}/api is a JSON API covering meta, grants, connect, grants/:id (PATCH), grants/:id/token, grants/:id/revoke, activity, oauth/request and oauth/consent. It uses your session through getUser, and writes must send JSON. AIShop (live at https://aishop-alpha.vercel.app) uses its own React screens on top of this API.

Security model

  • Tokens: 256-bit random tokens, stored as hashes. OAuth codes are single use, expire after 10 minutes and require PKCE (S256 only). Refresh tokens rotate on every use, and loopback-aware redirect URIs must match exactly.

  • Permissions: checked on every call against the live grant. An agent can't exceed what the user approved, and the user can narrow what the agent asked for but never widen it. An optional X-Agent-Id header must match the token's agent.

  • Consent pages: framing is denied, everything an agent supplies (such as its name) is escaped, and management writes must be JSON, which works as CSRF protection alongside your cookie's SameSite setting.

  • Audit log: records the agent, action, transport, required and granted scopes, redacted input, outcome and IP, plus authorization events (connect, authorize, deny, update, rotate, revoke).

  • Limits of this version: rate limits are kept in memory per process. OpenDoor trusts your getUser, so protect your sessions as usual.

Coding agents

skill/SKILL.md teaches Claude Code and similar coding agents to add OpenDoor to an existing codebase: survey the app, propose an action and scope map, wire it up, and verify it.

Examples

Requires Node 20+, PostgreSQL (or PGlite), Express 4.18+ or 5.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Provides AI agents with 220+ tools for building websites, sending email, managing contacts, invoicing, databases, automation, and more through a single secure connection. Features hardware-bound authentication and works with Claude Desktop, Claude Code, Cursor, and other MCP-compatible clients.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI assistants to discover and invoke 2,000+ models and APIs—including web search, social media, scraping, image/video generation, and audio—through a single local MCP bridge using OAuth, with no per-API keys.
      133 npm
      186
      Apache 2.0
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables exposing product capabilities to ChatGPT, Claude, and other MCP clients via a stateless Streamable HTTP endpoint with OAuth resource binding and structured-output helpers.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables existing apps to expose their users and data to external AI agents via MCP with OAuth 2.1 authentication and scoped tools.
      51 npm
      MIT