docs(mcp): per-client onboarding pages + first-class HTTP transport doc#524
Merged
docs(mcp): per-client onboarding pages + first-class HTTP transport doc#524
Conversation
Splits the lump-everything-together MCP quickstart into four short
per-client pages (Claude Desktop, Claude Code, Cursor, Windsurf) and
promotes HTTP/SSE transport from a one-paragraph aside to a real
how-to page.
WHY
The previous setup had the four AI clients sharing a single
quickstart with a generic STDIO config and a one-line aside per
client. Readers landing from "Cursor MCP setup" or "Windsurf MCP
setup" search queries hit a dense umbrella page rather than a
60-second walkthrough scoped to their tool.
HTTP / SSE transport is implemented in @runcycles/mcp-server but
was buried in a 14-line "HTTP transport" section of
how-to/integrating-cycles-with-mcp.md. Anyone wanting a shared
team gateway, a sidecar in CI, or a co-deploy with cycles-server
had no documented decision tree, no auth notes, no working
example.
Audited the current shipping surface (no Dockerfile in the MCP
repo, no GHCR image, peer container pattern in cycles-server
reusable when/if HTTP demand validates). Concluded the missing
surface is per-client onboarding polish + HTTP doc promotion,
NOT a container.
CHANGES
Quickstart (per-client pages, NEW)
quickstart/mcp-claude-desktop.md
quickstart/mcp-claude-code.md
quickstart/mcp-cursor.md
quickstart/mcp-windsurf.md
Each follows the same shape: prerequisites, exact config-file
paths (per OS where relevant), config blob, mock mode block,
verify step, common gotchas, and cross-links to the umbrella +
sibling clients + HTTP how-to.
Quickstart (umbrella, slimmed)
quickstart/getting-started-with-the-mcp-server.md
Replaced the per-client setup duplication with a "Pick your
client" table linking to the four new pages. Kept the
protocol-level content (reserve/commit lifecycle, available
tools, prompts, configuration reference) since that's
transport-agnostic. Added a forward link to the new HTTP
how-to.
How-To (HTTP transport, NEW)
how-to/running-the-mcp-server-over-http.md
Decision tree for STDIO vs HTTP, --transport http startup,
env config, docker-compose worked example with cycles-server
co-deploy, auth & scope-derivation behavior over HTTP, known
limitations (no first-party container yet, no per-user auth,
in-memory sessions). The HowTo + Article schema is auto-
injected by the existing transformPageData hook, verified
via dist HTML grep.
How-To (existing integration page)
how-to/integrating-cycles-with-mcp.md
Promoted the one-paragraph "HTTP transport" section to a
"Transport modes" overview that names both transports,
cross-links to the per-client quickstarts, keeps the quick
HTTP startup snippet, and forward-links to the new HTTP
how-to for the deep treatment.
Sidebar (.vitepress/config.ts)
Quickstart group: replaced the flat "Add to Claude / Cursor
/ Windsurf" entry with a collapsible "MCP server (Claude /
Cursor / Windsurf)" group containing Overview + 4 per-client
pages.
Integrations > Agent Platforms group: added "MCP server over
HTTP / SSE" alongside the existing "MCP (Claude, Cursor,
Windsurf)" entry.
VERIFIED
- npm run build completes cleanly (97s, no errors)
- All 5 new pages render to dist
- Umbrella's HTML contains all 4 mcp-claude-* / mcp-cursor /
mcp-windsurf links
- HowTo schema present in
dist/how-to/running-the-mcp-server-over-http.html
- No sidebar group or page-link regressions
- Display total preserved (8,109)
…tcha trims Internal review pass on PR #524 surfaced six items worth fixing. One commit, six files, +39 / −42 lines. CHANGES Claude Code scopes (mcp-claude-code.md) Two corrections. (1) Default scope for `claude mcp add` is `local`, not user-wide as the prior text said; rewrote the paragraph to name all three scopes (local / user / project) and explain when each fits. (2) Updated the gotcha bullet to match — was describing two scopes, there are three. Docker-compose worked example (running-the-mcp-server-over-http.md) The original compose used `node:22-alpine + npx` as the mcp-server command. That setup is fragile under compose: the npm cache is non-persistent and runs as the `node` user without HOME/cache wiring, so `npx` re-downloads on every restart and may hit permission errors. Replaced with a tiny pinned Dockerfile (`npm install` at build time → `CMD npx ...`) plus a smaller compose that builds it. Removed the cycles-server + db services entirely since their config was incomplete for this page's purpose (and outside scope — this page is about running the MCP server in HTTP mode, not deploying the full Cycles stack). Added a forward link to "Self-Hosting the Server" for readers who need a Cycles server. Reframed the "no first-party container" limitation to point readers at the new Dockerfile pattern, with explicit guidance to pin the package version in production rather than `@latest`. Remote-MCP client config example (running-the-mcp-server-over-http.md) The original example showed only the bare `{ "url": ... }` shape. In practice early-2026 clients are split between `{ "url": ... }` and `{ "type": "http", "url": ... }`. Showed both shapes and added an explicit "check your client's current docs" caveat. Cursor gotcha cleanup (mcp-cursor.md) Trimmed an out-of-place sentence about `claude mcp list` not showing Cursor's config — it was a true but bizarre cross- reference inside a Cursor-specific gotcha. Kept the project-vs- user-scope point itself. Windsurf project-scoped claim (mcp-windsurf.md) Softened the absolute "does not currently support a project- scoped MCP config" claim; per-workspace overrides are rolling out across release channels and the safer phrasing is "config is typically user-scoped, check your build's settings panel". Sidebar label (.vitepress/config.ts) Renamed the Quickstart group from "MCP server (Claude / Cursor / Windsurf)" to just "MCP server" — the parenthetical missed Claude Code, and a 4-client list in a sidebar label is noisy anyway. The 4 children speak for themselves. Description length (mcp-claude-desktop.md) Trimmed the frontmatter description to under 160 chars for SEO snippet rendering. VERIFIED - npm run build completes cleanly (92s, no errors) - All 5 new pages still render to dist - Sidebar shows the renamed "MCP server" group with all 5 children present - HowTo schema still injected on the HTTP how-to page
…I-first paths External review pass on PR #524 with citations from the official MCP / Claude Code / Cursor / Windsurf docs. Six accepted findings applied across all four per-client pages. CHANGES Claude Code scope precedence (mcp-claude-code.md) Corrected. The official precedence is local → project → user (highest to lowest), not "project wins" as I had it. Updated the gotcha bullet to name all three scopes and the precedence order explicitly. Source: code.claude.com/docs/en/mcp scope precedence section. Claude Code project .mcp.json uses env expansion Replaced the hardcoded `cyc_live_...` example in the committable .mcp.json with `${CYCLES_API_KEY}` and `${CYCLES_BASE_URL:-http://localhost:7878}`. Claude Code supports env expansion in .mcp.json — committing real secrets in a project file is the wrong default to model. Added an explicit "do not commit real secrets" line. Claude Code CLI: --env at registration Promoted the `--env KEY=VALUE` flag pattern as the primary setup path instead of `claude mcp add` followed by shell `export`s. Export-then-launch only works if Claude Code is launched from a shell where those vars are set; --env at registration rides with the server config. Claude Desktop: Node.js prereq + UI path + log paths + secret note Added Node.js 18+ to prerequisites (was previously buried in a gotcha). Added the in-app **Settings → Developer → Edit Config** path as the fastest way to open the file. Added log locations to gotchas (~/Library/Logs/Claude on macOS, %APPDATA%\Claude\logs on Windows). Added a "treat config as secret" callout next to the API-key paste step. Cursor: version-tolerant mode wording Softened "Composer mode enabled" to "tool-enabled Agent / Composer flow" with an explicit note that the mode label varies across Cursor releases. Added a "Settings → MCP is the source of truth" gotcha for when the file path itself changes. Windsurf: UI-first config path + tool-limit gotcha Windows path divergence is real — community guides cite both %USERPROFILE%\.codeium\... and %APPDATA%\Codeium\... — so promoted the in-app **Settings → Cascade → MCP Servers → View Raw Config** path as the primary way to open the file. Listed both Windows path variants as fallbacks. Added the Cascade-100-tool-limit gotcha: Cycles exposes ~9 tools, but the cap exists across all enabled servers. Source: docs.windsurf.com/windsurf/cascade/mcp. "What Cycles adds" footer on all 4 pages Same 2-sentence callout on Claude Desktop, Claude Code, Cursor, Windsurf: MCP gives the client a standard way to call tools, Cycles adds runtime authority (budget, risk, scope, reserve→commit/release) before those tools run. Reinforces the product thesis on every onboarding page without turning setup into a sales page. VERIFIED - npm run build completes cleanly (93s, no errors) - All 4 per-client pages render with the new sections - HowTo/Article schema unchanged (auto-injected by transformPageData) - Sidebar unchanged
… verify, auth tightening
External review pass on the Streamable HTTP / SSE how-to. Six
findings, all sourced from official MCP / Claude Code / Windsurf
docs, all accepted.
CHANGES (running-the-mcp-server-over-http.md)
Title and heading rename to "Streamable HTTP / SSE"
MCP's current terminology is "Streamable HTTP" with SSE as
the older/legacy shape. The endpoint table already named both
correctly; the page title and heading now match. Slight SEO
win on the canonical term, and removes the implied "HTTP and
SSE are equally first-class" framing.
Claude Code remote CLI example, promoted
Claude Code has first-party CLI support:
claude mcp add --transport http cycles https://mcp.example.com/mcp
Added a "Claude Code" subsection above the generic JSON shapes
to show the CLI form (production URL + local-testing URL),
then kept the generic JSON for clients that take config files.
Source: code.claude.com/docs/en/mcp.
Tightened audit-vs-enforcement language in the auth section
The original wording could be read as "tag the user identity
and you have per-user enforcement" — that's wrong. Tagging is
audit context. Per-user enforcement requires either mapping
the authenticated user to an explicit tenant/scope policy
before calling Cycles, or running separate gateway identities
per boundary. Made that distinction explicit and bold-marked
"audit context, not enforcement."
Port-publish warning in docker-compose
The compose example published `3000:3000` while the security
section later warned not to expose `/mcp` publicly. Added an
inline comment on the `ports:` line: "Local/dev only. In
production, drop ports: and use expose: ['3000']" with a
pointer to put a reverse proxy in front. Internally consistent
with the security warnings instead of contradicting them.
Windsurf compatibility note
Per Windsurf's current docs, Cascade supports stdio, HTTP, and
SSE transports. The page previously said "remote support is
rolling out unevenly" without distinguishing — now names
Windsurf as known-supported and Claude Code as having a CLI,
while keeping the "other clients vary" caveat.
Source: docs.windsurf.com/windsurf/cascade/mcp.
MCP Inspector verification section, NEW
Added a "Verify with MCP Inspector" section between the
docker-compose example and the client config section:
npx @modelcontextprotocol/inspector
Select Streamable HTTP, point at http://localhost:3000/mcp,
list tools, call cycles_check_balance. Lets readers prove the
server itself works before debugging Cursor/Windsurf/Claude
client wiring. Reduces support-burden on us and resolves
"is it the server or my client" 90% of the time.
Source: platform.claude.com/docs/en/agents-and-tools/mcp-connector.
VERIFIED
- npm run build completes cleanly (93s)
- HowTo / Article schema unchanged (auto-injected)
- All cross-links still resolve
… API-key permissions, prereqs
External review pass on the umbrella MCP quickstart. Six findings,
all accepted. The most important is the tools-vs-enforcement
distinction — the page previously implied that adding the MCP
server gives hard enforcement, which contradicts the broader
Cycles thesis that "tools alone are not hard gates."
CHANGES (quickstart/getting-started-with-the-mcp-server.md)
Reframe: tools exposure, not automatic enforcement
Intro and frontmatter description rewritten to say the MCP
server "exposes Cycles tools" rather than "gives runtime
authority." Added an explicit one-line follow-up: "For hard
production enforcement, route costly or risky actions through
the reserve → execute → commit/release lifecycle, or enforce
Cycles in the application/gateway layer."
Added a `::: warning ::: ` callout immediately after the
intro titled "What this does and does not enforce" with the
"use this for / for production enforcement" framing the
reviewer suggested verbatim. Reinforces honest claim
boundaries without weakening the page's value prop.
API key wording softened
"always start with cyc_live_" → "Use a runtime API key such
as cyc_live_...". Test keys (cyc_test_...) exist and are
referenced in the per-client gotchas — "always" was wrong.
Sample permissions clarified
The sample curl creates a key with reserve/commit/release/
extend/list/balances:read permissions only. But the tools
table includes cycles_decide and cycles_create_event, which
require additional perms in most Cycles deployments. Added
an explicit note that the sample is "enough for the core
reserve / commit / release lifecycle" and that decide /
create_event need their own permissions to avoid auth errors.
Node.js / npx promoted to prerequisites
Was previously implicit (and called out in per-client
gotchas). Now explicit at the umbrella level, matching the
per-client pages.
Lifecycle wording
"reserve → execute → commit" → "reserve → execute → commit,
or release if the operation fails or is cancelled." The
release path is on equal footing with commit; the prior
framing made it feel like an afterthought.
cycles_create_event description sharpened
"Record usage directly without reserve/commit (fire-and-
forget)" → "Record usage or governance events without a
reservation lifecycle. Useful for telemetry; not a substitute
for pre-execution enforcement." Closes the same loophole as
the top-level reframe — fire-and-forget events are NOT
enforcement.
VERIFIED
- npm run build completes cleanly (94s)
- Umbrella renders with the new warning callout
- All cross-links to per-client pages and HTTP how-to still
resolve
- HowTo / Article schema still injected on the page
…ement, idempotency, Streamable HTTP
External review pass on how-to/integrating-cycles-with-mcp.md.
Six findings, all accepted. Same thesis-alignment fixes as the
umbrella + HTTP page passes — keep the page consistent across the
whole MCP doc set.
CHANGES (how-to/integrating-cycles-with-mcp.md)
Reframe: tools exposure, not "automatic budget authority"
Intro rewritten. The page previously said agents "gain budget
authority automatically" and that MCP gives them the ability
to "reserve, spend, and release without any SDK integration"
— directionally true for tool *access*, but easy to read as
"all agent actions are now governed." Replaced with the
explicit "MCP exposes Cycles tools; for hard production
enforcement, the Cycles check must be in the actual execution
path (tool/model/gateway/harness)."
Frontmatter description updated to match (was "give any
MCP-compatible AI agent runtime authority"; now "expose
Cycles runtime tools").
Replaced the "Zero code changes" tip with "No SDK changes" +
explicit "do not rely on the model voluntarily calling these
tools. Put the Cycles check in the tool execution path or
gateway layer." Same wording the umbrella now uses.
Pattern 5 (cycles_create_event) post-hoc warning
Added a callout after the fire-and-forget example: "This is
post-hoc metering, not pre-execution enforcement. It records
that the action happened — it does not stop the action before
it happens. For preventative control, use cycles_decide
(preflight) or cycles_reserve (lock budget) before execution."
Closes the same loophole as the umbrella's create_event
description sharpening — fire-and-forget events are NOT
enforcement.
Idempotency wording: drop "exactly-once", use "stable"
"Use unique idempotency keys ... to ensure exactly-once
processing" was technically wrong on two counts:
1. Idempotency gives replay-safe request handling, not
exactly-once external side effects.
2. For retries, the SAME logical operation needs the SAME
key — not a new UUID per attempt.
Replaced with: "Use a unique, stable idempotencyKey per
logical Cycles operation so retries replay safely and do not
double-settle reservations. The same retry of the same
logical call must use the same key, not a new UUID per
attempt."
Streamable HTTP rename
"HTTP / SSE" → "Streamable HTTP / SSE compatibility" in the
transport modes section, matching the title rename on the
HTTP how-to page in the previous commit. Cross-link label
updated to match. Aligns with the current MCP spec
terminology.
caps payload field-naming softened
The page asserted specific camelCase field names
(maxTokens, toolAllowlist, toolDenylist, cooldownMs,
maxStepsRemaining). Without independently verifying the wire
shape returned by the MCP server today, replaced specific
field names with descriptive prose ("max output tokens",
"allowed/denied tool lists", "cooldown timing") and pointed
readers at the protocol page for current schema. Avoids
drift between docs and adapter shape.
Pattern 6 long-workflow polish
Added the explicit anti-pattern callout: "Do not reserve
once for an entire long workflow unless you are comfortable
locking that whole estimate up front — per-step reservations
give the authority layer a chance to stop mid-run, and
unused budget returns to the pool sooner."
VERIFIED
- npm run build completes cleanly (94s)
- HowTo / Article schema unchanged
- Cross-link to /how-to/running-the-mcp-server-over-http still
resolves (page exists from earlier in this PR)
- Forward and back links between umbrella ↔ how-to ↔ HTTP
page now use consistent terminology and consistent claim
boundaries (tools-exposure vs. hard-enforcement)
… flag order
User-driven correction pass on the per-client + umbrella pages. Two
factual errors I had wrong, plus a few precision improvements.
CHANGES
Cursor + Windsurf: env interpolation IS supported
Reverses my earlier "Env not interpolated" gotcha on both pages.
Both clients document `${env:NAME}` expansion in MCP config
fields (env, and for Windsurf also url, serverUrl, headers).
Project config blocks updated to use `${env:CYCLES_API_KEY}`
and `${env:CYCLES_BASE_URL}` instead of hardcoded `cyc_live_...`
placeholders. This is the correct default for a shared
`.cursor/mcp.json` or `mcp_config.json` — secrets never enter
the file.
Replaced the wrong gotcha with a GUI-launch caveat: when the
client is launched from a desktop launcher rather than a shell,
it may not see `CYCLES_API_KEY`/`CYCLES_BASE_URL`. Suggested
fixes: set them in OS environment, use `envFile` (Cursor), or
use a wrapper script.
Cursor `.gitignore` gotcha sharpened
Updated to reference env interpolation: commit env references
or mock-mode config, keep any local `.env` out of git. Replaces
the previous "commit only with CYCLES_MOCK: true" workaround
that's no longer needed once env interpolation is on the table.
Claude Code CLI flag order corrected
`claude mcp add [options] <name> <command> [args...]` — flags
must come before the server name. The previous form
`claude mcp add cycles --env ...` was wrong on documented
syntax. Reordered to:
claude mcp add \
--transport stdio \
--env CYCLES_API_KEY=... \
--env CYCLES_BASE_URL=... \
cycles \
-- npx -y @runcycles/mcp-server
Mock-mode line reordered consistently. Added explicit
`--transport stdio` (default, but clearer).
Two new gotchas:
- "CLI option order matters" — explains where flags vs
positional arg vs `--`-passed args go
- "Native Windows needs a wrapper" — on native Windows
(not WSL), `npx` won't launch directly under Claude
Code; use `-- cmd /c npx -y @runcycles/mcp-server`
Node.js 18+ → 20+
Node 18 hit EOL in 2025; 20+ is the realistic floor for
@runcycles/mcp-server in 2026. Updated the prereq line in
the umbrella, the Claude Desktop page prereq, and the Claude
Desktop "npx not found on Windows" gotcha to match.
Umbrella: cycles_check_balance recursion semantics
The previous wording said the call "returns balances for all
scopes under that tenant" — overstated the default. The tool
accepts `includeChildren: true` for descendant scopes; without
it, you get matching balance records only. Updated the
paragraph to say "ask for child scopes explicitly; the tool
maps that to includeChildren: true where the server supports
it."
VERIFIED
- npm run build completes cleanly (88s)
- All 5 modified pages render correctly
- Cross-links between umbrella and per-client pages still resolve
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.
Splits the lump-everything-together MCP quickstart into four short per-client pages and promotes HTTP/SSE transport from a one-paragraph aside into a real how-to. Outcome of the audit that walked back the earlier "ship a GHCR container for the MCP server" recommendation.
What changed
Per-client quickstarts (NEW, 4 pages)
quickstart/mcp-claude-desktop.mdcyc_test_vscyc_live_quickstart/mcp-claude-code.mdclaude mcp addCLI, project- vs user-scoped.mcp.json, mock mode via--envquickstart/mcp-cursor.md.cursor/mcp.jsonproject vs user, Composer-mode requirement, secret-handling notequickstart/mcp-windsurf.md~/.codeium/windsurf/mcp_config.json, Cascade-mode requirement, user-only scopeEach page: prerequisites → exact config blob → mock-mode block → verify step → common gotchas → cross-links to siblings + umbrella + HTTP how-to.
Umbrella (slimmed)
quickstart/getting-started-with-the-mcp-server.md— replaced the per-client setup duplication with a "Pick your client" table linking to the four new pages. Kept the protocol-level content (reserve/commit lifecycle, available tools, prompts, configuration reference) since it's transport-agnostic. Added a forward link to the new HTTP how-to.HTTP/SSE how-to (NEW)
how-to/running-the-mcp-server-over-http.md— first-class doc for the HTTP transport that was previously a 14-line aside. Contains:--transport httpstartup,PORT/ env config, endpoint tableThe existing
transformPageDatahook auto-injects the HowTo + Article schema — verified the JSON-LD lands indist/how-to/running-the-mcp-server-over-http.html.Existing integration page
how-to/integrating-cycles-with-mcp.md— the previous one-paragraph "HTTP transport" section is now a "Transport modes" section that names both transports, cross-links the per-client quickstarts, keeps the quick HTTP startup snippet, and forward-links to the new how-to for the deep treatment.Sidebar (
.vitepress/config.ts)Add to Claude / Cursor / Windsurfentry → collapsibleMCP server (Claude / Cursor / Windsurf)group with Overview + 4 per-client items.MCP server over HTTP / SSEalongside the existingMCP (Claude, Cursor, Windsurf)entry.Why this and not a GHCR container
A targeted audit of the existing MCP shipping surface refuted the prior "ship a
cycles-mcp-serverGHCR container" recommendation:npxsubprocess and own the lifecycle. Containerizing a STDIO subprocess is architecturally incoherent.cycles-mcp-serverclones are source-inspection signal, not container demand. Users are already installing via npm.So the actual underweight surface is per-client onboarding polish + HTTP/SSE doc promotion, which this PR ships. The container is deferred until HTTP demand validates (Search Console signal on the new how-to, GitHub issues asking for it, etc.) — at which point the cycles-server
release.yml+ Trivy + GHCR pattern can be copied verbatim. ~3 hours when the time comes.Test plan
npm run buildpasses locally — 97s, no errors, display total 8,109 preserveddist/distHTML contains all 4 per-client links (mcp-claude-desktop,mcp-claude-code,mcp-cursor,mcp-windsurf)dist/how-to/running-the-mcp-server-over-http.htmlFollow-up (NOT in this PR, gated on data)
cycles-mcp-server(~3 hours)🤖 Generated with Claude Code