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

@keycardai/mcp

v0.3.0

Published

High-security OAuth implementation for Model Context Protocol

Readme

@keycardai/mcp

MCP-specific OAuth integration for Keycard — Express middleware for bearer token verification, OAuth metadata serving, delegated access via token exchange, and MCP client providers.

Builds on @keycardai/oauth (included as a dependency). Part of the Keycard TypeScript SDK.

Installation

npm install @keycardai/mcp

This includes @keycardai/oauth automatically.

Quick Start

Protect an MCP Server with Bearer Auth

import express from "express";
import { requireBearerAuth } from "@keycardai/mcp/server/auth/middleware/bearerAuth";
import { mcpAuthMetadataRouter } from "@keycardai/mcp/server/auth/router";

const app = express();

// Mount OAuth metadata endpoints (.well-known)
app.use(
  mcpAuthMetadataRouter({
    oauthMetadata: { issuer: "https://your-zone.keycard.cloud" },
  }),
);

// Protect routes with bearer token verification
app.use("/api", requireBearerAuth({ requiredScopes: ["read"] }));

app.get("/api/data", (req, res) => {
  res.json({ message: "Authenticated!" });
});

Delegated Access (Token Exchange)

Exchange a user's bearer token for resource-specific tokens to call external APIs on their behalf:

import express from "express";
import { AuthProvider } from "@keycardai/mcp/server/auth/provider";
import { ClientSecret } from "@keycardai/mcp/server/auth/credentials";
import { requireBearerAuth } from "@keycardai/mcp/server/auth/middleware/bearerAuth";
import type { DelegatedRequest } from "@keycardai/mcp/server/auth/provider";

const authProvider = new AuthProvider({
  zoneUrl: "https://your-zone.keycard.cloud",
  applicationCredential: new ClientSecret("your-client-id", "your-client-secret"),
});

const app = express();
app.use(requireBearerAuth());

app.get(
  "/api/github-user",
  authProvider.grant("https://api.github.com"),
  async (req, res) => {
    const { accessContext } = req as DelegatedRequest;

    if (accessContext.hasErrors()) {
      return res.status(502).json(accessContext.getErrors());
    }

    const token = accessContext.access("https://api.github.com").accessToken;
    const response = await fetch("https://api.github.com/user", {
      headers: { Authorization: `Bearer ${token}` },
    });
    res.json(await response.json());
  },
);

MCP Client Provider

import { BaseOAuthClientProvider } from "@keycardai/mcp/client/auth/providers/base";

class MyOAuthProvider extends BaseOAuthClientProvider {
  constructor() {
    super(
      {
        redirect_uris: [new URL("http://localhost:3000/callback")],
        client_name: "My MCP Client",
      },
      "your-client-id",
    );
  }

  redirectToAuthorization(authorizationUrl: URL) {
    // Redirect user to authorization URL
    window.location.href = authorizationUrl.toString();
  }
}

API Overview

Server Auth Middleware

| Export | Import Path | Description | |---|---|---| | requireBearerAuth | @keycardai/mcp/server/auth/middleware/bearerAuth | Express middleware — verifies JWT bearer tokens, checks scopes, validates resource claims | | mcpAuthMetadataRouter | @keycardai/mcp/server/auth/router | Express router for .well-known/oauth-protected-resource and .well-known/oauth-authorization-server | | JWTOAuthTokenVerifier | @keycardai/mcp/server/auth/verifiers/jwt | Token verifier implementing the MCP SDK's OAuthTokenVerifier interface |

Delegated Access

| Export | Import Path | Description | |---|---|---| | AuthProvider | @keycardai/mcp/server/auth/provider | Coordinates token exchange — use .grant() as Express middleware or .exchangeTokens() standalone | | AccessContext | @keycardai/mcp/server/auth/provider | Result of a grant — contains tokens or errors per resource. Non-throwing by design | | DelegatedRequest (type) | @keycardai/mcp/server/auth/provider | Express Request extended with auth and accessContext |

Application Credentials

| Export | Import Path | Description | |---|---|---| | ClientSecret | @keycardai/mcp/server/auth/credentials | Client ID + secret authentication | | WebIdentity | @keycardai/mcp/server/auth/credentials | Private key JWT authentication (RFC 7523) with file-based key storage | | EKSWorkloadIdentity | @keycardai/mcp/server/auth/credentials | AWS EKS pod identity token authentication | | ApplicationCredential (type) | @keycardai/mcp/server/auth/credentials | Interface for custom credential implementations |

Client Auth

| Export | Import Path | Description | |---|---|---| | BaseOAuthClientProvider | @keycardai/mcp/client/auth/providers/base | Abstract base class implementing the MCP SDK's OAuthClientProvider interface | | JSONWebTokenSigner | @keycardai/mcp/client/auth/signers/jwt | Signs authentication headers with JWT for client-side auth |

Errors

| Export | Import Path | Description | |---|---|---| | ResourceAccessError | @keycardai/mcp/server/auth/errors | Token exchange failure for a specific resource | | AuthProviderConfigurationError | @keycardai/mcp/server/auth/errors | Missing zone configuration | | EKSWorkloadIdentityConfigurationError | @keycardai/mcp/server/auth/errors | EKS token file not found |

AccessContext Error Handling

AccessContext never throws during token exchange. Errors are captured and queryable:

const { accessContext } = req as DelegatedRequest;

const status = accessContext.getStatus(); // "success" | "partial_error" | "error"

if (accessContext.hasError()) {
  console.error(accessContext.getError()); // Global error (e.g., missing auth token)
}

if (accessContext.hasResourceError("https://api.github.com")) {
  console.error(accessContext.getResourceErrors("https://api.github.com"));
}

console.log("OK:", accessContext.getSuccessfulResources());
console.log("Failed:", accessContext.getFailedResources());

Related Packages

  • @keycardai/oauth — Pure OAuth 2.0 primitives (JWT, JWKS, discovery) without Express or MCP dependencies
  • @keycardai/sdk — Aggregate package re-exporting from both oauth and mcp
  • Keycard TypeScript SDK — Root documentation with full quick start and delegated access guide