mpp-mcp-gateway
mpp-mcp-gateway
Монетизируйте любой MCP-сервер с помощью микроплатежей в стейблкоинах через протокол Machine Payments Protocol (MPP) в блокчейне Tempo.
Создавайте MCP-серверы инструментов, которые взимают с AI-агентов плату за вызов, за сессию или через ключи доступа — с расчётом в pathUSD и других TIP-20 стейблкоинах. Создавайте клиенты AI-агентов, которые автоматически платят за эти инструменты с настраиваемыми лимитами расходов.
Table of Contents
Related MCP server: easy-mcp
Обзор
mpp-mcp-gateway — это библиотека TypeScript, которая добавляет шлюз микроплатежей в стейблкоинах к MCP-серверам (Model Context Protocol). Когда AI-агент вызывает платный инструмент, сервер отвечает ошибкой 402 Payment Required. Клиент агента подписывает платёжную транзакцию в блокчейне Tempo, повторяет вызов с учётными данными, а сервер проверяет расчёт перед запуском обработчика и возвращает результат с чеком.
Ключевые возможности:
Четыре модели ценообразования — за вызов, многоуровневая, сессионная (платёжные каналы) и по ключам доступа (подписки)
Поддержка нескольких валют — приём нескольких TIP-20 стейблкоинов для каждого инструмента
Точный учёт выручки — арифметика BigInt предотвращает дрейф чисел с плавающей запятой при миллионах платежей меньше цента
Подключаемое хранилище — in-memory, Upstash Redis (атомарный CAS), Cloudflare KV или своё собственное
Ограничение частоты запросов — token bucket (в памяти или на базе Redis) с переопределениями для отдельных инструментов
Промежуточное ПО аутентификации — bearer-токен, API-ключ, HTTP Basic, подписанные URL, CORS — всё с защитой от timing-атак
Метрики Prometheus — эндпоинт
/metrics, без зависимостейТрассировка OpenTelemetry — опциональное дерево спанов для каждого платного вызова, нулевая стоимость при отключении
Вебхуки — отправка событий с подписью HMAC, повторами, экспоненциальной задержкой и dead-letter хуками
Обнаружение сервисов — OpenAPI 3.1 с расширениями
x-payment-info(сканируется 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
Сервер отвечает кодом ошибки MCP
-32042, содержащим MPP-челленджКлиент соблюдает лимиты расходов, подписывает платёж и повторяет запрос с учётными данными
Сервер проверяет расчёт в блокчейне через
mppxВыполняется обработчик, результат возвращается с платёжным чеком (хэш транзакции, метка времени)
Установка
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()Модели ценообразования
За вызов
Фиксированная цена за вызов. Одна транзакция в блокчейне за вызов.
pricing: { type: 'per-call', amount: '0.001' }Многоуровневая
Цена уменьшается (или увеличивается) в зависимости от накопленного количества вызовов.
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Ключ доступа (подписки)
Агент платит один раз заранее и получает непрозрачный токен. Последующие вызовы предъявляют токен — дальнейших платежей не требуется, пока ключ не истечёт или не будет исчерпан. Лучше всего подходит для UX «купить дневной пропуск» или «купить N вызовов».
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 (legacy) | Старые MCP-клиенты |
|
In-Memory | Тестирование, в рамках одного процесса |
|
Адаптеры хранилища
Шлюз использует подключаемый интерфейс MppMcpStore для сохранения записей ключей доступа и состояния сессионных каналов.
import { Store } from 'mpp-mcp-gateway/stores'Адаптер | Атомарность | Вариант использования |
| Атомарная (цепочка промисов) | Тесты, локальная разработка, один инстанс |
| Атомарная (Lua CAS) | Продакшен, несколько инстансов |
| Best-effort | Ключи доступа на периферии (не для сессий) |
| Best-effort | Обратная совместимость с хранилищами 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,
})Собственное хранилище
Реализуйте интерфейс из четырёх методов:
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 должен гарантировать атомарное чтение-изменение-запись. Колбэк transform может вызываться несколько раз при конкуренции (CAS-подобные бэкенды).
Ограничение частоты запросов
Ограничение частоты запросов срабатывает до логики платежей и обработчиков — отклонённые вызовы никогда не выдают 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 },
})Промежуточное ПО аутентификации
Пять фабрик промежуточного ПО 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}— суммарная выручка в микро-USDmppmcp_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 buildОтдавайте dashboard/dist/ как статические файлы из вашего Express-приложения.
Обнаружение сервисов
Создавайте и отдавайте документ OpenAPI 3.1 с расширениями x-payment-info в соответствии с черновиком IETF по обнаружению сервисов MPP. Публичные реестры, такие как 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Вебхуки
Отправляйте события на URL с подписями HMAC-SHA-256. Доставка выполняется по принципу fire-and-forget (неблокирующая), с повторами и экспоненциальной задержкой.
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)
Поле | Тип | По умолчанию | Описание |
|
| обязательно | Имя клиента |
|
| обязательно | Версия клиента |
|
| обязательно | Приватный ключ кошелька агента |
|
|
| Максимальный расход за один вызов (USD) |
|
|
| Максимальный суммарный расход (USD) |
|
|
| Максимальный депозит канала (USD) |
|
|
| Сеть Tempo |
|
| console+redaction | Структурированный логгер |
|
|
| Проверять транзакцию расчёта сессии в блокчейне |
Примеры
Пример | Ценообразование | Транспорт | Что демонстрирует |
| за вызов | InMemory | Полный цикл 402 в одном процессе |
| за вызов | stdio | Агент запускает сервер как подпроцесс |
| за вызов | Streamable HTTP | Сетевой сервер на Express |
| за вызов | SSE (устаревший) | Обратно совместимый SSE-транспорт |
| за вызов + ключ доступа | Streamable HTTP | Комбинированный MCP + дашборд + discovery |
| сессия | 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, поскольку маршрут дохода доступен только в live-режиме.
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. Edge-развёртывания вместо этого используют нативный роутер и примитивы аутентификации своей платформы.
Архитектура
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 десятичных знаков). Никакого дрейфа чисел с плавающей точкой после миллионов операций.Подключение без затрат — трассировка, вебхуки и ограничение скорости являются no-op, если не настроены. Развёртывания без трассировки не выделяют спаны.
Всё подключаемо — хранилища, логгеры, ограничители скорости и аутентификация основаны на интерфейсах. Меняйте реализации, не трогая код шлюза.
Быстрый отказ — ошибки конфигурации выбрасываются в момент создания, а не в момент запроса.
Ошибки — это значения — типизированные классы ошибок со стабильными кодами. Используйте
instanceofилиerr.codeдля программной обработки.Кольцевой буфер журнала вызовов — O(1) с предварительным выделением памяти, никогда не растёт. Нет нагрузки на GC при высокой пропускной способности.
Плавный жизненный цикл — шлюз завершения отклоняет новые вызовы, drain ожидает выполняющиеся, сброс вебхуков, затем отключение.
Разработка
# 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 фабрик)
Кольцевой буфер журнала вызовов (переполнение, ограничения ёмкости)
Плавное завершение и drain
Ответы API дашборда
Генерация Discovery / OpenAPI
Таксономия ошибок
Бесплатные инструменты (путь без оплаты)
Логгер (структурированный вывод, редактирование, дочерние логгеры)
Форматирование метрик Prometheus
Мультивалютный discovery
Платный поток (402 → учётные данные → квитанция)
Расчёт цен (тарифы, за вызов)
Ограничение скорости (token bucket, отказ, retry-after)
Точность расчётов (накопление BigInt при множестве вызовов)
Хелперы среды выполнения (randomHex, hmacSha256Hex)
Жизненный цикл сессии (открытие → ваучер → закрытие → расчёт)
Лимиты расходов (за вызов, суммарный, депозит сессии)
Трассировка OpenTelemetry (атрибуты спанов, запись ошибок)
Вебхуки (доставка, повтор, подпись HMAC, dead-letter)
Тесты типов (через
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. По умолчанию: JSON в stderr с автоматическим редактированием секретов (приватные ключи, учётные данные, подписанные транзакции).
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.430 npm-
- AlicenseNot gradedqualityDmaintenanceSimplifies creating MCP servers in TypeScript with an Express-like API and experimental decorators, enabling quick definition of tools, resources, and prompts.5 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.42,741,935 npmMIT