Centurian Python SDK — thin MCP wrapper for AI agents. Auto-registers, instruments tool calls, attributes cost. Implements ADR-017 SDK perf primitives: local rule cache + per-action OPA decision cache + durable sqlite-backed event queue + async batched MCP calls. Owner: Connect agent (T12 W3-W5).
Project description
centurian-sdk (Python)
Thin MCP wrapper for AI agents. See docs/prd/v4.1/Centurian_Solo_Developer_Experience.md.
Status
Version 0.1.0b8 ships real network calls to the Centurian control plane. The previous 0.1.0b7 shipped a stub MCP transport (security audit C1) — anyone on <= 0.1.0b7 should upgrade.
Install
pip install centurian-sdk
# optional: enable httpx transport (otherwise stdlib urllib is used)
pip install 'centurian-sdk[http]'
For local-monorepo development:
pip install -e ./packages/sdk-python
Quickstart
from centurian import Agent
agent = Agent(
name="my-agent",
purpose="Answer questions about my docs",
# token is the provisioning token from your /signup flow
# (also auto-read from CENTURIAN_TOKEN env)
)
@agent.tool
def search_docs(query: str) -> str:
return run_my_search(query)
agent.run()
agent.run() does this over the network:
- POST
/api/mcp/tools/callwithtools/callJSON-RPC and toolcenturian.register_agent. - GET
/api/mcp/resources/org_global_rules_manifest?org_id=...to seed the local rule cache. - Start the durable sqlite-backed event queue. Tool invocations enqueue trajectory + tool-call events; the queue flushes via
centurian.report_*_bulkJSON-RPC calls.
Auth
| Call | Auth |
|---|---|
register_agent |
Authorization: Bearer <provisioning_token> (passed via token constructor arg or CENTURIAN_TOKEN env var) |
All spine-ingest tools (report_*, submit_*) |
signing_credential field inside the tool arguments — extracted from the agent identity returned by register_agent |
Action evaluation
agent.evaluate_action(verb, attributes) consults the local rule cache and returns an ActionDecision:
| Effect | decision.allowed |
When |
|---|---|---|
allow |
True |
Rule explicitly allows or no rule matches and manifest is fresh |
deny |
False |
Rule explicitly denies |
escalate |
False |
Synchronous human-in-the-loop gate required |
miss |
False |
Rule manifest stale or absent — treat as deny (Shadow #21 fix). Re-prime via agent.run() or mcp.prime_rule_cache(). |
Use agent.assert_action_allowed(...) to raise ActionRefusedError instead of branching.
Configuration
Reads CENTURIAN_TOKEN, CENTURIAN_MCP_URL, CENTURIAN_ORG_ID, CENTURIAN_OWNER_USER_ID, CENTURIAN_QUEUE_PATH from env.
Errors
McpRpcError(code, message, data)— JSON-RPC error envelope from the server (4xx).McpTransportError(message, status=None)— network failure after retries exhausted (5xx, DNS, TLS).ActionRefusedError(decision)— local rule cache refused the action.
Known beta limitations (v0.1.0b8)
These are documented gaps tracked for the 0.1.0 GA release. Production usage on --pre should be aware:
W3-C1c — register_agent provisioning-token binding is surface-only
The HTTP endpoint at /api/mcp/tools/call requires an Authorization: Bearer <provisioning_token> header for register_agent, but only validates that the token is ≥16 characters. The handler trusts the org_id and owner_user_id claims supplied in the call arguments; it does NOT verify that the bearer token is bound to those claims server-side. Implication: anyone with any 16+ char string can register an agent under any org/owner they claim. The registered agent's signing credential IS bound at the row level, so subsequent calls authenticate normally — but the registration itself is a trust gap.
Mitigation in beta: treat your provisioning tokens as confidential; only obtain them through the documented /signup flow; rotate via centurian.rotate_credential if compromised. GA fix planned: introspectable provisioning_tokens table that binds each token to a specific (org_id, owner_user_id, expires_at) and rejects mismatches.
#13 — validateSigningCredential runs scrypt on every event ingest
Each report_trajectory_step, report_tool_call, etc. validates the signing_credential via scrypt (~30ms per call). High-throughput callers should batch via the bulk variants (report_trajectory_steps_bulk, report_tool_calls_bulk) which amortize the auth cost across up to 1,000 events per round trip. The SDK's BatchClient does this automatically; manual MCP callers should follow the pattern. GA fix planned: auth-cache layer keying validated credentials by (prefix, secret_hash) for 60s LRU.
#17 — No nonce/JTI replay defense on signing credentials
Captured cnt_live_* credentials are valid for their full TTL (default 90 days) until rotated. There is no nonce/JTI/timestamp on signed requests. Mitigation in beta: rotate credentials proactively if you suspect interception; restrict your SDK runtime environment so credentials cannot be exfiltrated. GA fix planned: SDK signs requests with timestamp + nonce; server rejects nonces seen within rotation window or timestamps with >5min skew.
Other deferred items
- KMS-managed signing keys for tier-3 audit reports — not yet shipped; tier-3 audit emit throws in production until the host registers a real signer resolver.
- Per-org rate limiting at the MCP HTTP route — not yet implemented; free-tier $5/mo + 10K-step caps at the cost layer mitigate.
License
Proprietary. © Centurian.
Project details
Release history Release notifications | RSS feed
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 centurian_sdk-0.1.0b8.tar.gz.
File metadata
- Download URL: centurian_sdk-0.1.0b8.tar.gz
- Upload date:
- Size: 29.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf88bf86b2def05568d5fc7b487e75e267c7d68d45253bec801d56677f62b880
|
|
| MD5 |
b1dff24013aae871bd19a37c2a79bbaa
|
|
| BLAKE2b-256 |
ea9616f9775d85ea9f43f5d5ee3137b77064560cf7ba27f04cd0f9b61338046f
|
Provenance
The following attestation bundles were made for centurian_sdk-0.1.0b8.tar.gz:
Publisher:
release.yml on omniviewai/Centurian
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
centurian_sdk-0.1.0b8.tar.gz -
Subject digest:
bf88bf86b2def05568d5fc7b487e75e267c7d68d45253bec801d56677f62b880 - Sigstore transparency entry: 1404665068
- Sigstore integration time:
-
Permalink:
omniviewai/Centurian@9e78c80b450d1c8a4c91f9e186d556d2707de228 -
Branch / Tag:
refs/tags/v0.1.0-beta.8 - Owner: https://github.com/omniviewai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9e78c80b450d1c8a4c91f9e186d556d2707de228 -
Trigger Event:
push
-
Statement type:
File details
Details for the file centurian_sdk-0.1.0b8-py3-none-any.whl.
File metadata
- Download URL: centurian_sdk-0.1.0b8-py3-none-any.whl
- Upload date:
- Size: 23.0 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 |
527614cc3630bffd99dd02b5689a25c78593381bdb55cf23cf8c9ba31a7696d9
|
|
| MD5 |
b9129dfb36ed837992d112c244144407
|
|
| BLAKE2b-256 |
5e86a0d1e7c6cc568a814ef229539d8a237ecda43886591dca5789699d9a8ccf
|
Provenance
The following attestation bundles were made for centurian_sdk-0.1.0b8-py3-none-any.whl:
Publisher:
release.yml on omniviewai/Centurian
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
centurian_sdk-0.1.0b8-py3-none-any.whl -
Subject digest:
527614cc3630bffd99dd02b5689a25c78593381bdb55cf23cf8c9ba31a7696d9 - Sigstore transparency entry: 1404665199
- Sigstore integration time:
-
Permalink:
omniviewai/Centurian@9e78c80b450d1c8a4c91f9e186d556d2707de228 -
Branch / Tag:
refs/tags/v0.1.0-beta.8 - Owner: https://github.com/omniviewai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9e78c80b450d1c8a4c91f9e186d556d2707de228 -
Trigger Event:
push
-
Statement type: