-
Notifications
You must be signed in to change notification settings - Fork 772
Example of elicitation for MCP cloud #493
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Deploying the elicitation example to the cloud | ||
|
||
In `mcp_agent.secrets.yaml`, set your OpenAI `api_key`. | ||
|
||
Then, in the current directory (`cloud`), run: | ||
|
||
```bash | ||
uv run mcp-agent deploy elicitation --config-dir . | ||
``` | ||
|
||
Once deployed, you should see an app ID, and a URL in the output. | ||
You can use the URL to access the MCP via e.g. the [MCP Inspector](https://github.com/modelcontextprotocol/inspector). | ||
Add `/sse` to the end of the url, as the MCP is exposed as a server-sent events endpoint. | ||
Do not forget to add an authorization header with your MCP-agent API key as the bearer token. | ||
|
||
The app ID can be used to delete the example again afterward: | ||
|
||
```bash | ||
uv run mcp-agent cloud app delete --id=<app-id> | ||
``` |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,55 @@ | ||||||
import asyncio | ||||||
import logging | ||||||
import sys | ||||||
|
||||||
from mcp.server.fastmcp import FastMCP, Context | ||||||
from mcp.server.elicitation import ( | ||||||
AcceptedElicitation, | ||||||
DeclinedElicitation, | ||||||
CancelledElicitation, | ||||||
) | ||||||
from pydantic import BaseModel, Field | ||||||
from mcp_agent.app import MCPApp | ||||||
from mcp_agent.server.app_server import create_mcp_server_for_app | ||||||
from mcp_agent.executor.workflow import Workflow, WorkflowResult | ||||||
from temporalio import workflow | ||||||
|
||||||
# Initialize logging | ||||||
logging.basicConfig(level=logging.INFO) | ||||||
logger = logging.getLogger(__name__) | ||||||
|
||||||
app = MCPApp( | ||||||
name="elicitation_demo", | ||||||
description="Demo of workflow with elicitation" | ||||||
) | ||||||
|
||||||
|
||||||
# mcp_context for fastmcp context | ||||||
@app.tool() | ||||||
async def book_table(date: str, party_size: int, app_ctx: Context) -> str: | ||||||
"""Book a table with confirmation""" | ||||||
|
||||||
# Schema must only contain primitive types (str, int, float, bool) | ||||||
class ConfirmBooking(BaseModel): | ||||||
confirm: bool = Field(description="Confirm booking?") | ||||||
notes: str = Field(default="", description="Special requests") | ||||||
|
||||||
app.logger.info(f"Confirming the use wants to book a table for {party_size} on {date} via elicitation") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a typo in the log message:
Suggested change
Spotted by Diamond |
||||||
|
||||||
result = await app.context.upstream_session.elicit( | ||||||
message=f"Confirm booking for {party_size} on {date}?", | ||||||
requestedSchema=ConfirmBooking.model_json_schema(), | ||||||
) | ||||||
|
||||||
app.logger.info(f"Result from confirmation: {result}") | ||||||
|
||||||
if result.action == "accept": | ||||||
data = ConfirmBooking.model_validate(result.content) | ||||||
if data.confirm: | ||||||
return f"Booked! Notes: {data.notes or 'None'}" | ||||||
return "Booking cancelled" | ||||||
elif result.action == "decline": | ||||||
return "Booking declined" | ||||||
elif result.action == "cancel": | ||||||
return "Booking cancelled" | ||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing return statement for the function. The book_table function can reach the end without returning a value when result.action is not 'accept', 'decline', or 'cancel'. This will cause the function to return None instead of a string, violating the return type annotation and potentially causing runtime errors in calling code that expects a string. Add a default return statement like 'return "Unknown action"' at the end of the function.
Suggested change
Spotted by Diamond |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,15 @@ | ||||||
$schema: ../../schema/mcp-agent.config.schema.json | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainConfirm From this file’s location, If it lives at repo-root -$schema: ../../schema/mcp-agent.config.schema.json
+$schema: ../../../../schema/mcp-agent.config.schema.json 🏁 Script executed: #!/bin/bash
# Show where the config schema actually lives
fd -a 'mcp-agent.config.schema.json' -S -HI Length of output: 137 🏁 Script executed: #!/bin/bash
# Search for the schema file and compute relative path from the YAML file's directory.
yaml_path="examples/mcp/mcp_elicitation/cloud/mcp_agent.config.yaml"
schema_name="mcp-agent.config.schema.json"
echo "PWD: $(pwd)"
echo "Looking for $schema_name..."
# 1) try find
echo "Using find..."
find . -type f -name "$schema_name" -print 2>/dev/null || true
# 2) try fd (if available) with correct separate flags
if command -v fd >/dev/null 2>&1; then
echo "Using fd..."
fd -H -I -S "$schema_name" || true
fi
# 3) try rg to list files then filter
if command -v rg >/dev/null 2>&1; then
echo "Using rg..."
rg --files | rg -nF "$schema_name" || true
fi
# Compute relative path(s) from YAML dir to each match (if any)
echo "Computing relative path(s) from $(dirname "$yaml_path") to matches..."
matches=$(find . -type f -name "$schema_name" -print 2>/dev/null || true)
if [ -n "$matches" ]; then
while IFS= read -r f; do
python - <<PY
import os
yaml_dir=os.path.normpath(os.path.dirname("$yaml_path"))
schema=os.path.normpath("$f")
print("FOUND:", schema)
print("RELATIVE_PATH:", os.path.relpath(schema, yaml_dir))
PY
done <<< "$matches"
else
echo "No matches found."
fi Length of output: 558 Fix $schema path in examples/mcp/mcp_elicitation/cloud/mcp_agent.config.yaml. Schema is at schema/mcp-agent.config.schema.json; correct relative path from this YAML is ../../../../schema/mcp-agent.config.schema.json. -$schema: ../../schema/mcp-agent.config.schema.json
+$schema: ../../../../schema/mcp-agent.config.schema.json 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||
|
||||||
execution_engine: asyncio | ||||||
logger: | ||||||
transports: [file] | ||||||
level: debug | ||||||
path_settings: | ||||||
path_pattern: "logs/mcp-agent-{unique_id}.jsonl" | ||||||
unique_id: "timestamp" # Options: "timestamp" or "session_id" | ||||||
timestamp_format: "%Y%m%d_%H%M%S" | ||||||
|
||||||
openai: | ||||||
# Secrets (API keys, etc.) are stored in an mcp_agent.secrets.yaml file which can be gitignored | ||||||
# default_model: "o3-mini" | ||||||
default_model: "gpt-4o-mini" |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,7 @@ | ||||
$schema: ../../schema/mcp-agent.config.schema.json | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 🧩 Analysis chainSchema reference likely incorrect for a secrets file.
Apply this diff to remove it pending confirmation: -$schema: ../../schema/mcp-agent.config.schema.json 🏁 Script executed: #!/bin/bash
# Verify if a secrets schema exists and confirm the correct relative path
fd -a 'mcp-agent.*schema.json' -S -HI Length of output: 137 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== schema files (case-insensitive) ==="
find . -type f -iname "*schema*.json" -print || true
echo
echo "=== files with 'mcp-agent' in name ==="
find . -type f -iname "*mcp-agent*.json" -print || true
echo
echo "=== files with 'secrets' and 'schema' in name ==="
find . -type f -iname "*secrets*schema*.json" -print || true
echo
echo "=== show target example file ==="
if [ -f "examples/mcp/mcp_elicitation/cloud/mcp_agent.secrets.yaml.example" ]; then
echo "FOUND: examples/mcp/mcp_elicitation/cloud/mcp_agent.secrets.yaml.example"
sed -n '1,200p' examples/mcp/mcp_elicitation/cloud/mcp_agent.secrets.yaml.example
else
echo "MISSING: examples/mcp/mcp_elicitation/cloud/mcp_agent.secrets.yaml.example"
fi
echo
echo "=== listing 'schema' directory (if any) ==="
[ -d "schema" ] && ls -la schema || echo "schema directory not present" Length of output: 681 Remove $schema from secrets example This secrets example references the config schema (schema/mcp-agent.config.schema.json); there is no separate secrets schema — remove the $schema line to avoid false validation errors. File: examples/mcp/mcp_elicitation/cloud/mcp_agent.secrets.yaml.example — line 1 -$schema: ../../schema/mcp-agent.config.schema.json 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||
|
||||
openai: | ||||
api_key: openai_api_key | ||||
|
||||
anthropic: | ||||
api_key: anthropic_api_key |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Core framework dependency | ||
mcp-agent | ||
|
||
# Additional dependencies specific to this example | ||
anthropic | ||
openai | ||
Comment on lines
+2
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 🧩 Analysis chainPin and lock dependencies for reproducible cloud deploys. Unpinned deps can break the example at deploy time. Prefer constraints or a uv lockfile. 🌐 Web query:
💡 Result:
Sources: Pin dependencies for reproducible cloud deploys — examples/mcp/mcp_elicitation/cloud/requirements.txt (lines 2–6): pin mcp-agent==0.1.17 (uploaded Sep 5, 2025), openai==1.104.2 (Sep 2, 2025), anthropic==0.66.0 (Sep 3, 2025). Prefer adding a constraints file or a checked-in lockfile for reproducible deploys. 🤖 Prompt for AI Agents
|
Uh oh!
There was an error while loading. Please reload this page.