Repository navigation
feat(assistant): turn the MCP runner and a browser on from the web app, with ready-made MCP servers - #491
Merged
Conversation
…p, with ready-made MCP servers
The host upgrade agent's services action now takes a profile (mcp,
browser or monitoring, a fixed list) and turn=on|off, so the web app,
the API (GET /admin/services, PUT /admin/services/{profile}) and the MCP
tools services and set_service can start or stop any of Lens's optional
containers; the old monitoring=on|off request still works.
The new browser profile runs Playwright MCP in a hardened container on
an internal network whose only way out is browser-proxy, netguard run
on its own (public addresses, ports 80 and 443, a byte budget per
connection). Add MCP server gains Ready-made: Browser (one click once
its container answers, browser_run_code_unsafe off) and GitHub (a field
for the token). ${NAME} values get their own fields, and a spec with
keep: true reuses one MCP session between calls.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
…-r960xc-c6-browser # Conflicts: # threat-model.json # threat-model.md # threat-model.yaml
…machine The preview waits 600 ms after the last keystroke, and findByText gives up after 1 s, so the test failed when the machine was busy. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
# Conflicts: # threat-model.yaml
19 of 22 tasks
The tmpfs at /home/node was root's, so Playwright couldn't make its profile there and every navigation failed with EACCES. Mount it with node's uid and gid (1000), in both compose files. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
Ported from #512 so this PR's upgrade check passes while that lands: the entity-types step re-types weekday Terms as Dates, which the default entity list leaves out, so the check read them as gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
# Conflicts: # docker-compose.prod.yml # docker-compose.yml # docs/mcp.md # fastapi_backend/app/api/mcp_tools.py # fastapi_backend/app/api/v1/routes/updates.py # fastapi_backend/app/schemas/updates.py # fastapi_backend/tests/api/test_mcp.py # nextjs-frontend/app/openapi-client/index.ts # nextjs-frontend/app/openapi-client/sdk.gen.ts # nextjs-frontend/app/openapi-client/types.gen.ts # nextjs-frontend/openapi.json # threat-model.md # threat-model.yaml
# Conflicts: # docs/mcp.md # threat-model.yaml
# Conflicts: # threat-model.md # threat-model.yaml
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXPWXcSCQb9hWPr7xkZu7B
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
…ay and clipper sign-in as built Since the last README refresh, #474, #484, #510, #511, #497, #495, #406, #516, #517 and #491 merged. The README's built list now says a conversation exports as Markdown, PDF or JSON and its answers, questions and code copy; a Tools chip picks an answer's tools, limit and namespaces; sandbox runs open under the answer with downloads, and Settings starts the gateway; deep research plans, runs and returns a cited report; ready-made MCP servers (the browser, GitHub) and the optional containers start from the web app; and the web clipper signs in or takes an API token. Each has its checks in docs/requirements.md. In progress drops the merged PRs and lists the open feature PRs; the Planned proof item keeps only the Raspberry Pi timing (#481 and #482 are closed); the docs index links requirements and checks, and published feeds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS
17 of 23 tasks
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
…ay and clipper sign-in as built Since the last README refresh, #474, #484, #510, #511, #497, #495, #406, #516, #517, #491, #400 and #506 merged. The README's built list now says the assistant answers questions about Lens itself; a conversation exports as Markdown, PDF or JSON and its answers, questions and code copy; a Tools chip picks an answer's tools, limit and namespaces; sandbox runs open under the answer with downloads, and Settings starts the gateway; deep research plans, runs and returns a cited report; ready-made MCP servers, the MCP servers page and the optional containers start from the web app; and the web clipper signs in or takes an API token. Each has its checks in docs/requirements.md. In progress lists only open PRs; the Nebula mesh (#546, merged, partly built) moves to Planned with what's next; the Planned proof item keeps only the Raspberry Pi timing; the docs index links requirements and checks, and published feeds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…ay and clipper sign-in as built (#536) Since the last README refresh, #474, #484, #510, #511, #497, #495, #406, #516, #517, #491, #400 and #506 merged. The README's built list now says the assistant answers questions about Lens itself; a conversation exports as Markdown, PDF or JSON and its answers, questions and code copy; a Tools chip picks an answer's tools, limit and namespaces; sandbox runs open under the answer with downloads, and Settings starts the gateway; deep research plans, runs and returns a cited report; ready-made MCP servers, the MCP servers page and the optional containers start from the web app; and the web clipper signs in or takes an API token. Each has its checks in docs/requirements.md. In progress lists only open PRs; the Nebula mesh (#546, merged, partly built) moves to Planned with what's next; the Planned proof item keeps only the Raspberry Pi timing; the docs index links requirements and checks, and published feeds. Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Adeel · project thread
Description
Before: the MCP runner could only be turned on by editing
.envand running the install line again, the assistant had no browser on the server, and adding a well-known MCP server meant typing it in by hand.After: Add MCP server starts with Ready-made. Browser adds a headless Chromium the assistant drives (Playwright MCP) with one click once its container answers, and its switch turns the container on first. GitHub fills in GitHub's own server with a field for the token. The runner gets the same switch under Command. Values written as
${NAME}in a pasted config get a field of their own.How: the host upgrade agent's
action=servicesnow takesprofile=(a fixed list:mcp,browser,monitoring) andturn=on|off; the oldermonitoring=on|offrequest still works.domain/services.pywrites those requests and follows them, one at a time, and monitoring goes through it too. The newbrowserCompose profile runsmcr.microsoft.com/playwright/mcp:v0.0.83hardened (caps dropped, read-only, memory and process limits, profile in memory) on an internal network whose only way out isbrowser-proxy:netguard.pyrun on its own, which reaches public addresses on ports 80 and 443 only, with a byte budget per connection. A spec withkeep: truemakes Lens reuse one MCP session between calls (the browser keeps its open page), and it opens a new one when the server forgets it. The preset switchesbrowser_run_code_unsafeoff and lets navigating run at once until outside text was read.This also makes
mail-routes.test.tsxwait long enough for its 600 ms debounced preview, which failed under load in local CI.Motivation and Context
Part of the chat-app gaps: settings for chat tools and MCP servers, and a browser MCP. A follow-up adds the MCP servers block in Settings › AI assistant.
Local CI (
ci/local-ci.sh): backend pass on 96e8835 (1373 passed); Next.js, pre-commit and PR title pass on 969c44d (the head, which only adds the test fix).Types of changes
!in the title)Checklist:
make hookschecks it on commit).test_services.py,test_netguard_forwarder.py, the browser preset and kept sessions intest_mcp_servers.py,test_mcp.py,test_monitoring.py,mcp-server-ui.test.tsx,packaging/host/test-services.sh(a newhost-agentNx project), and.github/workflows/browser.yml, which starts the two containers and checks the sandbox (private and metadata addresses refused, no direct way out, wrongHostrefused, a page kept between sessions).docs/accordingly:assistant.md(The browser, Optional containers, Ready-made,keep),mcp.md,updates.md,prometheus.md,contributing.md.## UnreleasedinCHANGELOG.md.Done questions (AGENTS.md)
GET /api/v1/admin/services,PUT /api/v1/admin/services/{profile},GET /api/v1/extensions/mcp/presets, and the MCP toolsservicesandset_service.COMPOSE_PROFILESand start the containers; without an agent it shows the one line to run.ci/validate_threat_model.pypasses).mcp.call).saidis a new optional field read with a default.make openapi).--image-responses=omittoday); a browser per person instead of one shared.Generated by Claude Code