mpp-mcp-gateway
mpp-mcp-gateway
MCPサーバーを、Tempoブロックチェーン上のMachine Payments Protocol(MPP)によるステーブルコインのマイクロペイメントで収益化します。
AIエージェントに対して、呼び出しごと、セッションごと、またはアクセスキーごとに課金するMCPツールサーバーを構築できます。決済はpathUSDおよびその他のTIP-20ステーブルコインで行われます。また、設定可能な支出上限に基づいて、これらのツールに自動的に支払うAIエージェントクライアントを構築できます。
目次
Related MCP server: easy-mcp
概要
mpp-mcp-gateway は、MCP(Model Context Protocol)サーバーにステーブルコインのマイクロペイメントゲーティングを追加するTypeScriptライブラリです。AIエージェントが有料ツールを呼び出すと、サーバーは402 Payment Requiredチャレンジを発行します。エージェントのクライアントはTempoブロックチェーン上で支払いトランザクションに署名し、資格情報を付けて呼び出しを再試行します。サーバーはハンドラーを実行してレシート付きで結果を返す前に、決済を検証します。
主な機能:
4つの価格モデル — 従量課金(per-call)、段階的(tiered)、セッション(支払いチャネル)、アクセスキー(サブスクリプション)
マルチカレンシー対応 — ツールごとに複数のTIP-20ステーブルコインを受け付け
正確な収益追跡 — BigInt演算により、数百万件のサブセント支払いでも浮動小数点のずれを防止
プラグ可能なストレージ — インメモリ、Upstash Redis(アトミックCAS)、Cloudflare KV、または独自実装
レート制限 — トークンバケット(インメモリまたはRedisバックエンド)とツールごとの上書き設定
認証ミドルウェア — ベアラートークン、APIキー、HTTP Basic、署名付きURL、CORS — すべてタイミングセーフ
Prometheusメトリクス —
/metricsエンドポイント、依存関係ゼロOpenTelemetryトレーシング — 有料呼び出しごとのオプトインのスパンツリー、無効時はコストゼロ
ウェブフック — HMAC署名付きイベントプッシュ、リトライ、バックオフ、デッドレターフック付き
サービスディスカバリー —
x-payment-info拡張機能を備えたOpenAPI 3.1(mpp.landがクロール)ダッシュボード — ライブ収益と呼び出し監視のためのReact UI + JSON API
グレースフルシャットダウン — 実行中の呼び出しをドレインし、フックを発火し、ウェブフックを決済
ランタイムポータブル — Node.js 20+、Cloudflare Workers、Vercel Edge、Deno、Bunで動作
仕組み
┌─────────────┐ 402 Challenge ┌──────────────────┐
│ AI Agent │ ────────────────────────────── │ Paid MCP Server │
│ (Client) │ │ (Gateway) │
│ │ ◄── Payment Required (-32042) │ │
│ │ │ │
│ Signs tx │ ── Credential (signed payment) │ Verifies on │
│ via mppx │ ──► │ Tempo chain │
│ │ │ │
│ │ ◄── Tool Result + Receipt │ Runs handler │
└─────────────┘ └──────────────────┘エージェントがMCP経由で有料ツールを呼び出す
サーバーがMPPチャレンジを含むMCPエラーコード
-32042で応答するクライアントが支出上限を適用し、支払いに署名し、資格情報を付けて再試行する
サーバーが
mppx経由でオンチェーン決済を検証するハンドラーが実行され、支払いレシート(txハッシュ、タイムスタンプ)とともに結果が返される
インストール
npm install mpp-mcp-gatewayピア依存関係(使用するものだけをインストール):
# For HTTP/Express transports and dashboard
npm install express
# For Upstash Redis stores / rate limiting
npm install @upstash/redis
# For OpenTelemetry tracing
npm install @opentelemetry/api
# For Cloudflare Workers KV store
npm install @cloudflare/workers-typesクイックスタート
サーバー(ツールプロバイダー)
import { createPaidMcpServer } from 'mpp-mcp-gateway/server'
import { z } from 'zod'
const server = createPaidMcpServer({
name: 'my-api',
version: '1.0.0',
recipient: '0xYourWalletAddress',
secretKey: process.env.PAYMENT_SECRET_KEY!,
network: 'testnet',
tools: [
{
name: 'get_weather',
description: 'Get weather for a city. $0.001 per call.',
inputSchema: { city: z.string() },
pricing: { type: 'per-call', amount: '0.001' },
handler: async ({ city }) => ({
content: [{ type: 'text', text: `Weather in ${city}: 72°F, sunny` }],
}),
},
{
name: 'ping',
description: 'Free liveness check.',
inputSchema: {},
// No pricing = free tool
handler: async () => ({
content: [{ type: 'text', text: 'pong' }],
}),
},
],
})
await server.startStdio()クライアント(AIエージェント)
import { createPaidMcpClient } from 'mpp-mcp-gateway/client'
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
const client = createPaidMcpClient({
name: 'my-agent',
version: '1.0.0',
privateKey: process.env.AGENT_PRIVATE_KEY! as `0x${string}`,
maxPerCall: '0.10', // safety cap: max $0.10 per single call
maxTotal: '10.00', // safety cap: max $10.00 total spend
network: 'testnet',
})
const transport = new StdioClientTransport({
command: 'node',
args: ['server.js'],
})
await client.connect(transport)
// Free call — no payment required
const ping = await client.callTool('ping')
console.log(ping.content[0].text) // "pong"
console.log(ping.paid) // false
// Paid call — automatic 402 → sign → retry
const weather = await client.callTool('get_weather', { city: 'Tokyo' })
console.log(weather.content[0].text) // "Weather in Tokyo: 72°F, sunny"
console.log(weather.paid) // true
console.log(weather.receipt?.reference) // "0xabc...def" (tx hash)
await client.close()価格モデル
従量課金(Per-Call)
呼び出しごとの固定価格です。1回の呼び出しにつき1つのオンチェーントランザクションが必要です。
pricing: { type: 'per-call', amount: '0.001' }段階的(Tiered)
累計呼び出し回数に応じて価格が下がる(または上がる)方式です。
pricing: {
type: 'tiered',
tiers: [
{ upTo: 100, amount: '0.01' },
{ upTo: 1000, amount: '0.005' },
{ upTo: 'unlimited', amount: '0.001' },
],
}セッション(支払いチャネル)
エージェントはオンチェーンのエスクローチャネルを一度だけ開きます。以降の呼び出しでは、署名済みバウチャーをオフチェーンで送信します。サーバーはチャネルが閉じられたときに最も高いバウチャーを決済します。ストリーミングや高頻度のツールに最適です。
pricing: {
type: 'session',
amount: '0.0005', // per-unit price
unitType: 'request', // informational label
suggestedDeposit: '0.50', // hint for initial channel funding
}クライアント側のセッション管理:
// Make multiple calls against the same channel
await client.callTool('think', { topic: 'AI alignment' })
await client.callTool('think', { topic: 'quantum computing' })
// Cooperatively close and settle on-chain
const result = await client.closeSession('think')
console.log(result.receipt.reference) // settlement tx hashアクセスキー(サブスクリプション)
エージェントは前払いで一度だけ支払い、不透明なトークンを受け取ります。以降の呼び出しではそのトークンを提示します。キーが期限切れになるか使い切られるまで追加の支払いは不要です。「デイパスを購入」や「N回分の呼び出しを購入」といったUXに最適です。
pricing: {
type: 'access-key',
amount: '0.01', // upfront cost
validFor: '1d', // time limit (supports: 60s, 30m, 4h, 7d)
maxCalls: 100, // call limit (at least one of validFor/maxCalls required)
}クライアントはキャッシュを自動的に処理します:
// First call: pays $0.01, receives access key
const r1 = await client.callTool('premium_data', { query: 'foo' })
console.log(r1.paid) // true
console.log(r1.accessKey?.justIssued) // true
console.log(r1.accessKey?.remainingCalls) // 99
// Subsequent calls: free (key presented in _meta)
const r2 = await client.callTool('premium_data', { query: 'bar' })
console.log(r2.paid) // falseマルチカレンシー
どの価格モデルでも複数のTIP-20ステーブルコインを受け付けることができます:
pricing: {
type: 'per-call',
amount: '0.001',
accept: [
{ currency: '0x20c0...0000', amount: '0.001' }, // pathUSD
{ currency: '0x20c0...0001', amount: '0.001' }, // alphaUSD
],
}サーバーAPI
import { createPaidMcpServer, PaidMcpServer } from 'mpp-mcp-gateway/server'
const server = createPaidMcpServer(config)
// Start on stdio (for CLI / subprocess use)
await server.startStdio()
// Or access the underlying McpServer for custom transports
const mcpServer = server.server
await mcpServer.connect(someTransport)
// Runtime inspection
server.getStats() // GatewayStats (calls, revenue, sessions, keys)
server.listTools() // tool names, descriptions, current prices
server.getRecentCalls(100) // last N calls from the ring buffer
server.getInFlightCount() // currently active handlers
server.isShuttingDown() // true after close() begins
server.describe() // full descriptor for discovery/OpenAPI
// Access-key management
await server.listAccessKeys() // live keys issued by this instance
await server.revokeAccessKey(token) // { revoked: boolean }
// Graceful shutdown
await server.close({ timeoutMs: 25_000 })クライアントAPI
import { createPaidMcpClient, PaidMcpClient } from 'mpp-mcp-gateway/client'
const client = createPaidMcpClient(config)
await client.connect(transport)
await client.listTools()
const result = await client.callTool('tool_name', { arg: 'value' })
// Spending state
client.getSpending() // { totalSpent, remaining, maxTotal, maxPerCall, ... }
client.resetSpending() // reset cumulative counter (for tests)
// Access key management
client.getAccessKeys() // cached keys by tool name
client.clearAccessKey('tool') // force re-payment on next call
client.clearAccessKeys() // drop all cached keys
// Session management
client.getOpenSessions() // open channels by tool name
await client.closeSession('tool') // settle channel on-chain
await client.close()トランスポート
ゲートウェイは任意のMCPトランスポートで動作します。同梱の例:
トランスポート | ユースケース | 例 |
stdio | CLIツール、サブプロセス起動 |
|
Streamable HTTP | ネットワークサーバー(モダン) |
|
SSE(レガシー) | 旧来のMCPクライアント |
|
In-Memory | テスト、同一プロセス |
|
ストアアダプター
ゲートウェイは、アクセスキーレコードとセッションチャネル状態を永続化するためのプラグ可能な MppMcpStore インターフェースを使用します。
import { Store } from 'mpp-mcp-gateway/stores'アダプター | 原子性 | ユースケース |
| アトミック(プロミスチェーン) | テスト、ローカル開発、単一インスタンス |
| アトミック(Lua CAS) | 本番、複数インスタンス |
| ベストエフォート | エッジアクセスキー(セッション用ではない) |
| ベストエフォート | mppxストアとの後方互換 |
Upstashの例
import { Redis } from '@upstash/redis'
import { createUpstashStore } from 'mpp-mcp-gateway/stores'
const store = createUpstashStore(
new Redis({ url: process.env.UPSTASH_URL!, token: process.env.UPSTASH_TOKEN! }),
{ keyPrefix: 'mppmcp:', ttlSeconds: 30 * 24 * 3600 }
)
const server = createPaidMcpServer({
// ...
accessKeyStore: store,
sessionStore: store,
})カスタムストア
4つのメソッドからなるインターフェースを実装します:
interface MppMcpStore {
get<T>(key: string): Promise<T | null>
put(key: string, value: unknown): Promise<void>
delete(key: string): Promise<void>
update<T>(key: string, transform: (current: T | null) => T | null): Promise<T | null>
}update メソッドはアトミックな読み取り-変更-書き込みを保証する必要があります。競合が発生した場合(CAS方式のバックエンド)、transform コールバックが複数回呼び出される可能性があります。
レート制限
レート制限は支払いおよびハンドラーロジックの前に実行されます。拒否された呼び出しは402を発行せず、ハンドラーも実行されません。
const server = createPaidMcpServer({
// ...
rateLimit: {
refillPerMinute: 60, // sustained rate
capacity: 10, // burst capacity
perTool: {
expensive_ai: { refillPerMinute: 5, capacity: 2 },
cheap_lookup: { refillPerMinute: 600, capacity: 100 },
},
// Custom bucketing (e.g. per-session on HTTP transports)
keyExtractor: (toolName, extra) => `${toolName}:${extra.sessionId ?? 'default'}`,
},
})複数インスタンスのデプロイでは、Upstashバックエンドのリミッターを使用します:
import { upstashTokenBucketLimiter } from 'mpp-mcp-gateway/rate-limit'
const limiter = upstashTokenBucketLimiter(redis, {
keyPrefix: 'mppmcp:rl:',
refillPerMinute: 120,
capacity: 20,
})
const server = createPaidMcpServer({
// ...
rateLimit: { limiter },
})認証ミドルウェア
ダッシュボード、メトリクス、ディスカバリーの各エンドポイントを保護するための5つのExpressミドルウェアファクトリー:
import { auth } from 'mpp-mcp-gateway'
// Bearer token (constant-time comparison)
mountDashboard(server, app, {
middleware: auth.bearerToken(process.env.DASHBOARD_TOKEN!, { realm: 'admin' }),
})
// API key in custom header
mountMetrics(server, app, {
middleware: auth.apiKey({ header: 'x-api-key', value: process.env.METRICS_KEY! }),
})
// HTTP Basic Auth (multi-user)
mountDashboard(server, app, {
middleware: auth.basicAuth({ users: { admin: 'secret' }, realm: 'gateway' }),
})
// HMAC-signed URLs with TTL
mountDashboard(server, app, {
middleware: auth.signedQuery({ secret: process.env.URL_SECRET!, ttlSeconds: 300 }),
})
// Public CORS for registry crawlers
mountDiscovery(server, app, {
middleware: auth.publicCors(),
})ダッシュボードとモニタリング
JSON API
import { mountDashboard } from 'mpp-mcp-gateway'
mountDashboard(server, app, { prefix: '/api' })公開エンドポイント:
エンドポイント | レスポンス |
|
|
|
|
|
|
|
|
|
|
Prometheusメトリクス
import { mountMetrics } from 'mpp-mcp-gateway'
mountMetrics(server, app, {
middleware: auth.bearerToken(process.env.METRICS_TOKEN!),
})公開メトリクス:
mppmcp_calls_total{tool}— ツール別カウンターmppmcp_calls_by_mode_total{mode}— paid、free、session、access_key、totalmppmcp_revenue_micro_usd_total{tool}— マイクロUSD単位の累計収益mppmcp_in_flight_calls— 実行中ハンドラーのゲージmppmcp_access_keys_issued_total/expired_totalmppmcp_sessions_opened_total/closed_totalmppmcp_rate_limited_total— レートリミッターによって拒否された呼び出しmppmcp_rejected_shutting_down_total— シャットダウン中に拒否された呼び出しmppmcp_uptime_secondsmppmcp_shutting_down
Reactダッシュボード
ビルド済みのReact + Viteダッシュボードは dashboard/ にあります。JSON APIを2秒ごとにポーリングし、以下を表示します:
収益カウンターと収益順にソートされたツールテーブル
支払いモードごとに色分けされたライブ呼び出しログ
アクセスキーとセッションの統計
cd dashboard
npm install
npm run builddashboard/dist/ をExpressアプリから静的ファイルとして配信します。
サービスディスカバリー
MPPサービスディスカバリーIETFドラフトに従い、x-payment-info 拡張機能を含むOpenAPI 3.1ドキュメントを生成して配信します。mpp.landなどの公開レジストリがこれを自動的にクロールします。
import { mountDiscovery } from 'mpp-mcp-gateway'
mountDiscovery(server, app, {
baseUrl: 'https://api.example.com',
categories: ['data', 'search'],
docs: { homepage: 'https://example.com/docs' },
})
// GET /openapi.json → OpenAPI 3.1 with x-payment-info per toolウェブフック
HMAC-SHA-256署名付きでイベントをURLにプッシュします。配信はファイアアンドフォーゲット(非ブロッキング)で、リトライと指数バックオフ付きです。
const server = createPaidMcpServer({
// ...
webhooks: {
url: 'https://example.com/webhook',
secret: process.env.WEBHOOK_SECRET!,
events: ['payment.received', 'session.closed'], // or omit for all
maxAttempts: 3,
onDrop: async (event, lastError) => {
// Dead-letter: persist to DB for replay
await db.insert('webhook_dlq', { event, error: lastError })
},
},
})イベントタイプ: payment.received、access-key.issued、access-key.expired、session.opened、session.closed、call.failed
受信側の検証:
import { createHmac } from 'node:crypto'
function verify(req) {
const expected = 'sha256=' + createHmac('sha256', WEBHOOK_SECRET)
.update(`${req.headers['x-mppmcp-timestamp']}.${req.body}`)
.digest('hex')
return timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers['x-mppmcp-signature']))
}OpenTelemetryトレーシング
オプトイン方式です。トレーサーを渡すと、有料呼び出しごとにスパンツリーが取得できます。無効時はオーバーヘッドゼロです。
import { trace } from '@opentelemetry/api'
const server = createPaidMcpServer({
// ...
tracer: trace.getTracer('mpp-mcp-gateway', '1.0.0'),
})スパンツリー:
mppmcp.tool.call (root)
├── mppmcp.payment.charge (or mppmcp.session.advance, mppmcp.access-key.redeem)
└── mppmcp.handler.run属性: mppmcp.tool.name、mppmcp.pricing.type、mppmcp.amount、mppmcp.payment.mode、mppmcp.payment.tx-hash、mppmcp.session.action、mppmcp.error.code
オペレーターCLI
デプロイ済みゲートウェイをコマンドラインから検査および管理します:
npx mpp-mcp inspect https://my-gateway.fly.dev --token=secret123
npx mpp-mcp stats https://api.example.com
npx mpp-mcp tools https://api.example.com
npx mpp-mcp calls https://api.example.com --limit=50
npx mpp-mcp keys list https://api.example.com --token=admin
npx mpp-mcp keys revoke mppmcp_abc123... https://api.example.com --token=admin設定リファレンス
サーバー(PaidMcpServerConfig)
フィールド | 型 | デフォルト | 説明 |
|
| 必須 | クライアントに通知されるサーバー名 |
|
| 必須 | サーバーバージョン |
|
| 必須 | 支払いを受け取るウォレットアドレス |
|
| 必須 | 支払いチャレンジをバインドするためのHMACキー |
|
| 必須 | ハンドラー付きのツール定義 |
|
| pathUSD | TIP-20ステーブルコインのコントラクトアドレス |
|
|
| Tempoネットワーク |
|
| — | サーバー負担のガス(フィーペイヤーの秘密鍵) |
|
| — | セッション決済に必要なオペレーターキー |
|
| ネットワークごとのデフォルト | セッションのエスクローコントラクト |
|
| インメモリ | アクセスキーの永続化 |
|
| インメモリ | セッションチャネルの永続化 |
|
|
| キーを支払いウォレットにバインド |
|
|
| リングバッファ容量(0 = 無効) |
|
| console+redaction | 構造化ロガー |
|
|
| グレースフルシャットダウンのタイムアウト |
|
| — | ドレイン開始時に発火するフック |
| object | 60/min per tool | レート制限の設定 |
|
| — | OpenTelemetryトレーサー(オプトイン) |
|
| — | イベントプッシュの設定 |
クライアント(PaidMcpClientConfig)
フィールド | 型 | デフォルト | 説明 |
|
| required | クライアント名 |
|
| required | クライアントバージョン |
|
| required | エージェントウォレットの秘密鍵 |
|
|
| 1回の呼び出しあたりの最大支出(USD) |
|
|
| 累計最大支出(USD) |
|
|
| チャネル最大預入額(USD) |
|
|
| Tempoネットワーク |
|
| console+redaction | 構造化ロガー |
|
|
| セッション決済トランザクションをオンチェーンで検証 |
例
例 | 料金体系 | トランスポート | デモ内容 |
| 呼び出しごと | InMemory | 単一プロセスでの完全な402ラウンドトリップ |
| 呼び出しごと | stdio | エージェントがサーバーをサブプロセスとして起動 |
| 呼び出しごと | Streamable HTTP | Express上のネットワークサーバー |
| 呼び出しごと | SSE (legacy) | 後方互換のSSEトランスポート |
| 呼び出しごと + アクセスキー | Streamable HTTP | MCP + ダッシュボード + ディスカバリの組み合わせ |
| セッション | stdio | ペイメントチャネル、バウチャー、クローズ |
| アクセスキー | stdio | デイパス、時間限定、コールパック |
| 呼び出しごと | stdio | Peer Cashツールをゲートし、MPP収益を現金化 |
任意の例を実行:
# In-memory demo (no wallet needed)
npm run example:demo
# Server + client pairs
npm run example:server # then in another terminal:
npm run example:client
npm run example:http:server
npm run example:http:client
npm run example:streaming:server
npm run example:streaming:client
npm run example:subscription:server
npm run example:subscription:client
# Node.js 22+, Tempo mainnet
npm run example:peer-cash:server
# Dashboard (with all endpoints)
npm run example:dashboard:serverテストウォレットへの資金投入
有料の例では、Tempoテストネット上で資金が入ったウォレットが必要です。Peer Cashの例は例外で、収益ルートがライブのみのためTempoメインネットを使用します。
cast rpc tempo_fundAddress 0xYourAddress --rpc-url https://rpc.moderato.tempo.xyzランタイム互換性
コアライブラリ(サーバー、クライアント、ストア、レート制限、金額、アクセスキー)は、Web Cryptoを介してランタイム間で移植可能です:
ランタイム | サポート |
Node.js 20+ | 完全 |
Cloudflare Workers | 完全 |
Vercel Edge | 完全 |
Deno | 完全 |
Bun | 完全 |
auth.tsミドルウェアモジュールはnode:cryptoを使用し、Node.jsが必要です。エッジデプロイメントでは、代わりにプラットフォームのネイティブルーターと認証プリミティブを使用します。
アーキテクチャ
src/
├── server.ts PaidMcpServer — payment gating, stats, shutdown, webhooks
├── client.ts PaidMcpClient — auto-payment, caps, key caching, sessions
├── types.ts Core interfaces (PricingModel, configs, stats, results)
├── index.ts Barrel exports (11 subpath entry points)
├── access-keys.ts Issue, redeem (atomic), validate, duration parsing
├── amounts.ts BigInt <-> USD string conversion (exact arithmetic)
├── auth.ts 5 Express middleware factories (timing-safe)
├── cli.ts Operator CLI (inspect, stats, tools, calls, keys)
├── constants.ts Tempo networks, token addresses, escrow contracts
├── dashboard.ts JSON API: /api/stats, /api/tools, /api/calls
├── discovery.ts OpenAPI 3.1 generation with x-payment-info
├── errors.ts 9 typed error classes with stable codes
├── logger.ts Logger interface + 4 implementations + redaction
├── metrics.ts Prometheus /metrics (hand-formatted, zero deps)
├── rate-limit.ts RateLimiter interface + 3 implementations
├── runtime.ts Cross-runtime: randomHex, writeLogLine, hmacSha256Hex
├── tracing.ts OTel span helpers (no-op when disabled)
├── webhooks.ts HMAC-signed event push with retry + dead-letter
└── stores/
├── types.ts MppMcpStore interface
├── index.ts Store namespace + re-exports
├── memory.ts In-memory (atomic via promise chains)
├── upstash.ts Upstash Redis (atomic via Lua CAS)
├── cloudflare-kv.ts Cloudflare KV (best-effort)
└── bridge.ts Legacy 3-method store adapterパッケージエクスポート
{
".": "Main barrel (everything)",
"./server": "PaidMcpServer",
"./client": "PaidMcpClient",
"./dashboard": "mountDashboard",
"./discovery": "mountDiscovery, buildOpenApi",
"./stores": "Store adapters",
"./rate-limit": "Rate limiter implementations",
"./auth": "Auth middleware factories",
"./metrics": "mountMetrics, formatMetrics",
"./tracing": "startSpan, withSpan, TRACE_ATTRS",
"./webhooks": "WebhookDispatcher, event types"
}設計原則
収益の正確性 — すべての金額計算は
bigint基本単位(小数6桁)を使用します。数百万回の操作後も浮動小数点のずれは発生しません。ゼロコストのオプトイン — トレーシング、ウェブフック、レート制限は、設定しない限りノーオペレーションです。トレースしないデプロイメントではスパンは割り当てられません。
すべてプラグ可能 — ストア、ロガー、レートリミッター、認証はインターフェースベースです。ゲートウェイコードに触れることなく実装を交換できます。
フェイルファスト — 設定エラーはリクエスト時ではなく構築時にスローされます。
エラーは値 — 安定したコードを持つ型付きエラークラス。プログラムによる処理には
instanceofまたはerr.codeを使用します。リングバッファコールログ — O(1)で事前割り当てされ、決して増大しません。高スループット下でもGCプレッシャーがありません。
グレースフルライフサイクル — シャットダウンゲートは新しい呼び出しを拒否し、ドレインは進行中の呼び出しを待機し、ウェブフックをフラッシュしてから切断します。
開発
# Install dependencies
npm install
# Build
npm run build
# Type check
npm run typecheck
# Run tests
npm run test
# Run tests in watch mode
npm run test:watch
# Type tests (tsd)
npm run test:types
# Benchmarks
npm run bench
# Generate docs
npm run docsテストスイート
27以上のテストファイルが以下をカバー:
アクセスキーの原子性(Nコールキーの並行リデーム)
アクセスキーフロー(発行 → リデーム → 消費 → 再支払い)
金額計算(BigInt変換、エッジケース)
認証ミドルウェア(全5ファクトリー)
コールログリングバッファ(ラップアラウンド、容量制限)
グレースフルシャットダウンとドレイン
ダッシュボードAPIレスポンス
ディスカバリ / OpenAPI生成
エラータクソノミー
無料ツール(支払い不要パス)
ロガー(構造化出力、リダクション、子ロガー)
Prometheusメトリクスフォーマット
マルチカレンシーディスカバリ
有料フロー(402 → クレデンシャル → レシート)
料金計算(段階的、呼び出しごと)
レート制限(トークンバケット、拒否、retry-after)
収益の正確性(多数の呼び出しにわたるBigInt累積)
ランタイムヘルパー(randomHex、hmacSha256Hex)
セッションライフサイクル(オープン → バウチャー → クローズ → 決済)
支出上限(1回あたり、合計、セッション預入)
OpenTelemetryトレーシング(スパン属性、エラー記録)
ウェブフック(配信、リトライ、HMAC署名、デッドレター)
型テスト(
tsd経由)スループットベンチマーク(
vitest bench経由)
グレースフルシャットダウン
close()をコンテナのシャットダウンシグナルに接続:
process.on('SIGTERM', async () => {
try {
await server.close({ timeoutMs: 25_000 })
process.exit(0)
} catch {
process.exit(1) // drain timed out
}
})構造化ロギング
ライブラリにはプラグ可能なLoggerインターフェースが同梱されています。デフォルト:秘密情報(秘密鍵、クレデンシャル、署名済みトランザクション)を自動的にリダクションしてstderrにJSONで出力します。
import { consoleLogger, silentLogger, withRedaction } from 'mpp-mcp-gateway'
// Custom logger
const server = createPaidMcpServer({
// ...
logger: withRedaction(consoleLogger({ level: 'debug', pretty: true })),
})
// Silence for tests
const server = createPaidMcpServer({
// ...
logger: silentLogger(),
})pino、winston、または任意のロギングライブラリに適合:
const adapter: Logger = {
debug: (m, c) => pino.debug(c, m),
info: (m, c) => pino.info(c, m),
warn: (m, c) => pino.warn(c, m),
error: (m, c) => pino.error(c, m),
child: (bindings) => /* wrap pino.child(bindings) */,
}ライセンス
MIT — Gaurav Pant
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Pay-per-use tool marketplace for AI agents. Search, price-check, and call APIs via MCP.
Remote MCP server for AI.TV creators — delegate account operations to your AI agent over MCP.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceA production-ready TypeScript MCP server providing basic tools (add, echo, timestamp), resources (server info, greetings, data access), and prompt templates (analyze, code-review, summarize). Serves as a foundation for building custom MCP servers with extensible architecture.452 npm-
- AlicenseNot gradedqualityDmaintenanceSimplifies creating MCP servers in TypeScript with an Express-like API and experimental decorators, enabling quick definition of tools, resources, and prompts.18 npm197MIT
- AlicenseNot gradedqualityDmaintenanceTurn your typed TypeScript functions into an MCP server — tool, resource, and prompt schemas inferred from your types and JSDoc. No schema library, no decorators, no boilerplate.7 npmMIT
- AlicenseNot gradedqualityCmaintenanceA TypeScript SDK for building MCP servers and clients, providing standardized context provision for LLMs through tools, resources, and prompts.87,228,630 npmMIT