118 Commits

Author SHA1 Message Date
Marc Nuri
f3a446676f refactor(kubernetes): keep Provider as only external Kubernetes interface (#372)
* refactor(kubernetes): keep Provider as only external Kubernetes interface

Initial phase to unify-merge the Provider interface with the Manager struct.

- Renamed ManagerProvider to Provider (i.e. kubernets.Provider)
- Moved Manager related logic to specific files
- Exposed relevant method through Provider interface (GetDerivedKubernetes, IsOpenShift, VerifyToken)

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* Update pkg/kubernetes/provider_kubeconfig.go

Co-authored-by: Calum Murray <cmurray@redhat.com>
Signed-off-by: Marc Nuri <marc@marcnuri.com>

---------

Signed-off-by: Marc Nuri <marc@marcnuri.com>
Co-authored-by: Calum Murray <cmurray@redhat.com>
2025-10-14 15:25:49 +02:00
Calum Murray
a2d16e9f41 feat: Multi Cluster Support (#348)
* feat: add cluster provider for kubeconfig

Signed-off-by: Calum Murray <cmurray@redhat.com>

* feat: move server to use ClusterProvider interface

Signed-off-by: Calum Murray <cmurray@redhat.com>

* feat: authentication middleware works with cluster provider

Signed-off-by: Calum Murray <cmurray@redhat.com>

* fix: unit tests work after cluster provider changes

Signed-off-by: Calum Murray <cmurray@redhat.com>

* feat: add tool mutator to add cluster parameter

Signed-off-by: Calum Murray <cmurray@redhat.com>

* test: handle cluster parameter

Signed-off-by: Calum Murray <cmurray@redhat.com>

* fix: handle lazy init correctly

Signed-off-by: Calum Murray <cmurray@redhat.com>

* refactor: move to using multi-strategy ManagerProvider

Signed-off-by: Calum Murray <cmurray@redhat.com>

* feat: add contexts_list tool

Signed-off-by: Calum Murray <cmurray@redhat.com>

* refactor: make tool mutator generic between cluster/context naming

Signed-off-by: Calum Murray <cmurray@redhat.com>

* feat: introduce tool filter

Signed-off-by: Calum Murray <cmurray@redhat.com>

* refactor: use new ManagerProvider/mutator/filter within mcp server

Signed-off-by: Calum Murray <cmurray@redhat.com>

* fix(test): tests expect context parameter in tool defs

Signed-off-by: Calum Murray <cmurray@redhat.com>

* feat: auth handles multi-cluster case correctly

Signed-off-by: Calum Murray <cmurray@redhat.com>

* fix: small changes from local testing

Signed-off-by: Calum Murray <cmurray@redhat.com>

* chore: fix enum test

Signed-off-by: Calum Murray <cmurray@redhat.com>

* review: Multi Cluster support (#1)

* nit: rename contexts_list to configuration_contexts_list

Besides the conventional naming, it helps LLMs understand the context of the tool by providing a certain level of hierarchy.

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* fix(mcp): ToolMutator doesn't rely on magic strings

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* refactor(api): don't expose ManagerProvider to toolsets

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* test(mcp): configuration_contexts_list basic tests

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* test(toolsets): revert edge-case test

This test should not be touched.

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* test(toolsets): add specific metadata tests for multi-cluster

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* fix(mcp): ToolFilter doesn't rely on magic strings (partially)

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* test(api): IsClusterAware and IsTargetListProvider default values

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* test(mcp): revert unneeded changes in mcp_tools_test.go

Signed-off-by: Marc Nuri <marc@marcnuri.com>

---------

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* fix: always include configuration_contexts_list if contexts > 1

Signed-off-by: Calum Murray <cmurray@redhat.com>

* feat: include server urls in configuration_contexts_list

Signed-off-by: Calum Murray <cmurray@redhat.com>

---------

Signed-off-by: Calum Murray <cmurray@redhat.com>
Signed-off-by: Marc Nuri <marc@marcnuri.com>
Co-authored-by: Marc Nuri <marc@marcnuri.com>
2025-10-06 12:01:16 +02:00
Marc Nuri
b55f28b36e feat(mcp): events_list returns parseable YAML output (#346)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-26 11:01:21 +02:00
Marc Nuri
792d2f5b80 chore(lint): fix linting issues (#344)
* chore(lint): fix linting issues

Signed-off-by: Marc Nuri <marc@marcnuri.com>

* feat(ci): add linting to build and build-all-platforms target

Signed-off-by: Marc Nuri <marc@marcnuri.com>

---------

Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-26 06:56:48 +02:00
Marc Nuri
c69e90c70d fix(mcp): InputSchema schema with empty properties for no-arg tools (#341)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-25 11:54:07 +02:00
iamsudip
053fb2e31c feat(pods): add optional tail parameter to pod logs retrieval (#335)
* feat(pods): add tailLines parameter to pod logs retrieval with default 256 lines

Signed-off-by: iamsudip <sudip.maji@harness.io>

* address review comments

Signed-off-by: iamsudip <sudip.maji@harness.io>

* test(pods): add tailLines parameter to pod logs retrieval with default 256 lines

Signed-off-by: Marc Nuri <marc@marcnuri.com>

---------

Signed-off-by: iamsudip <sudip.maji@harness.io>
Signed-off-by: Marc Nuri <marc@marcnuri.com>
Co-authored-by: Marc Nuri <marc@marcnuri.com>
2025-09-25 09:17:53 +02:00
Marc Nuri
8af889bc8f test(mcp): refactor helm toolset tests (#333)
Refactor tests to new approach before adding more functionality.

Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-18 16:08:53 +02:00
Marc Nuri
6e29a2ada5 feat(pods): update metrics to comply with new API
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-18 07:07:46 +02:00
Marc Nuri
e16114dfc5 test(mcp): refactor core toolset tests (namespaces) (#330)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-17 15:48:57 +02:00
Marc Nuri
2bf6c549fe test(mcp): remove side-effects from toolsets tests (#329)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-17 12:06:33 +02:00
Marc Nuri
d6936f42d3 test(mcp): refactor events toolset tests (#328)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-17 11:48:35 +02:00
Marc Nuri
f496c643e7 test(mcp): refactor configuration toolset tests (#327)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-17 11:11:50 +02:00
Marc Nuri
d9d35b9834 test(toolsets): toolset specific metadata tests (#326)
- Refactor tests to use testify (more clarity+composability for complex tests)
- Tests for default toolsets
- Tests for configured, granular toolsets

Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-17 11:06:17 +02:00
Marc Nuri
48cf204a89 feat(toolsets): add support for multiple toolsets in configuration (#323)
Users can now enable or disable different toolsets either by providing
a command-line flag or by setting the toolsets array field in the TOML
configuration.

Downstream Kubernetes API developers can declare toolsets for their
APIs by creating a new nested package in pkg/toolsets and registering
it in pkg/mcp/modules.go

Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-17 10:53:56 +02:00
Marc Nuri
209e8434d5 feat(mcp): toolset definitions completely agnostic from underlying MCP impl (#322)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-12 11:56:22 +02:00
Marc Nuri
2b6c886d95 refactor(mcp): toolset Tools definition is agnostic of MCP impl (#319)
Initial PR to make the toolsets agnostic of the usd MCP implementation (migration to go-sdk).
The decoupling will also be needed to move the different toolsets to separate nested packages (toolsets).

Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-12 09:58:54 +02:00
Marc Nuri
ea641e6796 test(mcp): toolset metadata assertion (#318)
This test ensures that any tool definition refactoring
preserves the current behavior.

Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-11 10:31:39 +02:00
Samuel Masuy
6c573f31c8 feat(kubernetes): add support for previousPod container logs (#256)
Add 'previous' parameter to pods_log tool to retrieve logs from terminated containers, equivalent to kubectl logs --previous functionality.
This enables debugging of containers that have restarted due to crashes or updates.

Signed-off-by: Samuel Masuy <samuel.masuy@goto.com>
Co-authored-by: opencode <noreply@opencode.ai>
2025-09-11 09:29:51 +02:00
Marc Nuri
10c82f7bff refactor(toolsets): renamed Profile to Toolset (#309)
As a prior step to providing support for toolsets
this change repurposes the current work in profiles
which partially aligns with the toolsets expected features

Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-09-11 09:25:09 +02:00
Marc Nuri
1bd0b32976 test: misc fixes and typos (#284)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-08-26 15:38:05 +02:00
Marc Nuri
0ec2599bd8 fix:test: prevent usage of real cluster in tests (#282)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-08-26 14:52:27 +02:00
Marc Nuri
58c47dc95c refactor(auth): temporarily disable scope authorization (#254)
It's unclear how the scopes are going to be populated in the JWT.
Disable scope authorization for the time being.

Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-08-08 12:46:45 +03:00
Marc Nuri
cfc42b3bd3 test(auth): complete test scenarios for raw token and oidc (#248)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-08-07 16:04:12 +03:00
Marc Nuri
43744f2978 test: extract mock-server for reutilization (#247)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-08-07 15:32:20 +03:00
Marc Nuri
29b65fd565 fix: linting issues (#240)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-08-05 16:14:00 +03:00
Marc Nuri
9cc7192d4d feat(mcp): log tool call (hide sensitive HTTP headers) (#225)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-07-31 15:36:34 +02:00
Arda Güçlü
be80db1a01 feat(auth): introduce scoped based authorization
Signed-off-by: Arda Güçlü <aguclu@redhat.com>
2025-07-31 11:01:26 +02:00
Marc Nuri
49dcff3f21 feat(mcp): log tool call (HTTP headers) (#221)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-07-30 15:25:07 +02:00
Marc Nuri
cad863ff22 fix(migration): rebranded from manusa/kubernetes-mcp-server to containers/kubernetes-mcp-server (#202)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-07-25 09:53:04 +02:00
Marc Nuri
ca0aa4648d feat(mcp): log tool call (function name + arguments)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-07-22 14:35:19 +02:00
Marc Nuri
3fbfd8d7cb fix(lint): add golangci-lint make target + lint
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-07-22 14:22:19 +02:00
Arda Güçlü
73e9e845c4 refactor(auth): carry oidc provider directly instead of mcpServer 2025-07-18 12:52:51 +02:00
Marc Nuri
cb9f296566 test(mcp): speed up tests by not setting the fake kubeconfig master to example.com
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-07-18 10:46:32 +02:00
Marc Nuri
e4a8f604a1 test:fix: age expectation regex for minutes-no-seconds (42m)
Signed-off-by: Marc Nuri <marc@marcnuri.com>
2025-07-17 07:27:59 +02:00
Arda Güçlü
77671617df feat(auth): introduce OIDC token verification if authorization-url is specified (176)
Pass correct audience
---
Validate server and authorization url via url.Parse
---
Import go-oidc/v3
---
Wire initialized oidc provider if authorization url is set
---
Wire oidc issuer validation
2025-07-16 14:45:18 +02:00
Marc Nuri
5c753275ab test(mcp): refactor tool filtering tests
- Prevent declaring tools that are both read-only and destructive
- Remove redundant tests and preserve those behavioral and semantic
2025-07-14 11:36:01 +02:00
Arda Güçlü
275b91a00d feat(auth): introduce require-oauth flag to comply with OAuth in MCP specification (170)
Introduce require-oauth flag

When this flag is enabled, authorization middleware will be turned on.
When this flag is enabled, Derived which is generated based on the client
token will not be used.
---
Wire Authorization middleware to http mux

This commit adds authorization middleware. Additionally, this commit
rejects the requests if the bearer token is absent in Authorization
header of the request.
---
Add offline token validation for expiration and audience

Per Model Context Protocol specification, MCP Servers must check the
audience field of the token to ensure that they are generated specifically
for them.

This commits parses the JWT token and asserts that audience is correct
and token is not expired.
---
Add online token verification via TokenReview request to API Server

This commit sends online token verification by sending request to
TokenReview endpoint of API Server with the token and expected audience.

If API Server returns the status as authenticated, that means this token
can be used to generate a new ad hoc token for MCP Server.

If API Server returns the status as not authenticated, that means this token
is invalid and MCP Server returns 401 to force the client to initiate OAuth flow.
---
Serve oauth protected resource metadata endpoint
---
Introduce server-url to be represented in protected resource metadata
---
Add error return type in Derived function
---
Return error if error occurs in Derived, when require-oauth
---
Add test cases for authorization-url and server-url
---
Wire server-url to audience, if it is set
---
Remove redundant ssebaseurl parameter from http
2025-07-14 06:31:17 +02:00
Arda Güçlü
114726fb7c test(config): add new test case to increase the test coverage of Derived Config (167)
Add new unit tests to check the values in Derived config
---
Rely on kubeconfig in staticConfig instead of a separate but equal one
2025-07-08 06:07:18 +02:00
Arda Güçlü
9ffb818ab2 feat(auht): accept standard oauth authorization header by keeping the current header 2025-07-03 06:57:42 +02:00
Arda Güçlü
524e4f5d2a feat(http): introduce middleware for audit logs and authentication checks (157)
Introduce wrapper middleware to intercept http requests
---
Rename middleware to http
2025-07-02 15:08:17 +02:00
Arda Güçlü
e6b19034aa feat(mcp): serve sse and streamable from a single port 2025-07-02 14:04:18 +02:00
Arda Güçlü
186f445ca2 feat(config): introduce enabled/disabled tool list in configuration file (155)
Introduce allow/deny tool functionality in toml config
---
Remove duplicate fields that already defined in staticConfig
---
Add unit tests to verify tool valid check
---
Wire staticConfig to fix unit tests
---
Rename to enabled/disabled instead of allowed/denied
2025-07-01 16:02:36 +02:00
Marc Nuri
af2a8cd19d feat(config): deny resources by using RESTMapper as an interceptor (149)
feat(config): deny resources by using RESTMapper as an interceptor

This approach ensures that resources in the deny list are **always**
processed regardless of the implementation.

The RESTMapper takes care of verifying that the requested Group Version Kind
complies with the deny list while checking for the REST endpoint.
---
feat(config): provide a limited clientset which check access
---
review: addressed PR comments
---
feat(config): provide a limited metrics clientset to check access
---
review: addressed PR comments regarding pods_exec
2025-07-01 14:44:22 +02:00
Marc Nuri
1968652aca test(config): extensive test suite for denied lists 2025-06-23 13:09:02 +02:00
Marc Nuri
f3915cd13e test(profiles): add missing pods_top to full profile tools validation 2025-06-20 16:41:17 +02:00
Arda Güçlü
bca2cda21a fix(mcp): gracefully cast tool call params objects and return err instead of panic 2025-06-20 15:32:13 +02:00
Arda Güçlü
754da19d81 feat(config): introduce toml configuration file with a set of deny list 2025-06-19 13:41:47 +02:00
Marc Nuri
25608daf4a fix(kubernetes): remove unneeded CacheInvalidate() method (127)
fix(kubernetes): remove unneeded CacheInvalidate() method
---
test(output): improve age regex
---
test(kubernetes): remove unneeded CacheInvalidate() method (mutex lock)
---
test(kubernetes): split TestPodsTop to avoid discovery client cache issues
2025-06-18 12:51:09 +02:00
Marc Nuri
f138b06ba8 refactor(kubernetes): force usage of Derived kubernetes (125)
refactor(kubernetes): force usage of Derived kubernetes

Prevents consumers of the kubernetes package the usage of
public methods on a non-derived config instance.
---
review(kubernetes): force usage of Derived kubernetes

Addresses comment by ardaguclu
2025-06-18 06:46:05 +02:00
Arda Güçlü
4a3ff2f2ce refactor(mcp): use k8s.io/utils ptr.Deref instead of a custom func 2025-06-18 05:10:29 +02:00