metrify-sdk
Billing infrastructure for MCP servers. Add one decorator. Start charging. Get paid in USDT.
Installation
pip install metrify-sdk
Requires Python 3.8+
Quickstart (Provider)
Step 1 — Register at metrify.dev and get your pk_live_... provider key.
Step 2 — Install the SDK:
pip install metrify-sdk
Step 3 — Write two functions: an inner one that does the billed work, and an outer one that the MCP framework actually exposes:
from metrify import Metrify
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-mcp-server")
m = Metrify(provider_key="your_provider_key")
# Inner — billing-wrapped. Metrify needs to know WHICH consumer to check the
# balance of and charge, so consumer_api_key must be the first parameter.
@m.tool(price=0.01, description="Search the web for a query")
def search(consumer_api_key: str, query: str) -> str:
# Your logic here
return f"Results for: {query}"
# Outer — the tool an agent actually calls over MCP. Its job is to figure
# out WHICH consumer is calling (from the incoming request's Bearer token)
# and pass that into the inner, billed function above.
@mcp.tool()
def search_mcp(query: str) -> str:
consumer_api_key = resolve_consumer_api_key() # see below
return search(consumer_api_key=consumer_api_key, query=query)
if __name__ == "__main__":
mcp.run(transport="streamable-http")
This two-layer split is required, not optional. @m.tool() bills a
specific consumer, so it needs their api_key — but it doesn't see the raw
HTTP request, so it can't extract that itself. Today, resolving
consumer_api_key from the incoming Authorization: Bearer <JWT> header
is on you, the provider — the SDK doesn't do it for you yet. In
practice that means validating the JWT (RS256, verified against Metrify's
published JWKS) and reading its sub claim.
You don't have to build that from scratch: examples/auth_middleware_example.py
is a complete, copyable JWT-validation middleware — adapted from the exact
code metrify-demo runs in production — that does this for you and exposes
the resolved key via a ContextVar your outer tool function can read. It's
a standalone example file (not an importable part of this package yet), so
copy it into your project and wire it into your ASGI app as shown at the
bottom of that file.
How billing works
When a consumer calls your tool, Metrify verifies their balance before execution. If sufficient, the tool runs. On success, the consumer wallet is debited atomically: 95% goes to you, 5% to Metrify. If your tool raises an exception, the consumer is not charged.
Consumer wallet → [Metrify] → Provider wallet
$0.01000 ↓ $0.00950
fee: $0.00050
@m.tool() parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
price |
float | ✓ | Cost per call in USDT |
description |
str | ✓ | Tool description shown to agents |
Policy: no charge on upstream error
If your tool raises any exception, the consumer is not charged.
Raise UpstreamError explicitly when an external API you depend on fails:
from metrify import Metrify, UpstreamError
m = Metrify(provider_key="your_provider_key")
@m.tool(price=0.05, description="Summarize text using an LLM")
async def summarize(consumer_api_key: str, text: str) -> str:
try:
result = await llm_client.complete(text)
except Exception as e:
raise UpstreamError(f"LLM unavailable: {e}")
return result
The consumer receives your error message and is not charged. Idempotency keys are implemented from day one — duplicate charges are impossible.
Provider registration
metrify.dev — currently invite-only waitlist.
Links
- metrify.dev
- metrify-mcp — consumer wallet management MCP server
- Changelog
License
MIT
Metadata
Release files for metrify-sdk 0.2.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| metrify_sdk-0.2.4.tar.gz | 16.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| metrify_sdk-0.2.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.7 kB
Release files / metrify_sdk-0.2.4.tar.gz
| Download URL | metrify_sdk-0.2.4.tar.gz |
|---|---|
| Size | 16.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d40e3ebf367cfc2f1de765fc150e23f6c6400fc14c9bf931fd3d1fd7714ffe7b
|
|
BLAKE2b-256 checksum How to use checksums |
e29abe8875f6ec81763655d12c815c9e3f8b601988838e4956190fa0ae1adbff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.13
|
Release files / metrify_sdk-0.2.4-py3-none-any.whl
| Download URL | metrify_sdk-0.2.4-py3-none-any.whl |
|---|---|
| Size | 7.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
72dd5b3e12ac4de79c561523a174276a171c6c63e3eaa7ef4c40a5293753da9e
|
|
BLAKE2b-256 checksum How to use checksums |
6674c3a0c3c7854994cfabb1841412e9e9168f95dc4e6e1cbe5385b866895926
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.13
|
Security for metrify-sdk 0.2.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.