Integrating with LangChain agentic framework
Complete the following steps to integrate the remote MCP server with LangChain and enable AI agents to invoke tools using custom metadata:
Note: All steps below are intended to be executed within a Python environment, specifically within a Jupyter notebook.
-
Run the following code to install dependencies.
!pip3 install langchain_core langchain_mcp_adapters langchain_ibm langchain fastmcp -
Run the following code to add environment variables.
os.environ["WATSONX_API_KEY"]="<>" os.environ["WATSONX_PROJECT_ID"]="<>" os.environ["WATSONX_URL"]="<>" os.environ["MCP_ENDPOINT"]="<>"Note:- To obtain your
WATSONX_API_KEY, refer API keys. - To find your
WATSONX_PROJECT_ID, navigate to your project in the watsonx.ai web console, click theManagetab, and locate theProject IDunder theGeneral Informationsection. - For
WATSONX_URL, refer Introduction to IBM watsonx.ai Runtime and choose the correct instance URL based on your region.
- To obtain your
-
Run the following code to imprort dependencies.
from fastmcp import Client import os from langchain.agents import create_agent -
Run the following code to load tools from the remote MCP server.
authToken = "" config = { "mcpServers": { "server_name": { "transport": "streamable-http", "url": os.getenv("MCP_ENDPOINT"), "headers": {"Authorization": f"Bearer {authToken}"}, }, } } client = Client(config) async with client: # Initialize the connection await client.ping() # Get tools tools = await client.list_tools() print(tools) print("\n",len(tools))Note:To generate
authToken, refer Authentication. -
Run the following code to set up ChatWatsonx llm.
from langchain_ibm import ChatWatsonx llm = ChatWatsonx( model_id="mistralai/mistral-medium-2505", url = os.getenv("WATSONX_URL"), apikey = os.getenv("WATSONX_API_KEY"), project_id = os.getenv("WATSONX_PROJECT_ID"), temperature=0, max_completion_tokens=15000 ) -
Run the following code to define progress handler callback.
async def progress_handler( progress: float, total: float | None, message: str | None ) -> None: if total is not None: percentage = (progress / total) * 100 print(f"Progress: {percentage:.1f}% - {message or ''}") else: print(f"Progress: {progress} - {message or ''}") -
Run the following code to patch tools with progress handler.
from langchain_core.tools import StructuredTool from langchain_mcp_adapters.tools import _convert_call_tool_result def patch_tools_with_progress_handler(tools, session): wrapped = [] for tool in tools: async def wrapper(_tool=tool,**kwargs): call_tool_result = None mcp_tool_name = _tool.name # Call the tool using the progress handler call_tool_result = await session.call_tool( mcp_tool_name, kwargs, progress_callback=progress_handler ) if call_tool_result is None: raise RuntimeError( "Tool call failed: no result returned from the underlying MCP SDK. " "This may indicate that an exception was handled or suppressed " "by the MCP SDK (e.g., client disconnection, network issue, " "or other execution error)." ) # Use the original call_tool converter return _convert_call_tool_result(call_tool_result) # Create a NEW StructuredTool wrapped_tool = StructuredTool.from_function( name=tool.name, description=tool.description, args_schema=tool.args_schema, coroutine=wrapper, metadata=tool.metadata, response_format="content_and_artifact", ) wrapped.append(wrapped_tool) return wrapped -
Run the following code to invoke the agent.
from langchain_core.messages import AIMessage, SystemMessage, HumanMessage from langchain_mcp_adapters.tools import load_mcp_tools client = Client(config) async with client: # Initialize the connection await client.ping() tools = await client.list_tools() tools = await load_mcp_tools(session=client.session) wrapper_tools = patch_tools_with_progress_handler(tools,client.session) agent = create_agent( model=llm, tools=wrapper_tools, ) guidance_prompt_with_query = await client.session.get_prompt(name="workflow_guidance") print("Guidance Prompt: ", guidance_prompt_with_query) prompt_text = guidance_prompt_with_query.messages[0].content.text messages = [SystemMessage(content=prompt_text)] print("\n--- Agent Ready ---\n") while True: user_input = input("Human: ") if user_input.strip().lower() in {"q", "quit", "exit"}: print("Exiting...") break messages.append(HumanMessage(content=user_input)) result = await agent.ainvoke({"messages": messages}) ai_msg = result["messages"][-1] print("AI:", ai_msg.content) messages.append(ai_msg)
Parent topic: IBM watsonx.data remote Model Context Protocol (MCP) server