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

lockin-mcp

v1.0.14

Published

LockIn MCP — block distractions at the system level with AI-powered focus tools

Readme

LockIn MCP

A Model Context Protocol (MCP) server that blocks distracting websites at the system level by managing entries in /etc/hosts. Use it with Poke, Claude Desktop, or ChatGPT custom MCP connectors to stay focused.

Features

| Tool | Description | |------|-------------| | get_agent_guidelines | Coaching instructions for AI agents (when to enforce focus, how to handle unblock requests) | | block_domains | Block a list of domains (e.g. youtube.com, x.com, tiktok.com) | | unblock_domains | Permanently unblock specific domains | | temporarily_unblock_domains | Allow access for a limited time, then auto re-block | | enter_focus_mode | Block common distraction sites in one action (YouTube, X, TikTok, Instagram, Reddit, Facebook, Netflix, Twitch) | | get_block_status | Show what is blocked, temporarily allowed, and system readiness |

Blocking redirects domains to 127.0.0.1 and ::1, including www. variants.

Pro license required: block_domains, unblock_domains, temporarily_unblock_domains, and enter_focus_mode require an active Pro license. get_agent_guidelines and get_block_status are read-only and work without Pro. For local development only, set MDB_SKIP_LICENSE_CHECK=1.

Requirements

  • macOS / Linux / Windows (hosts-based blocking; macOS uses dscacheutil for DNS flush)
  • Node.js 18+
  • Administrator privileges to modify /etc/hosts (see below)

Web App & Pro Licensing

The web/ directory contains the landing page, user accounts, Stripe checkout, and license API.

Quick start (local)

# Terminal 1 — web app
cd web
cp ../.env.example .env.local   # edit with your Stripe keys
npm install
npm run dev                     # http://localhost:3001

# Terminal 2 — CLI installer (points at local API by default)
export MDB_APP_URL=http://localhost:3001
export MDB_LICENSE_API_URL=http://localhost:3001/api/v1
npm run build
npm run install:local
# or from GitHub (no clone):
# npx -y lockin-mcp install

Architecture

| Component | Purpose | |-----------|---------| | Landing page (/) | Features, how-it-works, pricing | | Device auth (/device) | Browser login for CLI OAuth device flow | | Dashboard (/dashboard) | Pro status, license key, MCP connection card with live blocked sites | | Dashboard sessions (/dashboard/sessions) | Focus time history and Chrome extension distraction journey | | Dashboard focus stats (/dashboard/focus) | Heatmap, streaks, and weekly share image | | Dashboard agents (/dashboard/agents) | Connect OAuth agents (Poke, Claude web, ChatGPT, Cursor, Hermes, OpenClaw); revoke connections | | Chrome extension (/extension/connect) | OAuth sign-in for Pro users; logs blocked-site visits during active focus | | Report (/report) | Bug reports and feature requests (rate-limited; not indexed) | | MCP OAuth consent (/oauth/consent) | Browser approval for ChatGPT / Claude web MCP connectors | | Checkout (/checkout) | Stripe checkout (requires verified email) | | API (/api/v1/*) | License verify, OAuth device flow, token status | | Stripe webhook | Pro upgrade + license key generation |

CLI auth handshake

  1. Installer calls POST /api/v1/oauth/device → receives user_code + device_code
  2. Browser opens /device?code=ABCD-1234
  3. User signs in and approves (requires Pro)
  4. Installer polls POST /api/v1/oauth/token → receives access_token
  5. Daemon verifies token via POST /api/v1/license/status on startup and hourly

MCP OAuth (ChatGPT, Claude web)

  1. MCP client registers via DCR at POST /api/v1/oauth/register (proxied from relay at POST /register)
  2. Client discovers metadata from /.well-known/oauth-authorization-server (web app and relay)
  3. User authorizes at /api/v1/oauth/authorize → browser consent at /oauth/consent
  4. Client exchanges code at POST /api/v1/oauth/token
  5. MCP requests to relay use OAuth access tokens or the device mdb_* API key

Environment variables

See .env.example for all configuration options.

Production deployment

Use this checklist before pointing lockinmcp.com at live traffic.

1. Generate secrets (once)

openssl rand -base64 32   # MDB_JWT_SECRET
openssl rand -base64 32   # MDB_SERVER_SECRET
openssl rand -base64 32   # REGISTRATION_SECRET (relay)

Set Vercel and Convex production env vars separately in each dashboard — do not copy MDB_SERVER_SECRET from your laptop with a sync script (local dev secrets are different from production).

| Secret | Vercel | Convex prod | |--------|--------|-------------| | MDB_SERVER_SECRET | Yes — same value on both | Yes — npx convex env set MDB_SERVER_SECRET '…' --prod once | | MDB_JWT_SECRET | Yes — same value on both (OAuth state signing) | Yes — npx convex env set MDB_JWT_SECRET '…' --prod once | | LOCKIN_CHROME_EXTENSION_IDS | Yes — published Chrome Web Store extension ID(s), comma-separated | No | | STRIPE_* | Yes | No |

2. Convex production

cd web
npx convex deploy          # production only — not convex dev

Set env vars in the Convex dashboardProduction → Settings → Environment Variables. Do not run ./scripts/sync-convex-env.sh for production — it only targets your dev deployment and .env.local often has localhost URLs.

| Convex prod variable | Value | |---------------------|--------| | MDB_APP_URL | https://www.lockinmcp.com | | MDB_SERVER_SECRET | Same string as Vercel | | MDB_JWT_SECRET | Production JWT secret (Convex only) | | GOOGLE_* / GITHUB_* | Production OAuth app credentials | | RESEND_API_KEY / RESEND_FROM_EMAIL | Production Resend | | MDB_RELAY_URL / MDB_RELAY_PUBLIC_URL | https://relay.lockinmcp.com | | REGISTRATION_SECRET | Same as relay Worker |

One-off CLI (paste production values, not from .env.local):

cd web && npx convex env set MDB_APP_URL 'https://www.lockinmcp.com' --prod

3. Stripe live mode

In Stripe Dashboard (toggle Live):

| Variable | Where to get it | |----------|-----------------| | STRIPE_SECRET_KEY | Developers → API keys → sk_live_... | | STRIPE_PRICE_ID | Products → one-time $19.99 lifetime price → price_... | | STRIPE_PRICE_ID_TIERED | Products → one-time $9.99 lifetime price (tiered batch 1) → price_... | | STRIPE_WEBHOOK_SECRET | Developers → Webhooks → endpoint https://www.lockinmcp.com/api/stripe/webhookwhsec_... | | STRIPE_PROMOTION_CODE_ID | Products → Coupons → LOCKIN50 (50% off) → promotion code promo_... (auto-applied on discounted checkout) |

Checkout appearance (product name, short description, logo, colors) is set in code via web/lib/stripe-checkout-display.ts when each session is created — you do not need a long product description in the Stripe Dashboard.

Webhook events: checkout.session.completed, checkout.session.created, checkout.session.expired (follow-up scheduling backup)

Abandoned checkout follow-up (24h email)

When a signed-in user starts Stripe Checkout but does not pay, a follow-up email is scheduled via Convex (ctx.scheduler.runAfter). After deploy:

cd web && npx convex deploy
./scripts/backfill-oauth-email-verified.sh --prod   # one-time OAuth emailVerified backfill

Verify production:

  1. Convex MDB_APP_URL is https://www.lockinmcp.com (not localhost).
  2. Vercel MDB_SERVER_SECRET === Convex MDB_SERVER_SECRET.
  3. Stripe webhook enables checkout.session.created and checkout.session.expired.
  4. Preview email: ./scripts/send-abandoned-checkout-preview.sh [email protected]
  5. Dev smoke test (60s delay): npx convex env set CHECKOUT_FOLLOW_UP_DELAY_MS 60000 then ./scripts/test-abandoned-checkout-schedule.sh <userId>
  6. Inspect jobs: ./scripts/list-checkout-follow-ups.sh scheduled

Optional Convex env: CHECKOUT_FOLLOW_UP_DELAY_MS (default 86400000 = 24h).

4. OAuth (production callbacks)

| Provider | Redirect URI | |----------|--------------| | Google | https://www.lockinmcp.com/api/auth/oauth/google/callback | | GitHub | https://www.lockinmcp.com/api/auth/oauth/github/callback |

Add GOOGLE_* / GITHUB_* to Vercel and Convex production dashboards (not dev keys from .env.local).

5. App URLs (hosting + Convex)

MDB_APP_URL=https://www.lockinmcp.com
NEXT_PUBLIC_APP_URL=https://www.lockinmcp.com
MDB_LICENSE_API_URL=https://www.lockinmcp.com/api/v1
MDB_RELAY_PUBLIC_URL=https://relay.lockinmcp.com
MDB_RELAY_URL=https://relay.lockinmcp.com

The apex domain (lockinmcp.com) redirects to www in production.

6. Deploy web app

Deploy the web/ Next.js app to your host (Vercel, etc.) with all env vars from .env.example.

7. Smoke test

  1. Sign up → verify email → checkout with a real card (or Stripe test in test mode first)
  2. Confirm /dashboard shows Pro + license key
  3. Run installer: curl -fsSL https://www.lockinmcp.com/install | bash
  4. Approve device at /device → confirm MCP tunnel provisions

One-Line Installer

The fastest way to set up blocking, tunneling, and Poke integration:

macOS / Linux (curl)

curl -fsSL https://raw.githubusercontent.com/Kiog-Aser/LockIn/main/install.sh | bash

Or use the hosted installer (recommended):

curl -fsSL https://www.lockinmcp.com/install | bash

Windows (PowerShell)

iwr -useb https://raw.githubusercontent.com/Kiog-Aser/LockIn/main/install.ps1 | iex

npm

npx -y lockin-mcp install
# or from a local clone:
npm run install:local

The npm package lockin-mcp replaces the legacy mac-distraction-blocker-mcp name. Legacy bin aliases (mac-distraction-blocker-mcp, mdb-install) still work.

What the installer does

  1. Detects your platform (macOS, Linux, or Windows)
  2. Verifies your $9.99 Pro license via browser login or license key
  3. Prompts for distraction sites — popular presets pre-selected (YouTube, X, TikTok, Instagram, Reddit) plus custom domains
  4. Applies initial blocks to /etc/hosts
  5. Starts the MCP HTTP server locally with an outbound relay connection (background LaunchAgent on macOS)
  6. Provisions a stable relay URL (https://relay.lockinmcp.com/device/{id}/mcp) so Poke, Claude, and ChatGPT can reach your Mac
  7. Connects your AI agent — Poke, Claude (web), ChatGPT, Cursor, Hermes, and OpenClaw connect via the dashboard or OAuth; Claude Desktop uses connect-agent CLI + mcp-remote (not on the dashboard grid)
  8. Auto-updates the daemon — when a background service is installed, checks npm every 5 minutes and restarts after upgrading

Installer flags (non-interactive)

curl -fsSL .../install.sh | bash -s -- --yes --browser-login --poke-recipe
npx -y lockin-mcp install --license-key lockin_pro_xxx --sites all --poke-recipe

| Flag | Description | |------|-------------| | --yes | Non-interactive with defaults | | --license-key <key> | Pro license key | | --browser-login | Verify license via browser device flow (default) | | --skip-tunnel | Local MCP only (no relay URL) | | --skip-block | Skip initial domain blocking | | --skip-poke | Skip Poke URL generation | | --port <number> | Local MCP HTTP port (default 3847) | | --sites all | Block all presets | | --custom-domains a.com,b.com | Extra domains | | --poke-recipe | Generate distraction-coach recipe URL | | --mcp-auth-token <token> | Custom bearer token for tunneled MCP |

Setup details are saved to ~/.lockin/setup-manifest.json.

Pro licensing ($9.99 lifetime — 50% off $19.99)

  • Purchase: Create an account at /login (email or Google/GitHub; /signup redirects here), verify email, pay via Stripe
  • License key: Available on dashboard after purchase; pass --license-key to installer
  • Browser login: Default installer flow — OAuth device authorization in your browser
  • Auth: Google and GitHub OAuth supported; email/password requires verification before checkout
  • Support: Bug reports and feature requests at /report (also linked in the site footer)

Quick Start (manual)

git clone https://github.com/Kiog-Aser/LockIn
cd LockIn
npm install
npm run build

Run locally (stdio — advanced)

For MCP clients that spawn a local subprocess:

node dist/index.js --stdio

MCP Client Configuration (after installer)

Your MCP URL and API key are in ~/.lockin/setup-manifest.json:

  • MCP URL: from manifest — e.g. https://relay.lockinmcp.com/device/abc123/mcp (Poke, Claude, ChatGPT, Cursor, Hermes, OpenClaw)
  • API key: mdb_…

Dashboard connect (recommended)

After install, open lockinmcp.com/dashboard/agents to connect OAuth agents or copy CLI commands for Cursor, Hermes, and OpenClaw. Claude Desktop is not on the dashboard grid — use the CLI below.

connect-agent CLI

For Claude Desktop or guided setup from the terminal:

npx -y lockin-mcp connect-agent
npx -y lockin-mcp connect-agent --agent claude-desktop

Poke

The installer copies your relay MCP URL and opens poke.com/integrations/new. In Poke:

  1. Paste the MCP URL (ends with /mcp)
  2. Choose OAuth authentication (do not paste your API key in the integration form)
  3. Sign in on lockinmcp.com when prompted
  4. Install the LockIn recipe

Legacy CLI (optional): npx poke@latest mcp add 'https://YOUR_RELAY_HOST/device/YOUR_ID/mcp' -n 'LockIn MCP' with OAuth in the Poke UI.

Claude (claude.ai)

The installer opens a link that pre-fills the connector name and MCP URL (connectorName + connectorUrl). Claude web uses OAuth — do not paste your API key in Advanced settings. See the connector setup guide.

  1. Choose Claude (claude.ai) in the installer (or build the link with connectorName=LockIn MCP and your encoded MCP URL)
  2. Confirm the pre-filled MCP server URL (e.g. https://relay.lockinmcp.com/device/abc123/mcp)
  3. Leave Advanced OAuth settings empty. Click Add, then sign in on lockinmcp.com when Claude prompts (Pro license required)
  4. Start a new chat with LockIn enabled

For Bearer/API-key auth, use Claude Desktop instead — the installer can write claude_desktop_config.json automatically.

Claude Desktop

Claude Desktop is not on the dashboard agent grid — connect via CLI:

npx -y lockin-mcp connect-agent --agent claude-desktop

Claude Desktop only supports stdio MCP servers in claude_desktop_config.json — not direct url entries. The installer or connect-agent merges a config that uses mcp-remote to bridge your relay URL (requires Node.js 18+).

Config paths:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Manual example:

{
  "mcpServers": {
    "lockin-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote@latest",
        "https://relay.lockinmcp.com/device/YOUR_ID/mcp",
        "--header",
        "Authorization:${LOCKIN_MCP_AUTH_HEADER}"
      ],
      "env": {
        "LOCKIN_MCP_AUTH_HEADER": "Bearer mdb_..."
      }
    }
  }
}

On Windows, use "command": "npx.cmd" instead of "npx". Quit Claude Desktop completely before editing, then reopen.

Cursor, Hermes, OpenClaw

Connect from the dashboard Agents page — copy your relay MCP URL or run the CLI command shown for each provider. See connector guides for Hermes and OpenClaw setup.

ChatGPT

Custom MCP connectors require Developer mode under Advanced settings. ChatGPT cannot accept credentials from an external link — copy from the installer or setup guide.

  1. Open ChatGPT → Settings → Connectors → Advanced
  2. Enable Developer mode
  3. Add connector → paste MCP server URL from your manifest
  4. Set Authentication to OAuth and leave DCR enabled — sign in on lockinmcp.com when prompted (do not paste your API key in OAuth fields)
  5. Start a new chat and enable the LockIn connector

Relay deployment (operators)

The relay/ package is a Cloudflare Worker + Durable Object that bridges remote MCP HTTP requests to each Mac daemon over an outbound WebSocket.

cd relay
npm install
npx wrangler secret put REGISTRATION_SECRET
npx wrangler secret put MDB_JWT_SECRET   # optional, same as web app
npm run deploy

Set relay vars on Convex production in the dashboard. For local dev only: web/.env.local + ./scripts/sync-convex-env.sh (dev deployment).

Local OAuth development

When running the web app locally (http://localhost:3001):

  • MCP OAuth CORS allows localhost:3000/3001 and 127.0.0.1:3000/3001
  • Dynamic Client Registration redirect URIs must use http://localhost:… (not 127.0.0.1) per OAuth validation

Chrome extension (optional)

The Chrome extension tracks page visits during active focus sessions and syncs them to your dashboard distraction journey.

  1. Load unpacked from the extension/ folder (see extension/README.md)
  2. Click the extension icon → Sign in (OAuth at lockinmcp.com/extension/connect)
  3. Pro license required — only blocked-site visits during active focus are logged
  4. View the journey on Dashboard → Sessions (expand a day)

Daemon auto-update

When the background service (LaunchAgent/systemd/Windows task) is installed, the daemon checks npm for new lockin-mcp releases every 5 minutes (first check after 5 seconds). Updates install to ~/.lockin/npm/ and restart the service automatically. Last check timestamp: ~/.lockin/last-update-check.json.

Force an update check anytime:

npx lockin-mcp update

Privileges & /etc/hosts

The server writes marked entries between:

# lockin-mcp BEGIN
...
# lockin-mcp END

Legacy installs may still show # mac-distraction-blocker-mcp markers; those are stripped on the next hosts sync.

Only those lines are touched; the rest of /etc/hosts is preserved.

Option A: Run the server with sudo (simplest)

sudo node dist/index.js --http --port 3847

For stdio MCP clients, configure the client to launch with sudo (see client config examples below).

Option B: Passwordless sudo for hosts updates (recommended)

The installer creates ~/.lockin/update-hosts.sh and a sudoers entry at /etc/sudoers.d/lockin-mcp-hosts that allows your user to run that script without a password. Temp files use the prefix lockin-mcp-hosts-{pid}.

If you installed manually, re-run the installer or configure sudoers to allow (replace YOUR_USER with your macOS username):

sudo visudo -f /etc/sudoers.d/lockin-mcp-hosts

Add:

YOUR_USER ALL=(ALL) NOPASSWD: /Users/YOUR_USER/.lockin/update-hosts.sh

(Adjust paths for Linux/Windows as needed.)

Verify permissions

Call get_block_statushostsFileWritable: true means the server can update blocking without extra setup.

Legacy: local stdio (Claude Desktop)

~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "lockin-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/LockIn/dist/index.js", "--stdio"]
    }
  }
}

Security

  • MCP bearer auth: HTTP MCP requires MDB_MCP_AUTH_TOKEN or --mcp-auth-token (mdb_* tokens). Relay-backed HTTP refuses to start without a token.
  • API rate limiting: Login, signup, OAuth (account + MCP), license verify, checkout, consent, and user-report routes are rate-limited.
  • User reports: POST /api/report accepts bug/feature submissions (5 per IP per hour). Requires RESEND_API_KEY in production; falls back to Convex logs in dev.
  • Relay tokens: Device tokens are hashed at rest on the Cloudflare worker (SHA-256).
  • Setup manifest: Written with 0o600 permissions; contains your relay URL and API key — do not commit or share.

Hooking up to poke.com/kitchen

The installer tunnels your local MCP over HTTPS so Poke can connect remotely — no extra terminal tab. When you choose Poke during install, it copies your relay URL and opens the integrations page for OAuth setup.

Recipe / Kitchen (recommended)

Install the official LockIn recipe for the best Poke experience:

https://poke.com/r/KQ7myvC_Xpo

The recipe connects your MCP tools and coaches you through focus sessions. You can also build custom recipes in poke.com/kitchen using get_agent_guidelines, block_domains, get_block_status, etc.

Tool Examples

Get agent guidelines

No arguments. Returns focus-coaching instructions for AI agents — call at the start of focus or blocking conversations.

Block sites

{
  "domains": ["youtube.com", "x.com", "tiktok.com", "reddit.com"]
}

Unblock one site

{
  "domains": ["youtube.com"]
}

15-minute break

{
  "domains": ["youtube.com"],
  "duration_seconds": 900
}

Check status

No arguments. Returns blocked list, temporary allowances with expiry timestamps, and whether hosts is writable.

How it works

flowchart LR
  A[MCP Client / Poke] --> R[Relay Worker]
  R --> B[MCP Server on Mac]
  B --> C[State JSON\n~/.lockin/]
  B --> D[/etc/hosts]
  B --> E[DNS cache flush]
  C --> B
  1. State — Block list and temporary unblocks live in ~/.lockin/state.json
  2. Hosts sync — Active blocks are written to /etc/hosts with a managed marker
  3. Expiry watcher — A background timer re-applies blocks when temporary unblocks expire (server process must be running)
  4. DNS flush — Best-effort dscacheutil / mDNSResponder refresh after changes

Development

npm install
npm run dev          # watch TypeScript
npm run build
npm run lint
npm test             # Vitest (root MCP tests)
cd web && npm test   # web rate-limit tests
cd relay && npm test # relay token hashing tests

CI (.github/workflows/ci.yml) runs lint, test, build, and npm audit --audit-level=high for the MCP server, web app, and relay worker.

Reset local install state (development only):

npx lockin-mcp dev-reset              # reset hosts, manifest, relay config
npx lockin-mcp dev-reset --full       # also remove LaunchAgent / background service
npx lockin-mcp dev-reset --wipe-license  # clear saved license

See relay/README.md for Cloudflare WebSocket hibernation details on the device relay worker.

Troubleshooting

| Issue | Fix | |-------|-----| | EACCES on block/unblock | Run with sudo or configure passwordless sudo (see above) | | Site still loads | Hard-refresh browser; DNS cache may take a moment. Try private window. | | Temp unblock didn't re-block | Keep the MCP server process running (expiry watcher runs in-process) | | Poke can't connect | Re-run install and confirm OAuth completed in Poke. Check manifest relay URL + /health returns lockin-mcp with relay.connected: true. If offline, re-run npx lockin-mcp install once — the daemon self-heals reconnects automatically. | | Wrong platform | macOS, Linux, and Windows are supported; DNS flush behavior differs by OS |

License

MIT