GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — feat: run plugin MCP servers discovered by agentcontext by jscottmiller · Pull Request #29326 · coder/coder Conversation
|
| Category | Files | + | - |
|---|---|---|---|
| prod (backend) | 10 | 423 | 92 |
| test (backend) | 8 | 824 | 103 |
| docs | 1 | 61 | 0 |
| Total | 19 | 1308 | 195 |
agent/x/agentmcp/manager.go (+119/-66): SetSources and ReloadCurrent, which replace Reload and ReloadSources, re-read the registered sources on every attempt and error after maxReloadAttempts. The snapshot records each source's position and LoadError, so a plugin reorder or a changed load error reloads. parseAndDedup does not start a plugin server whose ID equals a legacy name. Reconnect reloads the registered sources and does nothing until the first reload settles.agent/agentcontext/mcp.go (+113/-11): buildMCPServerResources uses <plugin>/<server> sources and copies PluginName. It omits a plugin server whose ID equals a legacy server name, with a warning on the legacy row, and counts plugin servers whose source is over 1024 bytes on a <plugin>/mcp.json row.agent/agent.go (+86/-4, concurrency): mcpConfigSources adds one source per plugin at the working directory, and none when the MCP config file list was set explicitly or the manifest has no directory. A tracked goroutine, runPluginMCPSync, subscribes to snapshot changes before Run starts and calls ReloadCurrent.agent/agentcontext/plugin.go (+54/-0): Snapshot.Plugins() returns OK plugins in name-claim order, and Snapshot.PluginsAt(dir) keeps those a scan root at dir discovers.agent/agentcontextconfig/api.go (+16/-5): Config.MCPConfigFilesSet, set by ReadEnvConfig when CODER_AGENT_EXP_MCP_CONFIG_FILES is non-empty, and API.MCPConfigFilesSet().agent/x/agentmcp/config.go, plugindata.go (+26/-3): ConfigSource.LoadError, reported for an existing plugin mcp.json instead of loading it, and PluginSource.codersdk/deployment.go (+1, API): agent-plugins joins ExperimentsSafe.This PR was generated by Coder Agents on behalf of @jscottmiller.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
4a5f2c5 to
d8f7100
Compare
d8f7100 to
7d71863
Compare
UAT run on this tip (
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
7d71863 to
bf74037
Compare
bf74037 to
311b7fd
Compare
311b7fd to
3511ebb
Compare
e7dca4c to
7e655a8
Compare
7e655a8 to
250b756
Compare
250b756 to
5ea3704
Compare
c279941 to
f9e9502
Compare
f9e9502 to
4951489
Compare
4951489 to
a5c91c5
Compare
a5c91c5 to
9461fb6
Compare
|
/coder-agents-review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Chat: Review posted | View chat Review historydeep-review v0.13.0 | Round 4 | Last posted: Round 4, 50 findings (3 P2, 19 P3, 20 P4, 8 Nit), COMMENT. Review Finding inventoryFindings
Contested and acknowledgedCRF-6 (P2, agent/agent.go:555) - plugin command created after mcp.json stays failed
CRF-50 (P4, agent/x/agentmcp/manager.go:659) - plugin server ID and legacy-collision rule in two packages
CRF-54 (P4, agent/agentcontext/mcp.go:92) - legacy-collision warning hides the plugin row's own error
Round logRound 1Round type: round 1 (full panel). Netero: 1 P2, 2 P3, 1 Note; no P0, so the panel ran. Law not run (517 effective additions). Panel of 13: specialists ging-go, takumi, ryosuke, kurapika, melody, luffy, killua (7 triggered: Go files, goroutines and shutdown, Go package boundaries, path containment and subprocess launch, paired source lists and wire format, new feature, reload resource lifecycle); core pariston, mafuuu; pool bisky (tests changed), gon, leorio (once-per-PR floor); wildcard meruem (shuf). Size target 9-12 for security-sensitive code exceeded by one because the 7 triggered specialists plus core, Bisky, and the Gon/Leorio floor reach 12 before the wildcard. Cross-check decisions:
Round 2 updateBLOCKED. Churn guard: 28 of 29 open findings addressed in 22cc66d; CRF-6 (P2) deferred by the author ("a follow-up ticket is being filed") with no ticket linked and no stated reason the failed-server state is acceptable. No reviewers, no Netero. Status cells updated from churn-guard classifications; fixes are author claims, not panel-verified. Reviewed against 9461fb6..22cc66d. Round 3Churn guard PROCEED: CRF-6 deferred to CODAGT-1391 with explicit acceptance. Round type: restructure (exported API changed: ReloadFrom removed; SetSources, ReloadCurrent, PluginSource added; PluginInfo.HasMCPConfig removed), so full panel. Netero (advisory, post-panel): CRF-46 to CRF-51. Law not run (783 effective additions). Panel of 13: same 7 triggered specialists as R1 (ging-go, takumi, ryosuke, kurapika, melody, luffy, killua), core pariston and mafuuu, bisky, gon and leorio (mandatory on restructure), wildcard razor (shuf). Exceeds 12 by one for the same reason as R1. Verified fixed by reviewers: CRF-1 addition half (Netero mutation), CRF-5 (Takumi, Pariston, Mafuuu), CRF-7, CRF-12, CRF-17 (Bisky), CRF-8, CRF-13 (Luffy), CRF-9, CRF-18 (Leorio), CRF-11 (Netero), CRF-14 (Mafuuu, Gon), CRF-16, CRF-20, CRF-21, CRF-22, CRF-23, CRF-26, CRF-27, CRF-30 (Gon), CRF-24, CRF-25 (Ging-Go), CRF-2 (Netero, code removed). CRF-3 code fixed, no test (CRF-46). Cross-check decisions:
Round 4 updateBLOCKED. Branch rebased (base 1cb2cc2 to f76e6bf, head d731736). Churn guard: 15 addressed, 2 acknowledged without ticket (CRF-50, CRF-54), 1 deferred (CRF-6), 6 silent: CRF-15, CRF-29, CRF-52, CRF-53 (R3 replies on threads whose unresolve failed with "Resource not accessible by integration", so the threads still show resolved) and CRF-64, CRF-65 (folded into the R3 review body). Orchestrator confirmed CRF-52, CRF-53, CRF-64 unchanged in code. No reviewers, no Netero. Human approval from ethanndickson on the PR. Reviewed against f76e6bf..d731736. About deep-reviewCRF = Coder Review Finding (P0-P4, Nit, Note)
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This PR starts and stops plugin MCP servers from the agentcontext plugin snapshot and attributes their resources to the plugin. Findings: 3 P2, 12 P3, 7 P4, 7 Nit.
Out of scope (needs a ticket or explicit acceptance by a human):
coderd/agentapi/context.go:483: coderd requires a plugin MCP server source of <plugin>/<server>, and legacy server names may contain /, so plugin and legacy sources can collide; a separator that cannot collide needs a coderd change.agent/agentcontext/mcp.go:193: a legacy .mcp.json server name over 1024 bytes makes coderd reject the whole context push; this existed before the PR.agent/x/agentmcp/manager.go:922: the raw ListTools error is stored and shown to users; for HTTP servers it may include the request URL with query-string credentials (unverified).agent/agentcontext/plugin.go:478: an escaping plugin.json symlink is also reported as escaping a "scan root" that is the plugin root.Notes:
mcp.json stdio commands under <working dir>/plugins/* and <working dir>/.agents/plugins/* now start automatically when the workspace supports plugins. This is the trust level the working-directory .mcp.json already has.mcp.json that fails to parse appears as a KindMCPServer resource named mcp.json with source <plugin>/mcp.json; #30577 has to show it as a file error.Manager.Reload(paths) has no production caller after this PR.TestReloadSources_ConcurrentCallerAppliesItsSources does not force the second Reload to join the in-flight body before close(release). It failed 20 of 20 runs against the base manager.go, but under heavy scheduler load it can pass against broken code.🤖 This review was automatically generated with Coder Agents.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
8fa7b32 to
22cc66d
Compare
|
/coder-agents-review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Re-review of 22cc66d. The author reports fixes for 28 of the 29 round 1 findings; these are not verified yet, because this round ran no reviewers.
The finding below is deferred without a ticket, so further review is blocked until it has a response:
agent/agent.go:555, P2: a plugin whose ./-relative command or cwd is created after its mcp.json keeps a failed server until mcp.json changes or the agent restarts. The reply says a follow-up ticket is being filed, but no ticket is linked, and the reply does not say why the stuck failed server is acceptable. This needs a human decision: link the ticket in that thread, or state explicitly that the gap is accepted.The out-of-scope items and notes from round 1 are unchanged and do not block.
🤖 This review was automatically generated with Coder Agents.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
/coder-agents-review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
22cc66d to
55133e9
Compare
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Re-review of 22cc66d. This round: 7 P3, 13 P4, 1 Nit, and two prior findings re-raised on their threads.
Reviewers verified these fixes: the watcher now uses the registered source function; the plugin-set guard is gone; the legacy-name collision no longer starts the plugin server; the collision warning text; the attempt-cap error; the per-attempt source test; the orphaned-server test; PluginSource; the removed HasMCPConfig layer; and the round 1 comment and naming fixes, apart from the two re-raised on their threads. The ./-command retry is deferred to CODAGT-1391 with the gap accepted. Two fixes introduced new problems: the 1024-byte source fix and the removal test (replies on those threads).
Out of scope (needs a ticket or explicit acceptance by a human):
agent/x/agentmcp/manager.go:457: SnapshotChanged ignores the order of legacy .mcp.json sources, so reordering MCPConfigFiles without a file change keeps the old first-wins winner for a shared legacy name until a file changes or the agent restarts.agent/x/agentmcp/manager.go:367
P3 [CRF-48] The handleWatchedConfigChange doc still says it reloads "using the most recently observed path set" through "a singleflight Reload", but it now calls reloadFrom with the function registered by SetSources. (Netero)
A maintainer reading it will expect the watcher to reuse the last reload's list, which is the stale-list behavior the round 1 fix removed. The lastSources field comment at line 116 also says it holds "sources passed to ReloadSources", while line 347 records the sources of every reload. Update both comments.
🤖
agent/x/agentmcp/manager.go:396
P4 [CRF-64] A failed watcher reload logs watched reload failed, while the two agent triggers now log failed to reload MCP servers. (Leorio)
All three call reloadFrom and can return the same new attempt-cap error, so an operator who greps for failed to reload MCP servers misses failures from config file edits. Use failed to reload MCP servers here too; the logger already carries trigger=fsnotify (line 386).
🤖
agent/x/agentmcp/manager.go:192
P4 [CRF-65] The ReloadSources doc says it waits for one reconnect and does not mention the attempt-cap error, and ReloadCurrent refers to it. (Leorio)
Only the unexported reloadFrom doc says a call can reload up to maxReloadAttempts times and then return an error while the Manager is still open. Add that to the ReloadSources doc, including that servers from the last completed reload keep running.
🤖
🤖 This review was automatically generated with Coder Agents.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
55133e9 to
1d40c18
Compare
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
pr lgtm in relative isolation (i havent spent much time on the rest of the stack) but maybe a $comment-cleanup is due
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
@ethanndickson Ran a comment-cleanup pass across the whole stack; see the CRF-62 thread. (Coder Agents generated) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
/coder-agents-review |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Re-review of d731736. The author reports fixes for 15 of the round 3 findings. They are not verified yet, because this round ran no reviewers.
Further review is blocked until each item below has a fix or a reply. The first four were replies on review threads that the reviewer could not reopen, so those threads still show as resolved. Expand the resolved threads to find them.
agent/agentcontext/mcp.go:111, P3: a plugin server whose <plugin>/<server> is over 1024 bytes is still started, and only its resource is dropped. agentmcp has no length check, so the command runs while chatd never receives its tools. Reject the entry in parseAndDedup, next to the legacy-name check. Reply on the thread for the 1024-byte source finding.agent/agent_context_test.go:281, P3: the removal step of TestAgent_PluginMCPServersFollowPluginChanges still calls os.RemoveAll(pluginDir) and checks only the push. It passes when mcpConfigSources keeps returning the removed plugin. Delete only plugin.json and check that the server stopped, not only the pushed resources. Reply on the thread about testing plugin changes after startup.agent/agentcontext/mcp_internal_test.go:160, P3 follow-up: the legacy test server is still named workspace.agent/agent_context_test.go:159 and the doc on TestReloadCurrent_ReadsSourcesOnEachAttempt in reload_internal_test.go, Nit follow-up: both comments still restate the code.agent/x/agentmcp/manager.go:370, P4 (round 3 review body): a failed watcher reload still logs watched reload failed, while the agent triggers log failed to reload MCP servers.ReloadCurrent doc in agent/x/agentmcp/manager.go, P4 (round 3 review body): it still does not say that the call can reload up to maxReloadAttempts times and then return an error.Accepted without a ticket, so these need a human decision (file a ticket or explicitly accept the gap):
agent/x/agentmcp/manager.go:632: the <plugin>/<server> ID and the legacy-collision rule are implemented in both agentmcp and agentcontext, and no test ties them together.agent/agentcontext/mcp.go:87: the legacy-collision warning replaces a plugin row's own error, such as an invalid entry, whatever caused that row.The out-of-scope items from rounds 1 and 3 are unchanged and do not block.
🤖 This review was automatically generated with Coder Agents.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Docs previewCheck off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Approving the docs in docs/ai-coder/agents/extending-agents.md; I did not review the agent code.
I checked the "Plugin MCP servers" section against the agent code at c3570ad.
The claims match the implementation, and markdownlint and Vale are clean.
The inline comments are non-blocking.
The main gaps are the plugin mcp.json rules that differ from .mcp.json, the start and stop behavior without a workspace restart, and the known limitation for late-appearing ./ commands, which matters now that agent-plugins is a safe experiment.
The remaining comments are wording and link nits.
🤖 Review generated with Coder Agents on behalf of @nickvigilante.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| A plugin declares MCP servers in an `mcp.json` file at its root, with `"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json"`. | ||
| Each server requires `type`, set to `stdio`, `streamable-http`, or `sse`. | ||
| A stdio server runs with `PLUGIN_ROOT` set to the plugin directory and `PLUGIN_DATA` set to a data directory for the plugin under `~/.coder/plugin-data`. | ||
| The agent expands `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` in `args`, `env` values, and `cwd`. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This section tells readers how to declare servers but leaves out the rules that make a plugin mcp.json stricter than .mcp.json. A reader copying the .mcp.json example above will hit these errors without explanation:
$schema and mcpServers, or the whole file is rejected (agent/x/agentmcp/plugin.go:52).type isn't inferred from command or url, and "http" is rejected in favor of streamable-http (plugin.go:174-181). Line 339 lists http as valid for .mcp.json, so the contrast is worth stating.command must be a bare name on PATH or a ./-relative path inside the plugin (plugin.go:257).cwd defaults to the plugin root, not the workspace working directory, and must start with ./, ${PLUGIN_ROOT}, or ${PLUGIN_DATA} (plugin.go:303-323).url must be https, or http on a loopback host (plugin.go:459).env can't set PLUGIN_ROOT or PLUGIN_DATA, and fields from another type are rejected (plugin.go:98-100, plugin.go:239)..mcp.json, which fails as a whole.A short list or a minimal example mcp.json would cover most of this.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| Setting `CODER_AGENT_EXP_MCP_CONFIG_FILES` to a non-empty value, including `.mcp.json`, turns off plugin MCP servers. | ||
| A template that points it at a file outside the project, as in [network isolation](./platform-controls/agent-isolation.md), also keeps plugins in the project from starting servers. | ||
| Plugins in `~/.coder` or in a declared source contribute skills only, even when the declared source is inside the working directory. | ||
| If the template doesn't set `dir` on the `coder_agent` resource, the workspace has no working directory, so no plugin starts MCP servers. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Two gaps after this paragraph:
mcp.json files appear or disappear, without a workspace restart. "How discovery works" says this only for .mcp.json. One sentence here, possibly pointing to the existing out-of-date-chat note, would cover it../ command file appears after its mcp.json isn't retried until a config or snapshot change. Since this PR adds agent-plugins to ExperimentsSafe, the content guidelines call for documenting known limitations. That change also means --experiments='*' turns the feature on, which "Enable the experiment" could mention.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| If the template doesn't set `dir` on the `coder_agent` resource, the workspace has no working directory, so no plugin starts MCP servers. | ||
|
|
||
| Plugin servers and `.mcp.json` servers share one set of server names, which prefix their [tool names](#tool-naming). | ||
| A plugin server doesn't start when a `.mcp.json` server or another plugin's server already uses its name, and its context entry shows the conflict. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
As written, "already" doesn't say who wins. parseAndDedup (manager.go:638-672) gives .mcp.json servers priority over every plugin server, and between plugins the first to claim the name (resolver name-claim order) wins. This also uses "context list" to match line 411 instead of introducing "context entry".
| A plugin server doesn't start when a `.mcp.json` server or another plugin's server already uses its name, and its context entry shows the conflict. | |
| A plugin server doesn't start when another server already uses its name, and it appears in the chat's context list with the conflict. | |
| A `.mcp.json` server always keeps its name over a plugin server, and between plugins, the first plugin the agent discovers keeps the name. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| - `CODER_AGENT_EXP_MCP_CONFIG_FILES` is not set on the agent. | ||
|
|
||
| Setting `CODER_AGENT_EXP_MCP_CONFIG_FILES` to a non-empty value, including `.mcp.json`, turns off plugin MCP servers. | ||
| A template that points it at a file outside the project, as in [network isolation](./platform-controls/agent-isolation.md), also keeps plugins in the project from starting servers. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Nit: the env var is set in the "1. Configure the template" section, so a deep link lands readers on it.
| A template that points it at a file outside the project, as in [network isolation](./platform-controls/agent-isolation.md), also keeps plugins in the project from starting servers. | |
| A template that points it at a file outside the project, as in [Network isolation](./platform-controls/agent-isolation.md#1-configure-the-template), also keeps plugins in the project from starting servers. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| - The plugin is the workspace working directory, or is in its `plugins/` or `.agents/plugins/` directory. | ||
| - `CODER_AGENT_EXP_MCP_CONFIG_FILES` is not set on the agent. | ||
|
|
||
| Setting `CODER_AGENT_EXP_MCP_CONFIG_FILES` to a non-empty value, including `.mcp.json`, turns off plugin MCP servers. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Nit: the second bullet and line 432 say nearly the same thing, and "The plugin is the workspace working directory" reads oddly. Possible tightening:
| - The plugin is the workspace working directory, or is in its `plugins/` or `.agents/plugins/` directory. | |
| - `CODER_AGENT_EXP_MCP_CONFIG_FILES` is not set on the agent. | |
| Setting `CODER_AGENT_EXP_MCP_CONFIG_FILES` to a non-empty value, including `.mcp.json`, turns off plugin MCP servers. | |
| - The plugin is the working directory itself, or is in its `plugins/` or `.agents/plugins/` directory. | |
| - `CODER_AGENT_EXP_MCP_CONFIG_FILES` is unset on the agent. | |
| Setting `CODER_AGENT_EXP_MCP_CONFIG_FILES` to any non-empty value, even `.mcp.json`, turns off plugin MCP servers. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
The agent now feeds the mcp.json of each valid plugin discovered at the working directory (the directory itself, plugins/*, and .agents/plugins/*) into the MCP engine, but only while CODER_AGENT_EXP_MCP_CONFIG_FILES is unset. Setting it, even to .mcp.json, starts no plugin servers; agentcontextconfig.Config.MCPConfigFilesSet records whether it was set. Plugins found through other scan roots, including declared sources nested under the working directory, start no servers. mcpConfigSources composes the env-configured .mcp.json files followed by one plugin-scoped source per plugin, built by agentmcp.PluginSource with PLUGIN_DATA under ~/.coder/plugin-data. A plugin without an mcp.json contributes no servers, and the engine's config watcher picks the file up when it appears. When the home directory or a plugin's data directory cannot be determined, the plugin is still passed as a ConfigSource with LoadError set, which an existing mcp.json reports on the plugin's <plugin>/mcp.json resource; only the first such failure logs at warn level. LoadError is kept out of PluginScope, so it is not part of server identity; the file snapshot records it, and a change to it reloads. Plugin sources come only from the context snapshot, so no plugin server starts while Manifest.AgentPluginsEnabled is off. The agent registers mcpConfigSources with Manager.SetSources, and the startup reload, a context snapshot subscriber, and config watcher reloads all compute the current sources from it. ReloadCurrent is the only reload entry point besides Reconnect: Reload, ReloadSources, and the watcher's last-sources fallback are removed. Reconnect, which a context resync calls to retry failed servers, reloads the current sources and does nothing until the first reload settles. ReloadCurrent calls the function on every attempt and re-checks the snapshot after joining a concurrent reload, so one trigger cannot drop another's servers. It returns an error if the sources keep changing after three reloads. The subscriber reloads on every snapshot change once the first resolve has finished; a reload with unchanged sources is a no-op. The subscription is taken before the context manager's Run loop starts, and the current snapshot is examined before the first wait. Snapshot.Plugins() returns the valid plugins in the order the resolver claimed their names, so the first plugin to claim a server name wins deterministically. Snapshot.PluginsAt keeps the ones a scan root at a given directory discovers. The engine's snapshot records source order, so a reorder alone triggers a reload. MCPServerStatus gains PluginName, which buildMCPServerResources copies onto the resource. MCP server resources declared by a plugin carry the plugin name and use <plugin>/<server> as their source, so a plugin entry that lost a name collision with a legacy server still appears with its error. A plugin server whose <plugin>/<server> ID equals a legacy server name is not started, and the legacy server's resource carries a warning naming it. A plugin server whose source exceeds the 1024-byte source limit is left out and counted on an unreadable <plugin>/mcp.json resource, or on the plugin's server named mcp.json when there is one. agent-plugins joins ExperimentsSafe, so --experiments='*' enables it. The extending-agents docs gain a Plugin MCP servers section covering the plugin mcp.json, when the agent starts plugin servers, name conflicts with .mcp.json servers, and repository trust.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.