Files
cleveragents-core/features/mcp_lifecycle.feature
T
freemo 81c2878ec8
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 17s
CI / helm (pull_request) Successful in 22s
CI / quality (pull_request) Successful in 34s
CI / lint (pull_request) Successful in 3m19s
CI / typecheck (pull_request) Successful in 4m6s
CI / security (pull_request) Successful in 4m7s
CI / unit_tests (pull_request) Successful in 7m4s
CI / integration_tests (pull_request) Successful in 7m11s
CI / docker (pull_request) Successful in 1m35s
CI / coverage (pull_request) Failing after 8m51s
CI / e2e_tests (pull_request) Failing after 17m45s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-regression (pull_request) Successful in 54m58s
feat(mcp): implement lazy start/auto-stop and sandbox path rewriting for MCP tools
Add lifecycle management and sandbox support for MCP tools:

- McpClient: lazy start (server starts on first call_tool()),
  configurable idle timeout with auto-stop, health monitoring
  with automatic restart on server crash
- McpRegistry: namespace-isolated tracking of multiple MCP servers
  with independent lifecycles
- SandboxPathRewriter: bi-directional file path rewriting between
  host and sandbox workspaces using PathMapper
- MCPCapabilityMetadata: structured exposure of full MCP server
  capabilities (tools, resources, prompts)
- MCPToolDescriptor: extended with annotations field
- MCPToolAdapter: capability_metadata property, enhanced source_metadata
  with server capabilities and tool annotations

BDD scenarios:
- 16 lifecycle scenarios (lazy start, auto-stop, health check, registry)
- 10 sandbox path rewriting scenarios (arguments, responses, roundtrip)
- All 42 existing MCP adapter scenarios continue to pass

ISSUES CLOSED: #938
2026-03-30 22:42:15 +00:00

161 lines
7.0 KiB
Gherkin

Feature: MCP Server Lifecycle Management
As an actor runtime
I want MCP servers to start lazily and stop when idle
So that resources are used efficiently and server management is automatic
# -------------------------------------------------------------------
# Lazy Start
# -------------------------------------------------------------------
Scenario: MCP server starts on first tool call (lazy start)
Given an MCP client config for "github" with lazy start enabled
And a mock MCP transport with tool "list_repos"
When I create an MCP client
Then the MCP client state should be "idle"
And the MCP client should not be connected
When I call MCP tool "list_repos" with arguments {}
Then the MCP client should be connected
And the MCP client state should be "running"
Scenario: MCP server does not start without tool call when lazy start enabled
Given an MCP client config for "github" with lazy start enabled
And a mock MCP transport with tool "list_repos"
When I create an MCP client
Then the MCP client should not be connected
Scenario: Explicit start works with lazy start enabled
Given an MCP client config for "github" with lazy start enabled
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I explicitly start the MCP client
Then the MCP client should be connected
And the MCP client state should be "running"
Scenario: Tool call fails when lazy start disabled and not started
Given an MCP client config for "github" with lazy start disabled
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I call MCP tool "list_repos" expecting a runtime error
Then the MCP client error should mention "not started"
Scenario: Explicit start is idempotent
Given an MCP client config for "github" with lazy start enabled
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I explicitly start the MCP client
And I explicitly start the MCP client
Then the MCP client should be connected
# -------------------------------------------------------------------
# Auto-Stop
# -------------------------------------------------------------------
Scenario: MCP server auto-stops after idle timeout
Given an MCP client config for "github" with idle timeout 0.15 seconds
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I call MCP tool "list_repos" with arguments {}
And I wait 0.5 seconds
Then the MCP client state should be "stopped"
And the MCP client should not be connected
Scenario: Activity resets idle timer
Given an MCP client config for "github" with idle timeout 0.5 seconds
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I call MCP tool "list_repos" with arguments {}
And I wait 0.25 seconds
And I call MCP tool "list_repos" with arguments {}
And I wait 0.25 seconds
Then the MCP client should be connected
Scenario: Auto-stop disabled when timeout is zero
Given an MCP client config for "github" with idle timeout 0.0 seconds
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I call MCP tool "list_repos" with arguments {}
And I wait 0.15 seconds
Then the MCP client should be connected
# -------------------------------------------------------------------
# Shutdown
# -------------------------------------------------------------------
Scenario: Explicit shutdown stops the server
Given an MCP client config for "github" with lazy start enabled
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I call MCP tool "list_repos" with arguments {}
And I shutdown the MCP client
Then the MCP client state should be "stopped"
And the MCP client should not be connected
Scenario: Double shutdown is safe
Given an MCP client config for "github" with lazy start enabled
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I call MCP tool "list_repos" with arguments {}
And I shutdown the MCP client
And I shutdown the MCP client
Then the MCP client state should be "stopped"
# -------------------------------------------------------------------
# Health Monitoring
# -------------------------------------------------------------------
Scenario: Health check detects crash and auto-restarts
Given an MCP client config for "github" with health check interval 0.15 seconds
And a mock MCP transport with tool "list_repos" that crashes after 1 call
When I create an MCP client
And I call MCP tool "list_repos" with arguments {}
And I wait 1.0 seconds
Then the MCP client restart count should be greater than 0
Scenario: Health check disabled when interval is zero
Given an MCP client config for "github" with health check interval 0.0 seconds
And a mock MCP transport with tool "list_repos"
When I create an MCP client
And I call MCP tool "list_repos" with arguments {}
Then the MCP client health check failures should be 0
# -------------------------------------------------------------------
# Registry (Multiple Servers)
# -------------------------------------------------------------------
Scenario: Multiple MCP servers with independent lifecycles
Given an MCP registry
And an MCP client config for "github" with lazy start enabled
And a mock MCP transport with tool "list_repos"
When I register the MCP client in namespace "gh"
And I register another MCP client config for "jira" in namespace "jira"
Then the MCP registry should have 2 namespaces
And MCP namespace "gh" should not be connected
And MCP namespace "jira" should not be connected
Scenario: Registry call_tool starts specific server lazily
Given an MCP registry
And an MCP client config for "github" with lazy start enabled
And a mock MCP transport with tool "list_repos"
When I register the MCP client in namespace "gh"
And I call tool "list_repos" on MCP namespace "gh" with arguments {}
Then MCP namespace "gh" should be connected
Scenario: Registry shutdown_all stops all servers
Given an MCP registry with 2 running servers
When I shutdown all MCP servers
Then the MCP registry should have 2 namespaces
And all MCP servers should be stopped
# -------------------------------------------------------------------
# Capability Metadata
# -------------------------------------------------------------------
Scenario: Full capability metadata exposed after connect
Given an MCP client config for "github" with lazy start enabled
And a mock MCP transport with full capabilities
When I create an MCP client
And I explicitly start the MCP client
Then the MCP adapter capability metadata should have tools true
And the MCP adapter capability metadata should have resources true
And the MCP adapter capability metadata should have prompts true