Skip to main content

mcp-core

Release License: MIT Python

Auth, billing, and logging infrastructure for MCP-first servers. Sits between your product code and fastapi-mcp, with provider-aware auth for Logto and Supabase.

Your MCP Server  (product-specific tool handlers)
     mcp-core    (auth, billing, logging, health)
    fastapi-mcp  (MCP protocol: JSON-RPC, SSE, tool discovery)
      FastAPI

Install

pip install mcp-core-auth

The package is published as mcp-core-auth on PyPI (the bare mcp-core name is held by an unrelated project), but the import path is unchanged:

from mcp_core import MCPCore

Quick Start

from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from mcp_core import MCPCore

core = MCPCore(
    product_name="my-product",
    auth_provider="logto",
    logto_endpoint="https://your-tenant.logto.app",
    logto_api_resource="https://api.my-product.app",
    mongodb_uri="mongodb+srv://...",
    stripe_secret_key="sk_test_...",
    stripe_price_id="price_...",
    free_credits=30,
    tool_costs={"browse": 0, "generate": 5},
    read_only_tools={"browse"},
)

@asynccontextmanager
async def lifespan(app: FastAPI):
    await core.connect_db()
    yield

app = FastAPI(lifespan=lifespan)
core.install_routes(app)  # /health, /api/billing/credits, webhook, OAuth metadata

@app.post("/api/mcp/generate")
async def generate(request: Request):
    user = await core.auth_and_bill(request, "generate")
    result = do_generation()
    await core.log_tool_call(request, "generate", user=user, duration_ms=1200)
    return result

All config can also come from MCP_CORE_* environment variables.

To use Supabase Auth instead, switch the provider and pass your Supabase URL and anon key:

core = MCPCore(
    product_name="my-product",
    auth_provider="supabase",
    supabase_url="https://your-project.supabase.co",
    supabase_anon_key="sb_publishable_...",
    supabase_api_resource="https://api.my-product.app",
    mongodb_uri="mongodb+srv://...",
    free_credits=30,
    tool_costs={"browse": 0, "generate": 5},
    read_only_tools={"browse"},
)

If auth_provider is omitted, mcp-core infers Supabase when both MCP_CORE_SUPABASE_URL and MCP_CORE_SUPABASE_ANON_KEY are present; otherwise it preserves the existing Logto default.

Modules

Auth (mcp_core.auth)

Provider-aware bearer-token auth. Creates MongoDB user records on first auth using a neutral auth_user_id while preserving legacy logto_user_id fields for existing Logto apps.

  • Logto JWT validation via JWKS
  • Supabase access-token validation through Supabase Auth
  • Cloud or self-hosted provider URLs
  • 30s clock skew tolerance
  • Race-condition-safe user upsert
  • Dev bypass (Bearer dev-bypass) for local development
  • M2M token rejection for paid tools

Billing (mcp_core.billing.StripeBilling)

Stripe billing for credit-based products and all-access subscription products.

  • Credit mode deducts free credits first, then falls back to Stripe metered billing.
  • Subscription mode (BILLING_MODE=subscription) requires an active subscription for paid tools and never consumes credits.
  • Standard billing routes include /api/billing/credits, /api/billing/checkout-subscription, /api/billing/sync, /api/billing/portal, and /api/stripe/webhook.
  • Subscription webhooks track checkout.session.completed, customer.subscription.created, customer.subscription.updated, customer.subscription.paused, customer.subscription.resumed, customer.subscription.deleted, invoice.payment_failed, invoice.payment_action_required, and invoice.paid.
  • Access defaults to active, trialing, and past_due; unpaid, paused, incomplete, incomplete_expired, and canceled do not grant subscription access.
  • Stripe Customer Portal should handle payment methods, invoices, receipts, and cancellation self-service. Stripe Billing customer-email settings should handle invoice, receipt, failed-payment, and renewal emails; auth providers such as Supabase should remain responsible for auth and security emails.

Useful subscription env vars:

BILLING_MODE=subscription
STRIPE_SECRET_KEY=sk_live_or_test_...
STRIPE_PRICE_ID=price_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PORTAL_CONFIGURATION_ID=bpc_...
SUBSCRIPTION_PLAN_NAME="Pro"
SUBSCRIPTION_PRICE_LABEL="$20/month"

Store billing and plans (mcp_core.store)

App Store subscriptions through RevenueCat, next to Stripe:

  • PlanCatalog / Plan: map Stripe prices and store entitlements to plans. require_plan(core, user, "pro") reads both, and the highest plan wins.
  • RevenueCatBilling: webhook (constant-time Authorization check, idempotent event log), reconcile(user) through the v1 REST API behind RevenueCatClient, a sandbox allowlist, and an on_change hook for product-owned allowances.
  • core.install_store_routes(app) and core.install_account_routes(app, before_delete=...) (POST /api/account/delete).

See integration guide section 10.

Tool Logging (mcp_core.tool_logging.ToolLogger)

Audit trail for every MCP tool call. Writes to MongoDB tool_logs collection.

Health (mcp_core.health.HealthCheck)

Composable health check builder. Supports sync and async checks with timeouts.

Readiness (mcp_core.readiness)

Provider-aware MCP OAuth onboarding diagnostics. The bundled CLI follows the same discovery path as RFC 9728 clients:

mcp-core-check-readiness https://your-app.example.com/mcp/v2/

It checks protected-resource metadata, authorization-server discovery, Dynamic Client Registration, unauthenticated MCP bearer challenges, and provider-specific behavior for Logto and Supabase. For Supabase, it also verifies that the authorize endpoint redirects back to your app's consent UI with an authorization_id.

Client auth matrix (operators / products)

Server readiness is not enough for release confidence. Use the client auth matrix to verify real MCP clients (Claude Code, OpenCode, Grok, Cursor, …):

Product-specific eval harnesses (isolated CLI profiles, Windows runners, etc.) belong in the product repo, not in mcp-core.

Testing

# Mock tests (no external services)
pip install -e ".[dev]"
pytest tests/ -v

# Live tests (requires .env.live with real credentials)
RUN_LIVE_TESTS=1 pytest tests/live/ -v

Contributing

Bug reports and PRs welcome. See CONTRIBUTING.md for the workflow and SECURITY.md for vulnerability reporting.

The multi-provider auth design reference lives in docs/multi-provider-auth-plan.md.

License

MIT

Metadata

Release files for mcp-core-auth 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-core-auth 0.6.0
File Size Uploaded Provenance
mcp_core_auth-0.6.0.tar.gz 641.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-core-auth 0.6.0
File Interpreter ABI Platform
mcp_core_auth-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 707.6 kB

Release files / mcp_core_auth-0.6.0.tar.gz

Download URL mcp_core_auth-0.6.0.tar.gz
Size 641.0 kB
Tags Source
SHA-256 checksum
How to use checksums
55288ac954afe5c97810d2864c79a9e9dd21d1c7dca91e5fe2f4745890fe624d
BLAKE2b-256 checksum
How to use checksums
58434cbac7d90e5a0f05d635b62a41c4e5bedfdff4dd64b75c570103724d73ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / mcp_core_auth-0.6.0-py3-none-any.whl

Download URL mcp_core_auth-0.6.0-py3-none-any.whl
Size 66.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6a8a4ac08ca1e715b1dc7f581ecd3993cc3ab7ff1822865120a5d3e44ee319ba
BLAKE2b-256 checksum
How to use checksums
0d60547fe919b0e7150cf46066a4200b48c86518ded4d8fb999c6ee2dc3df579
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Security for mcp-core-auth 0.6.0

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page