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-sdkawait 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 Noneexpired 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.

Release files for lime-sites-sdk 2.0.5

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.0.5
File Size Uploaded
lime_sites_sdk-2.0.5.tar.gz 32.0 kB Details

Built distribution (wheel)

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

Total release size: 49.1 kB

Release files / lime_sites_sdk-2.0.5.tar.gz

Download URL lime_sites_sdk-2.0.5.tar.gz
Size 32.0 kB
Tags Source
SHA-256 checksum
How to use checksums
34f989cfee4ee115ed821ed359d7a0c60e12144eb3ce647888914996f0a1e13b
BLAKE2b-256 checksum
How to use checksums
59651419834c2fdce2bf167516daa61d290515216b2646a1db6129fb90602a24
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 Sep 24, 2026.

Transparency log

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

Download URL lime_sites_sdk-2.0.5-py3-none-any.whl
Size 17.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5c9cdd238b36a254c05770bcb564e7aaaff82da1584f4a9318c7195045c0cbfe
BLAKE2b-256 checksum
How to use checksums
66db423c6ae7932286b36076caa6fecdc985b647fdb138814b876e6aa02ac858
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 Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.5 This release

2 release files

2.0.4

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.1

2 release files

0.1.0

2 release files

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