mcp-use 1.3.5__tar.gz → 1.3.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mcp-use might be problematic. Click here for more details.
- mcp_use-1.3.7/.github/workflows/publish.yml +81 -0
- mcp_use-1.3.7/.github/workflows/tests.yml +95 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/PKG-INFO +8 -3
- {mcp_use-1.3.5 → mcp_use-1.3.7}/README.md +6 -1
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/docs.json +31 -9
- mcp_use-1.3.7/docs/essentials/elicitation.mdx +363 -0
- mcp_use-1.3.7/docs/essentials/sampling.mdx +86 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/essentials/server-manager.mdx +1 -2
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/browser_use.py +4 -5
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/agents/mcpagent.py +4 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/client.py +38 -5
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/config.py +11 -1
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/connectors/base.py +46 -11
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/connectors/http.py +21 -12
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/connectors/sandbox.py +13 -2
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/connectors/stdio.py +13 -2
- {mcp_use-1.3.5 → mcp_use-1.3.7}/pyproject.toml +2 -2
- mcp_use-1.3.7/tests/integration/conftest.py +38 -0
- mcp_use-1.3.7/tests/integration/primitives/test_elicitation.py +26 -0
- mcp_use-1.3.7/tests/integration/primitives/test_prompts.py +20 -0
- mcp_use-1.3.7/tests/integration/primitives/test_resources.py +42 -0
- mcp_use-1.3.7/tests/integration/primitives/test_sampling.py +48 -0
- mcp_use-1.3.7/tests/integration/primitives/test_tools.py +28 -0
- mcp_use-1.3.7/tests/integration/servers_for_testing/primitive_server.py +72 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_client.py +29 -7
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_http_connector.py +9 -3
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_sandbox_connector.py +8 -2
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_stdio_connector.py +9 -3
- mcp_use-1.3.5/.github/workflows/claude.yml +0 -36
- mcp_use-1.3.5/.github/workflows/publish.yml +0 -80
- mcp_use-1.3.5/.github/workflows/transportstests.yml +0 -41
- mcp_use-1.3.5/.github/workflows/unittests.yml +0 -31
- mcp_use-1.3.5/examples/browser_mcp.json +0 -11
- mcp_use-1.3.5/tests/integration/transports/sse/test_connection_state_tracking.py +0 -297
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.env.example +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.github/pull_request_template.md +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.github/release-drafter.yml +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.github/workflows/changelog.yml +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.github/workflows/release-drafter.yml +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.github/workflows/stale.yml +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.github/workflows/update-readme.yml +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.gitignore +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/.pre-commit-config.yaml +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/CHANGELOG.md +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/CLAUDE.md +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/CODE_OF_CONDUCT.md +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/CONTRIBUTING.md +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/LICENSE +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/README.md +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/api-reference/adapters.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/api-reference/introduction.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/api-reference/mcpagent.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/api-reference/mcpclient.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/changelog.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/community/showcase.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/development/observability.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/development/telemetry.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/development.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/essentials/agent-configuration.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/essentials/client-configuration.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/essentials/configuration.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/essentials/connection-types.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/essentials/llm-integration.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/favicon.svg +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/fonts.css +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/guides/building-custom-agents.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/guides/logging.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/guides/multi-server-setup.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/guides/security.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/guides/streaming.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/01.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/02.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/configuration-dark.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/configuration-light.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/examples-dark.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/examples-light.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/hero-dark.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/hero-light.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/installation-dark.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/installation-light.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/quickstart-dark.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/images/quickstart-light.png +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/index.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/installation.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/logo/dark.svg +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/logo/light.svg +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/logo/react.svg +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/quickstart.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/snippets/snippet-intro.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/snippets/youtube-embed.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/troubleshooting/common-issues.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/troubleshooting/connection-errors.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/docs/troubleshooting/performance.mdx +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/airbnb_mcp.json +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/airbnb_use.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/blender_use.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/chat_example.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/filesystem_use.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/http_example.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/mcp_everything.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/multi_server_example.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/sandbox_everything.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/examples/stream_example.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/adapters/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/adapters/base.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/adapters/langchain_adapter.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/agents/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/agents/base.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/agents/prompts/system_prompt_builder.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/agents/prompts/templates.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/connectors/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/connectors/utils.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/connectors/websocket.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/logging.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/server_manager.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/tools/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/tools/base_tool.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/tools/connect_server.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/tools/disconnect_server.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/tools/get_active_server.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/tools/list_servers_tool.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/tools/search_tools.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/managers/tools/use_tool.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/observability/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/observability/laminar.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/observability/langfuse.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/session.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/task_managers/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/task_managers/base.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/task_managers/sse.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/task_managers/stdio.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/task_managers/streamable_http.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/task_managers/websocket.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/telemetry/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/telemetry/events.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/telemetry/telemetry.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/telemetry/utils.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/types/sandbox.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/mcp_use/utils.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/pytest.ini +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/ruff.toml +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/static/logo_black.svg +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/static/logo_white.svg +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/conftest.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/servers_for_testing/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/servers_for_testing/custom_streaming_server.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/servers_for_testing/simple_server.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/servers_for_testing/timeout_test_server.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/transports/customStreaming/__init__.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/transports/customStreaming/test_custom_streaming_integration.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/transports/sse/test_sse_integration.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/transports/stdio/test_stdio_integration.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/integration/transports/streamableHttp/test_streamable_http_integration.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_config.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_logging.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_search_tools_issue_138.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_session.py +0 -0
- {mcp_use-1.3.5 → mcp_use-1.3.7}/tests/unit/test_websocket_connection_manager.py +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
# Required for PyPI trusted publishing
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
check-version-and-publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v3
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v4
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.11"
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install build twine wheel tomli
|
|
29
|
+
|
|
30
|
+
- name: Verify version match
|
|
31
|
+
id: check-version
|
|
32
|
+
run: |
|
|
33
|
+
# Extract current version from pyproject.toml
|
|
34
|
+
PYPROJECT_VERSION=$(python -c "
|
|
35
|
+
import tomli
|
|
36
|
+
with open('pyproject.toml', 'rb') as f:
|
|
37
|
+
data = tomli.load(f)
|
|
38
|
+
print(data['project']['version'])
|
|
39
|
+
")
|
|
40
|
+
|
|
41
|
+
# Get release tag version (remove 'v' prefix if present)
|
|
42
|
+
RELEASE_VERSION="${{ github.event.release.tag_name }}"
|
|
43
|
+
RELEASE_VERSION=${RELEASE_VERSION#v}
|
|
44
|
+
|
|
45
|
+
echo "PyProject version: $PYPROJECT_VERSION"
|
|
46
|
+
echo "Release version: $RELEASE_VERSION"
|
|
47
|
+
|
|
48
|
+
if [ "$PYPROJECT_VERSION" = "$RELEASE_VERSION" ]; then
|
|
49
|
+
echo "✅ Versions match! Proceeding with PyPI publish"
|
|
50
|
+
echo "should_publish=true" >> $GITHUB_OUTPUT
|
|
51
|
+
echo "version=$PYPROJECT_VERSION" >> $GITHUB_OUTPUT
|
|
52
|
+
else
|
|
53
|
+
echo "❌ Version mismatch! PyProject: $PYPROJECT_VERSION, Release: $RELEASE_VERSION"
|
|
54
|
+
echo "should_publish=false" >> $GITHUB_OUTPUT
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
- name: Build package
|
|
59
|
+
if: steps.check-version.outputs.should_publish == 'true'
|
|
60
|
+
run: |
|
|
61
|
+
python -m build
|
|
62
|
+
|
|
63
|
+
- name: Check if already published to PyPI
|
|
64
|
+
if: steps.check-version.outputs.should_publish == 'true'
|
|
65
|
+
id: check-pypi
|
|
66
|
+
run: |
|
|
67
|
+
# Check if this version exists on PyPI
|
|
68
|
+
VERSION="${{ steps.check-version.outputs.version }}"
|
|
69
|
+
if pip index versions mcp-use | grep -q "Available versions: .*$VERSION"; then
|
|
70
|
+
echo "Version $VERSION already exists on PyPI"
|
|
71
|
+
echo "publish_needed=false" >> $GITHUB_OUTPUT
|
|
72
|
+
else
|
|
73
|
+
echo "Version $VERSION not found on PyPI, will publish"
|
|
74
|
+
echo "publish_needed=true" >> $GITHUB_OUTPUT
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
- name: Publish to PyPI
|
|
78
|
+
if: steps.check-pypi.outputs.publish_needed == 'true'
|
|
79
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
80
|
+
with:
|
|
81
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v3
|
|
14
|
+
- name: Set up Python 3.11
|
|
15
|
+
uses: actions/setup-python@v4
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.11"
|
|
18
|
+
- name: Install dependencies
|
|
19
|
+
run: |
|
|
20
|
+
python -m pip install --upgrade pip
|
|
21
|
+
pip install ruff
|
|
22
|
+
- name: Lint with ruff
|
|
23
|
+
run: |
|
|
24
|
+
ruff check .
|
|
25
|
+
- name: Format check with ruff
|
|
26
|
+
run: |
|
|
27
|
+
ruff format --check .
|
|
28
|
+
|
|
29
|
+
unit-tests:
|
|
30
|
+
needs: lint
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
strategy:
|
|
33
|
+
matrix:
|
|
34
|
+
python-version: ["3.11", "3.12"]
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v3
|
|
37
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
38
|
+
uses: actions/setup-python@v4
|
|
39
|
+
with:
|
|
40
|
+
python-version: ${{ matrix.python-version }}
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: |
|
|
43
|
+
python -m pip install --upgrade pip
|
|
44
|
+
pip install .[dev,anthropic,openai,search,e2b]
|
|
45
|
+
- name: Test with pytest
|
|
46
|
+
run: |
|
|
47
|
+
pytest tests/unit
|
|
48
|
+
|
|
49
|
+
transport-tests:
|
|
50
|
+
needs: lint
|
|
51
|
+
name: "transport/${{ matrix.transport }}"
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
strategy:
|
|
54
|
+
fail-fast: false
|
|
55
|
+
matrix:
|
|
56
|
+
transport: [stdio, sse, streamableHttp]
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v3
|
|
59
|
+
- name: Set up Python 3.11
|
|
60
|
+
uses: actions/setup-python@v4
|
|
61
|
+
with:
|
|
62
|
+
python-version: "3.11"
|
|
63
|
+
- name: Install uv
|
|
64
|
+
run: |
|
|
65
|
+
pip install uv
|
|
66
|
+
- name: Install dependencies
|
|
67
|
+
run: |
|
|
68
|
+
uv pip install --system .[dev,anthropic,openai,search,e2b]
|
|
69
|
+
- name: Run integration tests for ${{ matrix.transport }} transport
|
|
70
|
+
run: |
|
|
71
|
+
pytest tests/integration/transports/${{ matrix.transport }}
|
|
72
|
+
|
|
73
|
+
primitive-tests:
|
|
74
|
+
needs: lint
|
|
75
|
+
name: "primitive/${{ matrix.primitive }}"
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
strategy:
|
|
78
|
+
fail-fast: false
|
|
79
|
+
matrix:
|
|
80
|
+
primitive: [sampling, tools, resources, prompts, elicitation]
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v3
|
|
83
|
+
- name: Set up Python 3.11
|
|
84
|
+
uses: actions/setup-python@v4
|
|
85
|
+
with:
|
|
86
|
+
python-version: "3.11"
|
|
87
|
+
- name: Install uv
|
|
88
|
+
run: |
|
|
89
|
+
pip install uv
|
|
90
|
+
- name: Install dependencies
|
|
91
|
+
run: |
|
|
92
|
+
uv pip install --system .[dev,anthropic,openai,search,e2b]
|
|
93
|
+
- name: Run integration tests for ${{ matrix.primitive }} primitive
|
|
94
|
+
run: |
|
|
95
|
+
pytest tests/integration/primitives/test_${{ matrix.primitive }}.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-use
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.7
|
|
4
4
|
Summary: MCP Library for LLMs
|
|
5
5
|
Author-email: Pietro Zullo <pietro.zullo@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -28,7 +28,7 @@ Requires-Dist: langchain-anthropic; extra == 'anthropic'
|
|
|
28
28
|
Provides-Extra: dev
|
|
29
29
|
Requires-Dist: black>=23.9.0; extra == 'dev'
|
|
30
30
|
Requires-Dist: fastapi; extra == 'dev'
|
|
31
|
-
Requires-Dist: fastmcp==2.
|
|
31
|
+
Requires-Dist: fastmcp==2.10.5; extra == 'dev'
|
|
32
32
|
Requires-Dist: isort>=5.12.0; extra == 'dev'
|
|
33
33
|
Requires-Dist: mypy>=1.5.0; extra == 'dev'
|
|
34
34
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
@@ -89,7 +89,12 @@ Description-Content-Type: text/markdown
|
|
|
89
89
|
|
|
90
90
|
💬 Get started quickly - chat with your servers on our <b>hosted version</b>! [Try mcp-use chat (beta)](https://chat.mcp-use.com).
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
| Supports | |
|
|
93
|
+
| :--- | :--- |
|
|
94
|
+
| **Primitives** | [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) |
|
|
95
|
+
| **Transports** | [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) |
|
|
96
|
+
|
|
97
|
+
## Features
|
|
93
98
|
|
|
94
99
|
<table>
|
|
95
100
|
<tr>
|
|
@@ -44,7 +44,12 @@
|
|
|
44
44
|
|
|
45
45
|
💬 Get started quickly - chat with your servers on our <b>hosted version</b>! [Try mcp-use chat (beta)](https://chat.mcp-use.com).
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
| Supports | |
|
|
48
|
+
| :--- | :--- |
|
|
49
|
+
| **Primitives** | [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) |
|
|
50
|
+
| **Transports** | [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) [](https://github.com/pietrozullo/mcp-use/actions/workflows/tests.yml) |
|
|
51
|
+
|
|
52
|
+
## Features
|
|
48
53
|
|
|
49
54
|
<table>
|
|
50
55
|
<tr>
|
|
@@ -8,10 +8,32 @@
|
|
|
8
8
|
"dark": "#000000"
|
|
9
9
|
},
|
|
10
10
|
"favicon": "/favicon.svg",
|
|
11
|
+
"contextual": {
|
|
12
|
+
"options": [
|
|
13
|
+
"copy",
|
|
14
|
+
"view",
|
|
15
|
+
"chatgpt",
|
|
16
|
+
"claude"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
11
19
|
"icons": {
|
|
12
20
|
"library": "lucide"
|
|
13
21
|
},
|
|
14
22
|
"navigation": {
|
|
23
|
+
"global": {
|
|
24
|
+
"anchors": [
|
|
25
|
+
{
|
|
26
|
+
"anchor": "Website",
|
|
27
|
+
"href": "https://mcp-use.com",
|
|
28
|
+
"icon": "globe"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"anchor": "Forum",
|
|
32
|
+
"href": "https://discord.gg/XkNkSkMz3V",
|
|
33
|
+
"icon": "discord"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
},
|
|
15
37
|
"tabs": [
|
|
16
38
|
{
|
|
17
39
|
"tab": "Documentation",
|
|
@@ -30,7 +52,15 @@
|
|
|
30
52
|
"pages": [
|
|
31
53
|
"essentials/configuration",
|
|
32
54
|
"essentials/client-configuration",
|
|
33
|
-
|
|
55
|
+
{
|
|
56
|
+
"group": "Client Features",
|
|
57
|
+
"icon": "list-plus",
|
|
58
|
+
"pages": [
|
|
59
|
+
"essentials/connection-types",
|
|
60
|
+
"essentials/sampling",
|
|
61
|
+
"essentials/elicitation"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
34
64
|
]
|
|
35
65
|
},
|
|
36
66
|
{
|
|
@@ -196,14 +226,6 @@
|
|
|
196
226
|
}
|
|
197
227
|
]
|
|
198
228
|
},
|
|
199
|
-
"contextual": {
|
|
200
|
-
"options": [
|
|
201
|
-
"copy",
|
|
202
|
-
"view",
|
|
203
|
-
"chatgpt",
|
|
204
|
-
"claude"
|
|
205
|
-
]
|
|
206
|
-
},
|
|
207
229
|
"seo": {
|
|
208
230
|
"metatags": {
|
|
209
231
|
"charset": "UTF-8",
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Elicitation"
|
|
3
|
+
description: "Enable user input requests for MCP tools"
|
|
4
|
+
icon: "user-question"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Elicitation
|
|
8
|
+
|
|
9
|
+
<Info>
|
|
10
|
+
Elicitation allows MCP tools to request additional information from users during their execution.
|
|
11
|
+
</Info>
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
To enable elicitation, provide an `elicitation_callback` function when initializing the MCPClient:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from mcp_use.client import MCPClient
|
|
19
|
+
from mcp.client.session import RequestContext
|
|
20
|
+
from mcp.types import ElicitRequestParams, ElicitResult
|
|
21
|
+
|
|
22
|
+
async def elicitation_callback(
|
|
23
|
+
context: RequestContext,
|
|
24
|
+
params: ElicitRequestParams
|
|
25
|
+
) -> ElicitResult:
|
|
26
|
+
"""
|
|
27
|
+
Your elicitation callback implementation.
|
|
28
|
+
This function receives a request for user input and returns the user's response.
|
|
29
|
+
"""
|
|
30
|
+
# Display the message to the user and collect their input
|
|
31
|
+
print(f"Server requests: {params.message}")
|
|
32
|
+
|
|
33
|
+
# Example: Get user input (replace with your UI logic)
|
|
34
|
+
if hasattr(params, 'requestedSchema'):
|
|
35
|
+
# Handle structured input based on the schema
|
|
36
|
+
user_input = await collect_structured_input(params.requestedSchema)
|
|
37
|
+
else:
|
|
38
|
+
# Handle simple text input
|
|
39
|
+
user_input = input("Please provide your response: ")
|
|
40
|
+
|
|
41
|
+
# Return the result
|
|
42
|
+
return ElicitResult(
|
|
43
|
+
action="accept", # or "decline" or "cancel"
|
|
44
|
+
content=user_input
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Initialize client with elicitation support
|
|
48
|
+
client = MCPClient(
|
|
49
|
+
config="config.json",
|
|
50
|
+
elicitation_callback=elicitation_callback
|
|
51
|
+
)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Handler Parameters
|
|
55
|
+
|
|
56
|
+
The elicitation handler receives two parameters:
|
|
57
|
+
|
|
58
|
+
### Elicitation Handler Parameters
|
|
59
|
+
|
|
60
|
+
| Parameter | Type | Description |
|
|
61
|
+
|-----------|------|-------------|
|
|
62
|
+
| **context** | `RequestContext` | Request context containing metadata about the elicitation request |
|
|
63
|
+
| **params** | `ElicitRequestParams` | The MCP elicitation request parameters containing the message and optional schema |
|
|
64
|
+
|
|
65
|
+
#### ElicitRequestParams Structure
|
|
66
|
+
|
|
67
|
+
| Field | Type | Description |
|
|
68
|
+
|-------|------|-------------|
|
|
69
|
+
| **message** | `str` | The prompt message to display to the user |
|
|
70
|
+
| **requestedSchema** | `dict \| None` | Optional JSON schema defining the expected response structure |
|
|
71
|
+
|
|
72
|
+
### Response Structure
|
|
73
|
+
|
|
74
|
+
The handler must return an `ElicitResult` object that specifies how the user responded:
|
|
75
|
+
|
|
76
|
+
#### ElicitResult Structure
|
|
77
|
+
|
|
78
|
+
| Field | Type | Description |
|
|
79
|
+
|-------|------|-------------|
|
|
80
|
+
| **action** | `Literal['accept', 'decline', 'cancel']` | How the user responded to the elicitation request |
|
|
81
|
+
| **content** | `dict \| str \| None` | The user's input data (required for "accept", omitted for "decline"/"cancel") |
|
|
82
|
+
|
|
83
|
+
#### Action Types:
|
|
84
|
+
|
|
85
|
+
- **accept**: User provided valid input - include their data in the `content` field
|
|
86
|
+
- **decline**: User chose not to provide the requested information - omit `content`
|
|
87
|
+
- **cancel**: User cancelled the entire operation - omit `content`
|
|
88
|
+
|
|
89
|
+
### Example Parameter Usage
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
async def detailed_elicitation_callback(
|
|
93
|
+
context: RequestContext,
|
|
94
|
+
params: ElicitRequestParams
|
|
95
|
+
) -> ElicitResult:
|
|
96
|
+
"""Example showing how to use all parameters."""
|
|
97
|
+
|
|
98
|
+
# Access the user message
|
|
99
|
+
user_message = params.message
|
|
100
|
+
print(f"Request: {user_message}")
|
|
101
|
+
|
|
102
|
+
# Check if schema is provided for structured data
|
|
103
|
+
schema = getattr(params, 'requestedSchema', None)
|
|
104
|
+
|
|
105
|
+
if schema:
|
|
106
|
+
# Handle structured input
|
|
107
|
+
schema_type = schema.get('type')
|
|
108
|
+
properties = schema.get('properties', {})
|
|
109
|
+
required_fields = schema.get('required', [])
|
|
110
|
+
|
|
111
|
+
print(f"Expecting {schema_type} with fields: {list(properties.keys())}")
|
|
112
|
+
print(f"Required fields: {required_fields}")
|
|
113
|
+
|
|
114
|
+
# Collect structured data
|
|
115
|
+
user_data = {}
|
|
116
|
+
for field_name, field_def in properties.items():
|
|
117
|
+
field_type = field_def.get('type', 'string')
|
|
118
|
+
description = field_def.get('description', '')
|
|
119
|
+
|
|
120
|
+
prompt = f"Enter {field_name}"
|
|
121
|
+
if description:
|
|
122
|
+
prompt += f" ({description})"
|
|
123
|
+
prompt += ": "
|
|
124
|
+
|
|
125
|
+
value = input(prompt)
|
|
126
|
+
|
|
127
|
+
# Basic type conversion
|
|
128
|
+
if field_type == 'number':
|
|
129
|
+
value = float(value) if value else None
|
|
130
|
+
elif field_type == 'integer':
|
|
131
|
+
value = int(value) if value else None
|
|
132
|
+
elif field_type == 'boolean':
|
|
133
|
+
value = value.lower() in ('true', '1', 'yes') if value else None
|
|
134
|
+
|
|
135
|
+
user_data[field_name] = value
|
|
136
|
+
|
|
137
|
+
# Validate required fields
|
|
138
|
+
missing = [f for f in required_fields if not user_data.get(f)]
|
|
139
|
+
if missing:
|
|
140
|
+
print(f"Missing required fields: {missing}")
|
|
141
|
+
return ElicitResult(action="cancel")
|
|
142
|
+
|
|
143
|
+
return ElicitResult(action="accept", content=user_data)
|
|
144
|
+
|
|
145
|
+
else:
|
|
146
|
+
# Handle simple text input
|
|
147
|
+
response = input(f"{user_message}: ")
|
|
148
|
+
if not response:
|
|
149
|
+
return ElicitResult(action="cancel")
|
|
150
|
+
|
|
151
|
+
return ElicitResult(action="accept", content=response)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Response Actions
|
|
155
|
+
|
|
156
|
+
Elicitation responses use a three-action model to clearly distinguish between different user intentions:
|
|
157
|
+
|
|
158
|
+
### Accept
|
|
159
|
+
User explicitly approved and submitted data:
|
|
160
|
+
```python
|
|
161
|
+
return ElicitResult(
|
|
162
|
+
action="accept",
|
|
163
|
+
content={"name": "John Doe", "email": "john@example.com"}
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Decline
|
|
168
|
+
User explicitly declined the request:
|
|
169
|
+
```python
|
|
170
|
+
return ElicitResult(
|
|
171
|
+
action="decline"
|
|
172
|
+
# content field is typically omitted
|
|
173
|
+
)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Cancel
|
|
177
|
+
User dismissed without making an explicit choice:
|
|
178
|
+
```python
|
|
179
|
+
return ElicitResult(
|
|
180
|
+
action="cancel"
|
|
181
|
+
# content field is typically omitted
|
|
182
|
+
)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Structured Data Requests
|
|
186
|
+
|
|
187
|
+
MCP tools can request structured data using JSON schemas. The schema defines the expected format and validation rules:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
async def advanced_elicitation_callback(
|
|
191
|
+
context: RequestContext,
|
|
192
|
+
params: ElicitRequestParams
|
|
193
|
+
) -> ElicitResult:
|
|
194
|
+
"""Handle structured data requests with validation."""
|
|
195
|
+
|
|
196
|
+
# Check if a schema is provided
|
|
197
|
+
if hasattr(params, 'requestedSchema') and params.requestedSchema:
|
|
198
|
+
schema = params.requestedSchema
|
|
199
|
+
|
|
200
|
+
# Example: Handle different schema types
|
|
201
|
+
if schema.get('type') == 'object':
|
|
202
|
+
properties = schema.get('properties', {})
|
|
203
|
+
required_fields = schema.get('required', [])
|
|
204
|
+
|
|
205
|
+
# Collect data for each property
|
|
206
|
+
user_data = {}
|
|
207
|
+
for field_name, field_schema in properties.items():
|
|
208
|
+
field_type = field_schema.get('type', 'string')
|
|
209
|
+
field_description = field_schema.get('description', '')
|
|
210
|
+
|
|
211
|
+
print(f"{field_name} ({field_type}): {field_description}")
|
|
212
|
+
|
|
213
|
+
# Collect input based on field type
|
|
214
|
+
if field_type == 'string':
|
|
215
|
+
value = input(f"Enter {field_name}: ")
|
|
216
|
+
elif field_type == 'number':
|
|
217
|
+
value = float(input(f"Enter {field_name}: "))
|
|
218
|
+
elif field_type == 'boolean':
|
|
219
|
+
value = input(f"Enter {field_name} (true/false): ").lower() == 'true'
|
|
220
|
+
elif field_type == 'integer':
|
|
221
|
+
value = int(input(f"Enter {field_name}: "))
|
|
222
|
+
else:
|
|
223
|
+
value = input(f"Enter {field_name}: ")
|
|
224
|
+
|
|
225
|
+
user_data[field_name] = value
|
|
226
|
+
|
|
227
|
+
# Basic validation for required fields
|
|
228
|
+
missing_fields = [field for field in required_fields if field not in user_data or not user_data[field]]
|
|
229
|
+
if missing_fields:
|
|
230
|
+
print(f"Missing required fields: {missing_fields}")
|
|
231
|
+
return ElicitResult(action="cancel")
|
|
232
|
+
|
|
233
|
+
return ElicitResult(action="accept", content=user_data)
|
|
234
|
+
|
|
235
|
+
# Fallback to simple text input
|
|
236
|
+
response = input(f"{params.message}: ")
|
|
237
|
+
return ElicitResult(action="accept", content=response)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Creating Elicitation-Enabled Tools
|
|
241
|
+
|
|
242
|
+
When building MCP servers, tools can request user input using the context parameter:
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
from fastmcp import Context, FastMCP
|
|
246
|
+
|
|
247
|
+
mcp = FastMCP(name="MyServer")
|
|
248
|
+
|
|
249
|
+
@mcp.tool
|
|
250
|
+
async def purchase_item(ctx: Context) -> str:
|
|
251
|
+
"""Purchase an item with user-provided details."""
|
|
252
|
+
|
|
253
|
+
# Define the schema for purchase information
|
|
254
|
+
purchase_schema = {
|
|
255
|
+
"type": "object",
|
|
256
|
+
"properties": {
|
|
257
|
+
"quantity": {
|
|
258
|
+
"type": "number",
|
|
259
|
+
"minimum": 1,
|
|
260
|
+
"description": "Number of items to purchase"
|
|
261
|
+
},
|
|
262
|
+
"unit": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"enum": ["kg", "lbs", "pieces"],
|
|
265
|
+
"description": "Unit of measurement"
|
|
266
|
+
},
|
|
267
|
+
"item_name": {
|
|
268
|
+
"type": "string",
|
|
269
|
+
"description": "Name of the item to purchase"
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
"required": ["quantity", "unit", "item_name"]
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
# Request purchase details from the user
|
|
276
|
+
result = await ctx.elicit(
|
|
277
|
+
message="Please provide purchase details",
|
|
278
|
+
response_type=purchase_schema
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Handle different response actions
|
|
282
|
+
if result.action == "accept":
|
|
283
|
+
data = result.data
|
|
284
|
+
return f"Purchasing {data['quantity']} {data['unit']} of {data['item_name']}"
|
|
285
|
+
elif result.action == "decline":
|
|
286
|
+
return "Purchase declined by user"
|
|
287
|
+
else:
|
|
288
|
+
return "Purchase cancelled"
|
|
289
|
+
|
|
290
|
+
@mcp.tool
|
|
291
|
+
async def collect_feedback(ctx: Context) -> str:
|
|
292
|
+
"""Collect user feedback with a simple text request."""
|
|
293
|
+
|
|
294
|
+
result = await ctx.elicit(
|
|
295
|
+
message="Please provide your feedback about our service"
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
if result.action == "accept":
|
|
299
|
+
return f"Thank you for your feedback: {result.data}"
|
|
300
|
+
else:
|
|
301
|
+
return "No feedback provided"
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Integration with MCPAgent
|
|
305
|
+
|
|
306
|
+
When using elicitation with MCPAgent, the elicitation callback is automatically used during tool execution:
|
|
307
|
+
|
|
308
|
+
```python
|
|
309
|
+
import asyncio
|
|
310
|
+
from mcp_use import MCPAgent, MCPClient
|
|
311
|
+
from langchain_openai import ChatOpenAI
|
|
312
|
+
|
|
313
|
+
async def main():
|
|
314
|
+
# Define elicitation callback
|
|
315
|
+
async def handle_user_input(ctx, params):
|
|
316
|
+
# Your UI logic here - this example uses simple input
|
|
317
|
+
print(f"\n🤖 Server Request: {params.message}")
|
|
318
|
+
|
|
319
|
+
if hasattr(params, 'requestedSchema') and params.requestedSchema:
|
|
320
|
+
# Handle structured input
|
|
321
|
+
schema = params.requestedSchema
|
|
322
|
+
if schema.get('type') == 'object':
|
|
323
|
+
data = {}
|
|
324
|
+
for field, field_schema in schema.get('properties', {}).items():
|
|
325
|
+
value = input(f"Enter {field}: ")
|
|
326
|
+
data[field] = value
|
|
327
|
+
return ElicitResult(action="accept", content=data)
|
|
328
|
+
|
|
329
|
+
# Simple text input
|
|
330
|
+
response = input("Your response: ")
|
|
331
|
+
return ElicitResult(action="accept", content=response)
|
|
332
|
+
|
|
333
|
+
# Create client with elicitation support
|
|
334
|
+
client = MCPClient.from_config_file(
|
|
335
|
+
"config.json",
|
|
336
|
+
elicitation_callback=handle_user_input
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
# Create agent
|
|
340
|
+
llm = ChatOpenAI(model="gpt-4")
|
|
341
|
+
agent = MCPAgent(llm=llm, client=client)
|
|
342
|
+
|
|
343
|
+
# Run agent - tools can now request user input
|
|
344
|
+
result = await agent.run("Help me purchase some items from the store")
|
|
345
|
+
print(result)
|
|
346
|
+
|
|
347
|
+
if __name__ == "__main__":
|
|
348
|
+
asyncio.run(main())
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## Error Handling
|
|
352
|
+
|
|
353
|
+
If no elicitation callback is provided but a tool requests user input:
|
|
354
|
+
|
|
355
|
+
```python
|
|
356
|
+
# Without elicitation callback
|
|
357
|
+
client = MCPClient(config="config.json") # No elicitation_callback
|
|
358
|
+
|
|
359
|
+
# Tool that requires elicitation will return an error
|
|
360
|
+
session = client.get_session("server_name")
|
|
361
|
+
result = await session.connector.call_tool("purchase_item", {})
|
|
362
|
+
# This will fail because no elicitation callback is configured
|
|
363
|
+
```
|