Skip to content

Comments

feat: mcp server for validate plugin#518

Open
s4kh wants to merge 22 commits intomainfrom
feat-mcp-server
Open

feat: mcp server for validate plugin#518
s4kh wants to merge 22 commits intomainfrom
feat-mcp-server

Conversation

@s4kh
Copy link
Contributor

@s4kh s4kh commented Feb 17, 2026

Exposes plugin-validator CLI as MCP server. Tool: validate_plugin

  1. Separate release for mcpserver - published to npm and docker-hub
  2. MCP server uses npx or docker to run the latest validator CLI
  3. Includes configs for vscode extension, claude code, openAI codex configs in the README

@s4kh s4kh moved this from 📬 Triage to 🧑‍💻 In development in Grafana Catalog Team Feb 17, 2026
}

func ValidatePlugin(ctx context.Context, req *mcp.CallToolRequest, input Input) (*mcp.CallToolResult, Output, error) {
return nil, Output{}, nil
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have to do same stuffs we do in plugincheck2/main.go (reading archive, checksum, etc.) Maybe extract those into separate package and reuse it.

@s4kh s4kh self-assigned this Feb 17, 2026
@s4kh s4kh force-pushed the feat-mcp-server branch 2 times, most recently from abbd531 to 8b5e130 Compare February 17, 2026 15:20
@@ -0,0 +1,228 @@
package service
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Extracted from plugincheck2/main.go.

@s4kh s4kh marked this pull request as ready for review February 17, 2026 16:50
@s4kh s4kh requested review from a team as code owners February 17, 2026 16:50
echo -e "${YELLOW}Warning: $INSTALL_DIR is not in your PATH${NC}"
echo "Add the following to your ~/.bashrc or ~/.zshrc:"
echo ""
echo " export PATH=\"\$HOME/.local/bin:\$PATH\""
Copy link
Contributor Author

Choose a reason for hiding this comment

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

.local/bin exists both on macos and linux


// HasProperArchiveStructure checks if the archive has the proper structure:
// single top-level directory containing plugin.json
func HasProperArchiveStructure(archiveDir string) bool {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

plugincheck2 used to check this using GetIdAndVersion from quickmeta and if it returns error it would add an invalid structure report to the result.

}

func main() {
if err := run(); err != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

@academo academo left a comment

Choose a reason for hiding this comment

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

I would like you to reconsider the approach for the mcp server

the validator already supports outputting as json, could you invoke the validator binary here and parse the output instead?

here are my two concerns with this approach:

  1. single source of truth: now we are effectively creating two different software that embed the same engine. I much rather prefer we keep a single entry point (the validator cli binary) and make MCP just another user, like for example github actions is an user of the validator, and ci-workflows, and the community pipeline.

We don't need to create separate binaries for those cases because we have a common serialized output any user can read.

  1. updates: this binary will be out of date very quickly. instead we can have this wrapper checking the latest version (once a day?), downloading it and executing it to get the json output.

I don't see a mechanism to update mcp servers, they need to auto-update. People that use the validator mainly use it via docker or npx that always pulls the latest version (except NPM when it wants to be a pain)

my bottom line: we can make this wrapper simply call npx or docker or yarn dlx or similar (support several fallbacks) and parse the json output.


func TestValidatePlugin_InvalidZip(t *testing.T) {
// Skip if neither docker nor npx is available (e.g., in CI/CD)
if !isDockerAvailable() && !isNpxAvailable() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We are running the tests locally. In CI it will be skipped due to docker and npx not present.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

CI has docker available.

Copy link
Contributor Author

@s4kh s4kh Feb 20, 2026

Choose a reason for hiding this comment

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

So we run the tests using mage -v build:ci inside a container which uses goalpine(Dockerfile) thus no docker or npm. I have created a new job inside the test.yml of the github workflows.

@s4kh s4kh requested a review from academo February 18, 2026 14:30
type Diagnostics map[string][]Diagnostic

// Severity constants
const (
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we import the types from the existing definitions instead of re-defining them here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted the binary for MCP to pretty thin and no dependency on the analysis package.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So the docker build can be also minimal.

@@ -0,0 +1,86 @@
#!/bin/bash
Copy link
Collaborator

@academo academo Feb 19, 2026

Choose a reason for hiding this comment

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

most MCP servers I see run from npx or docker.

We should publish this validator MCP in NPM just like we do with the validator. instead of throwing a bash file to execute and auto-detec people's setup

It requires a bit more of setup but it removes all the complications of this script failing on edge cases.

we can also publish it as a docker image which is another popular way of running mcp servers

plugincheck2 -sourceCodeUri [source_code_location/] [plugin_archive.zip]
```

### MCP Server (for AI assistants)
Copy link
Collaborator

Choose a reason for hiding this comment

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

consider this will be what we ask people to do to install our MCP server the instructions are far off.

Most people that want to install an mcp server expect instructions to tell them something like:

modify your mcp.json file and add

{
 "mcpServers": {
    "grafana-plugin-validator": {
      "command": "npx",
      "args": ["-y", "@grafana/plugin-validator-mcp"]
    }
  }
}

@s4kh s4kh requested review from academo and xnyo February 19, 2026 21:42
@s4kh
Copy link
Contributor Author

s4kh commented Feb 19, 2026

@academo addressed the feedbacks - It is definitely on the right direction 👏 . Except, do not redefine types that are already available - decoupling from the pkg/ so the MCP server binary can be minimal.

@s4kh s4kh moved this from 🧑‍💻 In development to 🔬 In review in Grafana Catalog Team Feb 20, 2026
@s4kh s4kh requested a review from Copilot February 20, 2026 14:16
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds Model Context Protocol (MCP) server support to the plugin-validator, allowing AI assistants (like Claude, Cline, etc.) to validate Grafana plugins programmatically. The MCP server is a Go binary that wraps the plugin-validator CLI and exposes it via the MCP protocol, communicating over stdin/stdout. The implementation supports both Docker and npx execution methods, with Docker preferred when available.

Changes:

  • Added MCP server implementation (pkg/cmd/mcpserver/main.go) that wraps the plugin-validator CLI via Docker or npx
  • Created NPM package wrapper to download and execute platform-specific MCP server binaries
  • Added separate release workflows and configurations for MCP releases (tagged as mcp/v*)

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
pkg/cmd/mcpserver/main.go Core MCP server implementation that executes plugin-validator via Docker or npx
pkg/cmd/mcpserver/main_test.go Integration tests for MCP server with valid/invalid plugin archives
mcp-package/index.js NPM wrapper that downloads and executes platform-specific binaries
mcp-package/package.json NPM package configuration with binary wrapper metadata
mcp-package/Dockerfile Docker image for running the MCP server
mcp-package/README.md Documentation with configuration examples for various MCP clients
.goreleaser.mcp.yaml Goreleaser configuration for building MCP server binaries
.github/workflows/release-mcp.yml Workflow to release MCP server to GitHub, NPM, and Docker Hub
.github/workflows/do-release-mcp.yml Manual workflow to trigger MCP version bumps and releases
.github/workflows/release.yml Updated tag filter to prevent MCP tags from triggering main releases
go.mod Added MCP SDK dependency
go.sum Updated dependency checksums
README.md Added link to MCP server documentation

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🔬 In review

Development

Successfully merging this pull request may close these issues.

2 participants