Slim Redis RPC implementation
Project description
Callite
Callite is a lightweight Remote Procedure Call (RPC) library over Redis, designed for communication between components of a distributed system. It uses Redis Streams for request transport and Redis Pub/Sub for response delivery, with pickle serialization.
Installation
pip install callite
To use the MCP bridge (for AI agent integration):
pip install callite[mcp]
Prerequisites
A running Redis instance is required. You can start one locally:
docker run -d -p 6379:6379 redis:alpine
Or use the included Docker Compose setup for a full development environment:
docker-compose up
Usage
Request/Response (register + execute)
The most common pattern: the client sends a request and waits for a response.
Server:
from callite.server import RPCServer
server = RPCServer("redis://localhost:6379/0", "my_service")
@server.register
def healthcheck():
return "OK"
@server.register
def add(a, b):
return a + b
server.run_forever()
Client:
from callite.client import RPCClient
client = RPCClient("redis://localhost:6379/0", "my_service")
# Positional arguments
result = client.execute("add", 1, 2)
print(result) # 3
# Keyword arguments
result = client.execute("add", a=10, b=20)
print(result) # 30
# No arguments
status = client.execute("healthcheck")
print(status) # "OK"
# Close when done
client.close()
execute() blocks until the server responds or the timeout is reached (default: 30 seconds). If the server-side handler raises an exception, execute() re-raises it on the client side.
Fire-and-Forget (subscribe + publish)
For one-way messages where the client does not need a response.
Server:
from callite.server import RPCServer
server = RPCServer("redis://localhost:6379/0", "my_service")
@server.subscribe
def log(message):
print(f"Received: {message}")
server.run_forever()
Client:
from callite.client import RPCClient
client = RPCClient("redis://localhost:6379/0", "my_service")
# publish() returns immediately without waiting for a response
client.publish("log", "Something happened")
Combining Both Patterns
A single service can use both register and subscribe:
from callite.server import RPCServer
server = RPCServer("redis://localhost:6379/0", "my_service")
@server.register
def add(a, b):
return a + b
@server.subscribe
def log(message):
print(message)
server.run_forever()
from callite.client import RPCClient
client = RPCClient("redis://localhost:6379/0", "my_service")
# Request/response
result = client.execute("add", 3, 4)
# Fire-and-forget
client.publish("log", f"Result was {result}")
MCP Integration (AI Agent Integration)
Callite includes three MCP (Model Context Protocol) components for bridging AI agents to RPC services. All three are available from callite.mcp:
from callite.mcp import MCPBridge, MCPHTTPProxy, MCPProxy
Defining Tools and Prompts
register_tool works like register but extracts type hints and docstrings to generate rich metadata for MCP tool discovery:
from callite.server import RPCServer
server = RPCServer("redis://localhost:6379/0", "data_service")
@server.register_tool(description="Add two numbers together")
def add(a: int, b: int) -> int:
"""Add two numbers.
Args:
a: The first number.
b: The second number.
"""
return a + b
server.run_forever()
register_prompt registers prompt templates that AI agents can discover and invoke:
@server.register_prompt(description="Analyze a dataset")
def analyze(data: str, focus: str = "general") -> str:
return f"Please analyze the following data with focus on {focus}:\n{data}"
MCPBridge
A multi-service MCP gateway that discovers callite services via their __describe__ endpoint and registers all tools, prompts, and resources as MCP primitives. Tool names are prefixed with the service name (e.g. data_service_add).
From the command line:
mcp-callite-bridge --redis redis://localhost:6379/0 --services data_service
Or programmatically:
from callite.mcp import MCPBridge
bridge = MCPBridge("redis://localhost:6379/0", ["data_service", "auth_service"])
bridge.run() # stdio transport by default
CLI options:
| Flag | Description | Default |
|---|---|---|
--redis |
Redis connection URL | redis://localhost:6379/0 |
--services |
Comma-separated service names | (required) |
--transport |
stdio or streamable-http |
stdio |
--name |
MCP server display name | callite-bridge |
--timeout |
RPC execution timeout (seconds) | 30 |
--queue-prefix |
Redis key prefix | /callite |
MCPHTTPProxy
An HTTP server that exposes a single callite service over Streamable HTTP. Unlike MCPBridge, tool names are not prefixed with the service name, making it suitable for single-service deployments.
from callite.client import RPCClient
from callite.mcp import MCPHTTPProxy
client = RPCClient("redis://localhost:6379/0", "data_service")
proxy = MCPHTTPProxy(client, host="0.0.0.0", port=8080)
proxy.run() # serves at /mcp
MCPProxy
A client-side proxy that manages an external MCP server subprocess (e.g. uvx mcp-server-sqlite) over stdio and exposes its tools through a synchronous Python API. Use register_proxy on an RPCServer to re-publish external MCP tools as callite RPC methods.
from callite.mcp import MCPProxy
from callite.server import RPCServer
server = RPCServer("redis://localhost:6379/0", "my_service")
proxy = MCPProxy("uvx", ["mcp-server-sqlite", "--db-path", "test.db"])
server.register_proxy(proxy, prefix="sqlite")
server.run_forever()
The proxy auto-reconnects if the subprocess crashes, caches the tool list, and is thread-safe.
Configuration
Environment Variables
| Variable | Description | Default |
|---|---|---|
LOG_LEVEL |
Logging verbosity (DEBUG, INFO, ERROR, etc.) |
ERROR (server), INFO (client) |
EXECUTION_TIMEOUT |
Client-side timeout in seconds for execute() |
30 |
REDIS_URL |
Redis URL (used by the MCP bridge CLI) | redis://localhost:6379/0 |
Constructor Options
RPCServer:
RPCServer(
conn_url="redis://localhost:6379/0",
service="my_service",
queue_prefix="/callite", # Redis key prefix
xread_groupname="generic", # Consumer group name
)
RPCClient:
RPCClient(
conn_url="redis://localhost:6379/0",
service="my_service",
execution_timeout=30, # Timeout in seconds
queue_prefix="/callite", # Redis key prefix
)
Docker Development
The included docker-compose.yml starts Redis, a sample server, and a sample client:
docker-compose up
This runs the example main.py (server) and healthcheck.py (client stress test with 100 concurrent threads).
License
Proprietary
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 callite-1.0.5.tar.gz.
File metadata
- Download URL: callite-1.0.5.tar.gz
- Upload date:
- Size: 24.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
487494605adf1076641df77701a0632664d6d6bc7e11cb20a1dec668a3d50512
|
|
| MD5 |
b8d3af49fc7c57c68ea0ecd68527107e
|
|
| BLAKE2b-256 |
ddd95a2871047286160998e01c54321d5d17e89c785791f6db8ac04d75a93f48
|
Provenance
The following attestation bundles were made for callite-1.0.5.tar.gz:
Publisher:
python-publish.yml on gri-ai/callite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
callite-1.0.5.tar.gz -
Subject digest:
487494605adf1076641df77701a0632664d6d6bc7e11cb20a1dec668a3d50512 - Sigstore transparency entry: 1006502138
- Sigstore integration time:
-
Permalink:
gri-ai/callite@93f5fe414019fc04c6bf598b50bca053a05e9306 -
Branch / Tag:
refs/tags/v1.0.5 - Owner: https://github.com/gri-ai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@93f5fe414019fc04c6bf598b50bca053a05e9306 -
Trigger Event:
push
-
Statement type:
File details
Details for the file callite-1.0.5-py3-none-any.whl.
File metadata
- Download URL: callite-1.0.5-py3-none-any.whl
- Upload date:
- Size: 26.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81380a889d36784f6932a1555bb1214ed31443b62b7d19b35a0a118a165147bb
|
|
| MD5 |
c953c9fc369778da2efc1e70c55a9349
|
|
| BLAKE2b-256 |
81a64b16ab7ee4c9036f8acafc66588a47031928bf7b9f5b80a407206d24ef35
|
Provenance
The following attestation bundles were made for callite-1.0.5-py3-none-any.whl:
Publisher:
python-publish.yml on gri-ai/callite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
callite-1.0.5-py3-none-any.whl -
Subject digest:
81380a889d36784f6932a1555bb1214ed31443b62b7d19b35a0a118a165147bb - Sigstore transparency entry: 1006502139
- Sigstore integration time:
-
Permalink:
gri-ai/callite@93f5fe414019fc04c6bf598b50bca053a05e9306 -
Branch / Tag:
refs/tags/v1.0.5 - Owner: https://github.com/gri-ai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@93f5fe414019fc04c6bf598b50bca053a05e9306 -
Trigger Event:
push
-
Statement type: