Skip to main content
Glama
aspiring-100x

mpp-mcp-gateway

mpp-mcp-gateway

Tempo 블록체인의 MPP(Machine Payments Protocol)를 통해 모든 MCP 서버를 스테이블코인 마이크로페이먼트로 수익화하세요.

AI 에이전트에게 호출별, 세션별, 또는 액세스 키 방식으로 요금을 부과하는 MCP 도구 서버를 구축하세요 — pathUSD 및 기타 TIP-20 스테이블코인으로 결제됩니다. 구성 가능한 지출 한도로 해당 도구 비용을 자동으로 지불하는 AI 에이전트 클라이언트도 구축하세요.

License: MIT

목차

Related MCP server: MCP Server TypeScript

개요

mpp-mcp-gateway는 MCP(Model Context Protocol) 서버에 스테이블코인 마이크로페이먼트 게이팅을 추가하는 TypeScript 라이브러리입니다. AI 에이전트가 유료 도구를 호출하면 서버는 402 Payment Required 챌린지를 발행합니다. 에이전트의 클라이언트는 Tempo 블록체인에서 결제 트랜잭션에 서명하고, 자격 증명을 사용해 호출을 재시도하며, 서버는 핸들러를 실행하고 영수증과 함께 결과를 반환하기 전에 결제 완료를 검증합니다.

주요 기능:

  • 네 가지 가격 모델 — 호출별, 단계별, 세션(결제 채널), 액세스 키(구독)

  • 다중 통화 지원 — 도구별로 여러 TIP-20 스테이블코인 허용

  • 정확한 수익 추적 — BigInt 연산으로 수백만 건의 1센트 미만 결제에서 부동소수점 오차 방지

  • 플러그형 스토리지 — 인메모리, Upstash Redis(원자적 CAS), Cloudflare KV, 또는 자체 구현

  • 속도 제한 — 토큰 버킷(인메모리 또는 Redis 기반) 및 도구별 재정의

  • 인증 미들웨어 — Bearer 토큰, 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    │
└─────────────┘                                └──────────────────┘
  1. 에이전트가 MCP를 통해 유료 도구를 호출

  2. 서버가 MPP 챌린지를 포함한 MCP 오류 코드 -32042로 응답

  3. 클라이언트가 지출 한도를 적용하고 결제에 서명한 뒤 자격 증명으로 재시도

  4. 서버가 mppx를 통해 온체인 결제 완료를 검증

  5. 핸들러가 실행되고 결제 영수증(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()

가격 모델

호출별 과금

호출당 고정 가격입니다. 호출마다 온체인 트랜잭션이 한 번 발생합니다.

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

액세스 키(구독)

에이전트가 선불로 한 번 결제하고 불투명 토큰을 받습니다. 이후 호출은 토큰을 제시합니다 — 키가 만료되거나 소진될 때까지 추가 결제가 없습니다. '하루 이용권 구매' 또는 '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 도구, 하위 프로세스 생성

examples/paid-weather-mcp/

Streamable HTTP

네트워크 서버(최신)

examples/paid-weather-http/

SSE (legacy)

구형 MCP 클라이언트

examples/paid-weather-sse/

In-Memory

테스트, 동일 프로세스

examples/in-memory-demo/

스토어 어댑터

게이트웨이는 액세스 키 레코드와 세션 채널 상태를 저장하기 위해 플러그형 MppMcpStore 인터페이스를 사용합니다.

import { Store } from 'mpp-mcp-gateway/stores'

어댑터

원자성

사용 사례

Store.memory()

원자적(promise 체인)

테스트, 로컬 개발, 단일 인스턴스

Store.upstash(redis)

원자적(Lua CAS)

프로덕션, 다중 인스턴스

Store.cloudflareKv(ns)

최선 노력(best-effort)

엣지 액세스 키(세션 제외)

Store.bridge(legacy)

최선 노력(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 },
})

인증 미들웨어

대시보드, 메트릭, 디스커버리 엔드포인트를 보호하기 위한 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' })

제공하는 엔드포인트:

엔드포인트

응답

GET /api/stats

{ stats: GatewayStats } — 호출, 수익, 세션, 키, 가동 시간

GET /api/tools

{ tools: [{ name, description, price }] }

GET /api/calls?limit=N

{ calls: CallLogEntry[] } — 최신순

GET /api/keys

{ keys: AccessKeyListEntry[] } — 활성 액세스 키

DELETE /api/keys/:token

{ revoked: boolean } — 키 폐기(변경 작업, 미들웨어로 보호)

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} — 유료, 무료, 세션, access_key, 전체

  • mppmcp_revenue_micro_usd_total{tool} — 마이크로 USD 단위 누적 수익

  • mppmcp_in_flight_calls — 활성 핸들러 게이지

  • mppmcp_access_keys_issued_total / expired_total

  • mppmcp_sessions_opened_total / closed_total

  • mppmcp_rate_limited_total — 속도 제한기에 의해 거부된 호출

  • mppmcp_rejected_shutting_down_total — 종료 중 거부된 호출

  • mppmcp_uptime_seconds

  • mppmcp_shutting_down

React 대시보드

사전 빌드된 React + Vite 대시보드가 dashboard/에 있습니다. JSON API를 2초마다 폴링하여 다음을 표시합니다:

  • 수익 카운터 및 수익 기준 정렬 도구 테이블

  • 결제 모드별 색상으로 구분된 실시간 호출 로그

  • 액세스 키 및 세션 통계

cd dashboard
npm install
npm run build

Express 앱에서 dashboard/dist/를 정적 파일로 제공하세요.

서비스 디스커버리

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에 이벤트를 푸시합니다. 전송은 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)

필드

타입

기본값

설명

name

string

필수

클라이언트에 광고되는 서버 이름

version

string

필수

서버 버전

recipient

0x${string}

필수

결제를 수신하는 지갑 주소

secretKey

string

필수

결제 챌린지 바인딩용 HMAC 키

tools

PaidToolDefinition[]

필수

핸들러가 포함된 도구 정의

currency

0x${string}

pathUSD

TIP-20 스테이블코인 컨트랙트 주소

network

'mainnet' | 'testnet'

'testnet'

Tempo 네트워크

feePayerKey

0x${string}

서버가 부담하는 가스(수수료 납부자 개인 키)

sessionAccountKey

0x${string}

세션 정산에 필요한 운영자 키

escrowContract

0x${string}

네트워크별 기본값

세션 에스크로 컨트랙트

accessKeyStore

MppMcpStore

in-memory

액세스 키 영속화

sessionStore

MppMcpStore

in-memory

세션 채널 영속화

accessKeyBinding

'none' | 'wallet'

'none'

키를 결제 지갑에 바인딩

callLogSize

number

1000

링 버퍼 용량(0 = 비활성화)

logger

Logger

console+redaction

구조화된 로거

drainTimeoutMs

number

30000

그레이스풀 셧다운 타임아웃

onShutdown

() => void

드레인이 시작될 때 실행되는 훅

rateLimit

object

도구당 60회/분

속도 제한 구성

tracer

Tracer

OpenTelemetry 트레이서(옵트인)

webhooks

WebhookConfig

이벤트 푸시 구성

클라이언트 (PaidMcpClientConfig)

Field

Type

Default

Description

name

string

required

클라이언트 이름

version

string

required

클라이언트 버전

privateKey

0x${string}

required

에이전트 지갑 개인 키

maxPerCall

string

'1.00'

단일 호출당 최대 지출(USD)

maxTotal

string

'100.00'

누적 최대 지출(USD)

maxSessionDeposit

string

'1.00'

최대 채널 예치금(USD)

network

'mainnet' | 'testnet'

'testnet'

Tempo 네트워크

logger

Logger

console+redaction

구조화된 로거

verifySettlement

boolean

false

세션 정산 트랜잭션을 온체인에서 검증

예제

Example

Pricing

Transport

What it demonstrates

in-memory-demo

per-call

InMemory

단일 프로세스에서의 전체 402 라운드트립

paid-weather-mcp

per-call

stdio

에이전트가 서버를 하위 프로세스로 실행

paid-weather-http

per-call

Streamable HTTP

Express 기반 네트워크 서버

paid-weather-sse

per-call

SSE (legacy)

하위 호환 SSE 전송

paid-weather-dashboard

per-call + access-key

Streamable HTTP

MCP + 대시보드 + 디스커버리 결합

paid-streaming-mcp

session

stdio

결제 채널, 바우처, 종료

paid-subscription-mcp

access-key

stdio

데이 패스, 시간제, 콜 팩

paid-peer-cash-mcp

per-call

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를 통해 런타임 간 이식이 가능합니다:

Runtime

Support

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자리)를 사용합니다. 수백만 번의 연산 후에도 부동소수점 오차가 없습니다.

  • 무비용 옵트인 — 추적, 웹훅, 속도 제한은 구성하지 않으면 no-op입니다. 추적하지 않는 배포는 스팬을 할당하지 않습니다.

  • 모든 것이 플러그 가능 — 스토어, 로거, 속도 제한기, 인증은 인터페이스 기반입니다. 게이트웨이 코드를 건드리지 않고 구현체를 교체할 수 있습니다.

  • 빠른 실패 — 구성 오류는 요청 시점이 아니라 생성 시점에 발생합니다.

  • 오류는 값 — 안정적인 코드를 가진 타입화된 오류 클래스입니다. 프로그래밍 방식 처리를 위해 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)

  • 세션 수명 주기(열기 → 바우처 → 닫기 → 정산)

  • 지출 상한(호출당, 총액, 세션 예치금)

  • 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

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    A 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.
    225
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for AgentPay — the payment gateway for autonomous AI agents. Fund a wallet once, give your agent the key, and it discovers, provisions, and pays for tool APIs on its own. One key, every tool.
    112
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Simplifies creating MCP servers in TypeScript with an Express-like API and experimental decorators, enabling quick definition of tools, resources, and prompts.
    26
    196
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aspiring-100x/mpp-mcp-gateway'

If you have feedback or need assistance with the MCP directory API, please join our Discord server