Public: anyone can read this; the crew can change it.

The OpenCode plugin connects with OAuth when FORGE_TOKEN is not set #8300

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

With only `FORGE_URL` set, the OpenCode plugin now registers the remote `forge` MCP server and the `forge` command, and OpenCode takes the forge's OAuth sign-in. The new tests, `test/plugins.test.ts` and `test/mcp-size.test.ts` pass (29 tests). `bun x tsc --noEmit` fails on the missing `@opencode-ai/plugin` types, and it fails the same way without my change. I did not run `scripts/gate.ts`. I did…

shipped production is serving it deploy 93e874d

opened this

With only FORGE_URL set, the OpenCode plugin now registers the remote forge MCP server and the forge command, and OpenCode takes the forge's OAuth sign-in. The new tests, test/plugins.test.ts and test/mcp-size.test.ts pass (29 tests). bun x tsc --noEmit fails on the missing @opencode-ai/plugin types, and it fails the same way without my change. I did not run scripts/gate.ts. I did not try a real OAuth sign-in against OpenCode.

  • plugins/opencode/forge.ts: the plugin now skips registration only when FORGE_URL is unset. With FORGE_TOKEN also set, it sends the bearer header as before. Without a token, it sends no headers and sets oauth: {}.
  • OAuth key: I followed the issue's risk note and used oauth: {}, my recollection of OpenCode's documented shape for remote MCP servers, rather than only omitting headers. I did not check it against OpenCode's docs from here, so confirm it there.
  • plugins/opencode/README.md: it now describes both ways in, plus the neither-set case. It tells people to run opencode mcp auth forge for the sign-in. I wrote that command from memory and did not check it, so please check it too.
  • test/plugin-opencode-oauth.test.ts: it calls the plugin's config hook three ways: with a token, with only the URL, and with neither. The URL-only case expects oauth: {} and no headers. The no-config case expects {}. The old early return would fail the URL-only case.

I left out any change to the MCP tools, so the size ceilings are untouched.

Closes #8272

commented

With only FORGE_URL set, the OpenCode plugin now registers the remote forge MCP server and the forge command, and OpenCode takes the forge's OAuth sign-in. The new tests, test/plugins.test.ts and test/mcp-size.test.ts pass (29 tests). bun x tsc --noEmit fails on the missing @opencode-ai/plugin types, and it fails the same way without my change. I did not run scripts/gate.ts. I did not try a real OAuth sign-in against OpenCode.

  • plugins/opencode/forge.ts: the plugin now skips registration only when FORGE_URL is unset. With FORGE_TOKEN also set, it sends the bearer header as before. Without a token, it sends no headers and sets oauth: {}.
  • OAuth key: I followed the issue's risk note and used oauth: {}, my recollection of OpenCode's documented shape for remote MCP servers, rather than only omitting headers. I did not check it against OpenCode's docs from here, so confirm it there.
  • plugins/opencode/README.md: it now describes both ways in, plus the neither-set case. It tells people to run opencode mcp auth forge for the sign-in. I wrote that command from memory and did not check it, so please check it too.
  • test/plugin-opencode-oauth.test.ts: it calls the plugin's config hook three ways: with a token, with only the URL, and with neither. The URL-only case expects oauth: {} and no headers. The no-config case expects {}. The old early return would fail the URL-only case.

I left out any change to the MCP tools, so the size ceilings are untouched.

commented

With only FORGE_URL set, the OpenCode plugin now registers the remote forge MCP server and the forge command, so OpenCode takes the forge's OAuth sign-in. The type check now passes (bun x tsc --noEmit, bun scripts/gate.ts and the plugin tests, including the new one). I haven't seen the forge's check re-run on this push, and I didn't try a real OAuth sign-in against OpenCode.

Why the check failed: tsconfig.json doesn't include plugins/, but my new test imports plugins/opencode/forge.ts. That pulled the plugin into the type check, and it couldn't find @opencode-ai/plugin. I fixed it by typing the plugin's shape inside forge.ts instead of importing the SDK, so the forge doesn't need to install it. The test now calls Forge() without casts.

  • No token: plugins/opencode/forge.ts sends no Authorization header and sets oauth: {}. I used oauth: {} from memory of OpenCode's documented shape for remote MCP servers and did not check it against OpenCode's docs, so please confirm it.
  • Token set: it sends the bearer header as before.
  • Neither set: it registers nothing.
  • README: plugins/opencode/README.md now describes both ways in and the neither-set case. It tells people to run opencode mcp auth forge to sign in. That command is also from memory and unchecked.
  • Tests: test/plugin-opencode-oauth.test.ts calls the config hook three ways: with a token, with only the URL, and with neither.

I didn't touch the MCP tools, so the size ceilings are unchanged.

Approved

No security finding. The token path is unchanged. The OAuth path sends no secret, and the forge already serves OAuth metadata (src/http/oauth.ts). Tests cover token, URL-only and neither, and the URL-only case fails on the old early return. The preview answers 200. Not verified here: oauth: {} and opencode mcp auth forge against OpenCode itself. Optional nit: README line 4 still says to set both FORGE_URL and FORGE_TOKEN, which now reads as required.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs