/ Directory / Playground / Unla
● Community AmoyLab ⚡ Instant

Unla

by AmoyLab · AmoyLab/Unla

Turn any REST API into an MCP server from YAML — zero code changes, hot reload, multi-tenant, SSE + Streamable HTTP.

Unla (AmoyLab) is a lightweight Go gateway that converts REST APIs and existing MCP services into MCP endpoints via YAML configuration. Web UI for management, multi-tenant, OAuth pre-auth, Docker-first deployment.

Why use it

Key features

Live Demo

What it looks like in practice

unla.replay ▶ ready
0/0

Install

Pick your client

~/Library/Application Support/Claude/claude_desktop_config.json  · Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "unla": {
      "command": "npx",
      "args": [
        "-y",
        "Unla"
      ],
      "_inferred": true
    }
  }
}

Open Claude Desktop → Settings → Developer → Edit Config. Restart after saving.

~/.cursor/mcp.json · .cursor/mcp.json
{
  "mcpServers": {
    "unla": {
      "command": "npx",
      "args": [
        "-y",
        "Unla"
      ],
      "_inferred": true
    }
  }
}

Cursor uses the same mcpServers schema as Claude Desktop. Project config wins over global.

VS Code → Cline → MCP Servers → Edit
{
  "mcpServers": {
    "unla": {
      "command": "npx",
      "args": [
        "-y",
        "Unla"
      ],
      "_inferred": true
    }
  }
}

Click the MCP Servers icon in the Cline sidebar, then "Edit Configuration".

~/.codeium/windsurf/mcp_config.json
{
  "mcpServers": {
    "unla": {
      "command": "npx",
      "args": [
        "-y",
        "Unla"
      ],
      "_inferred": true
    }
  }
}

Same shape as Claude Desktop. Restart Windsurf to pick up changes.

~/.continue/config.json
{
  "mcpServers": [
    {
      "name": "unla",
      "command": "npx",
      "args": [
        "-y",
        "Unla"
      ]
    }
  ]
}

Continue uses an array of server objects rather than a map.

~/.config/zed/settings.json
{
  "context_servers": {
    "unla": {
      "command": {
        "path": "npx",
        "args": [
          "-y",
          "Unla"
        ]
      }
    }
  }
}

Add to context_servers. Zed hot-reloads on save.

claude mcp add unla -- npx -y Unla

One-liner. Verify with claude mcp list. Remove with claude mcp remove.

Use Cases

Real-world ways to use Unla

How to expose your internal REST API as MCP without writing a server

👤 Platform engineers, internal tools teams ⏱ ~30 min intermediate

When to use: You have a company REST API and want Claude/Cursor to use it without building a bespoke MCP.

Prerequisites
  • Docker — docker.com/get-started
  • OpenAPI/Swagger spec for the API (helpful but optional) — Most internal APIs already have one
Flow
  1. Deploy Unla
    docker run -d --name unla -p 8080:80 -p 5234:5234 -p 5235:5235 ghcr.io/amoylab/unla/allinone:latest✓ Copied
    → Web UI at :8080
  2. Add a YAML server definition
    In the UI, create a server 'internal-api' with endpoints /users (GET) and /orders (GET, POST), mapped to https://api.internal/v1.✓ Copied
    → Tools show up: get_users, get_orders, create_order
  3. Point your client at it
    Add https://gateway.internal/mcp/internal-api to Claude Desktop.✓ Copied
    → New tools appear in the client

Outcome: Your internal API usable from any MCP client within an hour.

Pitfalls
  • Auth leaks if you map sensitive headers unrestricted — Use Unla's OAuth pre-auth to gate per-user; never hardcode admin tokens in YAML
  • Write endpoints expose destructive calls — Mark POST/DELETE endpoints as 'confirm' so they require explicit user approval
Combine with: mcphub

How to give each customer their own MCP namespace

👤 SaaS teams offering MCP access to customers ⏱ ~45 min advanced

When to use: You run a platform and want per-tenant tool isolation.

Flow
  1. Create tenants in Unla
    In admin, create tenants 'acme' and 'globex', each with their own API key mapping.✓ Copied
    → Two isolated namespaces
  2. Route per-tenant
    Acme users hit /mcp/acme, globex hits /mcp/globex.✓ Copied
    → Tools show tenant-scoped data

Outcome: Multi-tenant MCP without running multiple gateways.

Pitfalls
  • Cross-tenant leakage via shared YAML templates — Use tenant-scoped variables, never $ENV references that resolve cross-tenant

How to put your existing MCPs behind a single authenticated URL

👤 Teams with scattered MCP deployments ⏱ ~20 min intermediate

When to use: Multiple stdio MCPs in different places and you want one public URL with OAuth.

Flow
  1. Register each downstream MCP
    In Unla, add github-mcp (stdio) and postgres-mcp (HTTP) as proxied servers.✓ Copied
    → Both show as healthy
  2. Enable OAuth
    Turn on GitHub OAuth for the gateway.✓ Copied
    → Login flow works end-to-end

Outcome: One endpoint, one login, all your MCPs.

Combinations

Pair with other MCPs for X10 leverage

unla + mcphub

Use Unla for REST-to-MCP conversion and MCPHub for routing/grouping

Register Unla-exposed tools in MCPHub under the 'internal' group.✓ Copied
unla + proxy

Use mcp-proxy as a last-mile stdio bridge and Unla as the public-facing gateway

Bridge my local stdio MCP to HTTP with mcp-proxy, then register it in Unla.✓ Copied

Tools

What this MCP exposes

ToolInputsWhen to callCost
(gateway) yaml-defined REST tools As declared in YAML Whatever the exposed REST endpoint does 1 request to upstream API
(gateway) proxied MCP tools Pass-through Same as downstream Same as downstream MCP

Cost & Limits

What this costs to run

API quota
None at the gateway layer; upstream API quotas still apply
Tokens per call
Minimal gateway overhead
Monetary
Free (Apache 2.0)
Tip
Cache GET endpoints at the gateway to avoid duplicate upstream billing.

Security

Permissions, secrets, blast radius

Minimum scopes: OAuth issuer config + tenant-scoped API keys
Credential storage: Gateway config on disk (encrypt via your secret manager); tenant tokens via DB
Data egress: The gateway forwards to whichever upstream URLs you configure
Never grant: Do not expose the admin UI publicly without auth Do not YAML-encode production tokens in git

Troubleshooting

Common errors and fixes

Upstream 401 on every call

Gateway isn't forwarding auth header. Add an Authorization mapping rule in YAML.

Verify: curl gateway with -v; check upstream headers
Hot reload didn't pick up my YAML change

Validate YAML in the UI's Lint tab first; hot reload rejects invalid configs silently.

OAuth redirect_uri mismatch

Register the exact gateway URL in your OAuth provider.

SSE disconnects after 60s

Load balancer idle timeout. Raise to 3600s or use Streamable HTTP.

Alternatives

Unla vs others

AlternativeWhen to use it insteadTradeoff
MCPHubYou want a TypeScript hub with smart vector routingLess focus on REST-to-MCP conversion
ToolHiveYou want containerized per-MCP isolationNot a REST-to-MCP converter

More

Resources

📖 Read the official README on GitHub

🐙 Browse open issues

🔍 Browse all 400+ MCP servers and Skills