`deepagents-code` now supports experimental plugin marketplaces with
namespaced skills and MCP servers. Enable with
`DEEPAGENTS_CODE_EXPERIMENTAL=1`.
Docs: https://github.com/langchain-ai/docs/pull/4905
---
`deepagents-code` can now manage experimental plugin marketplaces and
load installed plugins that contribute namespaced skills and MCP
servers. The new plugin manager establishes the `tui/modals`,
`tui/screens`, and `tui/widgets` UI convention, with colocated styling
and focused state/content modules.
- Supports local, GitHub, Git, and marketplace JSON sources.
- Adds install, enable, disable, uninstall, and safe marketplace removal
through `/plugins` and `dcode plugin`.
- Reloads plugin skills and plugin MCP configuration with `/reload` when
experimental mode is enabled.
- Namespaces plugin skills as `{plugin_id}:{skill_name}` through a
code-local `PluginSkillsMiddleware` adapter, so no SDK changes are
required.
Made by [Open
SWE](https://openswe.vercel.app/agents/019f5dea-0f1f-73fe-9803-32d1b13fbd4c)
---------
Signed-off-by: Johannes du Plessis <johannes@langchain.dev>
Co-authored-by: Alexander Olsen <aolsenjazz@gmail.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: open-swe[bot] <215916821+open-swe[bot]@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Deep Agents Code now supports amending, pausing, and resuming persistent
goals while keeping their status visible above the input. Amendments are
reviewed before they apply, and paused goals remain saved without
driving work or grading until resumed.
---
Deep Agents Code now keeps goals visible above the input and lets users
steer ongoing goal-driven work without cancelling the current task and
replaying work.
- `/goal amend <feedback>` proposes coordinated updates to the objective
and acceptance criteria while preserving unaffected criteria and
explicit constraints. The inline review supports accepting, editing,
rejecting, or cancelling the proposal before it becomes canonical state.
- `/goal pause` saves the goal without letting it drive work or grading.
`/goal resume` continues from the existing conversation and checkpoint
rather than resubmitting the original task.
- The goal panel shows the current objective and its active, paused,
blocked, or completed state.
- Ordinary messages submitted during active goal work retain queue and
interruption ordering and steer the next turn under the current goal.
Goal checkpoint changes wait for graph execution and turn-end
reconciliation to reach a safe boundary. A goal update accepted during
execution applies after the current turn finishes and before a
subsequent turn begins. If a user message is already queued, it runs
under the updated goal before any synthetic continuation turn.
## User stories and before/after examples
<details>
<summary>Amend a goal without restarting the work</summary>
**User story:** As a user whose requirements change during a
long-running task, I want to update the current objective and acceptance
criteria without discarding context or repeating work that is already
complete.
**Before**
1. I start a goal to “Add CSV and JSON export with tests.”
2. Partway through, I decide that JSON export is out of scope and CSV
must also support streaming.
3. There is no goal-specific amendment flow. I must replace or clear the
goal and describe the revised work again, without a review that
preserves unaffected criteria and constraints.
**After**
1. I run `/goal amend Remove JSON export, add streaming CSV support, and
keep the existing CSV test requirements`.
2. dcode drafts a coordinated revision of both the objective and
criteria while preserving requirements that the feedback did not change.
3. The inline review lets me accept the proposal, edit its criteria,
request another revision, or cancel it.
4. Once accepted, dcode continues from the existing conversation and
work instead of replaying the original task.
</details>
<details>
<summary>Pause a goal while keeping it available to resume</summary>
**User story:** As a user who needs to switch to unrelated work
temporarily, I want to pause my current goal so it remains saved but
does not affect the intervening prompts.
**Before**
1. I have an active multi-turn goal.
2. To stop that goal from driving later work and grading, I must clear
it.
3. Returning to it requires creating the goal again and redrafting its
acceptance criteria.
**After**
1. `/goal pause` saves the objective and criteria with a paused status.
2. Unrelated prompts run without the paused goal driving work or
grading.
3. `/goal resume` reactivates the saved goal and continues from the
existing conversation and checkpoint without resubmitting the original
objective.
</details>
<details>
<summary>See the current goal and lifecycle state while
working</summary>
**User story:** As a user working across multiple turns, I want the
current goal and its status to remain visible so I can tell what dcode
is working toward and whether it needs my input.
**Before**
The current objective is not persistently visible above the input. I
must use `/goal show` or infer its state from earlier transcript
messages.
**After**
- A persistent panel above the input shows the current objective.
- The panel distinguishes active, paused, blocked, and completed states.
- The display follows checkpoint restoration and lifecycle changes, so
reopening a thread or changing the goal state keeps the visible status
aligned with the saved goal.
</details>
<details>
<summary>Apply in-flight goal changes without reordering queued
input</summary>
**User story:** As a user who amends a goal while the agent is still
working, I want the current turn to finish safely and my next message to
run under the accepted revision in the order I submitted it.
**Before**
There is no accepted amendment to coordinate with graph execution,
checkpoint writes, and messages already waiting in the queue.
**After**
1. If I accept a goal update during an active turn, dcode waits until
that turn and its reconciliation finish before changing the saved goal.
2. The accepted update is applied before a subsequent turn begins.
3. If I already submitted another message, that message runs first under
the updated goal; dcode does not race ahead with a synthetic
continuation turn.
</details>
Deep Agents Code now supports `/tools`, which lists the built-in and MCP
tools available to the current agent.
---
Adds an interactive `/tools` slash command to the `deepagents-code` TUI
so users can see the tools available to the current agent, grouped into
built-in tools and tools from each MCP server. MCP servers that are
disabled, need login, or failed to load are shown separately instead of
disappearing from the list.
For managed sessions, built-in tools are enumerated off the UI thread
with a credential-free agent compile. For preconfigured local agents,
`/tools` inspects the active graph directly so custom tool sets remain
authoritative. When a custom or remote agent cannot be inspected, the
command explains that limitation rather than incorrectly reporting that
no tools are available.
MCP entries reuse the metadata loaded for the running agent instead of
starting discovery inside Textual's live event loop. If `/mcp`
configuration changes are waiting for a reconnect, `/tools` keeps using
the pre-change snapshot so its output continues to match the tools the
agent can currently invoke.
The catalog is rendered as a chat message, like `/tokens`, and is
discoverable through `/help`, command completion, and a startup tip.
Made by [Open
SWE](https://openswe.vercel.app/agents/626ca1ec-726e-58e8-7dae-4e85363c953d)
## References
- Plan:
https://openswe.vercel.app/agents/626ca1ec-726e-58e8-7dae-4e85363c953d/plan
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Deep Agents Code now includes an in-app Debug Console. Press `Ctrl+\` to
inspect session details and filter, view, or copy recent application
logs without enabling file-based debug logging.
---
Debugging client-side TUI problems currently requires restarting with
file logging enabled and tailing a log in another terminal. This adds an
in-app Debug Console, modeled on Mistral Vibe's console, so users can
inspect session state and recent application logs without leaving the
TUI.
Open the console with `Ctrl+\` or the hidden `/debug` command. It shows
a point-in-time snapshot of the version, model, thread, working
directory, auto-approve state, sandbox, MCP servers, token usage, and
debug-log path. Below that, it tails recent `deepagents_code.*` records
from an always-on bounded in-memory buffer and supports filtering by
severity.
The buffer captures `INFO` and above by default, or the level selected
with `DEEPAGENTS_CODE_LOG_LEVEL`. `DEEPAGENTS_CODE_DEBUG` continues to
enable append-only file logging and defaults capture to `DEBUG`.
`Ctrl+L` clears the current console view without clearing the underlying
buffer; `c` copies the visible filtered records retained since the last
clear, and clicking a record copies only that record.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
The `dcode` TUI now supports `/threads -r [ID]` to resume a previous
thread in place, and `/clear` shows the thread you just left with a
one-step resume hint.
---
After `/clear` mints a new thread, there was no low-friction path back
to the thread you just left — the id was dropped and only the modal
`/threads` selector could find it again.
This adds an in-TUI equivalent of the launch-time `-r` flag rather than
a bespoke one-level `/go-back`, keeping parity with muscle memory users
already have and composing better:
- `TextualSessionState` now records the outgoing thread as
`previous_thread_id` on every `reset_thread` (`/clear`).
- `/clear` output names the previous thread (with the same clickable
LangSmith-link upgrade as the new-thread line) and prints a resume hint.
- `/threads -r [ID]` resumes without opening the modal: bare `-r`
returns to the previous thread (falling back to the most recent thread
on disk), and `-r <ID>` resumes a specific thread. It reuses the
existing `_resume_thread` machinery, so behavior matches selecting a
thread in the modal. Because `/threads` is an `IMMEDIATE_UI` command,
only the bare form bypasses the busy queue — `/threads -r …` is queued
while the agent is running, so a resume never races an active turn.
Autocomplete gains an `[-r [ID]]` argument hint and a splash tip
advertises the shortcut.
Made by [Open
SWE](https://openswe.vercel.app/agents/b717ea48-7edd-8049-95cc-64384c56e8a8)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
New users were confused that `/offload` (alias `/compact`) only
"offloads" context, when it actually runs an LLM summarization of older
messages before writing the originals to a recovery file. This updates
the slash-command description to mention summarization, staying under 60
characters ("Summarize and offload older messages to free context", 52
chars), and regenerates the `COMMANDS.md` catalog to match.
Made by [Open
SWE](https://openswe.vercel.app/agents/d78e6bda-ad23-13f1-e566-a01f25a05364)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Closes#3491
---
Adds a `/effort` slash command for configuring reasoning effort on the
current model. The command resolves provider/model-specific effort
levels, applies the selected effort through the existing per-session
model-params override path, and rejects unsupported levels for the
active model.
The bare `/effort` command opens an interactive selector matching the
existing modal selector UX. Users can also pass an effort level
directly, or clear/reset the per-session effort override. The active
effort is shown next to the model in the status label and updates when
the effort is set, cleared, or the model is switched.
This also fixes provider credential switching so gateway-provisioned
custom auth headers, such as `ANTHROPIC_CUSTOM_HEADERS`, are cleared
when returning to a provider-native key and endpoint.
## Release note
Users can now configure supported reasoning effort levels with `/effort`
and see the active effort displayed next to the current model. Switching
back to a provider-native credential now clears gateway custom-header
auth for supported providers.
## Video
https://github.com/user-attachments/assets/4a347939-b5e8-4fb6-bd0d-c50635017593
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
Closes#4404
Deep Agents Code now uses clearer acceptance-criteria grading messages,
lets the rubric grader inspect offloaded tool-result evidence referenced
in the transcript, defers the rubric iteration default to the SDK, and
adds interactive grader controls for goals and rubrics.
---
This improves the goal and rubric grading UX so the status messages
describe the acceptance criteria check rather than implying the rubric
text itself is wrong. When grading fails with `needs_revision`, the UI
now says the changes need revision. Iteration numbers are hidden unless
the user explicitly configured an iteration cap, keeping the default
`/goal` and `/rubric` flow less noisy.
Deep Agents Code no longer sets its own default rubric iteration cap. If
the user does not pass `--rubric-max-iterations`, dcode omits
`max_iterations` and lets `RubricMiddleware` use the SDK default.
Explicit `--rubric-max-iterations` values are still forwarded, and the
SDK now accepts any positive cap instead of enforcing the previous hard
upper bound.
The rubric grader also gets a narrow `read_file` tool that can only
inspect `/large_tool_results/` paths explicitly referenced in the
transcript. This gives the grader a way to verify offloaded evidence
without exposing broader filesystem access or waiting for an SDK-level
transcript reconstruction change.
The TUI now exposes `/rubric max-iterations <N|clear>` and `/goal
max-iterations <N|clear>` for interactive sessions. Changing the value
restarts the app-owned LangGraph server so the construction-time
`RubricMiddleware` setting takes effect. `/goal model
[provider:model|clear]` and `/goal max-iterations` are goal-first entry
points for the same shared grader settings surfaced by `/rubric model`
and `/rubric max-iterations`.
Closes#3548
---
The chat surface had two nits: message blocks didn't line up with the
input box (the chat container had horizontal padding the input border
didn't), and the vertical scrollbar was always on unless the terminal
was in ASCII mode — with no way for a user to hide it on a capable
terminal.
This makes the chat area flush with the input box and adds a
user-toggleable scrollbar so people can choose whether the scrollbar is
visible.
- `#chat` drops its horizontal padding so message blocks span the same
full width as the input box border below.
- The input box and status bar switch from `$surface` to `$background`
so they blend with the app background instead of reading as a separate
band.
- New `/scrollbar` slash command toggles the vertical scrollbar on or
off for the current session and persists the choice to
`[ui].show_scrollbar` (and `DEEPAGENTS_CODE_SHOW_SCROLLBAR` for an
env-var override). It defaults to off, matching the look of other coding
CLIs; wheel and keyboard scrolling still work when the scrollbar is
hidden. ASCII-mode terminals keep the scrollbar hidden regardless of the
preference, since they can't render the glyphs.
## Screenshots
### Before
<img width="861" height="632" alt="Screenshot 2026-06-29 at 5 38 10 PM"
src="https://github.com/user-attachments/assets/4add48dd-f761-4edf-a2a1-aefa9c6e4697"
/>
### After
<img width="862" height="634" alt="Screenshot 2026-06-29 at 5 36 48 PM"
src="https://github.com/user-attachments/assets/d7ecb5b7-87b3-4122-8b28-bc61b248b670"
/>
<img width="857" height="634" alt="Screenshot 2026-06-29 at 5 37 19 PM"
src="https://github.com/user-attachments/assets/2f656c5b-5509-4326-a68a-ad2a3a59fd6a"
/>
---------
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
Adds rubric-driven acceptance criteria to Deep Agents Code and layers a
goal workflow on top of it.
A rubric is the explicit definition of done. Use it when you already
know the criteria the agent should satisfy before it considers the work
complete. Criteria can be sticky for the thread, one-shot for the next
turn, or loaded from a file. While the agent works, the TUI shows
grading lifecycle messages so the user can see when the work is being
checked, revised, satisfied, or stopped.
Usage examples:
```text
/rubric set tests pass; no unrelated files changed; help text is updated
/rubric next only change the auth callback; do not refactor unrelated code
/rubric file acceptance.md
/rubric show
/rubric clear
```
A goal is the objective-oriented workflow. Use it when you know the
outcome, but want `dcode` to propose acceptance criteria before
execution. `/goal <objective>` asks the model to draft criteria and
displays them in an inline review prompt. The user can accept the
criteria, edit them directly, reject them with feedback to regenerate,
or cancel. Accepted goal criteria become the sticky rubric for the
thread.
Usage examples:
```text
/goal add OAuth refresh handling
/goal show
/goal clear
```
The `--goal` CLI flag starts the same goal-review workflow when
launching the TUI. It is intentionally interactive: the generated
criteria must be reviewed before execution. After the user accepts the
proposal, the accepted goal is sent as the first task.
```bash
dcode --goal "add OAuth refresh handling"
```
`--goal` cannot be combined with `-n`, `-m`, `--skill`, or `--rubric`.
For non-interactive/headless runs, users should provide criteria
explicitly with `--rubric` instead:
```bash
dcode -n "implement OAuth refresh handling" --rubric "tests pass; no unrelated files changed"
dcode -n "implement OAuth refresh handling" --rubric @acceptance.md
```
Accepted goal/rubric state is persisted on the thread and restored on
resume. For example, a user can set `/goal add OAuth refresh handling`,
accept the proposed criteria, quit the TUI, and later resume the same
thread with the goal and criteria still active. That matters because the
acceptance criteria continue to guide future turns and remain visible in
`/goal show` instead of becoming hidden context that disappears between
sessions.
When the agent believes the goal is done, it does not get to declare
victory on its own. For example, after implementing OAuth refresh
handling, the agent can ask to mark the goal complete with evidence such
as "tests pass." `dcode` keeps that request pending until the rubric
check finishes. If the rubric still needs revision, the goal stays
active and the user sees why it was not completed. If the rubric is
satisfied, auto-approve mode records the completion automatically;
manual mode asks the user before changing the goal status. This keeps
the user's accepted criteria as the source of truth for whether the goal
is actually finished.
The active criteria and goal are also visible to the agent through
constrained tools. `get_rubric` lets the agent inspect the current
criteria and whether they came from a goal, a sticky rubric, or the
current invocation. `get_goal` lets it inspect the active objective,
status, criteria, and any prior note. `update_goal` lets it report when
it believes the goal is `complete` or `blocked` with evidence. The
constraints matter: the agent can read criteria and update progress, but
it cannot create, pause, resume, clear, or replace goals. Those
lifecycle actions stay user/system controlled so the model cannot
silently redefine or remove the user's objective.
LangSmith tracing can now be configured directly from `/auth` (and
`dcode auth set langsmith`), including enabling tracing, a temporary
opt-out via `DEEPAGENTS_CODE_LANGSMITH_TRACING=false`, and a custom
project name.
---
Wires LangSmith tracing into the `/auth` surface as a configurable
service, mirroring how Tavily is already handled. Storing a LangSmith
key via `/auth` persists it to the credential store, bridges it onto
`LANGSMITH_API_KEY`, and opts the user into tracing — so configuring
tracing no longer requires exporting environment variables before
launch.
Key behaviors:
- A stored key turns tracing on by default. An explicit falsy tracing
flag (most simply `DEEPAGENTS_CODE_LANGSMITH_TRACING=false`) is honored
as a non-destructive, session-scoped opt-out — pause tracing without
deleting the key. The TUI prompt surfaces this path.
- An optional project name (advanced field in the TUI prompt,
`--project` on `dcode auth set`) routes traces to a custom
`LANGSMITH_PROJECT`; the default stays `deepagents-code`.
- Services are now surfaced in `dcode auth list`/`status` (this also
fixes a pre-existing gap where Tavily was invisible to the CLI).
- Bootstrap reordered so a `/auth`-stored key is applied before
orphaned-tracing detection, keeping tracing alive instead of being
disabled.
Made by [Open
SWE](https://openswe.vercel.app/agents/2ba1485c-7c70-59b6-82bf-18302c214c6c)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
`/update --deps` (and a prompt on `/update` when already current)
refreshes dependencies to their newest in-range versions without waiting
for a new release.
---
Dependencies are range-pinned, so newer in-range releases (e.g. a fresh
`langchain-openai`) are already permitted by a published
`deepagents-code` — but `/update` only ever checked the dcode version on
PyPI and dead-ended at "Already on the latest version", so users had to
drop to raw `uv` to pull them in.
This makes the refresh first-class in the TUI:
- `/update --deps` re-resolves the tool environment via `uv tool install
-U deepagents-code==<current>` (`perform_dependency_refresh`), so
compatible dependency releases are picked up without crossing to a newer
app version. If a dcode update also happens to be available, `/update
--deps` first asks (via `UpdateBeforeDependenciesConfirmScreen`) whether
to take the app update instead; declining continues with the deps-only
refresh.
- Plain `/update`, when dcode is already current, computes a preflight
dry-run plan first and only then offers the refresh through a
confirmation modal (`RefreshDependenciesConfirmScreen`, which previews
the planned changes) instead of dead-ending.
- Both paths parse uv's environment diff and report exactly which
dependencies moved; a normal version bump also surfaces any dependency
changes that rode along.
Editable (and other non-uv) installs are still refused, and a dep
refresh stays explicit/confirmed (it is not folded into silent
background auto-update), consistent with the "announce before running
shell" rule. `uv tool install`/`upgrade` has no `--dry-run`, so the
preflight plan is computed against the running tool environment with `uv
pip install --dry-run --python <sys.executable>`
(`perform_dependency_refresh_dry_run`), using the same pinned
requirement, extras, and preserved `--with` packages as the real
refresh.
Made by [Open
SWE](https://openswe.vercel.app/agents/d64c7415-11cc-947f-f5f3-67aca0ec21ed)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
New-contributor onboarding currently requires stitching knowledge
together from `AGENTS.md`, per-package `Makefile`s, and external docs,
and neither the cross-layer request flow nor the `libs/code` process
model is mapped anywhere in the repo.
This adds:
- Root `ARCHITECTURE.md` (the three-layer `deepagents` → `create_agent`
→ LangGraph stack and request flow) and `DEVELOPMENT.md` (a single
bootstrap + command reference), cross-linked from `README.md` and
`libs/README.md`.
- `libs/code/ARCHITECTURE.md` (process model, interactive/headless
request lifecycles, module map, and a "where do I change X" cheat
sheet), linked from `DEV.md` and `AGENTS.md`.
Made by [Open SWE](https://openswe.vercel.app)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Makes `/restart` a public `deepagents-code` slash command so users can
discover it in autocomplete and `/help` while preserving its
always-immediate recovery behavior.
Made by [Open SWE](https://openswe.vercel.app)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
When a configured model's provider package can't be imported, the model
is built *before* the LangGraph server starts, so construction fails and
the app holds a `_server_startup_error` state that parks queued slash
commands until a successful start drains them. `/install` — the command
that installs the missing package — is `QUEUED`, so it was trapped
behind the very failure it repairs: typing `/install <pkg>` appeared to
hang because it never ran. `/model` and `/auth` already escaped this
wedge via `IMMEDIATE_UI`, but the package-recovery path did not.
Adds a first-class way to install optional extras into an existing
`dcode` install without dropping back to a shell or guessing package
names. Surfaces it as both the `/install <extra>` slash command (in-app)
and a `dcode --install EXTRA` headless flag, and rewrites the ecosystem
of `pip install …` recovery hints to point at the new flow.
Closes#3474
---
deepagents-code: `F2` in the `/mcp` viewer now disables (or re-enables)
the selected MCP server. Disabled servers persist across sessions and
are skipped at load time.
_Opened collaboratively by Mason Daugherty and open-swe._
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Mason Daugherty <61371264+mdrxy@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
## Description
Two related `/mcp` UX improvements in `deepagents-code`:
1. `unauthenticated` MCP servers now float to the top of the `/mcp`
viewer (stable sort within status groups) so the actionable login
prompts are visible without scrolling past `ok` servers.
2. After a successful MCP login, the LangGraph server no longer restarts
automatically. Users see a confirmation modal
(`MCPReconnectPromptScreen`) and can choose "Reconnect now" or "Later" —
the latter lets them authenticate with multiple servers before paying
the restart cost once. A new `/mcp reconnect` subcommand triggers the
deferred restart on demand.
## Release Note
Surface unauthorized MCP servers at the top of `/mcp` and prompt for
confirmation before reconnecting after an MCP login (use `/mcp
reconnect` to apply deferred logins).
## Test Plan
- [ ] Open `/mcp` with a mix of `ok` and `unauthenticated` servers;
verify unauthenticated servers render first.
- [ ] Complete an MCP OAuth login; verify the reconnect modal appears
instead of an automatic restart.
- [ ] Choose "Later", authenticate with a second server, then run `/mcp
reconnect`; verify a single restart picks up both new tokens.
_Opened collaboratively by Mason Daugherty and open-swe._
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Mason Daugherty <61371264+mdrxy@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Builds on #3468Closes#3116
---
MCP OAuth login now runs entirely inside the TUI — no need to `dcode mcp
login <server>` in a separate terminal. Either `/mcp login <server>` or
activating an unauthenticated server row in the `/mcp` viewer kicks off
the same modal flow. On success, the local LangGraph subprocess restarts
automatically so the new credentials take effect without any manual
action.
## Changes
- Add `MCPLoginScreen` (`widgets/mcp_login.py`), a new `ModalScreen`
that implements the `OAuthInteraction` protocol — renders authorize URLs
as clickable links, accepts pasted callback URLs, handles RFC 8628
device-code flows (e.g. GitHub), and runs a spinner animation during
async waits; cancellation raises `MCPLoginCancelledError` to unblock the
worker
- Add `/mcp login <server>` subcommand routing via
`_handle_mcp_subcommand`; `_start_mcp_login` guards against
connecting/no-server-proc/remote-server-mode/agent-switching states and
defers to `DeferredAction(kind="mcp_login")` when the agent is mid-run
- `MCPViewerScreen` changed from `ModalScreen[None]` to `ModalScreen[str
| None]`; clicking or pressing Enter on an `unauthenticated` server
header dismisses with the server name, which the viewer's dismiss
callback hands off to `_start_mcp_login`; unauthenticated headers show
an `— Enter to log in` hint
- On successful login, `_restart_server_for_mcp_refresh` calls
`ServerProcess.restart()`, rebuilds the agent, and fires `ServerReady`
to refresh tool counts, welcome banner state, and all MCP snapshots in
one pass; cancellation and failures skip the restart to preserve the
prior tool set; remote-server mode surfaces a notice that auto-restart
isn't available
- Switch Slack's redirect URI from the old copy-paste
`https://localhost` to a fixed loopback
`http://localhost:3118/callback`; add `loopback_port()` override hook to
`MCPOAuthProvider` (default `None` for ephemeral) so providers can
declare a required port; update `_prompt_slack_team` to use `getattr` so
TUI surfaces (which don't implement `prompt_slack_team_id`) skip
workspace selection and let Slack's browser page handle it
- Add animated ellipsis (`_DOT_FRAMES`, `_tick_dots`) to
`WelcomeBanner`'s connecting footer for both initial connect and
mid-session reconnect; add splash tip advertising `/mcp login <server>`
_Opened collaboratively by Mason Daugherty and open-swe._
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Mason Daugherty <61371264+mdrxy@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>