The Problem
Developers need a language‑agnostic way to drive Cursor agents without pulling in the full TypeScript or Python SDKs. The bridge protocol (sdk.v1 protobuf) offers a thin, local gRPC‑Web server that exposes the full SDK surface, but creating an adapter requires a concrete reference implementation and clear wiring.
What This Does
The repository publishes the stable protobuf contract under proto/sdk/v1/ and a minimal Python adapter in examples/python-adapter/. The adapter spawns the bridge binary (fetch-bridge.sh) and talks to it via the generated _transport module, which issues HTTP‑based RPCs (unary, server_stream). Core logic lives in the cursor_adapter package:
__init__.pyexposesprompt– the public entry for scripts._client.py,_agent.py,_run.pyimplement high‑level client, agent, and streaming‑run objects._transport.pyhandles low‑level HTTP calls (_post,unary)._bridge.pystarts the bridge process (start) and monitors its readiness.
Documentation in docs/ explains the protocol, services, error model, and a curl‑based smoke test.
How It Is Wired
Execution begins at examples/python-adapter/demo.py:34 in the main function. The call chain is:
main→version(callsunary→_post) – performs a network request to the bridge (urllib.request.Request).main→prompt(fromcursor_adapter/__init__.py) – constructs aClient(_client.py).Client.__init__creates a_transport._postsession and stores bridge endpoint info.Client→start(_bridge.py) – runsfetch-bridge.shviasubprocess.Popen, launching the local bridge binary (external command).startcalls_await_ready_linethenscan, both of which invokeTransportErrorhandling paths (4 callers).- Streaming runs use
Client._run(_run.py) which iterates overserver_stream→_transport.server_stream→_read_exact→TransportErroron read failures.
The internal call graph shows 89 intra‑repo edges; the most widely used symbols are unary, TransportError, and BridgeProcessError. The hub modules (_client.py, _agent.py, _run.py) form a circular import cycle (3 files), increasing the risk of refactor breakage because any change propagates through the cycle.
External effects are limited to:
- One subprocess launch (
fetch-bridge.sh) from_bridge.start. - One outbound HTTP request from
_transport.unary/_post.
No file currently touches a database or filesystem beyond spawning the bridge.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/sdk-bridge.git
cd sdk-bridge
# Install the Python example adapter dependencies
pip install -r examples/python-adapter/requirements.txt
# (or use a PEP‑517 build: pip install .[example] if a pyproject extra existed)
# Verify the bridge binary is present (download from the latest release)
# e.g., curl -L -o cursor-sdk-bridge.tar.gz \
# https://github.com/cursor/sdk-bridge/releases/latest/download/cursor-sdk-bridge-standalone-linux-x64.tar.gz
# tar -xzf cursor-sdk-bridge.tar.gz && chmod +x cursor-sdk-bridge
# Run the demo script (spawns the bridge, prints version, runs a simple prompt)
python examples/python-adapter/demo.py
The demo prints the bridge version, then calls prompt which uses the Client API to talk to the bridge. Adjust fetch-bridge.sh if you place the binary elsewhere.
Real‑World Use
A microservice written in Go could embed the same binary, generate Go stubs from proto/sdk/v1/, and use the same sdk.v1 contract to drive agents. The Python adapter serves as a reference for spawning the bridge, handling RPC transport, and translating errors—mirroring the pattern any new language adapter would follow.
Code Health & Issues
- Measured findings (static analysis)
- HIGH – Import cycle in
examples/python-adapter/cursor_adapter/_client.py,_agent.py,_run.py. Break the cycle by extracting shared types or deferring imports. - MEDIUM – Deep nesting (max indent 6) in
_transport.pyanddemo.py. Refactor with early returns or helper functions.
- Repository hygiene
- HIGH – Unpinned GitHub Action (
.github/workflows/proto-check.ymlusesbufbuild/buf-setup-action@v1). Pin to a commit SHA to avoid supply‑chain risk. - LOW – Missing job timeout in the same workflow; add
timeout-minutesto prevent overlapping runs. - No lockfile for Python dependencies (
pyproject.toml/requirements.txt), making reproducible builds non‑deterministic. - Tests exist (
tests/folder) but only one file; coverage may be insufficient for production use.
The Bottom Line
The repo supplies a solid, version‑controlled protobuf contract and a working Python adapter that clearly demonstrates how to spawn and communicate with the Cursor bridge. However, the import cycle and deep nesting hinder maintainability, and CI configuration lacks pinning and timeouts. It is suitable as a reference implementation for building adapters in other languages, provided the consumer addresses the noted structural and CI hygiene concerns.