Skip to content

Add support for Cursor - #42

Merged
luisiul359 merged 10 commits into
mainfrom
cursor
Aug 11, 2026
Merged

Add support for Cursor#42
luisiul359 merged 10 commits into
mainfrom
cursor

Conversation

@luisiul359

@luisiul359 luisiul359 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Add Cursor as a first-class supported harness with plugin-based app support and CLI support

Changes

New Files

  • .cursor-plugin/marketplace.json — Cursor Team Marketplace index for plugin distribution
  • cursor/.cursor-plugin/plugin.json — Cursor plugin manifest (name, version, skills)
  • cursor/skills/outsystems/SKILL.md — Agent guidance doc (plugin-shipped, used by both app and CLI)
  • cursor/README.md — Install instructions for both Cursor App (plugin) and Cursor CLI
  • cursor/mcp.json — Canonical Cursor CLI MCP server configuration template

Modified Files

  • README.md — Added Cursor CLI (all plans) and Cursor App (Team/Enterprise plugin) install sections; updated .cursorrules references to .cursor/rules/outsystems.md with AGENTS.md fallback
  • CLAUDE.md — Updated harness table with two Cursor rows (App + CLI); documented plugin/CLI dual paths and version lockstep (all 4 manifest files)
  • CONTRIBUTING.md — Updated repository structure, prerequisites, and testing sections; added plugin version alignment requirements; updated CLI config references to .cursor/rules/
  • copilot/skill.md — Added YAML frontmatter (name: outsystems, description) for consistency with plugin-shipped skill docs
  • skills/outsystems/SKILL.md, kiro/outsystems/steering/skill.md, copilot/skill.md, cursor/skills/outsystems/SKILL.md, SKILL.md — Added callback-failure troubleshooting guidance (connection-refused in VMs, don't wait for timeout, ask user for URL, IPv4→IPv6 adjustment)
  • .claude-plugin/plugin.json — Bumped 0.12.0 → 0.13.0
  • .claude-plugin/marketplace.json — Bumped 0.12.0 → 0.13.0
  • cursor/.cursor-plugin/plugin.json — Version 0.13.0 (new)
  • .cursor-plugin/marketplace.json — Version 0.13.0 (new)

Details

Cursor CLI (All Plans)

  • Simple copy-paste format matching Copilot CLI pattern
  • File-based config: ~/.cursor/mcp.json (global) or .cursor/mcp.json (project)
  • Top-level key: mcpServers (not servers)
  • Format: {"mcpServers": {"outsystems": {"url": "https://..."}}} — no type field
  • Authentication via agent mcp login and agent mcp enable CLI commands
  • Works for all users: free, team, and enterprise (no restrictions)
  • Conventions file: fetch cursor/skills/outsystems/SKILL.md and save to .cursor/rules/outsystems.md (or AGENTS.md if project uses that)

Cursor App (Team/Enterprise Plan Plugin)

  • Plugin ships skills only — agent prompts for tenant and completes setup
  • Team admin imports plugin to Team Marketplace (Dashboard → Plugins → Team Marketplaces → Import from Repo)
  • Individual users auto-setup via agent conversation (writes ~/.cursor/mcp.json)
  • Free plan users: use CLI instead (Team Marketplace unavailable)
  • Enterprise customers: can choose either CLI or plugin

Plugin Version Alignment

  • Claude and Cursor plugin versions must stay in sync:
    • .claude-plugin/plugin.jsonversion
    • .claude-plugin/marketplace.jsonplugins[0].version
    • cursor/.cursor-plugin/plugin.jsonversion
    • .cursor-plugin/marketplace.jsonplugins[0].version
  • All four must be bumped together in the same commit

Skill Doc Updates

  • copilot/skill.md — Added YAML frontmatter for consistency with plugin-shipped skill docs
  • All 5 skill docs (Claude Code, Cursor, Kiro, Copilot, root) — Enhanced callback-failure troubleshooting:
    • When browser shows "site can't be reached" at callback URL (e.g., IPv4/IPv6 mismatch in VMs)
    • Agent guidance: don't wait for timeout; ask user for full callback URL from address bar
    • Offer IPv4→IPv6 adjustment guidance (change 127.0.0.1 to [::1])
    • Emphasize code is short-lived, act immediately
    • Harness-specific instruction: Claude Code can use deferred tool, Kiro/Copilot/Cursor handle in native UI

Validation

  • ✓ Plugin structure matches production pattern from rd-ai-common#33
  • ✓ All 5 skill docs have matching ## Rules, ## Workflows, ## Feedback sections
  • ✓ Callback-failure guidance synchronized across all 5 skill docs (harness-specific implementations)
  • ✓ Copilot skill doc now includes YAML frontmatter matching Claude and Cursor
  • ✓ CLAUDE.md harness table documents both Cursor paths (App + CLI)
  • ✓ Version numbers synchronized to 0.13.0 across all four manifest files (Claude + Cursor pairs)
  • ✓ README and CONTRIBUTING.md updated to reference .cursor/rules/ instead of .cursorrules
  • ✓ README presents CLI and App as equal options (no assumptions about preference)
  • ✓ CLI instructions are copy-paste friendly, matching other harnesses
  • ✓ Team Marketplace limitation clearly marked for App only; CLI available to all

@luisiul359
luisiul359 requested a review from a team as a code owner August 5, 2026 16:22
@luisiul359 luisiul359 changed the title Add support for Cursor CLI Add support for Cursor Aug 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Cursor as a first-class supported harness (Cursor App via Team Marketplace plugin + Cursor CLI via file-based config), and updates repo docs/manifests to reflect the new distribution surface and required version/skill-doc lockstep.

Changes:

  • Introduces Cursor plugin + marketplace manifests and Cursor-specific install docs/config (cursor/ + .cursor-plugin/).
  • Updates root documentation (README/CLAUDE/CONTRIBUTING) to include Cursor as a supported harness and document dual App/CLI paths.
  • Bumps plugin versions and extends “version alignment” guidance to include Cursor.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
README.md Adds installation instructions for Cursor CLI and Cursor App plugin.
cursor/skills/outsystems/SKILL.md Adds Cursor harness skill doc (agent rules/workflows) for plugin + CLI use.
cursor/README.md Adds Cursor-specific setup guide and version/lockstep guidance.
cursor/mcp.json Adds canonical Cursor CLI mcpServers configuration example.
cursor/.cursor-plugin/plugin.json Adds Cursor plugin manifest (name/version/skills path).
CONTRIBUTING.md Updates contribution docs for new Cursor distribution surfaces and lockstep requirements.
CLAUDE.md Updates supported harness table and expands lockstep/version-alignment guidance to include Cursor.
.cursor-plugin/marketplace.json Adds Cursor Team Marketplace index manifest pointing at cursor/.
.claude-plugin/plugin.json Bumps Claude plugin version.
.claude-plugin/marketplace.json Bumps Claude marketplace plugin version.
Suppressed comments (3)

cursor/README.md:68

  • This line says “Update all three together”, but there are four version fields that must be kept in sync (Claude plugin + marketplace, Cursor plugin + marketplace).
Update all three together in the same commit when bumping the version.

CLAUDE.md:60

  • The lockstep grep loop includes cursor/skill.md, which doesn’t exist in the repo; the Cursor doc path is cursor/skills/outsystems/SKILL.md. As written, the check will fail or silently miss Cursor changes.
for f in skills/outsystems/SKILL.md kiro/outsystems/steering/skill.md copilot/skill.md cursor/skill.md SKILL.md; do

CLAUDE.md:73

  • This sentence references cursor/skill.md, but the Cursor skill doc is cursor/skills/outsystems/SKILL.md. Keeping the correct path here matters for the “host-specific affordances” exception.
Host-specific UI surfaces (typed shortcuts, hotkeys) live only in the doc for the host that has them. The Claude Code marketplace plugin ships slash commands under `commands/` (declared in `.claude-plugin/plugin.json`'s `commands` key); Kiro Powers do not have an equivalent. So mentions of `/outsystems-feedback` and similar slash-command trigger phrases belong only in `skills/outsystems/SKILL.md`, not in `kiro/outsystems/steering/skill.md`, `copilot/skill.md`, `cursor/skill.md`, or root `SKILL.md`. The underlying *behavior* (what the agent does on the trigger) still has to lockstep across all five docs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread cursor/README.md
Comment thread CONTRIBUTING.md Outdated
Comment thread CLAUDE.md Outdated
Comment thread .claude-plugin/plugin.json

@david-santos-os david-santos-os left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work overall — the structure is right: the ## Rules section is byte-identical across all five skill docs, the slash-command mentions are correctly stripped from the Cursor doc, and all four manifests land on 0.13.0 together. I left the blockers and the smaller fixes as inline comments. The short version: the new skill doc was forked from a pre-0.12.0 revision of the shared content and needs a re-sync, and a few paths/URLs in the docs don't match the files the PR actually ships.

Three things I couldn't verify from the diff and would like confirmed before merge:

  1. Is the CLI binary really agent? Every CLI instruction here uses agent mcp list / agent mcp enable / agent mcp login, but Cursor's CLI installs as cursor-agent. If the name is wrong, every CLI step in README.md, CONTRIBUTING.md, and cursor/README.md fails. Please confirm on a current install and note the version you tested with.

  2. Is .cursorrules still the right target? It's Cursor's legacy rules mechanism, superseded by .cursor/rules/ and AGENTS.md support. Before we standardize on it across three docs, worth confirming the CLI actually loads it today.

  3. Can you record an end-to-end run for both new harness rows? Per CLAUDE.md's validate-every-harness policy: a Team Marketplace import for the app path, and agent mcp list → OAuth → a real tool call for the CLI path. The PR notes the structure matches rd-ai-common#33, but a couple of the inline findings (the 404 in the install prompt, the missing frontmatter) are exactly the kind of thing an e2e run would have caught.

One more small thing: the PR description has drifted from the diff — it says 0.11.0 → 0.12.0 (the diff is 0.12.1 → 0.13.0), the new-files list is missing cursor/mcp.json, and the validation section says "all 6 skill docs" where there are five. Worth updating so the merge record is accurate.

Comment thread cursor/skills/outsystems/SKILL.md
Comment thread cursor/skills/outsystems/SKILL.md Outdated
Comment thread cursor/skills/outsystems/SKILL.md Outdated
Comment thread cursor/skills/outsystems/SKILL.md
Comment thread CLAUDE.md Outdated
Comment thread cursor/README.md Outdated
Comment thread CONTRIBUTING.md Outdated
Comment thread CONTRIBUTING.md
Comment thread CLAUDE.md Outdated
Comment thread README.md Outdated
@luisiul359

Copy link
Copy Markdown
Contributor Author
  1. Is the CLI binary really agent? Every CLI instruction here uses agent mcp list / agent mcp enable / agent mcp login, but Cursor's CLI installs as cursor-agent. If the name is wrong, every CLI step in README.md, CONTRIBUTING.md, and cursor/README.md fails. Please confirm on a current install and note the version you tested with.

Yes, the correct command is agent: https://cursor.com/docs/cli/overview#getting-started.

  1. Is .cursorrules still the right target? It's Cursor's legacy rules mechanism, superseded by .cursor/rules/ and AGENTS.md support. Before we standardize on it across three docs, worth confirming the CLI actually loads it today.

Fixed.

  1. Can you record an end-to-end run for both new harness rows? Per CLAUDE.md's validate-every-harness policy: a Team Marketplace import for the app path, and agent mcp list → OAuth → a real tool call for the CLI path. The PR notes the structure matches rd-ai-common#33, but a couple of the inline findings (the 404 in the install prompt, the missing frontmatter) are exactly the kind of thing an e2e run would have caught.

e2e was done in a session with David.

@david-santos-os david-santos-os left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the previous findings are addressed — I re-verified rather than took it on faith: every shared section of the Cursor doc now hashes identical to the Kiro doc (builder_retry_friction, the revision-notes caveat, and the explicit publish recipe included), the frontmatter is in, the lockstep grep runs against real paths, the raw URL resolves, and the version lists, counts, and numbering are all correct. Thanks for the quick turnaround, and for the answers on the CLI binary and the e2e run.

The remaining asks are about the new callback-troubleshooting content that came in with 724375d. It's a good addition, but the "extract the authorization code" advice only works on the one host that has a tool to accept a pasted code (Claude Code's complete_authentication), and in the Cursor doc it contradicts the same section it lives in. Details inline — they're wording-level fixes, plus one .cursorrules straggler.

Two non-code asks:

  1. One more pass on the PR description, please. It still says .cursorrules in the skill-doc structure section and "All 6 skill docs" / "synchronized to 0.12.0" under Validation — and it doesn't mention the callback-troubleshooting guidance or the copilot/skill.md frontmatter at all, which are real behavioral changes shipping in this PR. It's the merge record; it should describe what's actually landing.

  2. Is the frontmatter added to copilot/skill.md intentional? That file is copied verbatim into .github/copilot-instructions.md, which is plain markdown — the YAML block will show up as literal content in every Copilot user's instructions file. If it's there for AGENTS.md tooling or a Copilot feature I'm missing, a line in the PR description would help; if not, it can be dropped (root SKILL.md didn't get one either).

Comment thread cursor/skills/outsystems/SKILL.md Outdated
Comment thread cursor/skills/outsystems/SKILL.md Outdated
Comment thread kiro/outsystems/steering/skill.md Outdated
Comment thread copilot/skill.md Outdated
Comment thread SKILL.md Outdated
Comment thread CLAUDE.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Suppressed comments (10)

cursor/skills/outsystems/SKILL.md:67

  • A refused TCP callback happens before Cursor's listener or the token endpoint receives the code, so it does not itself spend the code. This contradicts the preceding curl replay of the identical callback and can trigger needless reauthentication. Only start fresh if that replay reports an ended/expired session or redemption failure.
**If the browser shows "site can't be reached" at the callback URL:** The sign-in already succeeded on the tenant side — the identity provider issued the code and redirected. Only the last local hop failed: Cursor's callback listener and the browser's redirect resolved to different addresses, typically an IPv4/IPv6 loopback mismatch in a VM, where the listener is on `[::1]:PORT` and the redirect went to `127.0.0.1:PORT`. **Do not wait for the timeout, and tell the user so immediately** — they don't need to sit through the two-minute failure. Ask the user for the full URL from the address bar (it contains `callback?state=...&code=...`), then **complete the callback yourself via the terminal**: find the port Cursor is listening on with `lsof -nP -iTCP -sTCP:LISTEN | grep LISTEN` and look for the port in the URL. Re-send the identical callback to Cursor's listener with `curl "http://[::1]:PORT/callback?state=...&code=..."`, swapping the host to `[::1]` if the address bar showed `127.0.0.1`. This hand-off is not an auth tool call; it simply delivers the code to Cursor's loopback listener where the redirect was meant to land. The code is single-use, so do not also ask the user to retry in the browser — one of you, not both. **Expect the attempt to be dead already:** the refused connection tears down the authorization session, so you'll likely get "Authorization session ended" and that code is spent. If so, ask the user to start a fresh sign-in and tell them the corrected address (`[::1]` instead of `127.0.0.1`) to use *before* they click through. Treat authorization codes as credentials either way.

copilot/skill.md:43

  • A refused TCP callback happens before Copilot CLI's listener or the token endpoint receives the code, so it does not itself spend the code. This contradicts the preceding curl replay of that same callback and can trigger needless reauthentication. Only start fresh if replay reports an ended/expired session or redemption failure.
- **Copilot CLI** runs the OAuth flow on the first tool call (opens the system browser and listens on an ephemeral `localhost` port for the callback). A browser must be reachable on the same machine. If the browser shows "site can't be reached" at the callback URL (typically an IPv4/IPv6 loopback mismatch in a VM): **do not wait for timeout, and tell the user immediately** — tenant-side sign-in already succeeded. Ask the user for the full URL from the address bar. Complete the callback yourself via the terminal: find the port from the URL and run `lsof -nP -iTCP -sTCP:LISTEN | grep LISTEN` to confirm the listener. Re-send the callback with `curl "http://[::1]:PORT/callback?state=...&code=..."`, swapping the host to `[::1]` if the URL showed `127.0.0.1`. This delivers the code to Copilot CLI's loopback listener, not a tool call. Do not also ask the user to retry in the browser. **Expect the code to be spent:** the refused connection tears down the auth session. If you get "Authorization session ended", have the user start fresh with the corrected address before clicking through. Treat authorization codes as credentials.

cursor/README.md:3

  • The plugin is only the Cursor App distribution path; the CLI path in this directory is a manual MCP config plus a copied skill file. Saying the plugin is available for CLI conflicts with the installation sections below.
This directory ships the OutSystems MCP plugin for Cursor, available for both Cursor app and Cursor CLI.

cursor/skills/outsystems/SKILL.md:17

  • This setup is not universally a two-stage flow: Cursor CLI users do not install the Team Marketplace plugin, as the CLI section below confirms. Present App and CLI as alternative paths so CLI users are not told that an admin/plugin install is a prerequisite.

This issue also appears on line 67 of the same file.

The OutSystems MCP server registration happens in two stages:

1. **Team admin adds the plugin** (via Dashboard → Plugins → Team Marketplaces → Import from Repo)
2. **Individual user completes setup** via agent prompts in Cursor app or CLI

CLAUDE.md:47

  • This omits the primary automatic consumer introduced by the PR: Cursor App loads this document through the plugin manifest, while Cursor CLI consumes a manual copy. Document both paths to keep the canonical harness table and this list consistent.
- `cursor/skills/outsystems/SKILL.md` is the Cursor skill doc, consumed by Cursor CLI.

SKILL.md:15

  • The new generic skill has no harness-specific authentication subsections, so this reference sends fallback-client users to instructions that do not exist in the document. Point readers to their client's authentication documentation instead.
**If the browser shows "site can't be reached" at the callback URL:** The sign-in succeeded on the tenant side — only the callback connection failed, typically an IPv4/IPv6 loopback mismatch in a VM. **Do not make the user wait for timeout; tell them immediately.** Ask for the full callback URL from the address bar. Recovery depends on your harness: some clients can replay the callback via shell commands; others require the user to adjust the address in their browser. See your harness's specific Authenticating section for the exact steps. Treat authorization codes as credentials — code is single-use and short-lived.

copilot/skill.md:43

  • The PR description and validation state that YAML name/description frontmatter was added here, but this file still starts directly with # OutSystems - Remote MCP at line 1; this callback edit is the only current change. Add the promised frontmatter or correct the stated scope.

This issue also appears on line 43 of the same file.

- **Copilot CLI** runs the OAuth flow on the first tool call (opens the system browser and listens on an ephemeral `localhost` port for the callback). A browser must be reachable on the same machine. If the browser shows "site can't be reached" at the callback URL (typically an IPv4/IPv6 loopback mismatch in a VM): **do not wait for timeout, and tell the user immediately** — tenant-side sign-in already succeeded. Ask the user for the full URL from the address bar. Complete the callback yourself via the terminal: find the port from the URL and run `lsof -nP -iTCP -sTCP:LISTEN | grep LISTEN` to confirm the listener. Re-send the callback with `curl "http://[::1]:PORT/callback?state=...&code=..."`, swapping the host to `[::1]` if the URL showed `127.0.0.1`. This delivers the code to Copilot CLI's loopback listener, not a tool call. Do not also ask the user to retry in the browser. **Expect the code to be spent:** the refused connection tears down the auth session. If you get "Authorization session ended", have the user start fresh with the corrected address before clicking through. Treat authorization codes as credentials.

CLAUDE.md:60

  • The supported-harness expansion leaves .github/pull_request_template.md:16-19 stale: it still lists only Claude Code/Kiro/Copilot, four skill docs, and the two Claude manifests. Future PRs following that checklist can therefore skip Cursor validation and the new five-doc/four-manifest lockstep requirements documented here.
After any skill-doc change, grep for a distinctive phrase from the change across all five files and confirm the count matches:

```bash
PHRASE="<a distinctive substring from your change>"
for f in skills/outsystems/SKILL.md kiro/outsystems/steering/skill.md copilot/skill.md cursor/skills/outsystems/SKILL.md SKILL.md; do

skills/outsystems/SKILL.md:40

  • A refused TCP callback happens before the listener or token endpoint receives the authorization code, so the refusal does not itself spend the code. This contradicts the recovery immediately above that forwards the same callback URL and can cause an unnecessary second sign-in. Only require a fresh flow after replay actually reports an ended/expired session or redemption failure.
- **Remote session** (callback page fails to load, e.g. SSH / devcontainer, or "site can't be reached" in a VM): **do not wait for timeout, and tell the user immediately** — tenant-side sign-in already succeeded; they don't need to sit through the two-minute failure. Ask the user to copy the full URL from their browser's address bar (`http://localhost:<port>/callback?code=...&state=...`), then call `mcp__outsystems__complete_authentication { callback_url: "<that URL>" }` to deliver the code to Claude Code's callback listener. This completes the sign-in flow. The authorization code is single-use, so if it fails, start a fresh `mcp__outsystems__authenticate` and do not ask the user to also retry in the browser. **Expect the code to be spent:** if the callback connection was refused, the authorization session was torn down and that code is no longer valid. If you get a "session ended" error, ask the user to start a fresh sign-in. Treat authorization codes as credentials either way.

kiro/outsystems/steering/skill.md:45

  • A refused TCP callback happens before Kiro's listener or the token endpoint receives the code, so it does not itself spend the code. This also contradicts the preceding instruction to retry that same URL with the corrected host. Start a fresh flow only when the corrected callback actually returns an ended/expired session or redemption failure.
**If the browser shows "site can't be reached" at the callback URL:** The sign-in already succeeded on the tenant side — the identity provider issued the code and redirected. Only the last local hop failed: Kiro's callback listener and the browser's redirect resolved to different addresses, typically an IPv4/IPv6 loopback mismatch in a VM, where the listener is on `[::1]:PORT` and the redirect went to `127.0.0.1:PORT`. **Do not wait for the timeout, and tell the user immediately** — they don't need to sit through the two-minute failure. Ask the user to adjust the address in their own browser: if the address bar shows `http://127.0.0.1:PORT/callback?state=...&code=...`, they should change just the host to `[::1]` (keeping the square brackets and the entire rest of the URL), then press Enter. This routes the callback to Kiro's IPv6 loopback where it's actually listening. Do not ask them to also retry after — one attempt, not both. **Expect the code to be spent:** the refused connection tears down the authorization session. If it answers "Authorization session ended", start a fresh sign-in and give them the corrected address *before* they click through. Treat authorization codes as credentials either way.

@david-santos-os david-santos-os left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-verified the latest round: the callback recovery guidance is now actionable on every host (and honest about the code usually being spent), the CLI reactive path is back, the .cursorrules straggler is gone, and all shared sections still hash identical across the five skill docs with the manifests aligned on 0.13.0. Good to go — thanks for the thorough turnaround across all three rounds.

@luisiul359
luisiul359 merged commit d597932 into main Aug 11, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants