* feat(client): support mixed OAuth servers
* fix(inspector): pause mixed-auth tool calls
* Revert "fix(inspector): pause mixed-auth tool calls"
This reverts commit 9bac9ddfe7.
* chore: finalize mixed OAuth changeset
* docs: explain mixed OAuth client flows
* fix: bound mixed auth metadata discovery
* docs(server): add runnable mixed oauth example
* fix(inspector): recover stale local connections
* fix(inspector): resume tools after mixed auth
* fix: address mixed auth review feedback
* fix(inspector): scope mixed auth retries
* test(inspector): remove jsdom-only regressions
* chore: enter canary prerelease mode
* chore(typescript): version packages (canary)
* fix(inspector): stream v2 subscription acknowledgements
* fix(client): discover mixed auth after ready
* test(client): preserve mocked connection compatibility
* fix(client): defer mixed auth discovery until ready
* fix(client): discover mixed auth after ready paint
* perf(client): expose tools before auxiliary inventories
* fix(client): refresh mixed auth discovery after reconnect
* chore(typescript): version packages (canary)
* fix(client): make codeMode custom executor functions actually work (#2123)
* fix(client): make codeMode custom executor functions actually work
`_ensureCodeExecutor()` handled a function-valued `codeMode.executor` by
assigning `this._customCodeExecutor` and then throwing
"Custom executor function should be handled in executeCode". Since
`executeCode()` read that field *before* calling `_ensureCodeExecutor()`,
and only `_ensureCodeExecutor()` ever populated it, the first
`executeCode()` call always rejected and only the second succeeded.
`searchTools()` had no such fallback, so it rejected on every call --
including via the `search_tools` meta tool on `CodeModeConnector`. Because
`_codeExecutor` stayed null, `close()` also skipped executor cleanup.
Route function executors through a new `FunctionCodeExecutor` adapter so
they participate in the normal executor lifecycle, and drop the now-unused
`_customCodeExecutor` field and its pre-check in `executeCode()`.
Also fix `detail_level` validation in `CodeModeConnector.callTool`: it
used `detailLevel in ["names", "descriptions", "full"]`, and `in` tests
property keys, so an array literal only has `"0"`/`"1"`/`"2"`/`"length"`.
Every valid detail level failed the guard and was silently rewritten to
`"full"`, so an agent requesting `"names"` received full input schemas for
every tool. Replaced with a `Set` membership test.
Adds 10 unit tests: first-call success, timeout forwarding, `searchTools`,
`close()` cleanup, the `BaseCodeExecutor` instance path, each valid
`detail_level`, and the unknown/omitted fallbacks.
Closes#2122
* fix(client): preserve `this` for custom executors, tighten tests, document the contract
Addresses review feedback on the code-mode custom-executor fix.
The `this` binding regression is real -- I measured it both ways. On the
pre-fix code the executor function was invoked as
`this._customCodeExecutor(code, timeout)`, so a non-arrow function saw the
`MCPClient` as its `this`; through the new adapter it saw the
`FunctionCodeExecutor`. `FunctionCodeExecutor.execute` now calls
`this.fn.call(this.client, ...)` so a `function`-form executor keeps the same
context it had before, and a test asserts it.
Two tests were weaker than their titles claimed:
- the `searchTools` test ran against an empty client, so it only proved the
call did not throw. It now registers a stub session with one tool and
asserts the full `{ meta, results }` payload, including the namespace and
the tool's `input_schema`.
- the `close()` test only asserted the promise resolved, which would pass
even if cleanup were skipped. It now spies on the resolved executor's
`cleanup()` and asserts it ran exactly once.
Documentation: the API reference listed one "Custom" executor row saying to
implement `execute()` + `cleanup()`, which is only true for the
`BaseCodeExecutor` subclass form. Split it into separate class and function
rows, add the `CodeExecutorFunction` signature to the types block, and add a
worked example to the code-mode guide (current and v2) stating the `this`
context and that the function owns its runtime cleanup.
* docs(client): use a non-arrow custom executor in the code-mode example
The example demonstrated the documented `this` context with an arrow function,
which has lexical `this` and therefore cannot observe it. Switched to
`async function (this: MCPClient, code, timeout)` and had it actually call
`this.getServerNames()`, so the snippet exercises the contract it describes.
Type-checked the snippet shape against the real `MCPClient` type with
`tsc --noEmit` before committing.
Also reworded the surrounding paragraph: the `this` binding is specific to the
non-arrow form, whereas the cleanup-ownership rule applies to every custom
function.
* docs(client): drop v1 code-mode custom executor docs
This change is v2-only; keep the custom-executor contract on the v2 docs path.
* chore(typescript): version packages (canary)
* fix(create-app): sanitize the npm name for named projects, not just "." (#2209)
deriveProjectInfo only ran sanitizePackageName on the "." branch. A named
project passed the raw argument straight through as packageName, which is
then written into package.json and substituted into the template's index.ts.
The CLI rejects path separators, ".." and a few protected names, but not
spaces, quotes or capitals, so `create-mcp-use-app 'My "App"'` emitted
`name: "My "App""` in index.ts, which is not valid TypeScript.
Sanitize on both branches. The directory still uses the name as typed.
* chore(typescript): version packages (canary)
* fix: enable skills tab after HMR (#2220)
* chore(typescript): version packages (canary)
* fix(create-app): strip leading underscores when sanitizing a package name (#2221)
sanitizePackageName removed leading dots and dashes but not underscores, so
create-mcp-use-app _foo wrote "name": "_foo" into package.json.
npm publish rejects that outright:
npm error code EINVALIDPACKAGENAME
npm error Invalid package name "_foo": name cannot start with an underscore.
Widen the leading-character class to [._-] and cover both the sanitizer and a
named project starting with an underscore.
Closes#2219
* chore(typescript): version packages (canary)
* fix(client): surface auth for protected operations
* fix(inspector): resume mixed-auth chat tools (#2226)
* chore(typescript): version packages (canary)
* fix: harden stable mixed-auth flows
---------
Co-authored-by: Enrico <2827496+tonxxd@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: LHMQ878 <72402929@cityu-dg.edu.cn>
Co-authored-by: Ayaan Gazali <ayaangazali.work@gmail.com>
The skills auth references pointed at
libraries/typescript/packages/mcp-use/examples/server/oauth/<provider>,
which is the deleted v1 package path. Those examples live at
libraries/typescript/packages/server/examples/auth/<provider> in v2.
README.md and packages/server/README.md both linked the self-hosting guide
to a Mintlify preview deployment, mcpuse-codex-v1-v2-docs-split.mintlify.site,
which 404s. The server README ships with the published package.
Reported in #2210.
knip cannot follow #mcp-use-skills-loader, which resolves into another
workspace package (@mcp-use/cli/internal/skills-loader). Its sibling
#mcp-use-node-http is already listed in ignoreUnresolved; this one was
never added when the skills work landed.
That unresolved import was the only knip error, since exports and types
are configured as warnings, so knip goes from exit 1 to exit 0.