Blog · 2026-09-07

"One template, many clients: running client MCP servers on DenkOps"

Build one connector template, deploy it once per client, each in its own always-on slot. Per-client isolation, deploy from git, one dashboard.

Freelancers and agencies building custom MCP connectors for several clients tend to hit the same wall: the tools are 80% identical (CRM lookups, ticket search, a couple of internal APIs), but each client needs their own credentials, their own domain, and their own access list. The fix is not one shared server with a client ID parameter bolted on. It is one template, deployed once per client, so isolation is structural instead of something your code has to remember to enforce.

Build the template once

Write the connector as a normal project: a denkops.json, your tool handlers, connector: true for hosted OAuth. Keep client-specific values out of the code entirely, referenced only by env var name:

{ "name": "acme-support", "slug": "acme-support", "runtime": "bun", "connector": true }

The handlers, the tool schemas, the error handling, all of it lives in one git repository. That repository is your product. What changes per client is not the code, it is the deploy target.

Deploy once per client, each in its own slot

Clone the repo's config per client (a folder, a branch, or a small script that stamps out denkops.json files with a different slug) and deploy each one separately. Every deploy lands in its own project, its own always-on slot, with its own environment variables, its own optional custom domain, and its own OAuth access policy. Client A's API key is never in the same process, the same slot, or even the same access list as client B's.

npx @denkopsai/mcp deploy --project acme-support
npx @denkopsai/mcp deploy --project globex-support

Push a fix to the template, redeploy the client projects that need it, and each rollout is independent: you can ship the fix to one client today and the rest next week without touching a shared service that all of them depend on.

One dashboard, twenty projects

The part that actually saves the time is not the deploy, it is what happens after. All of a client's projects live in the same dashboard, so you get one place to check status, read logs, roll back a bad deploy, and see who has access, across every client, without SSHing into anything or juggling separate consoles per customer. A support ticket that says "client X's connector is erroring" turns into: open the dashboard, find the project, read the logs, done.

This is the same shape as running twenty small SaaS backends, because that is what it is. Each client gets a real, isolated, always-on service; you get a single control plane over all of them. See the full list of what a deploy gives you on capabilities.

FAQ

Do I need to write different code for each client?

No. Keep one connector template in git and deploy it once per client with different environment variables and slug. The tool handlers, schemas, and logic stay identical; only the deploy target and secrets differ per client.

How isolated are two client deployments from each other?

Fully. Each deploy is its own project with its own slot, its own environment variables, its own OAuth access policy, and optionally its own custom domain. Nothing is shared between them, so a problem or a leaked credential in one client's project has no path into another's.

Can I manage all my client connectors from one place?

Yes. Every project you deploy shows up in the same dashboard, where you can check status, read logs, roll back, and manage access across all clients, without a separate console per customer.

Ship it yourself: bunx denkops deploy or say "deploy on DenkOps" from your coding agent.

Start on DenkOps →

← An on-call ops connector for your assistant · "What a slot is, and why per-slot beats per-request when you have 20 clients" →