I almost replaced Lovable with a $5 VPS, Dokploy and one MCP gateway A developer built Junctio, an open-source MCP gateway that runs the @dokploy/mcp server as a stdio process and exposes its tools over Streamable HTTP with a built-in OAuth authorization server, allowing agents like Claude to deploy sites to a self-hosted Dokploy VPS. The gateway keeps the Dokploy API key server-side, logs every tool call without storing request bodies, and trims the official server's roughly 600 tools down to about 20 curated deployment actions to reduce context and wrong tool calls. It is packaged as a Docker Compose service that joins Dokploy's Traefik network, positioning it as a cheaper alternative to hosted site builders such as Lovable. Lovable is nice. You describe a site, an agent writes it, you click publish. It also costs $25–50 a month for the tiers that are actually usable, the code lives on their side, and the agent only knows how to do one thing. I already pay for Claude. I already have a VPS with Dokploy on it. The missing piece was a way for the agent to deploy, and gateways for that already exist — MetaMCP, IBM’s ContextForge, a few others. None of them gave me the combination I wanted: multiple runtimes, one container, an OAuth server of its own, and a UI I don’t mind looking at. So I wrote one. @dokploy/mcp server, running inside Junctio as a stdio process The client talks to one URL. Junctio runs the Dokploy MCP server, keeps the Dokploy API key, and exposes the tools over Streamable HTTP with OAuth. php Schema AI Agent App --OAuth-- Junctio --stdio-- @dokploy/mcp -- Dokploy API API key lives here The prompt is something like: “Build a landing page for X, push it to my GitHub, deploy it on Dokploy under x.example.com”. The agent writes the page, creates the app in Dokploy, points it at the repo, adds the domain and triggers the build. A few minutes end to end, most of it the Docker build. Every tool call goes through the gateway and lands in the request log: method, tool, upstream, status, timing. Bodies are not stored: arguments and results can carry anything your agent touched, and a log full of that is a leak waiting to happen. npx @dokploy/mcp in the client claude.ai has no stdio. Claude Desktop and Claude Code will happily spawn a local stdio server; claude.ai in the browser and ChatGPT connectors will not, and they can’t send an API key header either. A custom connector means a remote MCP server with a real OAuth authorization server behind it: RFC 8414 metadata, dynamic client registration, PKCE, a consent screen. Junctio has that built in. Add the connector URL, approve at the consent screen with the admin password, done. No Cloudflare Worker wrapper, no separate auth service. ~600 tools is too many. The official Dokploy MCP server exposes the whole API, upwards of 600 tools at the moment.. That’s a lot of context, and the agent picks the wrong application- call half the time. In Junctio I put the server in a namespace and hid everything except about 20: create project, create application, set source, set domain, deploy, read logs. Plus a short instruction block on the namespace “never delete, ask before creating databases” . The client only sees the small set. The key stays on the server. With the stdio setup every client machine has the Dokploy API key in a mcp.json. With the gateway there is one key, in one place, encrypted at rest. Each client gets its own OAuth client or API key and I can revoke it from the UI. services: junctio: image: ghcr.io/k2so-dev/junctio:latest pull policy: always restart: unless-stopped environment: JUNCTIO SECRET: ${JUNCTIO SECRET:?set JUNCTIO SECRET, e.g. openssl rand -hex 32} JUNCTIO BASE URL: ${JUNCTIO BASE URL:?set JUNCTIO BASE URL, e.g. https://mcp.example.com} JUNCTIO TRUST PROXY: "true" JUNCTIO ADMIN TOKEN: ${JUNCTIO ADMIN TOKEN:-} LOG LEVEL: ${LOG LEVEL:-info} volumes: - junctio-data:/data - junctio-cache:/cache tmpfs: - /tmp read only: true networks: - dokploy-network networks: dokploy-network: external: true volumes: junctio-data: junctio-cache: Add it in Dokploy as a Compose service with the Raw provider. No published ports: Dokploy routes through its own Traefik, so the service joins dokploy-network and gets its domain on the Domains tab, pointed at container port 3000 with Let’s Encrypt on. junctio-cache holds the npx and uvx package caches — throwaway, but without it every cold start is slow. Outside Dokploy, put Caddy in front instead; either way OAuth needs TLS, while an API-key endpoint works fine over plain http on localhost. Then in the UI: add server runtime npx or bunx package @dokploy/mcp env DOKPLOY URL , DOKPLOY API KEY . Create a namespace, hide tools, create an endpoint with OAuth on. Paste the URL into your agent app as a custom connector. Full walkthrough: https://junctio.pages.dev/use-cases/claude-ai-connector/ https://junctio.pages.dev/use-cases/claude-ai-connector/ It is not Lovable. No live preview, no visual editor, no “click this button and change its color”. You get a chat and a deploy. If you want to iterate on UI visually, this is worse. It is also not safer by default. You are giving an agent write access to your deployment platform. I hid the destructive tools and the agent still once tried to redeploy the wrong app because two had similar names. Keep a namespace per project, keep the tool set small, read the logs. Junctio can also run a scheduled vulnerability check on the servers it launches through npx, bunx, node or uvx, which matters when you install packages from npm with one click. It’s off by default, it’s advisory data rather than analysis, and container images, custom commands and remote servers are marked “not audited” because the gateway can’t tell what’s inside them: VPS $5 a month. Dokploy free. Junctio free, MIT. AI subscription I already had. Memory: Junctio idles at about 60 MB. A running stdio server adds its own footprint, @dokploy/mcp is another 60 MB or so. Idle servers get stopped after a timeout and restarted on the next call, so most of the time you’re back at 60 MB. It’s TypeScript on Bun, not Go, and I’m fine with that. I can maintain it. The same trick works with anything that has an OpenAPI spec: run an OpenAPI-to-MCP server inside the gateway, hide the tools you don’t want, write instructions for the rest, and the agent can manage your shop, your DNS, your VPN panel. The gateway also browses the public MCP registry, so adding the next server is a click: Repo: https://github.com/k2so-dev/junctio https://github.com/k2so-dev/junctio Docs: https://junctio.pages.dev/docs/ https://junctio.pages.dev/docs/