LocalSend MCP Skill
Use This Skill When
- The user mentions LocalSend, AirDrop-like transfer, or peer-to-peer file sharing.
- The task asks for an MCP server or tool set around LocalSend.
- Discovery/advertising needs to use NATS or Tailscale before transferring data.
Reality Check (LocalSend in This Repo)
localsend (Flox package) launches a GUI and does not exit for --help.
- Discovery uses UDP multicast
224.0.0.167:53317 (LAN only).
- Transfer runs HTTPS on port
53317; direct IPs are required across subnets.
- For headless automation, prefer a CLI client (e.g.,
jocalsend) or a small protocol wrapper.
Architecture: Advertise -> Negotiate -> Transfer -> Tune
- Advertise capabilities over NATS (or Tailscale if LAN multicast is blocked).
- Negotiate transport and parameters (LAN multicast vs direct IP).
- Transfer via LocalSend protocol/CLI.
- Tune throughput until spectral gap <= 0.25 (>= 75% of target throughput).
MCP Tool Set (Draft)
Discovery / Advertising
localsend_advertise:
- Inputs:
agent_id, device_name, localsend_port, tailscale_ip?, capabilities, spectral_gap_target
localsend_list_peers:
- Inputs:
source = localsend_multicast | nats | tailscale
Session Negotiation
localsend_negotiate:
- Inputs:
peer_id, preferred_transport, max_chunk_bytes, max_parallel
- Output:
session_id, transport, target_ip, port
Transfer
localsend_send:
- Inputs:
session_id, file_path, chunk_bytes, parallelism
localsend_receive:
- Inputs:
session_id, dest_dir, accept
Throughput Tuning
localsend_probe:
- Inputs:
session_id, probe_bytes, probe_parallelism
- Output:
throughput_bps, rtt_ms, loss_rate
localsend_session_status:
- Inputs:
session_id
- Output:
bytes_sent, bytes_received, throughput_bps, spectral_gap
Spectral Gap Heuristic (Practical)
Define:
spectral_gap = 1.0 - (observed_throughput / target_throughput)
Stop tuning when spectral_gap <= 0.25.
Tuning Loop:
- Start
chunk_bytes = 256KB, parallelism = 1
- Increase parallelism to 2, 4, 8 while loss < 1%
- Increase chunk size up to 1MB while RTT stable
- Recompute spectral gap each step
Integration Points in This Repo
- NATS broadcast helpers:
lib/synadia_broadcast.rb
- Tailscale patterns:
lib/tailscale_file_transfer_skill.rb
- MCP server reference:
mcp_unified_server.py
GitHub GraphQL (GH CLI) Reference
Use gh api graphql for contributor snapshots (limit: history(first: 100)):
gh api graphql \
-F owner=localsend \
-F name=localsend \
-F history=100 \
-f query='query($owner:String!,$name:String!,$history:Int!){
repository(owner:$owner,name:$name){
defaultBranchRef{name target{
... on Commit{
history(first:$history){
nodes{author{user{login} name}}
}
}
}}
}
}'
Aggregate top contributors:
gh api graphql -F owner=localsend -F name=localsend -F history=100 -f query='query($owner:String!,$name:String!,$history:Int!){repository(owner:$owner,name:$name){defaultBranchRef{name target{... on Commit{history(first:$history){nodes{author{user{login} name}}}}}}}}' \
| jq -r '.data.repository.defaultBranchRef.target.history.nodes[].author | if .user then .user.login else .name end' \
| sort | uniq -c | sort -nr | head -20
Duck Lake Snapshots (Feedback + Bidirectional Flow)
Persist LocalSend sessions and GitHub snapshots into DuckDB for time travel:
CREATE TABLE IF NOT EXISTS localsend_sessions (
session_id TEXT,
peer_id TEXT,
direction TEXT, -- send|receive
bytes BIGINT,
throughput_bps DOUBLE,
spectral_gap DOUBLE,
created_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS localsend_contributors_snapshot (
snapshot_at TIMESTAMP,
repo TEXT,
contributor TEXT,
commit_count INT
);
Store snapshots per run and query later with existing DuckDB time-travel commands.
Implementation Notes
- Avoid assuming LocalSend has a stable CLI; verify with
jocalsend --help if installed.
- If multicast discovery fails (Tailscale), use NATS to exchange
target_ip + port.
- Keep tool outputs structured; avoid dumping large blobs through MCP.
1---2name: localsend-mcp3description: LocalSend-based P2P transfer with MCP server design for NATS/Tailscale discovery and throughput tuning.4license: UNLICENSED5---67# LocalSend MCP Skill89## Use This Skill When10- The user mentions LocalSend, AirDrop-like transfer, or peer-to-peer file sharing.11- The task asks for an MCP server or tool set around LocalSend.12- Discovery/advertising needs to use NATS or Tailscale before transferring data.1314## Reality Check (LocalSend in This Repo)15- `localsend` (Flox package) launches a GUI and does not exit for `--help`.16- Discovery uses UDP multicast `224.0.0.167:53317` (LAN only).17- Transfer runs HTTPS on port `53317`; direct IPs are required across subnets.18- For headless automation, prefer a CLI client (e.g., `jocalsend`) or a small protocol wrapper.1920## Architecture: Advertise -> Negotiate -> Transfer -> Tune21221. **Advertise** capabilities over NATS (or Tailscale if LAN multicast is blocked).232. **Negotiate** transport and parameters (LAN multicast vs direct IP).243. **Transfer** via LocalSend protocol/CLI.254. **Tune** throughput until spectral gap <= 0.25 (>= 75% of target throughput).2627## MCP Tool Set (Draft)2829**Discovery / Advertising**30- `localsend_advertise`:31 - Inputs: `agent_id`, `device_name`, `localsend_port`, `tailscale_ip?`, `capabilities`, `spectral_gap_target`32- `localsend_list_peers`:33 - Inputs: `source` = `localsend_multicast` | `nats` | `tailscale`3435**Session Negotiation**36- `localsend_negotiate`:37 - Inputs: `peer_id`, `preferred_transport`, `max_chunk_bytes`, `max_parallel`38 - Output: `session_id`, `transport`, `target_ip`, `port`3940**Transfer**41- `localsend_send`:42 - Inputs: `session_id`, `file_path`, `chunk_bytes`, `parallelism`43- `localsend_receive`:44 - Inputs: `session_id`, `dest_dir`, `accept`4546**Throughput Tuning**47- `localsend_probe`:48 - Inputs: `session_id`, `probe_bytes`, `probe_parallelism`49 - Output: `throughput_bps`, `rtt_ms`, `loss_rate`50- `localsend_session_status`:51 - Inputs: `session_id`52 - Output: `bytes_sent`, `bytes_received`, `throughput_bps`, `spectral_gap`5354## Spectral Gap Heuristic (Practical)5556Define:57```58spectral_gap = 1.0 - (observed_throughput / target_throughput)59```60Stop tuning when `spectral_gap <= 0.25`.6162**Tuning Loop**:631. Start `chunk_bytes = 256KB`, `parallelism = 1`642. Increase parallelism to 2, 4, 8 while loss < 1%653. Increase chunk size up to 1MB while RTT stable664. Recompute spectral gap each step6768## Integration Points in This Repo69- NATS broadcast helpers: `lib/synadia_broadcast.rb`70- Tailscale patterns: `lib/tailscale_file_transfer_skill.rb`71- MCP server reference: `mcp_unified_server.py`7273## GitHub GraphQL (GH CLI) Reference7475Use `gh api graphql` for contributor snapshots (limit: `history(first: 100)`):7677```bash78gh api graphql \79 -F owner=localsend \80 -F name=localsend \81 -F history=100 \82 -f query='query($owner:String!,$name:String!,$history:Int!){83 repository(owner:$owner,name:$name){84 defaultBranchRef{name target{85 ... on Commit{86 history(first:$history){87 nodes{author{user{login} name}}88 }89 }90 }}91 }92 }'93```9495Aggregate top contributors:96```bash97gh api graphql -F owner=localsend -F name=localsend -F history=100 -f query='query($owner:String!,$name:String!,$history:Int!){repository(owner:$owner,name:$name){defaultBranchRef{name target{... on Commit{history(first:$history){nodes{author{user{login} name}}}}}}}}' \98 | jq -r '.data.repository.defaultBranchRef.target.history.nodes[].author | if .user then .user.login else .name end' \99 | sort | uniq -c | sort -nr | head -20100```101102## Duck Lake Snapshots (Feedback + Bidirectional Flow)103104Persist LocalSend sessions and GitHub snapshots into DuckDB for time travel:105106```sql107CREATE TABLE IF NOT EXISTS localsend_sessions (108 session_id TEXT,109 peer_id TEXT,110 direction TEXT, -- send|receive111 bytes BIGINT,112 throughput_bps DOUBLE,113 spectral_gap DOUBLE,114 created_at TIMESTAMP115);116117CREATE TABLE IF NOT EXISTS localsend_contributors_snapshot (118 snapshot_at TIMESTAMP,119 repo TEXT,120 contributor TEXT,121 commit_count INT122);123```124125Store snapshots per run and query later with existing DuckDB time-travel commands.126127## Implementation Notes128- Avoid assuming LocalSend has a stable CLI; verify with `jocalsend --help` if installed.129- If multicast discovery fails (Tailscale), use NATS to exchange `target_ip` + `port`.130- Keep tool outputs structured; avoid dumping large blobs through MCP.