Skip to content

feat(gemini): GM-AG-001 validate auth block in agent MCP servers (#809)#817

Merged
avifenesh merged 3 commits intomainfrom
feat/gm-ag-001-agent-mcp-auth-block
Apr 26, 2026
Merged

feat(gemini): GM-AG-001 validate auth block in agent MCP servers (#809)#817
avifenesh merged 3 commits intomainfrom
feat/gm-ag-001-agent-mcp-auth-block

Conversation

@avifenesh
Copy link
Copy Markdown
Collaborator

@avifenesh avifenesh commented Apr 25, 2026

Summary

Adds GM-AG-001 which validates the `auth` block inside `mcp_servers.` entries in Gemini CLI local agent markdown files (`.gemini/agents/*.md`). This block was added in gemini-cli v0.39.0 via google-gemini/gemini-cli#24770.

Closes

Upstream schema

From `packages/core/src/agents/agentLoader.ts` in the upstream PR:

```typescript
const mcpServerSchema = z.object({
// ... other fields ...
auth: z.union([
z.object({
type: z.literal('google-credentials'),
scopes: z.array(z.string()).optional(),
}),
z.object({
type: z.literal('oauth'),
client_id: z.string().optional(),
client_secret: z.string().optional(),
scopes: z.array(z.string()).optional(),
authorization_url: z.string().url().optional(),
token_url: z.string().url().optional(),
}),
]).optional(),
});
```

Behavior

Valid - google-credentials variant:
```yaml
mcp_servers:
spanner:
auth:
type: google-credentials
scopes:
- https://www.googleapis.com/auth/cloud-platform
```

Valid - oauth variant:
```yaml
mcp_servers:
remote:
auth:
type: oauth
client_id: abc
client_secret: xyz
scopes: [read, write]
authorization_url: https://accounts.example.com/authorize
token_url: https://accounts.example.com/token
```

Flagged:

  • Missing `type` discriminator
  • Invalid `type` value (not "google-credentials" or "oauth")
  • OAuth fields under google-credentials variant (`client_id`, etc.)
  • Unknown fields under oauth variant
  • Non-string `client_id` / `client_secret`
  • Malformed `authorization_url` / `token_url` (must be http(s)://host/…)
  • `scopes` not an array, or scope entry not a string

Implementation

  • New FileType variant `FileType::GeminiAgent` with detection for files ending in `.md` where the parent is `agents` and the grandparent is `.gemini`.
  • New validator `GeminiAgentValidator` with:
    • Frontmatter extractor (`---`-delimited YAML, BOM-tolerant)
    • YAML parser via `serde_yaml` (already a workspace dep)
    • Per-server auth block walker
    • Per-variant schema enforcement (google-credentials allows only `type` + `scopes`; oauth allows the five documented fields)
    • Best-effort line scanner that locates `auth:` under `mcp_servers.:`
    • Lenient URL classifier (http:// or https:// + non-empty host)

Test plan

  • 24 unit tests - see commit message for the full list
  • Valid fixture: `tests/fixtures/valid/gemini-agents/.gemini/agents/spanner.md` (mirrors the test case from the upstream PR)
  • Invalid fixture: `tests/fixtures/invalid/gemini-agents/.gemini/agents/broken.md`
  • `cargo test --workspace --all-targets` passes
  • `cargo clippy --workspace --all-targets -- -D warnings` clean
  • Docs site regenerated, parity tests green

Housekeeping

  • `total_rules`: 413 → 414
  • `validator count`: 41 → 42
  • `FileType` variants: 45 → 46
  • `EXPECTED_BUILTIN_COUNT`: 76 → 77, MiscProvider count 26 → 27
  • New `gemini-agents` rule category + `GM-AG-` prefix

Follow-ups

7/7 of the rule-candidate series for v0.21.0 done! Remaining session work:


Note

Medium Risk
Adds a new FileType::GeminiAgent and validator registration, which changes file-type detection and validation coverage for .gemini/agents/*.md; risk is moderate but scoped to new Gemini agent surfaces with extensive tests/fixtures.

Overview
Adds GM-AG-001 to validate the auth block under mcp_servers.* in Gemini CLI local agent files (.gemini/agents/*.md), enforcing the type discriminator (google-credentials vs oauth), rejecting unknown fields per variant, type-checking strings/arrays, and doing basic http(s) URL sanity checks.

Introduces FileType::GeminiAgent (with detection for .gemini/agents/*.md) and wires a new GeminiAgentValidator into the default registry, i18n strings, and rule-parity/category plumbing; adds valid/invalid fixtures, unit tests, and regenerates rule/docs metadata (rule counts bumped 413 → 414).

Reviewed by Cursor Bugbot for commit 1e19964. Configure here.

Gemini CLI v0.39.0 added support for an `auth` block inside
`mcp_servers.<name>` entries in local agent markdown frontmatter -
google-gemini/gemini-cli#24770. Two variants:

- type: "google-credentials" - only `scopes` allowed beyond type
- type: "oauth" - client_id, client_secret, scopes, authorization_url,
  token_url are all optional strings/arrays

Schema extracted from packages/core/src/agents/agentLoader.ts Zod
definitions in the upstream PR.

- New FileType::GeminiAgent variant; detection for *.md files with
  `agents` parent and `.gemini` grandparent.
- New crates/agnix-core/src/rules/gemini_agent.rs with the
  GeminiAgentValidator:
  - Extracts YAML frontmatter between --- markers
  - Parses via serde_yaml (workspace dep)
  - Walks mcp_servers.*.auth and validates each block
  - Enforces discriminator, rejects unknown fields per variant,
    type-checks strings + arrays, validates URL shape for
    authorization_url + token_url
  - Best-effort line scanner for reporting position
- 24 unit tests covering: both variant happy paths, missing type,
  invalid type, non-object auth, unknown field per variant, non-string
  client_id, malformed URL, valid URL accepted, scopes shape, per-
  server independent validation, disable path, URL classifier unit
  tests, frontmatter extractor unit tests.
- Valid/invalid fixtures under tests/fixtures/{valid,invalid}/gemini-agents/.
- New gemini-agents rule category + GM-AG- prefix registered in
  rule_parity + "Gemini Agents" label in docs generator.
- total_rules 413 -> 414, validator count 41 -> 42, FileType variants
  45 -> 46.

Closes #809.
Copilot AI review requested due to automatic review settings April 25, 2026 23:57
Copy link
Copy Markdown
Contributor

@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 new validation rule, GM-AG-001, to verify the 'auth' block in Gemini CLI agent MCP configurations. The changes include the implementation of a new GeminiAgentValidator, detection logic for .gemini/agents/*.md files, and comprehensive updates to documentation, localization, and test fixtures. Review feedback correctly identifies a compilation risk regarding the use of unstable 'let chains' in the new validator and provides a more efficient implementation for frontmatter extraction to avoid unnecessary performance overhead.

Comment thread crates/agnix-core/src/rules/gemini_agent.rs
Comment thread crates/agnix-core/src/rules/gemini_agent.rs Outdated
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1e19964. Configure here.

Comment thread crates/agnix-core/src/rules/gemini_agent.rs
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Gemini CLI validator + rule (GM-AG-001) to validate the auth block under mcp_servers.<name> in local Gemini agent markdown frontmatter (.gemini/agents/*.md), aligning agnix with the gemini-cli v0.39.0 schema update.

Changes:

  • Introduces FileType::GeminiAgent with path-based detection for .gemini/agents/*.md.
  • Adds GeminiAgentValidator implementing GM-AG-001 (auth discriminator + per-variant field/type checks + URL/scopes validation) with unit tests and fixtures.
  • Updates rule inventories/docs/site counts and rule parity bookkeeping to include the new rule/category.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
website/src/data/siteData.json Bumps totalRules to 414 for the website.
website/docs/rules/index.md Updates rule count and adds GM-AG-001 to the rules index table.
website/docs/rules/generated/gm-ag-001.md Adds generated documentation page for GM-AG-001.
tests/fixtures/valid/gemini-agents/.gemini/agents/spanner.md Adds a valid Gemini agent fixture including an auth block.
tests/fixtures/invalid/gemini-agents/.gemini/agents/broken.md Adds an invalid Gemini agent fixture with unsupported auth.type.
scripts/generate-docs-rules.py Adds display label for new gemini-agents category.
knowledge-base/rules.json Increments total_rules and adds the GM-AG-001 rule entry.
knowledge-base/VALIDATION-RULES.md Documents the new Gemini agent rule section and GM-AG-001.
crates/agnix-rules/rules.json Mirrors knowledge-base rule additions for the Rust crate.
crates/agnix-core/tests/api_contract.rs Updates FileType variant coverage assertions for GeminiAgent.
crates/agnix-core/src/rules/mod.rs Exposes the new gemini_agent validator module.
crates/agnix-core/src/rules/gemini_agent.rs Implements GeminiAgentValidator and unit tests for GM-AG-001.
crates/agnix-core/src/registry.rs Registers the new file type + validator and updates expected counts.
crates/agnix-core/src/file_types/types.rs Adds FileType::GeminiAgent enum variant and Display mapping.
crates/agnix-core/src/file_types/detection.rs Detects .gemini/agents/*.md as FileType::GeminiAgent.
crates/agnix-core/locales/en.yml Adds i18n strings for GM-AG-001 diagnostics.
crates/agnix-cli/tests/rule_parity.rs Adds category + fixtures mapping for gemini-agents.
README.md Updates the headline rule count to 414.
CLAUDE.md Updates rule/validator counts to reflect the new additions.
CHANGELOG.md Adds an Unreleased entry describing GM-AG-001 and related plumbing.
AGENTS.md Mirrors CLAUDE.md count updates (keeps parity).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread knowledge-base/rules.json Outdated
Comment thread crates/agnix-core/src/registry.rs
Comment thread crates/agnix-core/src/file_types/types.rs
- cursor: non-string `auth.type` (e.g. numeric) was reported as
  "missing type" because .and_then(as_str) collapses missing-key and
  wrong-type into the same None. Split into two diagnostics: missing
  stays as gm_ag_001.missing_type; non-string uses gm_ag_001.not_string
  with field='type'. New regression test
  test_non_string_type_flags_as_type_not_string.
- gemini: extract_frontmatter was O(N^2) because it re-split + summed
  line lengths on every closing-marker hit. Rewrote to walk lines once
  with a running byte offset.
- gemini: let-chain syntax flagged as unstable is a false positive -
  the workspace uses Rust edition 2024 where let-chains are stable;
  reply in thread.
- Rule name casing. "Invalid auth Block in Agent MCP Server" had
  inconsistent capitalization. Renamed to "Invalid auth block in
  Gemini agent MCP server" - sentence case + explicit tool name.
- GeminiAgent was losing XML/Imports/CrossPlatform checks. Those
  previously ran on .gemini/agents/*.md via the GenericMarkdown
  fallback; now registered explicitly for FileType::GeminiAgent so
  agent body markdown keeps XML-balance + import + cross-platform
  validation alongside the new GM-AG-001.
- Updated types.rs unit tests (display_all_variants,
  is_validatable_all_variants, is_generic_only_for_generic_markdown)
  to include both KiroSettings (from #808) and GeminiAgent so
  exhaustive-variant coverage is maintained.
- Bumped EXPECTED_BUILTIN_COUNT 77 -> 80 and MiscProvider count 27 -> 30
  for the three additional validator registrations.
- disable_after_construction_removes_from_cache test updated to expect
  XmlValidator on 11 file types (was 10 - GeminiAgent now has it too).
Copilot AI review requested due to automatic review settings April 26, 2026 00:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +64 to +67
let parsed: serde_yaml::Value = match serde_yaml::from_str(frontmatter_raw) {
Ok(v) => v,
Err(_) => return diagnostics, // Malformed YAML surfaced by other validators
};
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

serde_yaml::from_str(frontmatter_raw) parse errors are silently ignored (Err(_) => return diagnostics). For FileType::GeminiAgent, the registry only runs GeminiAgentValidator + generic markdown validators (CrossPlatform/Xml/Imports), so malformed YAML frontmatter likely produces no diagnostics at all and also prevents GM-AG-001 from running. Consider emitting a diagnostic on YAML parse failure (ideally using error.location() for line/col) so users get actionable feedback when the frontmatter is syntactically invalid.

Copilot uses AI. Check for mistakes.
Comment on lines +386 to +388
for (idx, line) in content.lines().enumerate() {
let trimmed = line.trim_start();
let lead_ws_len = line.len() - trimmed.len();
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

find_auth_line scans the entire file body (for ... in content.lines()), not just the YAML frontmatter section. If the markdown body mentions mcp_servers: / server names (or contains code blocks with similar YAML), the line scanner can return a line number from outside frontmatter, producing confusing diagnostics. Consider scanning only within the extracted frontmatter (and offsetting by the frontmatter start line), or stopping the scan once the closing --- delimiter is reached.

Copilot uses AI. Check for mistakes.
@avifenesh avifenesh merged commit 53269e2 into main Apr 26, 2026
25 checks passed
@avifenesh avifenesh deleted the feat/gm-ag-001-agent-mcp-auth-block branch April 26, 2026 00:24
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.

2 participants