Skip to main content

Billing SDK for MCP servers

Project description

metrify

Billing SDK for MCP servers. Add pay-per-call monetization to any MCP tool in under 5 minutes — no payment infrastructure required.


Quickstart

1. Register as a provider

Sign up at the Metrify dashboard and get your pk_live_... provider key.

2. Install the SDK

pip install metrify

3. Configure your provider key

export METRIFY_PROVIDER_KEY="pk_live_your_key_here"

Or pass it directly in code (see step 4).

4. Decorate your tools and register them

from metrify import Metrify

m = Metrify()  # reads METRIFY_PROVIDER_KEY from env

@m.tool(price=0.01, unit="per_call")
async def summarize(consumer_api_key: str, text: str) -> str:
    """Summarize a block of text."""
    # Balance is pre-checked before this runs; charge happens only on success
    return f"Summary of: {text[:50]}..."

# On startup, push all decorated tools to the Metrify dashboard:
await m.register_tools()

register_tools() is idempotent — run it every time your server starts. Tools with no docstring get description=None; pass description= explicitly to override:

@m.tool(price=0.05, unit="per_call", description="OCR a PDF page")
async def ocr_page(consumer_api_key: str, page_url: str) -> str:
    ...

5. Deploy

Your tool now charges consumers on every call. The consumer_api_key is extracted automatically by the decorator — consumers pass it as the first argument or as a keyword argument.


Full example with FastMCP

from metrify import Metrify
from mcp.server.fastmcp import FastMCP

m = Metrify(provider_key="pk_live_your_key_here")
server = FastMCP("my-mcp-server")

@server.tool()
@m.tool(price=0.05, unit="per_call")
async def analyze_document(consumer_api_key: str, content: str) -> str:
    """Analyze a document and return insights."""
    # billing.charge() runs before this line
    analysis = await run_analysis(content)
    return analysis

@server.tool()
@m.tool(price=0.001, unit="per_token")
async def generate_text(consumer_api_key: str, prompt: str) -> str:
    """Generate text from a prompt."""
    result = await llm.complete(prompt)
    return result

Billing flow

The decorator runs a two-phase billing flow on every call:

  1. Pre-check — verify the consumer has enough balance (no charge yet).
  2. Execute — run your tool function.
  3. Charge — deduct only if the function completed without error.

If the function raises any exception the consumer is never charged.

Exception reference

Exception Raised by Behavior
InsufficientBalanceError Pre-check Propagated — consumer has no funds
UpstreamError Your tool Caught — returns message to consumer, no charge
ProviderSuspendedError Pre-check / charge Propagated — your account is suspended
ConsumerSuspendedError Pre-check / charge Propagated — consumer account is suspended
ProviderNotFoundError Pre-check / charge Propagated — your provider key is invalid
GatewayError Pre-check / charge Propagated — network error or backend 5xx
Any other Exception Your tool Caught — returns "Tool error: ...", no charge

Signalling upstream failures with UpstreamError

Use UpstreamError when an external API your tool depends on fails. The decorator catches it, skips billing, and returns your message to the consumer:

from metrify import Metrify, UpstreamError

m = Metrify()

@m.tool(price=0.05, unit="per_call")
async def summarize(consumer_api_key: str, text: str) -> str:
    try:
        result = await anthropic_client.messages.create(...)
    except anthropic.APIError as e:
        raise UpstreamError(f"Anthropic API error: {e.message}")
    return result.content[0].text

The consumer receives "Anthropic API error: ..." and is not charged.

from metrify.exceptions import InsufficientBalanceError, GatewayError

# In your MCP server error handler:
try:
    result = await my_tool(consumer_api_key=ck, query=q)
except InsufficientBalanceError:
    return "Insufficient balance. Please top up at the Metrify dashboard."
except GatewayError:
    return "Billing service temporarily unavailable. Please retry."

Environment variables

Variable Default Description
METRIFY_PROVIDER_KEY Your provider key (pk_live_...)
METRIFY_GATEWAY_URL https://airy-wholeness-production-fcc4.up.railway.app Override backend URL
METRIFY_MCP_URL Public URL of your MCP server (e.g. https://myserver.railway.app/mcp)

Supported billing units (V1)

All units charge a flat price per call. The unit field is displayed in your dashboard for reporting purposes.

Unit Use case
per_call Fixed price per tool invocation
per_token LLM completions (flat in V1)
per_minute Audio/video processing
per_image Image generation or analysis
per_page Document processing

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

metrify_sdk-0.2.2.tar.gz (13.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

metrify_sdk-0.2.2-py3-none-any.whl (7.7 kB view details)

Uploaded Python 3

File details

Details for the file metrify_sdk-0.2.2.tar.gz.

File metadata

  • Download URL: metrify_sdk-0.2.2.tar.gz
  • Upload date:
  • Size: 13.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.4

File hashes

Hashes for metrify_sdk-0.2.2.tar.gz
Algorithm Hash digest
SHA256 dc799eb60e7e6ddbc10ceb07b936aec0b376ebd9392fc80720acb16e8fb89f2f
MD5 9535c68e1113160fd9f2188c4c322eae
BLAKE2b-256 fdf27be7a61cb5b7ce14cf3544fadbda42bf78ff0fd263966b70e5464a32707c

See more details on using hashes here.

File details

Details for the file metrify_sdk-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: metrify_sdk-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 7.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.4

File hashes

Hashes for metrify_sdk-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 cc86cfe7a09b9b78cafbc8fed1ed564b7970326ea15abdded3a051b69f08f4e2
MD5 250cc9cb39cc50391027a86fb9c680a4
BLAKE2b-256 16046227636f6fd931d09dd7d09e427f552e53244b95cca27641e40d1039b29e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page