-
Notifications
You must be signed in to change notification settings - Fork 366
feat(helm): extract Helm chart for Grafana MCP #812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| prometheus: | ||
| url: "prometheus.kagent:9090/api/v1" | ||
| username: "" | ||
| password: "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this was unused so cleaned up while I was at it. Same goes for grafana.username and grafana.password just below.
| @@ -0,0 +1,14 @@ | |||
| apiVersion: kagent.dev/v1alpha2 | |||
| kind: RemoteMCPServer | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know I could have just used the Service, but I prefer this because, since the removal of the ToolServer, one has to look at controller logs to see if there are any issues with Service/McpServer-based tooling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am cognisant that the original stdio implementation may have been used to dog-food the KMCP integration, but hopefully a different solution can be found for that.
| - name: querydoc | ||
| version: ${VERSION} | ||
| repository: file://../tools/querydoc | ||
| condition: external-mcp.querydoc.enabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed this condition while I was here
4ce7c4b to
821858c
Compare
There was a problem hiding this 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 extracts the Grafana MCP server functionality into a standalone Helm chart while upgrading to use Streamable HTTP transport. Previously, the Grafana MCP server was tightly coupled with the observability agent, and this change enables independent deployment and improved connectivity through HTTP streaming.
- Extracts Grafana MCP server into a standalone Helm chart in
helm/tools/grafana-mcp/ - Migrates from stdio transport to streamable-http transport protocol
- Updates observability agent to reference the new standalone Grafana MCP server
Reviewed Changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| helm/tools/grafana-mcp/ | New standalone Helm chart for Grafana MCP server with streamable-http transport |
| helm/kagent/values.yaml | Adds configuration for new grafana-mcp tool dependency |
| helm/kagent/Chart-template.yaml | Updates dependencies to include new grafana-mcp chart |
| helm/agents/observability/ | Removes embedded Grafana MCP server and updates agent to reference standalone version |
| Makefile | Adds build steps for new grafana-mcp Helm chart |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| labels: | ||
| {{- include "grafana-mcp.labels" . | nindent 4 }} | ||
| spec: | ||
| replicas: {{ .Values.replicas }} |
Copilot
AI
Aug 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The template references .Values.replicas but the values.yaml file defines replicaCount. This will cause the deployment to fail. Change this to {{ .Values.replicaCount }}.
| replicas: {{ .Values.replicas }} | |
| replicas: {{ .Values.replicaCount }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
helm/tools/grafana-mcp/values.yaml
Outdated
|
|
||
| resources: {} | ||
|
|
||
| # Deployment configuration |
Copilot
AI
Aug 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The config: section is empty but referenced in the ConfigMap template. Consider either providing a default value (e.g., config: {}) or adding a comment explaining its purpose.
| # Deployment configuration | |
| # Deployment configuration | |
| # The 'config:' section is used to populate the ConfigMap template. | |
| # Add custom configuration values here as needed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
| {{/* | ||
| Create the grafana server URL | ||
| */}} | ||
| {{- define "grafana-mcp.serverUrl" -}} | ||
| {{- printf "http://%s.%s:%d/mcp" (include "grafana-mcp.fullname" .) .Release.Namespace (.Values.service.port | int) }} | ||
| {{- end }} |
Copilot
AI
Aug 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The helper function grafana-mcp.serverUrl is defined but not used anywhere in the templates. Consider removing it or using it in the RemoteMCPServer template where the URL is currently hardcoded.
| {{/* | |
| Create the grafana server URL | |
| */}} | |
| {{- define "grafana-mcp.serverUrl" -}} | |
| {{- printf "http://%s.%s:%d/mcp" (include "grafana-mcp.fullname" .) .Release.Namespace (.Values.service.port | int) }} | |
| {{- end }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
| - name: grafana-mcp | ||
| version: ${VERSION} | ||
| repository: file://../tools/grafana-mcp | ||
| condition: tools.grafana-mcp.enabled, agents.observability-agent.enabled |
Copilot
AI
Aug 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition uses agents.observability-agent.enabled but this should be agents.observability.enabled based on the values structure. Also, using multiple conditions with comma separation creates an AND condition - verify this is the intended behavior.
| condition: tools.grafana-mcp.enabled, agents.observability-agent.enabled | |
| condition: tools.grafana-mcp.enabled, agents.observability.enabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
observability-agent is correct - see here.
821858c to
3670f8f
Compare
|
Just out of curiosity why did you move from the |
The main reason at this point is that I think that using a native CRD, Also, whilst I think the KMCP integration is great, I do, however, also disagree with the current implementation, which couples the two projects - but that's a bigger discussion that I was hoping to save for another time 😅. |
3670f8f to
0854937
Compare
Leaving aside the larger architecture question for one moment. I think the fact that the status is not useful is a bug rather than an inherent feature. If the MCPServer status is not properly indicative of what’s happening that’s something we can absolutely fix. In terms of the service, I think we can pretty easily expose a status via the kagent CLI. |
Absolutely. This should be addressed at some point, and was something else I was going to bring up at another point. IMO the correct way to do this is to ensure that all tool servers are reflected in the cluster and not only stored in the database 😅 |
Enables this to be deployed as a standalone component (i.e. without the observability-agent) and also, incidentally, 😉, without the need for KMCP to be deployed to the cluster since this now supports Streamable HTTP. Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com>
0854937 to
36e979c
Compare
| tools: | ||
| grafana-mcp: | ||
| enabled: true | ||
| querydoc: | ||
| enabled: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have a separate block for this, and not just nest it in the individual blocks below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tools.x block has a slightly different semantic meaning from the individual blocks below. The tools.x block is used to enable the subcharts for the various tools, whereas the individual querydoc and grafana-mcp blocks are used to configure the subcharts themselves. I.e., any values/directives within the individual blocks themselves will be passed through/sent to the subchart. Were we to specify enabled: true within the individual blocks, this would also be passed through to the subcharts' values. Now, neither of the charts actually defines/makes use of enabled: true at present, so there is no real harm in doing that, but this sort of thing can lead to weird/unexpected behaviour, so generally I prefer maintaining a distinction between the two use-cases. I also noticed that the agents themselves are enabled/disabled/configured in a similar manner, and so I thought I'd be consistent with that for tools. That said, I don't have a hard opinion here, so if you'd prefer enabled to be part of the individual blocks, then I'll happily make it so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just define these in the deployment. Personally I much prefer an env block in the values file, and then fill them directly into the deployment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't have a strong opinion here either - both work. I did it this way to be consistent with how things are done in querydoc. Happy to refactor as per your desire.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with keeping it here, but can we change the values.yaml field to env to better reflect where these values end up, config is a little too generic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure about just changing the name? IMO it would be confusing to specify env as key/values. config is currently a key/value map. env on the other hand implies a list of objects like
- name: FOO
value: bar... or at least that is how env is used on a Deployment. I honestly don't mind the use of either, but would recommend keeping to commonly expected formats.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok fine, we can always change later if we need
Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com>
This PR decouples the kmcp integration, ensuring that kmcp is a separate, optional component that can be deployed alongside, and independently of, kagent. The kmcp integration remains fully in place and, by default, is enabled as is the case in the current version. The main difference being that, instead of the hard-coupling that is in place today, where the `kagent-controller` [runs the kmcp controller](https://github.com/kagent-dev/kagent/blob/bdbde1109e7fd214a2536940043a6afef8e07c92/go/pkg/app/app.go#L323-L329), the kmcp controller is deployed as a separate, standalone component/pod. This is important for numerous reasons... not least of which is the fact that these are separate projects with separate lifecycles and one should be able to manage them independently if desired. Notes: - The `KMCP_ENABLED` flag (and associated Helm setting) merely determines whether the kmcp controller and associated CRDs are installed as part of the `kagent` and `kagent-crds`. Users can set this to false and install kmcp independently of the `kagent` Helm chart, and the controller will still work with any additional configuration. The controller simply enables/disables reconciliation of `MCPServer` resources based on whether or not the CRD is present in the cluster. If desired, in the future, a flag could be added to the controller to disable/enable the integration manually, but for now, I think that's overkill - the (automatic) integration is great 💌 - The default setup will currently break if `KMCP_ENABLED` is set to `false`. This is due to the use of the `MCPServer` for the [`grafana` MCP](https://github.com/kagent-dev/kagent/blob/bdbde1109e7fd214a2536940043a6afef8e07c92/helm/agents/observability/templates/mcp-server.yaml#L12-L31) as part of the `observability` agent. This is addressed as part of #812, which switches to using `RemoteMCPServer`, ensuring that all built-in components/agents/tools work regardless of whether KMCP is enabled. --------- Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com> Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Eitan Yarmush <eitan.yarmush@solo.io>
This PR decouples the kmcp integration, ensuring that kmcp is a separate, optional component that can be deployed alongside, and independently of, kagent. The kmcp integration remains fully in place and, by default, is enabled as is the case in the current version. The main difference being that, instead of the hard-coupling that is in place today, where the `kagent-controller` [runs the kmcp controller](https://github.com/kagent-dev/kagent/blob/bdbde1109e7fd214a2536940043a6afef8e07c92/go/pkg/app/app.go#L323-L329), the kmcp controller is deployed as a separate, standalone component/pod. This is important for numerous reasons... not least of which is the fact that these are separate projects with separate lifecycles and one should be able to manage them independently if desired. Notes: - The `KMCP_ENABLED` flag (and associated Helm setting) merely determines whether the kmcp controller and associated CRDs are installed as part of the `kagent` and `kagent-crds`. Users can set this to false and install kmcp independently of the `kagent` Helm chart, and the controller will still work with any additional configuration. The controller simply enables/disables reconciliation of `MCPServer` resources based on whether or not the CRD is present in the cluster. If desired, in the future, a flag could be added to the controller to disable/enable the integration manually, but for now, I think that's overkill - the (automatic) integration is great 💌 - The default setup will currently break if `KMCP_ENABLED` is set to `false`. This is due to the use of the `MCPServer` for the [`grafana` MCP](https://github.com/kagent-dev/kagent/blob/bdbde1109e7fd214a2536940043a6afef8e07c92/helm/agents/observability/templates/mcp-server.yaml#L12-L31) as part of the `observability` agent. This is addressed as part of kagent-dev#812, which switches to using `RemoteMCPServer`, ensuring that all built-in components/agents/tools work regardless of whether KMCP is enabled. --------- Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com> Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Eitan Yarmush <eitan.yarmush@solo.io> Signed-off-by: killjoycircuit <rutujdhawale@gmail.com>


Enables this to be deployed as a standalone component (i.e. without the
observability-agent) and also upgrades to make use of Streamable HTTP as this is now supported.