Commit graph

618 commits

Author SHA1 Message Date
Radoslav Dimitrov
35b20719ee
fix(validators/oci): fail closed on upstream rate limiting (#1281) v1.7.9
## Summary

When the OCI validator's anonymous manifest fetch returns HTTP 429,
return a retryable error instead of `nil`. This aligns OCI with the
fail-closed behavior of the npm / PyPI / NuGet / MCPB validators, and
ensures the `io.modelcontextprotocol.server.name` label-match always
runs before a publish is accepted.

## Test plan

- [x] `go test ./internal/validators/registries/ -run TestValidateOCI`
passes locally
- [x] `gofmt` + `golangci-lint` clean on the changed file
- [ ] CI green

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 16:59:59 -04:00
dependabot[bot]
4e319e81ff
build(deps): bump github.com/go-git/go-git/v5 from 5.18.0 to 5.19.0 in /deploy (#1279)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git)
from 5.18.0 to 5.19.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/go-git/go-git/releases">github.com/go-git/go-git/v5's
releases</a>.</em></p>
<blockquote>
<h2>v5.19.0</h2>
<h2>What's Changed</h2>
<ul>
<li>build: Update module github.com/go-git/go-git/v5 to v5.18.0
[SECURITY] (releases/v5.x) by <a
href="https://github.com/go-git-renovate"><code>@​go-git-renovate</code></a>[bot]
in <a
href="https://redirect.github.com/go-git/go-git/pull/2010">go-git/go-git#2010</a></li>
<li>v5: Bump sha1cd and go-billy by <a
href="https://github.com/pjbgf"><code>@​pjbgf</code></a> in <a
href="https://redirect.github.com/go-git/go-git/pull/2060">go-git/go-git#2060</a></li>
<li>v5: Align object encoding with upstream by <a
href="https://github.com/pjbgf"><code>@​pjbgf</code></a> in <a
href="https://redirect.github.com/go-git/go-git/pull/2065">go-git/go-git#2065</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/go-git/go-git/compare/v5.18.0...v5.19.0">https://github.com/go-git/go-git/compare/v5.18.0...v5.19.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bc930f4cbe"><code>bc930f4</code></a>
Merge pull request <a
href="https://redirect.github.com/go-git/go-git/issues/2065">#2065</a>
from go-git/commit-v5</li>
<li><a
href="d315264343"><code>d315264</code></a>
plumbing: object, Reset object before decode</li>
<li><a
href="6e1d34890a"><code>6e1d348</code></a>
plumbing: object, Align Tree handling with upstream</li>
<li><a
href="e134ba34cf"><code>e134ba3</code></a>
tests: Skip double checks in Git v2.11</li>
<li><a
href="1971422f6b"><code>1971422</code></a>
tests: Add git conformance tests for signing verification</li>
<li><a
href="a387aa8857"><code>a387aa8</code></a>
plumbing: object, Add ErrMalformedTag</li>
<li><a
href="f415670d90"><code>f415670</code></a>
plumbing: object, Decode Tag headers via a state machine</li>
<li><a
href="5b0cd38a62"><code>5b0cd38</code></a>
plumbing: object, Reject multi-signature commits at Verify</li>
<li><a
href="fe8ed6223a"><code>fe8ed62</code></a>
plumbing: object, Align Tag.EncodeWithoutSignature with Commit</li>
<li><a
href="98e337d5bd"><code>98e337d</code></a>
plumbing: object, Add support for Tag.SignatureSHA256</li>
<li>Additional commits viewable in <a
href="https://github.com/go-git/go-git/compare/v5.18.0...v5.19.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-git/go-git/v5&package-manager=go_modules&previous-version=5.18.0&new-version=5.19.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/modelcontextprotocol/registry/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 07:21:18 -04:00
d 🔹
276037b1ad
docs(complete): align publish CLI flags with implementation (closes #767) (#1278)
## Summary

`complete.md` documents three flags for `mcp-publisher publish` that the
CLI does not actually parse:

- `--file=PATH` — Path to server.json
- `--registry=URL` — Registry URL override
- `--dry-run` — Validate without publishing

Reading
[`cmd/publisher/commands/publish.go`](https://github.com/modelcontextprotocol/registry/blob/main/cmd/publisher/commands/publish.go)
and
[`cmd/publisher/main.go`](https://github.com/modelcontextprotocol/registry/blob/main/cmd/publisher/main.go)
confirms the actual interface is a single positional `PATH` argument
(default `./server.json`):

```go
serverFile := \"server.json\"
if len(args) > 0 && !strings.HasPrefix(args[0], \"-\") {
    serverFile = args[0]
}
```

Registry URL is bound at login time via the saved token, and \"validate
without publishing\" is a separate `mcp-publisher validate` subcommand.
The bug user in #767 hit \"server.json not found\" precisely because
`--file .registry/server.json` is filtered out by the
`HasPrefix(args[0], \"-\")` check, leaving the default lookup in place.

## Background

The canonical reference at
[`docs/reference/cli/commands.md`](https://github.com/modelcontextprotocol/registry/blob/main/docs/reference/cli/commands.md)
was already updated to the correct positional shape. `complete.md` (the
concatenated single-file mirror of `docs/` used for LLM/quickstart
consumption) had drifted out of sync — these were the only remaining
`--file` references in the repo outside of test fixtures.

Per the discussion on the prior flag-implementation attempt in #771,
maintainers preferred fixing the documentation over adding the
unimplemented flags:

> @domdomegg: I'd lean towards removing the options from the docs.

This PR closes that loop on the last stale doc surface.

## Changes

`complete.md`: the `mcp-publisher publish` block now matches
`docs/reference/cli/commands.md` line-for-line (positional `PATH`, no
spurious flags, no dry-run example).

```diff
-mcp-publisher publish [options]
+mcp-publisher publish [PATH]

-- \`--file=PATH\` - Path to server.json (default: \`./server.json\`)
-- \`--registry=URL\` - Registry URL override
-- \`--dry-run\` - Validate without publishing
+- \`PATH\` - Path to server.json (default: \`./server.json\`)

-# Dry run validation
-mcp-publisher publish --dry-run
-
 # Custom file location
-mcp-publisher publish --file=./config/server.json
+mcp-publisher publish ./config/server.json
```

Closes #767.

## Out of scope

- `cmd/publisher/README.md:17` still shows `./bin/mcp-publisher publish
--registry=http://localhost:8080` in the contributor quickstart. The
flag is silently ignored at runtime (caught by the same
`HasPrefix(\"-\")` filter). Happy to fold that fix into this PR or send
a follow-up — flagging here in case a maintainer prefers one option.
- `complete.md` is missing `mcp-publisher validate` and `mcp-publisher
status` sections that exist in `docs/reference/cli/commands.md`. Out of
scope for this single-concern PR; if there's interest, a broader sync
would be a separate PR.

## Test plan

- [x] `grep -r -- '--file' .` outside test fixtures returns 0 hits after
the change
- [x] `grep -r 'mcp-publisher publish --' docs/ complete.md` shows only
legitimate flags (`--registry` on `login`)
- [x] No code changes — `make check` not exercised since this is
doc-only

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: d 🔹 <258577966+voidborne-d@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:01:52 -04:00
dependabot[bot]
1d36806960
build(deps): bump golang.org/x/mod from 0.35.0 to 0.36.0 (#1271)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.35.0 to
0.36.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="643da9ba74"><code>643da9b</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="ccc3cdf529"><code>ccc3cdf</code></a>
zip: include 'but content has correct sum' note in TestVCS</li>
<li><a
href="ab30318032"><code>ab30318</code></a>
zip: update zip hashes for new flate compression</li>
<li>See full diff in <a
href="https://github.com/golang/mod/compare/v0.35.0...v0.36.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/mod&package-manager=go_modules&previous-version=0.35.0&new-version=0.36.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-11 05:10:51 -04:00
dependabot[bot]
7bc506f245
build(deps): bump github.com/pulumi/pulumi/sdk/v3 from 3.236.0 to 3.237.0 in /deploy (#1272)
Bumps
[github.com/pulumi/pulumi/sdk/v3](https://github.com/pulumi/pulumi) from
3.236.0 to 3.237.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/releases">github.com/pulumi/pulumi/sdk/v3's
releases</a>.</em></p>
<blockquote>
<h2>v3.237.0</h2>
<h2>3.237.0 (2026-05-08)</h2>
<h3>Features</h3>
<ul>
<li>
<p>[cli] Include the running command name and detected AI agent (when
present) in the User-Agent header on Pulumi Cloud API requests
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22908">#22908</a></p>
</li>
<li>
<p>[engine] Include <code>result</code> on the summary engine event
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22883">#22883</a></p>
</li>
<li>
<p>[sdkgen] Eagerly error on schemas with unconstructable types
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22890">#22890</a></p>
</li>
<li>
<p>[cli/cloud] Auto-fill <code>lang</code> and <code>os</code> query
parameters on <code>pulumi cloud api</code> GET/HEAD requests when the
matched OpenAPI operation declares them and the caller hasn't supplied
them
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22726">#22726</a></p>
</li>
<li>
<p>[cli/package] Add <code>pulumi package new</code> to bootstrap a
Pulumi package from a template
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22837">#22837</a></p>
</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>
<p>[cli] Add blank-line gaps between <code>pulumi neo</code> TUI
conversation blocks
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22846">#22846</a></p>
</li>
<li>
<p>[cli/import] Preserve <code>__</code>-prefixed keys when generating
PCL for imported resource state, so provider-defined payloads round-trip
correctly
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22856">#22856</a></p>
</li>
<li>
<p>[cli/neo] Render <code>ux__ask_user</code> clarifying questions as
questions instead of approval prompts
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22862">#22862</a></p>
</li>
<li>
<p>[cli/neo] Fix a panic when cancelling a <code>pulumi neo</code>
session
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22898">#22898</a></p>
</li>
<li>
<p>[cli/neo] Render every assistant message in the TUI scrollback so
multi-turn commentary no longer disappears between tool calls</p>
</li>
<li>
<p>[cli/neo] Return the bare stack name and canonical project name from
<code>pulumi_preview</code> and <code>pulumi_up</code> tool results
instead of echoing the raw input
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22891">#22891</a></p>
</li>
<li>
<p>[codegen/pcl] Stop reporting spurious circular references when an
<code>ignoreChanges</code>, <code>hideDiffs</code>,
<code>replaceOnChanges</code>, or <code>additionalSecretOutputs</code>
entry shares a name with a top-level node
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22916">#22916</a></p>
</li>
<li>
<p>[programgen/pcl] Fix PCL binder panic when a conditional mixes a
Promise-typed branch with a try() branch
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22907">#22907</a></p>
</li>
<li>
<p>[sdk/python] Support <code>NotRequired</code>, <code>Required</code>
and <code>total=False</code> in TypedDicts for component resource arg
types
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22858">#22858</a></p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/blob/master/CHANGELOG.md">github.com/pulumi/pulumi/sdk/v3's
changelog</a>.</em></p>
<blockquote>
<h2>3.237.0 (2026-05-08)</h2>
<h3>Features</h3>
<ul>
<li>
<p>[cli] Include the running command name and detected AI agent (when
present) in the User-Agent header on Pulumi Cloud API requests
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22908">#22908</a></p>
</li>
<li>
<p>[engine] Include <code>result</code> on the summary engine event
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22883">#22883</a></p>
</li>
<li>
<p>[sdkgen] Eagerly error on schemas with unconstructable types
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22890">#22890</a></p>
</li>
<li>
<p>[cli/cloud] Auto-fill <code>lang</code> and <code>os</code> query
parameters on <code>pulumi cloud api</code> GET/HEAD requests when the
matched OpenAPI operation declares them and the caller hasn't supplied
them
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22726">#22726</a></p>
</li>
<li>
<p>[cli/package] Add <code>pulumi package new</code> to bootstrap a
Pulumi package from a template
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22837">#22837</a></p>
</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>
<p>[cli] Add blank-line gaps between <code>pulumi neo</code> TUI
conversation blocks
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22846">#22846</a></p>
</li>
<li>
<p>[cli/import] Preserve <code>__</code>-prefixed keys when generating
PCL for imported resource state, so provider-defined payloads round-trip
correctly
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22856">#22856</a></p>
</li>
<li>
<p>[cli/neo] Render <code>ux__ask_user</code> clarifying questions as
questions instead of approval prompts
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22862">#22862</a></p>
</li>
<li>
<p>[cli/neo] Fix a panic when cancelling a <code>pulumi neo</code>
session
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22898">#22898</a></p>
</li>
<li>
<p>[cli/neo] Render every assistant message in the TUI scrollback so
multi-turn commentary no longer disappears between tool calls</p>
</li>
<li>
<p>[cli/neo] Return the bare stack name and canonical project name from
<code>pulumi_preview</code> and <code>pulumi_up</code> tool results
instead of echoing the raw input
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22891">#22891</a></p>
</li>
<li>
<p>[codegen/pcl] Stop reporting spurious circular references when an
<code>ignoreChanges</code>, <code>hideDiffs</code>,
<code>replaceOnChanges</code>, or <code>additionalSecretOutputs</code>
entry shares a name with a top-level node
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22916">#22916</a></p>
</li>
<li>
<p>[programgen/pcl] Fix PCL binder panic when a conditional mixes a
Promise-typed branch with a try() branch
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22907">#22907</a></p>
</li>
<li>
<p>[sdk/python] Support <code>NotRequired</code>, <code>Required</code>
and <code>total=False</code> in TypedDicts for component resource arg
types
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22858">#22858</a></p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="dc35aff826"><code>dc35aff</code></a>
only don't run CI if changelog/config.yaml changes (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22937">#22937</a>)</li>
<li><a
href="a38b7dce73"><code>a38b7dc</code></a>
cli/neo: keep prior streaming text when the agent emits a new turn (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22897">#22897</a>)</li>
<li><a
href="6d84bb5ed7"><code>6d84bb5</code></a>
add continue-on-error to upload code coverage and upload codecov test
results...</li>
<li><a
href="8377d1277e"><code>8377d12</code></a>
Eagerly error on schemas with unconstructable types (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22890">#22890</a>)</li>
<li><a
href="9d209a07ad"><code>9d209a0</code></a>
bump java and yaml dependencies (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22932">#22932</a>)</li>
<li><a
href="dd82f69c24"><code>dd82f69</code></a>
LocalWorkspace.nested_config: use a new stack per test (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22926">#22926</a>)</li>
<li><a
href="c5180568c9"><code>c518056</code></a>
Fix flaky TestFuzz: targeted update with refresh + deleted parent (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22925">#22925</a>)</li>
<li><a
href="46486da224"><code>46486da</code></a>
Thread workspace.Context to ProviderFromSource (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22880">#22880</a>)</li>
<li><a
href="ad42ef389e"><code>ad42ef3</code></a>
increase nodejs automation API timeout (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22920">#22920</a>)</li>
<li><a
href="0b8a78bd77"><code>0b8a78b</code></a>
Test on Node.js 26 and drop 20 (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22872">#22872</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pulumi/pulumi/compare/v3.236.0...v3.237.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/pulumi/pulumi/sdk/v3&package-manager=go_modules&previous-version=3.236.0&new-version=3.237.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-11 05:10:33 -04:00
dependabot[bot]
fe0cb3bfcb
build(deps): bump sigstore/cosign-installer from 4.1.1 to 4.1.2 in the actions group (#1265)
Bumps the actions group with 1 update:
[sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).

Updates `sigstore/cosign-installer` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sigstore/cosign-installer/releases">sigstore/cosign-installer's
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump cosign to 3.0.6 in <a
href="https://redirect.github.com/sigstore/cosign-installer/pull/232">sigstore/cosign-installer#232</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="6f9f177880"><code>6f9f177</code></a>
Bump cosign to 3.0.6 (<a
href="https://redirect.github.com/sigstore/cosign-installer/issues/232">#232</a>)</li>
<li><a
href="b5e753ae2d"><code>b5e753a</code></a>
Bump actions/github-script from 8.0.0 to 9.0.0 (<a
href="https://redirect.github.com/sigstore/cosign-installer/issues/230">#230</a>)</li>
<li><a
href="115e4ce455"><code>115e4ce</code></a>
Bump actions/setup-go from 6.3.0 to 6.4.0 (<a
href="https://redirect.github.com/sigstore/cosign-installer/issues/226">#226</a>)</li>
<li>See full diff in <a
href="cad07c2e89...6f9f177880">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sigstore/cosign-installer&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
2026-05-08 07:57:35 -04:00
dependabot[bot]
8af641cf1c
build(deps): bump github.com/pulumi/pulumi/sdk/v3 from 3.235.0 to 3.236.0 in /deploy (#1264)
Bumps
[github.com/pulumi/pulumi/sdk/v3](https://github.com/pulumi/pulumi) from
3.235.0 to 3.236.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/releases">github.com/pulumi/pulumi/sdk/v3's
releases</a>.</em></p>
<blockquote>
<h2>v3.236.0</h2>
<h2>3.236.0 (2026-05-06)</h2>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/blob/master/CHANGELOG.md">github.com/pulumi/pulumi/sdk/v3's
changelog</a>.</em></p>
<blockquote>
<h2>3.236.0 (2026-05-06)</h2>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="7db07780c1"><code>7db0778</code></a>
exclude another nodejs language test for bun (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22861">#22861</a>)</li>
<li><a
href="3a74cfbe73"><code>3a74cfb</code></a>
Bump the version of pulumi-hcl to v0.2.0 (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22867">#22867</a>)</li>
<li><a
href="8437bfea3a"><code>8437bfe</code></a>
Expand <code>l1-output-map</code> to handle adversarial strings (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22854">#22854</a>)</li>
<li><a
href="a9b310f7c9"><code>a9b310f</code></a>
cli/neo: support typing quit/exit to leave the TUI (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22859">#22859</a>)</li>
<li><a
href="f499abf677"><code>f499abf</code></a>
cli/neo: show CLI version in the welcome banner (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22860">#22860</a>)</li>
<li><a
href="cec8b905e2"><code>cec8b90</code></a>
fix integration test (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22857">#22857</a>)</li>
<li><a
href="060f73f614"><code>060f73f</code></a>
Add changelog message guidance to AGENTS.md (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22848">#22848</a>)</li>
<li><a
href="a9f6c19a13"><code>a9f6c19</code></a>
skip more signal cancellation tests (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22844">#22844</a>)</li>
<li><a
href="b0b94fa329"><code>b0b94fa</code></a>
Change PluginInfo timestamps to be cached like size (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22839">#22839</a>)</li>
<li><a
href="1e4e2f0052"><code>1e4e2f0</code></a>
freeze 3.235.0 (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22850">#22850</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pulumi/pulumi/compare/v3.235.0...v3.236.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/pulumi/pulumi/sdk/v3&package-manager=go_modules&previous-version=3.235.0&new-version=3.236.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
2026-05-08 07:57:18 -04:00
dependabot[bot]
d93f8f78a0
build(deps): bump cloud.google.com/go/kms from 1.30.0 to 1.31.0 (#1263)
Bumps
[cloud.google.com/go/kms](https://github.com/googleapis/google-cloud-go)
from 1.30.0 to 1.31.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-cloud-go/releases">cloud.google.com/go/kms's
releases</a>.</em></p>
<blockquote>
<h2>kms: v1.31.0</h2>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/kms/v1.30.0...kms/v1.31.0">v1.31.0</a>
(2026-05-07)</h2>
<h2>retail: v1.31.0</h2>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/retail/v1.30.0...retail/v1.31.0">v1.31.0</a>
(2026-05-07)</h2>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md">cloud.google.com/go/kms's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/documentai/v1.30.5...documentai/v1.31.0">1.31.0</a>
(2024-08-01)</h2>
<h3>Features</h3>
<ul>
<li><strong>documentai:</strong> A new field <code>imageless_mode</code>
is added to message
<code>.google.cloud.documentai.v1.ProcessRequest</code> (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/10615">#10615</a>)
(<a
href="97fa56008a">97fa560</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li><strong>documentai:</strong> Keep the API doc up-to-date with recent
changes (<a
href="97fa56008a">97fa560</a>)</li>
</ul>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/documentai/v1.30.4...documentai/v1.30.5">1.30.5</a>
(2024-07-24)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>documentai:</strong> Update dependencies (<a
href="257c40bd6d">257c40b</a>)</li>
</ul>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/documentai/v1.30.3...documentai/v1.30.4">1.30.4</a>
(2024-07-10)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>documentai:</strong> Bump google.golang.org/grpc@v1.64.1 (<a
href="8ecc4e9622">8ecc4e9</a>)</li>
</ul>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/documentai/v1.30.2...documentai/v1.30.3">1.30.3</a>
(2024-07-01)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>documentai:</strong> Bump google.golang.org/api@v0.187.0 (<a
href="8fa9e398e5">8fa9e39</a>)</li>
</ul>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/documentai/v1.30.1...documentai/v1.30.2">1.30.2</a>
(2024-06-26)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>documentai:</strong> Enable new auth lib (<a
href="b95805f4c8">b95805f</a>)</li>
</ul>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/documentai/v1.30.0...documentai/v1.30.1">1.30.1</a>
(2024-06-20)</h2>
<h3>Documentation</h3>
<ul>
<li><strong>documentai:</strong> Update the comment to add a note about
<code>documentai.processors.create</code> permission (<a
href="4fa4308251">4fa4308</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9a44b31c75"><code>9a44b31</code></a>
chore: librarian release pull request: 20260409T070606Z (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14406">#14406</a>)</li>
<li><a
href="18a3318e01"><code>18a3318</code></a>
feat: Make AgentEngine APIs public</li>
<li><a
href="db45f2d9b6"><code>db45f2d</code></a>
feat(bigtable): enable bigtable conn pool by default (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14319">#14319</a>)</li>
<li><a
href="124ffd3b68"><code>124ffd3</code></a>
feat(vertexai): Add AgentEngine Memories Revisions module</li>
<li><a
href="e247d48b88"><code>e247d48</code></a>
chore: onboard new library appoptimize (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14393">#14393</a>)</li>
<li><a
href="ece84abc19"><code>ece84ab</code></a>
chore: update librarian to v0.10.1-0.20260408193841-095ea7e727aa (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14392">#14392</a>)</li>
<li><a
href="ecf9783b6e"><code>ecf9783</code></a>
chore: librarian release pull request: 20260408T191440Z (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14390">#14390</a>)</li>
<li><a
href="70b47d20b8"><code>70b47d2</code></a>
chore: librarian release pull request: 20260408T190447Z (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14389">#14389</a>)</li>
<li><a
href="95c53a6540"><code>95c53a6</code></a>
chore(bigquery): bump <code>api</code> to v0.275.0 and unskip bq tracing
tests (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14333">#14333</a>)</li>
<li><a
href="df22e9e38e"><code>df22e9e</code></a>
fix(storage): add retry logic for &quot;http2: client connection
lost&quot; (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14385">#14385</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/googleapis/google-cloud-go/compare/kms/v1.30.0...dlp/v1.31.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cloud.google.com/go/kms&package-manager=go_modules&previous-version=1.30.0&new-version=1.31.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
2026-05-08 07:56:59 -04:00
Radoslav Dimitrov
f5fe2e97f6
build(deps): bump golang.org/x/net from v0.52.0 to v0.53.0 (#1269)
## Summary

Bumps `golang.org/x/net` from `v0.52.0` to `v0.53.0` to address
`GO-2026-4918` (HTTP/2 transport infinite loop on bad
`SETTINGS_MAX_FRAME_SIZE`). `go mod tidy` also pulls
`golang.org/x/crypto` to v0.50.0 and `golang.org/x/text` to v0.36.0.

## Why now

`govulncheck` is failing on `main` and every open Dependabot PR (#1263,
#1264, #1265) after the 2026-05 Go security release. The findings split
into:

- **One we control** — `golang.org/x/net@v0.52.0` → fixed in `v0.53.0`.
Addressed here.
- **Six stdlib findings** (`GO-2026-4986`, `4982`, `4980`, `4977`,
`4971`, and the stdlib half of `4918`) — all fixed in `go1.26.3`. We
deliberately do **not** pin a Go patch in the workflow: `go-version:
'stable'` will pick up `1.26.3` automatically once the
`actions/go-versions` manifest catches up, with no workflow maintenance.

## Test plan

- [x] `go build ./...`
- [x] `go vet ./...`
- [x] `GOTOOLCHAIN=go1.26.3 govulncheck ./...` → "No vulnerabilities
found."

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 07:33:10 -04:00
Andrew Cunliffe
718735cfbb
docs(authentication): note OpenSSL 3.x requirement for Ed25519 (#1253)
## Summary

The DNS and HTTP authentication guides currently run `openssl genpkey
-algorithm Ed25519 -out key.pem` without caveat. macOS ships LibreSSL as
the system `openssl` binary, and LibreSSL doesn't implement Ed25519 in
`genpkey` — so the very first command in the Ed25519 codepath errors out
with:

```
Algorithm Ed25519 not found
```

A first-time integrator on macOS hits this immediately, with no path to
a fix from the docs alone. Cost me ~5 minutes earlier today before I
figured out I needed `brew install openssl@3` and an explicit binary
path.

This PR adds a `<Note>` callout to the **DNS Authentication** section
right above the Ed25519 codepath, and a shorter cross-reference Note in
the **HTTP Authentication** section since the same `openssl genpkey
-algorithm Ed25519` commands appear there. The ECDSA P-384 codepath
works on LibreSSL, so it's untouched.

## Test plan

- [x] Verified locally that `/opt/homebrew/opt/openssl@3/bin/openssl
genpkey -algorithm Ed25519 -out key.pem` works on macOS Darwin 25.4.0
- [x] Verified the system `/usr/bin/openssl genpkey -algorithm Ed25519
-out key.pem` fails with `Algorithm Ed25519 not found` on the same
machine (LibreSSL 3.3.6)
- [x] Verified the published `ai.ravenmcp/raven-mcp` flow end-to-end
with the OpenSSL 3 binary
- [ ] Markdown rendering of the `<Note>` callouts — relying on the
existing `<Note>` pattern in this file (line 6) to validate the syntax

Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
2026-05-07 10:42:37 -04:00
Radoslav Dimitrov
321337c810
docs: add ToolHive Registry Server to community projects (#1261)
## Summary

- Add a new **Registry Implementations** section to
`docs/community-projects.md` for self-hostable servers that implement
the MCP Registry API spec.
- Move existing **ToolSDK MCP Registry** entry from "Other" into the new
section.
- Add **ToolHive Registry Server**
(https://github.com/stacklok/toolhive-registry-server) to the new
section.

## Test plan

- [x] `docs/community-projects.md` renders correctly (markdown only, no
build step).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:36:03 -04:00
dependabot[bot]
6ae2d54e73
build(deps): bump github.com/pulumi/pulumi/sdk/v3 from 3.234.0 to 3.235.0 in /deploy (#1259) 2026-05-06 17:34:08 -04:00
Radoslav Dimitrov
2b90d93712
deploy: update prod to v1.7.8 (#1256)
## Summary
- Bump `mcp-registry:imageTag` from `1.7.7` → `1.7.8` in
`deploy/Pulumi.gcpProd.yaml`
- v1.7.8 ships the metrics fix that stops counting client-cancelled
requests as server errors (#1255). Under scraper-driven load, clients
with short timeouts close the socket while PG is still iterating; the
handler converts `context.Canceled` to a 500 and the metric middleware
was bumping `mcp_registry_http_errors_total` even though NGINX recorded
499 and never delivered a response. This is what's been firing the daily
~17:00 UTC `Availability dropped below 95%` alert.
- Also includes a CI-only `pulumi/actions` 6.6.1 → 7.0.0 bump (#1254).
No registry runtime impact.
- Staging is on `4e14707` (the v1.7.8 commit) and
`staging.registry.modelcontextprotocol.io/v0.1/version` reports it.

## Test plan
- [ ] Confirm release workflow's `ko-push` job has published
`ghcr.io/modelcontextprotocol/registry:1.7.8` before merging
- [ ] Watch deploy-production roll the registry pods to `1.7.8`
- [ ] Hit `https://registry.modelcontextprotocol.io/v0.1/version` and
confirm `git_commit` matches `4e147072f0`
- [ ] Through the next ~17:00 UTC scraper burst, watch in Prometheus:
- `mcp_registry_http_errors_total{status_code="500",
path="/v0.1/servers"}` should stay flat
- `mcp_registry_http_requests_total{status_code="499",
path="/v0.1/servers"}` should grow during the burst
- The `Availability dropped below 95%` alert should not fire on
cancellation-only bursts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 06:14:49 -04:00
Radoslav Dimitrov
4e147072f0
metrics: stop counting client-cancelled requests as server errors (#1255) v1.7.8
## Summary

- Remap recorded status to `499` (NGINX-style "client closed") when
`ctx.Context().Err()` is `context.Canceled` after the handler returns
- Skip the `http_errors_total` increment for `499`s so the availability
metric reflects server-visible errors only

## Why

Under scraper-driven load, clients with short timeouts paginate
`/v0.1/servers`, give up while PG is busy, and close the TCP connection.
The handler's DB iteration returns `context canceled`, the handler
converts that to `huma.Error500InternalServerError`, and tries to write
a response to the now-closed socket. NGINX records `499` (client closed)
and never delivers anything to the client — but the registry's
middleware records `status_code=500` and bumps
`mcp_registry_http_errors_total`.

That's what's been firing the `Availability dropped below 95%` alert
during the daily 17:00 UTC bursts. Recent prod numbers from one pod
(~19h uptime):

```
mcp_registry_http_errors_total{path="/v0.1/servers", status_code="500"} 7396
mcp_registry_http_errors_total{path="/v0.1/servers/{serverName}/versions", status_code="500"} 283
mcp_registry_http_errors_total{path="/v0/servers", status_code="500"} 352
```

…against zero 5xx in NGINX ingress logs over the same window. The alert
was correct *given the data it had*; the data was misclassifying client
cancellations as server errors.

## What this does

In `internal/api/router/router.go` (the metric middleware): after
`next(ctx)`, check `ctx.Context().Err()`. If it's `context.Canceled`,
override `statusCode` to `499` and skip the error counter. Requests
counter and duration histogram still record so the cancellation rate
stays visible.

`context.DeadlineExceeded` is intentionally **not** remapped — that
would indicate a server-side timeout if we ever add per-request
deadlines, and should still count as a server error.

## What this does *not* do

- Doesn't reduce the underlying load (ServiceNow + notion catalog
scrapers driving the daily peak — separate work, see the `updated_since`
outreach we're doing).
- Doesn't change handler behaviour — handlers still call
`huma.Error500…` on `context.Canceled`. We could short-circuit earlier
(return without writing) to save the work, but that's a bigger refactor
and the metric fix unblocks the alert immediately.

## Companion change (no code, just a Grafana annotation tweak)

The `Availability dropped below 95%` alert (UID `bexrc60etvhmoa`)
currently has the annotation:

> No. of 5xx are increased from acceptable limit i.e. 5% of total
throughput

The query is on `mcp_registry_http_errors_total`, not 5xx specifically.
After this change the count is meaningful again, but the wording is
still misleading. Suggest updating to:

> Internal error rate exceeded 5% of total throughput

(no PromQL change required.)

## Test plan

- [x] `go test ./internal/api/router/...` — new test passes
- [x] `golangci-lint run ./internal/...` — clean
- [ ] After merge, watch a daily 17:00 UTC burst —
`mcp_registry_http_errors_total{status_code="500",
path="/v0.1/servers"}` should stay flat while
`mcp_registry_http_requests_total{status_code="499",
path="/v0.1/servers"}` grows. Availability alert should not fire on
cancellation-only bursts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 05:58:05 -04:00
dependabot[bot]
6d6a887174
build(deps): bump pulumi/actions from 6.6.1 to 7.0.0 in the actions group (#1254)
Bumps the actions group with 1 update:
[pulumi/actions](https://github.com/pulumi/actions).

Updates `pulumi/actions` from 6.6.1 to 7.0.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/actions/releases">pulumi/actions's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>minor style fixups for CONTRIBUTING.md by <a
href="https://github.com/tgummerer"><code>@​tgummerer</code></a> in <a
href="https://redirect.github.com/pulumi/actions/pull/1396">pulumi/actions#1396</a></li>
<li>Allow downloading PR artifacts by <a
href="https://github.com/iwahbe"><code>@​iwahbe</code></a> in <a
href="https://redirect.github.com/pulumi/actions/pull/1397">pulumi/actions#1397</a></li>
<li>Bump Node runtime from 20 to 24 by <a
href="https://github.com/nelsonfigueroa"><code>@​nelsonfigueroa</code></a>
in <a
href="https://redirect.github.com/pulumi/actions/pull/1404">pulumi/actions#1404</a></li>
<li>Bump TypeScript and jest toolchain by <a
href="https://github.com/nelsonfigueroa"><code>@​nelsonfigueroa</code></a>
in <a
href="https://redirect.github.com/pulumi/actions/pull/1405">pulumi/actions#1405</a></li>
<li>chore: update ESLint stack and migrate to flat config by <a
href="https://github.com/nelsonfigueroa"><code>@​nelsonfigueroa</code></a>
in <a
href="https://redirect.github.com/pulumi/actions/pull/1406">pulumi/actions#1406</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/iwahbe"><code>@​iwahbe</code></a> made
their first contribution in <a
href="https://redirect.github.com/pulumi/actions/pull/1397">pulumi/actions#1397</a></li>
<li><a
href="https://github.com/nelsonfigueroa"><code>@​nelsonfigueroa</code></a>
made their first contribution in <a
href="https://redirect.github.com/pulumi/actions/pull/1404">pulumi/actions#1404</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pulumi/actions/compare/v6...v7.0.0">https://github.com/pulumi/actions/compare/v6...v7.0.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/actions/blob/main/CHANGELOG.md">pulumi/actions's
changelog</a>.</em></p>
<blockquote>
<h1>CHANGELOG</h1>
<h2>HEAD (Unreleased)</h2>
<p><strong>(none)</strong></p>
<hr />
<h2>7.0.0 (2026-05-01)</h2>
<ul>
<li>chore: update Action runtime to node 24
(<a
href="https://redirect.github.com/pulumi/actions/pull/1404">#1404</a>)</li>
<li>chore: bump <code>typescript</code>, <code>jest</code>,
<code>ts-jest</code>, <code>@types/jest</code>, <code>@types/node</code>
(<a
href="https://redirect.github.com/pulumi/actions/pull/1405">#1405</a>)</li>
<li>chore: update ESLint stack and migrate to flat config
(<a
href="https://redirect.github.com/pulumi/actions/pull/1406">#1406</a>)</li>
</ul>
<h2>6.6.1 (2025-11-12)</h2>
<ul>
<li>chore: Update pulumi/pulumi dependency
(<a
href="https://redirect.github.com/pulumi/actions/pull/1394">#1394</a>)</li>
</ul>
<h2>6.6.0 (2025-09-29)</h2>
<ul>
<li>feat: Strip ansi control characters from GitHub step Summary and PR
comment
(<a
href="https://redirect.github.com/pulumi/actions/pull/1312">#1312</a>)</li>
</ul>
<h2>6.4.0 (2025-07-16)</h2>
<ul>
<li>feat: Add <code>run-program</code> flag support for refresh,
destroy, preview, and
up/update commands (<a
href="https://redirect.github.com/pulumi/actions/pull/1376">#1376</a>)</li>
</ul>
<h2>6.3.0 (2025-05-08)</h2>
<ul>
<li>
<p>feat: support <code>--exclude</code> and
<code>--exclude-dependents</code> flags
(<a
href="https://redirect.github.com/pulumi/actions/pull/1363">#1363</a>)</p>
</li>
<li>
<p>feat: verbosity and debug inputs to enable debug options
(<a
href="https://redirect.github.com/pulumi/actions/pull/1046">#1046</a>)</p>
</li>
<li>
<p>fix: update &quot;user agent&quot; string to pulumi/actions@v6
(<a
href="https://redirect.github.com/pulumi/actions/pull/1367">#1357</a>)</p>
</li>
</ul>
<h2>6.2.0 (2025-03-05)</h2>
<ul>
<li>feat: support continue on error flag (--continue-on-error)
(<a
href="https://redirect.github.com/pulumi/actions/pull/1357">#1357</a>)</li>
</ul>
<h2>6.1.0 (2025-02-27)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8e5e406f40"><code>8e5e406</code></a>
prepare v7.0.0 release (<a
href="https://redirect.github.com/pulumi/actions/issues/1407">#1407</a>)</li>
<li><a
href="22d32ee565"><code>22d32ee</code></a>
chore: update ESLint stack and migrate to flat config (<a
href="https://redirect.github.com/pulumi/actions/issues/1406">#1406</a>)</li>
<li><a
href="bee3070c66"><code>bee3070</code></a>
Bump TypeScript and jest toolchain (<a
href="https://redirect.github.com/pulumi/actions/issues/1405">#1405</a>)</li>
<li><a
href="eec25fe0b5"><code>eec25fe</code></a>
Bump Node runtime from 20 to 24 (<a
href="https://redirect.github.com/pulumi/actions/issues/1404">#1404</a>)</li>
<li><a
href="85a185baea"><code>85a185b</code></a>
chore(dist): Update dist [automated commit]</li>
<li><a
href="7bf44bfc85"><code>7bf44bf</code></a>
Allow downloading PR builds</li>
<li><a
href="ba4238626c"><code>ba42386</code></a>
minor style fixups for CONTRIBUTING.md (<a
href="https://redirect.github.com/pulumi/actions/issues/1396">#1396</a>)</li>
<li>See full diff in <a
href="8582a9e8cc...8e5e406f40">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pulumi/actions&package-manager=github_actions&previous-version=6.6.1&new-version=7.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-05 03:50:20 -04:00
Radoslav Dimitrov
1b9f69e81b
deploy: update prod to v1.7.7 (#1251)
## Summary
- Bump `mcp-registry:imageTag` from `1.7.6` → `1.7.7` in
`deploy/Pulumi.gcpProd.yaml`
- v1.7.7 is a security patch covering three findings (validator
hardening, attribute-context UI escaping, IPv6 SSRF blocklist
extension); see the v1.7.7 release notes
- Staging is on `f5f40bd` (the v1.7.7 commit) and verified end-to-end:
  - `/v0.1/version` reports the new commit
- `/v0.1/validate` rejects a poisoned `websiteUrl` with
`website-url-invalid-characters`
  - `/` HTML serves the `escapeAttr` helper

## Test plan
- [ ] Confirm release workflow's `ko-push` job has finished publishing
`ghcr.io/modelcontextprotocol/registry:1.7.7` before merging
- [ ] Watch deploy-production workflow rolls the registry pods to
`1.7.7`
- [ ] Hit `https://registry.modelcontextprotocol.io/v0.1/version` and
confirm `git_commit` matches `f5f40bd...`
- [ ] Spot-check the catalogue UI loads cleanly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 10:07:32 -04:00
Radoslav Dimitrov
f5f40bd980
fix(auth/http): extend SSRF blocklist to IPv6 6to4/NAT64/site-local prefixes (#1250) v1.7.7
The HTTP namespace-verification fetcher's `isBlockedIP` composed its
blocklist from Go stdlib's `Is*` helpers plus a manual CGNAT range. That
covers IPv4 cloud metadata, RFC1918, ULA, and link-local — but Go's
classification helpers don't recognise IPv6 prefix families that embed
or tunnel to arbitrary IPv4:

  - 2002::/16       RFC 3056 6to4 — bits 16-47 are an arbitrary IPv4
  - 64:ff9b::/96    RFC 6052 NAT64 well-known — low 32 bits are IPv4
  - 64:ff9b:1::/48  RFC 8215 NAT64 local-use — same IPv4-embedding shape
  - fec0::/10       RFC 3879 site-local (deprecated, still routed by
                    some stacks)

On hosts with 6to4 routing or a NAT64 next-hop (the default on
IPv6-only GKE node pools, AWS IPv6-only EC2, Azure IPv6 VMs with
NAT64, and many corporate DNS64/NAT64 networks), an attacker who
controls DNS for a publisher domain can cause the registry to dial
`169.254.169.254`, `10.0.0.0/8`, etc. via the IPv6 wrapper. Same
SSRF class as GHSA-56c3-vfp2-5qqj on n8n-mcp.

Define the four prefixes via a new `mustCIDR` helper (panic on
malformed CIDR at init so a typo can't fail-open silently) and iterate
them in `isBlockedIP` after the stdlib gates. Refactor the existing
CGNAT IIFE to use the same helper for consistency. IPv4-mapped IPv6
(::ffff:0:0/96) needs no special-casing: Go's `Is*` helpers honour the
`To4()` fast-path, so e.g. `::ffff:10.0.0.1` is already classified as
`IsPrivate`.

Adds 17 test cases to `TestIsBlockedIP` covering each new prefix
family, IPv4-mapped IPv6 sanity checks, and just-outside-the-range
positive controls (`2001::1`, `2003::1`, `64:ff9c::1`).

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

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 09:41:23 -04:00
Radoslav Dimitrov
78b7bbde07
fix(validators): reject HTML metacharacters and whitespace in websiteUrl (#1249)
`validateWebsiteURL` only checked that the URL parses, is absolute, and
uses the `https` scheme. It accepted literal `"`, `'`, `<`, `>`, and
ASCII space — none of which are valid in a URI per RFC 3986, and all of
which broke rendering when the value flowed into the catalogue UI's
`<a href="...">` template.

Add a `strings.IndexAny` check after the scheme check that rejects any
of these characters with a clear `website-url-invalid-characters` issue
that points at the offending byte position. Control characters (`\t`,
`\n`, `\r`) are also covered: they're caught one step earlier by Go's
`url.Parse`, but the bytes are listed in the rejection set so the
behaviour is explicit and survives any future relaxation of `url.Parse`.
Already-percent-encoded URLs (e.g. `?q=hello%20world`) continue to
validate cleanly.

Adds table-driven cases for `"`, `'`, `<>`, space, newline, and a
positive case for percent-encoded special characters.

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

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 09:26:50 -04:00
Radoslav Dimitrov
fbfd63ced8
fix(ui): encode publisher-controlled URLs for href attribute context (#1248)
The catalogue page interpolates publisher-supplied URL fields
(`server.repository.url`, `server.websiteUrl`) inside `href="..."`
attributes via `innerHTML`, escaping them with a
`textContent`→`innerHTML`
helper. Per the HTML5 fragment-serialisation algorithm, that round-trip
encodes only `&`, `<`, `>`, and U+00A0 inside text nodes — it does not
encode `"` or `'`. The helper is therefore safe in element-text
contexts (where it is used for `name`, `version`, `description`, etc.)
but unsafe inside an attribute value.

Add an attribute-safe `escapeAttr` helper that follows the OWASP
attribute-encoding rule (also encodes `"` and `'`) and use it for the
two `href` interpolations. Element-text usages keep the existing
`escapeHtml` and remain unchanged. A short comment on each helper
documents the contexts they cover so future fields are wired up
correctly.

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

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 09:25:41 -04:00
Radoslav Dimitrov
7a4216c528
refactor: rename readBody to readErrorBody and cap body size (#1246)
## Summary

Follow-up to #1241. Two small tweaks to the `readBody` helper:

- **Rename `readBody` → `readErrorBody`.** The helper is only ever
called on the error path (after a non-2xx status check), where we want a
small string for diagnostics. The generic name made it look reusable on
the success path, where streaming JSON decoding is the right approach.
The new name pins the intended use down.
- **Cap the read with `io.LimitReader` (8 KiB).** Defense in depth —
error diagnostics never need more than a few KB, and we shouldn't buffer
an arbitrarily large body from an upstream just to format an error
message. 8 KiB is well above any realistic GitHub API or JWKS error
response.

No behavior change on the happy path. On the unhappy path, error
messages are now bounded.

## Test plan

- [x] `go build ./...`
- [x] `go test ./internal/api/handlers/v0/auth/...`

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-04 07:09:57 -04:00
Mesut Oezdil
6f9bd6661c
refactor: extract readBody helper to remove duplicate io.ReadAll calls (#1241)
The same pattern for reading an error response body appeared in three
places across the auth handlers:

- `internal/api/handlers/v0/auth/github_at.go` (twice)
- `internal/api/handlers/v0/auth/github_oidc.go` (once)

A shared `readBody` helper function added to `common.go` now handles
this in one place.
The `io` import is removed from both files since it is no longer used
directly there.

---------

Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
2026-05-04 06:57:02 -04:00
Radoslav Dimitrov
dfaa8f3b82
auth/oidc: test slice-typed extra claims comparison (#1245)
## Summary
Follow-up to #1238 (closes #988). Adds direct unit-test coverage for the
`claimMatches` helper, which was the actual change in #1238.

`claimMatches` and `toAnySlice` are unexported, so the tests live in
`oidc_internal_test.go` (`package auth`) — same pattern as
`http_internal_test.go`. Cases covered:

- scalar/scalar match and mismatch
- scalar actual against array expected (both directions of overlap)
- array actual against scalar expected
- **array/array** — pre-#1238 this combination panicked with `comparing
uncomparable type []interface {}`
- `[]string` typed slice (exercises the typed-slice branch of
`toAnySlice`, which `[]any` skips)
- non-string scalars (int, bool)
- empty actual array

Test values use single letters (`x`, `y`, `p`, `q`) rather than role
labels — only the relationships matter, and short tokens keep `goconst`
quiet.

## Test plan
- [x] `go test ./internal/api/handlers/v0/auth/...` — all 13 subtests
pass
- [x] `golangci-lint run ./internal/api/handlers/v0/auth/...` — no new
issues vs main
2026-05-04 06:52:12 -04:00
Sai Asish Y
811046c4ce
auth/oidc: support slice-typed extra claims via overlap match (#1238)
Closes #988. Direct `actualValue != expectedValue` fails when the token
claim is an array (groups, roles, scp, aud). Switch to a slice-aware
any-of overlap so OIDC list claims are validated correctly.
2026-05-04 06:24:34 -04:00
dependabot[bot]
f3308d16f5
build(deps): bump github.com/pulumi/pulumi/sdk/v3 from 3.233.0 to 3.234.0 in /deploy (#1237)
Bumps
[github.com/pulumi/pulumi/sdk/v3](https://github.com/pulumi/pulumi) from
3.233.0 to 3.234.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/releases">github.com/pulumi/pulumi/sdk/v3's
releases</a>.</em></p>
<blockquote>
<h2>v3.234.0</h2>
<h2>3.234.0 (2026-05-01)</h2>
<h3>Features</h3>
<ul>
<li>
<p>[cli/cloud] Add <code>pulumi cloud api describe</code> for inspecting
the parameters, request
body, and response schema of any Pulumi Cloud API operation, with
text, markdown, and JSON output</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22770">#22770</a></p>
</li>
<li>
<p>[cli/cloud] Add <code>pulumi cloud api list</code> for browsing every
endpoint exposed by the Pulumi
Cloud OpenAPI spec, with table and JSON output</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22769">#22769</a></p>
</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>[engine] Revert changes to property path parsing that resulted in
errors for currently valid paths</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/blob/master/CHANGELOG.md">github.com/pulumi/pulumi/sdk/v3's
changelog</a>.</em></p>
<blockquote>
<h2>3.234.0 (2026-05-01)</h2>
<h3>Features</h3>
<ul>
<li>
<p>[cli/cloud] Add <code>pulumi cloud api describe</code> for inspecting
the parameters, request
body, and response schema of any Pulumi Cloud API operation, with
text, markdown, and JSON output</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22770">#22770</a></p>
</li>
<li>
<p>[cli/cloud] Add <code>pulumi cloud api list</code> for browsing every
endpoint exposed by the Pulumi
Cloud OpenAPI spec, with table and JSON output</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22769">#22769</a></p>
</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>[engine] Revert changes to property path parsing that resulted in
errors for currently valid paths</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="e802ef2c5b"><code>e802ef2</code></a>
Revert &quot;Tighten parsing on new property paths (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22695">#22695</a>)&quot;
(<a
href="https://redirect.github.com/pulumi/pulumi/issues/22801">#22801</a>)</li>
<li><a
href="f5deaa1b20"><code>f5deaa1</code></a>
cli/cloud: add <code>pulumi cloud api describe</code> (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22770">#22770</a>)</li>
<li><a
href="bccf53d1fb"><code>bccf53d</code></a>
cli/cloud: add <code>pulumi cloud api list</code> (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22769">#22769</a>)</li>
<li><a
href="5575172e07"><code>5575172</code></a>
Changelog and go.mod updates for v3.233.0 (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22795">#22795</a>)</li>
<li><a
href="caf13d6d14"><code>caf13d6</code></a>
Cancel in-flight fuzz iterations when the 20s cap fires (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22725">#22725</a>)</li>
<li><a
href="324811c0a7"><code>324811c</code></a>
Freeze v2.233.0 (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22793">#22793</a>)</li>
<li>See full diff in <a
href="https://github.com/pulumi/pulumi/compare/v3.233.0...v3.234.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/pulumi/pulumi/sdk/v3&package-manager=go_modules&previous-version=3.233.0&new-version=3.234.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-04 06:12:32 -04:00
dependabot[bot]
648da259b0
build(deps): bump github.com/caarlos0/env/v11 from 11.4.0 to 11.4.1 (#1236)
Bumps [github.com/caarlos0/env/v11](https://github.com/caarlos0/env)
from 11.4.0 to 11.4.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/caarlos0/env/releases">github.com/caarlos0/env/v11's
releases</a>.</em></p>
<blockquote>
<h2>v11.4.1</h2>
<h2>Changelog</h2>
<h3>Bug fixes</h3>
<ul>
<li>6daeb06ac7e3c9532a7eaa5768d45917393b7480: fix: use Key instead of
OwnKey in rawEnvVars to properly reference existing defaults in complex
structs (<a
href="https://redirect.github.com/caarlos0/env/issues/412">#412</a>) (<a
href="https://github.com/AndrewChubatiuk"><code>@​AndrewChubatiuk</code></a>)</li>
</ul>
<h3>Documentation updates</h3>
<ul>
<li>1ff55e6c9733833ce75d62b345916a407dbe4158: docs: adaptive starchart
(<a href="https://redirect.github.com/caarlos0/env/issues/416">#416</a>)
(<a
href="https://github.com/alexandear"><code>@​alexandear</code></a>)</li>
</ul>
<h3>Other work</h3>
<ul>
<li>cf4a9682420b025e44b4773fd7ee0be48bb68b2f: ci(deps): bump the actions
group with 3 updates (<a
href="https://redirect.github.com/caarlos0/env/issues/411">#411</a>) (<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot])</li>
<li>33faf6f333c2c3dacef2991825f8e03960a2c0cb: ci(deps): bump the actions
group with 3 updates (<a
href="https://redirect.github.com/caarlos0/env/issues/417">#417</a>) (<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot])</li>
<li>0cb635b62488f4d310809a82a8832cedc9aa94eb: ci(deps): bump the actions
group with 6 updates (<a
href="https://redirect.github.com/caarlos0/env/issues/415">#415</a>) (<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot])</li>
<li>a72d89a8930fc800372a6a338a1acf33e5cc3a56: ci: update release config
(<a href="https://github.com/caarlos0"><code>@​caarlos0</code></a>)</li>
</ul>
<hr />
<p><em>Released with <a href="https://goreleaser.com/pro">GoReleaser
Pro</a>!</em></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a72d89a893"><code>a72d89a</code></a>
ci: update release config</li>
<li><a
href="6daeb06ac7"><code>6daeb06</code></a>
fix: use Key instead of OwnKey in rawEnvVars to properly reference
existing d...</li>
<li><a
href="33faf6f333"><code>33faf6f</code></a>
ci(deps): bump the actions group with 3 updates (<a
href="https://redirect.github.com/caarlos0/env/issues/417">#417</a>)</li>
<li><a
href="1ff55e6c97"><code>1ff55e6</code></a>
docs: adaptive starchart (<a
href="https://redirect.github.com/caarlos0/env/issues/416">#416</a>)</li>
<li><a
href="0cb635b624"><code>0cb635b</code></a>
ci(deps): bump the actions group with 6 updates (<a
href="https://redirect.github.com/caarlos0/env/issues/415">#415</a>)</li>
<li><a
href="cf4a968242"><code>cf4a968</code></a>
ci(deps): bump the actions group with 3 updates (<a
href="https://redirect.github.com/caarlos0/env/issues/411">#411</a>)</li>
<li>See full diff in <a
href="https://github.com/caarlos0/env/compare/v11.4.0...v11.4.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/caarlos0/env/v11&package-manager=go_modules&previous-version=11.4.0&new-version=11.4.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-04 06:12:19 -04:00
dependabot[bot]
23f4fda297
build(deps): bump github.com/pulumi/pulumi/sdk/v3 from 3.232.0 to 3.233.0 in /deploy (#1234)
Bumps
[github.com/pulumi/pulumi/sdk/v3](https://github.com/pulumi/pulumi) from
3.232.0 to 3.233.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/releases">github.com/pulumi/pulumi/sdk/v3's
releases</a>.</em></p>
<blockquote>
<h2>v3.233.0</h2>
<h2>3.233.0 (2026-04-30)</h2>
<h3>Features</h3>
<ul>
<li>
<p>[auto/python] Expose the auto-generated Pulumi CLI interface as
<code>workspace.cli_api</code>
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22638">#22638</a></p>
</li>
<li>
<p>[cli] Add encrypted logging to ~/.pulumi/logs; use the
PULUMI_ENABLE_AUTOMATIC_LOGGING feature flag to turn it on
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22494">#22494</a></p>
</li>
<li>
<p>[cli] Implement the <code>filesystem__grep</code> and
<code>filesystem__content_replace</code> local tools
for <code>pulumi neo</code>. <code>grep</code> runs a regex search
across files in the project root
with an optional <code>include</code> glob filter and returns results in
<code>path:lineno: line</code>
form. <code>content_replace</code> performs a literal multi-file
search-and-replace with a
<code>file_pattern</code> glob and <code>dry_run</code> preview mode.
Both tools skip binary files,
hidden directories, and <code>node_modules</code>, and reject paths
outside the project
root. Their input schemas match the cloud-side tool definitions.</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22655">#22655</a></p>
</li>
<li>
<p>[cli] Add <code>pulumi_preview</code> and <code>pulumi_up</code> as
local tools for the experimental <code>pulumi neo</code>
agent. The Neo TUI renders a persistent bordered block for each
operation that
streams changed resources and diagnostics as the engine runs and
finalizes with a
summary of the op counts. Hidden behind PULUMI_EXPERIMENTAL.</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22697">#22697</a></p>
</li>
<li>
<p>[engine] Add <code>List</code> to the provider protocol and schema
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22693">#22693</a></p>
</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>
<p>[engine] Return a clear error when two installed plugins claim the
same default provider package name (for example, a native
<code>scaleway</code> provider alongside a
<code>terraform-provider</code> bridge parameterized as
<code>scaleway</code>) instead of panicking with &quot;Should not have
seen an older plugin if sorting is correct!&quot;
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22679">#22679</a></p>
</li>
<li>
<p>[programgen] Do not wrap a <code>call(...)</code> on a method whose
return type is marked plain in an Output. Previously
PCL bound every method call's return type as
<code>Output&lt;T&gt;</code>, which caused downstream program-gen
to emit broken <code>.apply(...)</code>/<code>.ApplyT(...)</code>
traversals against plain struct returns (e.g.
methods with <code>liftSingleValueMethodReturns=true</code> or
<code>ReturnTypePlain=true</code>).</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22696">#22696</a></p>
</li>
<li>
<p>[backend/diy] When using a backend url containing creds (e.g.
PostgreSQL conn string), mask user:pass as in lock-related error
messages
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22701">#22701</a></p>
</li>
<li>
<p>[codegen/go] Generate unqualified <code>Provider</code> references
for the package's own provider resource. Previously
the Go codegen always emitted <code>&lt;pkg&gt;.Provider</code> even
when the reference appeared inside <code>&lt;pkg&gt;</code></p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/blob/master/CHANGELOG.md">github.com/pulumi/pulumi/sdk/v3's
changelog</a>.</em></p>
<blockquote>
<h2>3.233.0 (2026-04-30)</h2>
<h3>Features</h3>
<ul>
<li>
<p>[auto/python] Expose the auto-generated Pulumi CLI interface as
<code>workspace.cli_api</code>
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22638">#22638</a></p>
</li>
<li>
<p>[cli] Add encrypted logging to ~/.pulumi/logs; use the
PULUMI_ENABLE_AUTOMATIC_LOGGING feature flag to turn it on
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22494">#22494</a></p>
</li>
<li>
<p>[cli] Implement the <code>filesystem__grep</code> and
<code>filesystem__content_replace</code> local tools
for <code>pulumi neo</code>. <code>grep</code> runs a regex search
across files in the project root
with an optional <code>include</code> glob filter and returns results in
<code>path:lineno: line</code>
form. <code>content_replace</code> performs a literal multi-file
search-and-replace with a
<code>file_pattern</code> glob and <code>dry_run</code> preview mode.
Both tools skip binary files,
hidden directories, and <code>node_modules</code>, and reject paths
outside the project
root. Their input schemas match the cloud-side tool definitions.</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22655">#22655</a></p>
</li>
<li>
<p>[cli] Add <code>pulumi_preview</code> and <code>pulumi_up</code> as
local tools for the experimental <code>pulumi neo</code>
agent. The Neo TUI renders a persistent bordered block for each
operation that
streams changed resources and diagnostics as the engine runs and
finalizes with a
summary of the op counts. Hidden behind PULUMI_EXPERIMENTAL.</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22697">#22697</a></p>
</li>
<li>
<p>[engine] Add <code>List</code> to the provider protocol and schema
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22693">#22693</a></p>
</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>
<p>[engine] Return a clear error when two installed plugins claim the
same default provider package name (for example, a native
<code>scaleway</code> provider alongside a
<code>terraform-provider</code> bridge parameterized as
<code>scaleway</code>) instead of panicking with &quot;Should not have
seen an older plugin if sorting is correct!&quot;
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22679">#22679</a></p>
</li>
<li>
<p>[programgen] Do not wrap a <code>call(...)</code> on a method whose
return type is marked plain in an Output. Previously
PCL bound every method call's return type as
<code>Output&lt;T&gt;</code>, which caused downstream program-gen
to emit broken <code>.apply(...)</code>/<code>.ApplyT(...)</code>
traversals against plain struct returns (e.g.
methods with <code>liftSingleValueMethodReturns=true</code> or
<code>ReturnTypePlain=true</code>).</p>
<p><a
href="https://redirect.github.com/pulumi/pulumi/pull/22696">#22696</a></p>
</li>
<li>
<p>[backend/diy] When using a backend url containing creds (e.g.
PostgreSQL conn string), mask user:pass as in lock-related error
messages
<a
href="https://redirect.github.com/pulumi/pulumi/pull/22701">#22701</a></p>
</li>
<li>
<p>[codegen/go] Generate unqualified <code>Provider</code> references
for the package's own provider resource. Previously
the Go codegen always emitted <code>&lt;pkg&gt;.Provider</code> even
when the reference appeared inside <code>&lt;pkg&gt;</code>
itself, producing identifiers that would not compile. Affects generated
code for method return</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fa313013d0"><code>fa31301</code></a>
don't stamp vcs information into binaries (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22788">#22788</a>)</li>
<li><a
href="17fd40453d"><code>17fd404</code></a>
double timeout in &quot;does not hang&quot; test (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22789">#22789</a>)</li>
<li><a
href="eb6e31d841"><code>eb6e31d</code></a>
split tests module on macos further (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22790">#22790</a>)</li>
<li><a
href="94dbe6401b"><code>94dbe64</code></a>
Remove runInStack from run-policy-pack (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22783">#22783</a>)</li>
<li><a
href="a35ec7e9d5"><code>a35ec7e</code></a>
retry pip install a few times (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22785">#22785</a>)</li>
<li><a
href="7a4beeaa44"><code>7a4beea</code></a>
Reject schemas with duplicate tokens after applying
<code>moduleFormat</code> (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22765">#22765</a>)</li>
<li><a
href="0b914cee46"><code>0b914ce</code></a>
unflake TestNodejsComponentProviderRun (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22782">#22782</a>)</li>
<li><a
href="5cd1646706"><code>5cd1646</code></a>
start logging encrypted logs for all pulumi commands (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22494">#22494</a>)</li>
<li><a
href="a81ef07c09"><code>a81ef07</code></a>
pin more plugin versions in integration tests (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22758">#22758</a>)</li>
<li><a
href="0d2b8bf114"><code>0d2b8bf</code></a>
Update list doc comment (<a
href="https://redirect.github.com/pulumi/pulumi/issues/22777">#22777</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pulumi/pulumi/compare/v3.232.0...v3.233.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/pulumi/pulumi/sdk/v3&package-manager=go_modules&previous-version=3.232.0&new-version=3.233.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-01 03:19:42 -04:00
dependabot[bot]
46bbe0dba3
build(deps): bump cloud.google.com/go/kms from 1.29.0 to 1.30.0 (#1233)
Bumps
[cloud.google.com/go/kms](https://github.com/googleapis/google-cloud-go)
from 1.29.0 to 1.30.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-cloud-go/releases">cloud.google.com/go/kms's
releases</a>.</em></p>
<blockquote>
<h2>kms: v1.30.0</h2>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/kms/v1.29.0...kms/v1.30.0">v1.30.0</a>
(2026-04-30)</h2>
<h2>retail: v1.30.0</h2>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/retail/v1.29.0...retail/v1.30.0">v1.30.0</a>
(2026-04-30)</h2>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md">cloud.google.com/go/kms's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/googleapis/google-cloud-go/compare/documentai/v1.29.0...documentai/v1.30.0">1.30.0</a>
(2024-06-05)</h2>
<h3>Features</h3>
<ul>
<li><strong>documentai:</strong> Make Layout Parser generally available
in V1 (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/10286">#10286</a>)
(<a
href="92dc381da2">92dc381</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="54d941a9a3"><code>54d941a</code></a>
chore: librarian release pull request: 20260402T153541Z (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14330">#14330</a>)</li>
<li><a
href="22d0749f8f"><code>22d0749</code></a>
docs(storage): Update <code>EnableParallelUpload</code> documentation
(<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14328">#14328</a>)</li>
<li><a
href="751febd843"><code>751febd</code></a>
feat(spanner): Switch to using builtin open telemetry for EEF (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14193">#14193</a>)</li>
<li><a
href="a70f04f178"><code>a70f04f</code></a>
chore: add a config check (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14327">#14327</a>)</li>
<li><a
href="9e2b3f5700"><code>9e2b3f5</code></a>
chore: update sources and regenerate (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14325">#14325</a>)</li>
<li><a
href="e0760b51f4"><code>e0760b5</code></a>
fix(spanner): set gauge metric start time to match end time (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14289">#14289</a>)</li>
<li><a
href="71df27f882"><code>71df27f</code></a>
docs(pubsub/v2): revamp package docs (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14317">#14317</a>)</li>
<li><a
href="a6efdbfd6c"><code>a6efdbf</code></a>
chore: update librarian version (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14323">#14323</a>)</li>
<li><a
href="22cda56edd"><code>22cda56</code></a>
chore: update librariangen image SHA (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14315">#14315</a>)</li>
<li><a
href="1720392ade"><code>1720392</code></a>
chore(all): update deps (main) (<a
href="https://redirect.github.com/googleapis/google-cloud-go/issues/14231">#14231</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/googleapis/google-cloud-go/compare/kms/v1.29.0...dlp/v1.30.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cloud.google.com/go/kms&package-manager=go_modules&previous-version=1.29.0&new-version=1.30.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-01 03:19:24 -04:00
Radoslav Dimitrov
42092742ce
deploy: update prod to v1.7.6 (#1232)
## Summary

- Bumps prod imageTag from \`1.7.5\` to \`1.7.6\`.

## Test plan

- [ ] Smoke staging at https://staging.registry.modelcontextprotocol.io
- [ ] Roll out via Pulumi
- [ ] Confirm prod health post-rollout: \`curl
https://registry.modelcontextprotocol.io/v0/version\` shows \`1.7.6\`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:08:54 -04:00
Radoslav Dimitrov
db43896209
docs: document GitHub OIDC audience binding for self-hosters and CI users (#1230) v1.7.6
## Summary

Follow-up to #1229. Three small doc additions so the new audience
requirement is discoverable without reading the source:

- `.env.example` lists `MCP_REGISTRY_GITHUB_OIDC_AUDIENCE` alongside the
other registry env vars, with a note that the value must match the
scheme+host that publishers pass via `--registry`.
- The publisher CLI reference (`docs/reference/cli/commands.md`)
explains that the CLI derives the audience from `--registry` and that
self-hosters must set the matching env var on the registry side.
- The GitHub Actions troubleshooting table
(`docs/modelcontextprotocol-io/github-actions.mdx`) maps the new
`invalid audience` error to the user-facing fix (upgrade
`mcp-publisher`).

No code changes — docs only.

## Test plan

- [ ] CI green (markdown lint / link checks if any)
- [ ] Eyeball-render the troubleshooting table on the
modelcontextprotocol.io preview to confirm the new row formats correctly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 20:56:53 -04:00
Radoslav Dimitrov
3f89fc2b1f
auth: bind GitHub OIDC token exchange to a per-deployment audience (#1229)
## What this does

The publisher CLI now derives the OIDC audience to request from the
`--registry` URL instead of using a fixed constant, and the server
validates the token's `aud` claim against a new per-deployment env var
(`MCP_REGISTRY_GITHUB_OIDC_AUDIENCE`).

Production sets this env var to
`https://registry.modelcontextprotocol.io` (and per-environment URL
elsewhere), so the deployment only accepts tokens that were requested
for it.

## Compatibility

This is a breaking change for older `mcp-publisher` binaries that still
request the legacy hardcoded audience. After this rolls to a deployment,
users on old `mcp-publisher` will see a clear `invalid audience:
expected …, got […]` error and need to upgrade. Users following the
documented `releases/latest` install pattern get the new binary
automatically.

## Test plan

- [ ] CI green
- [ ] Run a synthetic publish from a real GitHub Actions workflow
against staging after deploy
- [ ] Confirm an older `mcp-publisher` against the same staging deploy
returns the expected `invalid audience` error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 20:27:26 -04:00
Radoslav Dimitrov
88bbb851ad
deploy: update prod to v1.7.5 (#1228)
## Summary

- Bumps prod imageTag from `1.7.4` to `1.7.5`.
- Promotes the security release tagged at v1.7.5 (#1227 merged at
1201cbd).

## Test plan

- [ ] Smoke staging at https://staging.registry.modelcontextprotocol.io
— already done, all checks green
- [ ] Roll out via Pulumi
- [ ] Confirm prod health post-rollout: `curl
https://registry.modelcontextprotocol.io/v0/health`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 19:32:54 -04:00
Radoslav Dimitrov
1201cbd82b
security: fix open redirect and add small hardening (#1227) v1.7.5
## What this does

Fixes an open redirect plus a handful of small, mostly-invisible
hardening changes around it.

## What's in it

- **The fix**: trailing-slash redirects no longer let `//evil.com/`
redirect off-host.
- **SSRF block** on the DNS/HTTP namespace verification — refuses to
dial loopback, RFC1918, link-local, multicast, CGNAT, or
IP-literal/single-label \"domains\".
- **Slow-client guard**: `ReadTimeout` and `IdleTimeout` on the HTTP
server (no `WriteTimeout` — would risk cutting off legitimate
multi-package publishes).
- **Defence-in-depth headers** on the UI (`/`) and 404 responses.
- **5xx responses** stop leaking raw DB error text to clients (logged
server-side instead).
- **Search filter** stops treating `%` and `_` as wildcards.
- **Validators**: PyPI/NuGet identifiers URL-escaped before fetching;
MCPB no longer follows redirects.
- **Misc**: `Version` field bounded to 255 chars; logs quote user input;
`BlockedNamespaces` denylist now catches subdomain claimants.

Each change is its own commit so they can be reviewed (or reverted)
independently.

## Test plan

- [ ] CI green
- [ ] Synthetic publish in staging for each package type (npm, pypi,
nuget, oci, mcpb) — confirms validator changes don't regress
- [ ] Quick browser check of `/` after deploy to confirm UI still loads
with the new CSP
- [ ] `curl https://<host>//evil.com/` — confirm the open redirect is
closed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 19:14:00 -04:00
Radoslav Dimitrov
f7663fe91a
deploy: update prod to v1.7.4 (#1226)
## Summary

Promotes
[v1.7.4](https://github.com/modelcontextprotocol/registry/releases/tag/v1.7.4)
(#1225) to production: registry pod memory request `256Mi → 512Mi`,
limit `512Mi → 1Gi`.

## Why

#1221 doubled pgxpool `MaxConns` 30→60 per pod without bumping the
registry pod memory limit. pgxpool keeps per-connection state in the Go
process (prepared statement cache, scratch buffers, row iteration state)
so peak per-pod memory shifted from ~330 MB to ~450 MB against the 512
MiB limit. Pod `tx49f` was OOMKilled at 17:01 UTC on 2026-04-29.

## Validation so far

- Staging deployed cleanly via `deploy-staging.yml` after #1225 merged
- Both staging pods running with `req=512Mi limit=1Gi` ✓
- Rolling update was clean — no failed health checks during the
transition
- Both pods spread across nodes (q716 + 7exo)

## Deployment

**Zero downtime** — Deployment template change only, rolling update with
`maxSurge: 1, maxUnavailable: 0`. No PG involvement (no
`max_connections` change, no shared_preload_libraries change).

## Test plan

- [x] v1.7.4 release built and pushed
(`ghcr.io/modelcontextprotocol/registry:1.7.4`)
- [x] Staging deployed cleanly with new limits
- [ ] Prod Pulumi run applies cleanly; rolling update completes
- [ ] Prod pods come up with `req=512Mi limit=1Gi`
- [ ] After 24h: no OOMKills on either pod, peak memory stays under ~600
MB

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 14:43:18 -04:00
Radoslav Dimitrov
5dcae5b3ce
fix(deploy): bump registry pod memory to match doubled pgxpool size (#1225) v1.7.4
## Summary

Follow-up to #1221. That PR doubled pgxpool `MaxConns` from 30 to 60 per
pod without bumping the registry pod memory limit. pgxpool keeps
per-connection state in the Go process (prepared statement cache,
scratch buffers, row iteration state), so memory grew roughly
proportionally — peak per-pod usage shifted from ~330 MB to ~450 MB
against a 512 MiB limit.

## What surfaced it

Pod `tx49f` was OOMKilled at 17:01 UTC on 2026-04-29 (`exitCode 137`,
`reason: OOMKilled`). Memory history from Cloud Monitoring confirms the
regression:

| Pods | Peak 30-min memory |
|------|-------------------:|
| Pre-#1221 (`MaxConns=30`) | 178–333 MB |
| **Post-#1221** (`MaxConns=60`) | **437–449 MB** |
| Old limit | **512 MiB** ← right at the edge |

Other pod was at 394 MB at the time of inspection — could OOM again.

## Fix

`deploy/pkg/k8s/registry.go:217-225`:

| | Before | After |
|---|-------:|------:|
| `requests.memory` | 256 MiB | **512 MiB** |
| `limits.memory` | 512 MiB | **1 GiB** |

1 GiB is ~2× the current peak under load — gives room for traffic spikes
without immediate OOM risk. Either node has 4–5 GiB free allocatable
memory, so the new request fits comfortably.

## Test plan

- [x] `go build ./...` clean
- [x] `golangci-lint run` clean
- [ ] After release + prod promotion: pod memory stabilises around 450
MB peak with no OOMKills
- [ ] After release + prod promotion: tx49f restartCount stops climbing
(currently at 5)

## Deployment

Zero downtime — Deployment template change only, rolling update with
`maxSurge: 1, maxUnavailable: 0`. **No PG involvement** (no
`max_connections` change, no shared_preload_libraries change). Same
shape as a normal v1.7.x image promotion.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 14:05:09 -04:00
Radoslav Dimitrov
0a97e59ecb
deploy: update prod to v1.7.3 (#1223)
## Summary

Promotes
[v1.7.3](https://github.com/modelcontextprotocol/registry/releases/tag/v1.7.3)
to production. Contents:

- **#1220** — `RemoteURL` filter SQL rewritten to use JSONB containment
(`@>`) instead of `EXISTS jsonb_array_elements`. The new form is
GIN-indexable; the old form forced a full table scan. Local benchmark:
40,398 → 294 buffer reads, 17 ms → 1.6 ms. Maps to prod's 10,005 ms
cold-cache observation.
- **#1221** — pgxpool `MaxConns 30→60`, `MinConns 5→10`. PG
`max_connections 100→200`. Explicit PG `resources:` block (was unset).

## What this addresses

- **#1220**: yesterday's 17:08 UTC `Publish Endpoint Latency` alert
(`dev.storage/mcp` publish took 14.8s with `remotes_ms=10980` —
pinpointed by the per-phase slog from #1215).
- **#1221**: yesterday's 17:35–17:40 UTC `Availability dropped below
95%` alert and 18:17 UTC `Publish Endpoint Latency` re-fire. Both were
scraper-driven concurrency on `/v0/servers` (~15 req/s sustained from
ServiceNow + others). With the bumped pool, the queue at the Go HTTP
layer should clear faster instead of blowing up to 20–35s nginx-level
latencies.

## Deployment caveat

The PG `max_connections` change is a postmaster-level setting → CNPG
triggers a PG restart on the next prod Pulumi run. With `instances: 1`
this is brief downtime — staging took **~30s** during the equivalent
restart, with **one registry pod bouncing once** on its 8-attempt
DB-retry budget before recovering on the next kubelet restart.

**Time the merge for a low-traffic UTC window.** Alert history suggests
very early UTC (02:00–04:00) is quietest.

## Resource impact

PG node memory is currently 39% (~2.4 GiB / 6 GiB allocatable).
Worst-case PG memory growth with `max_connections=200` lands around 3–4
GiB, putting the node at ~65% — fits with headroom. Empirically, prod PG
has peaked at **413 MiB** in the last 30h of incident data, so the
proposed 4 GiB limit is ~10× the historical max — guardrail not
constraint.

## Post-merge

CNPG handles `pg_stat_statements` extension creation automatically (no
manual `CREATE EXTENSION` step needed — it was already done in v1.7.2's
deploy).

Verify after deploy:

```bash
PATH=/opt/homebrew/share/google-cloud-sdk/bin:$PATH

# max_connections actually changed
kubectl exec -i registry-pg-1 -c postgres \
  --context gke_mcp-registry-prod_us-central1-b_mcp-registry-prod \
  -- psql -U postgres -tAc "SHOW max_connections"  # expect: 200

# resources block applied
kubectl get pod registry-pg-1 \
  --context gke_mcp-registry-prod_us-central1-b_mcp-registry-prod \
  -o jsonpath='{.spec.containers[?(@.name=="postgres")].resources}{"\n"}'

# pgxpool MaxConns reflected (registry app uses 60 per pod after restart)
kubectl exec -i registry-pg-1 -c postgres \
  --context gke_mcp-registry-prod_us-central1-b_mcp-registry-prod \
  -- psql -U postgres -tAc "SELECT count(*) FROM pg_stat_activity WHERE datname='app'"
```

## Test plan

- [x] v1.7.3 release built and pushed
(`ghcr.io/modelcontextprotocol/registry:1.7.3`)
- [x] Staging deployed cleanly; PG restarted and came back with
`max_connections=200`; one staging pod bounced as expected
- [ ] Prod Pulumi run applies cleanly; brief PG restart
- [ ] Confirm `SHOW max_connections` returns 200 on prod
- [ ] Confirm `publish complete` events show `remotes_ms` < 10ms
- [ ] Watch for any "too many connections" errors during the rollout
window (none expected — Pulumi orders CNPG cluster before Deployment, so
PG accepts the new conn limit before pgxpool tries to use it)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 17:50:38 -04:00
Radoslav Dimitrov
736d376858
fix(db): raise pgxpool MaxConns + PG max_connections + set PG resources (#1221) v1.7.3
## Summary

Follow-up to #1215 and #1220. Both of those addressed *individual* slow
queries; this PR addresses *concurrency* — under today's scraper load
the cursor query is fast on average (mean 42ms) but the connection pool
saturates and queue depth blows up at the Go HTTP layer.

## Diagnosis

`pg_stat_statements` (added in #1215) made this possible to see:

```
max_ms   mean_ms  calls    template
10,755     41.8   94,009   plain cursor pagination, no filter
 7,277    214.7   14,770   ILIKE substring filter
 7,638    330.8    7,656   ILIKE substring + is_latest filter
```

Mean times are healthy. But `max_exec_time` of 7–10s on the cursor
query, combined with sustained ~15 req/s from scrapers (ServiceNow's
148.139.x.x range, anonymous `node` user-agent, etc) saturates
`MaxConns=30 × 2 pods = 60`. New requests queue at the Go HTTP layer;
nginx-side p99 hits 35s; eventually scrapers time out at 60s, retry, and
amplify the queue.

Today's two ongoing alerts are both this pattern:
- 17:35–17:40 UTC `Availability dropped below 95%` — 4,526 GET requests
in 5 min, hundreds of 504s
- 18:17 UTC `Publish Endpoint Latency` re-fire — same scraper
concurrency dragging the publish path

Critically, the symptoms today were also visible during yesterday's
incident, but yesterday's broken cursor (#1215) was the dominant cause.
After #1215 the cursor is fast individually; concurrency now becomes the
next bottleneck.

## Changes

### pgxpool (`internal/database/postgres.go`)

| Setting | Before | After |
|---------|-------:|------:|
| `MaxConns` | 30 | **60** per pod |
| `MinConns` | 5 | **10** per pod |
| `MaxConnIdleTime` | 30 min | (unchanged) |
| `MaxConnLifetime` | 2 h | (unchanged) |

2 pods × 60 = 120 total app connections. Cuts queue depth roughly in
half at current scraper load.

### PG cluster (`deploy/pkg/k8s/postgres.go`)

- `max_connections: 100 → 200` — required to support the larger pool.
120 (app) + ~10 (PG internals: autovacuum, replication, admin) + 70
headroom.
- Added explicit `resources:` block — previously the pod had no resource
limits, making node-level OOM behaviour unpredictable.

| | Request | Limit |
|---|--------:|------:|
| memory | 512Mi | **4Gi** |
| cpu | 200m | 1500m |

## Resource budget

| Node | Now | After |
|------|----:|------:|
| dy89 (PG node) | 39% mem (~2.4 GiB / 6 GiB) | ~65% mem worst-case
(~3.9 GiB) |
| 2yxm | 36% mem | unchanged |

Both nodes well within capacity. CPU usage <50% on both, plenty of
headroom.

PG worst-case memory math:
- 200 conns × ~15 MB per backend = 3 GiB
- + `shared_buffers` 128 MiB
- + `maintenance_work_mem`, OS overhead, etc.
- ≈ 3–4 GiB total

## Deployment caveat

`max_connections` is a postmaster-level setting → CNPG triggers a PG
restart on the change. Same in-pod restart shape as the
pg_stat_statements deploy yesterday — registry pods see ~30s of DB
unavailability, covered by v1.7.1's retry-with-backoff (8 attempts, 1→8s
capped). One registry pod may bounce once before recovering, like
yesterday.

**Time the merge for a low-traffic UTC window.**

Order of operations matters within the deploy itself:
1. Pulumi applies the new CNPG spec → PG restarts with
`max_connections=200`
2. Rolling deploy of registry pods picks up `MaxConns=60` config
3. New conns are accepted up to 200 limit

Pulumi's standard ordering does step 1 before step 2 in this scenario
(Pulumi resource graph: CNPG cluster precedes Deployment). If for any
reason it doesn't, the worst case is `too many connections` errors
during a small window — Self-correcting once the rollout completes.

## Test plan

- [x] `go build ./...` clean for app + deploy
- [x] `make lint` clean
- [x] `go test -race ./internal/database/...` green
- [ ] On merge: staging deploy applies the spec change cleanly; PG
restarts; pool reaches 60 max
- [ ] On prod deploy: same; verify no `too many connections` errors
during the rollout window
- [ ] After deploy: query `SHOW max_connections` returns 200; query
pg_stat_statements after a scraper burst, confirm `max_exec_time` for
cursor query no longer hits 10s

## Out of scope

- **ILIKE substring search** (`server_name ILIKE '%foo%'`) is
unindexable. Three pg_stat_statements variants run with means 141–333ms
and max 4–7s. Worth replacing with a `pg_trgm` GIN index or full-text
search in a separate PR.
- **Per-IP nginx rate limiting** — defends against scraper retry storms
regardless of pool size.
- **`Cache-Control` on `/v0/servers`** — let nginx absorb
scraper-repeated cursors.
- **Pre-existing `superfluous WriteHeader` warnings** — separate Huma
framework issue.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 15:21:24 -04:00
Radoslav Dimitrov
54cbe2473c
fix(list): use JSONB containment for RemoteURL filter (GIN-indexable) (#1220)
## Summary

Same shape of bug as #1215's cursor fix, different filter. The RemoteURL
filter built its WHERE predicate using `jsonb_array_elements` + `->>`
extraction, which the planner can't translate into a GIN search.
Replaced with a JSONB containment predicate `@>` that uses
`idx_servers_json_remotes`.

## Diagnosis (from the per-phase publish slog #1215 added)

Today's first publish-latency alert at 17:08 UTC pointed straight at
this:

```
publish complete server_name=dev.storage/mcp version=1.10.1 total_ms=14822
  validate_ms=0 lock_ms=238 remotes_ms=10980 version_checks_ms=535 unmark_ms=3014 create_ms=53
```

`remotes_ms=10,980` on a server with **one** remote URL pointed at
`validateNoDuplicateRemoteURLs`, which runs the RemoteURL filter against
the database. EXPLAIN ANALYZE on prod confirmed:

```
Filter: (status != 'deleted') AND EXISTS(SubPlan 1)
Rows Removed by Filter: 21,092       ← scans the whole table
Buffers: shared hit=20,028
Execution Time: 10,005 ms
```

## Fix

`internal/database/postgres.go:99` rewritten:

```sql
-- before  (planner can't use GIN index for this)
EXISTS (SELECT 1 FROM jsonb_array_elements(value->'remotes') AS remote
        WHERE remote->>'url' = $1)

-- after   (GIN-indexable)
value -> 'remotes' @> jsonb_build_array(jsonb_build_object('url', $1::text))
```

Semantically equivalent for our schema (`url` is always a string, NOT
NULL).

## Local benchmark — 20K rows, prod-shaped JSONB (~1KB/row)

| Form | Buffer hits | Index used | Time |
|------|------------:|------------|-----:|
| OLD | 40,398 | none — full scan | 17.0 ms |
| NEW | **294** | **`idx_servers_json_remotes` GIN bitmap** | **1.6 ms**
|

Maps to prod's 10,005 ms cold-cache observation — same shape of speedup
we got from the cursor fix.

## Scope honesty

This PR addresses the **publish slowness path**
(`validateNoDuplicateRemoteURLs` in the publish transaction). It
directly resolves today's 17:08 UTC `Publish Endpoint Latency` alert.

It does **not** address:

- Today's 17:35–17:40 UTC `Availability dropped below 95%` alert.
Per-investigation: only 4 publishes happened in the entire 17:00–17:50
window and zero during the burst minutes — so my initial "concurrent
slow publishes starved the pool" hypothesis was wrong. The actual cause
was scraper-driven concurrency (4,500+ requests in 5 min) on plain
cursor pagination + ILIKE substring search, where individual queries are
fast (mean 42 ms) but tail latency under concurrency reaches 10 s
server-side and 20–35 s nginx-level due to pool queueing.
- The 18:17 UTC `Publish Endpoint Latency` re-fire (same scraper-driven
concurrency).

A follow-up PR will raise pool size + PG `max_connections` + add
explicit PG resource limits to absorb concurrency without queue blowup.
That fix has a different shape (config) and a different risk profile (PG
restart for `max_connections`); kept separate so this surgical SQL
change can ship cleanly.

## Test plan

- [x] `go build ./...` clean
- [x] `make lint` clean
- [x] `go test -race ./internal/database/... ./internal/service/...`
green — existing `TestPostgreSQL_ListServers/filter by remote URL`
covers semantic correctness
- [x] EXPLAIN ANALYZE comparison locally on 20K rows + prod-shaped JSONB
- [ ] After merge + deploy: verify on prod via `EXPLAIN ANALYZE`;
confirm `remotes_ms` in `publish complete` slog drops to single-digit ms

## Out of scope (separate follow-ups)

- pgxpool `MaxConns` / `MinConns` bump + PG `max_connections` raise + PG
`resources` limits — addresses the cursor-tail and ILIKE-search
concurrency that this PR doesn't touch
- Per-IP rate limiting at nginx — defends against scraper retry storms
regardless of query speed
- `Cache-Control` headers on `/v0/servers` — let nginx absorb scraper
repeats
- Pre-existing `superfluous WriteHeader` warnings — separate Huma
framework issue
- ILIKE substring search on `server_name` is unindexable — could be
replaced with `pg_trgm` GIN index or full-text search

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 15:03:21 -04:00
dependabot[bot]
a490b6f1ec
build(deps): bump goreleaser/goreleaser-action from 7.1.0 to 7.2.1 in the actions group (#1218)
Bumps the actions group with 1 update:
[goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action).

Updates `goreleaser/goreleaser-action` from 7.1.0 to 7.2.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/goreleaser/goreleaser-action/releases">goreleaser/goreleaser-action's
releases</a>.</em></p>
<blockquote>
<h2>v7.2.1</h2>
<p>This fully removes the usage of the old <code>nightly</code> moving
tag.</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/goreleaser/goreleaser-action/compare/v7.2.0...v7.2.1">https://github.com/goreleaser/goreleaser-action/compare/v7.2.0...v7.2.1</a></p>
<h2>v7.2.0</h2>
<h2>What's Changed</h2>
<ul>
<li>test: cover install across release eras by <a
href="https://github.com/caarlos0"><code>@​caarlos0</code></a> in <a
href="https://redirect.github.com/goreleaser/goreleaser-action/pull/555">goreleaser/goreleaser-action#555</a></li>
<li>feat: add <code>version-file</code> input by <a
href="https://github.com/caarlos0"><code>@​caarlos0</code></a> in <a
href="https://redirect.github.com/goreleaser/goreleaser-action/pull/556">goreleaser/goreleaser-action#556</a></li>
<li>feat: resolve nightly to latest vX.Y.Z-<!-- raw HTML omitted
-->-nightly release by <a
href="https://github.com/caarlos0"><code>@​caarlos0</code></a> in <a
href="https://redirect.github.com/goreleaser/goreleaser-action/pull/558">goreleaser/goreleaser-action#558</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/goreleaser/goreleaser-action/compare/v7...v7.2.0">https://github.com/goreleaser/goreleaser-action/compare/v7...v7.2.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="1a80836c5c"><code>1a80836</code></a>
ci(nightly): pass GITHUB_TOKEN to nightly integration job</li>
<li><a
href="a71152e827"><code>a71152e</code></a>
refactor: drop legacy 'nightly' tag fallback</li>
<li><a
href="4c6ab561ad"><code>4c6ab56</code></a>
feat: resolve nightly to latest vX.Y.Z-&lt;sha&gt;-nightly release (<a
href="https://redirect.github.com/goreleaser/goreleaser-action/issues/558">#558</a>)</li>
<li><a
href="4f96abf297"><code>4f96abf</code></a>
feat: add <code>version-file</code> input (<a
href="https://redirect.github.com/goreleaser/goreleaser-action/issues/556">#556</a>)</li>
<li><a
href="15fa2a96d4"><code>15fa2a9</code></a>
test: cover install across release eras (<a
href="https://redirect.github.com/goreleaser/goreleaser-action/issues/555">#555</a>)</li>
<li>See full diff in <a
href="e24998b8b6...1a80836c5c">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=goreleaser/goreleaser-action&package-manager=github_actions&previous-version=7.1.0&new-version=7.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-28 03:23:31 -04:00
dependabot[bot]
3764acad40
build(deps): bump github.com/pulumi/pulumi-kubernetes/sdk/v4 from 4.29.0 to 4.30.0 in /deploy (#1217)
Bumps
[github.com/pulumi/pulumi-kubernetes/sdk/v4](https://github.com/pulumi/pulumi-kubernetes)
from 4.29.0 to 4.30.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi-kubernetes/releases">github.com/pulumi/pulumi-kubernetes/sdk/v4's
releases</a>.</em></p>
<blockquote>
<h2>v4.30.0</h2>
<p>No release notes provided.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi-kubernetes/blob/master/CHANGELOG.md">github.com/pulumi/pulumi-kubernetes/sdk/v4's
changelog</a>.</em></p>
<blockquote>
<h2>4.30.0 (April 24, 2026)</h2>
<h3>Fixed</h3>
<ul>
<li><a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/pull/4295">#4295</a>Fix
kustomize.v2.Directory resource output type in the schema to properly
support array outputs.
Previously, the resources field was incorrectly typed as a
<code>string</code> in the schema. This fix updates the type to an array
of <code>Any</code>, aligning the schema with the provider's Go
implementation (<code>pulumi.ArrayOutput</code>). This resolves a
regression that caused the Kustomize v2 resource to fail in the Python
SDK.</li>
<li><a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/2997">#2997</a>
Stop stripping null values when unmarshaling, fixing Helm chart default
deletion and <code>valueYamlFiles</code> null handling. Deprecate
<code>allowNullValues</code> (no longer needed).</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Upgrade Kubernetes schema and libraries to v1.35.4.</li>
<li>Upgrade Kubernetes schema and libraries to v1.36.0.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="55e3b2da39"><code>55e3b2d</code></a>
Automated upgrade: bump Kubernetes to v1.36.0 (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4304">#4304</a>)</li>
<li><a
href="437be67502"><code>437be67</code></a>
Update GitHub Actions workflows. (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4308">#4308</a>)</li>
<li><a
href="7e10bf37ae"><code>7e10bf3</code></a>
Don't skip nulls when unmarshaling (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4293">#4293</a>)</li>
<li><a
href="f4379df5a8"><code>f4379df</code></a>
Update GitHub Actions workflows. (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4301">#4301</a>)</li>
<li><a
href="da7a987493"><code>da7a987</code></a>
Update GitHub Actions workflows. (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4297">#4297</a>)</li>
<li><a
href="d1122d16e5"><code>d1122d1</code></a>
fix: correct <code>kustomize.v2.Directory</code> schema types to fix
Python SDK (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4295">#4295</a>)</li>
<li><a
href="ec3b5cbc20"><code>ec3b5cb</code></a>
Automated upgrade: bump Kubernetes to v1.35.4 (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4286">#4286</a>)</li>
<li><a
href="779d4c8247"><code>779d4c8</code></a>
Update GitHub Actions workflows. (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4294">#4294</a>)</li>
<li><a
href="fcfebd1805"><code>fcfebd1</code></a>
Update GitHub Actions workflows. (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4292">#4292</a>)</li>
<li><a
href="8b5816794b"><code>8b58167</code></a>
Update GitHub Actions workflows. (<a
href="https://redirect.github.com/pulumi/pulumi-kubernetes/issues/4291">#4291</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pulumi/pulumi-kubernetes/compare/v4.29.0...v4.30.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/pulumi/pulumi-kubernetes/sdk/v4&package-manager=go_modules&previous-version=4.29.0&new-version=4.30.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-28 03:23:14 -04:00
Radoslav Dimitrov
a4d9d82920
deploy: update prod to v1.7.2 (#1216)
## Summary

Promotes
[v1.7.2](https://github.com/modelcontextprotocol/registry/releases/tag/v1.7.2)
(PR #1215) to production:

- **Row-constructor cursor pagination** — fixes the 760ms list query
that was the root cause of today's pool-exhaustion alerts. Local
benchmark shows /v0/servers paginated requests dropping from ~30ms (cold
cache, 100K rows) to ~0.05ms.
- **Per-phase publish slog** — `publish complete` events now include
validate / lock / remotes / version_checks / unmark / db_create timings
so the next slow publish is self-diagnostic.
- **pg_stat_statements** — aggregate query visibility we didn't have
during today's incident.

## Deployment caveat

The CNPG cluster spec change for `pg_stat_statements` triggers an in-pod
postgres restart on the next prod Pulumi run. Staging took **~45–70s of
registry unavailability** during the equivalent restart. The DB
retry-with-backoff in v1.7.1 covers most of it, but registry pods may
bounce once before they reconnect (one staging pod hit `Failed to
connect after 8 attempts` then recovered on its next restart).

**Time the merge for a low-traffic UTC window** — the alert history
suggests very early UTC is quietest.

## Post-merge action

Once the prod Pulumi run completes, run once on the existing cluster:

```bash
PATH=/opt/homebrew/share/google-cloud-sdk/bin:$PATH
kubectl exec -i registry-pg-1 -c postgres \
  --context gke_mcp-registry-prod_us-central1-b_mcp-registry-prod \
  -- psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements"
```

Verify:

```bash
kubectl exec -i registry-pg-1 -c postgres \
  --context gke_mcp-registry-prod_us-central1-b_mcp-registry-prod \
  -- psql -U postgres -d app -c "
    SELECT round(mean_exec_time::numeric, 2) AS mean_ms, calls,
           substring(query, 1, 80) AS q
    FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10;"
```

## Test plan

- [x] v1.7.2 release built and pushed
(`ghcr.io/modelcontextprotocol/registry:1.7.2`)
- [x] Staging deployed cleanly; `pg_stat_statements` is collecting on
staging
- [ ] Prod Pulumi run applies cleanly; brief PG restart
- [ ] Run `CREATE EXTENSION` on prod
- [ ] Confirm `publish complete` events contain per-phase timings on the
next publish

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 15:58:11 -04:00
Radoslav Dimitrov
27af672c5e
fix(list): use row-constructor cursor + restore per-phase publish timings + enable pg_stat_statements (#1215) v1.7.2
## Summary

Three changes from the 2026-04-27 incident:

1. **Cursor SQL fix** — `addCursorCondition` rewritten to use a
row-constructor comparison `(server_name, version) > ($1, $2)` instead
of the OR-decomposed form. Postgres can index-seek on the row
constructor; it can't on the OR form, which scanned from the start of
the index and filtered rows before the cursor. Cost grew linearly with
cursor depth.
2. **Per-phase publish timings restored** — `createServerInTransaction`
was simplified during #1211 review to log only `validate_ms`. The
incident showed publishes spending 50+ s in `acquire_lock` /
`version_checks` / `db_create` while `validate_ms` reported a few
hundred ms — the diagnostic signal was hidden. Restored timings for
every phase, refactored into a small `runPhase` helper.
3. **`pg_stat_statements` enabled** in the CNPG cluster spec. We had no
aggregate query visibility during the incident — could only EXPLAIN
queries we happened to suspect.

## Cursor fix evidence

Local benchmark, 100K rows, cold cache:

| Form | Rows filtered | Buffer reads | Time |
|------|--------------:|-------------:|-----:|
| OLD | 80,001 | 7,679 | 31.6 ms |
| NEW | 2 | 1 | **0.05 ms** |

Maps to prod's measured 8,911 buffer hits → 760 ms. End-to-end API:
`/v0/servers?limit=100&cursor=…` returns in 4–7 ms regardless of depth.

Risk check: confirmed `(server_name, version)` index exists in that
column order (both `servers_pkey` and `idx_servers_name_version`), and
both columns are `NOT NULL` so row-constructor comparison can't silently
drop rows.

## Tests

- New
`TestPostgreSQL_PerformanceScenarios/compound_cursor_across_versions_of_same_server`
pins multi-version pagination semantics. The existing cursor tests only
exercised the fallback (single-component cursor) and degenerate (one
version per server) cases.
- `make lint` clean, `go test -race ./internal/... ./cmd/...` green.

## Deployment

The cursor + slog changes are zero-downtime. The CNPG spec change
triggers a brief PG restart (single-instance cluster). After the
restart, run once on prod:

```bash
kubectl exec -i registry-pg-1 -c postgres \
  --context gke_mcp-registry-prod_us-central1-b_mcp-registry-prod \
  -- psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements"
```

Time the merge for a low-traffic UTC window. v1.7.1's DB
retry-with-backoff covers the brief PG restart.

## Out of scope

`MaxConns` bump, per-IP rate limiting at nginx, response caching, the
pre-existing `superfluous WriteHeader` warnings — separate follow-ups.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 15:35:59 -04:00
Radoslav Dimitrov
762a4849a6
deploy: update prod to v1.7.1 (#1212)
## Summary

Promotes
[v1.7.1](https://github.com/modelcontextprotocol/registry/releases/tag/v1.7.1)
to production. Contents: the hardening + diagnostics from #1211.

What's in v1.7.1 (vs v1.7.0):
- Pulumi-managed IAM bindings for the default compute SA so
fluentbit-gke and the GMP collector can ship logs/metrics (already
applied to live cluster manually)
- `PodDisruptionBudget` with `minAvailable: 1` +
`TopologySpreadConstraints` to keep pods spread across nodes
- `StartupProbe` (30 × 5s) covering the new DB-retry budget
- Bounded retry-with-backoff on initial DB connect in
`cmd/registry/main.go`
- Memory request 128→256Mi, limit 256→512Mi
- `slog` `validate_ms` timing on the publish path so the next slow
`/v0/publish` is self-diagnostic

## Test plan
- [x] v1.7.1 release workflow built and pushed image successfully
(`ghcr.io/modelcontextprotocol/registry:1.7.1`)
- [x] Pulumi.gcpProd.yaml diff is the single-line image bump
- [ ] On merge, `deploy-production.yml` rolls out v1.7.1 — watch for
clean rolling update (`maxSurge: 1`, `maxUnavailable: 0`) and confirm
both pods reach Ready
- [ ] After rollout, confirm `Starting MCP Registry Application v1.7.1`
shows up in Cloud Logging from the new pods

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:44:10 -04:00
Radoslav Dimitrov
c6d3096d1b
fix(deploy): manage Cloud Resource Manager API enablement in Pulumi (#1213)
## Summary

Follow-up to #1211 to encode the GCP API and IAM dependencies its
node-SA bindings rely on. After #1211 merged, the staging deploy hit two
undocumented prereqs in sequence — Cloud Resource Manager API not
enabled (because `projects.NewIAMMember` calls SetIamPolicy through
CRM), then the Pulumi service account missing
`roles/resourcemanager.projectIamAdmin`. Both fixed manually to unblock;
this PR makes them explicit so they don't bite again.

## Changes

**`ensureRequiredAPIs` adopts five GCP APIs** as Pulumi-managed
`projects.Service` resources, all with `DisableOnDestroy: false` and
`DisableDependentServices: false` so a Pulumi destroy/refactor can never
disable a shared API:

| API | Why |
|-----|-----|
| `cloudresourcemanager` | `projects.NewIAMMember` → SetIamPolicy |
| `compute` | `compute.GetDefaultServiceAccount` invoke + GKE |
| `container` | GKE cluster |
| `logging` | fluentbit-gke ships container logs |
| `monitoring` | managed Prometheus collector ships metrics |

CRM is created explicitly (not in the loop) so callers get a direct
reference for `pulumi.DependsOn`. Storage is intentionally **not**
Pulumi-managed — Pulumi state itself lives in a GCS bucket,
chicken-and-egg.

**`grantNodeServiceAccountRoles`** now `DependsOn` the CRM
`projects.Service` for the four IAM bindings, and uses
`compute.GetDefaultServiceAccount` to derive the SA email (Compute API
was already required for GKE — avoids a CRM-dependent project-number
lookup).

**`deploy/README.md`** — adds `roles/resourcemanager.projectIamAdmin` to
the Pulumi SA's required roles and clarifies which APIs must be enabled
before the first `pulumi up` (storage, cloudresourcemanager, container)
vs. which `ensureRequiredAPIs` adopts.

## Notes

`projects.Service` is idempotent against already-enabled APIs — on
existing projects (staging/prod), Pulumi adopts the live enablement into
state without re-enabling. This was confirmed live: staging deploy went
green after the manual unblocks above, validating the runtime model.

## Test plan

- [x] `go build ./...` clean for `deploy/`
- [x] `golangci-lint run` clean for `deploy/pkg/providers/gcp/...` (one
pre-existing `nilnil` at line 61, unrelated)
- [x] Manual unblock + green staging deploy verified the runtime
behavior this PR encodes
- [ ] On merge: staging deploy adopts the existing API enablements
without churn, then proceeds normally
- [ ] Prod deploy via #1212 (image promotion) inherits the same setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:32:22 -04:00
Radoslav Dimitrov
b24d6c7657
fix: harden registry availability and add publish phase timings (#1211) v1.7.1
## Summary

Daily ~17:00 UTC `Publish Endpoint Latency` and `Availability < 95%`
alerts are caused by both registry pods exit-0'ing within seconds of
each other and racing with the still-recovering `registry-pg-rw`
endpoint on restart. Separately, the default compute SA had no project
IAM roles, so `fluentbit-gke` and the GMP collector were silently
dropping every log line and time series — which is why none of this was
visible in Cloud Logging.

All Kubernetes/IAM changes apply uniformly to staging and prod.

## Changes

- **GCP IAM** (`deploy/pkg/providers/gcp/provider.go`) — grant the
default compute SA `logging.logWriter`, `monitoring.metricWriter`,
`monitoring.viewer`, and `stackdriver.resourceMetadata.writer`. Already
applied live; this just encodes it in Pulumi.
- **Pod resilience** (`deploy/pkg/k8s/registry.go`) —
- `PodDisruptionBudget` (`minAvailable: 1`) prevents a synchronized
voluntary disruption.
- `TopologySpreadConstraints` (`ScheduleAnyway`, hostname) keeps the PDB
from deadlocking node drains when both pods co-locate.
- `StartupProbe` (30 × 5s = 150s) protects the DB-retry budget from the
liveness probe.
  - Memory bump 128→256Mi request, 256→512Mi limit.
- **Startup retry** (`cmd/registry/main.go`) — replace silent `return`
on initial DB-ping failure with bounded retry-with-backoff (8 attempts,
1→8s capped, 10s per-attempt). A brief endpoint flap no longer cascades
into a restart loop.
- **Diagnostic log** (`internal/service/registry_service.go`) — emit
`validate_ms` on each publish (success and failure). Validate fans out
to npm/PyPI/OCI with 10s per-host timeouts and is the most likely
contributor to publish latency. Total request duration is already
covered by the existing `http.request.duration` histogram.

## Calibration

The IAM, PDB, topology-spread, startup-probe, and DB-retry pieces are
mitigations — they reduce blast radius regardless of root cause. The
`validate_ms` log is the diagnostic for identifying the trigger when the
alert fires next. Single-PG SPOF (`deploy/pkg/k8s/postgres.go:57`)
remains a follow-up; today's evidence shows PG was a victim, not the
cause.

## Test plan

- [x] `go build ./...` and `go vet ./...` clean for both modules
- [x] `make lint` clean (12 pre-existing issues under `deploy/` are not
in `make lint`)
- [x] `go test -race -count=1 ./internal/... ./cmd/...` green
- [x] IAM applied live; `fluentbit-gke` and GMP no longer hitting
`IAM_PERMISSION_DENIED`
- [ ] After deploy, verify the next 17:00 UTC firing surfaces
`validate_ms` in Cloud Logging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 09:09:50 -04:00
Radoslav Dimitrov
7722031739
deploy: update prod to v1.7.0 (#1205)
## Summary
- Bumps production image tag from `1.6.0` to `1.7.0` in
`deploy/Pulumi.gcpProd.yaml`
- Corresponds to the [v1.7.0
release](https://github.com/modelcontextprotocol/registry/releases/tag/v1.7.0)
- Notable change: includes #1201 — fixes #1081 (`isLatest` no longer
stranded after soft-delete) and ships migration `014_heal_is_latest`
that auto-heals affected servers (e.g.
`io.github.containers/kubernetes-mcp-server`) on deploy

## Test plan
- [ ] Verify Pulumi preview shows only the image tag change
- [ ] After deploy, confirm migration 014 ran and
`io.github.containers/kubernetes-mcp-server`'s `/versions/latest`
returns `0.0.61` (or whichever is highest non-deleted)
- [ ] Sample a few unaffected servers and confirm `isLatest` is
unchanged
- [ ] Confirm overall service health

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 10:01:08 -07:00
Radoslav Dimitrov
0cb1f6bf52
fix: recalculate isLatest after status changes (#1081) (#1201) v1.7.0
## Summary

Fixes #1081. When the version flagged `is_latest` was soft-deleted, no
other version was promoted, and because `GetCurrentLatestVersion` didn't
filter deleted rows, subsequent publishes with a lower semver never
became latest — leaving `/v0/servers/{name}/versions/latest` permanently
404.

This PR has two parts:

### 1. Code fix — recalculate `is_latest` on every status change

- Recalculate `is_latest` after every status mutation
(`UpdateServerStatus`, `UpdateAllVersionsStatus`, and the inline status
change in `UpdateServer`), in the same transaction that already holds
the per-server advisory lock.
- Winner selection reuses the existing `CompareVersions` logic: highest
non-deleted version gets the flag; if every version is deleted, the
highest deleted version keeps it so admin lookups via
`includeDeleted=true` still resolve the server (important for restore
flows).
- New `SetLatestVersion` DB primitive issues two statements (clear old,
set new) — `idx_unique_latest_per_server` is a non-deferrable unique
partial index, so a single `UPDATE` that flips two rows trips the
constraint.

### 2. One-shot migration — heal servers already affected (no manual SQL
needed)

`014_heal_is_latest.sql` promotes the highest non-deleted version on
every server whose `is_latest` flag is on a deleted row (or absent
entirely). Picker parses `major.minor.patch` numerically and falls back
to `published_at` for non-semver or as a tiebreaker. Heals
`io.github.containers/kubernetes-mcp-server` to `0.0.61` automatically
and catches any other servers silently affected by the original bug,
without hardcoded version numbers.

Picker behavior vs. `CompareVersions`:
- Standard `M.m.p` semver: matches exactly, including the
backport-after-delete case (e.g. published 1.0.1 then 1.0.0 hotfix after
deleting 2.0.0 → picks 1.0.1, not 1.0.0).
- Non-semver: falls through to `published_at DESC`. Reasonable.
- Prereleases (`1.0.0-alpha` vs `1.0.0`): both parse to `(1,0,0)`,
tiebreak by `published_at`. Diverges from `CompareVersions` (which
always says `1.0.0 > 1.0.0-alpha`). Edge case requires (a) server hit by
this bug AND (b) prereleases at the top of the version list. Acceptable;
the publisher can flip it with one `mcp-publisher status` call (which
now triggers proper recalc thanks to part 1).

## Verification

End-to-end curl repro of the exact scenario from the issue, run against
both `main` and this branch:

**Before (main):**
```
publish 1.0.0 → 200
publish 0.0.59 → 200
PATCH .../1.0.0/status {deleted} → 200
GET /versions/latest → 404            ← bug
publish 0.0.60 → 200
GET /versions/latest → 404            ← bug persists, 0.0.60 has isLatest=False
```

**After (this branch):**
```
publish 1.0.0 → 200
publish 0.0.59 → 200
PATCH .../1.0.0/status {deleted} → 200
GET /versions/latest → 200 (0.0.59, isLatest=true)
publish 0.0.60 → 200
GET /versions/latest → 200 (0.0.60, isLatest=true)
```

## Test plan

- [x] Service tests covering: soft-delete latest → next highest active
promoted; the exact #1081 repro end-to-end through the service;
all-versions-deleted still keeps highest addressable for admin;
restore-to-higher-version reclaims latest.
- [x] Migration tests covering: kubernetes-mcp-server scenario (heals to
highest semver); backport scenario (semver beats most-recent-published);
no-is_latest-row defensive case; all-deleted server left untouched;
healthy server left untouched; non-semver versions fall back to
`published_at`.
- [x] Full unit test suite (`./internal/... ./cmd/...`) passes against a
real Postgres.
- [x] `make lint` (0 issues) and `make validate` pass.
- [x] Manual curl repro against a running registry confirms the fix
resolves the failure mode and `main` still reproduces it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 11:59:28 -04:00
Radoslav Dimitrov
c5f50e817b
fix(auth): better DNS verification errors and wrong-selector hint (#1202)
## Summary

DNS auth users have repeatedly hit two failure modes that both produce
the same opaque "Ed25519 signature verification failed" error, making
them indistinguishable to debug. This PR makes both diagnosable
end-to-end without changing the auth protocol or any successful path.

The two recurring failure modes:

1. **Wrong placement** — TXT record put under a selector
(`_mcp-auth.<domain>` or `_mcp-registry.<domain>`) instead of the apex.
DKIM-style intuition, but MCP DNS auth uses SPF-style apex placement.
See #385 (PR #388 fixed the docs but the failure recurred), #1103,
#1126.
2. **Stale apex record** — old TXT record left behind after a key
rotation, silently tried first and rejected.

## Changes

**`internal/api/handlers/v0/auth/dns.go`** — when the apex has no
`v=MCPv1` record, probe `_mcp-auth.<domain>` and
`_mcp-registry.<domain>` in parallel (2s individual timeout). If a
record is found there, return a targeted error pointing the user at the
apex. Costs zero extra DNS work in the success path.

**`internal/api/handlers/v0/auth/common.go`** — when verification fails
against records that *are* present, include short fingerprints of every
key the registry tried (`ed25519:YJLsHFhu`-style 8-char prefix). A new
`ErrSignatureMismatch` sentinel keeps structural errors (wrong signature
size, unsupported algorithm) passing through unchanged via `errors.Is`,
so existing assertions on those messages still hold.

**`docs/modelcontextprotocol-io/authentication.mdx`** — anti-pattern
`<Warning>` callout in the DNS section explicitly warning against
selector placement and stale records.

**Tests** — two new tests:
- `TestDNSAuthHandler_WrongSelectorProbe` — verifies the probe surfaces
records found at `_mcp-auth.` / `_mcp-registry.` and falls through to
the standard error when nothing is found anywhere
- `TestDNSAuthHandler_StaleKeyFingerprintInError` — verifies the
fingerprint hint appears in the failure message for #1126's exact
scenario

One existing test assertion was updated from a generic `"signature
verification failed"` substring to the more specific `"invalid signature
size for ECDSA P-384"` it should always have been asserting; the new
sentinel-based logic surfaces structural errors verbatim.

## Test plan

- [x] `make lint` — clean
- [x] `make test-unit` — all auth tests pass (existing + 2 new)
- [x] Verified existing single-key and multi-key paths preserve their
original (more specific) error messages where they were already specific
- [ ] Reviewer to sanity-check the docs callout renders well in the
Mintlify theme

## Out of scope

The publisher-side preflight DNS check (cross-link in #845) is
intentionally **not** in this PR — that belongs in the broader CLI UX
work tracked by #845.

Refs #845, #385, #1103
Fixes #1126

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 11:22:06 -04:00
Radoslav Dimitrov
8b893ae1f1
docs: recommend namespaced subkeys inside publisher-provided (#1197)
## Summary
- Adds a short "Recommended: Namespaced Subkeys" subsection to
`official-registry-requirements.md`, documenting the reverse-DNS subkey
convention for `publisher-provided` metadata with one worked example
- Explicitly notes this is not enforced, to avoid churning the ~15
existing flat-key examples elsewhere in the docs

Closes #477

## Test plan
- [ ] Render the file on GitHub and verify the new subsection appears
right after the `Publisher-Provided Metadata` size-limit note

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 07:15:32 -07:00
Radoslav Dimitrov
ccb7057c33
docs: note PostgreSQL requirement for prebuilt Docker image (#1196)
## Summary
- Clarifies in the README that the prebuilt Docker image does not bundle
PostgreSQL and needs an external instance reachable via
\`MCP_REGISTRY_DATABASE_URL\`
- Points readers to \`docker-compose.yml\` as a working multi-container
example

Closes #723

## Test plan
- [ ] Render the README on GitHub and verify the note appears in the
"Alternative: Running a pre-built Docker image" section

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 07:15:00 -07:00
Radoslav Dimitrov
aaa634ebb6
fix(publisher): honor mcpName as the authoritative server name in init (#1195)
## Summary

Follow-up to #1145. When `mcpName` is set in `package.json`, it should
be the server name used by `mcp-publisher init`. Two issues addressed:

### 1. `getNameFromPackageJSON` mangled `mcpName` through npm-name
transformation

`mcpName` values are already in MCP server name format (e.g.
`io.github.foo/bar`). The existing code ran them through the
`@scope/name → io.github.scope/name` transform and its
`io.github.<your-username>/*` fallback, producing a broken double-prefix
result.

Example with `"mcpName": "io.github.acme/weather"`:
- Before: `io.github.<your-username>/io.github.acme/weather` ❌
- After: `io.github.acme/weather` ✅

### 2. `detectServerName` consulted git before `mcpName`

Even with `mcpName` set in `package.json`, a github.com git remote (or a
`repository` field) silently won — the function returned
`io.github.<owner>/<repo>` and never looked at `mcpName`. Per the
[quickstart
docs](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/quickstart.mdx),
*"The value of `mcpName` will be your server's name in the MCP
Registry"*, so `mcpName` should take precedence.

## Changes

- `cmd/publisher/commands/init.go`:
- New `getMcpNameFromPackageJSON()` helper that returns `mcpName` or
`""`.
- `detectServerName` checks `mcpName` first, before git remote and the
`name`-based fallback.
- `getNameFromPackageJSON` simplified — the now-redundant `mcpName`
branch was removed; it only handles the npm `name` transformation.
- `cmd/publisher/commands/init_test.go` (new): 5 cases through the
public `InitCommand` API covering `mcpName` as-is, fallback to scoped
`name`, fallback to placeholder, version fallback, and `mcpName` winning
over a GitHub `repository` URL.

This completes the fix for #737.

## Test plan

- [x] `go test ./cmd/publisher/commands/` passes (5 new subtests)
- [x] `golangci-lint run ./cmd/publisher/commands/` clean
- [ ] Manual: `mcp-publisher init` in a git-tracked directory with
`package.json` containing `mcpName` produces a `server.json` whose
`name` matches `mcpName`, not the repo slug

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 07:14:11 -07:00