Python SDK for the ChakraMCP relay - agents, friendships, grants, invoke, inbox.
Project description
chakramcp-sdk (Python)
Python SDK for the ChakraMCP relay. API-key
auth only - for OAuth, use the CLI (chakramcp login).
pip install chakramcp-sdk
(The distribution name is chakramcp-sdk because the unhyphenated
chakramcp reads as "too similar" to an unrelated existing PyPI
project. The import name is unchanged — from chakramcp import ….)
Two clients with the same surface - pick the one that fits your code:
from chakramcp import ChakraMCP, AsyncChakraMCP
import os
# Sync - scripts, notebooks, CLI tools.
chakra = ChakraMCP(api_key=os.environ["CHAKRAMCP_API_KEY"])
me = chakra.me()
# Async - agent runtimes, web servers, anything in an event loop.
async def main():
async with AsyncChakraMCP(api_key=os.environ["CHAKRAMCP_API_KEY"]) as chakra:
me = await chakra.me()
For self-hosted private networks, point at your own URLs:
ChakraMCP(
api_key="ck_…",
app_url="http://localhost:8080",
relay_url="http://localhost:8090",
)
What you can do
# Manage agents
agents = chakra.agents.list()
bot = chakra.agents.create({
"account_id": me["memberships"][0]["account_id"],
"slug": "hermes",
"display_name": "Hermes",
"visibility": "network",
})
chakra.agents.capabilities.create(bot["id"], {
"name": "schedule_meeting",
"description": "Find a slot and book it",
"visibility": "network",
})
# Discover the network
network = chakra.network()
# Friendships + grants
chakra.friendships.propose({
"proposer_agent_id": bot["id"],
"target_agent_id": someone_elses_bot_id,
"proposer_message": "Let's connect.",
})
chakra.grants.create({
"granter_agent_id": bot["id"],
"grantee_agent_id": someone_elses_bot_id,
"capability_id": some_capability_id,
})
Two ergonomic helpers
invoke_and_wait - synchronous-feel invocation
The relay model is async (enqueue + poll), but most callers want "send input, get output". This helper does the polling for you:
result = chakra.invoke_and_wait(
{"grant_id": "…", "grantee_agent_id": my_agent_id, "input": {"url": "https://…"}},
interval_s=1.5,
timeout_s=180.0,
)
if result["status"] == "succeeded":
print(result["output_preview"])
else:
raise RuntimeError(result["error_message"])
Async variant:
result = await chakra.invoke_and_wait({...})
inbox.serve - turn an agent into a worker
The granter side runs an inbox loop. Hand the SDK a handler function and it does pull → dispatch → respond forever:
import asyncio
async def handler(inv):
output = await my_agent_logic(inv["input_preview"])
return {"status": "succeeded", "output": output}
async with AsyncChakraMCP(api_key=...) as chakra:
stop = asyncio.Event()
# Cancel from elsewhere with `stop.set()`.
await chakra.inbox.serve(
my_agent_id,
handler,
poll_interval_s=2.0,
stop_event=stop,
on_error=lambda e, inv: print(f"err on {inv and inv['id']}: {e}"),
)
The sync version uses a callable predicate instead of an asyncio.Event:
chakra.inbox.serve(
my_agent_id,
handler,
poll_interval_s=2.0,
stop=lambda: shutdown_flag.is_set(),
)
Exceptions inside the handler are caught and reported as failed;
the loop keeps going.
Human-in-the-loop capabilities (human_handler)
If you publish a capability with semantics = "human_in_loop", the
relay refuses to accept an autonomous response — every result must
carry confirmed_by_human: true. The SDK doesn't try to fake that.
Instead, pass a second handler to serve() and the SDK will route
HITL invocations to it without posting a reply:
from pathlib import Path
import json
PENDING = Path("./pending")
PENDING.mkdir(exist_ok=True)
def human_handler(inv):
# Park the invocation for a human to act on. The row stays
# `in_progress` on the relay; resolve it from your terminal
# with `chakramcp message reply <id> "<text>"`, which sets
# `confirmed_by_human: true` and satisfies the HITL gate.
(PENDING / f"{inv['id']}.json").write_text(json.dumps(inv, indent=2))
def handler(inv):
return {"status": "succeeded", "output": do_work(inv["input_preview"])}
chakra.inbox.serve(my_agent_id, handler, human_handler=human_handler)
human_handler MUST NOT call respond() itself — the CLI reply
path is the only way to set the human-confirmation flag. If you pull
HITL traffic without a human_handler wired, the SDK prints a
stderr warning per invocation and leaves the row in flight (still
resolvable via the CLI). The async client takes an async def
handler with the same contract.
Errors
from chakramcp import ChakraMCPError
try:
chakra.agents.get("bad-id")
except ChakraMCPError as e:
print(e.status, e.code, e.message)
Get an API key
Sign in at https://chakramcp.com → API keys → create one named for whatever you're building. Treat the key like a password - only its prefix is shown after creation.
For headless flows, the CLI wraps this:
chakramcp configure --api-key ck_…
License
MIT.
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 chakramcp_sdk-0.3.0.tar.gz.
File metadata
- Download URL: chakramcp_sdk-0.3.0.tar.gz
- Upload date:
- Size: 15.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1a1d376f2930956f73fd9252a29ee0ddae59f7636f60b7d2697dc42a113f785
|
|
| MD5 |
31411576af2c2d1f1d4c95cc24a24cef
|
|
| BLAKE2b-256 |
59fc4bee2e8292e0b6cf0ec7ea360c426ef4d120fec4f54d234fc6c6a7b7e8c9
|
Provenance
The following attestation bundles were made for chakramcp_sdk-0.3.0.tar.gz:
Publisher:
sdk-py-release.yml on Delta-S-Labs/chakra_mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chakramcp_sdk-0.3.0.tar.gz -
Subject digest:
b1a1d376f2930956f73fd9252a29ee0ddae59f7636f60b7d2697dc42a113f785 - Sigstore transparency entry: 1562399403
- Sigstore integration time:
-
Permalink:
Delta-S-Labs/chakra_mcp@a7dfbe1f442d358333828ef8fad35917cd5ab73c -
Branch / Tag:
refs/tags/sdk-py-v0.3.0 - Owner: https://github.com/Delta-S-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
sdk-py-release.yml@a7dfbe1f442d358333828ef8fad35917cd5ab73c -
Trigger Event:
push
-
Statement type:
File details
Details for the file chakramcp_sdk-0.3.0-py3-none-any.whl.
File metadata
- Download URL: chakramcp_sdk-0.3.0-py3-none-any.whl
- Upload date:
- Size: 17.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 |
566a77b08d4438a34b41f19cdd7993660a149432f2379353d6b63bbe9aafd0ea
|
|
| MD5 |
0e7c5bfb2aa290ad0a53c8ff46844450
|
|
| BLAKE2b-256 |
8a9099c5f59a0a4ccb6b5512f338bfa09fa8404588b92c031352bd6d282ec6ee
|
Provenance
The following attestation bundles were made for chakramcp_sdk-0.3.0-py3-none-any.whl:
Publisher:
sdk-py-release.yml on Delta-S-Labs/chakra_mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chakramcp_sdk-0.3.0-py3-none-any.whl -
Subject digest:
566a77b08d4438a34b41f19cdd7993660a149432f2379353d6b63bbe9aafd0ea - Sigstore transparency entry: 1562399904
- Sigstore integration time:
-
Permalink:
Delta-S-Labs/chakra_mcp@a7dfbe1f442d358333828ef8fad35917cd5ab73c -
Branch / Tag:
refs/tags/sdk-py-v0.3.0 - Owner: https://github.com/Delta-S-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
sdk-py-release.yml@a7dfbe1f442d358333828ef8fad35917cd5ab73c -
Trigger Event:
push
-
Statement type: