Table of Contents

FoundationaLLM MCP Client Tool

The FoundationaLLM MCP client tool allows agents to call any Model Context Protocol server using the official Python SDK. It mirrors the configuration patterns used by other FoundationaLLM tools while adding transport-specific options and telemetry instrumentation.

Capabilities

  • Connects to arbitrary MCP servers over STDIO, streamable HTTP, or HTTP + Server-Sent Events (SSE) transports.
  • Supports both synchronous (_run) and asynchronous (_arun) invocation paths.
  • Emits rich content artifacts summarizing the invocation, including transport details, session identifiers, initialization metadata, and structured responses.
  • Records OpenTelemetry spans for connection and request execution phases, aligning with existing FoundationaLLM tooling expectations.
  • Provides per-invocation transport overrides so that agents can adjust endpoints or headers dynamically without redeploying the tool configuration.

Plugin Architecture

The MCP client tool is part of the foundationallm-agent-plugins package (v0.9.8-beta117) within the FoundationaLLM plugin system.

Package layout

src/python/plugins/
├── core/                                  # Core platform library (foundationallm)
│   └── pkg/foundationallm/
│       ├── langchain/common/
│       │   ├── foundationallm_tool_base.py   # FoundationaLLMToolBase
│       │   └── foundationallm_tool_result.py # FoundationaLLMToolResult
│       ├── models/agents/agent_tool.py       # AgentTool configuration model
│       └── plugins/                          # ToolPluginManagerBase (abstract)
├── agent_core/                            # Agent tool implementations
│   ├── pkg/foundationallm_agent_plugins/
│   │   ├── tools/
│   │   │   ├── __init__.py                   # Tool exports
│   │   │   ├── foundationallm_mcp_client_tool.py
│   │   │   └── foundationallm_mcp_client_tool_input.py
│   │   └── tool_plugin_manager.py            # FoundationaLLMAgentToolPluginManager
│   ├── pkg/pyproject.toml
│   └── requirements.txt
├── agent_azure_ai/                        # Azure AI-specific tools and workflows
├── agent_langchain/                       # LangChain workflow implementations
└── agent_experimental/                    # Experimental tools

How tools are registered

All agent-core tools are exported from foundationallm_agent_plugins.tools.__init__:

from .foundationallm_mcp_client_tool import FoundationaLLMMCPClientTool

The FoundationaLLMAgentToolPluginManager in tool_plugin_manager.py acts as a factory that routes tool creation by class_name:

class FoundationaLLMAgentToolPluginManager(ToolPluginManagerBase):
    FOUNDATIONALLM_MCP_CLIENT_TOOL_CLASS = 'FoundationaLLMMCPClientTool'

    def create_tool(self, tool_config, objects, user_identity, config, intercept_http_calls=False):
        match tool_config.class_name:
            case self.FOUNDATIONALLM_MCP_CLIENT_TOOL_CLASS:
                return FoundationaLLMMCPClientTool(tool_config, objects, user_identity, config)
            # ... other tools ...

Base class

FoundationaLLMMCPClientTool extends FoundationaLLMToolBase (defined in the foundationallm core package at foundationallm.langchain.common). The base class provides:

  • get_main_language_model() — resolves the LLM from the tool's resource_object_ids where the role is main_model.
  • get_main_prompt() — resolves the orchestration prompt from the tool's resource_object_ids where the role is main_prompt.
  • create_content_artifact() / create_error_content_artifact() — standard artifact helpers.
  • tracer / logger — OpenTelemetry instrumentation from foundationallm.telemetry.
  • config — platform Configuration instance for secret resolution.

Installation

The mcp SDK is pinned in src/python/plugins/agent_core/requirements.txt:

mcp==1.17.0

Configuration Reference

Register the tool in an agent definition using the FoundationaLLMMCPClientTool class. Tool properties are validated by a Pydantic model with the following top-level fields:

Property Type Description
transport "stdio" \| "streamable_http" \| "http_sse" Transport protocol to use. Defaults to streamable_http.
endpoint_object_id String Preferred for HTTP transports. References a FoundationaLLM.Configuration/apiEndpointConfigurations resource; the runtime resolves URL, headers, and timeouts from that endpoint.
stdio Object Required when transport is stdio; see below.
streamable_http Object Required when transport is streamable_http and no endpoint_object_id is set; see below.
http_sse Object Required when transport is http_sse and no endpoint_object_id is set; see below.
client_name String Reported to the server as the MCP client name. Defaults to foundationallm-mcp-client.
client_version String Reported to the server as the MCP client version. Defaults to 1.0.0.
default_operation_timeout_seconds Number Optional default timeout applied to operations that accept a read_timeout_seconds parameter (e.g., call_tool).

STDIO settings

Note: STDIO transport is intended for advanced and local-development scenarios. It is not configurable via the Management Portal — use the API to configure agents with STDIO transport.

{
  "transport": "stdio",
  "stdio": {
    "command": "./my-mcp-server",
    "args": ["--flag"],
    "env": {"API_TOKEN": "config://my-secret"},
    "cwd": "/opt/mcp",
    "encoding": "utf-8",
    "encoding_error_handler": "strict"
  }
}

Streamable HTTP settings

{
  "transport": "streamable_http",
  "streamable_http": {
    "url": "https://example.com/mcp",
    "headers": {
      "Authorization": "config://my-service-token"
    },
    "timeout_seconds": 30,
    "sse_read_timeout_seconds": 300,
    "terminate_on_close": true
  }
}

HTTP + SSE settings

{
  "transport": "http_sse",
  "http_sse": {
    "url": "https://example.com/mcp",
    "headers": {},
    "timeout_seconds": 15,
    "sse_read_timeout_seconds": 120
  }
}

Configuration values that begin with config:// are resolved through Configuration.get_value, allowing secrets to be stored in Azure App Configuration or Key Vault. Values beginning with env:// are also resolved through Configuration.get_value, enabling environment variable lookups when the platform is configured to allow them.

Values beginning with context:// are runtime system headers resolved at MCP invocation time (HTTP transports only). They are configured in the Management Portal HTTP Headers editor under System / runtime context and are never stored as resolved values.

Token HTTP header Resolved from
context://user_identity X-USER-IDENTITY Signed-in user identity JSON
context://conversation_id X-FLLM-SESSION-ID Conversation/session ID for the current chat

Trusted internal MCP servers that call CoreAPI on behalf of the user (for example the Memory MCP server) typically require X-USER-IDENTITY = context://user_identity. See the Personalized Memory API Reference for the CoreAPI contract those servers must call.

System headers are opt-in: if a header row is not configured, nothing is sent. The MCP client tool does not implicitly inject user identity or session headers.

Example endpoint headers for an internal MCP server (Genesis):

{
  "X-USER-IDENTITY": "context://user_identity",
  "X-FLLM-SESSION-ID": "context://conversation_id"
}

For a full apiEndpointConfigurations resource you can POST via the Management API, see genesis-mcp-endpoint-template.json. Replace the placeholder URL with your Genesis MCP server base URL before creating or updating the endpoint.

External MCP servers (Perplexity, Microsoft Learn, etc.) should typically not include system context headers unless the server explicitly requires them.

Invocation Schema

The tool exposes the following input schema (see FoundationaLLMMCPClientToolInput):

{
  "operation": "list_tools",
  "arguments": {
    "cursor": null
  },
  "transport_overrides": {
    "headers": {"X-MCP-Trace": "123"}
  },
  "response_format": "json"
}
  • operation must match one of the supported ClientSession coroutine names: list_tools, list_resources, read_resource, list_prompts, get_prompt, call_tool, complete, ping, or intelligent_execute.
  • arguments is forwarded directly to the MCP SDK after basic validation (timeouts are converted to timedelta, URLs validated, etc.).
  • transport_overrides applies per-call URL, header, or timeout adjustments on top of the configured transport. Unsupported fields are ignored for non-HTTP transports.
  • response_format can be json (default) or text. JSON responses are pretty-printed before being returned.

Content Artifacts

Each invocation produces a TOOL_EXECUTION artifact containing:

  • The structured response body (JSON by default).
  • Metadata describing the transport (stdio, streamable_http, or http_sse), target endpoint or command, resolved headers/env (with secrets redacted upstream), and initialization payload returned by the MCP server.
  • A normalized record of the request arguments so downstream components can audit calls.

Errors generate an additional TOOL_ERROR artifact populated with the exception details.

Example: Microsoft Learn MCP Server

To connect to the Microsoft Learn MCP server (anonymous HTTP access), configure the tool in the agent's AgentTool definition:

{
  "name": "mslearn_mcp",
  "description": "Call the Microsoft Learn MCP server for training content.",
  "package_name": "foundationallm_agent_plugins",
  "class_name": "FoundationaLLMMCPClientTool",
  "properties": {
    "transport": "streamable_http",
    "streamable_http": {
      "url": "https://learn.microsoft.com/api/mcp",
      "headers": {},
      "timeout_seconds": 30,
      "sse_read_timeout_seconds": 300,
      "terminate_on_close": true
    }
  }
}

Invoke the tool with the following payload to enumerate available tools:

{
  "operation": "list_tools",
  "arguments": {}
}

Intelligent Execute Operation

The MCP Client Tool supports an intelligent_execute operation that uses an LLM to orchestrate multi-turn MCP operations. This provides a simplified interface for complex MCP workflows without requiring the agent to manually discover and execute tools.

Configuration Requirements

To use intelligent_execute, the tool's AgentTool definition must include resource_object_ids entries for:

  1. Main Model — a resource object ID with object_role: "main_model" pointing to a configured FoundationaLLM.AIModel resource. This is resolved at init time via get_main_language_model().
  2. Main Prompt — a resource object ID with object_role: "main_prompt" pointing to a FoundationaLLM.Prompt resource whose prefix field contains the orchestration prompt text. This is resolved via get_main_prompt().

See mcp-orchestration-prompt.md for the recommended orchestration prompt template.

Usage

The intelligent_execute operation accepts a user prompt and automatically:

  1. Discovers available MCP tools via list_tools
  2. Plans the execution strategy using the LLM
  3. Executes the planned MCP operations
  4. Synthesizes results into a coherent response
{
  "operation": "intelligent_execute",
  "arguments": {
    "prompt": "Search Microsoft Learn for MCP documentation"
  }
}

For the MS Learn MCP server, the tool will:

  1. Call list_tools to discover microsoft_docs_search
  2. Use the LLM to map the user prompt to appropriate tool arguments
  3. Execute call_tool with {"name": "microsoft_docs_search", "arguments": {"query": "MCP documentation"}}
  4. Synthesize the search results into a comprehensive response

Token Tracking

The intelligent_execute operation tracks LLM token usage across the planning and synthesis phases. The totals are reported in the returned FoundationaLLMToolResult.input_tokens and output_tokens fields, as well as in the content artifact metadata.

Testing

Tests for the MCP client tool are located at:

src/python/FoundationaLLMAgentPlugins/test/foundationallm_mcp_client_tool/test_tool.py

Note: The test file remains at the legacy FoundationaLLMAgentPlugins location. It should be migrated to src/python/plugins/agent_core/test/ to align with the new plugin directory structure.

Unit tests

Unit tests validate configuration parsing, transport override merging, synchronous/asynchronous execution paths, and artifact generation using mocked sessions.

Integration tests

An integration test exercises the Microsoft Learn MCP server when the MSLEARN_MCP_ENDPOINT environment variable is present. The test is skipped automatically when the endpoint is unavailable.

Running tests

pytest test/foundationallm_mcp_client_tool

Note: The integration test issues live requests; ensure the endpoint is reachable and stable before enabling it in automated pipelines.

Running the Microsoft Learn search integration test

To invoke the microsoft_docs_search tool with the query "How does Azure use Model Context Protocol (MCP)?", set the endpoint and run the targeted test:

$env:MSLEARN_MCP_ENDPOINT = "https://learn.microsoft.com/api/mcp"
pytest test/foundationallm_mcp_client_tool -k mslearn_docs_search -q

To also print request/response details to stdout, run the test in verbose mode:

$env:MSLEARN_MCP_ENDPOINT = "https://learn.microsoft.com/api/mcp"
pytest test/foundationallm_mcp_client_tool -k mslearn_docs_search -v -q

Showing print output

By default, pytest captures print output. To force printing to the console, add -s (disable capture). You can combine this with verbosity:

$env:MSLEARN_MCP_ENDPOINT = "https://learn.microsoft.com/api/mcp"
pytest test/foundationallm_mcp_client_tool -k mslearn_docs_search -vv -s

Relevant switches:

  • -k pattern: run tests matching the substring or expression (e.g., mslearn_docs_search).
  • -v: verbose mode. Shows each test node id as it runs, includes deselected/xfail/xpass summaries, and provides richer assertion diffs.
  • -vv: very verbose. Everything from -v, plus longer/full test node ids (paths and parametrization), more fixture/collection details, and chattier progress output.
  • -s: disable output capturing so print() statements appear in real time.
  • -q: quiet mode; reduces non-essential output (omit when you want more detail).

Alternative (logging instead of prints):

$env:MSLEARN_MCP_ENDPOINT = "https://learn.microsoft.com/api/mcp"
pytest test/foundationallm_mcp_client_tool -k mslearn_docs_search -vv -o log_cli=true -o log_cli_level=INFO

Agent prompt: Using the MCP Client Tool

Use this prompt snippet to guide the agent when working with MCP (Model Context Protocol) servers.

The MCP Client Tool provides a simplified interface where agents can delegate tool discovery, selection, and execution to the tool itself.

Primary Approach: Intelligent Execute

Use intelligent_execute for most scenarios - this allows the agent to provide a natural language prompt and let the MCP Client Tool handle:

  • Discovering available tools on the MCP server
  • Selecting appropriate tools based on the user's request
  • Executing the tools with proper arguments
  • Synthesizing results into a coherent response

Example Usage

{
  "operation": "intelligent_execute",
  "arguments": {
    "prompt": "Search for information about Azure authentication best practices"
  }
}

For Microsoft Learn MCP server, this would automatically:

  1. Discover the microsoft_docs_search tool
  2. Execute the search with appropriate query parameters
  3. Synthesize the results into a comprehensive response

More Examples

{
  "operation": "intelligent_execute",
  "arguments": {
    "prompt": "Find code samples for ASP.NET Core web API development"
  }
}
{
  "operation": "intelligent_execute",
  "arguments": {
    "prompt": "Get the latest documentation on Azure Functions deployment"
  }
}

Manual Approach (Advanced)

When you need precise control over MCP operations, use the manual approach:

Discover Available Tools

{
  "operation": "list_tools",
  "arguments": {}
}

Call Specific Tools

{
  "operation": "call_tool",
  "arguments": {
    "name": "tool_name",
    "arguments": {
      "param1": "value1",
      "param2": "value2"
    },
    "read_timeout_seconds": 30
  },
  "response_format": "json"
}

Other Operations

{
  "operation": "list_resources",
  "arguments": {}
}
{
  "operation": "read_resource",
  "arguments": {
    "uri": "resource://path/to/resource"
  },
  "read_timeout_seconds": 60
}

System Guidance for the Agent

  • Prefer intelligent_execute for most user requests - it handles complexity automatically
  • The MCP Client Tool requires top-level fields: operation and arguments
  • For intelligent_execute, simply provide a clear, descriptive prompt in the arguments.prompt field
  • Use manual operations only when you need specific control or when intelligent_execute doesn't meet your needs
  • Use response_format: "json" and set reasonable timeouts for long operations
  • Token tracking: The tool automatically tracks LLM token usage for intelligent_execute operations

Configuration Requirements

For intelligent_execute to work properly, ensure the tool is configured with:

  1. Main Model Resource: An LLM configured as main_model resource via resource_object_ids
  2. Main Prompt Resource: An orchestration prompt configured as main_prompt resource via resource_object_ids

Answering Behavior

  • Default to intelligent_execute for user queries that involve MCP server interactions
  • Provide clear, descriptive prompts that specify what information the user is seeking
  • Let the tool handle tool discovery and execution - don't manually discover tools unless necessary
  • Present the synthesized results in a user-friendly format
  • Include relevant metadata and links returned by the MCP server when appropriate