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

@offlocal/mcp

v0.4.1

Published

Production context layer for AI coding agents. MCPs give agents tools; offlocal.ai gives agents production context (which project, which environment, which provider account, what's allowed, what needs approval, what happened last time).

Readme

@offlocal/mcp

Production context layer for AI coding agents.

MCPs give AI agents tools. offlocal.ai gives AI agents production context.

When an AI coding agent (Claude Code, Codex, Cursor) connects to a provider MCP, it typically gets one account wired in globally. But real developers don't live in one account. They have:

  • one GitHub org with many repos,
  • one or more Vercel teams/projects,
  • multiple Supabase projects,
  • Stripe test/live accounts,
  • staging vs production,
  • client projects,
  • and production resources that must not be touched without approval.

A tool that can "deploy to Vercel" is dangerous if the agent doesn't know which Vercel project, in which environment, for which account — and whether it's even allowed to.

@offlocal/mcp is one local MCP server an agent connects to so it can ask:

  • Which project am I working on?
  • Which environment is active?
  • Which GitHub repo / Vercel project / Supabase project / Stripe mode belongs to it?
  • What am I allowed to do? What's blocked? What requires human approval?
  • What happened last time?

It resolves project → environment → provider mapping → policy/safety check → provider API → audit log / project memory before any real action runs.


The problem, concretely

AI coding agent
  → @offlocal/mcp
    → workspace
      → project            (your-project)
        → environment      (staging | production)
          → provider mappings   (github repo, vercel project, supabase ref, stripe mode)
            → policy / safety check   (allow | block | approval_required)
              → provider API action
                → audit log + project memory

Every provider action is forced through one choke point that resolves the right account/environment, checks policy, and writes an audit entry. There is no path to a provider call that skips this.


Status: V0

  • Local-first and open source (Apache 2.0). Runs entirely on your machine.
  • Providers: GitHub, Vercel, Supabase, Stripe (direct REST APIs) and Railway (GraphQL API).
  • Storage: plain JSON files under .offlocal/ (zero native deps).
  • Auth: environment variables only — tokens are read at call time and never written to disk.

See docs/provider-research.md for the API/auth research behind each adapter.


Getting started

Requires Node ≥ 18. There is nothing to clone and no config file to fill in — the server runs straight from npm, and you set everything else up by talking to your agent.

Step 1 — Add offlocal to your AI agent

Point your agent at @offlocal/mcp over npx and pass the provider tokens you actually use as env vars. The server is published to npm, so npx fetches and runs it on demand.

Claude Code — create .mcp.json in your project root:

{
  "mcpServers": {
    "offlocal": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "-p", "@offlocal/mcp", "offlocal-mcp"],
      "env": {
        "GITHUB_TOKEN": "ghp_your_token",
        "VERCEL_TOKEN": "your_vercel_token",
        "RAILWAY_TOKEN": "your_railway_token"
      }
    }
  }
}

Cursor.cursor/mcp.json (same shape, drop the "type" field). Codex~/.codex/config.toml:

[mcp_servers.offlocal]
command = "npx"
args = ["-y", "-p", "@offlocal/mcp", "offlocal-mcp"]
env = { GITHUB_TOKEN = "ghp_your_token", VERCEL_TOKEN = "your_vercel_token" }

Only include tokens for the providers you'll use — every other provider simply stays unavailable. Tokens are read at call time and never written to disk. Restart your agent (or reconnect MCP servers) after editing the config.

Step 2 — Provider tokens

| Variable | Provider | Notes | |---|---|---| | GITHUB_TOKEN | GitHub | Fine-grained PAT (Metadata: read, Contents: read) | | VERCEL_TOKEN | Vercel | Account/team token | | VERCEL_TEAM_ID | Vercel | Optional; required for team-owned resources | | SUPABASE_ACCESS_TOKEN | Supabase | Personal access token | | STRIPE_TEST_SECRET_KEY | Stripe | sk_test_... | | STRIPE_LIVE_SECRET_KEY | Stripe | sk_live_... — only used when policy allows a live write | | RAILWAY_TOKEN | Railway | Account/workspace token |

Step 3 — Let the agent set up your project (no YAML)

The first time you connect there are no projects yet — that's expected. You don't create them by hand or edit any file; you just ask your agent, and it calls the setup tools for you. For example:

"Use offlocal to create a project called acme-crm with a staging and a production environment. Map my Vercel project acme-crm-preview to staging and acme-crm-prod to production, and map Railway project <railway-project-id> to production."

Then start asking it to do real work:

"What's safe to touch in acme-crm staging?" "Fetch the latest staging logs." "Deploy acme-crm to Railway staging."

Behind the scenes the agent uses create_project, add_environment, map_provider_resource, get_project_context, and the provider tools — all gated by policy and written to the audit log. Your setup persists in a local .offlocal/ directory (in the agent's working directory; override with the OFFLOCAL_HOME env var), so you only do Step 3 once per machine.

That's the whole setup. You never have to write a config file.

Optional — declare everything in a config file instead

If you'd rather keep your setup as a version-controlled, repeatable file (handy for seeding several projects at once or sharing across a team), you can describe it in .offlocal/config.yaml and seed it with the bundled CLI — but this is entirely optional and most people can skip it:

npx -p @offlocal/mcp offlocal init        # seeds from .offlocal/config.yaml if present
npx -p @offlocal/mcp offlocal context acme-crm --env staging

See .offlocal/config.example.yaml for the full schema. require_approval entries apply to production (staging/dev stay permissive); block entries apply everywhere.

Want zero setup?

The self-hosted core in this repo is free and Apache-2.0 — you bring your own provider tokens and run it locally. A managed offering (hosted credential vault, one-click provider connect, real approve/deny workflows, an audit dashboard, and team seats) removes the manual steps above for teams that want it. See offlocal.ai.


MCP tools

Project / workspace: list_projects, create_project, select_project, get_project_context, add_environment, list_environments

Provider mappings: map_provider_resource, list_provider_mappings, get_provider_mapping

Policy: check_policy, list_policy_rules, set_policy_rule

Memory / audit: read_project_memory, write_project_memory, list_audit_log

GitHub: get_github_repo_context, get_github_repo_readme, list_github_repo_files

App logs: get_app_logs, get_vercel_logs, get_latest_deployment_logs

Vercel: get_vercel_project_context, get_vercel_deployments, get_vercel_deployment_status, get_vercel_deployment_logs, set_vercel_env_var, create_vercel_deployment

Railway: get_railway_project_context, get_railway_deployments, get_railway_logs, create_railway_deployment, set_railway_env_var

Supabase: list_supabase_projects, get_supabase_project_context, query_supabase*

Stripe: list_stripe_products, create_stripe_product, create_stripe_price

* gated by policy (production / live / destructive operations require approval or are blocked — see below).

get_project_context is the one to call first. For a project (and optionally a focused environment) it returns: the GitHub repo, the Vercel project + live latest deployment status / URL / failure (best-effort), the Supabase project, the Stripe mode, the allowed / blocked / approval-required action lists, project memory, recent audit history, suggested safe next actions, and a human-readable summary the agent can reason from directly.


Fetch app logs

Ask the agent something like "Use offlocal to fetch the latest staging logs." It resolves the project/environment, finds the mapped Vercel project, fetches the latest deployment's logs, and the read is written to the audit log.

  • get_app_logs — generic. Pass project + environment (and optionally provider, deployment_id, since, limit). With no provider it reads every mapped provider that supports logs (Vercel + Railway in V0, Vercel prioritized).
  • get_vercel_logs / get_railway_logs — provider-specific. Resolve the latest deployment when deployment_id is omitted; return the deployment id/url/status plus logs.
  • get_latest_deployment_logs — convenience; latest deployment for the mapped provider (provider defaults to Vercel, also accepts railway).

Log reads are a read capability, so they are allowed by default in every environment, including production. Secrets are redacted from log lines where recognizable, and every read is audited. If the provider's API can't return log lines, the tool returns the deployment status plus a clear limitation instead of failing silently — it never fabricates logs.

{
  "status": "ok",
  "project": "acme-crm",
  "environment": "staging",
  "provider": "vercel",
  "policy_decision": "allow",
  "executed": true,
  "data": {
    "resource": {
      "project": "acme-crm-preview",
      "deployment_id": "dpl_…",
      "deployment_url": "https://acme-crm-preview.vercel.app",
      "deployment_status": "ERROR"
    },
    "time_range": { "since": null },
    "logs": [
      { "timestamp": "2026-06-09T12:00:02.000Z", "level": "error", "message": "Error: DATABASE_URL is missing" }
    ],
    "audit_written": true
  }
}

Vercel's events API exposes build logs and recent runtime events. Older runtime logs require a configured log drain and are not retrievable through this API — the tool reports that as a limitation.


Policy & safety behavior

The policy engine reasons about capability × environment × provider × live-flag, not individual tool names — so new tools inherit safe defaults automatically.

Defaults:

| Situation | Default | |---|---| | Any read | allow | | Dev/staging write (non-destructive) | allow | | Production write / deploy / env-var change | approval_required | | Live Stripe write | approval_required | | Destructive SQL (DROP/TRUNCATE/DELETE/ALTER…) | block (everywhere) | | Deleting resources | block (everywhere) | | Every provider action | logged to the audit trail |

You override defaults with explicit rules (set_policy_rule) — higher priority wins. This is how you opt into something normally gated (e.g. "allow live Stripe writes for this reviewed project").

When an action needs approval, the tool returns a structured response instead of executing:

{
  "status": "approval_required",
  "policy_decision": "approval_required",
  "executed": false,
  "reason": "Production deploys require approval by default.",
  "project": "your-project",
  "environment": "production",
  "provider": "vercel",
  "action": "create_vercel_deployment",
  "suggested_next_step": "Approve manually by adding an allow PolicyRule (set_policy_rule) ..."
}

Every provider response carries explicit policy_decision (allow / block / approval_required) and executed (boolean) fields. Blocked actions return "status": "blocked". Both blocked and approval-required responses set executed: false and are written to the audit log with result: "not_executed" — the provider API is never called.

Audit log

Every attempt appends a JSON line to .offlocal/audit.log with: timestamp, project, environment, provider, tool, action summary, policy decision (allow/block/approval_required), result (success/error/not_executed), error message, and the provider resource used.

Project memory

Agents read/write short notes per project/environment (read_project_memory / write_project_memory). Memory is also bundled into get_project_context, so a future agent session sees what happened before — e.g. "Last Vercel deploy failed because DATABASE_URL was missing."


CLI (optional)

The MCP tools are the primary interface and most people never need the CLI — your agent does setup and inspection for you (Step 3 above). The offlocal CLI exists for scripting or seeding from a config file:

npx -p @offlocal/mcp offlocal init                # seed from .offlocal/config.yaml
npx -p @offlocal/mcp offlocal project create "Acme CRM"
npx -p @offlocal/mcp offlocal env add staging --kind staging
npx -p @offlocal/mcp offlocal map railway staging --resource '{"projectId":"<id>"}'
npx -p @offlocal/mcp offlocal context acme-crm --env staging

Installed globally (npm i -g @offlocal/mcp), drop the npx -p @offlocal/mcp prefix and just run offlocal ....


Develop from source

Contributing or running an unreleased build:

git clone https://github.com/adi4x4/offlocalai-mcp && cd offlocalai-mcp
npm install
npm run build        # compiles to dist/
npm test             # full test suite
npm run typecheck

Then point your agent at the local build with "command": "node", "args": ["./dist/index.js"] instead of the npx form above.


Architecture

src/
  types.ts           domain types (Workspace/Project/Environment/Connection/Mapping/PolicyRule/Audit/Memory)
  storage.ts         local-first JSON storage (.offlocal/)
  policy.ts          capability-based policy engine (the safety core)
  actions.ts         runGuarded() — the single choke point: policy + audit + execute
  context.ts         get_project_context bundle
  resolve.ts         project/environment/mapping resolution
  sql.ts             SQL classification (defense-in-depth)
  service.ts         business logic (used by both MCP tools and CLI)
  provider-actions.ts  guarded provider operations
  providers/         isolated REST adapters: github, vercel, supabase, stripe
  tools/index.ts     MCP tool registration
  index.ts           stdio MCP server entry
  cli.ts             offlocal CLI

Provider adapters are isolated and stateless (token in, data out). Adding a provider = one adapter file + a few guarded actions + tool registrations.


Roadmap

  • Approval flow — replace the approval_required response with a real approve/deny handshake (e.g. an approve_action tool + pending-action store).
  • More provider surface (Vercel git-backed deploys & file uploads, Supabase migrations, Stripe subscriptions/invoices).
  • More providers (the adapter interface is the extension point).
  • Optional SQLite backend + cross-process locking if state grows.

Known V0 limitations / TODOs

  • No real approval handshake yet — approval is granted by adding a policy rule.
  • Vercel create_deployment supports redeploy-by-id / git-backed deploys; full file-upload deploys are out of scope (documented in the research note).
  • Local SQL classification is defense-in-depth, not a security boundary — Supabase's backend read_only flag is the real enforcement for reads. For production, also use a read-only database role / restricted credentials so a misclassified statement can't write even if it slips past the classifier.
  • No cross-process file locking on .offlocal/state.json.
  • Stripe live writes are gated but, once allowed, are not transactional/rollback-able.

License

Apache License 2.0.