Skip to content
reaatechREAATECH

@reaatech/media-pipeline-mcp-keyvault

npm v0.3.0

Multi-tenant API key vault that resolves tenant-scoped provider credentials from AWS Secrets Manager, GCP Secret Manager, environment variables, or in-memory storage, exposing `resolve()`, `get()`, and `health()` methods with LRU TTL caching.

@reaatech/media-pipeline-mcp-keyvault

npm version License: MIT CI

Status: Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.

Multi-tenant API key vault with AWS Secrets Manager, GCP Secret Manager, environment-variable, and in-memory backends. Provides tenant-scoped provider credential resolution with caching and health checks.

Installation

terminal
npm install @reaatech/media-pipeline-mcp-keyvault
terminal
pnpm add @reaatech/media-pipeline-mcp-keyvault

Cloud backends require optional peer dependencies:

terminal
# AWS Secrets Manager
pnpm add @aws-sdk/client-secrets-manager
 
# GCP Secret Manager
pnpm add @google-cloud/secret-manager

Feature Overview

  • Four vault backends: in-memory (dev/testing), environment variables, AWS Secrets Manager, GCP Secret Manager
  • Per-tenant provider credential resolution with budget caps, allowed provider/model lists, and metadata
  • LRU-style TTL caching to avoid secret manager round-trips on every call
  • Health check probes per backend
  • Tenant resolution strategies for multi-protocol tenant identification (header, JWT, OAuth scope, mTLS CN, static)

Quick Start

typescript
import { InMemoryKeyVault, EnvKeyVault } from '@reaatech/media-pipeline-mcp-keyvault';
 
// Development / testing: seed keys programmatically
const vault = new InMemoryKeyVault();
vault.set('acme', {
  openai: 'sk-...',
  stability: 'sk-...',
});
 
// Production-style: read from environment
// Expects ACME_OPENAI_API_KEY, ACME_STABILITY_API_KEY env vars
const envVault = new EnvKeyVault();
 
// Resolve all credentials for a tenant
const ctx = await vault.resolve('acme');
console.log(ctx.tenantId);
// → 'acme'
console.log(ctx.providerKeys.get('openai'));
// → 'sk-...'
 
// Get a single key
const key = await vault.get('acme', 'openai');
 
// Check backend health
const { healthy, latencyMs } = await vault.health();

AWS Secrets Manager

typescript
import { AwsSecretsManagerKeyVault } from '@reaatech/media-pipeline-mcp-keyvault';
 
const vault = new AwsSecretsManagerKeyVault({
  region: 'us-east-1',
  secretPrefix: 'mp/tenants', // defaults to 'mp/tenants'
  cacheTtlMs: 300_000,         // 5 min — default
});
 
// Secret stored at mp/tenants/acme:
// {
//   "openai": "sk-...",
//   "stability": "sk-...",
//   "budgetCaps": { "dailyUsd": 50 },
//   "allowedProviders": ["openai", "stability"],
//   "metadata": { "tier": "enterprise" }
// }
 
const ctx = await vault.resolve('acme');
console.log(ctx.budgetCaps?.dailyUsd); // 50
console.log(ctx.allowedProviders);      // ['openai', 'stability']

GCP Secret Manager

typescript
import { GcpSecretManagerKeyVault } from '@reaatech/media-pipeline-mcp-keyvault';
 
const vault = new GcpSecretManagerKeyVault({
  projectId: 'my-gcp-project',
  secretPrefix: 'mp-tenants', // defaults to 'mp-tenants'
  cacheTtlMs: 300_000,
});
 
// Secret stored at projects/my-gcp-project/secrets/mp-tenants-acme/versions/latest
// Same JSON shape as AWS above.

API Reference

Types

TypeDescription
TenantContextResolved tenant: tenantId, providerKeys (ReadonlyMap), optional budgetCaps, allowedProviders, allowedModels, metadata
KeyVaultInterface: resolve(tenantId), get(tenantId, key), health()
TenantResolutionStrategyDiscriminated union of tenant identification strategies: header, jwt, oauth-scope, mtls-cn, static, custom

Classes

ClassDescription
InMemoryKeyVaultProgrammatic seed for development and testing. Call set(tenantId, keys, overrides?) to register tenants.
EnvKeyVaultReads keys from env vars matching ${TENANT_ID}_${PROVIDER}_API_KEY (case-insensitive). Provider list is discovered dynamically.
AwsSecretsManagerKeyVaultAWS Secrets Manager backend. One secret per tenant at ${prefix}/${tenantId}, JSON payload. Supports configurable region, credentials, and cache TTL.
GcpSecretManagerKeyVaultGCP Secret Manager backend. One secret per tenant at projects/${projectId}/secrets/${prefix}-${tenantId}, latest version. Supports service-account key file and cache TTL.

AwsSecretsManagerKeyVaultConfig:

OptionTypeDefaultDescription
regionstring(required)AWS region
secretPrefixstringmp/tenantsPath prefix for tenant secrets
cacheTtlMsnumber300_000Cache lifetime in ms
credentialsobject(none)Explicit AWS credentials (accessKeyId, secretAccessKey, sessionToken)

GcpSecretManagerKeyVaultConfig:

OptionTypeDefaultDescription
projectIdstring(required)GCP project ID
secretPrefixstringmp-tenantsPrefix segment before -${tenantId}
cacheTtlMsnumber300_000Cache lifetime in ms
keyFilenamestring(none)Service account key file path

Secret Payload Format

All cloud backends expect the same JSON shape per tenant secret:

json
{
  "openai": "sk-...",
  "stability": "sk-...",
  "replicate": "r8_...",
  "budgetCaps": { "dailyUsd": 100, "monthlyUsd": 3000 },
  "allowedProviders": ["openai", "stability"],
  "allowedModels": ["gpt-4o-mini", "sd3"],
  "metadata": { "tier": "premium" }
}

Top-level string values are treated as provider API keys. The reserved keys budgetCaps, allowedProviders, allowedModels, and metadata populate the corresponding TenantContext fields.

Usage Patterns

Multi-Provider Tenant Setup

typescript
const vault = new InMemoryKeyVault();
vault.set('enterprise', {
  openai: process.env.OPENAI_KEY,
  anthropic: process.env.ANTHROPIC_KEY,
  google: process.env.GOOGLE_KEY,
}, {
  budgetCaps: { dailyUsd: 500, monthlyUsd: 10000 },
  allowedProviders: ['openai', 'anthropic', 'google'],
  allowedModels: ['gpt-4o', 'claude-3-opus', 'gemini-1.5-pro'],
  metadata: { tier: 'enterprise' },
});

Health Check

The health() method returns { healthy, latencyMs }. Cloud backends issue a synthetic secret lookup and treat NOT_FOUND / ResourceNotFoundException as healthy (the service responded); other errors indicate unavailability.

License

MIT