Skip to main content

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:

  1. POST /api/mcp/tools/call with tools/call JSON-RPC and tool centurian.register_agent.
  2. GET /api/mcp/resources/org_global_rules_manifest?org_id=... to seed the local rule cache.
  3. Start the durable sqlite-backed event queue. Tool invocations enqueue trajectory + tool-call events; the queue flushes via centurian.report_*_bulk JSON-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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

centurian_sdk-0.1.0b8.tar.gz (29.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

centurian_sdk-0.1.0b8-py3-none-any.whl (23.0 kB view details)

Uploaded Python 3

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

Hashes for centurian_sdk-0.1.0b8.tar.gz
Algorithm Hash digest
SHA256 bf88bf86b2def05568d5fc7b487e75e267c7d68d45253bec801d56677f62b880
MD5 b1dff24013aae871bd19a37c2a79bbaa
BLAKE2b-256 ea9616f9775d85ea9f43f5d5ee3137b77064560cf7ba27f04cd0f9b61338046f

See more details on using hashes here.

Provenance

The following attestation bundles were made for centurian_sdk-0.1.0b8.tar.gz:

Publisher: release.yml on omniviewai/Centurian

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for centurian_sdk-0.1.0b8-py3-none-any.whl
Algorithm Hash digest
SHA256 527614cc3630bffd99dd02b5689a25c78593381bdb55cf23cf8c9ba31a7696d9
MD5 b9129dfb36ed837992d112c244144407
BLAKE2b-256 5e86a0d1e7c6cc568a814ef229539d8a237ecda43886591dca5789699d9a8ccf

See more details on using hashes here.

Provenance

The following attestation bundles were made for centurian_sdk-0.1.0b8-py3-none-any.whl:

Publisher: release.yml on omniviewai/Centurian

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page