Skip to main content

lane-mcp-auth

Lane sign-in for an MCP server, in Python. The TypeScript distribution is @getonlane/mcp-auth.

What it does for your MCP server

  • Lane sign-in for agents. Lane is your OAuth authorization server. The library verifies each bearer, serves the protected-resource document, and refuses every tool until the agent registers a session with your server.
  • Scopes, guest tools and step-up. A tool names the scopes it needs. A guest calls your public read tools with no Lane account. A missing scope starts a new Lane sign-in.
  • Purchases that a human approves. A priced tool answers with a proposal. The user approves the plan in their Lane wallet. Lane then calls the tool with an execution grant, and the library consumes each grant once.
  • Plan step events. Lane tells your server what happened to each step it sold, so your server fulfils, frees stock or cancels.
  • Telemetry. Lane records sign-ins and tool calls for your server, and on_gate_event gives you each gate decision in your own process.

Install

pip install "lane-mcp-auth[fastmcp]"
python -m lane_mcp_auth setup https://acme.com/mcp --name="Acme shop"

setup pairs your terminal with the Lane console and writes LANE_CLIENT_ID, LANE_CLIENT_SECRET, LANE_VERIFICATION, LANE_RESOURCE and LANE_ISSUER to .env. When Lane mints a sandbox org key for the pairing, it also writes LANE_ORG_KEY. The library requires an org key, and its prefix sets the environment: lane_org_sk_test_ is sandbox. With an org key, setup registers the server with no browser. It takes the key from --org-key, then from LANE_ORG_KEY in .env, then from the process environment. It writes the key it used to .env as LANE_ORG_KEY. The [fastmcp] extra adds only the FastMCP adapter.

Example

One gated tool on FastMCP 4, served over HTTP. The store keeps connections in memory, so it is correct for one process only.

import os

from fastmcp import Context, FastMCP
from fastmcp.server.dependencies import get_http_request
from fastmcp.server.middleware import Middleware
from lane_mcp_auth import ConnectionKey, ConnectionRecord, HttpTokenExchanger, LaneMcpAuth
from lane_mcp_auth.fastmcp import CLAIMS_ATTR, enable_lane_auth, requires
from starlette.middleware import Middleware as AsgiMiddleware
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import Response


class MemoryConnections:
    def __init__(self) -> None:
        self.rows: dict[tuple[str, str], ConnectionRecord] = {}

    async def get(self, key: ConnectionKey) -> ConnectionRecord | None:
        return self.rows.get((key.sub, key.client_id))

    async def put(self, key: ConnectionKey, record: ConnectionRecord) -> ConnectionRecord:
        self.rows[(key.sub, key.client_id)] = record
        return record


auth = LaneMcpAuth(
    resource=os.environ["LANE_RESOURCE"],
    client_id=os.environ["LANE_CLIENT_ID"],
    announce_secret=os.environ["LANE_CLIENT_SECRET"],
    verification=os.environ.get("LANE_VERIFICATION"),
    org_key=os.environ["LANE_ORG_KEY"],
    connections=MemoryConnections(),
    exchanger=HttpTokenExchanger(
        client_id=os.environ["LANE_CLIENT_ID"],
        client_secret=os.environ["LANE_CLIENT_SECRET"],
    ),
)

mcp = FastMCP("acme")


class AttachLaneClaims(Middleware):
    async def on_call_tool(self, context, call_next):
        claims = get_http_request().state.lane_claims
        setattr(context.fastmcp_context.request_context, CLAIMS_ATTR, claims)
        return await call_next(context)


class VerifyLaneBearer(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        if request.url.path.startswith("/.well-known/"):
            return await call_next(request)
        token = request.headers.get("authorization", "").removeprefix("Bearer ").strip() or None
        claims = auth.authenticate(token)
        if claims is None:
            return Response(status_code=401, headers={"WWW-Authenticate": auth.challenge(token)})
        request.state.lane_claims = claims
        return await call_next(request)


mcp.add_middleware(AttachLaneClaims())
enable_lane_auth(mcp, auth)


@mcp.tool()
@requires("read")
async def order_history(ctx: Context) -> str:
    return "two orders"


for path in filter(None, auth.metadata_paths()):
    @mcp.custom_route(path, methods=["GET"])
    async def lane_document(request) -> Response:
        return Response(auth.protected_resource_document(), media_type="application/json")


app = mcp.http_app(middleware=[AsgiMiddleware(VerifyLaneBearer)])

Serve app with any ASGI server, for example uvicorn server:app. An agent that calls order_history is told to call lane_register_session first. After that call, the tool runs when the connection holds <your host>/read.

Documentation

Start with the quickstart.

Licence

MIT

Metadata

Release files for lane-mcp-auth 1.2.1

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

Source distribution (sdist)

Source distribution for lane-mcp-auth 1.2.1
File Size Uploaded Provenance Actions
lane_mcp_auth-1.2.1.tar.gz 233.9 kB With provenance Details for lane_mcp_auth-1.2.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for lane-mcp-auth 1.2.1
File Interpreter ABI Platform Actions
lane_mcp_auth-1.2.1-py3-none-any.whl Python 3 none any Details for lane_mcp_auth-1.2.1-py3-none-any.whl

Total release size: 299.3 kB

Release files / lane_mcp_auth-1.2.1.tar.gz

Download URL lane_mcp_auth-1.2.1.tar.gz
Size 233.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3cf558ca0ee8ab6e06adf5f1618f140a4098aa70d16f5c425901bc424ff41798
BLAKE2b-256 checksum
How to use checksums
bb1c0a297e35c2379e12f52de9754fb8053dcc55caadcfb4584fd1cea049fc4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / lane_mcp_auth-1.2.1-py3-none-any.whl

Download URL lane_mcp_auth-1.2.1-py3-none-any.whl
Size 65.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4bf8465c66b50d76ff0fb171aca0a267e94300f29beeab0400edaef7a8024dd6
BLAKE2b-256 checksum
How to use checksums
7373711d5ec8aa6e95975f96c60b7a2310f48e90dd53c91f1f7a434b3e56e5e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Security for lane-mcp-auth 1.2.1

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for lane_mcp_auth-1.2.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

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