
ML Monday – Functional LangGraph with MCP
For the first Machine Learning Monday of this series, I spent a couple of hours setting up a basic LangGraph workflow that will be used to manage at least the main thread of an agentic workflow in my new side project. (See here for the daily plan).
I previously spent a weekend setting up a small python app demonstrating the use of Anthropic’s Model Context Protocol (MCP) that you can read about here. So, today’s work was mostly taking the parts I like from that, and deciding how to start splitting things up in a way that will allow me to take advantage of a serverless deployment architecture down the line.
This post is going to be a bit bare bones because I had to do a bunch of other stuff to get things going. In the future, expect pretty pictures/diagrams/examples, etc.
For now, here are a few thoughts/takeaways:
- I like using this dependency injection framework – It helps collect app configuration in one place, a
config.ymlfile (or technically two, since you also need to set up theContainersthat handle the dependency injection incontainers.py). For testing, any part can be easily overridden via awith container.override(...):block. - The new LangGraph Functional API seems pretty nice – It doesn’t end up saving LOC compared to the graph interface, but so far, I find it easier to read, and I hope that it will be easier to debug! You technically loose a bit of flexibility, but you can always call sub-graphs if needed to get back the deepest levels of control.
- MCP Client implementations are still pretty immature in both the official python-sdk and LangChain’s MCP adapters – I don’t want to re-invent the wheel, but I also want some insulation from breaking changes. I’m tackling this with a custom
GraphRunAdapterwhere I exclusively implement methods that I’m actually interested in using internally, in addition to my own subclass of the LC MCP client implementation. TheGraphRunAdapteruses my subclass of the LC client (so I can easily patch or fix behavior that I don’t like, without having to re-implement everything), and the rest of the code usesGraphRunAdapterso that any breaking changes from dependencies only need to be addressed in one place, and that’s the only place I ever need to think about the internals of langchain’s implementation.
In this session, I got to the point of the agent graph running with a test chat model, but I still have to deal with an issue related to a connection error between my MCP client and the “everything” MCP server.
Next steps
- Fix the MCP connection issue
- Check that tool calls can be made
- Check that the main agent can carry out multiple steps of thought before responding to the user
Further down the line
- Make the graph interruptable/resumable
- Make some configuration modifiable by user (e.g. prompt templates)
- Handle situations where context gets too large (either from long conversation, or tool returning too much information)
- Allow recursive call to the same graph as a sub-graph (this unlocks a LOT of customization of workflows via configuration only)