Skip to content

Commit 13e4f9d

Browse files
JAORMXclaude
andcommitted
Enhance Virtual MCP proposal with elicitation and composite tool patterns
Add MCP elicitation support to composite tools, enabling interactive workflows with human-in-the-loop confirmations. Include state persistence strategy for long-running workflows and demonstrate reusing single tools with different parameters through incident investigation example. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 807713b commit 13e4f9d

File tree

1 file changed

+106
-3
lines changed

1 file changed

+106
-3
lines changed

docs/proposals/virtual-mcp-server.md

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,99 @@ backend_auth:
9090
# Composite tools (Phase 2)
9191
composite_tools:
9292
- name: "deploy_and_notify"
93-
description: "Deploy PR and notify team"
93+
description: "Deploy PR with user confirmation and notification"
9494
parameters:
9595
pr_number: {type: "integer"}
9696
steps:
9797
- id: "merge"
9898
tool: "github.merge_pr"
9999
arguments: {pr: "{{.params.pr_number}}"}
100100

101+
# Elicitation step for user confirmation
102+
- id: "confirm_deploy"
103+
type: "elicitation"
104+
message: "PR {{.params.pr_number}} merged successfully. Proceed with deployment?"
105+
schema:
106+
type: "object"
107+
properties:
108+
environment:
109+
type: "string"
110+
enum: ["staging", "production"]
111+
enumNames: ["Staging", "Production"]
112+
description: "Target deployment environment"
113+
notify_team:
114+
type: "boolean"
115+
default: true
116+
description: "Send Slack notification to team"
117+
required: ["environment"]
118+
depends_on: ["merge"]
119+
on_decline:
120+
action: "skip_remaining"
121+
on_cancel:
122+
action: "abort"
123+
124+
- id: "deploy"
125+
tool: "kubernetes.deploy"
126+
arguments:
127+
pr: "{{.params.pr_number}}"
128+
environment: "{{.steps.confirm_deploy.content.environment}}"
129+
depends_on: ["confirm_deploy"]
130+
condition: "{{.steps.confirm_deploy.action == 'accept'}}"
131+
101132
- id: "notify"
102133
tool: "slack.send"
103-
arguments: {text: "Deployed PR {{.params.pr_number}}"}
104-
depends_on: ["merge"]
134+
arguments:
135+
text: "Deployed PR {{.params.pr_number}} to {{.steps.confirm_deploy.content.environment}}"
136+
depends_on: ["deploy"]
137+
condition: "{{.steps.confirm_deploy.content.notify_team}}"
138+
```
139+
140+
#### Example: Incident Investigation Using Multiple Fetch Calls
141+
142+
This composite tool demonstrates calling the same backend tool (`fetch`) multiple times with different static URLs to gather incident data from various monitoring sources:
143+
144+
```yaml
145+
composite_tools:
146+
- name: "investigate_incident"
147+
description: "Gather logs and metrics from multiple sources for incident analysis"
148+
parameters:
149+
incident_id: {type: "string"}
150+
time_range: {type: "string", default: "1h"}
151+
steps:
152+
- id: "fetch_app_logs"
153+
tool: "fetch.fetch"
154+
arguments:
155+
url: "https://logs.company.com/api/query?service=app&time={{.params.time_range}}"
156+
157+
- id: "fetch_error_metrics"
158+
tool: "fetch.fetch"
159+
arguments:
160+
url: "https://metrics.company.com/api/errors?time={{.params.time_range}}"
161+
162+
- id: "fetch_trace_data"
163+
tool: "fetch.fetch"
164+
arguments:
165+
url: "https://tracing.company.com/api/traces?time={{.params.time_range}}"
166+
167+
- id: "fetch_infra_status"
168+
tool: "fetch.fetch"
169+
arguments:
170+
url: "https://monitoring.company.com/api/infrastructure/status"
171+
172+
- id: "create_report"
173+
tool: "jira.create_issue"
174+
arguments:
175+
title: "Incident {{.params.incident_id}} Analysis"
176+
description: |
177+
Application Logs: {{.steps.fetch_app_logs.output}}
178+
Error Metrics: {{.steps.fetch_error_metrics.output}}
179+
Trace Data: {{.steps.fetch_trace_data.output}}
180+
Infrastructure: {{.steps.fetch_infra_status.output}}
181+
```
182+
183+
This pattern allows a single generic `fetch` tool to be reused with different static endpoints, creating a purpose-built incident investigation workflow without needing separate tools for each data source.
105184

185+
```yaml
106186
# Operational settings
107187
operational:
108188
timeouts:
@@ -162,6 +242,23 @@ Routes MCP protocol requests to appropriate backends:
162242
- Prompt requests handled similarly
163243
- Load balancing for duplicate capabilities
164244

245+
#### 6. Elicitation Support in Composite Tools
246+
247+
Composite tools can include elicitation steps to request additional information from users during workflow execution, following the [MCP elicitation specification](https://modelcontextprotocol.io/specification/2025-06-18/client/elicitation). This enables:
248+
249+
- **Interactive workflows**: Request user input between steps
250+
- **Safety confirmations**: Require approval before destructive operations
251+
- **Dynamic parameters**: Gather context-dependent information
252+
- **Conditional execution**: Branch workflow based on user responses
253+
254+
Elicitation steps use JSON Schema to define the structure of requested data (limited to flat objects with primitive properties). The Virtual MCP server forwards elicitation requests to the client and captures responses in three forms:
255+
256+
- **accept**: User provided data (accessible via `{{.steps.step_id.content}}`)
257+
- **decline**: User explicitly rejected the request
258+
- **cancel**: User dismissed without choosing
259+
260+
Subsequent steps can reference elicitation results through template expansion and use the `condition` field to execute conditionally based on user responses. The `on_decline` and `on_cancel` handlers control workflow behavior for non-acceptance scenarios.
261+
165262
### CLI Usage
166263

167264
```bash
@@ -191,6 +288,7 @@ thv virtual --group engineering-team \
191288

192289
**Phase 2**: Advanced features
193290
- Composite tool execution
291+
- Elicitation support in composite tools
194292
- Per-backend authentication strategies
195293
- Token exchange support
196294
- Failover and load balancing
@@ -220,6 +318,7 @@ The implementation will maximize reuse of existing ToolHive components:
220318
3. **Groups**: Use `groups.Manager` for group operations
221319
4. **Workloads**: Use `workloads.Manager` for workload discovery
222320
5. **Authentication**: Extend existing auth middleware patterns
321+
6. **Elicitation**: Implement MCP elicitation protocol for composite tool user interaction
223322

224323
### Authentication Complexity
225324

@@ -231,6 +330,10 @@ Different MCP servers may have vastly different authentication requirements:
231330

232331
The Virtual MCP must handle this complexity transparently, maintaining separate authentication contexts per backend while presenting a unified interface to clients.
233332

333+
### Composite Tool State Persistence
334+
335+
Composite tools with elicitation require state persistence to handle long-running workflows that span multiple user interactions. The Virtual MCP will maintain workflow execution state (current step, completed steps, elicitation responses, and template variables) in memory with a clean storage interface to enable future migration to persistent backends. Each composite tool invocation receives a unique workflow ID, and the server checkpoints state after each step completion and elicitation interaction. Workflows have a default timeout of 30 minutes, after which they are automatically cleaned up and any pending elicitations are treated as cancelled. This approach keeps the implementation simple for Phase 2 while establishing patterns that can scale to distributed persistence later.
336+
234337
## Alternative Approaches Considered
235338

236339
1. **Kubernetes CRD**: More complex, requires operator changes

0 commit comments

Comments
 (0)