Skip to content

Python: Add MCP channel for agent-framework-hosting#6700

Open
eavanvalkenburg wants to merge 3 commits into
microsoft:mainfrom
eavanvalkenburg:eavan/python-hosting-mcp
Open

Python: Add MCP channel for agent-framework-hosting#6700
eavanvalkenburg wants to merge 3 commits into
microsoft:mainfrom
eavanvalkenburg:eavan/python-hosting-mcp

Conversation

@eavanvalkenburg

@eavanvalkenburg eavanvalkenburg commented Jun 24, 2026

Copy link
Copy Markdown
Member

Motivation & Context

Adds Model Context Protocol (MCP) support for the agent-framework-hosting stack, allowing an AgentFrameworkHost to be exposed as an MCP server. Any MCP-compatible client or orchestrator can then invoke the hosted agent as a single tool over Streamable HTTP.

This is part of the channel-by-channel split of the hosting work tracked in #6265.

Description & Review Guide

Major changes:

  • agent-framework-hosting-mcp packageMCPChannel that:

    • Mounts a FastMCP server on the host's Starlette ASGI app via Streamable HTTP
    • Registers the hosted agent as a single MCP tool with configurable name and description
    • Routes call_tool requests through the full channel pipeline (run_hook, context providers, history providers)
    • Rich content conversion via _content_to_mcp and _value_to_mcp: text, reasoning, data, URI, function_result, and error content all map to appropriate MCP TextContent / ImageContent / EmbeddedResource items
    • Streaming: MCP progress notifications dispatched while consuming ResponseStream; final CallToolResult assembled from get_final_response()
    • Session continuity: caller-supplied session_id (when provided) is used as the AF isolation key; omitted session_id requests are treated as sessionless.
  • Test layout already uses tests/hosting_mcp/ with no __init__.py; tests exercise the full Streamable HTTP round-trip using mcp.client.streamable_http and an in-process uvicorn server

Impact: New alpha package with no changes to existing packages. Adds agent-framework-hosting-mcp to the workspace and lockfile. Removed stale mypy-specific # type: ignore comments flagged as unnecessary by pyright.

Reviewer focus: content-type mapping completeness in _content_to_mcp / _value_to_mcp, MCP progress notification correctness, tool descriptor schema generation.

Related Issue

Fixes #6592
Refs #6265

Contribution Checklist

  • I have read the CONTRIBUTING guidelines.
  • My changes include tests.
  • My changes include documentation (README).
  • This is not a breaking change.

- Add agent-framework-hosting-mcp package with MCPChannel that
  exposes an AgentFrameworkHost as a Streamable-HTTP MCP server,
  allowing any MCP client to invoke the agent as a single tool
- MCPChannel mounts a FastMCP server on the host's Starlette app
  and routes call_tool requests through the channel pipeline
  (run_hook, context providers, history providers)
- Rich content conversion via _content_to_mcp and _value_to_mcp:
  handles text, reasoning, data, URI, function_result, and error
  content types from AF responses into MCP TextContent/ImageContent
- Streaming: MCP progress notifications dispatched while consuming
  ResponseStream; final tool result assembled from get_final_response()
- Test layout uses tests/hosting_mcp/ (no tests/__init__.py)
- Remove old [tool.mypy] section and mypy poe task; remove empty
  [dependency-groups] section; remove stale mypy-only type: ignore
  comments that pyright reports as unnecessary
- Update uv.lock, pyproject.toml workspace sources, and PACKAGE_STATUS.md

Fixes microsoft#6592
Refs microsoft#6265

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 24, 2026 07:25
@moonbox3 moonbox3 added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels Jun 24, 2026
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/hosting-mcp/agent_framework_hosting_mcp
   _channel.py1991293%77, 87, 95, 126, 140, 151, 158, 389–391, 418, 437
TOTAL42347499288% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
8318 37 💤 0 ❌ 0 🔥 2m 16s ⏱️

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Python hosting channel package (agent-framework-hosting-mcp) that exposes an AgentFrameworkHost target as a single MCP tool over Streamable HTTP, including content conversion utilities and end-to-end tests.

Changes:

  • Introduces MCPChannel implementation that mounts an MCP Streamable HTTP transport and routes tool calls through the hosting pipeline.
  • Adds unit/integration-style tests exercising in-memory MCP sessions and a real Streamable HTTP round-trip via an in-process ASGI server.
  • Wires the new package into the Python workspace and documents/package-status it as alpha.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
python/pyproject.toml Adds agent-framework-hosting-mcp to the Python workspace.
python/packages/hosting-mcp/agent_framework_hosting_mcp/_channel.py Implements MCPChannel, MCP tool registration, streaming progress notifications, and content conversion.
python/packages/hosting-mcp/agent_framework_hosting_mcp/init.py Exports MCPChannel and package __version__.
python/packages/hosting-mcp/tests/hosting_mcp/test_channel.py Adds tests for tool listing, call routing, streaming aggregation, content conversion, and Streamable HTTP invocation.
python/packages/hosting-mcp/README.md Documents how to host an agent with the MCP channel and the tool I/O shape.
python/packages/hosting-mcp/pyproject.toml Defines the new package metadata, dependencies, and tooling config.
python/packages/hosting-mcp/LICENSE Adds MIT license file for the new package.
python/PACKAGE_STATUS.md Registers the new package as alpha.

Comment thread python/packages/hosting-mcp/agent_framework_hosting_mcp/_channel.py Outdated
Comment thread python/packages/hosting-mcp/agent_framework_hosting_mcp/_channel.py
Comment thread python/packages/hosting-mcp/pyproject.toml

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 5 | Confidence: 60%

✓ Correctness

No actionable issues found in this dimension.

✓ Security Reliability

No actionable issues found in this dimension.

✓ Test Coverage

The test suite provides solid coverage of the happy path, content conversion, hooks, and an end-to-end HTTP integration test. Two notable test coverage gaps exist: (1) no test exercises error propagation when the hosted target raises an exception during _invoke_tool, so it's unverified whether the channel returns a graceful MCP error or crashes the session; (2) the MCP progress notification path (_send_progress) is never exercised because no test supplies a progressToken, leaving that production logic untested.

✓ Failure Modes

The MCPChannel implementation is well-structured with appropriate failure handling: input validation with early error returns, best-effort progress notifications, and proper content conversion fallbacks. The response_hook integration with the streaming path is correctly handled through the hosting framework's _HostResponseStream. One minor lifecycle concern exists around the startup/shutdown context manager pattern, but it's unlikely to trigger in practice.

✗ Design Approach

The new MCP channel is close, but it currently ignores the MCP tool name on call_tool. Because the handler always forwards to _invoke_tool, a client can invoke any arbitrary tool name and still execute the hosted agent, which is a protocol-level correctness issue for a server that advertises a single named tool.

Flagged Issues

  • python/packages/hosting-mcp/agent_framework_hosting_mcp/_channel.py:303-305 advertises exactly one tool via list_tools() but never validates the incoming name in call_tool(), so a request like call_tool("does-not-exist", {"input": "hello"}) will still run the hosted agent instead of failing as an unknown-tool call.

Automated review by eavanvalkenburg's agents

@github-actions

Copy link
Copy Markdown
Contributor

Flagged issue

python/packages/hosting-mcp/agent_framework_hosting_mcp/_channel.py:303-305 advertises exactly one tool via list_tools() but never validates the incoming name in call_tool(), so a request like call_tool("does-not-exist", {"input": "hello"}) will still run the hosted agent instead of failing as an unknown-tool call.


Source: automated DevFlow PR review

eavanvalkenburg and others added 2 commits June 24, 2026 10:37
- Validate requested tool name in call_tool and return an MCP error for
  unknown tools instead of invoking the hosted target
- Raise minimum mcp dependency to >=1.24.0 to align with other MCP
  integrations and Streamable HTTP usage in this repo
- Harden MCP tests for strict typing:
  - add typed helper for TextContent extraction instead of union attr access
  - add helper that narrows channel._server before creating in-memory
    MCP client sessions
  - shape _HostedAgent fake to satisfy SupportsAgentRun protocol
- Add regression test for unknown tool-name rejection

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mcp sample

Channel fixes:
- Replace getattr(update, 'text', None) streaming pattern with
  update.contents iteration; extract text items for progress notifications
- Add _strip_options_hook as default when run_hook=None, matching the
  ResponsesChannel pattern so untrusted callers cannot inject options
- Update _hook type annotation to ChannelRunHook (non-optional)
- Update run_hook docstring to document default behaviour

Tests:
- Update _FakeStream to populate contents from text chunks
- Add stream_updates param to _FakeContext for injecting mixed-content updates
- Add test: non-text content in stream updates is not forwarded as progress
- Add test: default hook strips options when no run_hook is supplied

Sample (local_mcp/):
- app.py: WeatherAgent behind MCPChannel with run_hook and FileHistoryProvider
- call_client.py: outer Agent consuming the hosted agent via MCPStreamableHTTPTool
- pyproject.toml, README.md

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@eavanvalkenburg eavanvalkenburg mentioned this pull request Jun 24, 2026
9 tasks
@eavanvalkenburg eavanvalkenburg self-assigned this Jun 24, 2026
@eavanvalkenburg eavanvalkenburg marked this pull request as ready for review June 24, 2026 10:49

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 4 | Confidence: 62% | Result: All clear

Reviewed: Correctness, Security Reliability, Failure Modes, Design Approach


Automated review by eavanvalkenburg's agents

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hosting: MCP channel

3 participants