npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@humanlabs-kr/link-mcp-server

v0.4.0

Published

Model Context Protocol (MCP) server for HumanlabsLink — connect Claude, Cursor, and other AI tools to your deep links and analytics

Downloads

963

Readme

Universal Link MCP Server

Connect Claude, Cursor, Claude Code, and any MCP-compatible AI tool to the Human Labs deep-link platform.

npm version License: MIT Node MCP

Quick start · Available tools · Configuration


The Model Context Protocol server for the Human Labs self-hosted universal-link platform (link.humanlabs.world). It exposes 15 tools that let an AI assistant analyze data with free-form read-only SQL (schema + query), register apps, manage deep links, configure templates/webhooks, and generate ready-to-paste SDK integration code — all in natural language.

Data reads go through raw SQL rather than fixed endpoints: call schema to discover the tables/columns, then query to run any read-only SELECT. The rest of the tools are write/management actions. There are intentionally no list_*/get_* read tools — an analyst queries the database directly.

This is the operator's control plane for the universal-link API, which sits behind Cloudflare Access. The server authenticates non-interactively with a Cloudflare Access service token.

The server supports two transport modes:

  • stdio (default) — runs locally as a subprocess of your AI client, via npx
  • HTTP — a stateless multi-tenant server you host yourself

What you can do with it

Once connected, you can ask things like:

  • "Register a new app called Dollar with bundle id world.humanlabs.dollar"
  • "Create a deep link for the spring sale with UTM source=instagram, campaign=spring-sale"
  • "Which links drove the most clicks last week?" → the AI reads schema, then writes and runs a SELECT
  • "Break down installs by attribution method and country for the last 30 days"
  • "Add a webhook that fires on every install event"
  • "Help me add the SDK to my React Native app"

For analytical questions the AI first calls schema, then composes a read-only SELECT and runs it via query, so it can answer anything the data supports instead of being limited to canned reports. Writes go through the dedicated management tools.

Quick start

1. Get a Cloudflare Access service token

The universal-link API is protected by Cloudflare Access. Ask an admin for a service token scoped to the API — you'll receive a Client ID (ends in .access) and a Client Secret.

2. Add to your MCP client (stdio, recommended)

No clone or build needed — npx pulls the published package. Requires Node.js 18+.

Claude Code:

claude mcp add universal-link \
  -e HUMANLABSLINK_BASE_URL=https://link.humanlabs.world/api \
  -e CF_ACCESS_CLIENT_ID=<your-client-id>.access \
  -e CF_ACCESS_CLIENT_SECRET=<your-client-secret> \
  -- npx -y @humanlabs-kr/link-mcp-server

Claude Desktop — edit your claude_desktop_config.json:

{
  "mcpServers": {
    "universal-link": {
      "command": "npx",
      "args": ["-y", "@humanlabs-kr/link-mcp-server"],
      "env": {
        "HUMANLABSLINK_BASE_URL": "https://link.humanlabs.world/api",
        "CF_ACCESS_CLIENT_ID": "<your-client-id>.access",
        "CF_ACCESS_CLIENT_SECRET": "<your-client-secret>"
      }
    }
  }
}

Cursor — add to Cursor → Settings → MCP Servers:

{
  "universal-link": {
    "command": "npx",
    "args": ["-y", "@humanlabs-kr/link-mcp-server"],
    "env": {
      "HUMANLABSLINK_BASE_URL": "https://link.humanlabs.world/api",
      "CF_ACCESS_CLIENT_ID": "<your-client-id>.access",
      "CF_ACCESS_CLIENT_SECRET": "<your-client-secret>"
    }
  }
}

The base URL defaults to https://link.humanlabs.world/api, so HUMANLABSLINK_BASE_URL is optional — keep it for clarity or to point at another instance.

3. (Optional) HTTP transport

Host the stateless HTTP server yourself (see Dockerfile) and connect via URL. In HTTP mode the per-request Authorization: Bearer header carries the API key, so a single deployment can serve multiple users.

{
  "mcpServers": {
    "universal-link": {
      "type": "http",
      "url": "https://<your-mcp-host>/mcp",
      "headers": { "Authorization": "Bearer dl_your_api_key_here" }
    }
  }
}

Available tools

Data analysis (2)

| Tool | Description | |----------|----------------------------------------------------------------------------------------------------------| | schema | Return every universal_link table with columns, types, approximate row counts, and analyst notes | | query | Run a single read-only SELECT/WITH statement and return the rows. Writes/DDL are rejected at the DB level |

Raw SQL runs server-side inside a READ ONLY transaction, de-escalated to a role that can only read the universal_link schema (never other apps' data on the shared DB). Tables must be schema-qualified, e.g. universal_link.click_events. Timestamps are stored in UTC.

Apps (3)

| Tool | Description | |--------------|---------------------------------------------------------------------| | create_app | Register a first-party app (slug, iOS team/bundle, Android pkg/SHA) | | update_app | Update any field on an app | | delete_app | Delete a registered app |

Links (3)

| Tool | Description | |---------------|----------------------------------------------------------------------------| | create_link | Create a deep link with iOS/Android/web URLs, UTM, targeting, and more | | update_link | Update any field on an existing link | | delete_link | Permanently delete a link |

Templates (2)

| Tool | Description | |------------------------|---------------------------------------------------------| | create_template | Create a new template with default destinations and UTM | | set_default_template | Mark a template as the workspace default |

Webhooks (4)

| Tool | Description | |------------------|----------------------------------------------| | create_webhook | Create a webhook for link/install events | | update_webhook | Update a webhook's URL, events, or secret | | delete_webhook | Delete a webhook | | test_webhook | Send a test payload to a webhook |

SDK helper (1)

| Tool | Description | |---------------------------|----------------------------------------------------------------------------------------------------| | get_sdk_install_snippet | Generate ready-to-paste SDK init code for any platform (react-native, expo, ios, android, flutter) |

Configuration

stdio transport

| Environment variable | Required | Default | Description | |---------------------------|----------|------------------------------------|-----------------------------------------------------------------| | CF_ACCESS_CLIENT_ID | Yes* | — | Cloudflare Access service token Client ID (ends in .access) | | CF_ACCESS_CLIENT_SECRET | Yes* | — | Cloudflare Access service token Client Secret | | HUMANLABSLINK_API_KEY | No | — | Legacy bearer API key (dl_…); alternative to the CF token | | HUMANLABSLINK_BASE_URL | No | https://link.humanlabs.world/api | Override for another self-hosted instance |

* Either the CF Access service token (both vars) or HUMANLABSLINK_API_KEY must be set. Without auth, control-plane calls return 401.

HTTP transport

| Environment variable | Required | Default | Description | |---------------------------|----------|------------------------------------|----------------------------------------------| | PORT | No | 3001 | HTTP server port | | HUMANLABSLINK_BASE_URL | No | https://link.humanlabs.world/api | Override for another self-hosted instance | | CF_ACCESS_CLIENT_ID | No | — | CF Access service token (server → API) | | CF_ACCESS_CLIENT_SECRET | No | — | CF Access service token (server → API) |

In HTTP mode the workspace API key is provided per-request via the Authorization: Bearer header, not as an environment variable — so one deployment can serve multiple users.

Security and privacy

  • No data is stored or logged by the MCP server. It is a stateless translator between MCP requests and the universal-link REST API. Every tool call is a fresh HTTP request.
  • The CF Access service token gates the control plane. The server can only reach the API through Cloudflare Access; the token is read from your local MCP client config and sent only to link.humanlabs.world.
  • Raw SQL is read-only and schema-scoped. The query tool's SQL never touches the database directly — it is executed server-side by the API inside a READ ONLY transaction, de-escalated (SET LOCAL ROLE) to a role with SELECT on the universal_link schema only. Writes/DDL and reads of other schemas on the shared cluster are rejected by Postgres.
  • stdio mode: the server runs locally as a subprocess; credentials live in your local client config.

Development

Part of the universal-link monorepo (pnpm + turbo).

# from the repo root
pnpm install
pnpm --filter @humanlabs-kr/link-mcp-server build

# watch mode
pnpm --filter @humanlabs-kr/link-mcp-server dev

# test stdio transport
CF_ACCESS_CLIENT_ID=... CF_ACCESS_CLIENT_SECRET=... node apps/mcp-server/dist/index.js

# test HTTP transport
node apps/mcp-server/dist/http.js          # starts on port 3001
curl http://localhost:3001/health          # health check

Releasing

Publishing is automated. Bump version in apps/mcp-server/package.json, merge to main, and promote the production release — the _mcp-publish workflow publishes the new version to npm (a version already on npm is skipped).

License

MIT