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

patless

v0.1.1

Published

Vendor-neutral GitHub OIDC exchange, PAT migration, and lifecycle proof for MCP agents

Readme

PATless

Remove long-lived PATs from MCP agent workflows.

PATless is a vendor-neutral GitHub Action and CLI. The Action exchanges a job's OIDC identity with your authorization provider for a short-lived credential bound to one MCP resource:

- uses: bharath31/patless@FULL_40_CHARACTER_COMMIT_SHA
  id: mcp_auth
  with:
    token_endpoint: https://auth.example.com/oauth/token
    audience: https://auth.example.com/workloads
    resource: https://mcp.example.com/mcp
    scope: tools:read

The CLI finds existing PAT references, generates conservative GitHub Actions migrations, and proves the new credential can be granted, used, revoked, and rejected after revocation:

patless scan
patless migrate ...
patless prove ...

No browser flow. No required identity vendor. No secret values in scan reports, migration manifests, lifecycle evidence, or broker audit events.

PATless is not an identity provider. Auth0, a cloud authorization service, or the bundled reference broker can sit behind it. The Action handles the runtime exchange; the CLI handles find → replace → prove.

v0.1 is an early preview, not a production release. The reference broker is single-process, and the workload-identity exchange follows the request shape under discussion in MCP SEP-1933. Pin integrations and expect that draft contract to evolve.

The GitHub Actions problem

A coding agent needs to call a protected MCP server from CI, so the workflow gets a standing credential:

jobs:
  agent:
    permissions:
      contents: read
    steps:
      - name: Run MCP coding agent
        env:
          MCP_TOKEN: ${{ secrets.ENGINEERING_MCP_PAT }}
        run: npx coding-agent

GitHub encrypts the secret value, but the PAT can still outlive the job, be reused outside that workload, cover more than one MCP resource, and require manual rotation. Moving it to a different secret store protects storage; it does not remove the standing credential.

GitHub Actions can instead mint an ephemeral OIDC identity for one job. PATless adds the missing last mile: discover the old reference, wire that identity to the team's chosen token endpoint, and verify the replacement end to end. GitHub documents that id-token: write only permits requesting the OIDC token; it does not itself grant repository or resource access (GitHub OIDC reference).

After migration, the workflow uses an exchange step and passes only its short-lived output to the agent:

jobs:
  agent:
    permissions:
      contents: read
      id-token: write
    steps:
      - name: Exchange GitHub identity for MCP credential
        id: mcp_auth
        uses: bharath31/patless@0123456789abcdef0123456789abcdef01234567
        with:
          token_endpoint: https://auth.example.com/oauth/token
          audience: https://auth.example.com/workloads
          resource: https://mcp.example.com/mcp
          scope: tools:read tools:call

      - name: Run MCP coding agent
        env:
          MCP_TOKEN: ${{ steps.mcp_auth.outputs.access_token }}
        run: npx coding-agent

The exact action SHA above is illustrative. Replace it with the published commit you reviewed; PATless refuses --apply with a floating action tag.

Try it from source

PATless currently requires Node.js 22 or newer.

npm install -g patless

Or work from source:

npm install
npm test
npm run demo:github-actions

The demo creates a disposable GitHub Actions workflow containing a PAT reference, scans it, applies the migration, re-scans it, then starts a local OIDC issuer, HTTP broker, and MCP echo server. It exchanges two fresh assertions, makes one allowed MCP tool call, revokes the credential, retries it, and emits secret-free evidence of the HTTP 401 denial. npm run demo:lifecycle runs only the broker lifecycle.

1. Find

node ./bin/patless.js scan --root . --out patless-scan.json

The GitHub Actions scanner currently detects:

  • likely MCP credential references such as ${{ secrets.MCP_PAT }} in step-level env and with values;
  • well-known hardcoded GitHub and GitLab PAT formats in workflow and MCP configuration files; and
  • whether a workflow can be rewritten without guessing about implicit GitHub permissions.

It does not call the GitHub Secrets API or resolve ${{ secrets.* }}. Hardcoded values are redacted before entering a finding. ${{ secrets.GITHUB_TOKEN }} is ignored because GitHub creates that token per job; PATless targets standing credentials for other protected MCP resources.

Use the scanner as a CI guard after migration:

node ./bin/patless.js scan --root . --fail-on findings

Exit code 2 means the selected threshold found credential debt; operational errors use exit code 1.

2. Replace

Preview a migration first:

node ./bin/patless.js migrate \
  --report patless-scan.json \
  --token-endpoint https://auth.example.com/oauth/token \
  --audience https://auth.example.com/workloads \
  --resource https://mcp.example.com/mcp \
  --scope tools:read \
  --scope tools:call \
  --action bharath31/patless@FULL_40_CHARACTER_COMMIT_SHA

The default is a dry run. Apply the reviewed change explicitly:

node ./bin/patless.js migrate \
  --report patless-scan.json \
  --token-endpoint https://auth.example.com/oauth/token \
  --audience https://auth.example.com/workloads \
  --resource https://mcp.example.com/mcp \
  --scope tools:read \
  --scope tools:call \
  --action bharath31/patless@FULL_40_CHARACTER_COMMIT_SHA \
  --apply

PATless preserves an explicit job permission map, or copies an explicit workflow-level map into only the changed job before adding id-token: write. If permissions are implicit or expressed as a scalar such as read-all, it stops and explains the manual prerequisite. It will not silently change the effective permissions of a working job.

An applied migration writes a manifest under .patless/. The manifest contains file hashes and removed reference names, never credential values. PATless immediately re-scans the repository and records whether each migrated reference is absent.

That removes the standing credential from the workload, but it does not invalidate the original value at its issuer. The manifest marks legacy credential retirement as a required external action: revoke the old PAT where it was issued, then delete the obsolete GitHub secret.

3. Prove

From a GitHub Actions job with id-token: write:

node ./bin/patless.js prove \
  --github \
  --migration .patless/migration_ID.json \
  --token-endpoint https://auth.example.com/oauth/token \
  --revoke-endpoint https://auth.example.com/oauth/revoke \
  --audience https://auth.example.com/workloads \
  --resource https://mcp.example.com/mcp \
  --scope tools:read \
  --method tools/list

prove requests a fresh workload assertion for grant and another for revocation. It succeeds only when all checks pass:

  1. the migrated PAT reference is still absent;
  2. the provider grants a resource-bound, scoped credential;
  3. that credential completes the requested MCP operation;
  4. revocation succeeds; and
  5. the same MCP request then receives an actionable HTTP 401 Bearer challenge.

The resulting patless.lifecycle-proof/v1 document contains timestamps, scopes, resource identifiers, HTTP outcomes, and scan/migration IDs. It never contains either OIDC assertion or the issued access token.

The lifecycle proof revokes the new short-lived credential to verify fail-closed behavior. It does not claim to revoke the old PAT; retirement of that credential remains an issuer-specific release step.

Provider contract

The exchange action is vendor-neutral at the protocol boundary. It sends this form request:

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
assertion=<ephemeral workload JWT>
resource=<canonical MCP server URI>
scope=<space-separated scopes>

The token endpoint returns an OAuth Bearer access_token and should return expires_in, scope, and resource. The resource value is mandatory in PATless because current MCP authorization requires tokens to be issued for the canonical MCP server URI (MCP authorization specification).

The v0.1 proof runner uses the reference broker's revocation profile: a form POST containing a fresh assertion and the short-lived token. Providers with a different revocation contract need a small adapter. See the provider contract.

Is this competing with Auth0?

No. If Auth0 accepts GitHub workload identity and returns a resource-bound MCP credential, it is a PATless backend. Auth0 owns identity policy and token issuance; PATless owns discovery, repository migration, and lifecycle evidence. If a runtime implements the exchange natively, PATless can generate that runtime configuration instead of its own action.

Reference broker

The bundled broker exists so a team can test the complete lifecycle without waiting for a provider integration. It validates OIDC signatures and exact issuer/audience/subject policy; rejects reused jti values; caps access-token lifetime to both broker policy and source-identity expiry; binds every token to one configured MCP resource; removes bearer credentials before proxying; and stores only SHA-256 token hashes.

It also publishes OAuth authorization-server metadata, RFC 9728 protected-resource metadata, standards-shaped Bearer challenges, and uses the MCP 2026-07-28 per-request HTTP metadata (MCP-Protocol-Version, Mcp-Method, and Mcp-Name).

node ./bin/patless.js serve --config ./examples/broker.config.json

The reference broker is intentionally single-process. Credentials and revocations live in memory; restart invalidates all of them. Do not run multiple replicas or expose the upstream MCP server around the broker. See the HTTP API and threat model.

What PATless does not claim

  • It cannot replace a PAT unless the target MCP resource or its authorization service accepts workload federation.
  • A short-lived access token is still a bearer credential during its lifetime; “PATless” does not mean tokenless.
  • The first scanner targets GitHub Actions and common MCP config files, not every CI or workload platform.
  • It does not provide end-user OAuth consent, SSO, a gateway fleet, SIEM integration, or an enterprise dashboard.
  • The bundled MCP server is a protocol test target, not the official MCP conformance suite.
  • v0.1 evidence is structured but not cryptographically signed; preserve it in a trusted CI artifact store or attach your own attestation.

Product and release status

The product is a personal project by Bharath Natarajan under bharath.sh. The public surfaces are patless.bharath.sh, bharath31/patless, the npm package patless, and the patless CLI. mcp-auth and headless-auth remain temporary compatibility aliases during the rename.

PATless is copyright 2026 Bharath Natarajan and licensed under the Apache License 2.0. Before relying on the GitHub Action, pin it to the full commit SHA you reviewed. The reference broker remains a lifecycle test implementation, not a production authorization service.