Skip to content

fix(api): target api.wave.online/v1/* — the host AND path that serve the API (#89) - #90

Open
yakimoto wants to merge 4 commits into
mainfrom
fix/89-default-base-url
Open

fix(api): target api.wave.online/v1/* — the host AND path that serve the API (#89)#90
yakimoto wants to merge 4 commits into
mainfrom
fix/89-default-base-url

Conversation

@yakimoto

@yakimoto yakimoto commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Closes #89.

The issue was right that it's broken, and incomplete about why

#89 proposed changing the default WAVE_BASE_URL from https://wave.online to
https://api.wave.online. That alone would not have fixed a single tool, because every tool
also hardcodes /api/v1/*, and /api/v1/* is not a client path on any WAVE host.

/v1/* is the public API path space on api.wave.online. /api/v1/* is an internal path shape that
is not routable by a client on any host — confirmed against the API's own routing layer — so fixing only
the host, as the issue proposed, would still have 404'd on every call.

Measured live, 2026-08-07:

Request Result
POST https://api.wave.online/v1/streams 402 — route exists and is priced
POST https://api.wave.online/api/v1/streams 404
POST https://wave.online/api/v1/streams 404 (the old default — wrong origin entirely)
GET https://api.wave.online/v1/nonexistentgroupxyz 403 ROUTE_NOT_MAPPED (fail-closed control)

All 12 distinct /v1 paths the 18 tools use were probed individually; every one returns 402, i.e.
every one is a real, priced, scope-gated API route.

What changed

  • src/auth.tsDEFAULT_BASE_URLhttps://api.wave.online.
  • All 21 request sites (src/tools/*.ts, src/resources/*.ts) — /api/v1/*/v1/*.
  • WAVE_BASE_URL validation. An explicitly-set value is now parsed and required to be an
    absolute http(s) URL, with the trailing slash stripped (tool paths are absolute, so a trailing
    slash produced //v1/...). A bad value used to surface as an opaque fetch failure inside every
    individual tool call; it now fails at startup naming the offending value. The default is kept
    rather than made mandatory — there is a correct, measured answer, so requiring every user to
    supply it would be friction with no safety gain.
  • Key-minting URLhttps://console.wave.online/dashboard#keys (307 → /login?redirect=…,
    i.e. a real page). The old https://wave.online/settings/api-keys returned 404, so the only
    pointer a user got toward credentials was dead.

Docs corrected against live probes, not assumed

  • MCP-DEBUGGING.md advertised a staging origin, https://staging.wave.online. It has no DNS
    record
    (dig +short staging.wave.online → empty) and never resolved. The table has been removed
    rather than reworded — I did not invent a replacement staging host.
  • The same file said "Available tools (19)". There are 18.
  • Added a 402 troubleshooting entry, because a 402 is now the expected answer for an
    unscoped/unpaid call and reads like a failure if you don't know that.

Receipts

Built bundle (npm run build):

$ grep -o "/api/v1/[a-z]*" dist/*.js | sort | uniq -c
(no matches)

$ grep -o '/v1/[a-z]*' dist/*.js | sort | uniq -c
   2 dist/chunk-7677T5PZ.js:/v1/analytics      1 dist/chunk-7677T5PZ.js:/v1/clips
   2 dist/chunk-7677T5PZ.js:/v1/billing        8 dist/chunk-7677T5PZ.js:/v1/streams
   1 dist/chunk-7677T5PZ.js:/v1/cameras        3 dist/chunk-7677T5PZ.js:/v1/studio
   1 dist/chunk-7677T5PZ.js:/v1/switcher       1 dist/index.js:/v1/productions
   1 dist/index.js:/v1/streams

$ grep -o 'https://[a-z.]*wave.online[a-z/#-]*' dist/*.js | sort | uniq -c
   1 dist/chunk-7677T5PZ.js:https://api.wave.online
   1 dist/chunk-7677T5PZ.js:https://console.wave.online/dashboard#keys

End-to-end, driving the built stdio server over real JSON-RPC with a junk API key
(tools/callwave_list_streams):

TOOL RESULT: {"content":[{"type":"text","text":"Error 402: {\"x402Version\":1,
  \"error\":\"payment required\",\"accepts\":[{\"scheme\":\"exact\",...,
  \"resource\":\"/v1/streams\",...,\"payTo\":\"0x13014b6e42d6cae7d82798c17244b003c431b68c\",...

Before this change the same call produced a 404 from a host that does not serve the API. The 402 is
the receipt: the API answered, the route resolved, and it is priced.

npm run type-check, npm run lint --max-warnings 0, and npm run build all pass. This repo has
no test suite
(no *.test.ts / *.spec.ts, no test runner in package.json), so there is no
before/after suite count to report — that gap is worth its own issue.

Not done here — needs a release

This package is published to npm. A merge does not remediate installed copies. Every existing
install stays broken until a v* tag is pushed and the release workflow republishes. I did not bump
package.json (the release workflow requires tag version == package version, so the bump is part of
the release act, not this fix) and I did not tag — that is a publish crossing.

Given the default host changes and every request path changes, this warrants a minor bump
(0.2.0 → 0.3.0) and a note in the release announcement that prior versions were non-functional.

🤖 Generated with Claude Code

Note

Fix default API origin and tool path prefix to target api.wave.online/v1/*

  • Changes DEFAULT_BASE_URL in auth.ts from the marketing/app origin to the gateway origin (api.wave.online), fixing systematic 404s when WAVE_BASE_URL is unset.
  • Strips the /api prefix from all tool and resource fetch paths (e.g. /api/v1/streams/v1/streams) across all tool and resource files to match the gateway's public path space.
  • Adds assertConfigValid() called at startup in both server.ts and sdk-server.ts to fail fast with a clear error on a malformed WAVE_BASE_URL.
  • Hardens getBaseUrl() to reject non-absolute URLs, http for non-loopback hosts, and any URL with a path, query, or fragment.
  • Updates docs and error messages to point to the correct API key console URL and removes references to an unresolvable staging origin.

Macroscope summarized 1ca8943.


Note

High Risk
Touches every outbound API call and the default configuration path; incorrect rollout would break all 18 tools for npm consumers until they upgrade, though the change aligns endpoints with the live gateway.

Overview
Fixes #89: with the previous defaults (https://wave.online + /api/v1/*), none of the 18 tools could reach a real API route. The default origin is now https://api.wave.online, and every tool and wave:// resource fetch uses /v1/* instead of /api/v1/*.

WAVE_BASE_URL is validated when the stdio server starts (assertConfigValid in startServer): values must be a bare http(s) origin (no path/query/hash), remote hosts must use https (loopback http still allowed), and bad config fails once at startup instead of on every tool call. Missing-key errors point to console.wave.online/dashboard#keys instead of a 404 settings URL.

Docs (README, .wave/repo.json, MCP-DEBUGGING.md, CHANGELOG) match the new default, tool count (18), removed bogus staging host, and add 402 troubleshooting.

Reviewed by Cursor Bugbot for commit 938ce20. Configure here.

…the API (#89)

The default WAVE_BASE_URL was https://wave.online (the marketing/app origin, which
404s on the API surface) and every tool requested /api/v1/*. Both were wrong and
they compounded: with default configuration none of the 18 tools could ever succeed.

/api/v1/* was never a valid CLIENT path. The WAVE gateway serves /v1/* publicly and
re-prefixes to the spoke origin as /api/v1/* on forward (wave-gateway forward.ts
ORIGIN_PATH_PREFIX), so fixing only the host — as the issue proposed — would still
have 404d on every call.

Measured 2026-08-07:
  POST api.wave.online/v1/streams      -> 402 (route exists, priced)
  POST api.wave.online/api/v1/streams  -> 404
  POST wave.online/api/v1/streams      -> 404

Also: validate an explicitly-set WAVE_BASE_URL (fail loud at startup on a malformed
or non-http(s) value instead of failing opaquely inside each tool call), and repoint
the key-minting URL at console.wave.online/dashboard#keys (the old one 404d).

Docs corrected against live probes: the staging origin the debugging guide advertised
(staging.wave.online) has no DNS record and never resolved; the tool count said 19
when there are 18.

Installed copies stay broken until this is released to npm.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@yakimoto yakimoto added the rr:skip-cubic RF.P1 reviewer routing (#1039) label Aug 7, 2026
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_917fdd09-4ea8-4100-9631-c699c77f324e)

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 33 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5dac502a-2454-4117-84c8-b1e55744917b

📥 Commits

Reviewing files that changed from the base of the PR and between 8411936 and 1ca8943.

📒 Files selected for processing (14)
  • .wave/repo.json
  • CHANGELOG.md
  • MCP-DEBUGGING.md
  • README.md
  • src/auth.ts
  • src/resources/productions.ts
  • src/resources/streams.ts
  • src/sdk-server.ts
  • src/server.ts
  • src/tools/analytics.ts
  • src/tools/billing.ts
  • src/tools/production.ts
  • src/tools/streams.ts
  • src/tools/studio.ts

Comment @coderabbitai help to get the list of available commands.

@cursor cursor Bot 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.

Risk: medium. Left a non-blocking comment — Cursor Bugbot and Cursor Security Agent both completed as skipped (Bugbot hit a usage limit), so automated review signals are incomplete and this is not approved. Human review is needed; no additional reviewers could be assigned (CODEOWNERS team is unavailable and the only active human contributor is the PR author).

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Fix default Wave API origin and switch client paths to /v1 gateway routes

🐞 Bug fix 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Point default WAVE_BASE_URL to https://api.wave.online and use gateway /v1/* routes.
• Validate configured WAVE_BASE_URL early and strip trailing slashes to avoid broken requests.
• Update docs/changelog with correct key URL, tool count, and 402 troubleshooting.
Diagram

graph TD
  Tools["Tools & resources"] --> Fetch["waveFetch()"] --> Auth["auth.ts (base URL + headers)"] --> Gateway(["API gateway (api.wave.online /v1)"])
  Env(["WAVE_BASE_URL (env)"]) --> Auth
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Centralize API version prefix in waveFetch
  • ➕ Removes repeated "/v1" literals across tools/resources
  • ➕ Makes future version bumps less error-prone
  • ➖ Requires waveFetch to enforce a single API prefix (less flexible for non-/v1 endpoints)
  • ➖ Still needs careful handling of absolute vs relative paths
2. Make WAVE_BASE_URL include the /v1 prefix (treat as full base)
  • ➕ Tool code can use relative paths ("/streams" etc.)
  • ➕ Less opportunity for callers to mistakenly use a non-origin URL
  • ➖ Breaks the common expectation that *_BASE_URL is an origin
  • ➖ Harder to validate and document consistently when users supply custom gateways

Recommendation: The PR’s approach (keep WAVE_BASE_URL as a validated origin and switch all client calls to the gateway’s public /v1 paths) is the most robust and matches how the gateway is actually routed. If endpoint churn becomes common, consider the first alternative later to reduce repetition, but it’s not necessary to fix the current production breakage.

Files changed (11) +117 / -40

Bug fix (8) +64 / -24
auth.tsDefault to api.wave.online and validate/normalize WAVE_BASE_URL +44/-4

Default to api.wave.online and validate/normalize WAVE_BASE_URL

• Changes the default base URL to 'https://api.wave.online', introduces a constant for the console key URL, and updates the missing-key error message. Adds strict parsing and protocol checks for an explicitly set 'WAVE_BASE_URL' and strips trailing slashes to prevent '//v1/...' URLs.

src/auth.ts

productions.tsSwitch production resource fetch to /v1 gateway route +1/-1

Switch production resource fetch to /v1 gateway route

• Updates the resource fetch path from '/api/v1/productions/:id' to '/v1/productions/:id' to match the public gateway routing.

src/resources/productions.ts

streams.tsSwitch stream resource fetch to /v1 gateway route +1/-1

Switch stream resource fetch to /v1 gateway route

• Updates the resource fetch path from '/api/v1/streams/:id' to '/v1/streams/:id' to match the public gateway routing.

src/resources/streams.ts

analytics.tsUpdate analytics tool endpoints from /api/v1 to /v1 +2/-2

Update analytics tool endpoints from /api/v1 to /v1

• Rewrites analytics tool request paths to use the gateway’s '/v1/analytics/...' routes while preserving query parameter behavior.

src/tools/analytics.ts

billing.tsUpdate billing tool endpoints from /api/v1 to /v1 +2/-2

Update billing tool endpoints from /api/v1 to /v1

• Rewrites billing tool request paths to use '/v1/billing/...', ensuring calls hit the gateway route map.

src/tools/billing.ts

production.tsUpdate production/studio control endpoints from /api/v1 to /v1 +7/-7

Update production/studio control endpoints from /api/v1 to /v1

• Rewrites multiple mutating production endpoints (switcher control, clips, graphics actions, camera control, moderation, captions, highlights) to target '/v1/*' gateway routes.

src/tools/production.ts

streams.tsUpdate stream tool endpoints from /api/v1 to /v1 +5/-5

Update stream tool endpoints from /api/v1 to /v1

• Rewrites stream listing and lifecycle endpoints (create/start/stop/health) to use '/v1/streams...' gateway routes.

src/tools/streams.ts

studio.tsUpdate studio production endpoints from /api/v1 to /v1 +2/-2

Update studio production endpoints from /api/v1 to /v1

• Rewrites studio production list/create paths to use '/v1/studio/productions...' gateway routes.

src/tools/studio.ts

Documentation (3) +53 / -16
CHANGELOG.mdDocument corrected API host/path behavior and base URL validation +27/-0

Document corrected API host/path behavior and base URL validation

• Adds release notes explaining the previous broken defaults and the new 'api.wave.online' + '/v1/*' targeting. Notes early validation/normalization of 'WAVE_BASE_URL' and updates the key-minting URL reference.

CHANGELOG.md

MCP-DEBUGGING.mdFix key URLs, add 402 guidance, and correct API origin docs +24/-14

Fix key URLs, add 402 guidance, and correct API origin docs

• Updates links to the working console key page and console billing page, adds troubleshooting guidance for 402 responses, and replaces the staging/production table with a production-only API origin note. Corrects the listed tool count (18) and explains 'WAVE_BASE_URL' requirements.

MCP-DEBUGGING.md

README.mdUpdate key creation URL and default API origin +2/-2

Update key creation URL and default API origin

• Repoints the API key creation link to the Wave console and updates the documented default 'WAVE_BASE_URL' to 'https://api.wave.online' with '/v1/*' gateway paths.

README.md

devin-ai-integration[bot]

This comment was marked as resolved.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 7, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 7, 2026

Copy link
Copy Markdown

Approvability

Verdict: Approved 1ca8943

Bug fix correcting broken API URLs (wrong host and paths caused all 18 tools to 404). Changes are mechanical URL/path string updates plus defensive startup validation. Author owns all modified files. The unresolved review comment appears outdated - the diff shows assertConfigValid() is added to both server entry points.

You can customize Macroscope's approvability policy. Learn more.

@qodo-code-review

qodo-code-review Bot commented Aug 7, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Base URL accepts paths ✓ Resolved 🐞 Bug ≡ Correctness
Description
getBaseUrl() documents/enforces WAVE_BASE_URL as an origin, but it only checks protocol and strips
trailing slashes, so URLs with a path/query/fragment still pass and then corrupt request URL
construction. Because waveFetch() concatenates strings, a configured value like "https://host#x" or
"https://host?x=y" can cause the appended "/v1/..." to become part of the fragment/query and not be
sent as the request path.
Code

src/auth.ts[R63-64]

+  // Tool paths are absolute (`/v1/...`), so a trailing slash would produce `//v1/...`.
+  return configured.replace(/\/+$/, "");
Evidence
The docs and error message require WAVE_BASE_URL to be an origin (no path), and request helpers rely
on origin-only semantics by concatenating the base URL with an absolute path. However, getBaseUrl()
returns the raw configured URL (only trimming trailing slashes) without rejecting
pathname/search/hash, so invalid-but-parseable values can pass validation and then produce malformed
request targets.

MCP-DEBUGGING.md[54-58]
src/tools/shared.ts[32-47]
src/auth.ts[43-65]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`getBaseUrl()` is intended to validate that `WAVE_BASE_URL` is an **origin** (scheme+host+optional port) but currently returns the raw configured string (minus trailing slashes) without rejecting `pathname`, `search`, or `hash`. Since request URLs are later formed via string concatenation (`${getBaseUrl()}${path}`), allowing a base URL with a path/query/fragment can misroute or break all tool calls.

### Issue Context
- Tools/resources append absolute paths like `/v1/...`.
- A base URL containing `#fragment` or `?query` will swallow the appended `/v1/...` into the fragment/query portion of the URL string.

### Fix Focus Areas
- src/auth.ts[43-65]

### What to change
- After `new URL(configured)`:
 - Reject any value where `parsed.pathname` is not `/` (or empty), or where `parsed.search` / `parsed.hash` are non-empty.
 - Return a normalized origin (e.g. `parsed.origin`) instead of the raw `configured` string.
 - Keep the existing http(s) check.

Example logic sketch:
- if (parsed.pathname !== "/" && parsed.pathname !== "") throw ...
- if (parsed.search || parsed.hash) throw ...
- return parsed.origin;

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
✅ Compliance rules (platform): 2 rules
Review mode: ⚖️ Balanced: This changes runtime API routing across 21 request sites and adds URL validation, creating meaningful behavioral risk across multiple paths, but not enough new logic or defect density to justify redundant extended passes.

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

qodo-code-review[bot]

This comment was marked as resolved.

@qodo-code-review

Copy link
Copy Markdown

Qodo Fixer

No findings are within the configured fix scope. To change which findings are fixed, adjust the setting on your Qodo configuration page.

…ce (#89)

The public-repo-guard content policy blocked the previous commit: the explanatory
comment in src/auth.ts named a private WAVE repo and one of its internal source
files. That is exactly what the guard exists to catch, and it was right to.

The comment now explains the same thing — why the API origin is api.wave.online and
why the tool paths are /v1/* rather than /api/v1/* — without naming any private repo
or internal module. The measured probe table is unchanged; it was never the problem.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…tps (#89 review)

Four review findings, all correct:

1. The validation was lazy. getBaseUrl() is only reached when a tool runs, so a bad
   value still failed once per tool call — exactly what the change claimed to remove.
   startServer() now calls assertConfigValid() before binding the transport.

2. A value with surrounding whitespace, or a path/query/fragment, produced broken
   request URLs. The URL parser tolerates whitespace that string concatenation does
   not, and tool paths (/v1/...) are appended to this value. It now returns
   parsed.origin, and REJECTS a path/query/fragment rather than silently dropping it.

3. http:// to a remote host sent the API key in cleartext (every request attaches
   Authorization: Bearer). Now refused unless the host is loopback.

4. README is machine-generated from .wave/repo.json, which still carried the old
   default and the dead key-minting URL — the next regeneration would have reverted
   the README fix. The SSOT is updated too.

Also repairs the CHANGELOG: the previous commit inserted a "### Changed" heading
mid-list, which orphaned the existing .d.ts entry under it and produced two identical
headings in one release block.

Verified at startup against the built artifact:
  "https://api.wave.online/"      -> starts (trailing slash normalised)
  "  https://api.wave.online  "   -> starts (whitespace trimmed)
  "http://localhost:8787"         -> starts (loopback allowed)
  "http://api.wave.online"        -> Fatal: must use https for a remote host
  "https://api.wave.online/v1"    -> Fatal: must be an origin only
  "not-a-url"                     -> Fatal: not a valid absolute URL

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_8a979a98-ae4f-423c-95fe-d10bd53fad7a)

devin-ai-integration[bot]

This comment was marked as resolved.

@yakimoto

yakimoto commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Review responses — addressed in 938ce20

"Validation only fires when a tool runs, not at startup." Correct, and it invalidated the claim in my
own commit message. getBaseUrl() is reached per request, so a bad value still failed once per tool call.
startServer() now calls assertConfigValid() before binding the transport. Verified against the built
artifact:

"https://api.wave.online/"     → starts (trailing slash normalised)
"  https://api.wave.online  "  → starts (whitespace trimmed)
"http://localhost:8787"        → starts (loopback allowed)
"http://api.wave.online"       → Fatal: must use https for a remote host
"https://api.wave.online/v1"   → Fatal: must be an origin only
"not-a-url"                    → Fatal: not a valid absolute URL

Whitespace / trailing slash, and origins carrying a path, query or fragment. Both correct and they
have one fix: getBaseUrl now returns parsed.origin rather than the raw string, so whitespace (which
the URL parser tolerates but string concatenation does not) and trailing slashes normalise away. A
path/query/fragment is rejected loudly rather than silently discarded — someone who set one meant
something by it, and silently dropping it would substitute one surprise for another.

http:// transmits the API key in cleartext. Good catch; every request attaches
Authorization: Bearer. Remote http:// is now refused. Loopback (localhost/127.0.0.1/::1) is still
allowed so a local gateway stays usable in development.

"README is generated; the SSOT still has the old values." This one would have silently reverted the
whole fix on the next regeneration. .wave/repo.json carried both https://wave.online as the documented
WAVE_BASE_URL default and the dead wave.online/settings/api-keys link; both are updated, and the JSON
still parses.

Changelog structure. Correct — my previous commit inserted a ### Changed heading mid-list, which
orphaned the existing .d.ts entry under it and produced two identical headings in one release block.
Restructured: one ### Fixed, one ### Changed.

Two I did not change, with reasoning

/v1/productions/{id} vs /v1/studio/productions. Flagged as a possible asymmetry. I probed both
live: GET https://api.wave.online/v1/productions/abc402 and
GET https://api.wave.online/v1/studio/productions402. On this gateway a 402 proves the route
exists and is priced (an unmapped path returns 403 ROUTE_NOT_MAPPED, which I also verified against
/v1/nonexistentgroupxyz). So both are real, distinct, scope-mapped routes and the asymmetry is
intentional, not a typo. Preserving the pre-existing distinction was the conservative choice.

"No automated coverage for the URL construction." Entirely fair, and I want to be plain about it:
this repository has no test suite at all — no *.test.ts, no test runner in package.json. That is
why the PR reports no before/after suite count. I did not add a test framework in a bug-fix PR, but the
gap is real and deserves its own issue: the exact regression this PR fixes (a silently wrong base URL and
path prefix breaking all 18 tools) is one a single URL-construction test would have caught.

…oo (#89 review)

assertConfigValid() was wired into startServer() only, which is the stdio entry
point. Consumers using createWaveSdkMcpServer() never reached it, so the documented
"validated at startup" contract held for one of the two transports — and in-process
consumers kept seeing a malformed WAVE_BASE_URL surface once per tool call, which is
the behaviour the doc comment claims was removed.

Both transports now validate at construction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@devin-ai-integration devin-ai-integration Bot 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.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment thread MCP-DEBUGGING.md
@yakimoto

yakimoto commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 1ca8943

"In-process SDK server bypasses the new startup validation." Correct. assertConfigValid() was wired
into startServer() only — the stdio entry point — so createWaveSdkMcpServer() consumers never reached
it and kept seeing a malformed WAVE_BASE_URL surface once per tool call, which is precisely the
behaviour my doc comment claimed had been removed. A contract that holds for one of two transports is not
a contract. Both now validate at construction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rr:skip-cubic RF.P1 reviewer routing (#1039)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default WAVE_BASE_URL (wave.online) 404s on /api/v1/*; all 18 tools broken

1 participant