Commit Graph

24 Commits

Author SHA1 Message Date
Fahreddin Özcan 07580f10af feat(plugins): add Context7 plugin for OpenCode (#3008)
* feat(plugins): add Context7 plugin for OpenCode

Adds @upstash/context7-opencode, an OpenCode plugin that registers the
hosted Context7 MCP server, the context7-mcp skill, a docs-researcher
subagent, and the /context7-docs command through the config hook.

* docs(opencode): keep ctx7 setup as the primary install path

* refactor(opencode): drop the component toggles and tighten the option boundary

The skill/agent/command toggles were speculative: OpenCode dedupes skills by
name, so running ctx7 setup alongside the plugin is already safe, and a user
who wants a component gone can define it themselves, which the plugin never
overwrites. Removing them collapses resolveOptions into resolveApiKey and
deletes the duplicated defaulting between option parsing and config assembly.

Also assert the MCP endpoints as literals. The tests compared against the same
constants they exercised, so a wrong URL would have passed.

* refactor(opencode): drop tests and collapse the plugin into one file

config.ts existed to give the tests a seam. With the tests gone the split was
indirection with no consumer, so the constants, the config assembly, and the
plugin entry now live in src/index.ts and nothing but the default export is
public. Passing skillsDir through an ApplyInput object also stops being
necessary once it is a module constant.

* fix(opencode): run the MCP server over stdio and drop the slash command

Verified against a real OpenCode 1.18.11 session: the remote transport does
not work. OpenCode opens the optional GET SSE stream, mcp.context7.com answers
405, and OpenCode marks the server failed and registers no tools, so the model
never sees resolve-library-id and falls back to inventing bash calls. A control
project with a plain remote mcp block and no plugin fails the same way, so this
is not plugin-specific. Running the server over stdio connects and the model
calls the tools.

The bundled skill and the agent prompt also referenced the bare tool names.
OpenCode prefixes MCP tools with the server name, so they are now
context7_resolve-library-id and context7_query-docs.

Also removes the /context7-docs command. The skill already triggers on its own
and the subagent covers focused lookups.

* refactor(opencode): use the remote MCP server and drop the subagent

The plugin now adds two things: the hosted MCP server over the remote
transport, and the context7-mcp skill.

Known limitation: OpenCode opens the optional GET SSE stream on the endpoint
and mcp.context7.com answers 405, so OpenCode marks the server failed and
registers no tools. Reproduced on 1.18.11 and 1.18.16, and with a plain remote
mcp block and no plugin, so it is not plugin-specific. It resolves once
mcp.context7.com answers GET /mcp with a 200 SSE stream instead of 405.

* refactor(opencode): ship the canonical skill verbatim and drop the phantom peer dep

The bundled skill had been edited to hard-code OpenCode's context7_ tool
prefix. That divergence was unnecessary and counterproductive:

- It was fixing a misdiagnosis. The model only invented shell commands when
  the MCP server had failed to connect and no context7 tools existed at all.
  With the tools present, claude-haiku-4-5 calls context7_resolve-library-id
  correctly from the bare-name canonical skill.
- It was defeated where it mattered. OpenCode dedupes skills by name and scans
  ~/.claude/skills first, so on any machine that ran ctx7 setup the bundled
  copy is shadowed by the canonical one anyway.
- It was the only client copy to diverge in content. claude, copilot, codex
  and cursor all ship skills/context7-mcp/SKILL.md verbatim, and there is no
  tooling to keep copies in sync.

Also removes peerDependencies on @opencode-ai/plugin. The package is a
type-only import that the build erases, so the published dist has zero
references to it, and peerDependenciesMeta.optional made the declaration inert
anyway. The devDependency is what typechecking actually needs.

* refactor(opencode): strip commentary and inline the plugin function

Keeps only the two comments that stop someone breaking the plugin: why the
skills cast is needed, and why nothing but the default export may be exported.

Inlining the server function into the default export drops the Context7Plugin
binding and the Plugin type import, since satisfies PluginModule already types
the callback. 85 lines down to 56.

* docs(opencode): use the prefixed tool names consistently in the README
2026-08-18 15:20:43 +03:00
Konstantin Konstantinov 8d52608e4e feat: MCP v2 (#2843)
Co-authored-by: enesgules <abdullah.enes.gules@gmail.com>
Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-08-06 15:57:58 +03:00
Fahreddin Özcan beded6c0c8 fix(mcp): bump undici to 7, require Node >=20.18.1 (#2939)
Node 26 bundles undici 8, whose built-in fetch reads a global-dispatcher symbol
(Symbol.for('undici.globalDispatcher.2')) that the bundled undici 6
setGlobalDispatcher never wrote. The ProxyAgent and custom-CA Agent in api.ts
were therefore ignored, so HTTPS_PROXY and NODE_EXTRA_CA_CERTS were silently
dropped and requests failed with ENOTFOUND behind CONNECT proxies (#2935).

undici 7 writes both the legacy and current symbols, restoring proxy and CA
support across Node 20-26. It requires Node >=20.18.1, so Node 18 (EOL) is no
longer supported; the engines field and README are updated accordingly.

Fixes #2935
2026-07-23 12:37:10 +03:00
Fahreddin Özcan c61a56543d chore(deps): combined dependabot updates (Node 20 compatible) (#2891) 2026-07-09 12:50:14 +03:00
mehmet turac 8123b519ed fix: restore Node 18 support for context7 mcp (#2762)
* fix: restore Node 18 support for context7 mcp

* chore: add changeset for Node 18 fix

---------

Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-06-13 19:24:02 +03:00
Fahreddin Özcan cb6aee187e chore(deps): combined dependabot dependency updates (#2737)
* chore(deps): bump dependencies (combined dependabot updates)

Combines the safe dependabot dependency bumps into a single change:

- @modelcontextprotocol/sdk 1.25.2 -> 1.29.0 (mcp)
- undici 6.26.0 -> 8.3.0 (mcp)
- zod 4.3.5 -> 4.4.3 (mcp, tools-ai-sdk)
- commander 13.1.0 -> 15.0.0 (cli)
- ora 9.0.0 -> 9.4.0 (cli)
- dotenv 17.2.3 -> 17.4.2 (sdk, tools-ai-sdk, pi)
- @earendil-works/pi-coding-agent 0.75.5 -> 0.78.0 (pi)

eslint 9 -> 10 (#2703) is excluded: it is incompatible with the
pinned typescript-eslint v8 and breaks lint.

Verified: build, typecheck, lint, and tests pass.

* chore: add changesets for runtime dependency bumps

* fix(deps): pin undici to 7.x for Node 20 compatibility

undici 8 requires Node >=22.19.0 (it calls worker_threads.markAsUncloneable
unconditionally at module load), but CI and the release pipeline run Node 20,
which crashed the mcp test suite with 'markAsUncloneable is not a function'.
undici 7.27.0 guards that call and supports Node >=20.18.1.
2026-06-09 13:21:58 +03:00
Fahreddin Özcan 5a180d5b80 feat(cli): OAuth 2.0 device authorization flow (#2714)
* feat(cli): OAuth 2.0 device authorization flow

Adds RFC 8628 device-code login for headless / remote hosts (SSH,
Codespaces, Docker, CI) where the existing localhost-callback flow
can't work — the browser opens on the user's laptop while the
callback listener runs on the remote host, so the redirect target
is unreachable.

Device flow prints a verification URL and short code, then polls the
new /api/oauth/device/token endpoint. The user visits the URL on any
device, signs in, and approves; the CLI receives the same ctx7sk- API
key it would have gotten from the legacy flow.

- shouldUseDeviceFlow() auto-detects via SSH_CONNECTION /
  SSH_CLIENT / SSH_TTY and missing $DISPLAY on Linux.
- ctx7 login --device forces it. ctx7 setup picks it up
  automatically when resolveCliAuth needs to authenticate.
- pollDeviceToken returns a "transient" status for network errors
  and 5xx responses so a flaky backend or Upstash blip doesn't end
  the session — keeps polling until the device_code TTL elapses.

* polish(cli): boxed device-code prompt, Press-Enter, whoami success line

Tightens up the device-flow UX so it matches the patterns from gh /
stripe / wrangler:

- Wrap the user_code + verification URL in a boxen rounded box with
  a title, gray border, and the code as the visual headline (green
  bold, indented on its own line).
- Add a "Press Enter to open the browser, or Ctrl-C to quit..."
  confirmation step in TTY mode so the user can read the code before
  the browser steals focus. Skipped under --no-browser or non-TTY.
- Replace the generic "Login successful!" line with
  "Logged in as <email> (<team>)" by fetching /api/dashboard/whoami
  with the freshly minted token. Falls back to the old text if the
  call fails.
- Tighten the mockShouldUseDeviceFlow signature in the test mock so
  the spread-into-mock pattern typechecks.

No behavior change to the localhost-callback flow.

* test(cli): cover shouldUseDeviceFlow + start/poll + performDeviceLogin

auth-utils: SSH/$DISPLAY heuristics for shouldUseDeviceFlow; the
form-encoded start-device-authorization request shape and error
propagation; pollDeviceToken status mapping for each RFC 8628 code,
5xx -> transient, network error -> transient, and unknown 4xx ->
throw.

auth-commands: performDeviceLogin happy path (approved -> saveTokens
called), denied/expired return null and don't save, transient errors
keep polling instead of bailing, slow_down bumps the interval
(verified with fake timers), startDeviceAuthorization throwing exits
without polling, browser-open behavior under openBrowser=true/false.
Also covers the performLogin selector: forceDevice=true and
shouldUseDeviceFlow=true both route through performDeviceLogin
without hitting the localhost callback path.

28 new tests; suite is 235/235.

* docs(cli): tighten device-flow comments

Drop restatement; keep only WHY-bearing notes.

* fix(cli): default poll interval to 5s per RFC 8628 §3.2

The CLI was treating `interval` as required and would NaN-crash if
a future server omitted it. Spec requires clients to default to 5
when absent.

DeviceAuthorizationResponse.interval is now optional, and
performDeviceLogin uses DEFAULT_DEVICE_POLL_INTERVAL_SECONDS (5) as
the fallback. Test covers the missing-interval path.

* fix(cli): rfc 8628 spec gaps — backoff, hostname, bare verification_uri

Three small spec-compliance fixes from the §3.5 / §3.3 / §5.4 audit:

- §3.5: poll loop now bumps intervalMs by 5s on `transient` results
  (network errors and 5xx) — the RFC requires unilateral backoff on
  connection timeouts, and mirroring the slow_down handler is the
  simplest correct response.
- §3.3: the boxed prompt now prints the bare verification_uri
  alongside verification_uri_complete so screen readers / paper /
  another device can still type the short form.
- §5.4: startDeviceAuthorization sends `os.hostname()` so the server
  can show it on the verification page; the user can confirm the
  device they're authorizing matches the one running the CLI.

Transient-backoff test rewritten with fake timers (the new +5s wait
made the old real-timer assertion blow past the 5s default timeout).
2026-06-04 14:47:23 +03:00
Enes Gules f91b40c45c feat: pi context7 extension (#2666)
Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-05-25 13:32:34 +03:00
Enes Gules af6a7b5af1 feat: add sessions to MCP server (#2655) 2026-05-22 17:34:10 +03:00
Fahreddin Özcan dea0e4318d fix(cli): declare @inquirer/core as direct dependency (#2653)
* fix(cli): declare @inquirer/core as direct dependency

selectOrInput.ts imports from @inquirer/core directly, but the package
was only resolvable as a transitive of @inquirer/prompts. Under pnpm's
isolated linker this fails with ERR_MODULE_NOT_FOUND at startup.

Fixes #2651

* chore: add changeset
2026-05-20 12:46:12 +03:00
Enes Akar 17b864f23f expose research mode through MCP and CLI (#2498)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: enesgules <abdullah.enes.gules@gmail.com>
2026-04-24 20:48:05 +03:00
Fahreddin Özcan 00833f9262 fix(mcp): preserve default CAs with NODE_EXTRA_CA_CERTS (#2432)
* fix(mcp): support NODE_EXTRA_CA_CERTS for enterprise MITM proxies

When NODE_EXTRA_CA_CERTS is set, reads the CA certificate file and
injects it into undici's global dispatcher. This fixes fetch failures
behind enterprise transparent SSL intercept proxies (Zscaler, etc.)
where the default TLS context does not trust the corporate CA.

The CA certs are also passed through when an explicit HTTPS_PROXY is
configured, so both proxy modes work with custom certificates.

Fixes #2268

This contribution was developed with AI assistance (Claude Code).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add changeset for NODE_EXTRA_CA_CERTS support

* fix(mcp): preserve default CAs with NODE_EXTRA_CA_CERTS

* chore: add changeset for CA trust fix

* chore: remove superseded changeset

* fix(mcp): lint test files with test tsconfig

* fix(mcp): use explicit test file path

* fix(mcp): support older Node TLS CA APIs

* test(mcp): run certificate test with vitest

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 13:05:02 +03:00
dependabot[bot] 5d7e893a5a chore(deps-dev): bump @changesets/cli from 2.29.7 to 2.29.8 (#1938)
Bumps [@changesets/cli](https://github.com/changesets/changesets) from 2.29.7 to 2.29.8.
- [Release notes](https://github.com/changesets/changesets/releases)
- [Commits](https://github.com/changesets/changesets/commits)

---
updated-dependencies:
- dependency-name: "@changesets/cli"
  dependency-version: 2.29.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 11:00:31 +03:00
Fahreddin Özcan 18b3292d01 fix(cli): add token refresh and centralize auth constants (#2210)
* fix(cli): add token refresh support and centralize auth constants

Expired OAuth tokens are now automatically refreshed via getValidAccessToken()
instead of silently failing. CLI_CLIENT_ID moved to constants.ts to avoid
duplication across auth.ts and setup.ts.

* refactor(cli): internalize baseUrl and clientId in refreshAccessToken

Make refreshAccessToken a private function that resolves getBaseUrl()
and CLI_CLIENT_ID internally instead of requiring them as parameters.

* test(cli): add unit tests for auth utilities and commands

Add comprehensive vitest test suite covering OAuth PKCE flow, token
persistence, token refresh, and CLI auth commands (login/logout/whoami).

* chore: add changeset for CLI auth improvements

* refactor: move CLI auth tests to src/__tests__/

Move auth test files from colocated __tests__ directories to a
centralized src/__tests__/ directory, adjusting mock import paths
accordingly.
2026-03-16 13:03:33 +03:00
Fahreddin Özcan 8ba484cdc8 feat(cli): add interactive skill generation wizard (#1572)
* generate skills

* feat: add generate questions methods

* feat(cli): improve skill generation UX with streaming feedback

- Add real-time query results display during generation
- Collapse answered questions to show summary
- Separate query phase spinner from generation spinner
- Add skill preview with expand option
- Remove legacy generateSkill function
- Clean up redundant comments

* feat(cli): improve skill generation UX with streaming feedback

- Add real-time query results display during generation
- Collapse answered questions to show summary
- Separate query phase spinner from generation spinner
- Add skill preview with expand option
- Remove legacy generateSkill function
- Clean up redundant comments

* feat(cli): optimize feedback regeneration and clean up UI

- Add previousContent to StructuredGenerateInput for efficient feedback
- Remove redundant "Selected X libraries" log message
- Consolidate menu options (remove "Regenerate completely")
- Update feedback prompt with skip hint

* feat(cli): add skill generation with quota and improved display

- Add skill quota checking before generation
- Fix tool result display timing issue
- Show library project IDs in selection to avoid confusion
- Improve generation spinner with query log display

* docs(cli): add 0.2.0 changelog entry

* fix(cli): switch userinfo endpoint from dev to production

* docs(cli): add skill generation and auth sections to README

* fix(sdk): increase timeout for sequential search test

* chore(cli): replace manual changelog with changeset for skill generation
2026-01-29 11:46:45 +03:00
Fahreddin Özcan aacfd3165a feat(cli): add OAuth 2.0 support with login, whoami and logout commands (#1573)
* feat: add oauth 2.0 support with login,whoami and logout commands

* ci: lockfile

* fix: address security and port issues in OAuth flow

- Fix XSS vulnerability by escaping HTML in error page messages
- Change callback port from 9876 to 52417 (high ephemeral range, less likely to conflict)

* refactor: clean up auth code and remove unnecessary comments

- Remove obvious comments that duplicate function names
- Extract duplicate expiration display logic into printTokenExpiration helper
- Simplify logoutCommand (remove async, inline condition)
- Remove unused saved_at field from token storage

* fix: address auth bugs and remove unused code

Bug fixes:
- whoami now shows "Session expired" instead of misleading "Logged in" when token is invalid
- expires_at calculation preserves existing value instead of overwriting
- Login check now allows re-login when tokens are expired with no refresh token

Simplifications:
- Remove unused getAccessToken and refreshAccessToken functions
- Simplify printTokenExpiration (remove unused showExpired parameter)

* refactor: improve whoami output formatting

- Align labels using padEnd for consistent output
- Remove expiration time display from whoami
- Show login status first, then fetch user details

* chore: add changeset for OAuth feature
2026-01-28 14:36:39 +03:00
Fahreddin Özcan 1fbd3d906c feat: add skills registry CLI for managing AI coding agent skills (#1505)
* feat: add skills cli

* chore: cleanup comments

* feat: update commands with new apis

* chore: remove unnecessary deps

* chore: update aliases and package name

* feat: remove /owner/repo/skill convention

* fix: cleanup, path and param handling

* feat(cli): multi-keyword search and Claude symlink priority

- Support multi-keyword search: `ctx7 skills search react hooks`
- Prioritize Claude to receive original files when installing to multiple IDEs

* refactor(cli): rename project to repository, reorder options

- Rename "project" argument to "repository" in help text
- Reorder options: --all and --global first, then IDE options
- Simplify IDE option descriptions to show client name and path
- Update internal variable names (project → repo)

* refactor(cli): flatten search results display

- Remove grouping by repository in search results
- Remove "Select all from repo" option
- Show each skill on single line with repo name in parentheses
- Simplify selection handling

* docs(cli): improve main help output with detailed examples

- Add section headers for commands and examples
- Include npx prefix in all example commands
- Group examples by use case (search, install, manage)
- Add comments explaining each example group
- Add link to context7.com

* refactor(cli): simplify banner, add examples to --help

Move detailed examples to --help output using addHelpText().
Simplify the no-argument banner to show only quick start examples.

* chore: remove unnecessary package
2026-01-21 12:25:04 -08:00
dependabot[bot] 02148ff13c chore(deps): bump zod from 3.25.76 to 4.3.4 (#1349)
* chore(deps): bump zod from 3.25.76 to 4.3.4

Bumps [zod](https://github.com/colinhacks/zod) from 3.25.76 to 4.3.4.
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v3.25.76...v4.3.4)

---
updated-dependencies:
- dependency-name: zod
  dependency-version: 4.3.4
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: bump zod for mcp and tools-ai-sdk

* ci: update test .env source

* chore: match zod versions

* chore: add changeset

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-01-09 12:46:43 +03:00
Fahreddin Özcan ef82f3057c CTX7-884: OAuth Support for MCP (#1176)
Co-authored-by: enesgules <abdullah.enes.gules@gmail.com>
2026-01-08 20:17:19 +03:00
Fahreddin Özcan 07a53dc940 chore(deps): upgrade ai to v6 and @ai-sdk/amazon-bedrock to v4 (#1376) 2026-01-07 14:26:40 +03:00
dependabot[bot] d1252b75df chore(deps-dev): bump @types/node from 22.19.1 to 25.0.3 (#1347)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.19.1 to 25.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.0.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-01-07 11:31:57 +03:00
Fahreddin Özcan f820f7fecd CTX7-879: Context7 Vercel AI SDK Tools (#1122)
* feat: context7 vercel ai sdk tools package

* ci: remove master target condition on test action

* ci: manual actions trigger for test

* ci: always run all tests

* update tests and imports

* ci: typecheck command

* fix: tests

* docs: add readme

* update folder structure and tool descriptions

* tests: fix test env vars

* ci: bump pnpm version

* update ai sdk step count api

* Add stopWhen to docstring examples

* update tests

* update prompt name

* update context7 agent name

* update tool description var to description

* make context7agent config optional

* ci: add changeset

* make context7-sdk peer deps

* update pnpm-lock.yaml

* update package name to @upstash/context7-tools-ai-sdk

* remove check workflow

* update pnpm lock

* make the agent a class instead of function

* replace all name instances

* add agent generate test

* simplify agent config

* fix refs
2025-12-09 14:45:01 -08:00
Fahreddin Özcan 5e11d358af CTX7-855: TypeScript SDK (#1061)
* init sdk and monorepo

* init sdk and monorepo

* comment cleanup

* remove bun.lock

* cleanup: remove sdk package and deps

* update tsconfigs

* chore: add temp changelog

* ci: update scripts

* ci: update github workflows

* fmt: workflows

* fix: search libraries response type

* ci: update pack-mcpb script

* feat: init ts sdk

* feat: add commands and http client

* update keywords and author

* update eslint config for mcp

* include license and readme in build

* update release.yaml

* add readme symlink

* include readme in mcp package

* chore: add canary release workflow and update configs

* chore: format files

* ci: add changeset check workflow

* canary release trigger

* ci: login to npm before release

* bump mcp version on package

* remove pr trigger from canary release

* ci: remove package input

* finalize sdk with tests and proper types

* address reviews

* add client tests

* feat: use env var automatically

* add docs

* remove docs changes (moving to separate PR)

* remove docs

* update build config with tsup

* cleanup comments

* fix error hangling on http client

* minor fixes

* address reviews

* add txt pagination feature

* remove unnecessary types

* update default format

* cleanup

* add mcp lint command

* update format scripts

* fix: update eslint and tsconfig with update

* add readme

* make default format json

* change docType to mode

* update basic usage

* update changeset
2025-11-28 16:16:30 +03:00
Fahreddin Özcan 6255e26677 CTX7-854: Migrate to pnpm monorepo (#1058)
* init sdk and monorepo

* init sdk and monorepo

* comment cleanup

* remove bun.lock

* cleanup: remove sdk package and deps

* update tsconfigs

* chore: add temp changelog

* ci: update scripts

* ci: update github workflows

* fmt: workflows

* fix: search libraries response type

* ci: update pack-mcpb script

* update keywords and author

* update eslint config for mcp

* include license and readme in build

* update release.yaml

* add readme symlink

* include readme in mcp package

* chore: add canary release workflow and update configs

* chore: format files

* ci: add changeset check workflow

* canary release trigger

* ci: login to npm before release

* bump mcp version on package

* remove pr trigger from canary release

* ci: remove package input

* add mcp lint command

* update format scripts
2025-11-28 15:18:33 +03:00