Skip to content

refactor: optimize MCP loading with lazy-load strategy#191

Merged
marcusquinn merged 3 commits intomainfrom
refactor/optimize-mcp-loading
Jan 25, 2026
Merged

refactor: optimize MCP loading with lazy-load strategy#191
marcusquinn merged 3 commits intomainfrom
refactor/optimize-mcp-loading

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Jan 25, 2026

Summary

  • Add @claude-code subagent for on-demand claude-code-mcp access (instead of loading in main agents)
  • Implement lazy-loading strategy: 12 MCPs now start on-demand, 8 remain eager-loaded
  • Enable playwriter_* and repomix_* globally for all main agents

Changes

MCP Loading Policy

Eager-loaded (8) - Start at OpenCode launch, used by all main agents:

  • osgrep, augment-context-engine, context7, repomix, playwriter, gh_grep, sentry, socket

Lazy-loaded (12) - Start on-demand when subagent invokes them:

  • claude-code-mcp, gsc, localwp, chrome-devtools, outscraper, amazon-order-history
  • google-analytics-mcp, dataforseo, shadcn, macos-automator, quickfile, MCP_DOCKER

Agent Tool Changes

  • Removed claude-code-mcp_*: true from Build+ and AI-DevOps (use @claude-code subagent instead)
  • Added gh_grep_*: true to Plan+, Build+, AI-DevOps
  • Added playwriter_*: true and repomix_*: true to all main agents

New Subagent

  • tools/ai-assistants/claude-code.md - Invokes claude-code-mcp on-demand

Impact

Reduces OpenCode startup time by deferring 12 MCP server initializations until actually needed.

Testing

  • generate-opencode-agents.sh runs successfully
  • ShellCheck passes
  • MCP loading policy correctly applied to opencode.json

Summary by CodeRabbit

Release Notes

  • New Features

    • Added new code analysis and automation tools with expanded availability across multiple assistants.
    • Implemented optimized tool loading: essential tools launch immediately, others activate on-demand for improved performance.
    • Expanded multiple assistants with extended tool permissions for enhanced functionality.
  • Documentation

    • Added comprehensive guide for new Claude Code analysis tool.

✏️ Tip: You can customize this high-level summary in your review settings.

- Add claude-code subagent for on-demand claude-code-mcp access
- Remove claude-code-mcp_* from main agent tool lists (Build+, AI-DevOps)
- Set 12 MCPs to lazy-load (enabled: false): claude-code-mcp, gsc, localwp,
  chrome-devtools, outscraper, amazon-order-history, google-analytics-mcp,
  dataforseo, shadcn, macos-automator, quickfile, MCP_DOCKER
- Keep 8 MCPs eager-loaded for all main agents: osgrep, augment-context-engine,
  context7, repomix, playwriter, gh_grep, sentry, socket
- Enable playwriter_* and repomix_* globally for all main agents
- Add MCP loading policy enforcement to update existing configs

This reduces OpenCode startup time by deferring MCP server initialization
until the specific subagent that needs them is invoked.
@gemini-code-assist
Copy link

Summary of Changes

Hello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the Micro-service Control Plane (MCP) loading mechanism within OpenCode, shifting a significant portion of MCPs to a lazy-loading model. This change aims to improve application startup performance by only initializing services when they are explicitly required by a subagent. Concurrently, it introduces a dedicated subagent for claude-code-mcp and adjusts tool access for several main agents, streamlining the overall agent ecosystem and tool management.

Highlights

  • Lazy-Loading Strategy for MCPs: Implemented a lazy-loading strategy for 12 Micro-service Control Plane (MCP) servers, which now start on-demand when invoked by a subagent, significantly reducing OpenCode startup time. Eight core MCPs remain eager-loaded.
  • New @claude-code Subagent: Introduced a dedicated @claude-code subagent for on-demand access to the claude-code-mcp, enabling its use for complex coding tasks without being eager-loaded by main agents.
  • Global Tool Enablement: Globally enabled playwriter_* and repomix_* tools for all main agents, expanding their general capabilities across the platform.
  • Agent Tool Adjustments: Removed claude-code-mcp_* from Build+ and AI-DevOps agents, directing its usage through the new @claude-code subagent. The gh_grep_* tool was added to Plan+, Build+, and AI-DevOps agents.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 25, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 52 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This change introduces an eager/lazy MCP loading policy for the OpenCode agent framework, expanding tool permissions across 10+ agents with new subagent patterns (gh_grep, playwriter, claude-code-mcp), creating MCPs with classified startup behavior, and adding configuration documentation for the Claude Code MCP subagent.

Changes

Cohort / File(s) Summary
MCP Loading Policy & Configuration
.agent/scripts/generate-opencode-agents.sh
Introduces EAGER_MCPS (osgrep, augment-context-engine, context7, repomix, playwriter, gh_grep, sentry, socket) and LAZY_MCPS (claude-code-mcp, outscraper, dataforseo, shadcn, macos-automator, gsc, localwp, chrome-devtools, quickfile, amazon-order-history, google-analytics-mcp, MCP_DOCKER, ahrefs) classifications. Adds policy loop to enable/disable MCPs at runtime. Creates or updates MCP entries with enabled flags and tool toggles accordingly. Updates DEFAULT_TOOLS with new subagent patterns.
Per-Agent Tool Permissions
.agent/scripts/generate-opencode-agents.sh
Expands AGENT_TOOLS for Plan+, Build+, AI-DevOps, Onboarding, Accounts, Social-Media, SEO, WordPress, Content, and Research agents with new subagent tool patterns (gh_grep_*, playwriter_*, claude-code-mcp_*). Adds per-agent extra_tools mappings in subagent markdown generation.
Subagent Documentation & Index
.agent/subagent-index.toon, .agent/tools/ai-assistants/claude-code.md
Updates subagent index keyword tagging to include claude-code. Adds comprehensive markdown documentation for Claude Code MCP subagent including purpose, usage patterns, configuration, available tools, and best practices with YAML frontmatter.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🚀 MCPs march forth in eager stride,
While lazy ones await the call,
🎭 Playwriter dances, grep and code collide,
Subagents rise to answer all,
Tool permissions expand—DevOps thrives!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: introducing a lazy-load strategy for MCPs to optimize loading behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a lazy-loading strategy for MCPs to optimize startup time, which is a significant improvement. The changes are primarily within the generate-opencode-agents.sh script, where MCPs are now explicitly categorized as eager or lazy. The addition of a new @claude-code subagent is also a valuable enhancement. My review highlights a few areas for improvement in the script's robustness and maintainability, including a hardcoded path that impacts portability, a potential issue with uncategorized MCPs, some redundant code, and an inconsistency with a template file. Addressing these points will help make the implementation cleaner and more reliable.

import shutil
import platform
bun_path = shutil.which('bun')
npx_path = shutil.which('npx') or '/opt/homebrew/bin/npx'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The hardcoded fallback path for npx to /opt/homebrew/bin/npx compromises the script's portability. This path is specific to a particular setup on macOS (Homebrew on Apple Silicon) and will fail on other operating systems or different macOS configurations where npx might be located elsewhere.

To make the script more robust, it's better to rely solely on shutil.which('npx') to find the executable in the system's PATH. If npx is not found, you could then handle it gracefully by either printing a warning or exiting with an error message if it's a critical dependency.

Suggested change
npx_path = shutil.which('npx') or '/opt/homebrew/bin/npx'
npx_path = shutil.which('npx')

Comment on lines +520 to +524
for mcp_name in list(config.get('mcp', {}).keys()):
if mcp_name in EAGER_MCPS:
config['mcp'][mcp_name]['enabled'] = True
elif mcp_name in LAZY_MCPS:
config['mcp'][mcp_name]['enabled'] = False

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current logic only applies the loading policy to MCPs that are explicitly listed in EAGER_MCPS or LAZY_MCPS. If an MCP is present in the configuration but not categorized in either list, its enabled state remains unchanged. This could lead to inconsistent behavior and undermine the goal of a centralized loading policy.

To improve robustness, I suggest adding a handler for uncategorized MCPs. For instance, you could log a warning to alert the user that a new MCP needs to be categorized. This ensures that all MCPs are intentionally configured.

Suggested change
for mcp_name in list(config.get('mcp', {}).keys()):
if mcp_name in EAGER_MCPS:
config['mcp'][mcp_name]['enabled'] = True
elif mcp_name in LAZY_MCPS:
config['mcp'][mcp_name]['enabled'] = False
for mcp_name in list(config.get('mcp', {}).keys()):
if mcp_name in EAGER_MCPS:
config['mcp'][mcp_name]['enabled'] = True
elif mcp_name in LAZY_MCPS:
config['mcp'][mcp_name]['enabled'] = False
else:
print(f" Warning: MCP '{mcp_name}' is not categorized as eager or lazy. Its loading policy is unchanged.")

Comment on lines 595 to 597
else:
# Ensure existing config is set to lazy load
config['mcp']['outscraper']['enabled'] = False

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This else block, which sets enabled: False for an existing outscraper configuration, is redundant. The loop at lines 520-524 already iterates through all configured MCPs and sets their enabled state based on the EAGER_MCPS and LAZY_MCPS lists.

This redundant pattern is also present for dataforseo (lines 611-612), shadcn (lines 627-628), and macos-automator (lines 658-659).

To improve code clarity and maintainability, these else blocks should be removed. The centralized logic at the beginning of the section should be the single source of truth for enforcing the loading policy.

"type": "local",
"command": ["npx", "-y", "github:marcusquinn/claude-code-mcp"],
"enabled": True
"command": ["npx", "-y", "@steipete/claude-code-mcp"],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This line updates the claude-code-mcp command to use the upstream package @steipete/claude-code-mcp instead of a fork. This is a positive change. However, the corresponding template file, configs/mcp-templates/claude-code-mcp.json, still references the old fork (github:marcusquinn/claude-code-mcp).

This inconsistency could cause confusion or issues if the template is used for other configurations. To ensure consistency across the codebase, please consider updating configs/mcp-templates/claude-code-mcp.json to reflect this change as well.

@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 479 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Jan 25 02:19:24 UTC 2026: Code review monitoring started
Sun Jan 25 02:19:24 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 479
Sun Jan 25 02:19:24 UTC 2026: Qlty - 0 issues found, auto-formatting applied
Sun Jan 25 02:19:26 UTC 2026: Codacy analysis completed with auto-fixes

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 479
  • VULNERABILITIES: 0

Generated on: Sun Jan 25 02:20:50 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@augmentcode
Copy link

augmentcode bot commented Jan 25, 2026

🤖 Augment PR Summary

Summary: Refactors OpenCode agent generation to reduce startup time by lazy-loading most MCP servers.
Key Changes:

  • Adds an eager vs. lazy MCP loading policy and applies it to existing MCP entries in opencode.json.
  • Moves claude-code-mcp behind a new @claude-code subagent and disables its tools globally by default.
  • Adds the remote gh_grep MCP and enables gh_grep_* for Plan+/Build+/AI-DevOps.
  • Configures Playwriter as an eager-loaded MCP and enables playwriter_* broadly for main agents.
  • Enables repomix_* broadly for main agents.
  • Marks several niche MCPs (outscraper, dataforseo, shadcn, macos-automator, etc.) as lazy-loaded.
  • Updates the subagent index to include the new claude-code assistant entry.
Technical Notes: Relies on enabled: false on MCP definitions to defer startup until a subagent invokes the relevant tools. Startup impact: fewer MCP servers initialized at launch, with capabilities loaded on-demand as needed.

🤖 Was this summary useful? React with 👍 or 👎

Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 4 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

print(" Added gh_grep MCP (eager load - used by Plan+/Build+/AI-DevOps)")

# gh_grep tools disabled globally, enabled for specific agents
if 'gh_grep_*' not in config['tools']:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only disables gh_grep_* when the key is missing; if an existing opencode.json already has it true, the intended restriction to Plan+/Build+/AI-DevOps won't take effect. Is preserving pre-existing global enablement intentional for upgrades?

Other Locations
  • .agent/scripts/generate-opencode-agents.sh:599
  • .agent/scripts/generate-opencode-agents.sh:614
  • .agent/scripts/generate-opencode-agents.sh:630
  • .agent/scripts/generate-opencode-agents.sh:661

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

print(" Set gh_grep_* disabled globally (enabled for Plan+/Build+/AI-DevOps)")

# repomix_* enabled globally (used by all main agents)
config['tools']['repomix_*'] = True
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repomix_* is enabled globally here, but this script doesn't appear to create a config['mcp']['repomix'] entry if it's missing, so fresh configs may end up with enabled tools but no server. If repomix is expected to be present from elsewhere, it may be worth clarifying that assumption.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

elif mcp_name in LAZY_MCPS:
config['mcp'][mcp_name]['enabled'] = False

print(f" Applied MCP loading policy: {len(EAGER_MCPS)} eager, {len(LAZY_MCPS)} lazy")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAZY_MCPS currently contains 13 entries (so the log prints {len(LAZY_MCPS)} lazy), but the PR description/comments mention 12 lazy-loaded MCPs. Worth double-checking which set is intended to avoid confusing output.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎


| Tool | Description |
|------|-------------|
| `claude_code` | Execute a prompt via Claude Code CLI |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc lists the tool as claude_code, but elsewhere the MCP indexing/naming pattern uses <mcp>_<tool> names (e.g., claude-code-mcp_run_claude_code). Consider verifying the exposed tool name so users can invoke the right command.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.agent/scripts/generate-opencode-agents.sh:
- Around line 502-506: The fallback for locating npx is macOS-specific
(/opt/homebrew/bin/npx); update the npx resolution so it does not hardcode a
Homebrew path: change how npx_path and pkg_runner are determined (variables
bun_path, npx_path, pkg_runner) to use a platform-agnostic fallback such as just
'npx' (or prefer shutil.which('npx') and if that returns None use 'npx') so
pkg_runner will resolve correctly on Linux and other systems.
🧹 Nitpick comments (3)
.agent/scripts/generate-opencode-agents.sh (2)

519-526: Consider defensive access when enforcing MCP policy.

The loop assumes all existing MCP entries have a dict structure with an enabled key. If an MCP entry is malformed or has a different structure, this could raise a KeyError or TypeError.

♻️ Defensive access pattern
 for mcp_name in list(config.get('mcp', {}).keys()):
+    mcp_cfg = config['mcp'].get(mcp_name, {})
+    if not isinstance(mcp_cfg, dict):
+        continue
     if mcp_name in EAGER_MCPS:
-        config['mcp'][mcp_name]['enabled'] = True
+        mcp_cfg['enabled'] = True
     elif mcp_name in LAZY_MCPS:
-        config['mcp'][mcp_name]['enabled'] = False
+        mcp_cfg['enabled'] = False

789-793: Summary output should mention the new eager/lazy policy.

The summary section mentions "MCPs disabled globally, enabled per-agent" which is the old messaging. Consider updating to reflect the new eager/lazy loading strategy more accurately.

♻️ Updated summary messaging
 echo "MCP Loading Strategy:"
-echo "  - MCPs disabled globally, enabled per-agent (reduces context tokens)"
+echo "  - Eager MCPs: Start at launch (osgrep, context7, playwriter, etc.)"
+echo "  - Lazy MCPs: Start on-demand via subagents (claude-code-mcp, dataforseo, etc.)"
 echo "  - Use 'mcp-index-helper.sh search <query>' to discover tools on-demand"
 echo "  - Subagents enable specific MCPs via frontmatter tools: section"
.agent/tools/ai-assistants/claude-code.md (1)

107-112: Document the cost implications of nested Claude invocations.

The "Avoid loops" guidance is solid and correctly prevents infinite recursion and token exhaustion. Consider expanding this best practice to mention the potential cost multiplier of nested Claude invocations, as this provides developers with additional context for the prohibition on sub-agent loops.

- Remove hardcoded /opt/homebrew/bin/npx fallback, use shutil.which only
- Add warning for uncategorized MCPs in loading policy
- Remove redundant else blocks that duplicated loading policy logic
- Update claude-code-mcp.json template to use upstream @steipete package
- Add sys import for stderr warnings
Keep using github:marcusquinn/claude-code-mcp fork until
steipete/claude-code-mcp#40 is merged.
@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 479 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Jan 25 02:24:01 UTC 2026: Code review monitoring started
Sun Jan 25 02:24:01 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 479
Sun Jan 25 02:24:02 UTC 2026: Qlty - 0 issues found, auto-formatting applied
Sun Jan 25 02:24:04 UTC 2026: Codacy analysis completed with auto-fixes

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 479
  • VULNERABILITIES: 0

Generated on: Sun Jan 25 02:25:25 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 479 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Jan 25 02:25:50 UTC 2026: Code review monitoring started
Sun Jan 25 02:25:50 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 479
Sun Jan 25 02:25:50 UTC 2026: Qlty - 0 issues found, auto-formatting applied
Sun Jan 25 02:25:52 UTC 2026: Codacy analysis completed with auto-fixes

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 479
  • VULNERABILITIES: 0

Generated on: Sun Jan 25 02:27:15 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@marcusquinn marcusquinn merged commit 74ee00d into main Jan 25, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant