Synchronous Python SDK for code running inside Mitra Server Functions. It exposes the application-scoped capabilities granted to the function token without implementing browser login, token refresh, or privileged control-plane operations.
- Python 3.11 or later
- A short-lived Mitra access token with the resources required by the operations you call
pip install mitra-functions-sdkThe SDK is ready for the target runtime contract, but Functions and Sandbox do not inject it yet. The pending integration must deliver the platform access token separately from user-defined function secrets and install a pinned SDK version in the runtime template.
Until then, the variables below must be supplied explicitly in local or controlled execution environments. Once the runtime integration is available, create one client for the invocation and close it when the handler finishes:
from mitra_functions_sdk import create_client
def handler(event: dict[str, object], context: dict[str, object]) -> dict[str, object]:
with create_client() as mitra:
orders = mitra.entities.table("Order")
created = orders.create(
{
"customerId": event["customerId"],
"status": "pending",
}
)
execution = mitra.functions.execute(
"send-confirmation-function-id",
{"orderId": created["id"]},
)
return {"order": created, "notification": execution}The Python function runner is synchronous, so this SDK deliberately provides a single synchronous API backed by httpx.Client.
The test suite consumes the canonical SDK-PARITY-001 corpus maintained by
@mitralab.io/sdk-core. This repository vendors the exact fixture bytes with a
source repository, full Git commit, version, and SHA-256 digest so normal tests
stay deterministic and offline. Version 0.1.0 is pinned to sdk-core commit
b513454d0d1f7344a4656cd9c0e1e32530c5ea90.
Verify the vendored snapshot on its own:
python scripts/check_contract_fixture.pyWhen both worktrees are available, reproduce the cross-repository equivalence gate by passing the canonical file:
python scripts/check_contract_fixture.py \
--canonical ../mitra-core-sdk/contracts/v0.1.0/sdk-parity.jsonThe path is illustrative and may be absolute. No workspace path is stored in the package. Continuous integration and release gates download the canonical file from the public repository at that exact commit and compare the bytes. They fail even when the vendored file and its local digest are changed together.
The corpus drives all 16 success cases, every response-validation case, and
every concrete HTTP-adapter case through the real synchronous SDK modules and
HttpTransport with an httpx.MockTransport boundary.
create_client() reads the target runtime contract:
| Variable | Required | Description |
|---|---|---|
MITRA_API_URL |
yes | Base URL of the Mitra API gateway. |
MITRA_PLATFORM_ACCESS_TOKEN |
yes | Short-lived bearer token for the current function invocation. |
MITRA_APP_ID |
yes | Application scope propagated as X-App-Id. |
MITRA_DATA_SOURCE_ID |
no | Data source used by custom queries. If absent, call init(). |
For local development or tests, pass explicit configuration:
from mitra_functions_sdk import MitraClientConfig, create_client
mitra = create_client(
MitraClientConfig(
api_url="http://localhost:8000",
access_token="short-lived-token",
app_id="app-id",
timeout_seconds=10,
)
)The access token and injected HTTP client are excluded from the configuration representation. The SDK does not log credentials, refresh tokens, read browser storage, or retry requests automatically.
Entity CRUD is scoped by the token and X-App-Id, so it is available immediately. Custom queries also require a data source ID. Supply MITRA_DATA_SOURCE_ID or resolve it once through Code Studio:
with create_client() as mitra:
mitra.init()
result = mitra.queries.execute("5df41c69-2a74-4db6-9cca-4af2b473941f", {"limit": 20})Calling init() is idempotent. It requests GET /code-studio/api/v1/apps/{appId}/info only when no data source was configured.
The current release targets the Data Manager main custom-query request and
sends both dataSourceId and parameters. The recorded alpha contract accepts
the same request body but resolves the data source from the authenticated app,
ignoring the body field. The SDK never retries the POST with another shape. A
future parameters-only migration still requires the coordinated server,
canonical-corpus, deprecation, and SDK gates recorded in SDK-PARITY-001.
Requires PROFILE_READ.
current_user = mitra.auth.me()Requires ENTITY_READ, ENTITY_WRITE, or ENTITY_DELETE, depending on the operation.
tasks = mitra.entities.table("Task")
page = tasks.list(sort="-created_at", limit=20, fields=["id", "status"])
pending = tasks.filter({"status": "pending"}, limit=10)
task = tasks.get("task-id")
created = tasks.create({"title": "Prepare release", "status": "pending"})
created_many = tasks.bulk_create([{"title": "A"}, {"title": "B"}])
updated = tasks.update("task-id", {"status": "done"})
tasks.delete("task-id")
deleted = tasks.delete_many({"status": "archived"})delete_many() rejects an empty filter locally to preserve the Data Manager safety contract. Its result preserves the API envelope: {"deleted": number}.
Requires QUERY_EXECUTE and a resolved data source ID.
result = mitra.queries.execute(
"5df41c69-2a74-4db6-9cca-4af2b473941f",
{"status": "active"},
)Requires FUNCTION_EXECUTE. Reading an execution requires FUNCTION_EXECUTION_READ.
# Blocks until the execution reaches a terminal state.
terminal = mitra.functions.execute("function-id", {"orderId": "123"})
# Returns the accepted execution without waiting for completion.
accepted = mitra.functions.execute_async("function-id", {"orderId": "123"})
current = mitra.functions.get_execution(accepted["id"])
mitra.functions.cancel_execution(accepted["id"])execute() always sends X-Invocation-Type: sync. execute_async() always sends X-Invocation-Type: async, avoiding dependence on the service default.
Requires INTEGRATION_EXECUTE.
resource_result = mitra.integration.execute_resource(
"resource-id",
{"customerId": "123"},
)
proxy_result = mitra.integration.execute(
"template-config-id",
{
"method": "POST",
"endpoint": "/orders",
"body": {"customerId": "123"},
},
)Direct integration execution always sets source to SDK.
MitraConfigError: missing or invalid local configuration.MitraNetworkError: timeout or transport failure before a response.MitraResponseError: malformed successful response.MitraApiError: non-success HTTP response, with normalizedstatus,code,details,request_id, andretryablemetadata.
The local errors use the same normalized envelope as API errors.
MitraNetworkError exposes status=0, details=None, request_id=None, and
retryable=True. MitraResponseError exposes status=200,
code="INVALID_RESPONSE", details=None, request_id=None, and
retryable=False for the successful-response validation path.
When an API error omits retryable, the HTTP adapter classifies 4xx responses
as False and 5xx responses as True. This is diagnostic classification only.
The SDK still makes one attempt and never retries a request automatically.
The JavaScript package represents local timeout, network, and invalid-response failures as MitraApiError with codes REQUEST_TIMEOUT, NETWORK_ERROR, or INVALID_RESPONSE. These map to Python MitraNetworkError and MitraResponseError. API responses use MitraApiError in both packages.
The SDK does not include the access token in its error messages or structured details.
python -m pip install -e '.[test]'
ruff format --check .
ruff check .
mypy
pytest
python -m build
python -m twine check dist/*The continuous integration workflow runs linting, strict type checking, and tests with at least 80 percent coverage on Python 3.11 and 3.12. Distribution metadata checks and the isolated wheel import smoke run on Python 3.12.
Version 0.1.0 intentionally excludes browser authentication, token refresh, API keys, messaging, workspace administration, project administration, raw SQL, schema management, and legacy SDK global configuration.