rs_poke
June 8, 2026 ยท View on GitHub
Rust client and tunnel bridge for Poke.
A library and CLI for interacting with the Poke API, providing both an HTTP client interface and an asynchronous WebSocket tunnel for MCP (Model Context Protocol) connections. API parity with the official poke@0.4.2 npm SDK.
Features
- HTTP Client: Authenticated API client for Poke services with automatic token management
- Tunnel Bridge: WebSocket-based tunnel for MCP protocol connections
- Webhook Support: Create and manage webhooks programmatically
- Message Passing: Send messages through the Poke API
- CLI:
poke login,poke logout,poke whoami,poke mcp add - Async-First: Built on Tokio for efficient async/await patterns
Installation
Add to your Cargo.toml:
[dependencies]
rs_poke = "0.2.1"
Or install the CLI:
cargo install rs_poke
Usage
HTTP Client
use rs_poke::{Poke, PokeOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Poke::new(PokeOptions::default())?;
let response = client.send_message("Hello, world!").await?;
println!("{}", response.message);
let webhook = client.create_webhook(&rs_poke::CreateWebhook {
condition: "event.type == 'trigger'",
action: "POST",
}).await?;
println!("trigger: {}", webhook.trigger_id);
Ok(())
}
Tunnel Bridge
use rs_poke::{Poke, TunnelOptions, TunnelRunner};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let poke = Poke::new(rs_poke::PokeOptions::default())?;
let mut runner = TunnelRunner::new(poke, TunnelOptions {
url: "http://127.0.0.1:52333/mcp".into(),
name: "my-tunnel".into(),
cleanup_on_stop: true,
sync_interval: std::time::Duration::from_secs(300),
startup_timeout: std::time::Duration::from_secs(30),
..TunnelOptions::default()
});
let info = runner.start().await?;
println!("Tunnel connected: {}", info.tunnel_url);
let mut events = runner.subscribe();
while let Ok(event) = events.recv().await {
match event {
rs_poke::TunnelEvent::Connected(info) => {
println!("Connected: {}", info.tunnel_url);
}
rs_poke::TunnelEvent::Disconnected => break,
_ => {}
}
}
runner.stop().await?;
Ok(())
}
Authentication
use rs_poke::{login, logout, is_logged_in, CredentialsStore, LoginOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let store = CredentialsStore::default_store()?;
let result = login(
LoginOptions::new(store).on_code(|info| {
println!("Open {} and enter {}", info.login_url, info.user_code);
}),
)
.await?;
if is_logged_in() {
println!("Authenticated as {}", result.token);
}
logout().await?;
Ok(())
}
Configuration
Environment Variables
POKE_API- Base URL for Poke API (default:https://poke.com/api/v1)POKE_API_KEY- API key for authenticationPOKE_FRONTEND- Frontend URL for device login (default:https://poke.com)
Credentials Store
Credentials are stored in the user's configuration directory:
- Linux:
~/.config/poke/credentials.json - macOS:
~/Library/Application Support/poke/credentials.json(via XDG_CONFIG_HOME or~/.config/poke) - Windows:
%APPDATA%\poke\credentials.json(via XDG_CONFIG_HOME)
API Reference
Poke
new(options: PokeOptions)- Create a new clientapi_key()/base_url()- Get configured credentials and endpointsend_message(message)- Send a message to Pokecreate_webhook(request)- Create a new webhook (returnstrigger_id)send_webhook(url, token, data)- Send data to a webhook endpointpost_json(path, body)- Authenticated JSON POST helperraw_auth(method, path, body)- Low-level authenticated request
TunnelRunner
new(client, options)- Create a runnerstart()- Start the tunnel connectionstop()- Stop and optionally cleanup the tunnelsync_tools()- Synchronize MCP toolscreate_recipe(name)- Create a shareable recipe linkconnected()- Whether the tunnel is activesubscribe()/on(event, handler)/off(event)- Event handling
CLI
poke login
poke logout
poke whoami
poke mcp add http://127.0.0.1:52333/mcp -n my-server --recipe
Development
cargo test
cargo clippy --all-targets --all-features
cargo fmt
License
Licensed under the Mozilla Public License 2.0. See LICENSE for details.