MCP Server Part 8: MCP server routes#3750
Conversation
|
Thank you for your contribution to Dash! 🎉 This PR is exempt from requiring a linked issue due to its labels. |
876285b to
43c15b2
Compare
|
Hi Plotly team! First of all, thanks for integrating MCP into Dash - this looks really exciting!
Let me know what you think - if you see it the same way or if I overlooked something! Would also love to contribute these changes :) Best regards, |
8c1f392 to
f9b05da
Compare
43c15b2 to
f03c72f
Compare
|
Hey @chgiesse Thanks for the comments, and happy to see the excitement around the feature!
And absolutely, I'd welcome any contributions you have towards this effort - there's tons of potential to make Dash apps even more LLM friendly! Adrian |
f9b05da to
bc340e6
Compare
d3e1e19 to
976e0df
Compare
bc340e6 to
b3d4015
Compare
20d3ee7 to
bb25991
Compare
b3d4015 to
e407569
Compare
bb25991 to
9cc9959
Compare
e407569 to
37e92f0
Compare
9cc9959 to
e84d208
Compare
37e92f0 to
28d5fed
Compare
e84d208 to
943d9b2
Compare
|
Hi @KoolADE85 Thanks for the response and making it compatible! Looking forward to use it! Yes I also think that the functionality without sse is already a good starting point. Maybe providing it together with a native sse callback? :) |
28d5fed to
f098f88
Compare
ac43cd0 to
8d7b8ba
Compare
f098f88 to
79df12e
Compare
e0662fc to
3c39eac
Compare
f1b6cc2 to
d25123b
Compare
3c39eac to
a1ca057
Compare
a1ca057 to
409be55
Compare
…0 for missing session)
409be55 to
b788678
Compare
| [ | ||
| { | ||
| "id": str(comp.id), | ||
| "id": str(getattr(comp, "id", None)), |
There was a problem hiding this comment.
Doesn't line 49 guarantee that id exists?
| if pattern is None: | ||
| return None | ||
| matches = find_matching_components(pattern) |
There was a problem hiding this comment.
| if pattern is None: | |
| return None | |
| matches = find_matching_components(pattern) | |
| matches = find_matching_components(pattern) if pattern else None |
| dep: CallbackDependency, value: Any | ||
| ) -> CallbackInput | list[CallbackInput]: | ||
| def _expand_dep(dep: CallbackDependency, value: Any) -> CallbackInputs: | ||
| """Attach a concrete value to a callback dependency to produce a valid callback input. |
There was a problem hiding this comment.
Claude 😠!
| """Attach a concrete value to a callback dependency to produce a valid callback input. | |
| """ | |
| Attach a concrete value to a callback dependency to produce a valid callback input. |
| concrete_ids = [comp.id for comp in find_matching_components(pattern)] | ||
| expanded = [{"id": cid, "property": prop} for cid in concrete_ids] | ||
| concrete_ids = [ | ||
| getattr(comp, "id") for comp in find_matching_components(pattern) |
There was a problem hiding this comment.
Could comp be None here?
| if func is not None: | ||
| return _wrap(func) | ||
| return _wrap |
There was a problem hiding this comment.
Do you need to return the wrapping function here?
| app.mcp_decorated_functions = dict(MCP_DECORATED_FUNCTIONS) | ||
| MCP_DECORATED_FUNCTIONS.clear() | ||
|
|
||
| _session_id: str | None = None |
There was a problem hiding this comment.
Could you look into what would happen to this value if multiple users attempt to connect at the same time? Would some users end up with the wrong session id? It's a classic TOCTOU race condition 🙄.
Could multiple gunicorn works get there own session id? You mentioned this during our review.
Summary
This PR pulls together everything from the previous PRs into a working MCP server you can connect to from any MCP-compatible LLM agent. Example:
enable_mcpandmcp_pathconstructor params, (orDASH_MCP_ENABLED/DASH_MCP_PATHenv vars)