Skip to content

feat: add MCP server endpoint for dynamic tool discovery and invocation#123

Closed
syn-zhu wants to merge 1 commit intokagent-dev:mainfrom
syn-zhu:feat/mcp-server-endpoint
Closed

feat: add MCP server endpoint for dynamic tool discovery and invocation#123
syn-zhu wants to merge 1 commit intokagent-dev:mainfrom
syn-zhu:feat/mcp-server-endpoint

Conversation

@syn-zhu
Copy link

@syn-zhu syn-zhu commented Feb 26, 2026

Summary

Adds a Streamable HTTP MCP server endpoint to the kmcp controller, enabling agents to dynamically discover, introspect, and invoke tools on any MCPServer in the cluster at runtime. This mirrors the pattern already established by kagent-controller's A2A MCP endpoint (list_agents / invoke_agent) but for MCP server interactions.

Closes #122

New tools exposed at :8083/mcp

Tool Purpose
list_mcp_servers List MCPServer CRs (name, namespace, status, port, transport type)
list_tools Connect to a specific MCPServer and return its tool catalog
call_tool Invoke a specific tool on a specific MCPServer and return the result

Changes

  • pkg/mcp/handler.go — MCP handler implementing the three tools with session caching and automatic reconnection on stale sessions
  • pkg/mcp/server.go — HTTP server wrapper implementing manager.Runnable for controller-runtime lifecycle integration
  • pkg/app/app.go--mcp-bind-address flag (default :8083, set to 0 to disable) and MCP server wiring
  • go.mod — Added github.com/modelcontextprotocol/go-sdk v1.2.0 (same version as kagent)
  • Helm chart — MCP server values, deployment port, mcp-service.yaml (ClusterIP)

Tests

  • pkg/mcp/handler_test.go — 16 unit tests covering:
    • list_mcp_servers: empty cluster, multi-namespace listing, namespace filtering, mixed ready/not-ready, default port
    • list_tools validation: invalid ref format, server not found
    • call_tool validation: missing tool name, invalid ref, server not found
    • getMCPServer helper: valid lookup, invalid format, non-existent
    • mcpServerURL derivation: stdio/http transport, custom path, default port
  • pkg/mcp/server_test.go — 2 tests covering server start/shutdown lifecycle and construction

Test plan

  • go build ./... — compiles cleanly
  • go vet ./... — no issues
  • go test ./pkg/mcp/... — all 18 tests pass
  • helm template test helm/kmcp/ — renders correctly with MCP port, args, and service
  • E2E: Deploy to cluster, port-forward to MCP service, verify list_mcp_servers / list_tools / call_tool work

🤖 Generated with Claude Code

Add a Streamable HTTP MCP server endpoint to the kmcp controller,
enabling agents to dynamically discover, introspect, and invoke tools
on any MCPServer in the cluster at runtime. This mirrors the pattern
already established by kagent-controller's A2A MCP endpoint
(list_agents / invoke_agent) but for MCP server interactions.

New tools exposed at :8083/mcp:
- list_mcp_servers: List MCPServer CRs (name, namespace, status, port)
- list_tools: Connect to a specific MCPServer and return its tool catalog
- call_tool: Invoke a specific tool on a specific MCPServer

Includes:
- MCP handler with session caching and automatic reconnection
- HTTP server wrapper implementing manager.Runnable
- --mcp-bind-address flag (default :8083, set to 0 to disable)
- Helm chart updates (values, deployment port, MCP service)
- Comprehensive unit tests (18 test cases)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Simon Zhu <simon.zhu@mongodb.com>
@syn-zhu syn-zhu force-pushed the feat/mcp-server-endpoint branch from 326a8ef to 5446928 Compare February 26, 2026 07:28
@EItanya
Copy link
Contributor

EItanya commented Feb 26, 2026

Hey there, I really love this idea, but I think we should put this in kagent. kmcp only deals with the MCPServer CRD and is really mostly about deployment. If we do this in kagent then we can also do this for the Services and RemoteMCPServers. What do you think?

@syn-zhu
Copy link
Author

syn-zhu commented Feb 26, 2026

Hey there, I really love this idea, but I think we should put this in kagent. kmcp only deals with the MCPServer CRD and is really mostly about deployment. If we do this in kagent then we can also do this for the Services and RemoteMCPServers. What do you think?

Lemme take a look, just need to remind myself; the kagent controller already knows about RemoteMCPServers? If so then yeah, i think that makes sense

syn-zhu added a commit to syn-zhu/kagent that referenced this pull request Mar 5, 2026
Adds three new MCP tools to the kagent-controller's existing MCP endpoint
at :8083/mcp, enabling dynamic discovery and invocation of tools across
all tool source types:

- list_tool_servers: Lists all tool servers (RemoteMCPServer, Service
  with kagent.dev/mcp-service=true label, MCPServer CRs)
- list_tools: Connects to a tool server and returns its tool catalog
- call_tool: Invokes a specific tool on a specific tool server

This moves the functionality originally proposed in kagent-dev/kmcp#123
into kagent per reviewer feedback, since kagent already watches all three
resource types and has the existing MCP handler infrastructure.

Key design decisions:
- Unified ref format: Kind/namespace/name (e.g. RemoteMCPServer/default/my-server)
- Session caching with evict-and-retry for stale connections
- Reuses existing ConvertServiceToRemoteMCPServer and
  ConvertMCPServerToRemoteMCPServer from the translator package
- MCPServer CRD is optional (graceful degradation if not installed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@syn-zhu
Copy link
Author

syn-zhu commented Mar 5, 2026

Moved this to kagent per @EItanya's feedback — the implementation now lives in kagent-dev/kagent#1437, which adds the same three tools (list_tool_servers, list_tools, call_tool) to kagent's existing MCP handler alongside list_agents / invoke_agent.

The key improvement from moving to kagent: unified discovery across all tool source types (RemoteMCPServer, Service with kagent.dev/mcp-service=true, and MCPServer CRs), not just MCPServer.

@syn-zhu syn-zhu closed this Mar 5, 2026
syn-zhu added a commit to syn-zhu/kagent that referenced this pull request Mar 5, 2026
Adds three new MCP tools to the kagent-controller's existing MCP endpoint
at :8083/mcp, enabling dynamic discovery and invocation of tools across
all tool source types:

- list_tool_servers: Lists all tool servers (RemoteMCPServer, Service
  with kagent.dev/mcp-service=true label, MCPServer CRs)
- list_tools: Connects to a tool server and returns its tool catalog
- call_tool: Invokes a specific tool on a specific tool server

This moves the functionality originally proposed in kagent-dev/kmcp#123
into kagent per reviewer feedback, since kagent already watches all three
resource types and has the existing MCP handler infrastructure.

Key design decisions:
- Unified ref format: Kind/namespace/name (e.g. RemoteMCPServer/default/my-server)
- Session caching with evict-and-retry for stale connections
- Reuses existing ConvertServiceToRemoteMCPServer and
  ConvertMCPServerToRemoteMCPServer from the translator package
- MCPServer CRD is optional (graceful degradation if not installed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
syn-zhu added a commit to syn-zhu/kagent that referenced this pull request Mar 5, 2026
Adds three new MCP tools to the kagent-controller's existing MCP endpoint
at :8083/mcp, enabling dynamic discovery and invocation of tools across
all tool source types:

- list_tool_servers: Lists all tool servers (RemoteMCPServer, Service
  with kagent.dev/mcp-service=true label, MCPServer CRs)
- list_tools: Connects to a tool server and returns its tool catalog
- call_tool: Invokes a specific tool on a specific tool server

This moves the functionality originally proposed in kagent-dev/kmcp#123
into kagent per reviewer feedback, since kagent already watches all three
resource types and has the existing MCP handler infrastructure.

Key design decisions:
- Unified ref format: Kind/namespace/name (e.g. RemoteMCPServer/default/my-server)
- Session caching with evict-and-retry for stale connections
- Reuses existing ConvertServiceToRemoteMCPServer and
  ConvertMCPServerToRemoteMCPServer from the translator package
- MCPServer CRD is optional (graceful degradation if not installed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Simon Zhu <simon.zhu@mongodb.com>
syn-zhu added a commit to syn-zhu/kagent that referenced this pull request Mar 5, 2026
Adds three new MCP tools to the kagent-controller's existing MCP endpoint
at :8083/mcp, enabling dynamic discovery and invocation of tools across
all tool source types:

- list_tool_servers: Lists all tool servers (RemoteMCPServer, Service
  with kagent.dev/mcp-service=true label, MCPServer CRs)
- list_tools: Connects to a tool server and returns its tool catalog
- call_tool: Invokes a specific tool on a specific tool server

This moves the functionality originally proposed in kagent-dev/kmcp#123
into kagent per reviewer feedback, since kagent already watches all three
resource types and has the existing MCP handler infrastructure.

Key design decisions:
- Unified ref format: Kind/namespace/name (e.g. RemoteMCPServer/default/my-server)
- Session caching with evict-and-retry for stale connections
- Reuses existing ConvertServiceToRemoteMCPServer and
  ConvertMCPServerToRemoteMCPServer from the translator package
- MCPServer CRD is optional (graceful degradation if not installed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Simon Zhu <simon.zhu@mongodb.com>
syn-zhu added a commit to syn-zhu/kagent that referenced this pull request Mar 5, 2026
Adds three new MCP tools to the kagent-controller's existing MCP endpoint
at :8083/mcp, enabling dynamic discovery and invocation of tools across
all tool source types:

- list_tool_servers: Lists all tool servers (RemoteMCPServer, Service
  with kagent.dev/mcp-service=true label, MCPServer CRs)
- list_tools: Connects to a tool server and returns its tool catalog
- call_tool: Invokes a specific tool on a specific tool server

This moves the functionality originally proposed in kagent-dev/kmcp#123
into kagent per reviewer feedback, since kagent already watches all three
resource types and has the existing MCP handler infrastructure.

Key design decisions:
- Unified ref format: Kind/namespace/name (e.g. RemoteMCPServer/default/my-server)
- Session caching with evict-and-retry for stale connections
- Reuses existing ConvertServiceToRemoteMCPServer and
  ConvertMCPServerToRemoteMCPServer from the translator package
- MCPServer CRD is optional (graceful degradation if not installed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Simon Zhu <simon.zhu@mongodb.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add MCP server endpoint for dynamic tool discovery and invocation

2 participants