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

@vmenon25/mcp-server-webauthn-client

v0.0.5

Published

MCP server and CLI tool for generating WebAuthn TypeScript web clients

Readme

WebAuthn Client Generator - MCP Server

A Model Context Protocol (MCP) server that helps AI agents automatically generate complete WebAuthn web clients for testing authentication.

Overview

This MCP server provides AI agents with the ability to generate fully-functional WebAuthn web clients that connect to webauthn-server instances.

What Gets Generated

When you use this tool, you get a complete, zero-trust WebAuthn stack:

  • Envoy Gateway - Entry point with JWT authentication for protected routes
  • WebAuthn Server - FIDO2/Passkey authentication + JWT issuer
  • JWKS Endpoint (/.well-known/jwks.json) - Public key distribution for JWT verification
  • Example Service - Python FastAPI demo showing JWT-protected endpoints
  • PostgreSQL 15 - Credential storage with auto-schema initialization
  • Redis 7 - Session management
  • Jaeger - Distributed tracing (optional)
  • Docker Compose - Complete orchestration with secrets management
  • Playwright E2E Tests - Automated testing with Chromium virtual authenticator
  • TypeScript Web Client - Complete build toolchain and dev server

Key Feature: All services communicate through Envoy Gateway using JWT authentication verified via the JWKS endpoint, demonstrating a zero-trust architecture.

Generated Web Client Structure

web-client/
├── .gitignore                   # 🆕 Comprehensive gitignore for Node/TypeScript
├── package.json                 # All required dependencies
├── src/
│   ├── index.ts                # Entry point
│   ├── webauthn-client.ts      # Complete WebAuthn integration
│   ├── types.ts                # TypeScript type definitions
│   └── server.ts               # Express development server
├── public/
│   └── index.html              # Test UI
├── docker/                      # 🆕 Complete Docker stack
│   ├── docker-compose.yml      # PostgreSQL + Redis + WebAuthn Server
│   ├── init-db.sql             # Database schema initialization
│   ├── setup-secrets.sh        # Secret verification script
│   └── secrets/                # 🔐 Auto-generated passwords (gitignored)
│       ├── .gitignore          # Prevents accidental commits
│       ├── postgres_password   # Auto-generated 32-char password
│       └── redis_password      # Auto-generated 32-char password
├── tests/                       # 🆕 Playwright E2E tests
│   └── webauthn.spec.js        # Registration + Authentication tests
├── playwright.config.js         # Playwright configuration
├── global-setup.js              # Test setup (starts client server)
├── global-teardown.js           # Test cleanup
├── webpack.config.js            # Build configuration
├── tsconfig.json                # TypeScript configuration
├── tsconfig.build.json          # Build-specific TypeScript config
└── README.md                    # Usage instructions + security docs

Features

Single Focused Tool: generate_web_client

Generates a complete web client with:

  • TypeScript WebAuthn client with all critical integration patterns
  • Express development server (configurable port)
  • Complete build toolchain (Webpack, Babel, TypeScript)
  • Test UI with registration and authentication flows
  • Proper error handling for WebAuthn-specific errors
  • Type-safe implementation using published npm client library
  • Complete Docker stack (PostgreSQL + Redis + WebAuthn Server)
  • Secure password generation using crypto.randomBytes
  • Docker Compose secrets (no hardcoded credentials)
  • Playwright E2E tests with Chromium virtual authenticator
  • Auto-initialized database schema on first startup

Supported Frameworks

  • Vanilla TypeScript (default) - Currently implemented
  • React - Planned for future release
  • Vue - Planned for future release

Installation

Local Installation (Development)

cd mcp-server-webauthn-client
npm install  # Automatically builds dist/ via prepare script

Note: The dist/ directory is automatically built during npm install via the prepare script in package.json. For manual builds:

npm run build  # Build once
npm run dev    # Watch mode

Global Installation (For AI Agent Discovery)

npm install -g @vmenon25/mcp-server-webauthn-client

Usage

This package can be used in two ways:

  1. MCP Mode - For MCP-compatible AI agents (Claude Code, Continue.dev, Cline)
  2. CLI Mode - For non-MCP agents (Cursor, Aider, Windsurf) or direct usage

MCP Mode (For Claude Code & Compatible Agents)

  1. Add to your project's claude_config.json:
{
  "mcpServers": {
    "webauthn-client-generator": {
      "command": "npx",
      "args": [
        "-y",
        "@vmenon25/mcp-server-webauthn-client@latest"
      ]
    }
  }
}
  1. Use naturally in conversation:
You: "Please create a webauthn stack using the webauthn-client-generator MCP server."

Claude: I'll generate a complete web client for you using the WebAuthn client generator.

[Claude calls the generate_web_client tool]

✅ Web client generated successfully!

Files created:
  - ./web-client/package.json
  - ./web-client/src/webauthn-client.ts
  - ./web-client/src/types.ts
  - ./web-client/src/server.ts
  - ./web-client/public/index.html
  - ./web-client/webpack.config.js
  - ./web-client/tsconfig.json
  - ./web-client/README.md

Next steps:
1. cd web-client
2. npm install
3. npm run build
4. npm start
5. Open http://localhost:8082

Direct MCP Tool Call

The tool accepts these parameters:

{
  // Required
  project_path: string;                    // Where to create web client (e.g., './web-client')

  // Core Configuration
  framework?: 'vanilla' | 'react' | 'vue'; // Default: 'vanilla'
  server_url?: string;                     // Envoy Gateway URL (default: 'http://localhost:8000')
  forward_port?: number;                   // Client dev server port (default: 8082)

  // WebAuthn Configuration
  relying_party_id?: string;               // WebAuthn RP ID (default: 'localhost')
  relying_party_name?: string;             // WebAuthn RP name (default: 'WebAuthn Demo')

  // Infrastructure Port Customization (to avoid conflicts)
  postgres_host_port?: number;             // PostgreSQL host port (default: 5432)
  redis_host_port?: number;                // Redis host port (default: 6379)
  gateway_host_port?: number;              // Envoy Gateway host port (default: 8000)
  gateway_admin_port?: number;             // Envoy admin host port (default: 9901)

  // Jaeger Tracing Port Customization
  jaeger_ui_port?: number;                 // Jaeger UI port (default: 16686)
  jaeger_collector_http_port?: number;     // Jaeger collector HTTP (default: 14268)
  jaeger_collector_grpc_port?: number;     // Jaeger collector gRPC (default: 14250)
  jaeger_otlp_grpc_port?: number;          // Jaeger OTLP gRPC (default: 4317)
  jaeger_otlp_http_port?: number;          // Jaeger OTLP HTTP (default: 4318)
  jaeger_agent_compact_port?: number;      // Jaeger agent compact thrift UDP (default: 6831)
  jaeger_agent_binary_port?: number;       // Jaeger agent binary thrift UDP (default: 6832)
  jaeger_agent_config_port?: number;       // Jaeger agent config HTTP (default: 5778)
}

CLI Mode (Recommended for Non-MCP Agents)

The easiest way to use the client generator without MCP setup:

# Basic usage (generates in ./web-client)
npx -y @vmenon25/mcp-server-webauthn-client

# Custom path
npx -y @vmenon25/mcp-server-webauthn-client --path ./auth-client

# Custom server URL and forward port
npx -y @vmenon25/mcp-server-webauthn-client \
  --server http://localhost:9000 \
  --forward-port 3000

# Production server with custom relying party
npx -y @vmenon25/mcp-server-webauthn-client \
  --server https://auth.example.com

# Avoid port conflicts with existing infrastructure
npx -y @vmenon25/mcp-server-webauthn-client \
  --postgres-host-port 5433 \
  --redis-host-port 6380 \
  --gateway-host-port 8001

# Show help (lists all available options)
npx -y @vmenon25/mcp-server-webauthn-client --help

CLI Options:

Core Options:

  • -p, --path <path> - Directory to create web client (default: ./web-client)
  • -s, --server <url> - Envoy Gateway URL (default: http://localhost:8000)
  • -P, --forward-port <port> - Client dev server port (default: 8082)
  • -f, --framework <name> - Framework: vanilla|react|vue (default: vanilla)
  • -h, --help - Show help message with all options

Infrastructure Port Customization:

  • --postgres-host-port <port> - PostgreSQL host port (default: 5432)
  • --redis-host-port <port> - Redis host port (default: 6379)
  • --gateway-host-port <port> - Envoy Gateway host port (default: 8000)
  • --gateway-admin-port <port> - Envoy admin host port (default: 9901)

Jaeger Tracing Port Customization:

  • --jaeger-ui-port <port> - Jaeger UI port (default: 16686)
  • --jaeger-collector-http-port <port> - Jaeger collector HTTP (default: 14268)
  • --jaeger-collector-grpc-port <port> - Jaeger collector gRPC (default: 14250)
  • --jaeger-otlp-grpc-port <port> - Jaeger OTLP gRPC (default: 4317)
  • --jaeger-otlp-http-port <port> - Jaeger OTLP HTTP (default: 4318)
  • --jaeger-agent-compact-port <port> - Jaeger agent compact thrift UDP (default: 6831)
  • --jaeger-agent-binary-port <port> - Jaeger agent binary thrift UDP (default: 6832)
  • --jaeger-agent-config-port <port> - Jaeger agent config HTTP (default: 5778)

JWT Key Rotation Configuration (Advanced):

The generated WebAuthn stack includes automatic JWT signing key rotation for enhanced security (always enabled). These parameters control the rotation behavior using HOCON duration format:

CLI Parameters:

  • --jwt-rotation-interval <duration> - Time between key rotations (default: 180d = 6 months)
  • --jwt-grace-period <duration> - Grace period before retiring old key (default: 1h = 1 hour)
  • --jwt-retention <duration> - How long to keep retired keys for verification (default: 1h = 1 hour)
  • --jwks-cache-duration-seconds <seconds> - JWKS endpoint cache duration (default: 300 = 5 minutes)

Duration Format (HOCON Syntax):

  • Format: <number><unit> (e.g., 30s, 180d, 2h, 60m)
  • Supported units:
    • s, second, seconds
    • m, minute, minutes
    • h, hour, hours
    • d, day, days
  • Examples: "30s" (30 seconds), "2h" (2 hours), "180d" (180 days), "1 hour" (1 hour)

Production Example (6-month rotation with 1-hour grace period):

npx -y @vmenon25/mcp-server-webauthn-client \
  --jwt-rotation-interval 180d \
  --jwt-grace-period 1h \
  --jwt-retention 1h \
  --jwks-cache-duration-seconds 300

Testing Example (accelerated 30-second rotation for E2E tests):

npx -y @vmenon25/mcp-server-webauthn-client \
  --jwt-rotation-interval 30s \
  --jwt-grace-period 15s \
  --jwt-retention 30s \
  --jwks-cache-duration-seconds 5

How Key Rotation Works:

  1. Initial State: Server starts with first signing key (K1) in ACTIVE status
  2. Rotation Trigger: After rotation interval (e.g., 180 days), server generates new key (K2)
  3. Pending Phase: K2 is PENDING while K1 remains ACTIVE (seamless for existing tokens)
  4. Activation: After grace period (e.g., 1 hour), K2 becomes ACTIVE, K1 becomes RETIRED
  5. Cleanup: After retention period (e.g., 1 hour), K1 is deleted from database
  6. JWKS Endpoint: /.well-known/jwks.json always serves current ACTIVE + RETIRED keys for verification

Timeline Example (Production Settings):

T+0:        K1 ACTIVE → Rotation needed
T+0:        K2 PENDING generated
T+1h:       K2 ACTIVE, K1 RETIRED (grace period expired)
T+2h:       K1 deleted (retention period expired)
T+180d:     K3 PENDING generated, cycle repeats

Environment Variables (Alternative to CLI):

MPO_AUTHN_JWT_KEY_ROTATION_ENABLED: "true"
MPO_AUTHN_JWT_KEY_ROTATION_INTERVAL: "180d"
MPO_AUTHN_JWT_KEY_GRACE_PERIOD: "1h"
MPO_AUTHN_JWT_KEY_RETENTION: "1h"

Why HOCON Format?

  • Human-readable: "180d" is clearer than 15552000 seconds or 0.000347 days
  • Flexible: Same variable works for production (days) and testing (seconds)
  • Standard: Industry-standard format used by Kubernetes, Spring Boot, etc.
  • Safe: Native library parsing with clear error messages

Discovery File for Non-MCP Agents

For coding agents without native MCP support (Cursor, Aider, Windsurf, etc.), this tool can be discovered via the project's .ai-agents.json file:

Discovery URL: https://raw.githubusercontent.com/hitoshura25/mpo-api-authn-server/main/.ai-agents.json

How Non-MCP Agents Discover This Tool:

  1. Agent reads .ai-agents.json from the project root (~1500 tokens one-time cost)
  2. Finds mcp_servers.webauthn_client_generator section with complete usage documentation
  3. Suggests CLI command to user based on their requirements
  4. User runs command - tool executes locally (0 additional tokens)

Example Discovery Flow:

User: "I need a complete WebAuthn authentication stack for testing passkeys"

Agent (internal):
1. Reads .ai-agents.json from project
2. Finds webauthn-client-generator tool
3. Extracts CLI usage examples

Agent (response):
"I found a WebAuthn stack generator tool. Run this command to generate a complete authentication infrastructure:

npx -y @vmenon25/mcp-server-webauthn-client --path ./web-client

This will generate:
• Complete zero-trust architecture with Envoy Gateway
• WebAuthn Server Docker image (hitoshura25/webauthn-server)
• PostgreSQL + Redis + Jaeger infrastructure
• TypeScript web client with complete build toolchain
• E2E Playwright tests with virtual authenticator
• JWT authentication with JWKS endpoint

After generation:
1. cd web-client/docker && docker compose up -d  # Start infrastructure
2. cd .. && npm install && npm run build && npm start
3. npm test  # Run E2E tests
4. Open http://localhost:8082

What's in .ai-agents.json:

  • Complete tool description and usage examples
  • All CLI options with defaults
  • Critical integration patterns (JSON parsing, credential serialization)
  • Docker compose configuration examples
  • Common pitfalls and solutions

Benefits for Non-MCP Agents:

  • Accurate instructions: Based on official documentation
  • Complete examples: Working CLI commands ready to use
  • No manual configuration: Single command generates everything

What is MCP?

Model Context Protocol (MCP) is a standard protocol that allows AI agents like Claude to interact with external tools and services. MCP servers expose tools that AI agents can discover and use automatically to help users accomplish tasks.

Zero-Trust Architecture Explained

The generated stack implements a zero-trust architecture using industry-standard patterns:

1. Envoy Gateway as Entry Point

All traffic flows through Envoy Gateway - no direct access to backend services:

  • Public Routes (no authentication required):

    • /register/* - WebAuthn registration endpoints
    • /authenticate/* - WebAuthn authentication endpoints
    • /.well-known/jwks.json - Public key distribution (JWKS)
    • /health - Health check endpoint
  • Protected Routes (JWT authentication required):

    • /api/* - All application endpoints require valid JWT

2. JWKS Endpoint for JWT Verification

The JWKS (JSON Web Key Set) endpoint (/.well-known/jwks.json) provides public keys for JWT verification:

{
  "keys": [{
    "kty": "RSA",
    "use": "sig",
    "kid": "unique-key-id",
    "alg": "RS256",
    "n": "base64url-encoded-modulus",
    "e": "base64url-encoded-exponent"
  }]
}

How Envoy uses JWKS:

  1. Envoy Gateway fetches JWKS on startup and caches for 5 minutes
  2. When request comes to /api/*, Envoy extracts JWT from Authorization header
  3. Envoy verifies JWT signature using public key from JWKS
  4. If valid, request forwards to backend service; if invalid, returns 401 Unauthorized

Benefits:

  • ✅ JWT verification happens at gateway (zero-trust perimeter)
  • ✅ Backend services receive only verified requests
  • ✅ Key rotation supported via JWKS updates
  • ✅ No shared secrets between services

3. Example Service - Protected Endpoint Demo

The Example Service (Python FastAPI) demonstrates a protected microservice:

# Located at: web-client/example-service/main.py

@app.get("/api/example/data")
async def get_data():
    # This endpoint is protected by Envoy Gateway
    # JWT has already been verified before request reaches here
    return {"message": "Protected data", "timestamp": "..."}

Key Points:

  • Runs on port 9000 (not directly accessible from outside)
  • All requests come through Envoy Gateway
  • JWT already verified by Envoy (zero-trust model)
  • Service can extract user info from JWT claims

How to add your own protected services:

  1. Add service definition to docker/docker-compose.yml
  2. Add route to docker/envoy-gateway.yaml under protected routes
  3. Service receives only authenticated requests

4. mTLS Between Services (Phase 2)

The stack includes mTLS (mutual TLS) configuration between Envoy Gateway and backend services:

# envoy-gateway.yaml
transport_socket:
  name: envoy.transport_sockets.tls
  typed_config:
    common_tls_context:
      tls_certificates:  # Gateway's client cert
      validation_context:  # Validates service certs

Benefits:

  • ✅ Encrypted communication between services
  • ✅ Mutual authentication (both sides verify identity)
  • ✅ Protection against man-in-the-middle attacks
  • ✅ Zero-trust within the service mesh

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                      Generated Stack                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Web Client (TypeScript)                                        │
│  └─ http://localhost:8082                                       │
│         │                                                       │
│         │ WebAuthn Registration/Authentication                  │
│         ▼                                                       │
│  ┌────────────────────────────────────────┐                     │
│  │    Envoy Gateway (port 8000)           │                     │
│  │  ┌──────────────────────────────────┐  │                     │
│  │  │ Public Routes (no JWT required)  │  │                     │
│  │  │  ✓ /register/*                   │  │                     │
│  │  │  ✓ /authenticate/*               │  │                     │
│  │  │  ✓ /.well-known/jwks.json        │  │                     │
│  │  │  ✓ /health                       │  │                     │
│  │  └──────────────────────────────────┘  │                     │
│  │  ┌──────────────────────────────────┐  │                     │
│  │  │ Protected Routes (JWT required)  │  │                     │
│  │  │  ✓ /api/* → JWT verification via │  │                     │
│  │  │    JWKS endpoint                 │  │                     │
│  │  └──────────────────────────────────┘  │                     │
│  └─────┬──────────────┬─────────────────┘                       │
│        │              │                                         │
│        │              │ mTLS (Phase 2)                          │
│        ▼              ▼                                         │
│  ┌────────── ┐   ┌───────────────── ┐                           │
│  │ WebAuthn  │   │ Example Service  │                           │
│  │  Server   │   │  (Python/FastAPI)│                           │
│  │ :8080     │   │   :9000          │                           │
│  │           │   │                  │                           │
│  │ • Issues  │   │ • Validates JWT  │                           │
│  │   JWTs    │   │ • Protected      │                           │
│  │ • JWKS    │   │   /api/example/* │                           │
│  │   endpoint│   │   endpoints      │                           │
│  └────┬───── ┘   └───────────────── ┘                           │
│       │                                                         │
│       ├─ PostgreSQL 15 (credentials)                            │
│       ├─ Redis 7 (sessions)                                     │
│       └─ Jaeger (distributed tracing)                           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

JWT Authentication Flow:
1. User authenticates via WebAuthn → Server issues JWT
2. Client includes JWT in Authorization header for /api/* requests
3. Envoy Gateway fetches public key from /.well-known/jwks.json
4. Envoy verifies JWT signature using JWKS before forwarding request
5. Protected service receives verified request with JWT

Security Principles:
• Never trust, always verify (even internal traffic)
• JWT verification at perimeter (Envoy Gateway)
• Public key cryptography (JWKS) for verification
• mTLS for inter-service communication
• Secrets management via Docker secrets

Troubleshooting

Connection Refused Errors

Issue: ECONNREFUSED when accessing http://localhost:8000 or WebAuthn endpoints

Solution:

# Check if Docker stack is running
cd web-client/docker && docker compose ps

# Start services if not running
docker compose up -d

# Check service logs if issues persist
docker compose logs webauthn-server envoy-gateway

Prevention: Always run docker compose up -d BEFORE npm start

Port Already in Use

Issue: EADDRINUSE or "port already allocated" errors

Solution: Use custom ports when generating client:

npx -y @vmenon25/mcp-server-webauthn-client \
  --postgres-host-port 5433 \
  --redis-host-port 6380 \
  --gateway-host-port 8001 \
  --forward-port 3000 \
  --jaeger-ui-port 16687

Quick Fix: Kill process using the port:

lsof -ti:8000 | xargs kill -9

JWT Verification Failed (401 Unauthorized)

Issue: Protected endpoints return 401 Unauthorized even with JWT

Solutions:

  1. Check JWKS endpoint is accessible:

    curl http://localhost:8000/.well-known/jwks.json
  2. Verify JWT is included in Authorization header:

    fetch('http://localhost:8000/api/example/data', {
      headers: { 'Authorization': `Bearer ${jwtToken}` }
    })
  3. Restart Envoy to clear JWKS cache:

    cd docker && docker compose restart envoy-gateway

Generation Fails

Issue: Tool reports error during generation

Common Causes:

  • Directory already exists at project_path
  • Invalid framework name
  • Template files missing

Solution:

  • Choose different project_path or remove existing directory
  • Use 'vanilla', 'react', or 'vue' for framework
  • Rebuild MCP server: npm run build

Generated Client Won't Build

Issue: npm run build fails in generated client

Solution:

  1. Ensure all dependencies installed: npm install
  2. Check Node.js version: node --version (need 18+)
  3. Verify TypeScript version: npx tsc --version

Contributing

Contributions welcome! Please open an issue or pull request on the GitHub repository.

License

Apache-2.0

Links