lime-agents-sdk — Cryptographic Passport for AI Agents (JWT + MCP OAuth)
lime-agents-sdk is the official Python agent SDK for LIME — an AI agent identity platform that issues cryptographic passports (signed JWTs) for autonomous workers. Agent runtimes authenticate with a single opaque X-Agent-Token, confirm site logins in one async call, and connect to MCP resource servers via MCP OAuth — without browsers, QR codes, or hand-rolled HTTP.
Use this package when you build agent workers (not site backends). Pair with lime-sites-sdk on the site side for login creation, SSE delivery, and passport verification.
📖 Python API (Read the Docs): lime-agents-sdk.readthedocs.io
📖 Platform HTTP docs: lime.pics/docs#guide-agentSdk
📦 This SDK: github.com/Mawyxx/lime-agents-sdk
🌐 Platform: https://lime.pics
Why lime-agents-sdk?
| Problem | SDK solution |
|---|---|
| Manual PoW + approve HTTP | await agent.login(request_id) — challenge fetch, SHA-256 PoW, approve, retries |
| Two auth lanes (LIME vs MCP) | X-Agent-Token for LIME APIs; short-lived MCP JWT for external MCP servers |
| MCP OAuth boilerplate | list_tools / call_tool auto-issue + cache MCP JWT; optional get_mcp_access_token() for the raw token |
| Fragile agent credentials | Env-based LIME_AGENT_TOKEN (Stripe-style), typed errors, py.typed |
Two JWT flows (do not mix them)
LIME uses two different JWT artifacts. This SDK covers the agent worker side only.
| Flow | Who gets the JWT | Audience / use | This SDK |
|---|---|---|---|
| Site login passport | Site backend (via SSE) | aud=lime-site-login — cryptographic passport for the logged-in session |
Agent calls login() only; site verifies JWT with lime-sites-sdk + Core JWKS |
| MCP access token | Agent worker (cached in SDK; not sent to site) | aud=mcp — Bearer token for external MCP resource servers |
MCP facade methods auto-issue + cache; optional get_mcp_access_token() if you need the raw JWT |
The MCP JWT is signed with LIME Core keys (JWKS at GET /api/v1/core/.well-known/jwks.json). Default TTL is 300 seconds (5 minutes). The SDK caches it in your worker and performs lazy refresh on the next MCP call when the token is within ~30 seconds of expiry (mcp_token_refresh_skew, default 30) — there is no background refresh task. You send the JWT to remote MCP servers as Authorization: Bearer — not to the site backend. MCP JWTs are rejected on LIME HTTP APIs — only opaque X-Agent-Token works there.
Installation
pip install lime-agents-sdk
Latest from GitHub:
pip install git+https://github.com/Mawyxx/lime-agents-sdk.git
Requirements: Python 3.10+ · runtime deps: httpx, mcp
Quick start
Scenario A — Site login (headless agent authentication)
Story: A site backend starts a login request and hands request_id to your agent worker. The worker proves identity with PoW + approve. The site receives the signed agent passport JWT over SSE (handled by lime-sites-sdk). Your worker only runs the approve step.
import asyncio
import os
from lime_agents import LimeAgent, ApiError, PowTimeoutError
# LIME_AGENT_TOKEN=at_... (from the LIME owner portal — server-side secret only)
REQUEST_ID = "lr_abc123" # from your site backend / job queue
async def main() -> None:
# One LimeAgent per worker process (reuse across jobs)
agent = LimeAgent(agent_token=os.environ["LIME_AGENT_TOKEN"])
try:
result = await agent.login(REQUEST_ID)
print(result.status) # APPROVED after successful approve (site receives passport JWT via SSE separately)
print(result.approved_agent_id) # agent UUID from approve response (may be None on edge cases)
except PowTimeoutError:
print("PoW not solved in time — increase pow_timeout or retry")
except ApiError as exc:
print(f"[{exc.code}] {exc.message}")
finally:
await agent.aclose()
asyncio.run(main())
What login() does internally:
GET /api/v1/auth/requests/{request_id}— read PoW challenge (no auth)- Solve PoW in a thread pool (
asyncio.to_thread) POST /api/v1/modules/agent-login/requests/{request_id}/approvewithX-Agent-Token+{"pow_nonce": "..."}
Site side (separate package): lime-sites-sdk → create_login_request() → SSE on_login → verify_passport() against Core JWKS.
Scenario B — MCP tools (MCP OAuth + streamable HTTP client)
Story: Your agent calls tools on an external MCP resource server. LIME issues a short-lived MCP JWT (~5 min) from your X-Agent-Token. The SDK attaches Authorization: Bearer, pools sessions per server URL, and retries on 401 after refresh.
import asyncio
import os
from lime_agents import LimeAgent, CallToolResult, Tool
MCP_ENDPOINT = "https://mcp.example.com/mcp" # full streamable HTTP path, not just the host
async def main() -> None:
async with LimeAgent(agent_token=os.environ["LIME_AGENT_TOKEN"]) as agent:
# MCP JWT (~300s TTL) is fetched automatically on first list_tools / call_tool
tools: list[Tool] = await agent.list_tools(MCP_ENDPOINT)
print([t.name for t in tools])
result: CallToolResult = await agent.call_tool(
MCP_ENDPOINT,
tools[0].name,
{"text": "hello from LIME agent"},
)
if result.isError:
print("tool error:", result.content)
else:
print(result.content)
# Same agent, another MCP server — sessions cached per URL
# await agent.call_tool("https://other-mcp.example.com/mcp", "get_weather", {"city": "Berlin"})
asyncio.run(main())
Credential lanes (never swap headers):
| Lane | Header | Used for |
|---|---|---|
| LIME platform | X-Agent-Token |
login(), get_profile(), POST .../oauth/token |
| External MCP RS | Authorization: Bearer <mcp_jwt> |
list_tools, call_tool, resources, prompts |
OAuth issuance: POST /api/v1/modules/oauth/token — header only, empty body (MCP OAuth ADR). Resource servers verify the JWT via Core JWKS — use lime-mcp-server-sdk on the server side.
Features
- One-call site login —
await agent.login(request_id)wraps PoW fetch, solve, and approve withX-Agent-Token - MCP OAuth built-in — issue, cache, and lazy-refresh 5-minute MCP JWTs on the next
list_tools/call_toolwhen near expiry; no manual/oauth/tokenin app code - Typed MCP client —
list_tools,call_tool,read_resource,get_prompt, … withmcp.typesmodels re-exported fromlime_agents - Automatic Proof-of-Work — SHA-256 solver with configurable
pow_timeoutand transient retry policy - Production-ready LIME HTTP — httpx async client, exponential backoff on 408/429/5xx for platform calls (
login, profile, OAuth issuance); MCP calls retry on 401 after token refresh - Strict typing —
ApprovalResult,AgentProfile,McpAccessToken,py.typed, mypy-clean public API
API reference (summary)
LimeAgent
| Method | Description |
|---|---|
await agent.login(request_id) |
Site login approve flow → ApprovalResult |
await agent.get_profile() |
GET /core/agents/me/profile → AgentProfile |
await agent.get_mcp_access_token() |
Optional: expose cached MCP OAuth JWT (~300s TTL); not required before MCP calls |
await agent.list_tools(server_url) |
MCP tools (typed Tool) |
await agent.call_tool(server_url, name, args) |
MCP tool invocation → CallToolResult |
await agent.list_resources(...) / read_resource(...) / list_prompts(...) / get_prompt(...) |
Full MCP facade |
async with agent.mcp_session(url) |
Low-level mcp.ClientSession with per-URL lock |
Constructor highlights: agent_token / LIME_AGENT_TOKEN, base_url / LIME_API_BASE (default https://lime.pics/api/v1), timeout, max_retries, mcp_token_refresh_skew (default 30, lazy refresh window), serialize_mcp_per_url (default True).
Context manager: async with LimeAgent() as agent: calls aclose() on exit. For long-running workers, create one instance at startup and reuse it.
Environment variables
| Variable | Required | Description |
|---|---|---|
LIME_AGENT_TOKEN |
Yes* | Agent secret (at_...) from the LIME portal |
LIME_API_BASE |
No | API root, e.g. https://lime.pics/api/v1 |
*Unless agent_token= is passed to the constructor.
Errors
All inherit from LimeError: AuthenticationError, PowTimeoutError, RateLimitError, ApiError, McpAuthenticationError, OAuthCapabilityError.
Related packages
| Package | Role |
|---|---|
lime-sites-sdk |
Site backend: create login, SSE events, verify site passport JWT |
lime-mcp-server-sdk |
MCP resource server: verify MCP Bearer JWT via Core JWKS |
Contributing
Issues and pull requests: github.com/Mawyxx/lime-agents-sdk
git clone https://github.com/Mawyxx/lime-agents-sdk.git
cd lime-agents-sdk
pip install -e ".[dev]"
ruff check src tests
mypy src/lime_agents
pytest --cov=lime_agents --cov-fail-under=100
CI runs on Python 3.10–3.13 with 100% line coverage on src/lime_agents.
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lime_agents_sdk-0.5.6.tar.gz.
File metadata
- Download URL: lime_agents_sdk-0.5.6.tar.gz
- Upload date:
- Size: 37.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13e01d068d660cb433c3850d35ea5c637efc2bf0c894011d1a292d30203cae5f
|
|
| MD5 |
91058d365242a65620b2b4eb1b821204
|
|
| BLAKE2b-256 |
a9458c0f5655135631852bffe465ed68867056b2ed6cb72931790d6dda31e657
|
File details
Details for the file lime_agents_sdk-0.5.6-py3-none-any.whl.
File metadata
- Download URL: lime_agents_sdk-0.5.6-py3-none-any.whl
- Upload date:
- Size: 20.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2671e29197477e7c240abf57460655a94bd9d8506aa5f387b38bd40d13da9473
|
|
| MD5 |
cb74a31bdc3a04883ca44a66324665cb
|
|
| BLAKE2b-256 |
d4d09df04a57b8e45f552109d168b12448e5654f184c34550c3a6284021086f5
|