Skip to content

Conversation

streamnsight
Copy link

@streamnsight streamnsight commented Aug 14, 2025

usage:
On the MCP server side, specify the key to map to the state with annotations:

@mcp.tool(annotations={"injected_state": "state"}) 
def tool(a: int = 0, b: Union[str, None] = None, state):
   pass

On the client side, it is handled automatically by the added code.

Caveat:

  • trying to parse most types (base type, List, Unions, Literal, Optional) and default values, but probably not complete.
  • no implementation for the converter from langchain tool to mcp tool at the moment

@streamnsight streamnsight marked this pull request as ready for review August 15, 2025 21:11
@streamnsight
Copy link
Author

@eyurtsev for review.
Thanks

@streamnsight
Copy link
Author

@eyurtsev
Any chance you can give this one a look?
Thanks

@eyurtsev
Copy link
Collaborator

eyurtsev commented Sep 9, 2025

This feature needs more up front design before we can add an implementation

Could you explain the motivation and use case?

@eyurtsev eyurtsev self-assigned this Sep 9, 2025
@streamnsight
Copy link
Author

@eyurtsev
The use case is Langgraph InjectedState. It's a feature of Langgraph and it is not supported by MCP. This PR is resolving this.
Many tools use state to keep track of things going on between calls, for example you might have looked up a user Id and calling the next tool. You can rely on the LLM to pass the id correctly but more reliably you can store it in state and pass it to the next tool that way. Problem is this is injected by langgraph, not visible to the LLM, but it is needed when calling the tool. If the tool on the MCP side is defined with injected state as a param, it will show as a regular param to the LLM. So this PR performs the propagation and filtering of injected state when creating the tools.

Now, there is a potential security issue here were a MCP requesting agent state would get it from the client by just asking for it this way. We might need a flag to prevent propagating state by default.

@eyurtsev
Copy link
Collaborator

eyurtsev commented Sep 10, 2025

Why is a tool that is working with agent state being defined in an MCP server that should not know any specifics about the caller (e.g., not know that the caller uses langgraph, and should ideally not be aware that langgraph even exists)? Why is this tool not defined along side the agent?


Could you describe a bit more of what use case you're solving? (not the solution / implementation)

@streamnsight
Copy link
Author

because we want to maintain tools as a separate entity.
In enterprise use cases, we build private MCP that may need to be reused in multiple places. Of course I get your point of the agent not knowing what the state should be, but if you set your own conventions for that, that is a pattern that is useful. For an open-source/public MCP, that would not make much sense. agreed, but for all the other times you want to separate your tools from your client, it's convenient.

as for the suggestion of having some local tool calling on the MCP, then there is no point of having these tools in MCP; they might as well be an API server, called by those local tools. The point of MCP is that it can be called by the LLM directly.

In our particular use case, we add auth/RBAC to the MCP to authorize tools that the user can use, via existing middleware for MCP. Doing this locally would mean reinventing all that logic on the agent and tool node.

@yukovatce
Copy link

Basically there is the only reason: when you don't want to rely on LLM to pass some data (because of undeterministic nature), which can be critical in some contexts, like money numbers for example, but event the user ID or tenant ID could be critical.
Therefore we need a mechanism, where we can inject values from LangGraph state into the MCP tool, which is dynamically configured (enterprise context, agentic systems, different customer configurations, etc)

@PeriniM
Copy link

PeriniM commented Sep 20, 2025

Hey, could this be related to this PR. If the _meta param is exposed, you could pass additional metadata from the tool invocation and use it server side like here.

MCP main docs reference

@streamnsight
Copy link
Author

re-opened here #321

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants