Skip to content

feat: MCP server (analyze / explain_rule) — closes #24 - #28

Merged
oekazuma merged 12 commits into
mainfrom
feat/mcp-server
Jun 22, 2026
Merged

oekazuma merged 12 commits into
mainfrom
feat/mcp-server

Conversation

@oekazuma

@oekazuma oekazuma commented Jun 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

Ships @svelte-vitals/mcp, a Model Context Protocol server exposing svelte-vitals' static-mode SEO analysis to AI agents — the final increment of the agent-native epic (#18). Closes #24.

Two tools over stdio:

  • analyze — run static-mode analysis on a project path; returns the structured JSON report (per-route + site-wide scores, findings with fix/recommendation/docsUrl). Inputs mirror the CLI: path?, route?, treatDynamicAs?, rules?, ignore?, failOn?.
  • explain_rule — given a rule id (e.g. SEO001), returns its title, category, severity, rationale, docs URL, and fix template.

The MCP layer is an adapter over the existing pipeline — no rule logic is duplicated.

Changes

  • core: extract buildJsonReport from the json reporter; promote rationale/fix onto the Rule object as the single source of truth; add explainRule, RuleInfo, docsUrlFor; the JSON report's per-finding objects now carry docsUrl.
  • cli: extract analyzeProject() (the analysis pipeline) so both run() and the MCP server reuse it; re-export ProjectError + rules-config helpers. run() keeps its documented 0/1/2 exit-code contract, with one deliberate consistency change: a non-ProjectError failure during project detection now returns exit 2 (the documented "internal error" code) instead of propagating as an uncaught throw — uniform with how pipeline/reporter errors were already handled.
  • mcp (new package): analyze + explain_rule tool handlers, stdio server (svelte-vitals-mcp bin), library entry.
  • docs/release: README roadmap (drop closed --fix, move dev overlay + MCP to Shipped), package README, check:publish extended, changeset (mcp/core/cli minor).

Note on #11

--fix autofix (#11) was closed as agent-delegated during design: the only mechanically-safe fixes (robots.txt/sitemap.xml) are trivial for an agent, while the valuable ones (canonical/description/og) need the real domain & page content an agent already has. MCP is the higher-leverage path — give the agent fixable context, let it apply the fix.

Validation

  • pnpm -r test — 194 passed (core 69, vite 31, cli 88, mcp 6)
  • pnpm -r typecheck, pnpm lint, pnpm check:publish (publint, all 4 packages) — green
  • Manual stdio smoke: initialize + tools/list return both tools; tools/call explain_rule round-trips with structuredContent.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced @svelte-vitals/mcp, an MCP server for integrating Svelte Vitals analysis with AI agents via analyze and explain_rule tools
    • Added explainRule() API for retrieving rule metadata including documentation URLs
    • Enhanced JSON reports with documentation URLs for all findings
  • Documentation

    • Updated roadmap to reflect MCP server and dev overlay as shipped features
    • Added MCP package documentation with tool specifications and usage examples
  • Chores

    • Refactored CLI analysis pipeline to expose reusable analyzeProject() API
    • Extended workspace with new @svelte-vitals/mcp package

oekazuma and others added 8 commits June 22, 2026 13:38
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…24)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@oekazuma, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 48 minutes and 33 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9d6eed5d-c5ff-4792-9225-cc5e0191835c

📥 Commits

Reviewing files that changed from the base of the PR and between 22d9d8b and 0203c40.

📒 Files selected for processing (1)
  • packages/mcp/test/analyze-tool.test.ts
📝 Walkthrough

Walkthrough

Introduces @svelte-vitals/mcp, a new stdio MCP server package exposing analyze and explain_rule tools. Backed by three core refactors: buildJsonReport extraction, Rule interface enrichment with rationale/fix and docsUrlFor/explainRule/RuleInfo, and CLI analyzeProject extraction from run().

Changes

@svelte-vitals/mcp Server and Prerequisites

Layer / File(s) Summary
Core: buildJsonReport extraction and JsonReport type
packages/core/src/reporter/json.ts, packages/core/src/index.ts, packages/core/test/json-report.test.ts
Splits the JSON reporter into a structured buildJsonReport function returning a JsonReport interface and a thin formatJsonReport wrapper that stringifies it; publishes both from the core index; adds a test verifying the split and that stringified output is deterministic.
Core: Rule.rationale/fix, docsUrlFor, explainRule/RuleInfo
packages/core/src/rule.ts, packages/core/src/rules/index.ts, packages/core/src/rules/seo/head-tag-rule.ts, packages/core/src/rules/seo/project-rules.ts, packages/core/src/rules/seo/seo001-title.ts, packages/core/src/rules/seo/seo002-005-008.ts, packages/core/test/explain-rule.test.ts, packages/core/test/config-apply.test.ts
Extends Rule with required rationale and optional fix; adds docsUrlFor helper; implements explainRule/RuleInfo that perform case-insensitive lookups; populates all nine SEO rules with rationale/fix data and derives docs URLs; updates exports and tests.
CLI: analyzeProject extraction and re-exports
packages/cli/src/index.ts, packages/cli/test/analyze-project.test.ts
Extracts the static analysis pipeline from run() into an exported analyzeProject(opts) returning { results, config, version }; refactors run() to delegate to analyzeProject and centralizes error handling; re-exports ProjectError and rule-config helpers; adds tests for success, route filtering, and ProjectError.
MCP package scaffold and workspace wiring
packages/mcp/package.json, packages/mcp/tsconfig.json, packages/mcp/tsup.config.ts, pnpm-workspace.yaml, package.json
Creates the @svelte-vitals/mcp workspace package with package metadata, build/typecheck/test scripts, and ESM-only configuration; adds @modelcontextprotocol/sdk and zod to the pnpm catalog; extends the root check:publish script.
MCP tools, server factory, and stdio bin
packages/mcp/src/tools/analyze.ts, packages/mcp/src/tools/explain-rule.ts, packages/mcp/src/server.ts, packages/mcp/src/bin.ts, packages/mcp/src/index.ts
Implements handleAnalyze with zod validation, unknown-rule-id guard, and integration of analyzeProject + buildJsonReport; implements handleExplainRule with explainRule lookup and formatted text output; wires both into createServer() with tool registration; adds stdio transport bin; exports all public API.
MCP tool and server tests
packages/mcp/test/analyze-tool.test.ts, packages/mcp/test/explain-rule-tool.test.ts, packages/mcp/test/server.test.ts
Adds Vitest suites verifying structured report output and error handling for unknown rules and non-SvelteKit paths, case-insensitive rule id resolution, rule metadata shape, and createServer() smoke instantiation.
Docs, README, changeset, and implementation plan
README.md, packages/mcp/README.md, .changeset/mcp-server.md, docs/superpowers/specs/2026-06-22-mcp-server-design.md, docs/superpowers/plans/2026-06-22-mcp-server.md
Updates root README roadmap and Packages table to mark MCP server as shipped, adds the MCP package README with tool descriptions and stdio configuration example, adds the changeset for minor version bumps, records the design specification and implementation plan.

Sequence Diagram(s)

sequenceDiagram
  participant Agent as MCP Agent
  participant Server as createServer (McpServer)
  participant AnalyzeTool as handleAnalyze
  participant ExplainTool as handleExplainRule
  participant CLI as analyzeProject
  participant Core as buildJsonReport / explainRule

  rect rgba(100, 150, 255, 0.5)
    note over Agent,Core: analyze tool call
    Agent->>Server: tool call: analyze(path, rules, ...)
    Server->>AnalyzeTool: zod-validated AnalyzeArgs
    AnalyzeTool->>CLI: analyzeProject({ cwd, rules, ignore, failOn })
    CLI-->>AnalyzeTool: { results, config, version }
    AnalyzeTool->>Core: buildJsonReport(results, config, { version })
    Core-->>AnalyzeTool: JsonReport
    AnalyzeTool-->>Agent: McpToolResult { content, structuredContent }
  end

  rect rgba(100, 200, 150, 0.5)
    note over Agent,Core: explain_rule tool call
    Agent->>Server: tool call: explain_rule(id)
    Server->>ExplainTool: zod-validated ExplainRuleArgs
    ExplainTool->>Core: explainRule(id)
    Core-->>ExplainTool: RuleInfo | undefined
    ExplainTool-->>Agent: McpToolResult { content, structuredContent }
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 Hippity hop, a new tool is born,
With analyze and explain_rule this morn!
The agent calls in, the MCP replies,
buildJsonReport structured and wise.
No rule left behind with rationale clear —
The rabbit ships MCP, give it a cheer! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title clearly identifies the main change: shipping the MCP server with analyze and explain_rule tools, closing #24. Concise and specific.
Linked Issues check ✅ Passed All core objectives from #24 are met: MCP server shipped with analyze/explain_rule tools, core pipeline reused, structured findings with fix metadata and docsUrl, case-insensitive rule resolution, and comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes align with linked issue #24 scope. No unrelated modifications detected. The PR intentionally excludes suggest_fix (noted as agent-delegated), HTTP/SSE, and build-time analysis per design.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mcp-server

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.

@oekazuma oekazuma self-assigned this Jun 22, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
packages/mcp/test/analyze-tool.test.ts (2)

11-18: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Assert the serialized JSON matches structuredContent.

This tool returns both shapes; sampling only score/routes can miss a drift between content[0].text and structuredContent, or a regression in summary/finding metadata. Parse the text and compare it to the structured payload.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/mcp/test/analyze-tool.test.ts` around lines 11 - 18, The test for
the analyze tool in handleAnalyze only validates individual fields of
structuredContent but does not verify that the serialized JSON text matches the
structured payload. Parse the JSON from res.content[0].text and compare it
against the structuredContent object to ensure they match completely. This will
catch any drift between the text representation and the structured data, and
also validate that all fields including summary are properly serialized in both
formats.

20-30: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Tighten the error-path checks.

These branches only look for the failing rule id / SvelteKit, so they won’t catch regressions in the actual MCP error contract (Unknown rule id(s): … Known rule ids: … and propagated ProjectError text). Assert the full message shape, or at least the known-rule list/prefix.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/mcp/test/analyze-tool.test.ts` around lines 20 - 30, The error
assertions in both test cases are too loose and only check for partial
substrings. In the test for unknown rule ids, tighten the expectation to verify
the full error message shape including "Unknown rule id(s):" prefix and the
known-rule list, not just the presence of 'NOPE999'. Similarly, in the test for
non-SvelteKit path, enhance the assertion to check for the complete error
message format and context beyond just the substring 'SvelteKit'. This ensures
regressions in the actual MCP error contract structure will be caught, not just
that certain keywords appear somewhere in the response.
packages/mcp/test/explain-rule-tool.test.ts (2)

5-12: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Cover the full RuleInfo payload.

explain_rule is supposed to return title, category, rationale, docs URL, and optional fix data, but this test only checks id, severity, and docsUrl. Add assertions for the remaining metadata so regressions in the agent-facing contract are caught.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/mcp/test/explain-rule-tool.test.ts` around lines 5 - 12, The test
case for handleExplainRule in the 'returns rule info for a known id' test is
incomplete and only validates id, severity, and docsUrl. Extend the assertions
to also verify all fields in the full RuleInfo payload including title,
category, rationale, and optional fix data. Update the type cast for the info
variable to include all these expected fields and add corresponding expect
statements to validate that each field contains the expected values.

14-18: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Assert the full unknown-id error text.

Checking only for NOPE999 leaves the Unknown rule id prefix and known-rule list untested. Tightening this to the full message will catch contract regressions in handleExplainRule.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/mcp/test/explain-rule-tool.test.ts` around lines 14 - 18, In the
test "reports an error for an unknown id", the assertion on res.content[0]!.text
is too lenient by only checking that it contains 'NOPE999'. Replace the
.toContain('NOPE999') check with an exact match assertion using .toBe() or
.toEqual() that validates the complete error message including the "Unknown rule
id" prefix and the full list of known rules returned by handleExplainRule. This
will ensure the contract of the error response is fully tested and catch any
regressions in the error message format or content.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/specs/2026-06-22-mcp-server-design.md`:
- Around line 21-25: Remove the reference to `docsUrl` from the `analyze`
function description as the core report shape does not actually include this
field. The `docsUrl` should only be promised in the `explain_rule` function
specification, not in `analyze`. Update the `analyze` bullet point to only
mention the fields that are actually present in the report (per-finding
`fix`/`recommendation`, per-route and site-wide scores, and the summary), while
keeping `docsUrl` listed only in the `explain_rule` function specification where
it belongs.
- Around line 44-58: Add the language identifier `text` to the opening code
fence of the ASCII architecture diagram in the file. The bare code fence
(starting with just triple backticks) is causing markdownlint failures; changing
it to a properly labeled fence with `text` as the language identifier will keep
the ASCII diagram readable while satisfying lint requirements.

In `@packages/mcp/package.json`:
- Around line 1-51: The package.json manifest for the `@svelte-vitals/mcp` package
is missing the `devEngines.runtime.version` field that CI checks expect to read.
Add a `devEngines` object to the root level of the package.json file with a
`runtime` property containing a `version` field. Check other workspace
package.json files in the repository to determine the standard Node runtime
version value to use, then apply that same version value to match the repo's
standard.

In `@packages/mcp/README.md`:
- Around line 7-8: The `analyze` command description claims that findings
include `docs` metadata, but this field is not actually part of the structured
report returned by analyze. Remove the mention of `docs` from the `analyze`
description since that documentation metadata is only available through the
`explain_rule` command. Keep only the fields that are actually present in the
analyze report (such as `fix` and `recommendation`).

---

Nitpick comments:
In `@packages/mcp/test/analyze-tool.test.ts`:
- Around line 11-18: The test for the analyze tool in handleAnalyze only
validates individual fields of structuredContent but does not verify that the
serialized JSON text matches the structured payload. Parse the JSON from
res.content[0].text and compare it against the structuredContent object to
ensure they match completely. This will catch any drift between the text
representation and the structured data, and also validate that all fields
including summary are properly serialized in both formats.
- Around line 20-30: The error assertions in both test cases are too loose and
only check for partial substrings. In the test for unknown rule ids, tighten the
expectation to verify the full error message shape including "Unknown rule
id(s):" prefix and the known-rule list, not just the presence of 'NOPE999'.
Similarly, in the test for non-SvelteKit path, enhance the assertion to check
for the complete error message format and context beyond just the substring
'SvelteKit'. This ensures regressions in the actual MCP error contract structure
will be caught, not just that certain keywords appear somewhere in the response.

In `@packages/mcp/test/explain-rule-tool.test.ts`:
- Around line 5-12: The test case for handleExplainRule in the 'returns rule
info for a known id' test is incomplete and only validates id, severity, and
docsUrl. Extend the assertions to also verify all fields in the full RuleInfo
payload including title, category, rationale, and optional fix data. Update the
type cast for the info variable to include all these expected fields and add
corresponding expect statements to validate that each field contains the
expected values.
- Around line 14-18: In the test "reports an error for an unknown id", the
assertion on res.content[0]!.text is too lenient by only checking that it
contains 'NOPE999'. Replace the .toContain('NOPE999') check with an exact match
assertion using .toBe() or .toEqual() that validates the complete error message
including the "Unknown rule id" prefix and the full list of known rules returned
by handleExplainRule. This will ensure the contract of the error response is
fully tested and catch any regressions in the error message format or content.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d761358a-9acb-4633-93ee-3cfb66a6bf8c

📥 Commits

Reviewing files that changed from the base of the PR and between 6640a14 and 396a783.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (31)
  • .changeset/mcp-server.md
  • README.md
  • docs/superpowers/plans/2026-06-22-mcp-server.md
  • docs/superpowers/specs/2026-06-22-mcp-server-design.md
  • package.json
  • packages/cli/src/index.ts
  • packages/cli/test/analyze-project.test.ts
  • packages/core/src/index.ts
  • packages/core/src/reporter/json.ts
  • packages/core/src/rule.ts
  • packages/core/src/rules/index.ts
  • packages/core/src/rules/seo/head-tag-rule.ts
  • packages/core/src/rules/seo/project-rules.ts
  • packages/core/src/rules/seo/seo001-title.ts
  • packages/core/src/rules/seo/seo002-005-008.ts
  • packages/core/test/config-apply.test.ts
  • packages/core/test/explain-rule.test.ts
  • packages/core/test/json-report.test.ts
  • packages/mcp/README.md
  • packages/mcp/package.json
  • packages/mcp/src/bin.ts
  • packages/mcp/src/index.ts
  • packages/mcp/src/server.ts
  • packages/mcp/src/tools/analyze.ts
  • packages/mcp/src/tools/explain-rule.ts
  • packages/mcp/test/analyze-tool.test.ts
  • packages/mcp/test/explain-rule-tool.test.ts
  • packages/mcp/test/server.test.ts
  • packages/mcp/tsconfig.json
  • packages/mcp/tsup.config.ts
  • pnpm-workspace.yaml

Comment thread docs/superpowers/specs/2026-06-22-mcp-server-design.md
Comment thread docs/superpowers/specs/2026-06-22-mcp-server-design.md Outdated
Comment thread packages/mcp/package.json
Comment thread packages/mcp/README.md Outdated
…tests (#24)

Address CodeRabbit review on #28:
- json report findings now carry docsUrl (matches docs; gives agents the rule docs link)
- analyze/explain_rule tests assert full error contract and text/structured parity
- explain_rule test covers the full RuleInfo payload
- add handler docstrings; label the spec architecture fence as text

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new @svelte-vitals/mcp package that exposes svelte-vitals’ static-mode SEO analysis via an MCP stdio server, reusing the existing CLI/core pipelines (no duplicated rule logic). It also refactors core/CLI to expose structured report building and rule metadata lookup needed by MCP tool handlers.

Changes:

  • Add @svelte-vitals/mcp with analyze and explain_rule tools over stdio, plus tests and docs.
  • Refactor @svelte-vitals/core to expose buildJsonReport, docsUrlFor, and explainRule/RuleInfo, and promote rationale/fix onto Rule.
  • Refactor svelte-vitals (CLI) to extract analyzeProject() for reuse, and re-export rules-config helpers / ProjectError.

Reviewed changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Moves MCP/dev overlay into “Shipped” and adds the new package to the workspace table.
pnpm-workspace.yaml Adds catalog entries for @modelcontextprotocol/sdk and zod.
pnpm-lock.yaml Locks new MCP + zod dependencies and transitive graph.
package.json Extends check:publish to include @svelte-vitals/mcp.
.changeset/mcp-server.md Changeset for new MCP package + core/cli minor bumps.
docs/superpowers/specs/2026-06-22-mcp-server-design.md Design spec documenting MCP server goals, contracts, and architecture.
docs/superpowers/plans/2026-06-22-mcp-server.md Detailed implementation plan for the MCP server and supporting refactors.
packages/mcp/package.json New MCP package manifest with stdio bin and dependencies.
packages/mcp/README.md Usage docs for configuring the MCP server via npx.
packages/mcp/tsconfig.json TypeScript config for the MCP package.
packages/mcp/tsup.config.ts MCP build config (ESM-only) producing library + bin outputs.
packages/mcp/src/index.ts Public MCP package entrypoint exports.
packages/mcp/src/bin.ts svelte-vitals-mcp stdio binary that starts the MCP server.
packages/mcp/src/server.ts MCP server wiring that registers analyze and explain_rule tools.
packages/mcp/src/tools/analyze.ts Implements analyze tool handler that runs CLI pipeline + returns buildJsonReport.
packages/mcp/src/tools/explain-rule.ts Implements explain_rule tool handler backed by core explainRule().
packages/mcp/test/analyze-tool.test.ts Tests analyze tool handler (happy path + error cases).
packages/mcp/test/explain-rule-tool.test.ts Tests explain_rule tool handler (known/unknown ids).
packages/mcp/test/server.test.ts Smoke test that the MCP server can be constructed.
packages/core/src/rule.ts Adds rationale/fix to Rule and introduces docsUrlFor().
packages/core/src/rules/index.ts Adds RuleInfo and explainRule() helper for MCP/tooling use.
packages/core/src/rules/seo/head-tag-rule.ts Extends headTagRule to accept/store rationale and derives docs URL via docsUrlFor.
packages/core/src/rules/seo/seo001-title.ts Moves SEO001 rationale/fix into the rule and derives docs URL via docsUrlFor.
packages/core/src/rules/seo/seo002-005-008.ts Adds rationale to the head-tag rules (SEO002/003/004/005/008).
packages/core/src/rules/seo/project-rules.ts Adds rationale/canonical Fix constants for project rules (SEO006/007/009) + uses docsUrlFor.
packages/core/src/reporter/json.ts Extracts buildJsonReport() and includes docsUrl in per-finding objects when present.
packages/core/src/index.ts Re-exports buildJsonReport, JsonReport, docsUrlFor, explainRule, and RuleInfo.
packages/core/test/json-report.test.ts Updates JSON report tests and adds coverage for buildJsonReport parity with formatJsonReport.
packages/core/test/explain-rule.test.ts Adds tests for explainRule() and rationale/docs URL invariants.
packages/core/test/config-apply.test.ts Updates test fixtures to satisfy new required Rule.rationale.
packages/cli/src/index.ts Extracts analyzeProject() and refactors run() to consume it; re-exports helpers for MCP.
packages/cli/test/analyze-project.test.ts Adds tests for analyzeProject() behavior and error cases.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

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

Comment thread packages/cli/src/index.ts
oekazuma and others added 2 commits June 22, 2026 14:43
…ontract)

Address Copilot review on #28: a non-ProjectError during analysis now returns
exit 2 (documented 'internal error') instead of propagating as an uncaught
throw — uniform with how pipeline/reporter errors were already handled. Add an
intent comment and correct the 'behaviour unchanged' wording in the spec.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The analyze tool now accepts a metaComponents array, mirroring the CLI's
--meta-components flag, so projects using a meta-wrapper component (e.g.
<Seo />) are not falsely flagged for missing head tags via MCP.

Both tools now resolve rule ids case-insensitively: explainRule (core)
normalizes to the canonical uppercase id, and the analyze tool uppercases
rules/ignore before validation and config building. CLI behaviour is
unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/mcp/test/analyze-tool.test.ts`:
- Around line 41-43: The test assertion that iterates over the ids Set can
vacuously pass when no issues are returned, since an empty Set means the for
loop never executes and no assertions are checked. Add a guard assertion before
the for loop that iterates over ids to ensure the Set is not empty, verifying
that at least one issue exists so the case-insensitive allow-list behavior is
actually being tested.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 204d4fa8-f40f-4fe5-804d-1c5c82a492b2

📥 Commits

Reviewing files that changed from the base of the PR and between 396a783 and 22d9d8b.

📒 Files selected for processing (12)
  • .changeset/mcp-server.md
  • docs/superpowers/specs/2026-06-22-mcp-server-design.md
  • packages/cli/src/index.ts
  • packages/core/src/reporter/json.ts
  • packages/core/src/rules/index.ts
  • packages/core/test/explain-rule.test.ts
  • packages/core/test/json-report.test.ts
  • packages/mcp/README.md
  • packages/mcp/src/tools/analyze.ts
  • packages/mcp/src/tools/explain-rule.ts
  • packages/mcp/test/analyze-tool.test.ts
  • packages/mcp/test/explain-rule-tool.test.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/mcp/README.md
  • .changeset/mcp-server.md
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/core/test/explain-rule.test.ts
  • packages/core/test/json-report.test.ts
  • packages/core/src/rules/index.ts
  • packages/mcp/src/tools/explain-rule.ts
  • packages/mcp/src/tools/analyze.ts
  • docs/superpowers/specs/2026-06-22-mcp-server-design.md
  • packages/cli/src/index.ts
  • packages/core/src/reporter/json.ts

Comment thread packages/mcp/test/analyze-tool.test.ts
…pass (#24)

The for-of over the rule-id set would pass even with zero issues. Assert
the set is non-empty so the single-rule allow-list is actually exercised.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

feat: MCP server (analyze / explain_rule / suggest_fix)

2 participants