Skip to content

Mcp app 2#17

Open
MatthewKhouzam wants to merge 7 commits into
eclipse-tmll:mainfrom
MatthewKhouzam:mcp-app-2
Open

Mcp app 2#17
MatthewKhouzam wants to merge 7 commits into
eclipse-tmll:mainfrom
MatthewKhouzam:mcp-app-2

Conversation

@MatthewKhouzam
Copy link
Copy Markdown
Contributor

@MatthewKhouzam MatthewKhouzam commented May 12, 2026

What it does

Overhauls the MCP server to be production-ready for MCP stdio transport and adds several new capabilities:

  • Fix stdout corruption: Redirects logger and TSP output to stderr so they don't corrupt the JSON-RPC stdio transport. Adds a _StderrWithBuffer class that globally protects stdout while preserving the binary .buffer for MCP's I/O.
  • Simplify server: Removes verbose debug logging (_log, _safe_tool decorator) and simplifies run_cli error handling.
  • Rewrite plot_xy_with_anomalies: Returns JSON series data for MCP Apps iframe rendering. Adds as_image parameter — True (default) returns a PNG via matplotlib, False returns self-contained HTML with Plotly bundled inline.
  • Add MCP Apps UI resource: Registers a ui://tmll/xy-anomalies.html resource with interactive Plotly charts for sandboxed iframe rendering.
  • Mark read-only tools as non-destructive: Adds ToolAnnotations(readOnlyHint=True, destructiveHint=False) to query tools so MCP clients can auto-approve them.
  • Expose experiments as MCP resources: Adds experiment:// resource template and dynamic list_resources override to enumerate open experiments.
  • Docs: Updates README with plot_xy_with_anomalies tool, removes stale cluster reference.
  • CLI fix: Defaults resample-freq/min-size to None so module defaults apply instead of hardcoded values.

How to test

  1. Start the trace server: python tmll/mcp/server.py tmll/mcp/cli.py

  2. Use the MCP inspector to verify tools work without stdout corruption:

    npx @modelcontextprotocol/inspector python3 tmll/mcp/server.py tmll/mcp/cli.py

  3. Verify read-only tools show readOnlyHint: true in tool annotations.

  4. Test plot_xy_with_anomalies:
    - With as_image=True (default): should return a PNG image.
    - With as_image=False: should return JSON with { "type": "html", "html": "..." }.

  5. Verify list_resources returns open experiments as experiment:// resources.

  6. Run the CLI directly to confirm detect-anomalies works without explicit --resample-freq:

    python tmll/mcp/cli.py detect-anomalies -k "cpu usage"

Follow-ups

  • inspect.sh is a developer convenience script — consider adding it to .gitignore or removing before merge.
  • The _last_xy_payload global state for the MCP Apps resource is not thread-safe; acceptable for single-client stdio transport but would need rework for SSE/multi-client.
  • The dynamic list_resources override monkey-patches mcp.list_resources — consider upstreaming a proper hook to FastMCP.
  • The bundled plotly-basic.min.js (v2.35.2) adds ~8 lines to the repo; consider fetching at build time or documenting the update process.

Review checklist

  • No stdout writes in the MCP server code path (all go to stderr)
  • Tool annotations correctly mark read-only vs. destructive tools
  • plot_xy_with_anomalies docstring is clear enough to prevent LLM hallucination
  • CLI argument defaults don't break existing usage
  • HTML template properly sandboxes Plotly (no external fetches)
  • As an author, I have thoroughly tested my changes and carefully followed the instructions in this template

The Logger class and tsp submodule wrote to sys.stdout, corrupting
the JSON-RPC transport when running as an MCP server over stdio.

- Logger: write to sys.stderr instead of sys.stdout
- tsp submodule: error prints go to sys.stderr

This patch was made with claude opus 4.6

Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Remove verbose debug logging (_log, _safe_tool decorator) and simplify
run_cli error handling. Add _StderrWithBuffer class that redirects
sys.stdout text writes to stderr while preserving .buffer for MCP's
binary stdio transport.

this code was made with the assistance of claude opus 4.6

Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Rewrite the plot tool to produce JSON series data for MCP Apps iframe
rendering, with as_image=True (default) returning a PNG via matplotlib.
When as_image=False, returns self-contained HTML with Plotly bundled
inline for sandboxed iframe rendering.

- Add as_image parameter (default True) for PNG output
- Return inline HTML with bundled Plotly when as_image=False
- Add MCP Apps ui:// resource for interactive iframe chart
- Improve docstring to reduce LLM hallucination on parameter usage
- CLI: default resample-freq/min-size to None so module defaults apply
- ML modules: simplify _process to inline preprocessing, pass min_size
  as explicit kwarg

This code was written with the assistance of claude opus 4.6

Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Add ToolAnnotations(readOnlyHint=True, destructiveHint=False) to all
query tools so MCP clients can auto-approve them without user
confirmation. Improve list_experiments docstring to guide LLMs toward
resolving experiment names to UUIDs.

This code was generated with the assistance of claude opus 4.6

Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Add experiment:// resource template and dynamic list_resources override
that enumerates all open experiments from the trace server, allowing
MCP clients to browse experiments without calling tools.

This code was was generated with claude sonnet 4.6

Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
…er reference

Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Needs mcp inspector.

Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Copy link
Copy Markdown
Contributor

@kavehshahedi kavehshahedi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Just a point of discussion; As the MCP is now evolving, I feel that it might be decoupled from the tmll repository itself, and be moved to an independent repo (e.g., eclipse-tmll/tmll-mcp). As currently the MCP is evolving rapidly, and also, introducing new codes/features/etc., developing it in its own environment might be cleaner.

What do you think, Matthew?

Comment thread tmll/mcp/server.py
Comment on lines +355 to +357
def get_experiment_resource(experiment_id: str) -> str:
"""Return details for a specific experiment."""
return run_cli("list")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the experiment_id was not used here? I mean, does the run_cli("list") return the info for the currently loaded experiment?

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.

2 participants