mcp_client.py module, and a step-by-step explanation of each section so you can see how the pieces fit together.
Shell (context)
mcp_client.py
- Standard library:
json,os,Path, andtyping.Anyfor I/O, environment handling, and type hints. dotenv.load_dotenv: loads environment variables from a.envfile at the project root (viaPath(__file__).parents[3]).- LangChain:
create_agent— build the agent with an LLM and available tools.HumanMessage/BaseTool— message and tool abstractions used by LangChain agents.
- LLM client:
ChatOpenAI— a wrapper compatible with OpenAI-style LLM endpoints. - MCP tool conversion:
convert_mcp_to_langchain_tools— performs the MCP handshake and returns LangChain-ready tool objects so you don’t have to manually define tool schemas.
- The module expects a
.envat your project root with values required to construct the LLM client. Typical variables:OPENAI_MODEL_IDOPENAI_BASE_URLOPENAI_API_KEY- Optional tuning:
OPENAI_TEMPERATURE,OPENAI_MAX_TOKENS
- These are read by
build_llm()to initializeChatOpenAI.
Do not commit your real
.env to source control. The .env contains secrets (API keys) and should remain local or be injected via secure CI/CD secret management.
MCP URL and transport
MCP_URLdefaults tohttp://localhost:8000/mcpto match the locally run MCP container. Override withK8S_MCP_URLas needed.MCP_SERVERSsets up the server description used byconvert_mcp_to_langchain_toolsand specifiestransport: "streamable_http"(the transport used by the MCP container in this setup).
convert_mcp_to_langchain_toolsperforms discovery/handshake with MCP and returns tool objects that the LangChain agent understands. This removes manual tool wiring and keeps your application focused on prompts and orchestration.
decode_tool_result
- MCP tool outputs vary: some return Python dictionaries, others return JSON strings.
decode_tool_resultnormalizes either format into a predictabledictwith a safe fallback{"items": []}for empty/invalid outputs. Use this when consuming raw tool results to simplify downstream logic.
tool_by_name
- Simple utility that searches a list of LangChain tools by
.name. It raises a clearRuntimeErrorif the requested tool isn’t available, making debugging easier when a tool is missing.
get_mcp_tools
- Calls
convert_mcp_to_langchain_tools(MCP_SERVERS)and returns(tools, cleanup). Thecleanupcoroutine should be awaited when you’re finished with the tools to clean up any background connections.
build_llm
- Creates a configured
ChatOpenAIinstance from environment variables. You can overridemax_tokenswhen calling this function orrun_agent.
run_agent
This function encapsulates the minimal, robust loop for an agent-based call:
- Discover MCP tools and obtain a
cleanupcoroutine. - Build the LLM using
build_llm. - Create a LangChain agent with
create_agent. - Invoke the agent using
agent.ainvoke(...)with a singleHumanMessagecontaining your prompt. - Return the agent’s final assistant message content.
- Ensure
cleanup()is awaited in afinallyblock so resources are always released.
- Call
run_agent(prompt, max_tokens=...)from your application. The shared client handles discovery, LLM construction, agent orchestration, invocation, and cleanup. Your application code only needs to compose the user-facing prompt.
- If tools are not discovered, verify
K8S_MCP_URLand that the MCP container is reachable. - Ensure your
.envvariables match the expected names and values; missing or malformed keys will causebuild_llm()to fail. - Use
tool_by_name(tools, "tool-name")to validate that a specific tool exists before attempting to call it.
- The follow-up article will demonstrate a concise prompt that uses these helpers to call MCP tools and produce concrete answers. It will include examples of interpreting tool outputs and combining multiple tool calls in an agent workflow.