Skip to content

feat(mcp): query Google Cloud metrics live with PromQL - #1478

Closed
JeremyFunk wants to merge 34 commits into
feat/gcp-promql-widgetfrom
feat/gcp-promql-mcp
Closed

JeremyFunk wants to merge 34 commits into
feat/gcp-promql-widgetfrom
feat/gcp-promql-mcp

Conversation

@JeremyFunk

@JeremyFunk JeremyFunk commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

The agent can now read a customer's Google Cloud Monitoring metrics live, through Google's PromQL API, with two MCP tools. Nothing is ingested; the 5-minute poller and its gcp.* warehouse metrics stay as they are.

Stacked on #1475 (backend, GcpPromQlService) → #1477 (live-query access) → feat/gcp-promql-widget (dashboard widget). Merge after those, by merge commit.

Tools

  • find_gcp_metrics: search (substring of the metric type) and/or metric (one type to describe), project, limit. Search reads one project's metric list; describe returns kind, value type, unit, monitored resource types, labels and a starter query: sum(rate(…[5m])) for DELTA/CUMULATIVE, avg(…) for GAUGE, histogram_quantile(0.95, sum by (le) (rate(…_bucket[5m]))) for DISTRIBUTION, none for STRING. It adds a monitored_resource matcher when the metric has more than one resource type, because Google refuses the selector otherwise. Output FindGcpMetricsOutput.
  • query_gcp_promql: query, kind (timeseries default or instant at end_time), start_time/end_time (default 1 h, at most 6 weeks, Google's usual retention), bucket_seconds (60–86400, default from the window like the other tools, about 100 points; a finer one is widened to at most 500 points per series, which also bounds the chat payload), projects. Output QueryGcpPromQlOutput: the series sorted by last value, capped at 100 for the chat payload, plus totalSeries, projects and failures.
  • The model reads the top 20 series with last/min/avg/max, the projects that could not be read, and a note that each project is queried on its own (aggregation stays within a project, every series carries project_id). Both descriptions say to aggregate with sum by/avg by because Google bills per series returned, and that these are live reads, separate from list_metrics/query_data.
  • Both tools are public (MCP transport included), read-only, openWorld. The org always comes from the request's tenant.

Errors

Service error MCP error
invalid query (Google's message), too many series, too many projects, project not connected, unknown metric type McpInvalidInputError with the message
no Google service account key on the deployment McpUnavailableError (gcp_live_query)
no Google Cloud connection McpUnavailableError (gcp_connection)
every project failed (reader account missing, API off, denied…) McpNotReadyError, retry in 300 s, with the per-project cause and fix
the connections hold no project McpUnavailableError (gcp_connection)
upstream / persistence McpQueryError

Other changes

  • The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY the same way api does (optionalSecret); GcpPromQlService joins the MCP runtime services.
  • Chat: query_gcp_promql range results draw as the query chart (points merged into buckets by time); instant results as a table. find_gcp_metrics uses the generic renderer.
  • maple://instructions gains one tool-selection line; the MCP reference page lists both tools.

Decisions

  • One discovery tool with two modes instead of separate search and describe tools, to keep the catalog small.
  • "No connection" is McpUnavailableError, not McpNotReadyError: retrying cannot help until someone connects a project, which is what that error kind says.
  • Both tools are public: an MCP client with an org credential can trigger live Google reads billed to that org's own host project, like other public read tools; the 500-series cap and the edge cache bound it.
  • "Every project failed" is McpNotReadyError: most causes are fixed by a setup-script run whose grant takes minutes to apply, and the message names the fix.

Not verified without a live system

  • Chat: "Which Cloud Run services had the most requests in the last hour?" → find_gcp_metrics search=run.googleapis.com/request → describe → query_gcp_promql with a sum by (service_name) query; the chart renders.
  • A metric with several resource types (serviceruntime.googleapis.com/api/request_count) gets a working starter query.
  • An org without a Google Cloud connection gets the unavailable answer; a connection whose reader account is missing gets the setup-script message.
  • Over MCP with an API key, the tools list and answer for that key's org only.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

find_gcp_metrics searches a project's Cloud Monitoring metric types or
describes one with a starter query; query_gcp_promql runs PromQL over a
window or at an instant through GcpPromQlService. The chat renders range
results as a chart. The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY.
Explicit bucket_seconds is validated, not clamped; one error tail for both
query kinds; the describe output reuses the descriptor's fields; label
values are quoted and descriptions capped; gauge distributions skip rate;
chart series keep __name__ so none collide.
A bucket_seconds too fine for the window widens to 500 points instead of
a 400, which also bounds the chat payload. No project to read is
unavailable, not a retry. Describe suggestions skip names Google would
refuse; the instant lookback hint shows only on instant queries.
@maple-review-bot

maple-review-bot Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 8/10 · likely safe to merge
Every hunk read; the step widening, window bounds and error mapping are pinned by tests, but the chat render branch is untested and the live Google path cannot run here.
quality 100/100 · no findings · tests partial · risk medium · 3/3 new units observable

Two public MCP tools that run PromQL live against the org's own Google Cloud Monitoring projects, with a chart for range results and a table for instant ones. Wiring, error mapping and the chart rows are consistent with the existing api path; none of the open McpQueryError, SandboxSpawnError, IntegrationsUpstreamError or GithubAppError issues is addressed, and the new mapper adds one more source of McpQueryError on Google upstream failures.

  • query_gcp_promql runs PromQL live per connected project, capped at 100 series
  • find_gcp_metrics searches one project's metric types or describes one
  • Google failures map to typed MCP errors; all-projects-failed is McpNotReadyError
  • Chat draws range results as the query chart, instant results as a table

Before merge

  • Secret · Set MAPLE_GCP_SERVICE_ACCOUNT_KEY in the ai Worker's prd and dev secret stores (unset answers gcp_live_query unavailable) · apps/ai/src/worker.ts:65

Production impact

Open errors in the changed files
Issue Service Occurrences File
SandboxSpawnError maple-chat 52 apps/ai/src/mcp/dispatcher.ts
@maple/mcp/errors/McpQueryError maple-chat 45 apps/ai/src/mcp/tools/registry.ts
@maple/mcp/errors/McpQueryError maple-chat 36 apps/ai/src/mcp/tools/registry.ts
SandboxSpawnError maple-chat 29 apps/ai/src/mcp/dispatcher.ts
SandboxSpawnError maple-chat 23 apps/ai/src/mcp/dispatcher.ts
@maple/mcp/errors/McpQueryError maple-ai 18 apps/ai/src/mcp/tools/registry.ts
SandboxSpawnError maple-chat 17 apps/ai/src/mcp/dispatcher.ts
SandboxSpawnError maple-chat 15 apps/ai/src/mcp/dispatcher.ts
@maple/http/errors/IntegrationsUpstreamError maple-chat 15 apps/ai/src/mcp/tools/registry.ts
@maple/api/vcs/GithubAppError maple-chat 14 apps/ai/src/mcp/tools/registry.ts

After this merges, Maple checks whether they stop.

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Every read passes the request's orgId (gcp-promql.ts:154, :329); tenant scoping is the service's
  • Step is held >= 60 s and widened to 500 points; a 42-day window still fits the request schema
  • tool-renderer.tsx:173 handles both kinds and falls through to the generic renderer otherwise
Observability coverage: 3 of 3 changes observable
Change Kind Observable Evidence
query_gcp_promql (MCP tool handler) Server yes Effect.fn("McpTool.queryGcpPromQl") with Effect.annotateCurrentSpan orgId/kind/seriesCount (gcp-promql.ts:338, :365)
find_gcp_metrics (MCP tool handler) Server yes Effect.fn("McpTool.findGcpMetrics") with an orgId annotation (gcp-promql.ts:130, :156)
Google Monitoring PromQL reads, one per project Client yes spans and edge caching live in GcpPromQlService (base branch); this diff only puts it on the MCP runtime (dispatcher.ts:299)

72448fa · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e056140b-1f79-459e-a0f1-8bb34d36d417

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@maple-review-bot

maple-review-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 7/10 · likely safe to merge
The tool handler, error mapping and step widening are pinned by tests; only the chat renderer's instant branch is untested and shows the wrong point.
quality 90/100 · 1 warning · tests partial · risk medium · 3/3 new units observable

Adds two public MCP tools that read Google Cloud Monitoring metrics live through Google's PromQL API (find_gcp_metrics, query_gcp_promql), wires GcpPromQlService and its service-account key into the ai Worker, and renders range results as a chart in chat. Safe to merge once the instant table reads the value at end_time rather than the oldest point.

  • Registers find_gcp_metrics and query_gcp_promql as public MCP tools
  • query_gcp_promql widens a too-fine bucket_seconds to at most 500 points per series
  • Google's errors map onto McpInvalidInputError, McpUnavailableError, McpNotReadyError
  • Chat draws range results with QueryChart, instant results as a table

Before merge

  • Secret · Set MAPLE_GCP_SERVICE_ACCOUNT_KEY in the ai Worker's prd and dev secret stores; unset answers both tools as unavailable · apps/ai/src/worker.ts:65

Findings

🟠 Warning · F1 · Chat instant table shows the oldest point, not the value at end_time

correctness · apps/web/src/components/ai-elements/renderers/tool-renderer.tsx:192

An instant query whose selector is a range vector (sum(rate({"..."}[5m]))) comes back as a matrix with several points per series, and points[0] is the earliest, so the chat table prints a value from as far back as the selector's range while the tool's own table (apps/ai/src/mcp/tools/gcp-promql.ts:388, last point) and the "instant: one value per series at end_time" contract report the latest. Read the last point, as the tool does.

							String(series.points.at(-1)?.[1] ?? "-"),
🤖 Prompt to fix this finding with an AI agent
Findings from an automated review of commit 890f83efe07072ccabb19ffef4e035478db3cb7c. Verify each one against the current code before changing anything, fix only those that still apply, and keep each fix to the lines it names.

---

F1 · Warning · correctness · apps/web/src/components/ai-elements/renderers/tool-renderer.tsx:192
Chat instant table shows the oldest point, not the value at `end_time`
An `instant` query whose selector is a range vector (`sum(rate({"..."}[5m]))`) comes back as a matrix with several points per series, and `points[0]` is the earliest, so the chat table prints a value from as far back as the selector's range while the tool's own table (`apps/ai/src/mcp/tools/gcp-promql.ts:388`, last point) and the "instant: one value per series at end_time" contract report the latest. Read the last point, as the tool does.
Replace those lines with:
							String(series.points.at(-1)?.[1] ?? "-"),

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Both tools read the org from CurrentMcpTenant, never a parameter (gcp-promql.ts:154, 329)
  • Widened step stays far under the schema's 11,000-point cap (GCP_PROMQL_MAX_POINTS, gcp-promql.ts:336)
  • Search asks for limit + 1 and truncates on the extra row (gcp-promql.ts:164-171)
Observability coverage: 3 of 3 changes observable
Change Kind Observable Evidence
MCP tool call find_gcp_metrics Server yes Handler span Effect.fn("McpTool.findGcpMetrics") plus the dispatcher's maple.mcp.tool attribution (dispatcher.ts:122)
MCP tool call query_gcp_promql Server yes Handler span Effect.fn("McpTool.queryGcpPromql"), maple.ai.kind and result.seriesCount attributes
Google Cloud Monitoring PromQL read per project Client yes GcpPromQlService.queryRange/queryInstant Effect.fn spans via the Google client in packages/backend

890f83e · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot maple-review-bot 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.

1 inline note from Maple's review. The score and summary are in the review comment above.

headers: ["Series", "Value"],
rows: output.data.series.map((series) => [
seriesKey(series.labels),
String(series.points[0]?.[1] ?? "-"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

Chat instant table shows the oldest point, not the value at end_time

F1 · Warning · correctness

An instant query whose selector is a range vector (sum(rate({"..."}[5m]))) comes back as a matrix with several points per series, and points[0] is the earliest, so the chat table prints a value from as far back as the selector's range while the tool's own table (apps/ai/src/mcp/tools/gcp-promql.ts:388, last point) and the "instant: one value per series at end_time" contract report the latest. Read the last point, as the tool does.

Suggested change
String(series.points[0]?.[1] ?? "-"),
String(series.points.at(-1)?.[1] ?? "-"),
🤖 Prompt to fix with an AI agent
In `apps/web/src/components/ai-elements/renderers/tool-renderer.tsx:192`: Chat instant table shows the oldest point, not the value at `end_time`.

An `instant` query whose selector is a range vector (`sum(rate({"..."}[5m]))`) comes back as a matrix with several points per series, and `points[0]` is the earliest, so the chat table prints a value from as far back as the selector's range while the tool's own table (`apps/ai/src/mcp/tools/gcp-promql.ts:388`, last point) and the "instant: one value per series at end_time" contract report the latest. Read the last point, as the tool does.

Replace those lines with:

							String(series.points.at(-1)?.[1] ?? "-"),

Verify the problem exists at that location before changing it, and keep the fix to those lines.

@maple-review-bot

maple-review-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 7/10 · likely safe to merge
Open F1 survives at head (tool-renderer.tsx:192 still reads points[0]); the new tool logic, schemas and tests check out.
quality 90/100 · 1 warning · tests partial · risk medium · 2/2 new units observable

Adds two public MCP tools that read Google Cloud Monitoring live over Google's PromQL API, with their output schemas, chat rendering and tests. Contained and safe to merge once the open instant-table finding is fixed.

  • find_gcp_metrics and query_gcp_promql read Google Cloud Monitoring live, behind the org's tenant
  • GcpPromQlService joins the ai Worker's MCP runtime, with MAPLE_GCP_SERVICE_ACCOUNT_KEY bound
  • Chat draws PromQL range results as a chart and instant results as a table
  • FindGcpMetricsOutput / QueryGcpPromQlOutput added to the MCP output catalog

Before merge

  • Secret · Set MAPLE_GCP_SERVICE_ACCOUNT_KEY on the prd ai Worker secret store (bound at apps/ai/src/worker.ts:65) · apps/ai/src/worker.ts:65

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Step floor is safe: AUTO_BUCKET_LADDER starts at 60s and the 500-point widening never drops below it (gcp-promql.ts:334)
  • Tenant still comes from the request: CurrentMcpTenant feeds orgId into every GcpPromQlService call (gcp-promql.ts:154, 329)
  • The service's extra deps are provided: Env and EdgeCacheService in mcp-service-graph.ts:13
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
find_gcp_metrics tool call consumer yes dispatcher.ts:331 annotates maple.mcp.tool; handler span McpTool.findGcpMetrics (gcp-promql.ts:130)
query_gcp_promql tool call consumer yes handler span McpTool.queryGcpPromQl with orgId, maple.ai.kind and result.seriesCount (gcp-promql.ts:327, 338, 365)

b619108 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 7/10 · likely safe to merge
Tenant scoping, the series/point caps and the error mapping are verified in the tool and service; the one defect is the chart adapter's colliding series keys.
quality 88/100 · 1 warning · 1 note · tests covered · risk medium · 2/2 new units observable

Adds two read-only MCP tools that read Google Cloud Monitoring live over PromQL, registers them in the ai worker and draws range results as a chart. The tenant scoping, caps and error mapping look right; the new chart adapter has one label-collision bug.

  • find_gcp_metrics and query_gcp_promql read Google Cloud Monitoring live
  • promQlChartRows merges PromQL series into QueryChart rows for the chat
  • The ai worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY and provides GcpPromQlService

Before merge

Findings

🔵 Note · F2 · seriesKey collides two series whose label values contain , or =

correctness · apps/web/src/components/ai-elements/renderers/components/promql-chart-rows.ts:8

The key joins labels with a bare = and , , so { a: "b, c=d" } and { a: "b", c: "d" } produce the same string, and promQlChartRows then writes both series into one series map: the chart draws a single line and one series' points overwrite the other's. The comment's "so no two collide" does not hold; the tool's own seriesName (apps/ai/src/mcp/tools/gcp-promql.ts:103) JSON-quotes each value to avoid exactly this.

	return entries.length === 0 ? "value" : entries.map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(", ")
🤖 Prompt to fix this finding with an AI agent
Findings from an automated review of commit 29926291e32d8f067a97f70617f78c5e798b6348. Verify each one against the current code before changing anything, fix only those that still apply, and keep each fix to the lines it names.

---

F2 · Note · correctness · apps/web/src/components/ai-elements/renderers/components/promql-chart-rows.ts:8
`seriesKey` collides two series whose label values contain `, ` or `=`
The key joins labels with a bare `=` and `, `, so `{ a: "b, c=d" }` and `{ a: "b", c: "d" }` produce the same string, and `promQlChartRows` then writes both series into one `series` map: the chart draws a single line and one series' points overwrite the other's. The comment's "so no two collide" does not hold; the tool's own `seriesName` (`apps/ai/src/mcp/tools/gcp-promql.ts:103`) JSON-quotes each value to avoid exactly this.
Replace those lines with:
	return entries.length === 0 ? "value" : entries.map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(", ")

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Org and projects come from CurrentMcpTenant, never the model (gcp-promql.ts:154, 329)
  • MAX_POINTS widening and MAX_SERIES cap bound points and series (gcp-promql.ts:334-337, 371-373)
  • Google and schema failures map to McpInvalidInputError/McpUnavailableError/McpNotReadyError (gcp-promql.ts:355-364)
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
MCP tool entrypoints find_gcp_metrics / query_gcp_promql Server yes Handlers are Effect.fn("McpTool.findGcpMetrics") / ("McpTool.queryGcpPromql") annotating orgId (gcp-promql.ts:130,156,327,338), registered through the MCP registrar that spans tool calls (registry.ts:384)
Google Cloud Monitoring PromQL read Client yes GcpPromQlService.queryRange/queryInstant are Effect.fn spans annotating orgId (GcpPromQlService.ts:510-517), reached from the tool handlers

2992629 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Both earlier findings still reproduce at this head: the chat instant table reads points[0], and seriesKey still joins unescaped label text.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 3/3 new units observable

Adds two live-Google PromQL MCP tools with their output schemas, chat rendering and runtime wiring. The tool side is well tested, but the two earlier findings are both still live at this head, so it is not ready to merge as is.

  • find_gcp_metrics and query_gcp_promql registered, with starterQuery for each kind
  • QueryGcpPromQlOutput / FindGcpMetricsOutput added to the catalog
  • Chat draws range results through QueryChart, instant results as a table
  • ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY; GcpPromQlService joins the MCP runtime

Before merge

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • describeMetric returns the base type, so starterQuery appending _bucket does not double the suffix (GcpPromQlService.ts:587)
  • limit + 1 for truncation survives searchMetrics, whose request type is unvalidated and slices to the limit (GcpPromQlService.ts:570)
  • Step widening stays inside the 60–86400 schema range for the 42-day max window (gcp-promql.ts:334)
Observability coverage: 3 of 3 changes observable
Change Kind Observable Evidence
find_gcp_metrics MCP tool handler consumer yes Effect.fn("McpTool.findGcpMetrics") span plus Effect.annotateCurrentSpan orgId (gcp-promql.ts:130,156)
query_gcp_promql MCP tool handler consumer yes Effect.fn("McpTool.queryGcpPromQl") span, annotates orgId, kind and result.seriesCount (gcp-promql.ts:327,338,365)
live Google PromQL read (queryRange/queryInstant/searchMetrics/describeMetric) client yes GcpPromQlService Effect.fn spans, called from the new handlers (gcp-promql.ts:347,354)

78f405c · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Two earlier chat-rendering defects are untouched at this head: the instant table still reads points[0], and seriesKey still merges label sets whose values contain , .
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 2/2 new units observable

Adds two public MCP tools that read a customer's Google Cloud Monitoring metrics live through Google's PromQL API, plus their output schemas, chat rendering and ai-Worker key binding. Sound apart from two chat-rendering defects left unfixed at this head.

  • Adds public MCP tools find_gcp_metrics (search/describe) and query_gcp_promql (live Google reads)
  • query_gcp_promql widens bucket_seconds so a series keeps at most 500 points
  • GcpPromQlService joins the MCP runtime services; the ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY
  • Chat draws range results through promQlChartRows into QueryChart, instant results as a table

Before merge

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Step widening floors at the width the cap needs: Math.max of the request and the window/500 (gcp-promql.ts:334)
  • Search truncation works at the limit cap: the tool sends limit + 1 and searchMetrics slices to the request limit (GcpPromQlService.ts:581)
  • Both handlers carry an Effect.fn("McpTool.…") span and annotate orgId, matching every other MCP tool
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
MCP tool find_gcp_metrics Server yes Effect.fn("McpTool.findGcpMetrics") span + annotateCurrentSpan orgId (gcp-promql.ts:130,156)
MCP tool query_gcp_promql Server yes Effect.fn("McpTool.queryGcpPromql") span + orgId/kind/seriesCount annotations (gcp-promql.ts:327,338,365)

a2c20fb · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Both tools are well covered by new tests; the remaining risk is the chat instant table, which still prints the oldest point and has no test.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 3/3 new units observable

Adds two public MCP tools that read Google Cloud Monitoring live through Google's PromQL API, with output schemas, chat rendering and tests; nothing is ingested. The tool layer is sound, but the chat's instant table still shows the wrong point, so it should not merge as is.

  • find_gcp_metrics searches or describes a metric and returns a starter PromQL query
  • query_gcp_promql runs timeseries/instant PromQL per connected project, capped at 100 series
  • Chat draws timeseries through QueryChart, instant as a table
  • The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY; GcpPromQlService joins the MCP runtime

Before merge

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • stepSeconds is widened so the range request's 11,000-point check can never trip (gcp-promql.ts:334)
  • Org scoping comes from CurrentMcpTenant, so both tools read only the request's org
  • The new secret name matches Env.MAPLE_GCP_SERVICE_ACCOUNT_KEY (Env.ts:265) read by the service
Observability coverage: 3 of 3 changes observable
Change Kind Observable Evidence
find_gcp_metrics (MCP tool) inbound yes Dispatcher span with maple.mcp.tool (dispatcher.ts:114-122) plus the handler's own Effect.fn("McpTool.findGcpMetrics") span (gcp-promql.ts:130)
query_gcp_promql (MCP tool) inbound yes Same dispatcher span; handler span at gcp-promql.ts:327, with orgId and maple.ai.kind annotated (gcp-promql.ts:338)
Google Cloud PromQL reads (search, describe, range, instant) outbound yes GcpPromQlService wraps each in an Effect.fn span (GcpPromQlService.ts:506, 521, 553, 585), added on the stacked backend branch #1475

71cf272 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
The only file new since the last review, check-bundle-budget.ts, is a clean conflict resolution; the open chat instant-table bug is untouched.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 2/2 new units observable

Two public MCP tools now read Google Cloud metrics live over PromQL, with a chat renderer for the results. The merge resolution in the bundle budget is clean, but the instant-query table in the chat renderer still prints a stale value.

  • query_gcp_promql renders timeseries as QueryChart, instant as a table
  • promQlChartRows merges series into time-bucketed rows keyed by labels
  • Bundle budget raised to 706 KB with conflict markers removed

Before merge

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • check-bundle-budget.ts at the head has no conflict markers left (sandbox_grep for <<<<<<</=======)
  • Budget chain in the comment (702.5 → 703.5 → 706) matches the merged value at line 114
  • Tool spans come from the MCP dispatcher/registry (dispatcher.ts:122), so the new tools are traced
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
find_gcp_metrics MCP tool inbound yes dispatcher assigns maple.mcp.tool on McpToolDispatcher.call / McpToolExecutor.execute spans (apps/ai/src/mcp/dispatcher.ts:122)
query_gcp_promql MCP tool inbound yes same registry path; handler errors leave the dispatcher span as Error (dispatcher.ts:104-110)

0f86f4e · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
The changed-since file was not in this diff, so I re-read the whole head; the two open findings both still stand and the web instant table path has no test.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 3/3 new units observable

Adds two read-only MCP tools (find_gcp_metrics, query_gcp_promql) that read Google Cloud Monitoring live over PromQL, with tenant-scoped calls and typed error mapping, plus chat renderers for the range and instant result shapes. Safe to merge after the two open renderer findings from the earlier review are addressed.

  • registerGcpPromQlTools adds find_gcp_metrics (search/describe) and query_gcp_promql (timeseries/instant)
  • query_gcp_promql widens bucket_seconds so a series keeps at most 500 points
  • Chat draws query_gcp_promql range results as QueryChart, instant ones as a table
  • ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY and GcpPromQlService joins the MCP runtime

Before merge

  • Secret · Set MAPLE_GCP_SERVICE_ACCOUNT_KEY in the ai Worker's prd and dev secret stores, as apps/api already has it · apps/ai/src/worker.ts:65

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Step sizing: AUTO_BUCKET_LADDER floors computeBucketSecondsForRange at 60s and the widening Math.max keeps stepSeconds inside the request schema's 60–86400 (datetime.ts:750)
  • searchMetrics is passed limit + 1 (201 at the tool's max of 200) and the service only slices the cached name list, with no 200 cap to reject it (GcpPromQlService.ts:581)
  • Both tools run under the registry's existing McpToolExecutor.execute span and annotate it with orgId and result.seriesCount, so no new inbound entrypoint is unspanned
Observability coverage: 3 of 3 changes observable
Change Kind Observable Evidence
find_gcp_metrics MCP tool call MCP tool handler (inbound entrypoint) yes registry owns the call span (McpToolExecutor.execute, dispatcher.test.ts:233); handler annotates orgId (apps/ai/src/mcp/tools/gcp-promql.ts:156)
query_gcp_promql MCP tool call MCP tool handler (inbound entrypoint) yes same registry span plus maple.ai.kind / result.seriesCount annotations (gcp-promql.ts:338,365)
live Google Cloud Monitoring reads outbound HTTP (GcpPromQlService) yes service lives in the base branch and spans itself (Effect.fn("GcpPromQlService.queryRange"), GcpPromQlService.ts:506); not added by this diff

fc84879 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 7/10 · likely safe to merge
The tool path is pinned by 405 lines of tests, but the open warn on the chat instant table is unchanged at this head and its lines were only merged over.
quality 88/100 · 1 warning · 1 note · tests covered · risk medium · 2/2 new units observable

Adds two live Google Cloud PromQL MCP tools (find_gcp_metrics, query_gcp_promql), their output schemas, the ai Worker's service-account-key binding and their chat renderers. The tool logic is well tested; the instant chat table still reads the wrong point (F1 open) and seriesKey can still merge two series (F2 open), so it needs those two before merge.

  • query_gcp_promql widens bucket_seconds to keep at most 500 points per series
  • find_gcp_metrics searches or describes a metric type and returns a starter query
  • Chat draws PromQL range results as a chart, instant results as a table
  • The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY and the MCP runtime joins GcpPromQlService

Before merge

  • Secret · Set MAPLE_GCP_SERVICE_ACCOUNT_KEY in the ai Worker's prd (and dev) secret store: it is optional and unset answers both tools as unavailable · apps/ai/src/worker.ts:65

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Default step stays legal: the bucket ladder's smallest rung is 60 s (packages/query-engine/src/datetime.ts:750), so GCP_PROMQL_MIN_STEP_SECONDS is never undercut
  • Both tools scope every read to the request's org via CurrentMcpTenant, passed as tenant.orgId to GcpPromQlService (gcp-promql.ts:154,329)
  • The six apps/web/src/components/infra/gcp files the merges brought in only build console URLs, encoded with encodeURIComponent (inventory.ts:125), and add no data path
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
MCP tool find_gcp_metrics inbound entrypoint yes Effect.fn("McpTool.findGcpMetrics") span and Effect.annotateCurrentSpan({ orgId }) (gcp-promql.ts:130,156)
MCP tool query_gcp_promql inbound entrypoint yes Effect.fn("McpTool.queryGcpPromQl") span with orgId, maple.ai.kind and result.seriesCount (gcp-promql.ts:327,338,365)

ed85b69 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

# Conflicts:
#	apps/ai/src/mcp/dispatcher.ts
#	apps/ai/src/mcp/resources/instructions.ts
#	apps/ai/src/mcp/tools/runtime-requirements.ts
#	packages/domain/src/mcp-outputs/index.ts
@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Both earlier findings still stand at this head: the chat instant table reads the oldest point, and label-derived keys can merge two series.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 2/2 new units observable

Adds two public MCP tools that read Google Cloud Monitoring live through Google's PromQL API, plus their chat renderers. Contained and well covered on the tool side; the two defects raised in the earlier review are unchanged at this head, and the chat rendering of them has no test.

  • find_gcp_metrics searches or describes a metric type and returns a starter PromQL query
  • query_gcp_promql reads the window (or one instant) per connected project, at most 100 series
  • Chat draws query_gcp_promql ranges as the query chart, instants as a table
  • The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY and joins GcpPromQlService to the MCP runtime

Before merge

  • Secret · Add MAPLE_GCP_SERVICE_ACCOUNT_KEY to the ai Worker's prd and dev secret stores (Infisical), as api and alerting already have it · apps/ai/src/worker.ts:68

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Chat buckets are ISO strings that warehouseDateTimeToIso passes through and parseBucketMs parses (query-engine/src/datetime.ts:22)
  • stepSeconds is widened to about 500 points, so the 60s floor and 11,000-point ceiling in GcpPromQlRangeRequest always hold (gcp-promql.ts:334)
  • The new search limit is bounded: searchMetrics slices to the requested limit and the tool asks for limit + 1 (GcpPromQlService.ts:581)
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
find_gcp_metrics MCP tool inbound entrypoint yes Effect.fn("McpTool.findGcpMetrics") span and Effect.annotateCurrentSpan({ orgId }) at apps/ai/src/mcp/tools/gcp-promql.ts:130; the dispatcher annotates maple.mcp.tool (dispatcher.ts:126)
query_gcp_promql MCP tool inbound entrypoint yes Effect.fn("McpTool.queryGcpPromql") span with orgId, maple.ai.kind and result.seriesCount at apps/ai/src/mcp/tools/gcp-promql.ts:327-365

97445ed · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 7/10 · likely safe to merge
Nothing changed in the reviewed files since 97445ed, so the two open chat-renderer findings stand; the only new commits restore the widget branch's rails.
quality 88/100 · 1 warning · 1 note · tests covered · risk medium · 2/2 new units observable

Two public MCP tools read Google Cloud Monitoring live through Google's PromQL API, with output schemas, chat rendering, service wiring and tests. Reviewable code is identical to the last pass; the two open chat-renderer findings are untouched.

  • find_gcp_metrics and query_gcp_promql registered as public, read-only MCP tools
  • GcpPromQlService joins the MCP runtime; the ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY

Before merge

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • 97445ed..b482a90 touches only the six GCP rail/lab/route files, all reverts of widget-branch UI; no PR file changed
  • No dangling GcpListRail/RailLink import at head: gcp-list-rail.tsx is gone and its callers are updated
  • Chat instant table reads points[0], which GcpPromQlSeries documents as the earliest of several for a range selector (packages/domain/src/http/gcp-promql.ts:103)
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
find_gcp_metrics / query_gcp_promql tool handlers inbound yes Effect.fn("McpTool.findGcpMetrics")/"McpTool.queryGcpPromQl" with Effect.annotateCurrentSpan({ orgId, "maple.ai.kind" }) (apps/ai/src/mcp/tools/gcp-promql.ts:130,338)
Google Cloud Monitoring PromQL read (per project) outbound yes GcpPromQlService.queryRange/queryInstant are Effect.fn spans annotating orgId, cached through EdgeCacheService (packages/backend/src/services/integrations/GcpPromQlService.ts:506,521)

b482a90 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 7/10 · likely safe to merge
Both earlier chat-view findings still hold at this head (tool-renderer.tsx:192, promql-chart-rows.ts:8); the tool handlers themselves are thoroughly tested and I found no new defect.
quality 88/100 · 1 warning · 1 note · tests covered · risk medium · 3/3 new units observable

Adds two public MCP tools that read a customer's Google Cloud Monitoring metrics live over Google's PromQL API, plus their chat rendering. The tool logic is well tested and nothing new breaks; two earlier findings about the chat views of instant and labelled series are still unfixed.

  • find_gcp_metrics and query_gcp_promql read Google Cloud Monitoring live over PromQL
  • promQlChartRows merges PromQL points into the chat query chart
  • Instant PromQL results render in chat as a DataTable

Before merge

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Both handlers open Effect.fn spans and annotate orgId (gcp-promql.ts:130, :338)
  • Live Google reads stay in the base's instrumented GcpPromQlService spans (GcpPromQlService.ts:506), no new bare fetch
  • The six files the kickoff lists as changed since b482a90 (gcp-integration-card.tsx, lab/*, routes/integrations.tsx) are not in this PR's diff — they are identical to the base branch
Observability coverage: 3 of 3 changes observable
Change Kind Observable Evidence
query_gcp_promql MCP handler inbound tool handler yes Effect.fn("McpTool.queryGcpPromQl") span plus annotateCurrentSpan (gcp-promql.ts:338)
find_gcp_metrics MCP handler inbound tool handler yes Effect.fn("McpTool.findGcpMetrics") span plus annotateCurrentSpan (gcp-promql.ts:156)
Google Cloud Monitoring read (queryRange/queryInstant/searchMetrics/describeMetric) outbound call yes Effect.fn spans inside GcpPromQlService, base branch (packages/backend/src/services/integrations/GcpPromQlService.ts:506)

f7c812a · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Both open findings are still in the head code; the new tool handlers and their error mapping are otherwise well covered.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 2/2 new units observable

Adds two public MCP tools that read a customer's Google Cloud Monitoring metrics live through Google's PromQL API, plus a chat chart/table renderer for the range and instant results. Contained and well tested on the tool side; the two earlier chat-renderer findings still stand at this head.

  • find_gcp_metrics searches or describes Google metric types and returns a starter query
  • query_gcp_promql runs PromQL per connected project, widening a fine step to 500 points
  • Chat draws range PromQL results as the query chart and instant ones as a table
  • The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY optionally

Before merge

  • Secret · Add MAPLE_GCP_SERVICE_ACCOUNT_KEY to the ai Worker's secret store in each environment (api already has it) · apps/ai/src/worker.ts:68

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • GcpPromQlError's union matches the tags toMcpError switches on (GcpPromQlService.ts:81-90), so none falls through
  • searchMetrics lowercases the needle (GcpPromQlService.ts:575), so the case-insensitive search description holds
  • limit: params.limit + 1 stays sane: P.limit clamps to 200 and searchMetrics slices without a cap check
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
find_gcp_metrics handler MCP tool yes Effect.fn("McpTool.findGcpMetrics") span plus orgId annotation (gcp-promql.ts:130, 156)
query_gcp_promql handler MCP tool yes Effect.fn("McpTool.queryGcpPromQl") span, orgId/kind/seriesCount annotations (gcp-promql.ts:327, 338, 365); the Google call's client span lives in GcpPromQlService

2de85f4 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Both earlier findings survive at this head; the chat renderer in tool-renderer.tsx has no test that would catch F1.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 2/2 new units observable

Adds two public MCP tools that read Google Cloud Monitoring live through Google's PromQL API, plus their chat rendering and the gcp.* output schemas. The tool and its wiring are sound, but both findings from the previous review still hold at this head.

  • find_gcp_metrics searches one project's metric types or describes one with a starter query
  • query_gcp_promql reads range or instant PromQL, one call per connected project
  • Chat draws range results as QueryChart, instant results as a table
  • ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY; MCP runtime gains GcpPromQlService

Before merge

  • Secret · Add MAPLE_GCP_SERVICE_ACCOUNT_KEY to the ai Worker's prd and dev secret stores; unset answers both tools as unavailable · apps/ai/src/worker.ts:68

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • stepSeconds is widened so a series carries at most 500 points (gcp-promql.ts:334)
  • Decode SchemaError remaps stepSeconds to bucket_seconds before it reaches the model (gcp-promql.ts:360)
  • Both handlers take the org from CurrentMcpTenant, never from a parameter (gcp-promql.ts:154, :329)
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
find_gcp_metrics MCP tool handler MCP tool yes Effect.fn("McpTool.findGcpMetrics") at apps/ai/src/mcp/tools/gcp-promql.ts:130
query_gcp_promql MCP tool handler MCP tool yes Effect.fn("McpTool.queryGcpPromQl") at apps/ai/src/mcp/tools/gcp-promql.ts:327, with orgId/kind/seriesCount span attributes

fa6c05e · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Both earlier findings still stand at this head, and the five files listed as changed since the last review are not in this PR's diff, so their deltas were unreachable.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 2/2 new units observable

Adds two read-only public MCP tools that read a customer's Google Cloud Monitoring metrics live over PromQL, wired into the ai runtime, the output catalog and the chat renderers. The change is contained; the earlier findings at this head are unchanged.

  • find_gcp_metrics and query_gcp_promql read Google Cloud Monitoring live through Google's PromQL API
  • Both tools join the MCP runtime with GcpPromQlService.layer and the tenant from the request
  • The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY as an optional secret
  • Chat draws range results as a chart and instant results as a table

Before merge

  • Secret · Set MAPLE_GCP_SERVICE_ACCOUNT_KEY on the ai Worker in the prd and dev secret stores · apps/ai/src/worker.ts:68

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Prompt params are decoded before use and orgId comes from CurrentMcpTenant (gcp-promql.ts:154, gcp-promql.ts:329)
  • QueryChart takes ISO bucket strings elsewhere too, so promQlChartRows needs no conversion
  • maple-ai is live in Maple (171k requests in 7 days), so the new tool spans are visible
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
find_gcp_metrics handler mcp tool yes Effect.fn("McpTool.findGcpMetrics") span plus annotateCurrentSpan({ orgId }), apps/ai/src/mcp/tools/gcp-promql.ts:130
query_gcp_promql handler mcp tool yes Effect.fn("McpTool.queryGcpPromQl"), maple.ai.kind and result.seriesCount attributes, apps/ai/src/mcp/tools/gcp-promql.ts:327

41d4c1a · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
New 20-metric cap matches the schema's maxLength(20); the two open chat-table findings live in files this head did not touch.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 1/1 new units observable

This head only tightens the dashboard variable draft validation and adds a mapping test; both files changed since the last review are correct. The earlier chat-table findings (F1, F2) are unremedied, so the PR still needs attention before merge.

  • draftError rejects a metric variable naming more than 20 metrics
  • dashboardVariableOptionsQuery test pins the metric-variable attribute-values mapping

Before merge

  • Secret · Set MAPLE_GCP_SERVICE_ACCOUNT_KEY in the prd and dev secret stores for the ai Worker (unset answers the tools as unavailable) · apps/ai/src/worker.ts:68

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Cap of 20 matches Schema.isMaxLength(20) on metricNames (packages/widgets/src/dashboard/shared/variables.ts:50)
  • F1's series.points[0] and F2's seriesKey join are byte-identical at this head → left open
  • Diff 41d4c1a..d6ee7ab touches only the two dashboard-variable files
Observability coverage: 1 of 1 changes observable
Change Kind Observable Evidence
query_gcp_promql / find_gcp_metrics live Google Cloud reads outbound call yes handlers are Effect.fn("McpTool.findGcpMetrics") / McpTool.queryGcpPromQl spans; dispatcher annotates maple.mcp.tool, and the handlers annotate orgId and result.seriesCount (apps/ai/src/mcp/tools/gcp-promql.ts:156,338,365)

d6ee7ab · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Tool logic and step/error mapping are pinned by tests, but the chat renderer path the two open defects live in has none.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 3/3 new units observable

Adds the two public, read-only Google Cloud PromQL MCP tools, their output schemas, the ai Worker's GCP key binding and the chat renderers. The tool logic is contained and well tested; the two renderer defects already open on this PR are still present at this head.

  • find_gcp_metrics and query_gcp_promql are registered, public and read-only
  • GcpPromQlService joins the MCP runtime; the ai Worker binds the GCP key
  • Chat charts query_gcp_promql timeseries, tables instant results

Before merge

  • Secret · Set MAPLE_GCP_SERVICE_ACCOUNT_KEY in the ai Worker's prd and dev secret stores (the diff only declares it as optionalSecret) · apps/ai/src/worker.ts:68

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Org always comes from CurrentMcpTenant; tools default to the public audience (registry.ts:342)
  • stepSeconds is ladder-floored at 60 and widened to ≤500 points, so the request schema accepts every window
  • Both handlers carry Effect.fn spans with orgId; the Google reads are spanned in GcpPromQlService
Observability coverage: 3 of 3 changes observable
Change Kind Observable Evidence
find_gcp_metrics handler (live metric search/describe) MCP tool handler yes Effect.fn("McpTool.findGcpMetrics") + annotateCurrentSpan (gcp-promql.ts:130,156)
query_gcp_promql handler MCP tool handler yes Effect.fn("McpTool.queryGcpPromQl") + annotateCurrentSpan orgId/kind/series (gcp-promql.ts:327,338,365)
Google Cloud Monitoring PromQL reads outbound HTTP yes Issued inside GcpPromQlService (base), whose searchMetrics/describeMetric/queryRange are Effect.fn-traced

b439899 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
Only the rail guard changed since b439899 and it is safe; the two earlier chat-rendering findings are unchanged at this head.
quality 88/100 · 1 warning · 1 note · tests partial · risk low · 2/3 new units observable

Adds two public MCP tools that read Google Cloud Monitoring live through Google's PromQL API, their output schemas, chat rendering and the ai Worker's service-account binding. Safe to merge; the one warn from the earlier review is still present.

  • find_gcp_metrics searches or describes metric types and returns a starter PromQL query
  • query_gcp_promql runs timeseries or instant PromQL per project, capping series and points
  • Chat draws range results as the query chart, instant results as a table
  • The infra GCP rail only claims 'no spans' once the overview query succeeded

Before merge

  • Secret · Add MAPLE_GCP_SERVICE_ACCOUNT_KEY to the ai Worker's prd and dev secret stores; unset only makes the tools answer unavailable · apps/ai/src/worker.ts:68

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • Rail guard: traced is undefined until Result.isSuccess(overviewResult) ($service/$name.tsx:307), so loading no longer reads as "no spans"
  • Open F1 still at head: the instant chat table prints series.points[0] (tool-renderer.tsx:192) while the tool renders the last point (gcp-promql.ts:388)
  • Step is widened to at most 500 points per series (gcp-promql.ts:334), pinned by the 35-day test at gcp-promql.test.ts:274
Observability coverage: 2 of 3 changes observable
Change Kind Observable Evidence
find_gcp_metrics MCP tool inbound tool handler yes Effect.fn("McpTool.findGcpMetrics") span with orgId annotation (gcp-promql.ts:130,156)
query_gcp_promql MCP tool inbound tool handler yes Effect.fn("McpTool.queryGcpPromQl") span with orgId, maple.ai.kind and result.seriesCount (gcp-promql.ts:327,338,365)
Live Google Cloud Monitoring PromQL read (per project) outbound HTTP call no sandbox_grep for withSpan/peer.service/instrument in packages/backend/src/services/integrations/GcpPromQlService.ts (base branch): no matches

9cb9e82 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention
The only new hunks are merge noise, but the instant-table bug in the chat renderer is unchanged and untested at this head.
quality 88/100 · 1 warning · 1 note · tests partial · risk medium · 2/2 new units observable

Two live Google Cloud PromQL MCP tools plus their chat rendering; the head only merges the widget branch in. The earlier instant-table defect in the chat renderer is still present, so the two open findings stand.

  • find_gcp_metrics / query_gcp_promql read Google Cloud Monitoring live through PromQL
  • Chat draws range results as a chart and instant results as a table
  • ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY and the tools join the MCP runtime

Before merge

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
What was checked
  • F1 still reproduces: packages/domain/src/http/gcp-promql.ts:104 documents a matrix for an instant range selector, and gcp-promql.ts:388 shows the last point while tool-renderer.tsx:192 uses `poi…
  • F2 still reproduces: seriesKey (promql-chart-rows.ts:8) still joins labels with , and =, unlike seriesName in gcp-promql.ts:103
  • Head merges gcp-workload-rail.tsx and service-map-gcp.tsx only: an index-suffixed rail key and accepting dbSystem "postgres"; both safe
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
find_gcp_metrics MCP tool handler MCP tool yes Effect.fn("McpTool.findGcpMetrics") with Effect.annotateCurrentSpan({ orgId }) (gcp-promql.ts:130, 156)
query_gcp_promql MCP tool handler MCP tool yes Effect.fn("McpTool.queryGcpPromQl"), orgId/maple.ai.kind/result.seriesCount on the span (gcp-promql.ts:327, 338, 365)

4b1c492 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@maple-review-bot

maple-review-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 7/10 · likely safe to merge
The tools are contained and tested, but the two open rendering defects are still in the head's chat path.
quality 88/100 · 1 warning · 1 note · tests covered · risk medium · 2/2 new units observable

Adds two public MCP tools that read Google Cloud Monitoring live over Google's PromQL API, their output schemas, chart/table rendering and the ai Worker's Google key binding. Safe to merge once the two open chat-rendering issues are fixed.

  • query_gcp_promql and find_gcp_metrics register as public read-only MCP tools
  • Range results draw through promQlChartRows; instant results as a table
  • The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY and GcpPromQlService joins the MCP runtime

Before merge

  • Secret · Add MAPLE_GCP_SERVICE_ACCOUNT_KEY to the ai app's prd and dev secret stores; without it both tools answer unavailable · apps/ai/src/worker.ts:68

Still open from earlier reviews

Production impact

Telemetry this change adds and removes (2)
  • ➕ span name McpTool.findGcpMetrics · apps/ai/src/mcp/tools/gcp-promql.ts:130
  • ➕ span name McpTool.queryGcpPromQl · apps/ai/src/mcp/tools/gcp-promql.ts:327
Observability coverage: 2 of 2 changes observable
Change Kind Observable Evidence
query_gcp_promql MCP tool Consumer span yes Effect.fn("McpTool.queryGcpPromQl") with annotateCurrentSpan at apps/ai/src/mcp/tools/gcp-promql.ts:327,338,365
find_gcp_metrics MCP tool Consumer span yes Effect.fn("McpTool.findGcpMetrics") with annotateCurrentSpan at apps/ai/src/mcp/tools/gcp-promql.ts:130,156

7bccd6c · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

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