Add Cursor as an MCP client#192
Open
sunishsheth2009 wants to merge 1 commit into
Open
Conversation
Register Databricks managed MCP servers in Cursor's ~/.cursor/mcp.json and
add a `ucode cursor` launcher that authenticates them.
Cursor is MCP-only: cursor-agent runs models on the user's own Cursor account
and exposes no gateway base URL, so ucode configures no models for it (it stays
out of agents.__init__._MODULES). What ucode does is wire Databricks MCP servers
into ~/.cursor/mcp.json via the existing `ucode configure mcp` flow and mint the
OAuth token they authenticate with.
- agents/cursor.py: write_/remove_mcp_server_config merge surgically into the
shared ~/.cursor/mcp.json (preserving the user's own entries), using Cursor's
`Bearer ${env:OAUTH_TOKEN}` header form. launch() sets OAUTH_TOKEN and execs
cursor-agent, mirroring the claude/codex token-at-launch pattern.
- mcp.py: register cursor in MCP_CLIENTS; configure/remove branches; add
MCP_ONLY_CLIENTS so cursor is eligible whenever cursor-agent is installed
(it never lands in available_tools). Revert is handled by the generic
per-client removal loop.
- cli.py: `ucode cursor` launch command.
- Tests + README.
Co-authored-by: Isaac
7e10377 to
a40057e
Compare
rohita5l
approved these changes
Jul 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Cursor as an MCP client in ucode, so
ucode configure mcpcan register Databricks managed MCP servers into~/.cursor/mcp.json, plus aucode cursorlauncher that keeps them authenticated.Cursor is MCP-only:
cursor-agentruns models on the user's own Cursor account and exposes no gateway base URL, so ucode configures no models for it (it stays out ofagents.__init__._MODULES). What ucode does is wire Databricks MCP servers into Cursor's config via the existingucode configure mcpflow and authenticate them with a Databricks OAuth token.Auth: literal token + background refresh
cursor-agentdoes not expand environment variables in~/.cursor/mcp.jsonheader values. Given an unresolved${env:OAUTH_TOKEN}, it sends an empty credential, the server answers 401 with OAuth metadata, and cursor-agent then falls into a dynamic-client-registration flow that Databricks managed MCP does not support (Incompatible auth server: does not support dynamic client registration).So ucode embeds the resolved bearer token literally in the entry's
Authorizationheader. Cursor's mcp.json supports no per-request credential-helper command (the modelapiKeyHelpermechanism Claude/Codex use is unavailable for MCP here), so to keep the token freshucode cursoruses the same background-refresh pattern as the other literal-token agents (Copilot/OpenCode/Gemini): mint a token, rewrite the managed entries, spawncursor-agentas a child, and re-mint + rewrite every ~30 min until it exits.Changes
src/ucode/agents/cursor.py(new):write_/remove_mcp_server_configmerge surgically into the shared~/.cursor/mcp.json(preserving the user's own entries);refresh_mcp_tokensrewrites the ucode-managed entries with a fresh token;launch()refreshes, spawns cursor-agent, and runs a daemon refresh thread.src/ucode/mcp.py: registercursorinMCP_CLIENTS; configure/remove branches;MCP_ONLY_CLIENTSso cursor is eligible whenevercursor-agentis installed (it never lands inavailable_tools); thread the cursor bearer token throughapply_mcp_server_changes/configure_client_mcp_server.src/ucode/cli.py:ucode cursorlaunch command.Verification
Verified end-to-end against a live workspace (
e2-dogfoodUC):cursor-agent mcp list→databricks-system-ai: readycursor-agent mcp list-tools databricks-system-ai→ 4 live tools (system__ai__ai_classify,ai_extract,ai_parse_document,python_exec)OAUTH_TOKENunset — proving auth comes from the refreshed file header.${env:...}(DCR error) vs. success with a literal token, same endpoint/env.uv run pytest→ 868 passed (2 pre-existingtest_e2e_user_agentnetwork failures unrelated to this change);uv run ruff checkclean.Known limitation
The background thread bounds token staleness to the ~30-min refresh interval and keeps
~/.cursor/mcp.jsoncurrent, but whether Cursor picks up the rewritten token mid-session depends on cursor-agent re-reading mcp.json on change (not documented). This matches the freshness story of the other literal-token agents; a per-request helper isn't possible because Cursor's mcp.json has no credential-command field.This pull request and its description were written by Isaac.