Skip to main content
Glama
udah1

cursor-chat-bridge

πŸŒ‰ cursor-chat-bridge (Telegram, Discord, GitHub)

Drive the Cursor agent from your phone β€” over Telegram, Discord, or GitHub.

Say "start remote chat mode" (in any language) and Cursor posts a summary + question to a per-conversation thread at the end of every turn, waits for your reply, and auto-continues β€” looping until you stop it. Step away from the keyboard; keep shipping from your phone.

npm version GitHub stars license Made for Cursor

npm downloads node TypeScript CI Glama MCP server


Table of contents


Related MCP server: Cloud Agent MCP Server

Why

You kick off a task in Cursor, then need to leave your desk. Normally the agent stalls the moment it needs a decision. cursor-chat-bridge turns any chat app into a remote control: the agent reports back and asks its questions in a thread you can answer from your phone, and it resumes on its own the instant you reply β€” no laptop required.

  • A thread per conversation. Every Cursor chat maps to its own issue / channel / topic β€” even multiple chats in the same workspace stay separate.

  • Hands-free loop. Replies are re-injected automatically; you don't touch Cursor to continue.

  • Pluggable channels. Telegram, Discord, and GitHub Issues today β€” add your own in ~100 lines.

  • Safe by default. Remote replies are treated as untrusted; destructive actions require an explicit confirmation sent back through the thread.

  • Proxy-friendly. GitHub and Discord tunnel through TLS-intercepting corporate proxies.

Features

Capability

What it does

Phone-first

Answer the agent from the GitHub / Discord / Telegram mobile app, with native push.

Auto-resume

A stop hook waits for your reply and re-injects it as a followup_message.

Per-session isolation

Keyed by Cursor's conversation_id; no cross-talk between chats.

Long, cheap waits

One ~60-min blocking window per re-arm β‡’ minimal paid turns while idle.

Off when you type

A beforeSubmitPrompt hook disables the loop the moment you type in Cursor (set stopRemoteChatOnLocalMessage: false to keep it on).

Token-authed local API

The daemon's control API is loopback-only and token-guarded.

Optional ntfy push

Get a phone alert even on GitHub (which never notifies you of your own posts).

Image attachments

Send a photo from your phone; it's saved locally and the agent opens it with its Read tool.

Voice β†’ text

Optional speech-to-text (OpenAI or local): a voice note reaches the agent as transcribed text.

Adapter SDK

Implement one TransportAdapter interface to support any channel.

Update-aware

On activation it checks npm and offers to update when a newer release is out.

Channels at a glance

Adapter

Status

Model

Mobile push

Telegram (default)

βœ… code complete, unit-tested

A forum topic per session via a bot

βœ… native

Discord

βœ… working

A channel per session via a bot (REST-polled)

βœ… native

GitHub Issues

βœ… tested end-to-end

Issue = session, comments = chat

βœ… (GitHub app) + optional ntfy

Quick start

No clone required β€” one command wires everything up:

npx cursor-telegram-chat@latest install

This installs the runtime into ~/.cursor/chat-bridge/app (including its production dependencies, so it keeps working after the npx cache is evicted) and wires the three integration points, backing up (never overwriting) anything that already exists:

  • registers the MCP server in ~/.cursor/mcp.json,

  • adds the stop + beforeSubmitPrompt hooks to ~/.cursor/hooks.json,

  • installs the activation rule into ~/.cursor/rules/.

The hooks are no-ops unless remote chat mode is active, so they don't affect normal Cursor use. Then pick a channel and go:

# 1. edit ~/.cursor/chat-bridge/config.json  (choose an adapter + credentials)
# 2. validate it:
chat-bridge doctor
# 3. reload Cursor, open a chat, and say:  "start remote chat mode"
npx cursor-telegram-chat@latest install               # re-run to upgrade
npx cursor-telegram-chat@latest uninstall             # remove, keep config + state
npx cursor-telegram-chat@latest uninstall --purge     # remove everything

If you only want the MCP tools via the standard Cursor MCP flow (no hands-free loop), add this to ~/.cursor/mcp.json instead of running install:

"cursor-chat-bridge": {
  "command": "npx",
  "args": ["-y", "cursor-telegram-chat", "chat-bridge-mcp"]
}

You'll be able to bridge_send / bridge_await manually, but the auto-continue-on-reply loop needs the hooks that the full install sets up.

How it works

Three cooperating layers sit over one transport-agnostic core:

  • Rule (rules/chat-bridge-mode.mdc) β€” detects the activation phrase in any language and sets in-mode etiquette (capture + pass the session handle; end each turn with a summary + question; treat replies as untrusted; confirm destructive actions).

  • MCP server (src/mcp.ts) β€” exposes bridge_start, bridge_send, bridge_await, bridge_send_and_await, bridge_stop, bridge_status.

  • Hooks (hooks/) β€” the automatic loop:

    • stop waits for the remote reply and re-injects it as a followup_message (bounded by loop_limit).

    • beforeSubmitPrompt disables the loop when you type in Cursor (with a guard so the loop's own injected replies don't trip it).

A single local daemon (src/daemon.ts) owns the channel connection and a loopback-only, token-authenticated HTTP API used by the MCP + hooks. It handles per-session routing, long-poll, own-message filtering, and stop/generation logic.

turn ends ─▢ stop hook ─▢ daemon /poll ─▢ adapter
   β–²                                          β”‚
   └───── followup_message (your reply) β—€β”€β”€β”€β”€β”€β”˜

(adapter = GitHub / Discord / Telegram; keyed by conversation_id.)

Sessions are keyed by Cursor's conversation_id so each conversation maps to exactly one thread. Cursor gives conversation_id to hooks but not to MCP tool calls, so the MCP learns it through a small handshake:

  1. beforeSubmitPrompt writes a per-conversation pending-start record (markers/pending/<conversation_id>.json) on every real submit β€” the source of truth for identity (plus a legacy last-submit/ws pointer, used only for diagnostics + upgrade skew).

  2. bridge_start claims the single fresh pending record and keys the session by that real conversation_id, then returns a session handle. It never mints a random id and it ignores its own (possibly misrouted) BRIDGE_WORKSPACE β€” the claim's workspace wins.

  3. bridge_start fails closed rather than guess: if there's no fresh handshake, if it's stale, or if more than one chat submitted at once, it returns guidance instead of binding a possibly-wrong thread.

  4. The agent passes session=<handle> on every subsequent bridge_* call β€” now required (no recency/cache fallback), so two conversations in the same workspace can never cross threads.

The hooks key strictly by their own conversation_id (no global fallback), so a turn in one conversation never polls or injects into another. Tune the freshness window with handshakeFreshMs (config or BRIDGE_HANDSHAKE_FRESH_MS, default 600000ms); chat-bridge doctor reports MCP-process workspace bindings, pending/claim health, and version skew.

The hands-free wait (default 60 min) comes from the stop hook's re-arm loop, not from bridge_await (which only polls ~50s per call). Cursor kills a stop hook after a short, undocumented ceiling unless ~/.cursor/hooks.json sets a large timeout β€” the installer sets timeout: 3660. If your session stops after a couple of minutes:

  1. Using the MCP-only (lite) setup? It has no hooks, so there's no auto-resume. Run the full npx cursor-telegram-chat@latest install.

  2. Fully quit and reopen Cursor after installing β€” a reload doesn't always reload hooks.json.

  3. Confirm ~/.cursor/hooks.json has a stop hook with timeout: 3660 (re-running the latest install fixes an older one).

  4. Still killed early on your Cursor build? Shrink each wait window so it re-arms sooner: set "stopWindowMin": 5 in ~/.cursor/chat-bridge/config.json (the 60-min total is stopBudgetMin).

Image attachments

Send a photo (or an image file) in the chat thread and the agent can see it:

  1. The adapter captures the attachment on the message (Discord attachments, Telegram photo / image document).

  2. The daemon downloads the bytes to ~/.cursor/chat-bridge/media/<session>/ and appends a note to the message text with the local path.

  3. The agent opens that path with its Read tool β€” so the image reaches the model as vision input.

Behind a corporate TLS proxy: Discord's cdn.discordapp.com is often blocked while media.discordapp.net is allowed. The Discord adapter automatically rewrites attachment URLs to the media host, so downloads work on such networks.

Voice messages (speech-to-text)

Send a voice note (Telegram) or an audio attachment (Discord) and the agent receives a text transcription as if you'd typed it β€” off by default. Enable it under stt in the config:

"stt": {
  "enabled": true,
  "provider": "openai",     // "openai" (OpenAI-compatible via baseUrl) or "local"
  "tryLocalSttFirst": false,// true = force the local transcriber even if a cloud provider is set
  "apiKeyCommand": "…",     // or "apiKey", or env BRIDGE_STT_API_KEY
  "language": "auto",       // auto-detect, or force "he" / "en"
  "keepAudio": true         // false = delete the audio after transcribing
}
  • local provider (offline, recommended for sensitive audio): set localBin/localArgs to a CLI that prints the transcript to stdout (e.g. whisper.cpp). The configured provider is always respected β€” the bridge never silently falls back to local. To force the local transcriber even when a cloud provider is set, use "tryLocalSttFirst": true (or BRIDGE_STT_TRY_LOCAL_FIRST=1).

  • Transcription runs asynchronously in the daemon (never blocks the poll window); the transcript is delivered on the next reply cycle. See docs/stt-plan.md for the full design.

Read receipts (acknowledgments)

Without this, sending a message from your phone is silent until the agent finishes a whole turn β€” you can't tell whether it arrived at all. Turn it on and the daemon replies the moment a message lands, before any slow work (attachment downloads, transcription). Off by default:

"ack": {
  "enabled": true,
  "language": "auto",                     // "auto" matches you; force with "en" or "he"
  "adapters": ["discord", "telegram"],    // bot-identity channels only (see below)
  "echoTranscript": true,                 // repeat back what a voice note said
  "maxTranscriptChars": 200
}

What you get, per message kind:

You send

The bridge replies

text

Got it, on it…

an image

Got the image, taking a look…

a voice note

Got your voice message, transcribing… then Got your request: "…" once transcribed

stop

Remote chat session stopped.

The ack comes from the daemon, not the agent β€” the agent doesn't even see your message until its next turn begins, so an agent-authored ack would cost an LLM turn and arrive late.

On "auto" the reply matches the language you wrote in: Hebrew text gets a Hebrew reply, and for a voice note the transcriber's own detected language decides. Messages with nothing to go on (an uncaptioned image, a bare stop) reuse the last language you used in that session, defaulting to English.

Timing: the daemon only reads the channel while a poll is in flight β€” that is, while the agent is awaiting a reply or the stop hook is waiting. Messages sent while the agent is mid-turn aren't seen (and so aren't acked) until it finishes. They're never lost, just delayed.

Why not GitHub: there the agent comments under your own account, so an ack would read as you replying to yourself. You can still opt in by adding "github" to adapters.

Configuration

~/.cursor/chat-bridge/config.json (edits to this file are picked up automatically on the next poll β€” no daemon restart needed; only mcp.json env changes and adapter credentials need a restart):

{
  "activeAdapter": "telegram",
  "pollIntervalMs": 10000,   // check for replies every N ms (lower = snappier, more API calls)
  "minPollIntervalMs": 2000, // floor for the above; lower it if you set pollIntervalMs < 10000
  "stopBudgetMin": 60,       // wait budget (mins); resets on every reply
  "stopWindowMin": 60,       // mins per window (keep < hooks.json timeout)
  "caCertPath": "",          // corporate CA bundle (PEM) if behind a TLS proxy
  "requireConfirmForDestructive": true,
  "stopRemoteChatOnLocalMessage": true, // typing in Cursor turns remote mode off (set false to keep it on)
  "adapters": {
    "github": {
      "owner": "you",
      "repo": "cursor-bridge-inbox",
      "tokenCommand": "gh auth token --user you"
    },
    "discord":  { "botToken": "", "channelId": "", "allowedUserIds": [] },
    "telegram": { "botToken": "", "chatId": "", "allowedUserIds": [] }
  },
  "ack": { "enabled": false, "language": "auto" } // read receipts; see above
}

caCertPath is usually empty β€” leave it unless things fail. Some corporate networks intercept HTTPS with their own root cert that Node doesn't trust, so requests fail with TypeError: fetch failed while curl works. If you hit that, point caCertPath (or BRIDGE_CA_CERT) at your machine's CA bundle (PEM); doctor, the daemon, and the update check all honor it.

ntfy push is off by default and isn't part of this file β€” enable it only via BRIDGE_NTFY_* env vars (see below).

Environment overrides

Set these in the env block of the cursor-chat-bridge entry in ~/.cursor/mcp.json (or the shell) to override config.json without editing it. All namespaced BRIDGE_*. A change needs a daemon restart (chat-bridge shutdown) to affect a running daemon.

Env var

Overrides

Example

BRIDGE_PLATFORM

activeAdapter

github | telegram | discord

BRIDGE_POLL_INTERVAL

poll interval (seconds)

30

BRIDGE_STOP_BUDGET_MIN

wait budget, mins; resets on reply&nbsp;ΒΉ

60

BRIDGE_STOP_WINDOW_MIN

mins per blocking window&nbsp;Β²

60

BRIDGE_CA_CERT

caCertPath

/path/to/ca.pem

BRIDGE_GITHUB_REPO

github owner/repo

you/inbox

BRIDGE_GITHUB_TOKEN

github token

gho_…

BRIDGE_TELEGRAM_BOT_TOKEN

telegram bot token

β€”

BRIDGE_TELEGRAM_CHAT_ID

telegram forum group id

β€”

BRIDGE_TELEGRAM_ALLOWED_USER_IDS

whitelist (csv)

123,456

BRIDGE_DISCORD_BOT_TOKEN

discord bot token

β€”

BRIDGE_DISCORD_CHANNEL_ID

discord channel id&nbsp;Β³

β€”

BRIDGE_DISCORD_ALLOWED_USER_IDS

whitelist (csv)

123,456

BRIDGE_WORKSPACE

per-window session key

${workspaceFolder}

BRIDGE_NTFY_TOPIC

enable ntfy + set topic

cursor-bridge-…

BRIDGE_NTFY_PRIORITY

push priority 0–5 (0 = off)

2

BRIDGE_NTFY_SERVER

ntfy server base URL

https://ntfy.sh

ΒΉ Also stopBudgetMin in config.json β€” the reliable knob, since the hook doesn't inherit the MCP entry's env. Β² Also stopWindowMin in config.json. Keep below the stop hook timeout in ~/.cursor/hooks.json. Β³ Any existing text channel in your server; used to locate the server + category β€” a fresh channel is created per session alongside it (For example #General).

Per-conversation platform can also be chosen at runtime: say "start remote chat in Telegram" and the agent passes bridge_start(adapter: "telegram") for that conversation only.

The wait loop (stop hook)

While remote mode is active, the stop hook blocks at the end of each turn waiting for your reply. Two knobs control it:

  • stopWindowMin (default 60) β€” how long a single hook invocation blocks before it returns a silent keep-alive and re-arms. Cursor caps stop-hook runtime at the timeout in ~/.cursor/hooks.json (default 3660s / 61 min); probing showed no hidden cap below that, so one ~60-min window means just one paid keep-alive turn per hour while you're away.

  • stopBudgetMin (default 60) β€” the total time to keep waiting across re-arms. It resets on every reply, so it's really "keep waiting up to N minutes since your last message."

The loop ends when you reply, type in Cursor, send stop in the thread, or call bridge_stop.

Push notifications (ntfy)

GitHub never notifies you about your own activity β€” and the agent posts as you (self-mentions and self-assignment don't notify either). So to get a phone alert on the GitHub channel without a second account, cursor-chat-bridge can fire an out-of-band push via ntfy on every summary. It's free, account-less, open-source, self-hostable, and deep-links to the issue.

It's off by default. Enable it via env on the MCP entry:

  1. Install the ntfy app (iOS/Android) or use the web app.

  2. Pick a long, unguessable topic (topics are public-by-obscurity) and subscribe to it.

  3. Set BRIDGE_NTFY_TOPIC=cursor-bridge-<random> in the env block of the cursor-chat-bridge entry in ~/.cursor/mcp.json.

BRIDGE_NTFY_PRIORITY is the on/off dial: 0 = off (default), 1=min … 5=max. A push is sent only when priority β‰₯ 1 and a topic is set. Pushes are skipped for Telegram and Discord, which already notify natively.

Per-platform setup

  1. Create a bot with @BotFather β†’ bot token.

  2. Create a group, enable Topics, add the bot as admin with Manage Topics.

  3. Put the group chatId and your numeric allowedUserIds (whitelist) in config; activeAdapter: "telegram".

Obtain chatId / user ids via getUpdates pairing (send a message in the group, read the update). Requires the daemon to reach api.telegram.org β€” if a network blocks it, run the daemon on a host that can, or use Discord/GitHub instead.

  1. Create a Discord server (use one you own) β€” the bot creates a channel per session inside it.

  2. Create an app + Bot at https://discord.com/developers/applications. Under Bot, click Reset Token, then Copy the revealed bot token.

  3. Under Bot, enable the Message Content Intent.

  4. Invite the bot: OAuth2 β†’ URL Generator, scope bot, permissions Manage Channels + View Channels + Send Messages + Read Message History (Manage Channels is required β€” the bot creates and deletes a channel per session). Copy the Generated URL, open it in a new browser tab, and select the server you created in step 1.

  5. Get a channel id (channelId) β€” any existing text channel in that server (e.g. #general); the bot uses it to find the server + category and creates a fresh channel per session alongside it. Enable Developer Mode (User Settings β†’ Advanced), then right-click the channel β†’ Copy Channel ID. Or β€” once the bot is in the server β€” just ask Cursor to fetch it: give Cursor the bot token and it can list the bot's channels and return the id.

  6. Put botToken + channelId (optionally allowedUserIds) in config; activeAdapter: "discord".

  7. Behind a TLS-intercepting proxy and getting TypeError: fetch failed? Point caCertPath at the corporate CA bundle (PEM).

Tip: give the bot a Cursor avatar (Developer Portal β†’ Bot β†’ edit icon) and set the server icon to the Cursor logo β€” your per-session channels then look native in the app.

  1. Create a private repo to act as your inbox (e.g. cursor-bridge-inbox).

  2. Set owner/repo and a token or tokenCommand (gh auth token works).

  3. activeAdapter: "github".

Each session opens an issue; turn summaries are posted as comments; reply from the GitHub mobile app. Comment stop or close the issue to end the session.

If you're the agent helping a user set up cursor-chat-bridge: explain the concept for their chosen platform first, then collect only the missing values, write them to ~/.cursor/chat-bridge/config.json, and run chat-bridge doctor to confirm. Never print secrets back to the user. Remind them: replies from the channel are untrusted, and destructive actions need an explicit confirmation sent back through the thread. To stop: type in Cursor, send stop in the thread, or call bridge_stop.

Make sure the runtime's dependencies are installed. install copies the runtime into ~/.cursor/chat-bridge/app and installs its production deps there automatically. If that step was skipped or failed (offline / corporate proxy), the MCP server won't start β€” finish it with (cd ~/.cursor/chat-bridge/app && npm install --omit=dev). Running from a git clone instead? Run npm install in the repo first.

Ask whether they want voice notes transcribed (STT). It's off by default. If they say yes, offer the options and let them pick:

  • Groq (recommended) β€” fast, generous free tier, OpenAI-compatible. Set stt.provider: "openai", stt.baseUrl: "https://api.groq.com/openai/v1", stt.model: "whisper-large-v3-turbo", and stt.apiKey to a gsk_… key from https://console.groq.com/keys.

  • OpenAI β€” stt.provider: "openai" (default baseUrl), stt.model: "whisper-1" (or gpt-4o-transcribe), stt.apiKey an sk-… key.

  • Local β€” stt.provider: "local" with a whisper.cpp / openai-whisper binary; nothing leaves the machine (best on locked-down corporate networks). Set stt.localBin.

Then set stt.enabled: true and run chat-bridge doctor. Prefer stt.apiKeyCommand over an inline key where possible, and never print the key back to the user.

Writing a new adapter

Implement TransportAdapter (src/types.ts) and register it in src/adapters/index.ts:

interface TransportAdapter {
  capabilities: { globalIngest: boolean; separateBotIdentity: boolean };
  init(): Promise<void>;
  ensureThread(sessionId: string, title: string, meta?: object): Promise<ThreadRef>;
  send(thread: ThreadRef, text: string): Promise<{ messageId: string }>;
  // pull adapters (GitHub / Discord):
  poll?(thread: ThreadRef, cursor?: string): Promise<PollResult>;
  // push / global adapters (Telegram):
  startIngest?(router: Router): Promise<() => void>;
  stop?(thread: ThreadRef): Promise<void>;
}

Member

Required

Purpose

capabilities

βœ…

globalIngest: one stream for all sessions (Telegram) vs per-thread polling. separateBotIdentity: posts appear as a bot, not you.

init()

βœ…

Validate credentials + connectivity.

ensureThread()

βœ…

Create/lookup the per-session thread/channel; returns a ThreadRef.

send()

βœ…

Post a message (handle the platform's length limits / chunking).

poll()

pull adapters

Return new messages after cursor, filtered to allowed users.

startIngest()

push adapters

Start a single global stream and route updates; return a stop fn.

stop()

optional

Clean up (e.g. Discord deletes its per-session channel).

Security

  • The loopback control API is token-authenticated β€” only local processes with the token (the MCP + hooks) can drive the daemon.

  • Inbound messages are filtered by an allowedUserIds whitelist (Telegram/Discord).

  • Every remote reply is wrapped and marked untrusted; the rule forbids destructive actions without an explicit confirmation sent back through the thread.

  • Tokens live in ~/.cursor/chat-bridge/config.json (chmod 600) and are never committed. Prefer tokenCommand over a stored token where possible.

Permissions β€” what the daemon needs (and why scanners flag it)

Driving an agent from a chat app inherently needs some powerful capabilities. This package uses:

  • Child processes β€” to spawn the daemon, run your tokenCommand (e.g. gh auth token), the local whisper binary (only if you choose local STT), and npm install inside the installer.

  • Network access β€” a loopback-only control server plus outbound calls to your chosen channel (Telegram/Discord/GitHub), speech-to-text upload (if enabled), and an npm update check.

  • Filesystem access β€” read/write ~/.cursor/chat-bridge/ for config, media, and logs.

Because of these, supply-chain scanners (Socket, Snyk, etc.) show a lower Supply Chain Security score than a pure-logic library β€” even though there are no known vulnerabilities. That score reflects capability + package age (this project is new, single-maintainer), not a detected exploit. For transparency: there is no postinstall/install script β€” the only lifecycle script is prepublishOnly (a build that runs on the publisher's machine, never on your install). Everything network/filesystem/process happens only when you run the daemon, and the control API is loopback-only and token-guarded. The source is MIT and auditable in this repo.

Verification status

Verified end-to-end on-machine (no Cursor restart needed):

  • GitHub adapter β€” create issue, send, poll, own-message filtering, stop keyword, close-detection.

  • Daemon β€” token auth, long-poll, stop/generation, persistence.

  • MCP server β€” all tools over a real stdio JSON-RPC handshake.

  • Hooks β€” stop-loop followup_message injection, before-submit off-switch + injection guard, instant no-op when inactive.

  • Per-conversation routing (node scripts/e2e-conv.mjs) β€” distinct conversations open distinct issues; two conversations in the same workspace stay separate; re-activating a stopped session opens a fresh thread; unconfigured channels return onboarding guidance.

  • Unit tests β€” npm test (routing, store semantics, message filtering).

Contributing

Issues and PRs welcome. Local dev:

npm install
npm run build        # tsc β†’ dist/
npm run typecheck
npm test             # node --test
npm run dev:daemon   # run the daemon from source (tsx)

New channels are the easiest contribution β€” implement one TransportAdapter (see above).

License

MIT

Available Tools

6 tools
bridge_awaitWait for the user's replyA

Blocks on this conversation's chat thread for a single long-poll window and returns JSON with status 'message' plus the reply text, 'timeout', or 'stopped'. Use it when you already posted with bridge_send and only need the answer; to post and wait together, prefer bridge_send_and_await. Replies are consumed as they are delivered, so each message comes back exactly once and a later call will not see it again. A 'timeout' is normal rather than an error β€” the window elapsed with no reply, and you keep waiting by calling again. 'stopped' means the user ended remote chat mode, so stop calling bridge_* tools until a new bridge_start.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionYesSession handle returned by bridge_start for THIS conversation. Routes the call to the right chat thread and keeps concurrent conversations β€” even two in the same workspace β€” from crossing over.
maxBlockMsNoHow long to wait for a reply before giving up and returning status 'timeout', in milliseconds. Defaults to 50000 and is capped at 55000 to stay inside the MCP call timeout β€” wait longer by calling again, not by raising this.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds significant behavioral context beyond annotations: replies are consumed exactly once, a 'timeout' is normal and not an error, and 'stopped' indicates the user ended remote chat mode. These details help the agent anticipate non-obvious behaviors.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each earning its place: the first states the core function, the second gives usage guidance, the third explains consumption behavior, and the fourth clarifies status semantics. Front-loaded with the primary purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description thoroughly explains return values and all possible statuses, including edge cases (timeout is normal, stopped means stop calling). Covers usage prerequisites and post-conditions, making it complete for an agent to operate correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully documents both parameters with detailed descriptions (session routing/concurrency, maxBlockMs default/cap). The description does not add additional parameter-level semantics beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Blocks') and resource ('this conversation's chat thread'), and specifies the exact return statuses ('message', 'timeout', 'stopped'). It clearly distinguishes itself from the sibling bridge_send_and_await by stating when each should be used.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool ('when you already posted with bridge_send and only need the answer'), names the alternative ('prefer bridge_send_and_await'), and gives post-condition guidance ('stop calling bridge_* tools until a new bridge_start' after 'stopped').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bridge_sendPost a message to the chat threadA

Posts one message to this conversation's chat thread and returns immediately without waiting for a reply. Use it for a progress note or a closing remark that needs no answer; when you need the user to respond, use bridge_send_and_await instead so the post and the wait are one call. Each call appends a new message and never edits or replaces an earlier one, so a retry after a failure leaves a duplicate in the thread.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoMessage body to post, as plain text β€” typically the end-of-turn summary plus the question you need answered. Keep credentials and secrets out of it: whoever can read the chat thread can read this.
messageNoAlias for `text`; ignored when `text` is present. Message body to post, as plain text β€” typically the end-of-turn summary plus the question you need answered. Keep credentials and secrets out of it: whoever can read the chat thread can read this.
sessionYesSession handle returned by bridge_start for THIS conversation. Routes the call to the right chat thread and keeps concurrent conversations β€” even two in the same workspace β€” from crossing over.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnlyHint=false, openWorldHint=true, idempotentHint=false, destructiveHint=false. The description adds valuable context: 'returns immediately without waiting for a reply,' 'Each call appends a new message and never edits or replaces an earlier one,' and 'a retry after a failure leaves a duplicate in the thread.' This exceeds what annotations convey, clarifying side effects and non-idempotency explicitly. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, all informative. Front-loaded with the core action, then usage guidance, then side-effect warning. No filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Tool is simple (3 params, no output schema). Description covers the action, return behavior, use case, alternative, and side effects (duplicate on retry). Given the sibling tools and annotations, this is complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% because every parameter has a description. The description adds nuance: for `text` it warns 'Keep credentials and secrets out of it: whoever can read the chat thread can read this,' which isn't in the schema. For `session` it explains routing and concurrency safety. It elevates beyond schema basics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states it 'Posts one message to this conversation's chat thread and returns immediately without waiting for a reply,' using a specific verb (posts) and resource (chat thread). It clearly distinguishes from sibling bridge_send_and_await, which waits for a reply.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use: 'for a progress note or a closing remark that needs no answer.' It also gives an alternative: 'when you need the user to respond, use bridge_send_and_await instead.' This is direct when/when-not guidance naming an alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bridge_send_and_awaitPost a message and wait for the replyA

Posts a message to this conversation's chat thread and then blocks for the reply in one round trip β€” the end-of-turn summary-plus-question pattern, and the tool to reach for by default. Equivalent to bridge_send followed by bridge_await; use those separately only when you need to post and wait at different moments. Returns the same envelope as bridge_await: 'message' with the reply, 'timeout', or 'stopped'. The message is posted before the wait begins, so after a 'timeout' the user has already seen it β€” send only what is new rather than repeating the summary, which would post it twice.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoMessage body to post, as plain text β€” typically the end-of-turn summary plus the question you need answered. Keep credentials and secrets out of it: whoever can read the chat thread can read this.
messageNoAlias for `text`; ignored when `text` is present. Message body to post, as plain text β€” typically the end-of-turn summary plus the question you need answered. Keep credentials and secrets out of it: whoever can read the chat thread can read this.
sessionYesSession handle returned by bridge_start for THIS conversation. Routes the call to the right chat thread and keeps concurrent conversations β€” even two in the same workspace β€” from crossing over.
maxBlockMsNoHow long to wait for a reply before giving up and returning status 'timeout', in milliseconds. Defaults to 50000 and is capped at 55000 to stay inside the MCP call timeout β€” wait longer by calling again, not by raising this.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses blocking behavior, the fact that the message is posted before waiting, and the timeout side effect (user already saw the message). It also names the return envelope values. This goes beyond the annotations and adds critical behavioral context, with no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is information-dense yet concise, with every sentence earning its place: action, default status, alternatives, return envelope, and a practical caveat. Well-front-loaded and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (send + wait) and lack of an output schema, the description covers return values, timeout side effects, relationship to sibling tools, and the end-of-turn pattern. It provides enough context for an agent to select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for all four parameters, so the baseline is 3. The description does not add parameter-level details beyond the schema, though it does reinforce the timeout behavior related to maxBlockMs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool posts a message and blocks for the reply in one round trip, using a specific verb and resource. It distinguishes itself from siblings by positioning as the default and explaining equivalence to bridge_send + bridge_await.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly labels this as 'the tool to reach for by default' and advises using bridge_send/bridge_await separately only when posting and waiting at different moments. This provides clear when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bridge_startStart remote chat modeA

Opens a dedicated thread for THIS conversation in the configured chat channel (GitHub issue, Telegram topic, or Discord channel) and returns the session handle that every other bridge_* tool requires. Call it when the user asks β€” in any language β€” to start remote chat, bridge, or Telegram mode. Call it once per conversation: every call without session opens a NEW thread, so re-arm an existing session by passing its handle back instead of starting again. When no channel is configured it returns onboarding instructions rather than failing, so follow them and call again. It identifies the conversation from Cursor's pending handshake and fails closed with guidance when that is ambiguous β€” it will not guess which conversation it belongs to.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoNames the thread β€” a concise (≀6-word) summary of THIS conversation's topic, mirroring how it reads in Cursor's chat list (e.g. "GitHub Actions autopublish"). Falls back to the folder name, which is a poor label when several conversations share a workspace.
adapterNoChat channel to use for this session, overriding the configured default.
sessionNoHandle from a previous bridge_start, to re-arm that existing session instead of opening a second thread. Omit for a brand-new start.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnly=false and openWorld=true, but the description adds crucial behavioral details: every call without session opens a new thread, returns onboarding instructions when no channel is configured, and fails closed on ambiguous conversation identification. These go beyond the annotations without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is 5 sentences, each packed with essential information: main purpose, when to call, threading caution, failure mode, and safety behavior. No fluff; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (3 optional params, no output schema, sibling tools), the description fully covers intent, usage, side effects, failure modes, and integration with other bridge_* tools. It is complete and self-contained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so each parameter is well-documented. The description does not add new parameter meaning beyond the schema; it reiterates session reuse and adapter override, which are already in the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Opens a dedicated thread... and returns the session handle that every other bridge_* tool requires.' This specific verb+resource distinguishes it from sibling tools like bridge_send or bridge_await, making its role clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says when to use: 'Call it when the user asks β€” in any language β€” to start remote chat, bridge, or Telegram mode.' It also provides exclusions: 'Call it once per conversation' and warns against re-starting without session, advising to re-arm instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bridge_statusShow remote chat mode statusA
Read-onlyIdempotent

Reports the bridge's record for THIS conversation as JSON β€” which adapter is in use, the thread it is bound to, and whether the session is still active β€” or a null session once it has ended. Diagnostics only: it posts nothing to the thread and does not consume a pending reply, so unlike bridge_await it is safe to call at any point, including while deciding whether a bridge_start is still needed. It answers from local daemon state without contacting the chat provider, so it confirms what the bridge believes rather than that the provider is reachable.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionYesSession handle returned by bridge_start for THIS conversation. Routes the call to the right chat thread and keeps concurrent conversations β€” even two in the same workspace β€” from crossing over.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond annotations by disclosing that it posts nothing, does not consume a pending reply, and answers from local daemon state without contacting the chat provider. This is valuable behavioral context not captured by readOnlyHint or idempotentHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense yet concise, with three sentences each adding distinct value: output format, safety/diagnostics, and local-state nature. No fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a diagnostic tool with no output schema, the description fully explains the return value (JSON with specific fields, null session), side effects (none), and context (local state, no provider contact). It is complete for the agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already explains the session parameter thoroughly. The description adds no new parameter-level details beyond the schema, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reports the bridge's record for the conversation as JSON, listing specific fields (adapter, thread, session active status). It distinguishes from siblings by explicitly contrasting with bridge_await and noting it is diagnostics-only.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says when to use: 'Diagnostics only' and 'unlike bridge_await it is safe to call at any point, including while deciding whether a bridge_start is still needed.' This provides clear context and an alternative, making it easy to decide between tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bridge_stopEnd remote chat modeA
DestructiveIdempotent

Ends remote chat mode for THIS conversation: the daemon stops polling the thread, any in-flight wait returns 'stopped', and the session handle stops working β€” resuming later needs a fresh bridge_start. The conversation history is left intact; the thread is not deleted and a GitHub issue is not closed, so the record stays readable afterwards. Calling it twice, or on a session that already ended, is harmless. Use it when the user says they are done β€” not in response to a 'timeout' from bridge_await, which only means no reply has arrived yet.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionYesSession handle returned by bridge_start for THIS conversation. Routes the call to the right chat thread and keeps concurrent conversations β€” even two in the same workspace β€” from crossing over.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the annotations by disclosing side effects: the session handle stops working, conversation history remains intact, the thread is not deleted, and double-calling is harmless. It aligns with idempotentHint and refines destructiveHint by clarifying that the session state is destroyed but not the underlying data, so there is no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a compact, well-ordered paragraph that front-loads the primary action, then explains effects, data safety, idempotency, and usage guidelines. Every sentence adds value with no repetition or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple stop tool with one parameter and no output schema, it thoroughly covers behavior, side effects, data preservation, and when not to use it. The only minor gap is that it does not state the return value of bridge_stop itself, though it explains the asynchronous return of bridge_await, leaving the invocation context sufficiently clear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The only parameter 'session' is fully documented in the input schema with a detailed description about routing and isolating conversations. The tool description references 'session handle' but adds no new semantic detail beyond the schema, meeting the baseline for 100% schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with 'Ends remote chat mode for THIS conversation' – a specific verb and resource, clearly distinguishing it from siblings like bridge_start, bridge_send, and bridge_await. It also details concrete effects (daemon stops polling, in-flight waits return 'stopped'), making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance: 'Use it when the user says they are done' and a clear negative case: 'not in response to a timeout from bridge_await'. It also points to bridge_start for resuming, offering a direct alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.1.0
    • First observedbridge_await
    • First observedbridge_send
    • First observedbridge_send_and_await
    • First observedbridge_start
    • First observedbridge_status
    • First observedbridge_stop

TDQS

A4.8/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: start, send, await, send-and-await, stop, and status. The descriptions explicitly cross-reference each other, disambiguating the similar send and await variants.

Naming Consistency5/5

All tools follow the uniform `bridge_` prefix with a lowercase verb or verb phrase (start, send, await, send_and_await, stop, status). The naming pattern is perfectly consistent and predictable.

Tool Count5/5

Six tools is a well-scoped size for a chat bridge, covering start, messaging, waiting, stopping, and status. Each tool earns its place, with no redundant or unnecessary entries.

Completeness5/5

The tool set covers the entire session lifecycle: starting, sending, waiting for replies, combined send-and-wait, stopping, and checking status. There are no dead ends, and the status tool fills diagnostic gaps without side effects.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    F
    maintenance
    Enables remote control of AI coding assistants (Claude Code/Codex) via Telegram, allowing you to manage long-running tasks, send commands, and receive notifications from anywhere. Supports unattended mode with smart polling for up to 7 days and multi-session management.
    8
    30
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to create and manage Cursor Cloud Agents that autonomously work on GitHub repositories, including creating tasks, monitoring progress, and automatically generating pull requests.
    20
    7
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables remote control of Claude Code through Telegram, letting users start or resume sessions, review tool calls with approve/deny buttons, and manage long-running work from a phone.
    53
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/udah1/cursor-chat-bridge'

If you have feedback or need assistance with the MCP directory API, please join our Discord server