What hdls is & how it works

The short version: hdls is your back-office — a CRM, a helpdesk, and more — that you connect once and then run by talking to your AI assistant. No app to learn, no code. If that's all you need, head to Using hdls — just talk to your assistant, or jump straight to Getting connected to wire up your assistant.

This page is for when you're curious about how that works under the hood — the one mental model everything else follows from. (Developers: everything technical you need is right below.)

💬 Just connect, then ask. You never click around a UI — you tell your assistant what you want and it calls the right tool for you. The rest of this page explains the machinery behind that.

Start reading here. This page explains the one mental model you need before you connect anything. Everything else in hdls follows from it.

At a glance

hdls is a portfolio of headless, MCP-native SaaS backends — the database is the product. Instead of logging into a web app and clicking around, you operate hdls from your AI assistant (Claude, Cursor, Codex, and any other MCP client) by calling named tools. There is no per-product UI to learn.

You connect in two layers:

LayerEndpointWhat it's for
Concierge (control plane)https://hdls.ai/api/mcpDiscover products, install the ones you need, invite teammates, find skills + docs, store workspace memory
Product (the work)https://hdls.ai/api/mcp/<slug>The actual record tools for one product, e.g. /api/mcp/crmcreate_account, search_accounts, summarize_account

Authentication is one-click OAuth 2.1 — no key pasting. Tenant isolation is automatic: your credential is pinned to one workspace, and you never pass a tenant_id. It is stamped server-side on every call.


The big idea: the database is the product

Most SaaS gives you a database wrapped in a UI you didn't ask for. hdls removes the wrapper. Each product is just a schema with a set of purpose-built tools. You talk to those tools through your AI assistant over the Model Context Protocol (MCP), and the data is the deliverable.

What this means for you in practice:

  • No app to learn. You don't navigate menus. You say what you want ("create an account for Acme Corp, then log a call") and your assistant calls the right tools.
  • The tools are self-describing. Every product's tools carry their own field lists and descriptions, so your assistant knows exactly what to send without you reading a manual.
  • It's bring-your-own-frontend. If you want a UI, build one against the same backend. The MCP tools, a REST API, and an inspector console are all generic projections of the same schema. You can even publish hosted Pages straight from the concierge.

The two-endpoint model: concierge vs. product

This is the single most important thing to understand. hdls splits the surface in two on purpose.

The concierge — https://hdls.ai/api/mcp

This is the control plane. Connect here first. The concierge is deliberately lean: it tells you what exists and lets you manage the workspace. It does not do day-to-day record work. Its tools are:

  • Product managementlist_products, describe_product, install_product, uninstall_product
  • Teaminvite_teammate
  • Skillssearch_skills, get_skill
  • Workspace memoryset_workspace / get_workspace, set_bio / get_bio, set_preference / get_preferences
  • Pagespublish_page, list_pages, unpublish_page, find_logo
  • Orientationhelp, search_docs

The product endpoints — https://hdls.ai/api/mcp/<slug>

Each product you install exposes its own named tools at its own endpoint. The CRM lives at /api/mcp/crm and serves create_account, search_accounts, summarize_account, and so on. To actually do work, you add that endpoint as a second connector (same OAuth, one click) and call its tools directly.

Rule of thumb: The concierge tells you what exists and installs it. The product endpoint is where you do the work.

        ┌─────────────────────────────────────────────┐
        │  CONCIERGE   https://hdls.ai/api/mcp          │
        │  (control plane — one connection)            │
        │                                              │
        │  list_products · describe_product            │
        │  install_product · invite_teammate           │
        │  search_skills · help · workspace memory     │
        └───────────────┬─────────────────────────────┘
                        │ install_product({slug:"crm"})
                        ▼
        ┌─────────────────────────────────────────────┐
        │  PRODUCT      https://hdls.ai/api/mcp/crm     │
        │  (the work — add as its own connector)       │
        │                                              │
        │  create_account · search_accounts            │
        │  create_deal · move_deal_stage               │
        │  log_activity · summarize_account            │
        └─────────────────────────────────────────────┘

The mental model: workspace = tenant, products = schemas

Three terms, and you're fluent:

  • Workspace = tenant. One workspace is one isolated tenant. All your data lives there. Your credential is pinned to it.
  • Product = a schema you install. Products (crm, support, contacts, …) already exist in the shared database. Installing a product is a metadata flip — it records that your workspace uses that product, and its named tools light up on the product endpoint. Your data only ever appears in your tenant.
  • You never pass a tenant_id. Isolation is enforced by the database itself (Postgres Row-Level Security). Even if something went wrong upstream, a query with no tenant context returns zero rows — it fails closed, not open.

Roles

Every member has one of four roles, in increasing power:

reader  <  member  <  admin  <  owner
ActionMinimum role
list_products, describe_product, search_skills, helpreader (anyone)
install_product, invite_teammateadmin
uninstall_productowner

Reader and member roles also only ever see tools for products their credential actually grants — a low-privilege key can't reach a product it wasn't given.


Your first five minutes

1. Connect your assistant to the concierge

Add an MCP server pointing at https://hdls.ai/api/mcp and authenticate. It's one-click OAuth — you'll be redirected to sign in and approve, then dropped back. No API keys to copy.

In an MCP client config, that looks like:

{
  "mcpServers": {
    "hdls": {
      "url": "https://hdls.ai/api/mcp"
    }
  }
}

2. See what exists

Ask your assistant to list products, or call the tool directly:

list_products

You get back every product in the catalog, each with its one-line description, the named tools it exposes, its dedicated endpoint, and an installed flag for your workspace. For example, the crm entry reports tools like create_account, search_accounts, and summarize_account and the endpoint https://hdls.ai/api/mcp/crm.

To inspect one product in depth (every tool with a per-tool description):

describe_product
{ "slug": "crm" }

3. Install what you need (admin/owner)

install_product
{ "slug": "crm" }

This is idempotent — installing twice is harmless. It enables the product's tools on its own endpoint, not on the concierge. The response tells you the exact endpoint to connect to next.

A brand-new workspace starts with crm available by default, so your very first connection is never empty.

4. Connect to the product endpoint and do the work

Add a second MCP connector pointing at the product endpoint — same OAuth, one click:

{
  "mcpServers": {
    "hdls": { "url": "https://hdls.ai/api/mcp" },
    "hdls-crm": { "url": "https://hdls.ai/api/mcp/crm" }
  }
}

Now its named tools are callable. Notice you never mention a tenant or owner — they're stamped for you:

create_account
{ "name": "Acme Corp", "domain": "acme.com", "industry": "Manufacturing" }
create_deal
{ "account_id": "acc_01H...", "title": "Acme — Q3 expansion", "amount": 48000 }
log_activity
{ "account_id": "acc_01H...", "type": "call", "note": "Intro call — strong fit" }
summarize_account
{ "account_id": "acc_01H..." }

Each tool's exact field list is embedded in its own description, generated live from the schema. Your assistant reads that automatically — you don't have to.

5. Invite your team (admin/owner)

invite_teammate
{ "email": "sam@acme.com", "role": "member" }

They get a one-time sign-in link by email and join the workspace the moment they sign in — no password. Inviting at the admin/owner level triggers a one-time confirmation step for safety.


Why this is different — and what you gain

Traditional SaaShdls
Learn a new UI per productOne mental model; tools are self-describing
Copy/paste API keys, manage scopes by handOne-click OAuth 2.1; scoped server keys exist when you need them
Hope multi-tenancy is correctIsolation enforced by the database; fails closed
Integrations are a projectYour AI assistant is the client
Data trapped behind the vendor's frontendThe data is the product; bring your own frontend

Concretely, you gain:

  • Speed. Go from "I need a CRM" to creating records in minutes, entirely from your assistant.
  • Composability. Install several products into one workspace; records can be linked across products (e.g. a CRM contact ↔ a support ticket).
  • Trust. Tenant isolation isn't a feature flag — it's a database guarantee that a credential can only ever see its own workspace. More in Security & trust.
  • Memory. The concierge remembers context across sessions: set a workspace description, a personal bio, and per-user preferences, and read them back later. See Workspace memory.

Auth & access, honestly

  • OAuth 2.1, one click. The standard path. Your token resolves your tenant and role — there's nothing to configure beyond approving the connection.
  • Scoped API keys exist for server-to-server automation (a backend job, a script) where interactive OAuth doesn't fit. Use OAuth for your assistant; reach for a key only when a non-interactive service needs access.
  • One credential = one workspace. A credential is pinned to a single tenant. To work in a different workspace, you connect with that workspace's credential.

Gotchas worth knowing up front

  • Installing a product does not make its tools appear on the concierge. They appear on the product's own endpoint, /api/mcp/<slug>. You must add that endpoint as a connector to call them. This is by design — it keeps the control plane small and predictable.
  • install_product and invite_teammate are admin/owner only. A reader or member won't even see those tools. uninstall_product is owner-only.
  • Uninstalling does not delete data. It removes the product's tools from your connection and stops your workspace using it — the underlying rows are untouched. Re-install to get the tools back.
  • You never send tenant_id (or a record owner). If a tool seems to "want" one, you're overthinking it — it's stamped server-side.
  • Don't do record work on the concierge. It has no create_account / create_ticket. Those live only on the product endpoints.

Where to go next

  • Getting connected — step-by-step setup for your MCP client, then run list_products to see your catalog and describe_product({slug}) on anything that looks useful.
  • Using hdls — what to actually say to your assistant once you're connected.
  • Products — browse the full catalog, including the flagship trio: CRM, Support, and Contacts.
  • Skills — ready-made playbooks you can apply in your workspace (search_skills / get_skill).
  • Teams — invite teammates and manage roles.
  • Security & trust — how tenant isolation and auth work under the hood.

Inside your assistant, you can also ask the concierge help at any time — it reports your live connection (which product is active, your role, and what you can call) — or use search_docs to search hdls's own documentation without leaving the chat.