MCP server

@socketly/mcp gives a coding agent five tools and these docs as a resource. The tools matter less than what they add up to: an agent that can publish an event, watch the channel, and see the message arrive can check its own work. One that can only write code publishes blind and reports success, which is how generated realtime code ends up quietly wrong.

Install

claude mcp add socketly \
  --env SOCKETLY_SECRET_KEY=sk_app_… \
  --env SOCKETLY_PUBLIC_KEY=pk_app_… \
  -- npx -y @socketly/mcp

Both keys are minted together when you create an app in the dashboard. The secret is shown exactly once.

The secret key can publish to any channel on the app and sign a presence membership claiming to be anybody. That is the right credential for your own app on your own machine — it is the same trust as the dashboard. It is the wrong one to give an agent acting on someone else's behalf.

Tools

ToolReversibleWhat it does
socketly_publishnoPublishes an event to one or more channels, as your server would. Real clients receive it.
socketly_channel_inforead-onlyA channel's kind, and for presence- channels who is currently in it.
socketly_subscriberead-onlyOpens a connection and starts buffering. Returns a handle.
socketly_receiveread-onlyDrains a handle. Long-polls for the first message if you ask it to.
socketly_unsubscribeyesCloses the subscription and its connection.

socketly_publish is annotated as not read-only, so a client can gate it behind confirmation. It is the only one that changes anything.

Watching a channel is a buffer, not a stream

MCP cannot push a message into a model's turn. The specification's only server-to-client mechanism carries four notification types, all of them about lists changing, and none of them reaches the model. So the server holds the socket and buffers what arrives; the agent drains it with a tool call.

  • A subscription closes after 5 minutes without a receive. An expired handle returns an error telling the agent to resubscribe, rather than an empty result that reads exactly like a quiet channel.
  • The buffer holds 256 messages. Past that the oldest are dropped and receive reports how many — a silently truncated buffer is a lie an agent would reason from.
  • An open subscription is a connection, and counts against your app's concurrent connection limit.

Only public- channels can be watched. private- and presence- need a signature from your backend, which is the whole point of them.

The docs are a resource

The server exposes socketly://docs, fetched from llms-full.txt — which this site generates from the same constants its own pages render. So an agent scaffolding Socketly reads the checked source rather than whatever it remembers, and when a pattern here improves, every agent's output improves without anyone republishing the package.

Not yet

Creating apps and rolling keys. Those sit behind a session cookie, and exposing them needs a personal access token the API does not have. They are also a dashboard click, and rare.

An agent as a channel member. Replying in presence-support-4821 as a participant needs a credential scoped to one channel and one identity. A secret key grants far too much for that.