docs: add MCP lifecycle pattern and fix GSC/identity docs#173
docs: add MCP lifecycle pattern and fix GSC/identity docs#173marcusquinn merged 2 commits intomainfrom
Conversation
…ewrite - Add MCP lifecycle decision framework to architecture.md (when MCP vs curl) - Document three-tier MCP strategy (global, per-agent, replaced) - Fix stale SEO agent example in architecture.md - Add curl OAuth2 fallback to GSC subagent (JWT token exchange pattern) - Update GSC description to reflect MCP-primary with curl fallback - Clarify OpenCode→Claude Code identity rewrite is intentional design
Summary of ChangesHello @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 significantly enhances the project's documentation and clarifies core architectural decisions. It introduces a comprehensive lifecycle pattern for managing Multi-Context Proxy (MCP) tools, providing a clear framework for their usage and migration. Additionally, it refines the documentation for the Google Search Console (GSC) subagent, detailing its primary MCP integration and offering robust curl-based fallback instructions. Finally, it addresses potential confusion by explicitly documenting an intentional identity rewrite within prompts, ensuring consistency and preventing unintended modifications. Highlights
Using Gemini Code AssistThe 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
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 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
|
|
Caution Review failedThe pull request is closed. Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughDocumentation and scripts add a formal MCP lifecycle pattern and tool-gating model, update agent tool enablement in opencode.json guidance, make Google Search Console MCP-primary with a curl fallback and Playwright onboarding, add a cleanup routine and auto-enable logic in setup.sh, and clarify prompt identity rewriting for runtime auth. Changes
Sequence Diagram(s)sequenceDiagram
participant Agent as User Agent
participant Config as opencode.json
participant Decision as MCP Lifecycle Decision
participant MCP as MCP Server (gsc_*)
participant Curl as Curl Subagent
participant API as External API (Google Search Console)
Agent->>Config: read tool/tier configuration
Agent->>Decision: evaluate MCP vs curl (tool count, auth, sessions, state)
Decision-->>MCP: select MCP path (tier 1/2)
MCP->>API: proxy requests (gsc_* tools)
Decision-->>Curl: select curl subagent (tier 2/3)
Curl->>API: direct OAuth2 / curl requests
API-->>Agent: return data
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Sat Jan 24 15:29:22 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
There was a problem hiding this comment.
Code Review
This pull request introduces valuable documentation for the MCP lifecycle pattern and correctly updates the Google Search Console documentation to reflect its new MCP-primary, curl-fallback architecture. The clarification regarding the OpenCode vs Claude Code identity is also a welcome improvement to prevent future confusion. The overall changes are good, but I've identified a couple of critical issues in the new curl fallback examples for GSC. The provided shell commands will fail as written due to incorrect handling of home directory paths. I've included specific suggestions to fix these bugs.
| # Test GSC MCP connection | ||
| opencode mcp list | grep -i search | ||
| # Verify credentials file | ||
| python3 -c "import json; d=json.load(open('$HOME/.config/aidevops/gsc-credentials.json')); print(f'Service account: {d[\"client_email\"]}')" |
There was a problem hiding this comment.
This command will fail because the shell does not expand the $HOME variable inside single quotes. Python will then attempt to open a file at the literal path $HOME/..., which doesn't exist. Using os.path.expanduser('~/...') is a more robust way to resolve the home directory path.
| python3 -c "import json; d=json.load(open('$HOME/.config/aidevops/gsc-credentials.json')); print(f'Service account: {d[\"client_email\"]}')" | |
| python3 -c "import json, os; d=json.load(open(os.path.expanduser('~/.config/aidevops/gsc-credentials.json'))); print(f'Service account: {d[\"client_email\"]}')" |
| import json, time, jwt, requests | ||
| creds = json.load(open('$HOME/.config/aidevops/gsc-credentials.json')) | ||
| now = int(time.time()) | ||
| payload = {'iss': creds['client_email'], 'scope': 'https://www.googleapis.com/auth/webmasters.readonly', | ||
| 'aud': creds['token_uri'], 'iat': now, 'exp': now + 3600} | ||
| signed = jwt.encode(payload, creds['private_key'], algorithm='RS256') | ||
| r = requests.post(creds['token_uri'], data={'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion': signed}) | ||
| print(r.json()['access_token']) |
There was a problem hiding this comment.
This Python script has a few issues that will prevent it from running correctly:
- Path Expansion: The shell won't expand
$HOMEinside the single-quoted path string on line 63, causing the script to fail when trying to open the credentials file. This can be fixed by usingos.path.expanduser('~/.config/...'). - File Handling: The file is opened without a
withstatement, meaning it might not be closed properly if an error occurs. It's best practice to usewith open(...). - Error Handling: The
requests.postcall on line 68 does not check for HTTP errors. If the request fails, the script will raise an unhandled exception whenr.json()is called. It's better to addr.raise_for_status()to handle potential network or authentication issues gracefully.
| import json, time, jwt, requests | |
| creds = json.load(open('$HOME/.config/aidevops/gsc-credentials.json')) | |
| now = int(time.time()) | |
| payload = {'iss': creds['client_email'], 'scope': 'https://www.googleapis.com/auth/webmasters.readonly', | |
| 'aud': creds['token_uri'], 'iat': now, 'exp': now + 3600} | |
| signed = jwt.encode(payload, creds['private_key'], algorithm='RS256') | |
| r = requests.post(creds['token_uri'], data={'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion': signed}) | |
| print(r.json()['access_token']) | |
| import json, time, jwt, requests, os | |
| with open(os.path.expanduser('~/.config/aidevops/gsc-credentials.json')) as f: | |
| creds = json.load(f) | |
| now = int(time.time()) | |
| payload = {'iss': creds['client_email'], 'scope': 'https://www.googleapis.com/auth/webmasters.readonly', | |
| 'aud': creds['token_uri'], 'iat': now, 'exp': now + 3600} | |
| signed = jwt.encode(payload, creds['private_key'], algorithm='RS256') | |
| r = requests.post(creds['token_uri'], data={'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion': signed}) | |
| r.raise_for_status() | |
| print(r.json()['access_token']) |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @.agent/aidevops/architecture.md:
- Around line 116-118: Fix the typo "playwriter" to "playwright" in the
architecture documentation: update the list entry currently reading "playwriter"
to "playwright" (and search for any other occurrences of the string "playwriter"
in the repo to replace them) so tool naming and discovery match the actual
Playwright subagent.
In @.agent/seo/google-search-console.md:
- Around line 19-24: The "Capabilities" entry claiming "indexing requests" is
misleading because the example labeled "Submit URL for indexing" uses the URL
Inspection API (`urlInspection/index:inspect`) which only inspects status and
the doc currently references the `webmasters.readonly` scope; either remove
"indexing requests" from the Capabilities list and rename the example to
"Inspect URL index status" (update the example title and text to reflect
`urlInspection/index:inspect`), or add a new section describing the actual
Indexing API (`indexing.googleapis.com/v3/urlNotifications:publish`) including
required `auth/indexing` scope and the content restrictions
(JobPosting/BroadcastEvent) so readers know submission requires a separate API
and scope.
| 1. **Globally enabled** (always loaded, ~2K tokens each): osgrep, augment-context-engine, claude-code-mcp | ||
| 2. **Enabled, tools disabled** (zero context until agent invokes): gsc, outscraper, google-analytics-mcp, quickfile, amazon-order-history, context7, repomix, playwriter, chrome-devtools, etc. | ||
| 3. **Replaced by curl subagent** (removed entirely): hetzner, serper, dataforseo, ahrefs, hostinger |
There was a problem hiding this comment.
Typo: “playwriter” → “playwright”.
This will confuse tool naming and discovery.
🔧 Suggested fix
-2. **Enabled, tools disabled** (zero context until agent invokes): gsc, outscraper, google-analytics-mcp, quickfile, amazon-order-history, context7, repomix, playwriter, chrome-devtools, etc.
+2. **Enabled, tools disabled** (zero context until agent invokes): gsc, outscraper, google-analytics-mcp, quickfile, amazon-order-history, context7, repomix, playwright, chrome-devtools, etc.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 1. **Globally enabled** (always loaded, ~2K tokens each): osgrep, augment-context-engine, claude-code-mcp | |
| 2. **Enabled, tools disabled** (zero context until agent invokes): gsc, outscraper, google-analytics-mcp, quickfile, amazon-order-history, context7, repomix, playwriter, chrome-devtools, etc. | |
| 3. **Replaced by curl subagent** (removed entirely): hetzner, serper, dataforseo, ahrefs, hostinger | |
| 1. **Globally enabled** (always loaded, ~2K tokens each): osgrep, augment-context-engine, claude-code-mcp | |
| 2. **Enabled, tools disabled** (zero context until agent invokes): gsc, outscraper, google-analytics-mcp, quickfile, amazon-order-history, context7, repomix, playwright, chrome-devtools, etc. | |
| 3. **Replaced by curl subagent** (removed entirely): hetzner, serper, dataforseo, ahrefs, hostinger |
🤖 Prompt for AI Agents
In @.agent/aidevops/architecture.md around lines 116 - 118, Fix the typo
"playwriter" to "playwright" in the architecture documentation: update the list
entry currently reading "playwriter" to "playwright" (and search for any other
occurrences of the string "playwriter" in the repo to replace them) so tool
naming and discovery match the actual Playwright subagent.
| - **Primary access**: MCP tools (`gsc_*`) - enabled for SEO agent | ||
| - **Fallback**: curl with OAuth2 token from service account | ||
| - **API**: REST at `https://searchconsole.googleapis.com/v1/` | ||
| - **Auth**: Service account JSON at `~/.config/aidevops/gsc-credentials.json` | ||
| - **Capabilities**: Search analytics, URL inspection, indexing requests, sitemap management | ||
| - **Metrics**: clicks, impressions, ctr, position |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's view the file to understand the full context
cat -n .agent/seo/google-search-console.md | head -100Repository: marcusquinn/aidevops
Length of output: 4240
🌐 Web query:
Google Search Console API URL Inspection endpoint scope requirements webmasters.readonly
💡 Result:
The Search Console API URL Inspection endpoint (urlInspection.index.inspect → POST https://searchconsole.googleapis.com/v1/urlInspection/index:inspect) accepts either of these OAuth scopes:
https://www.googleapis.com/auth/webmasters.readonly(read-only)https://www.googleapis.com/auth/webmasters(read/write)
So webmasters.readonly is sufficient for calling the URL Inspection endpoint. [1]
🌐 Web query:
Google Indexing API vs Search Console API URL submission scope requirements
💡 Result:
Google Indexing API (URL submission)
- What it can submit: Individual URL notifications (
URL_UPDATED,URL_DELETED) to trigger recrawling/removal. (developers.google.com) - Allowed content scope (not OAuth scope): Only URLs whose pages contain structured data for
JobPostingorBroadcastEventembedded in aVideoObject. (developers.google.com) - OAuth scope required:
https://www.googleapis.com/auth/indexing. (developers.google.com) - Property/permission requirement: You must verify the site in Search Console and add the service account as a delegated owner of that Search Console property. (developers.google.com)
Google Search Console API (no “request indexing” URL submission)
- What it can do instead:
- URL Inspection API can inspect a URL’s index status, not submit it for indexing. (developers.google.com)
- Can manage/list sites and submit sitemaps (discovery), but this is not the same as submitting a single URL for “Request indexing”. (developers.google.com)
- OAuth scopes used (depends on method):
- URL Inspection:
https://www.googleapis.com/auth/webmastersor.../webmasters.readonly. (developers.google.com) - Sites list:
.../webmastersor.../webmasters.readonly. (developers.google.com) - Sites add:
.../webmasters. (developers.google.com)
- URL Inspection:
- URL/property requirement (URL Inspection): The inspected URL must be under the Search Console property provided in
siteUrl. (developers.google.com)
Net: If you need programmatic per-URL submission, Google only provides that via the Indexing API, and only for JobPosting/BroadcastEvent pages, using the auth/indexing scope plus Search Console ownership/delegation. (developers.google.com)
Citations:
- 1: https://developers.google.com/search/apis/indexing-api/v3/using-api?utm_source=openai
- 2: https://developers.google.com/search/apis/indexing-api/v3/using-api?utm_source=openai
- 3: https://developers.google.com/search/apis/indexing-api/v3/prereqs
- 4: https://developers.google.com/search/apis/indexing-api/v3/prereqs
- 5: https://developers.google.com/webmaster-tools/v1/urlInspection.index/inspect?utm_source=openai
- 6: https://developers.google.com/webmaster-tools/v1/api_reference_index?utm_source=openai
- 7: https://developers.google.com/webmaster-tools/v1/urlInspection.index/inspect?utm_source=openai
- 8: https://developers.google.com/webmaster-tools/v1/sites/list?utm_source=openai
- 9: https://developers.google.com/webmaster-tools/v1/sites/add?utm_source=openai
- 10: https://developers.google.com/webmaster-tools/v1/urlInspection.index/inspect?utm_source=openai
- 11: https://developers.google.com/search/apis/indexing-api/v3/using-api?utm_source=openai
Remove misleading "indexing requests" or clarify it requires a separate API setup.
The example at lines 87–91 is labeled "Submit URL for indexing" but uses the URL Inspection API (urlInspection/index:inspect), which only inspects index status—it does not submit URLs for indexing. Actual URL submission requires the Indexing API (indexing.googleapis.com/v3/urlNotifications:publish) with the separate auth/indexing scope and is restricted to JobPosting or BroadcastEvent content.
The doc's "Capabilities" line lists "indexing requests" and "sitemap management" as supported, but the example and scope (webmasters.readonly) don't support URL submission. Either:
- Remove "indexing requests" from the capabilities list, or
- Add a separate section with the correct Indexing API endpoint, scope, and content restrictions.
🤖 Prompt for AI Agents
In @.agent/seo/google-search-console.md around lines 19 - 24, The "Capabilities"
entry claiming "indexing requests" is misleading because the example labeled
"Submit URL for indexing" uses the URL Inspection API
(`urlInspection/index:inspect`) which only inspects status and the doc currently
references the `webmasters.readonly` scope; either remove "indexing requests"
from the Capabilities list and rename the example to "Inspect URL index status"
(update the example title and text to reflect `urlInspection/index:inspect`), or
add a new section describing the actual Indexing API
(`indexing.googleapis.com/v3/urlNotifications:publish`) including required
`auth/indexing` scope and the content restrictions (JobPosting/BroadcastEvent)
so readers know submission requires a separate API and scope.
🤖 Augment PR SummarySummary: Documents the MCP lifecycle decision framework and reconciles agent docs with current MCP usage. 🤖 Was this summary useful? React with 👍 or 👎 |
|
|
||
| ```python | ||
| # Tools disabled globally, enabled per-agent | ||
| GLOBAL_TOOLS = {"gsc_*": False, "outscraper_*": False, "osgrep_*": True, ...} |
There was a problem hiding this comment.
The GLOBAL_TOOLS example shows osgrep_* enabled globally, but generate-opencode-agents.sh currently writes config.tools.osgrep_* = false and relies on per-agent enablement. This mismatch could cause readers to configure opencode.json in a way that doesn’t match the generator’s behavior.
🤖 Was this useful? React with 👍 or 👎
| "Build+": {"write": True, "context7_*": True, "osgrep_*": True, ...}, | ||
| "SEO": {"gsc_*": True, "dataforseo_*": True, "serper_*": True, ...}, | ||
| "Build+": {"write": True, "context7_*": True, "repomix_*": True, ...}, | ||
| "SEO": {"gsc_*": True, "google-analytics-mcp_*": True, ...}, |
There was a problem hiding this comment.
This snippet implies the SEO agent enables google-analytics-mcp_* directly, but services/analytics/google-analytics.md describes GA tools as being enabled via the @google-analytics subagent. If the subagent-only pattern is the intended design, the example here may be misleading.
🤖 Was this useful? React with 👍 or 👎
|
|
||
| 1. **Globally enabled** (always loaded, ~2K tokens each): osgrep, augment-context-engine, claude-code-mcp | ||
| 2. **Enabled, tools disabled** (zero context until agent invokes): gsc, outscraper, google-analytics-mcp, quickfile, amazon-order-history, context7, repomix, playwriter, chrome-devtools, etc. | ||
| 3. **Replaced by curl subagent** (removed entirely): hetzner, serper, dataforseo, ahrefs, hostinger |
There was a problem hiding this comment.
Tier 3 states serper, dataforseo, ahrefs, etc are “removed entirely”, but the repo still configures these MCP servers (e.g., in generate-opencode-agents.sh) and references them in .agent/seo.md. If this table is meant as a future target, it might help to call that out so readers don’t assume the current config already matches.
🤖 Was this useful? React with 👍 or 👎
| -H "Authorization: Bearer $ACCESS_TOKEN" | ||
|
|
||
| # Search analytics query | ||
| curl -s -X POST "https://searchconsole.googleapis.com/v1/sites/https%3A%2F%2Fexample.com/searchAnalytics/query" \ |
There was a problem hiding this comment.
The sites/{siteUrl} examples omit the trailing / that URL-prefix properties require (and thus the %2F at the end of the URL-encoded path), so copy/paste may fail against real properties. Same issue applies to the siteUrl value in the URL Inspection request body.
Other Locations
.agent/seo/google-search-console.md:91
🤖 Was this useful? React with 👍 or 👎
| "rowLimit": 25 | ||
| }' | ||
|
|
||
| # Submit URL for indexing |
- setup_google_analytics_mcp() auto-detects shared GSC credentials - Add cleanup_deprecated_mcps step to main() flow - Update SEO confirm_step text (curl subagents, not MCP servers) - Update final output to show GSC/GA MCPs and SEO curl subagents
|
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Sat Jan 24 15:40:17 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |



Summary
Changes
.agent/aidevops/architecture.md.agent/seo/google-search-console.md.agent/prompts/build.txtMCP Lifecycle Pattern (new)
Three-tier strategy:
Decision factors: tool count, auth complexity, session frequency, context cost, statefulness.
Summary by CodeRabbit
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.