Skip to content

Add new endpoint to get the MCPServer to prefil the MCP server deploy modal#6902

Merged
openshift-merge-bot[bot] merged 3 commits intoopendatahub-io:mainfrom
ppadti:add-utility
Mar 27, 2026
Merged

Add new endpoint to get the MCPServer to prefil the MCP server deploy modal#6902
openshift-merge-bot[bot] merged 3 commits intoopendatahub-io:mainfrom
ppadti:add-utility

Conversation

@ppadti
Copy link
Copy Markdown
Contributor

@ppadti ppadti commented Mar 26, 2026

Closes: https://redhat.atlassian.net/browse/RHOAIENG-54986

Description

The PR aims to use the Utility to convert runtimeMetadata into MCPServer kind to prefil the deploy modal for MCP server.
Added a new endpoint which frontend could call to get the MCPServer kind.
This PR now conditionally renders the deploy button based on the server artifacts. if present we will show the button otherwise we hide it.

How Has This Been Tested?

I have used these MCP server data - https://redhat-internal.slack.com/archives/C08G31WCV16/p1774039108953109?thread_ts=1773931929.864539&cid=C08G31WCV16
Its present in both psi-16 and green-3

Run the application federated mode and try this curl
TOKEN=$(oc whoami -t) && curl -s -H "x-forwarded-access-token: $TOKEN" "http://localhost:4000/api/v1/mcp_catalog/mcp_servers/85/mcpserver?namespace=rhoai-model-registries" | jq .

Test Impact

Added test for handlers

Request review criteria:

Self checklist (all need to be checked):

  • The developer has manually tested the changes and verified that the changes work
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has added tests or explained why testing cannot be added (unit or cypress tests for related changes)
  • The code follows our Best Practices (React coding standards, PatternFly usage, performance considerations)

If you have UI changes:

  • Included any necessary screenshots or gifs if it was a UI change.
  • Included tags to the UX team if it was a UI/UX change.

After the PR is posted & before it merges:

  • The developer has tested their solution on a cluster by using the image produced by the PR to main

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (15)
  • packages/model-registry/upstream/bff/internal/api/app.go is excluded by !**/upstream/**
  • packages/model-registry/upstream/bff/internal/helpers/mcpserver_converter.go is excluded by !**/upstream/**
  • packages/model-registry/upstream/bff/internal/helpers/mcpserver_converter_test.go is excluded by !**/upstream/**
  • packages/model-registry/upstream/bff/internal/mocks/static_data_mock.go is excluded by !**/upstream/**
  • packages/model-registry/upstream/bff/internal/models/mcpserver.go is excluded by !**/upstream/**
  • packages/model-registry/upstream/bff/internal/redhat/handlers/mcp_server_converter.go is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/__tests__/cypress/cypress/tests/mocked/mcpCatalog/mcpServerDetails.cy.ts is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/app/api/mcpCatalogDeployment/service.ts is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/app/hooks/mcpCatalogDeployment/useMcpServerConverter.ts is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/app/hooks/mcpCatalogDeployment/useMcpServerDeployAvailable.ts is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/app/mcpDeploymentTypes.ts is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/app/pages/mcpCatalog/screens/McpServerDetailsPage.tsx is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/odh/components/McpDeployButton.tsx is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/odh/components/McpDeployModalExtension.tsx is excluded by !**/upstream/**
  • packages/model-registry/upstream/frontend/src/odh/extension-points/mcp-deploy.ts is excluded by !**/upstream/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 67fd9d01-74e2-4da4-a8cb-e2c8d8562ef7

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 26, 2026

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 64.49%. Comparing base (ca13601) to head (52a7a6a).
⚠️ Report is 38 commits behind head on main.

Files with missing lines Patch % Lines
...am/frontend/src/odh/extension-points/mcp-deploy.ts 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #6902      +/-   ##
==========================================
+ Coverage   64.09%   64.49%   +0.39%     
==========================================
  Files        2530     2504      -26     
  Lines       76695    77255     +560     
  Branches    19202    19181      -21     
==========================================
+ Hits        49161    49825     +664     
+ Misses      27534    27430     -104     
Files with missing lines Coverage Δ
...am/frontend/src/odh/extension-points/mcp-deploy.ts 50.00% <0.00%> (ø)

... and 120 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ca13601...52a7a6a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@openshift-ci openshift-ci bot added the needs-rebase PR needs to be rebased label Mar 26, 2026
@ppadti ppadti changed the title Add new endpoint to get the MCPServer kind to prefil the MCP server deploy modal Add new endpoint to get the MCPServer to prefil the MCP server deploy modal Mar 26, 2026
…erver with remote server url

Signed-off-by: ppadti <ppadti@redhat.com>
@openshift-ci openshift-ci bot added area/frontend and removed needs-rebase PR needs to be rebased labels Mar 26, 2026
Copy link
Copy Markdown
Member

@manaswinidas manaswinidas left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! Left inline comments on the high/medium items.

TL;DR of the main concerns:

  1. Bug in ExtractContainerImage — always returns on the first loop iteration, skipping subsequent artifacts
  2. Dead code — conversion result fields (env comments, optional env vars, prereq comments) are computed but discarded by the handler; IncludeComments option is unused; the new hook + service are never consumed
  3. Breaking behavior — deploy button is now completely hidden (instead of shown disabled) for servers without artifacts
  4. Missing validation — empty container image produces an invalid CR instead of an error response
  5. Test gaps — multi-artifact case for ExtractContainerImage, empty-string URI edge case, loading state

Comment on lines +139 to +148
func ExtractContainerImage(artifacts []models.McpArtifact) string {
for _, a := range artifacts {
uri := a.URI
if strings.HasPrefix(uri, "oci://") {
return strings.TrimPrefix(uri, "oci://")
}
return uri
}
return ""
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Bug: This loop always returns on the first iteration regardless of prefix. If the first artifact isn't oci://-prefixed, it's returned immediately without checking the rest. The return uri should be moved after the loop as a fallback, or the intent needs clarifying.

Suggested change
func ExtractContainerImage(artifacts []models.McpArtifact) string {
for _, a := range artifacts {
uri := a.URI
if strings.HasPrefix(uri, "oci://") {
return strings.TrimPrefix(uri, "oci://")
}
return uri
}
return ""
}
func ExtractContainerImage(artifacts []models.McpArtifact) string {
for _, a := range artifacts {
uri := a.URI
if strings.HasPrefix(uri, "oci://") {
return strings.TrimPrefix(uri, "oci://")
}
}
if len(artifacts) > 0 {
return artifacts[0].URI
}
return ""
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I believe we will have one artifacts fields in data right? This is from the util - maybe will double check with backend team about the same

type ConversionOptions struct {
Name string
ContainerImage string
IncludeComments bool
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: IncludeComments is declared but never read anywhere in this file or the handler. Remove it or wire it up.

Copy link
Copy Markdown
Contributor Author

@ppadti ppadti Mar 27, 2026

Choose a reason for hiding this comment

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

This is was from the util we have - let me double check.

return
}

containerImage := helper.ExtractContainerImage(server.Artifacts)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If server.Artifacts is empty, containerImage will be "" and the resulting CR will have an empty containerImage.ref. Consider returning a 400/422 here instead of producing an invalid CR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think we will not hit this case as frontend doesn't show a deploy button if the server.artifacts is not present. But I can update this to be handling it from bff

Comment on lines +86 to +107
{Name: "API_KEY", Description: "API key for auth", Example: ptr("sk-xxx")},
{Name: "ENDPOINT", Description: "Endpoint URL"},
},
}

result := ConvertToMCPServer(metadata, ConversionOptions{Name: "env-test", ContainerImage: "img:v1"})

assert.Len(t, result.MCPServer.Spec.Config.Env, 2)
assert.Equal(t, "API_KEY", result.MCPServer.Spec.Config.Env[0].Name)
assert.Equal(t, "<API_KEY>", result.MCPServer.Spec.Config.Env[0].Value)

assert.Contains(t, result.EnvComments, "Required environment variables:")
assert.Contains(t, result.EnvComments, " - API_KEY: API key for auth")
assert.Contains(t, result.EnvComments, " Example: sk-xxx")
}

func TestConvertToMCPServer_OptionalEnvVars(t *testing.T) {
metadata := &models.McpRuntimeMetadata{
OptionalEnvironmentVariables: []models.McpEnvVarMetadata{
{Name: "LOG_LEVEL", Description: "Log level", DefaultValue: ptr("info")},
{Name: "TIMEOUT", Description: "Timeout in seconds"},
},
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Missing coverage for the multi-artifact case in ExtractContainerImage — e.g., []McpArtifact{{URI: "docker.io/foo"}, {URI: "oci://quay.io/bar"}}. Adding this test would expose the early-return bug in the implementation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

will check with backend team before updating this. If this merges, we can follow up

Signed-off-by: ppadti <ppadti@redhat.com>
Copy link
Copy Markdown
Member

@manaswinidas manaswinidas left a comment

Choose a reason for hiding this comment

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

/lgtm
/approve

Remote MCP servers like "github" don't have Deploy button while others do - I noticed "Github" MCP server isn't visible in "All MCP servers" but that's maybe a different issue and should be a follow up.

The endpoint works as described:

Image

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Mar 27, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: manaswinidas

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@manaswinidas
Copy link
Copy Markdown
Member

The BFF util converter is added as is from the MCP lifecycle operator backend team

@openshift-merge-bot openshift-merge-bot bot merged commit 3ed63a5 into opendatahub-io:main Mar 27, 2026
54 of 55 checks passed
@ppadti
Copy link
Copy Markdown
Contributor Author

ppadti commented Mar 30, 2026

Remote MCP servers like "github" don't have Deploy button while others do - I noticed "Github" MCP server isn't visible in "All MCP servers" but that's maybe a different issue and should be a follow up.

That is because on All server section we only show 4 models and the rest will only be visible in its specific section

mturley added a commit to mturley/odh-dashboard that referenced this pull request Mar 31, 2026
…ServerCR types

PR opendatahub-io#6910 accidentally deleted the MCPServerCR type and its supporting types
from mcpDeploymentTypes.ts while adding McpDeploymentCreateRequest and
McpDeploymentUpdateRequest. This caused type errors in service.ts and
useMcpServerConverter.ts which both import MCPServerCR.

On investigation, the entire MCP deployment feature (types, API service,
hooks, and extension) is downstream-only — it doesn't exist in the upstream
kubeflow/model-registry repo. These files were incorrectly placed in the
upstream/ directory by PRs opendatahub-io#6902 and opendatahub-io#6910.

Changes:
- Move mcpDeploymentTypes.ts, api/mcpCatalogDeployment/service.ts,
  hooks/mcpCatalogDeployment/useMcpServerConverter.ts, and
  hooks/mcpCatalogDeployment/useMcpServerDeployAvailable.ts from
  upstream/frontend/src/app/ to src/mcpCatalogDeployment/
- Restore MCPServerCR and supporting types (MCPServerMetadata,
  MCPServerSpec, MCPSourceSpec, etc.) that were deleted in opendatahub-io#6910
- Update imports in moved files to use relative paths instead of ~/
- Move the mcp-catalog.mcp-server/deploy-modal extension from
  upstream extensions.ts to downstream extensions.ts
- Add mod-arch-core dependency to packages/model-registry/package.json
  so the downstream tsconfig can resolve it

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Mike Turley <mike.turley@alum.cs.umass.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants