@kasanovaio/kasia-mcp
v0.1.5
Published
MCP server for Kasia encrypted messaging on Kaspa
Downloads
14
Readme
Kasia MCP
MCP server for Kasia encrypted peer-to-peer messaging on the Kaspa blockDAG.
About Kasia
Kasia is an encrypted messaging protocol built on Kaspa. Messages are stored on-chain as transaction payloads, encrypted with ChaCha20-Poly1305 using ECDH key exchange on secp256k1. All cryptography happens client-side — the protocol is fully trustless.
Key Properties:
- End-to-end encrypted — ChaCha20-Poly1305 AEAD with ephemeral keys
- On-chain — messages are Kaspa transaction payloads, immutable once confirmed
- Trustless — no central server, no account registration
- Pseudonymous — conversations are identified by deterministic aliases derived from shared secrets
Installation
npm install
npm run buildConfiguration
Kasia MCP reuses the same wallet configuration as kaspa-mcp:
| Variable | Required | Description |
|----------|----------|-------------|
| KASPA_MNEMONIC | Yes* | BIP39 mnemonic phrase |
| KASPA_PRIVATE_KEY | Yes* | Hex-encoded private key (alternative to mnemonic) |
| KASPA_NETWORK | No | Must be mainnet (Kasia operates on mainnet only) |
| KASPA_ACCOUNT_INDEX | No | BIP44 account index. Defaults to 0 |
| KASIA_INDEXER_URL | No | Custom indexer URL. Defaults to https://indexer.kasia.fyi |
*Either KASPA_MNEMONIC or KASPA_PRIVATE_KEY must be set.
Usage with Claude Code
Add to your .mcp.json:
{
"mcpServers": {
"kasia": {
"command": "node",
"args": ["/path/to/kasia-mcp/dist/index.js"],
"env": {
"KASPA_MNEMONIC": "your mnemonic phrase here",
"KASPA_NETWORK": "mainnet"
}
}
}
}Important: Both kaspa-mcp and kasia-mcp must be configured. Kasia generates encrypted payloads, but relies on kaspa-mcp's send_kaspa tool to broadcast them.
Tools
Write Tools
kasia_send_handshake
Start an encrypted conversation with a Kaspa address.
Parameters:
address: Recipient Kaspa address
Returns: Transaction payload to broadcast via send_kaspa.
kasia_accept_handshake
Accept an incoming handshake request.
Parameters:
address: Address of the person who sent the handshake
Returns: Transaction payload to broadcast via send_kaspa.
kasia_send_message
Send an encrypted message in an active conversation.
Parameters:
address: Contact's Kaspa addressmessage: Plaintext message to encrypt and send
Returns: Transaction payload to broadcast via send_kaspa.
kasia_write_self_stash
Store encrypted data on-chain for yourself.
Parameters:
data: Data to encrypt and storescope: Category for the stash entry (e.g.,"notes","saved_handshake")
Returns: Transaction payload to broadcast via send_kaspa.
Read Tools
kasia_get_conversations
List all conversations with their status.
Returns: Array of conversations with status (pending_outgoing, pending_incoming, active), aliases, and last activity timestamp.
kasia_get_requests
List pending incoming handshake requests that need to be accepted.
Returns: Array of pending requests with sender address and transaction details.
kasia_get_messages
Read decrypted messages in a conversation.
Parameters:
address: Contact's Kaspa address
Returns: Array of decrypted messages sorted by timestamp, with from, fromMe, message, timestamp, and confirmed fields.
kasia_read_self_stash
Read your encrypted self-stash entries by scope.
Parameters:
scope: Category to read
Returns: Array of decrypted stash entries.
Protocol
Conversation Flow
- Handshake — Alice sends a handshake to Bob's address containing an ECDH key exchange payload
- Accept — Bob accepts by sending a response handshake back
- Message — Either party can now send encrypted messages
Payload Encoding
| Type | On-chain format | Encoding |
|------|----------------|----------|
| Handshake | ciph_msg:1:handshake:<encrypted_hex> | Fully hex-encoded |
| Message | ciph_msg:1:comm:<alias>:<base64_data> | UTF-8 then hex-encoded |
| Self-stash | ciph_msg:1:self_stash:<scope>:<encrypted_hex> | Fully hex-encoded |
Alias Derivation
Conversation aliases are 12-character hex strings (6 bytes) derived via ECDH + HKDF-SHA256 with asymmetric context pubkeys. Each party derives a unique alias pair — myAlias and theirAlias — ensuring both sides can identify message direction.
Architecture
┌─────────────┐ payload ┌─────────────┐ broadcast ┌────────────┐
│ kasia-mcp │ ───────────→ │ kaspa-mcp │ ─────────────→ │ Kaspa │
│ (encrypt) │ │ (send_kaspa)│ │ Network │
└─────────────┘ └─────────────┘ └─────┬──────┘
↑ │
│ HTTP GET │ indexes
│ ↓
└──────────────────────────────── ┌──────────────────────────┐
│ Kasia Indexer │
│ indexer.kasia.fyi │
└──────────────────────────┘- Write path: kasia-mcp generates encrypted payloads → kaspa-mcp broadcasts as transaction payloads
- Read path: kasia-mcp queries the Kasia indexer HTTP API → decrypts locally
Security
- All encryption/decryption happens locally — private keys never leave the process
- Messages use ephemeral ECDH keys — forward secrecy per message
- ChaCha20-Poly1305 AEAD provides authenticated encryption
- Error messages are sanitized to prevent secret leakage
Testing
npm test # Run tests
npm run test:coverage # Run with coverageDependencies
- kaspa-mcp — Wallet management and transaction broadcasting
- @modelcontextprotocol/sdk — MCP server framework
License
ISC
