Skip to main content

lime-sites-sdk

Accept AI agent login on your site backend — create a request, get a Core-signed passport over SSE, verify locally with JWKS.

Canonical docs

Surface URL
Hello (agents) https://lime.pics/agent
Auth https://lime.pics/auth.md
Flows https://lime.pics/.well-known/agent-flows
Site login guide https://lime.pics/docs/guides/site-login/
Binding guide https://lime.pics/docs/guides/site-binding/
Machine package https://lime.pics/.well-known/agent-context/
GitHub https://github.com/Mawyxx/lime-site-sdk

Prefer lime.pics + GitHub over stale RTD mirrors.

from lime_sites import LimeSite

site = LimeSite()  # LIME_SITE_TOKEN — construct inside a running asyncio loop

@site.on_login
async def handle_login(request_id: str, passport: str | None) -> None:
    if passport is None:
        return  # expired
    verified = await site.verify_passport(passport, expected_request_id=request_id)
    # issue YOUR session cookie from verified.claims

req = await site.create_login_request()
# show req.request_id on YOUR waiting screen → agent.login(request_id)

What the SDK handles: Site Token auth · login request · SSE passport delivery · JWKS verify · optional agent binding.

PyPI version Python versions License: MIT CI

Docs: lime.pics/docs · auth.md · GitHub


Installation

pip install lime-sites-sdk
export LIME_SITE_TOKEN=st_...   # from https://lime.pics — site portal

Requirements: Python 3.10+ · httpx · PyJWT · cryptography
Config: one secret — LIME_SITE_TOKEN (or site_token=). Never give Site Token to the agent.


Quick start (canonical) — FastAPI site login

from contextlib import asynccontextmanager

from fastapi import FastAPI
from lime_sites import InvalidPassportError, LimeSite

pending_logins: dict[str, object] = {}
site: LimeSite


@asynccontextmanager
async def lifespan(app: FastAPI):
    global site
    site = LimeSite()  # one LimeSite per process / site token

    @site.on_login
    async def handle_login(request_id: str, passport: str | None) -> None:
        if passport is None:
            pending_logins.pop(request_id, None)
            return
        try:
            verified = await site.verify_passport(
                passport,
                expected_request_id=request_id,
            )
        except InvalidPassportError:
            pending_logins.pop(request_id, None)
            return
        pending_logins[request_id] = verified.claims  # set YOUR session

    yield
    await site.aclose()


app = FastAPI(lifespan=lifespan)


@app.post("/login/start")
async def start_login() -> dict[str, str]:
    req = await site.create_login_request()
    return {"request_id": req.request_id}

Copy-paste: examples/fastapi-login/.

Agent worker (separate package): lime-agents-sdk → await agent.login(request_id).


Mental model

LimeSite
├── Site login (primary)   create_login_request · on_login · verify_passport
├── Agent binding          create_binding_request · verify_binding_passport
└── Lifecycle              aclose()
Credential Header Used for
Opaque Site Token X-Site-Token Your backend ↔ LIME only
Site passport JWT delivered on SSE Session after verify_passport (aud=lime-site-login)

Site login ≠ agent binding. MCP Bearer (aud=mcp) is not verified here — use lime-mcp-server-sdk.


Rules that prevent foot-guns

Rule Why
One LimeSite per site token per process One SSE connection
Construct inside a running asyncio loop Dispatcher uses create_task
Keep @site.on_login handlers fast Events dispatch sequentially
passport is None → expired Clear pending state

Second scenario — Agent binding

IS: Bind a LIME agent_id to a signed-in human via Connect (aud=lime-binding). No SSE.
DO: create → redirect human to connect_url → callback ?binding_code= → exchange → verify_binding_passport.
NEVER: JWT in redirect URL (query or fragment).

req = await site.create_binding_request(redirect_uri="https://yoursite.example/bind/callback")
# persist req.binding_id ↔ user_id, redirect browser to req.connect_url
# callback: binding_code = query["binding_code"]
# POST /api/v1/modules/bindings/exchange with X-Site-Token + {"binding_code": ...}
#   → data.passport, then:
# verified = await site.verify_binding_passport(passport)
# → claims["binding_id"] / claims["agent_id"] (sub)

Canonical wire: site-binding guide · flow agent_binding in agent-flows.
Example sketch: examples/binding/.


Minimal end-to-end loop

With both SDKs installed (lime-sites-sdk + lime-agents-sdk):

import asyncio

from lime_agents import LimeAgent
from lime_sites import LimeSite

async def main() -> None:
    received = asyncio.Event()
    box: dict[str, str] = {}

    site = LimeSite()

    @site.on_login
    async def handle_login(request_id: str, passport: str | None) -> None:
        if passport:
            box["jwt"] = passport
            received.set()

    req = await site.create_login_request()

    async with LimeAgent() as agent:
        await agent.login(req.request_id)

    await asyncio.wait_for(received.wait(), timeout=120)
    verified = await site.verify_passport(box["jwt"], expected_request_id=req.request_id)
    print(verified.claims)
    await site.aclose()

asyncio.run(main())

Example: examples/minimal-loop/.


API surface (summary)

Method Description
create_login_request() Start site login → request_id
@site.on_login Handler (request_id, passport | None)
verify_passport(jwt, …) JWKS verify aud=lime-site-login
create_binding_request(…) Start Connect binding → binding_id + connect_url
verify_binding_passport(jwt) JWKS verify aud=lime-binding (after ?binding_code= → exchange)
aclose() Stop SSE / close client

Env: LIME_SITE_TOKEN (required unless constructor), LIME_API_BASE (optional).


Package Role
lime-agents-sdk Agent worker: login(request_id) + MCP client
lime-mcp-server-sdk MCP RS: verify aud=mcp Bearer

Examples

Path Purpose
examples/fastapi-login/ Canonical site login
examples/minimal-loop/ Site + agent E2E sketch
examples/binding/ Connect binding sketch

Contributing

git clone https://github.com/Mawyxx/lime-site-sdk.git
cd lime-site-sdk
pip install -e ".[dev]"
ruff check src tests
mypy src/lime_sites
pytest --cov=lime_sites --cov-fail-under=100

License

MIT — see LICENSE.

Metadata

Release files for lime-sites-sdk 2.1.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 lime-sites-sdk 2.1.1
File Size Uploaded Provenance Actions
lime_sites_sdk-2.1.1.tar.gz 34.4 kB With provenance Details for lime_sites_sdk-2.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for lime-sites-sdk 2.1.1
File Interpreter ABI Platform Actions
lime_sites_sdk-2.1.1-py3-none-any.whl Python 3 none any Details for lime_sites_sdk-2.1.1-py3-none-any.whl

Total release size: 52.2 kB

Release files / lime_sites_sdk-2.1.1.tar.gz

Download URL lime_sites_sdk-2.1.1.tar.gz
Size 34.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c8724cf8e4bdecf5be3b4aa6d430514366e36de3215df54d18d6ecc22a69e514
BLAKE2b-256 checksum
How to use checksums
8c82082fe7c921256945d88a90bc1cccb4deeabb1a0957b43aeaa5396265c8bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 3, 2026.

Transparency log

Release files / lime_sites_sdk-2.1.1-py3-none-any.whl

Download URL lime_sites_sdk-2.1.1-py3-none-any.whl
Size 17.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1439fdd6e3b4b60f84585119c722e288d7cf35ac12284a92de7298dde13679c1
BLAKE2b-256 checksum
How to use checksums
e9b844570375e49a6eb7e9b4478d88aec9cbc738236aa2f0bbef24e278a0a7a7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 3, 2026.

Transparency log

Security for lime-sites-sdk 2.1.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

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for lime_sites_sdk-2.1.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 Nov 3, 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