Skip to content

[Bug] MCP servers from .agents/mcp.json are not loaded when the project is selected via the project picker (CLI started from an ancestor directory) #957

Description

@hermes-agent01

Summary

When the Freebuff CLI is started from a directory outside the project and the project is then selected via the project picker, the MCP servers defined in the project's .agents/mcp.json are silently not exposed to the main agent. The mcpServers are only loaded if the CLI is started directly inside the project directory (e.g. cd ~/projects/foo && freebuff).

Environment

  • CLI: freebuff npm package 0.0.142 (native binary at ~/.config/manicode/freebuff)
  • OS: Linux
  • Tested: 2026-08-07

Steps to reproduce

  1. Create a project with an .agents/mcp.json containing one or more MCP servers, e.g.:

    {
      "mcpServers": {
        "context7": {
          "type": "http",
          "url": "https://mcp.context7.com/mcp",
          "headers": { "Authorization": "Bearer $CONTEXT7_API_KEY" }
        },
        "chrome-devtools": {
          "command": "npx",
          "args": ["-y", "chrome-devtools-mcp@latest", "--headless", "--isolated"]
        }
      }
    }
  2. Start the CLI from a directory above the project (e.g. cd ~ && freebuff).

  3. In the project picker, select the project.

  4. Ask the main agent which tools it has available.

Result: the MCP tools (context7__*, chrome-devtools__*) are not present.

  1. Now exit, and restart with cd ~/projects/<project> && freebuff (no project picker).
  2. Ask the same question.

Result: the MCP tools are present.

Expected behavior

MCP servers from the selected project's .agents/mcp.json should be available to the main agent regardless of which directory the CLI was launched from.

Actual behavior

MCP servers are only available when the CLI is launched inside the project directory. Selecting the project afterwards via the picker never exposes them.

Root cause analysis

The MCP config is loaded once, at boot time, using the then-current process.cwd():

  • cli/src/index.tsx (~line 260): await initializeAgentRegistry() runs during startup. This calls loadMCPConfigSync({ verbose: false }) (sdk/src/agents/load-mcp-config.ts), which resolves {cwd}/.agents/mcp.json against process.cwd() and populates a module-level mcpServersCache.
  • cli/src/index.tsx (~line 347): only later, when the user picks a project, does the CLI call process.chdir(newProjectPath) followed by resetCodebuffClient().
  • resetCodebuffClient() recreates the client but never reloads mcp.json — the mcpServersCache module variable was already populated (with an empty/absent config) at boot.

The merge itself is correct and does run afterwards:

  • cli/src/utils/local-agent-registry.ts merges mcpServersCache into every agent definition whose id.startsWith('base') (the Freebuff root agent base2-free-deepseek-flash qualifies):

    for (const agent of definitions) {
      if (agent.id.startsWith('base')) {
        if (!agent.mcpServers) agent.mcpServers = {};
        agent.mcpServers = { ...agent.mcpServers, ...mcpServersCache };
      }
    }

    (Confirmed in the installed binary's minified JS: if(Object.keys(VW).length>0){for(let D of A)if(D.id.startsWith("base")){if(!D.mcpServers)D.mcpServers={};D.mcpServers={...D.mcpServers,...VW}}}.)

Because the cache was populated at boot from the wrong cwd, the merge operates on an empty cache → the main agent template ends up with mcpServers missing/null.

Evidence

Session state (run-state.json) for the same chat, comparing both launch modes:

Launch mode Main agent template mcpServers
freebuff from ~, project picked via picker missing / null
cd ~/projects/mathema && freebuff { "context7": …, "chrome-devtools": … }

The agent's registered toolNames (from the session log) match: context7__resolve-library-id, context7__query-docs, and 29 chrome-devtools__* tools appear only in the second mode.

Suggested fixes

  1. Reload MCP config on project change — after process.chdir(newProjectPath) in the project-picker path, re-run the MCP config load (or invalidate/re-populate mcpServersCache and re-run loadAgentDefinitions() / initializeAgentRegistry()).
  2. Resolve mcp.json from an explicit project root — instead of process.cwd(), pass the resolved project path to loadMCPConfigSync so it is independent of launch directory and chdir timing.
  3. Load lazily — resolve the MCP config from the project root at session/run start rather than at process boot, so the picker path is naturally covered.

Workaround

Always launch the CLI from inside the project directory:

cd ~/projects/<project> && freebuff

Affected files (approx., from main)

  • cli/src/index.tsx — boot order: initializeAgentRegistry() before process.chdir() / resetCodebuffClient() in the project picker path
  • cli/src/utils/local-agent-registry.ts — the merge of mcpServersCache into base* agent definitions
  • sdk/src/agents/load-mcp-config.ts — loadMCPConfigSync resolves config from process.cwd()

Activity

  1. bunnysayzz commented on Aug 11, 2026

    @bunnysayzz

    Hi, I'd like to fix this one, and I already have the fix on my fork.

    Root cause confirmed in the code: the CLI loads MCP servers exactly once at startup in initializeAgentRegistry() via loadMCPConfigSync(), which reads {cwd}/.agents/mcp.json. When you launch from an ancestor directory and then pick a project, handleProjectChange in cli/src/index.tsx does process.chdir(newProjectPath) and resets the codebuff client, but never re-runs the agent registry. So mcpServersCache stays empty and loadAgentDefinitions() merges nothing into the base agents.

    The fix adds a reloadLocalAgentRegistry() helper in cli/src/utils/local-agent-registry.ts that clears the derived caches (agent listings and the resolved .agents dir) and re-runs initializeAgentRegistry(). handleProjectChange now calls it right after chdir and setProjectRoot, so the selected project's .agents/mcp.json is picked up.

    Verification:

    • New regression test reproduces the exact scenario from the report (registry initialized in a directory without mcp.json, then chdir + setProjectRoot to a project that has one, then reload): it fails on the original code (the export does not exist) and passes with the fix.
    • Local Agent Integration suite: 37/37 pass.
    • tsc on cli: no errors in the changed files (10 total, same as baseline modulo one pre-existing react-dom/server declaration issue that my change actually resolves).

    Branch: fix/mcp-config-project-picker-957 (1 commit). PR is up next. Let me know if you'd like any changes.

  2. bunnysayzz commented on Aug 11, 2026

    @bunnysayzz

    PR is up: #973

  3. added
    area:cliThe Codebuff/Freebuff terminal client
    bot:triagedClassified by the community triage bot
    type:bugA defect in the code with a reproducible failure
    on Aug 19, 2026
  4. added
    staleNo activity after a maintainer request; queued for closing
    on Sep 9, 2026
  5. codebuff-team commented on Sep 9, 2026

    @codebuff-team
    Contributor

    Marking this stale - there has been no activity here for 29 days. It will close in 7 days unless someone comments.

    This is backlog upkeep, not a verdict on the issue. A single comment keeps it open, and anything closed this way can be reopened.

  6. codebuff-team commented on Sep 17, 2026

    @codebuff-team
    Contributor

    Closing this as stale - no activity since it was flagged 7 days ago. Reopen it any time if it is still relevant; that is not a hassle and we would rather have it open than lost.

    Closed automatically by the community triage bot. If this is wrong, reopen the issue or reply and a maintainer will take another look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:cliThe Codebuff/Freebuff terminal clientbot:auto-closedClosed by the community triage bot; reopen if wrongbot:triagedClassified by the community triage botstaleNo activity after a maintainer request; queued for closingtype:bugA defect in the code with a reproducible failure

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions