Skip to main content

One API Key vs 7,000 Tools: Where a Self-Hosted PaaS's MCP Server Should Land

11 min readDora NodaDora Noda
Share
On this page

An agent that deploys your app can arrive two ways. Either you hand it one API key to your homelab and let it figure out the rest, or you route it through a hosted engine with 7,000 pre-built tools and an OAuth vault standing between the agent and every credential. Both ends of that spectrum shipped real software this year: a Czech homelab team wired Coolify to AnythingLLM over MCP with a single token, and Arcade.dev runs a hosted-or-self-hostable MCP runtime that vaults per-user OAuth tokens behind thousands of tools. The question for anyone operating a self-hosted PaaS is not which demo is cooler. It is where your own MCP server should land between them — and the answer fits in one table.

Homelab bridge (xlop coolify-anythingllm-mcp)Hosted engine (Arcade.dev)
Tool surface7 tools over one API: list servers/apps, read logs, inspect containers, run SSH7,000+ pre-built tools across hundreds of integrations
Auth modelOne ambient API token in the process environmentPer-user vaulted OAuth, injected per call; the agent never holds a token
TransportLocal stdio subprocessRemote Streamable HTTP behind OAuth 2.1
Operator costAn afternoon to set up; you own every failure modeIntegration maintenance outsourced; you depend on someone else's auth proxy
Lock-inNone — MIT-licensed script, your machinesCatalog and consent flow live outside your fleet (self-hostable engine softens this)

The rest of this post earns that table: what each end concretely is, the operator math at three team sizes, and where bex's own MCP server lands — Render-compatible API as the tool surface, machine-readable state as context, OAuth 2.1 with scopes instead of one god-token.

End A: one API, one token, seven tools

The minimal end of the spectrum is xlop-dev/coolify-anythingllm-mcp, an MIT-licensed MCP server from the team behind xlop.cz that bridges Coolify's API to AnythingLLM so an agent can deploy and operate apps on a home lab or VPS through chat. The architecture is three parts: AnythingLLM acts as the agent and UI, MCP provides the tool-calling standard, and the Coolify API executes infrastructure tasks. AnythingLLM boots the server as a local subprocess from its anythingllm_mcp_servers.json plugin config and offers its tools to the agent loop behind the @agent directive.

Read the code rather than the README and the minimal surface gets very concrete. What ships is a Python stdio server answering JSON-RPC at MCP protocol 2024-11-05, configured with two environment variablesCOOLIFY_URL defaulting to plain HTTP on a LAN IP, COOLIFY_TOKEN defaulting to a placeholder — with TLS certificate verification switched off in code. Its entire vocabulary is seven tools: three Coolify reads (coolify_list_servers, coolify_list_applications, coolify_application_logs), three host container inspections that talk raw HTTP to /var/run/docker.sock (bypassing Coolify's permissions entirely), and ssh_exec, which runs an arbitrary bash command on any host you name. A working chat-to-container path in a single sitting — behind one ambient credential the agent wields in full.

That ceiling is structural, not a bug the next release fixes. Over stdio, the agent is cryptographically indistinguishable from the operator who pasted the token: no per-agent identity, no per-tool scope, no step where a call carries less authority than the environment holds. Coolify v4's own token levels (read-only through full access plus deploy-only) stop at the team boundary, and two of the three tool groups never present the token at all. The community has already demonstrated what "mature" looks like inside this model: StuMason's coolify-mcp grew the same single-token bridge to 42 token-optimized tools — v2 deliberately collapsed 60+ endpoint-mirror tools into fewer action-driven ones — with docs, a skill file, and an HTTP mode that runs the server in a container next to the Coolify instance it manages. More verbs on the same credential widen what the agent can say, not how narrowly it is trusted: vocabulary grows, authority stays flat.

So End A is fully specified: one API to wrap, one token to guard, stdio or a simple HTTP shim, zero marginal cost, and an authority model that caps out at "people and agents I trust like myself." For a solo homelab, that is not a compromise. It is the whole requirement.

End B: 7,000 tools behind someone else's auth proxy

Arcade.dev runs the opposite end: an MCP runtime for production agent deployments where the catalog and the credential handling are the product. The Arcade Engine — a hosted or self-hostable API surface — handles OAuth user authorization, manages user tokens, and exposes 7,000+ pre-built integrations as MCP tools that agent frameworks like LangChain, OpenAI Agents, CrewAI, AG2, Google ADK, Vercel AI, Mastra, and TanStack AI can call. Clients connect to a per-gateway URL (https://api.arcade.dev/mcp/<slug>) over Streamable HTTP with OAuth 2.0.

The 7,000 number needs a one-paragraph breakdown, because "tools" inflates fast in a catalog. Each integration contributes many operations — Gmail alone is search, send, draft, label, and a dozen more — so the count measures integration breadth times operation depth, not 7,000 distinct systems. That is still the honest metric for what the engine sells: the agent discovers a tool by name, and the runtime resolves the credential per call, per user. Arcade's architecture binds every authorization to a specific user — the tool declares what it needs, the engine runs the OAuth challenge for that user, vaults the resulting tokens keyed to that user, and injects them only during that user's invocation. The agent holds names. The runtime holds tokens.

That division of labor is the entire pitch, and it is aimed at the N×M auth matrix every agent platform eventually faces: N users times M integrations, each cell needing its own OAuth dance, token vault, refresh timer, scope check, and audit entry. One user and one GitHub connection is an afternoon of hand-rolled OAuth. Dozens of integrations across a whole org is a permanent maintenance burden — consent URLs and PKCE quirks per provider, encrypted storage with refresh ahead of expiry, per-call scope enforcement, revocation that actually propagates when someone leaves, and a log tying each agent action back to a real user. The engine exists so a platform team never builds that layer. The cost is exactly what the table says: the catalog, the consent flow, and the token vault live outside your fleet. The self-hostable engine softens the dependency but does not remove it — you still operate against someone else's tool definitions and gateway — and every tool call for your own infrastructure now transits a runtime you do not control.

The operator math at three team sizes

Both ends work. They just break at different sizes, and the break points are predictable once you price the two scarcities: human attention for auth plumbing, and context-window budget for tool definitions.

Solo homelab (1 user, 1–2 integrations). The bridge wins outright. One Coolify token, one subprocess, seven (or forty-two) tools, total setup measured in hours and marginal cost zero. The auth matrix is 1×2 — there is nothing to vault, no second user to isolate, no revocation story beyond rotating one token. The engine's catalog is pure overhead here: thousands of tool definitions the agent must wade through to restart a container.

Small team (5 users, 5–10 integrations). This is the crossover, and it turns on two lines. First, the auth matrix is now 25–50 cells of OAuth flows, refresh timers, and offboarding revocation — roughly a week of engineering to hand-roll and a permanent tail of provider-quirks maintenance. Second, tool count starts taxing every agent call: Dokploy's official MCP server demonstrated the failure mode by mirroring every API endpoint as a tool — 508 tools burning roughly 74k tokens of context before the first question — while community rivals cover the same API with 13 to 28 curated tools. A 7,000-tool catalog does not load all at once (gateways scope tools per connection), but the pressure is the same direction: each end must curate what the agent sees. At this size the honest options are a scoped bridge per team (narrow tokens, read-only where possible, human-in-the-loop on mutation) or the engine's free tier with your deploy tools as custom additions — and the deciding question is whether anyone on the team wants to own OAuth plumbing.

Growing org (50 users, dozens of integrations). The bridge breaks and the engine pays. Fifty users sharing ambient API tokens means fifty copies of credentials nobody can scope per person, revoke per departure, or audit per action — the homelab authority model does not survive first contact with offboarding. Here per-user vaulted OAuth with just-in-time consent stops being a luxury and becomes the only credible answer, which is why the engine's per-user isolation and audit trail are the features that matter, not the tool count. But note what still does not follow: routing your own platform's deploy path through the catalog. GitHub, Slack, Salesforce — those are other vendors' APIs, and vaulting them externally is natural. Your deploy, rollback, and scale verbs are your platform's authority to scope, and handing their credential path to a third-party runtime is a dependency on the single surface your PaaS exists to own.

That last sentence is the hinge the whole spectrum turns on. Third-party integrations want a vault. Your own control plane wants a scope. The right MCP server for a self-hosted PaaS is the one that refuses to confuse the two.

Where bex lands: own the deploy path, rent nothing per call

Bex's MCP server sits at the point the operator math points to: a first-party server that speaks OAuth 2.1 like the engine but scopes only its own API like the bridge. One endpoint, https://api.bex.co/mcp, served over stateless Streamable HTTP so any replica answers any request — the shape the MCP spec's 2026 stateless core wants remote servers to take, with no session affinity for a load balancer to preserve. Authentication follows the spec's authorization profile: a 401 with a WWW-Authenticate challenge pointing at the RFC 9728 protected-resource metadata, OAuth 2.1 through https://oauth.bex.co for interactive clients like Claude Code and Cursor, and an API-key-to-short-lived-Bearer exchange for headless clients and CI. No ambient god-token ever reaches the agent loop.

The scope model is where the bridge-vs-engine lesson lands concretely. Instead of one token that implies everything, tools carry explicit scopes — bex.read, bex.write, bex.sensitive — so "list my services" and "rewrite production env vars" are different grants, revocable separately and auditable per call. That is the engine's per-call scoping discipline applied to a first-party surface: the vocabulary stays small and curated (the Dokploy lesson — dozens of tools, not hundreds), while the authority model gets the per-user, least-privilege treatment the homelab bridge cannot express.

And tools are only half the surface. The other half is machine-readable state as context — and it is the half the bridge skips entirely. An agent deciding whether to redeploy needs current deploy state, recent logs, and service health as readable context, not just verbs to fire blind. MCP resources exist for exactly this: state the agent can read before it acts, over the same authenticated session, under the same scopes. A deploy tool without readable state is a loaded verb with no nouns; pairing scoped verbs with scoped reads is what turns "chat can touch prod" from a demo into an operable surface.

None of this rebuilds the catalog, deliberately. Bex does not need 7,000 tools because it is not vaulting anyone's Gmail — GitHub, Slack, and the rest stay where they belong, behind the user's own engine or gateway of choice. The platform owns precisely one column of the N×M matrix (its own API, all its users) and scopes it properly, instead of owning zero columns like the bridge or renting all of them like the engine.

The decision rule

If you run one box for yourself, ship the bridge: one token, a curated tool list, stdio, done. If your agents touch dozens of third-party SaaS apps across many users, rent the vault: per-user OAuth with just-in-time consent is genuinely hard to build and genuinely table stakes at that size. And if you operate the platform itself — the deploy, rollback, scale, and state verbs your tenants' agents call — build the third thing: a first-party MCP server with engine-grade auth and bridge-scale focus.

The spectrum was never really about tool count. Seven tools behind one key and 7,000 tools behind a vault are the same question asked at different sizes: who holds the credential, and how narrowly is it scoped? Answer that per surface instead of per platform, and the placement stops being a philosophy debate and becomes an operator checklist. Own your deploy path. Scope every verb. Vault what is not yours.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with a scoped MCP server your agents can operate today. Star the repo on GitHub or deploy your first app today.

Related articles

Give your agents a chain backend

Autonomous agents hit RPC endpoints very differently than people do. See what bex router handles on their behalf.

Read the agents guide