You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
devframe connect --port can't reach a hub mounted under a base path (Vite DevTools /__devtools/) and reports it as "no MCP endpoint" #403
devframe connect --port <n> always probes http://localhost:<n>/__connection.json. Vite DevTools mounts its hub at /__devtools/, so the probe misses the real connection meta at /__devtools/__connection.json. Vite's SPA fallback answers the root probe with 200 text/html, and the probe accepts that as a live devframe. The connector then lists a phantom port-<n> instance with mcp: null and fails call-tool with DF0051, telling the user to "restart the instance with the --mcp flag". That flag doesn't exist for a Vite server, and the MCP route is in fact up at /__devtools/__mcp.
There's no flag or documented way to give the connector a base path, so this isn't a usage problem: --port is the documented fallback for instances missing from the registry (docs/content/2.adapters/7.mcp.md, "Discovery: devframe connect"), and it only works for root-mounted devframes.
Scope: registry-based discovery of Vite DevTools is already handled by vitejs/devtools#579 (merged, not yet released), which registers the hub with its /__devtools/ base. This issue is only about the --port fallback and the __connection.json origin probe.
Node 24.21.0, Windows 11. Nothing here is platform-specific.
main at 18fa60e has no changes to packages/agentic/src/connect/ or packages/devframe/src/node/instance-registry.ts since v1.0.0, so the behavior is the same there.
Reproduction
Run any Vite 8.3 app with @vitejs/devtools 0.7.5 enabled (dev server on 127.0.0.1:5174 here, mcp left at its default).
{ "id": "port-5174", "port": 5174, "basePath": "/", "mcp": null,
"hint": "This instance runs without an MCP route. Restart it with the --mcp flag to expose its tools, then list instances again." }
{ "error": { "code": "DF0051", "message": "The devframe instance on port 5174 has no MCP endpoint.",
"fix": "Restart the instance with the --mcp flag to expose its tools, then list instances again." } }
For comparison, a registry record with the right base works end to end with the same 1.0.0 connector against the same server: 11 tools listed, and call-tool returns the state keys. The record is {"port":5174,"origin":"http://127.0.0.1:5174","basePath":"/__devtools/","mcp":{"path":"/__devtools/__mcp"},...}, the shape vitejs/devtools#579 now writes. So the MCP route and the connector's proxy are fine; only the --port probe is wrong.
Root cause
At 18fa60e:
The base is hardcoded to /.packages/agentic/src/connect/index.ts#L202-L217 (probePort) calls probeDevframeOrigin(\http://localhost:${port}\`, '/', timeoutMs), records basePath: '/', and resolves the MCP path with joinURL('/', probed.meta.mcp.path). For a hub at /__devtools/, whose meta advertises the relative "__mcp", that would give /__mcpeven if the meta were found. The in-process registration ininstance-shell.ts#L596correctly usesjoinURL(base, …)`.
Any 200 counts as a devframe.packages/devframe/src/node/instance-registry.ts#L195-L216 (probeDevframeOrigin) checks only response.ok, then falls back to {} when response.json() fails. An HTML SPA fallback therefore "proves" a devframe with no MCP route. That produces the misleading DF0051 instead of DF0050. The same probe is the registry's liveness check, so a stale record whose port is now held by some SPA dev server also stays "live" instead of being pruned.
Related
fix: register Vite DevTools for devframe discovery vitejs/devtools#579 (merged 2026-09-17, after the 0.7.5 release, not yet published) registers Vite DevTools in the instance registry with its base. That fixes discovery through the registry for the next @vitejs/devtools release. --port is still the documented fallback for anything unregistered: older @vitejs/devtools, DEVFRAME_DISABLE_INSTANCE_REGISTRY=1, a registry directory the connector can't see (container, WSL, a different HOME), or the window before the hub's first request, since registration waits for the origin.
No existing issue found for "connect" + base path, __connection.json probing, or DF0051 (searched issues and PRs).
Suggested fix
Happy to send a PR:
In probeDevframeOrigin, accept only a JSON object as connection meta (skip text/html or unparseable bodies). A non-devframe 200 then yields "no instance" (DF0050) instead of a phantom instance, and stale registry records on a port now held by an unrelated server get pruned.
Add a --base <path> option to devframe connect (default /, with a matching base field in ConnectServerOptions) that applies to the --port probes, and resolve the advertised MCP path against that base the same way instance-shell does. devframe connect --port 5174 --base /__devtools/ would then reach Vite DevTools, and the connector stays free of hardcoded mount paths.
Document --base in the CLI help and in the "Discovery" section of the MCP adapter docs.
Summary
devframe connect --port <n>always probeshttp://localhost:<n>/__connection.json. Vite DevTools mounts its hub at/__devtools/, so the probe misses the real connection meta at/__devtools/__connection.json. Vite's SPA fallback answers the root probe with200 text/html, and the probe accepts that as a live devframe. The connector then lists a phantomport-<n>instance withmcp: nulland failscall-toolwith DF0051, telling the user to "restart the instance with the --mcp flag". That flag doesn't exist for a Vite server, and the MCP route is in fact up at/__devtools/__mcp.There's no flag or documented way to give the connector a base path, so this isn't a usage problem:
--portis the documented fallback for instances missing from the registry (docs/content/2.adapters/7.mcp.md, "Discovery:devframe connect"), and it only works for root-mounted devframes.Scope: registry-based discovery of Vite DevTools is already handled by vitejs/devtools#579 (merged, not yet released), which registers the hub with its
/__devtools/base. This issue is only about the--portfallback and the__connection.jsonorigin probe.Versions
devframe1.0.0,@devframes/agentic1.0.0,@devframes/hub1.0.0,@devframes/vite1.0.0@vitejs/devtools0.7.5,vite8.3.0mainat18fa60ehas no changes topackages/agentic/src/connect/orpackages/devframe/src/node/instance-registry.tssincev1.0.0, so the behavior is the same there.Reproduction
@vitejs/devtools0.7.5 enabled (dev server on127.0.0.1:5174here,mcpleft at its default).DEVFRAME_INSTANCES_DIR=$(mktemp -d) npx devframe connect --port 5174devframe_connect_list-instancesreturns:{ "id": "port-5174", "port": 5174, "basePath": "/", "mcp": null, "hint": "This instance runs without an MCP route. Restart it with the --mcp flag to expose its tools, then list instances again." }devframe_connect_call-tool{ "port": 5174, "tool": "devframes_plugin_inspect_list-state-keys" }returns:{ "error": { "code": "DF0051", "message": "The devframe instance on port 5174 has no MCP endpoint.", "fix": "Restart the instance with the --mcp flag to expose its tools, then list instances again." } }For comparison, a registry record with the right base works end to end with the same 1.0.0 connector against the same server: 11 tools listed, and
call-toolreturns the state keys. The record is{"port":5174,"origin":"http://127.0.0.1:5174","basePath":"/__devtools/","mcp":{"path":"/__devtools/__mcp"},...}, the shape vitejs/devtools#579 now writes. So the MCP route and the connector's proxy are fine; only the--portprobe is wrong.Root cause
At
18fa60e:/.packages/agentic/src/connect/index.ts#L202-L217(probePort) callsprobeDevframeOrigin(\http://localhost:${port}\`, '/', timeoutMs), recordsbasePath: '/', and resolves the MCP path withjoinURL('/', probed.meta.mcp.path). For a hub at/__devtools/, whose meta advertises the relative"__mcp", that would give/__mcpeven if the meta were found. The in-process registration ininstance-shell.ts#L596correctly usesjoinURL(base, …)`.200counts as a devframe.packages/devframe/src/node/instance-registry.ts#L195-L216(probeDevframeOrigin) checks onlyresponse.ok, then falls back to{}whenresponse.json()fails. An HTML SPA fallback therefore "proves" a devframe with no MCP route. That produces the misleading DF0051 instead of DF0050. The same probe is the registry's liveness check, so a stale record whose port is now held by some SPA dev server also stays "live" instead of being pruned.Related
@vitejs/devtoolsrelease.--portis still the documented fallback for anything unregistered: older@vitejs/devtools,DEVFRAME_DISABLE_INSTANCE_REGISTRY=1, a registry directory the connector can't see (container, WSL, a differentHOME), or the window before the hub's first request, since registration waits for the origin.__connection.jsonprobing, or DF0051 (searched issues and PRs).Suggested fix
Happy to send a PR:
probeDevframeOrigin, accept only a JSON object as connection meta (skiptext/htmlor unparseable bodies). A non-devframe200then yields "no instance" (DF0050) instead of a phantom instance, and stale registry records on a port now held by an unrelated server get pruned.--base <path>option todevframe connect(default/, with a matchingbasefield inConnectServerOptions) that applies to the--portprobes, and resolve the advertised MCP path against that base the same wayinstance-shelldoes.devframe connect --port 5174 --base /__devtools/would then reach Vite DevTools, and the connector stays free of hardcoded mount paths.--basein the CLI help and in the "Discovery" section of the MCP adapter docs.