Skip to content

chore: add /sdk-proxy slash command for hitting the API via the SDK app proxy#1991

Open
serikjensen wants to merge 3 commits into
mainfrom
sj/chore/sdk-proxy-command
Open

chore: add /sdk-proxy slash command for hitting the API via the SDK app proxy#1991
serikjensen wants to merge 3 commits into
mainfrom
sj/chore/sdk-proxy-command

Conversation

@serikjensen
Copy link
Copy Markdown
Member

@serikjensen serikjensen commented Jun 2, 2026

Summary

Adds a Claude/Cursor slash command at .claude/commands/sdk-proxy.md that lets the agent run real curl requests against whatever demo company you already have running in the SDK Dev App. No re-provisioning, no env-file reads, no port hardcoding.

Invocation pattern:

/sdk-proxy create an employee named Alice Johnson
/sdk-proxy list payrolls for the current company
/sdk-proxy show me what a "submit payroll" request body looks like

What the command teaches the agent

  • Port discovery via lsof -iTCP:5200-5299 + cwd-match against git rev-parse --show-toplevel. Robust against auto-incremented ports (5201/5202/...) and multiple sibling-repo SDK apps running in parallel; verified with /sdk-app/api/validate-token signature endpoint as a fallback diagnostic.
  • Always route through the local Vite proxy (http://localhost:<port>/api/...), never the gws-flows host directly. The proxy's in-memory FLOW_TOKEN is the source of truth; the on-disk env file lags when "Set Manual Token" / "Refresh Token" is used in the Settings panel.
  • Discover the live company UUID by hitting /v1/companies, never by reading sdk-app/env/.env.demo.
  • Look up endpoints via the gusto-payroll MCP (find_endpoint / generate_curl / check_scopes / validate_workflow) instead of guessing paths from memory.
  • Temp-file curl pattern (curl -o $OUT -w "HTTP %{http_code}" && jq < $OUT) so the status code and JSON body never collide in jq's parse stream.
  • Per-repo cache in $TMPDIR (120s TTL + single verify probe) so repeat invocations skip discovery entirely — first call ~1.2s, subsequent calls ~150ms.

Two subtle footguns captured as inline author-notes

  1. Cursor's slash-command renderer interpolates dollar-digit tokens ($0$9) as positional args from the user's invocation, before the agent sees the prompt. An awk '{print $2}' literal becomes awk '{print <second word of user message>}'. The discovery snippet uses lsof -F field records + grep/sed instead of awk positional fields, and a verified-grep guard keeps it that way.
  2. Cache hygiene relies on unsetsource<rm + unset> on every failure path. Without the pre-source unset, a missing key in a partial cache file inherits prior shell state. Without the post-failure unset, a stale COMPANY_ID lingers in the shell environment and silently leaks into rediscovery in Step 1.

Files touched

Just one new file:

  • .claude/commands/sdk-proxy.md (+262 lines)

No source code changes. Cache file lives in $TMPDIR, outside the repo — no .gitignore update needed.

Test plan

  • Discovery snippet resolves SDK_APP_PORT=5200 against this repo's running SDK app (verified end-to-end during development).
  • Cache write → read → verify-probe round-trips with HTTP 200 (verified).
  • All four Step 0 code paths exercised (fresh-hit / expired / verify-fail / no-cache-with-leaked-shell-vars) and produce the expected CACHE_HIT / file / unset state.
  • curl -o $OUT -w "HTTP %{http_code}" && jq < $OUT pattern produces clean output (no jq: parse error noise).
  • Zero \$<digit> matches remain in the file (verified-grep guard).
  • Reviewer: try /sdk-proxy list employees for the current company against a running SDK app to confirm the end-to-end flow works in your environment.
Screen.Recording.2026-06-02.at.4.05.51.PM.mov

Made with Cursor

…pp proxy

Drops in a Claude/Cursor slash command at .claude/commands/sdk-proxy.md that
lets the agent run real curl requests against the demo company you already
have running in the SDK Dev App, without re-provisioning or reading the env
file directly.

The command teaches the agent to:

- Discover the SDK app's port robustly via lsof + cwd match (works across
  auto-incremented ports 5200/5201/... and multiple sibling-repo SDK apps
  running in parallel)
- Route curl through the running Vite proxy at http://localhost:<port>/api
  so the in-memory FLOW_TOKEN is always the source of truth (the on-disk
  env file lags when "Set Manual Token" or "Refresh Token" is used in the
  Settings panel)
- Discover the live company UUID by hitting /v1/companies, never by
  reading sdk-app/env/.env.demo (which can be stale)
- Look up endpoints via the gusto-payroll MCP (find_endpoint /
  generate_curl / check_scopes / validate_workflow) instead of guessing
  paths from memory
- Use a temp-file pattern (curl -o ... -w "HTTP %{http_code}" && jq < ...)
  so status code and JSON body never collide in jq's parse stream
- Cache the discovered port + company UUID in $TMPDIR with a 120s TTL and
  a single verify probe, so repeat invocations skip discovery entirely

Includes author notes on two subtle footguns: (1) Cursor's slash-command
renderer interpolates dollar-digit tokens as positional args from the
user's invocation, so awk positional fields cannot be used here -- the
discovery snippet uses lsof -F field records + grep/sed instead; (2) the
cache hygiene relies on unset-before-source plus rm+unset on every
failure path to prevent stale shell state from leaking into rediscovery.

No source code changes; only the new .claude/commands/sdk-proxy.md file.

Co-authored-by: Cursor <cursoragent@cursor.com>
@serikjensen serikjensen requested a review from a team as a code owner June 2, 2026 22:17
serikjensen and others added 2 commits June 2, 2026 16:36
…prompt install

The previous draft of this command referenced the `gusto-payroll` MCP at
the internal staging URL (gusto-partner-api.staging.zp-int.com), which
isn't installable by partners or by anyone outside Gusto's network. The
Embedded Dev Assistant MCP is the documented, public, partner-facing
equivalent -- this commit migrates the command to point at it and adds a
project-level config so teammates get auto-prompted to install on first
workspace open.

Changes:

- Add `.cursor/mcp.json` at the repo root with the public
  `embedded-payroll` entry from docs.gusto.com. Cursor auto-detects
  project-level MCP configs and prompts the user to enable them, so
  teammates opening the workspace see a one-click install instead of
  hitting "MCP not loaded" errors when they run /sdk-proxy.
- Rename all MCP references in .claude/commands/sdk-proxy.md from
  `gusto-payroll` -> `embedded-payroll` to match the docs canonical
  server name.
- Replace Step 3's hardcoded tool-name table (find_endpoint /
  generate_curl / check_scopes / validate_workflow / generate_typescript)
  with a capability-keyed one. The public MCP's docs describe its
  surface as "API reference access, documentation search, code/snippet
  generation" without naming individual tools, and tool names are
  subject to change as the MCP evolves. Describing what we need by
  capability lets the agent introspect the live tool surface and pick
  the right one, rather than failing on a renamed tool.
- Add a Prerequisites section at the top of the command linking the
  official Dev Assistant MCP docs, with the canonical install snippet
  and a verification step ("ask the agent what MCP tools it has").
- Update the worked example and the discovery-only escape hatch to
  match the new capability-based phrasing.

Net effect: a partner who clones this repo, opens it in Cursor, and
clicks "Enable" on the prompt can run /sdk-proxy with no further setup.

Co-authored-by: Cursor <cursoragent@cursor.com>
On first install of the `embedded-payroll` MCP -- either via the
project-level `.cursor/mcp.json` prompt or a manual edit to
`~/.cursor/mcp.json` -- Cursor shows the server as enabled but doesn't
actually load its tools until the user manually toggles it off and back
on in settings. Before this commit, /sdk-proxy would simply bail with
"MCP not loaded; see Prerequisites", leaving the user to guess what to
do next.

Two changes:

- Add a "First-install gotcha" subsection to Prerequisites that names
  the toggle dance up front (Cmd+, -> Tools & MCP -> embedded-payroll
  -> off/on), with fallbacks for the older "MCP" / "Integrations"
  settings labels. This makes the workaround discoverable to anyone
  reading the docs ahead of time.
- Replace Step 3's terse "stop and link the user to Prerequisites" with
  a verbatim user-facing message the agent should emit when it can't
  see embedded-payroll tools. The message branches on "never installed"
  vs "just installed", walks through the exact toggle steps, and asks
  the user to reply when done so the agent can retry the original
  request without needing them to re-issue /sdk-proxy.

Net effect: a first-time user who hits the toggle bug gets a one-screen
fix from the agent itself, instead of a docs link they have to dig
through.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown
Contributor

@mariechatfield mariechatfield left a comment

Choose a reason for hiding this comment

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

Ah this is so cool! loved using it to update some data live

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.

2 participants