mcp-fs
A file server that demonstrates the model
I implemented a rust-based file MCP server that showcases the UI extensions end-to-end. It includes diff views for every file edit and a broader file browser application.
MCP For Humans.
MCP servers can encapsulate data that the user might not have easy access to. This means informing the user of what will be done, what has been done and the overall state of the data can be a challenge.
So I've suggested a few extensions which are inspired by MCP Apps, stay MCP-compatible, opt-in, and do not change normal operations or inflate LLM token use.
There are two challenges: informing a user what a tool call did or will do. And informing the user of the overall state of the system.
It's important to note that the user typically needs different information for this than the LLM.
The first challenge in MCP is informing the user of the impact a particular tool action has. If the user just looks at tool input or output, it might not tell the whole story.
The LLM has a context built up over the conversation which may consist of different tool calls and interactions. Based on that context the LLM decides to perform a tool call to "replace this line with this other line". For the user however, looking just at the input might not be enough. He may want to see the broader context of that line to understands what the replacement means.
At the same time we don't want to add unnecessary tools to the MCP server that the LLM might get confused by. Instead we want to generate side effects that are aimed solely at the user and invisible to the LLM.
In the file server I added to this project (the mcp-fs project), the edit_file tool call
will always generate a visual diff (both unified and side-by-side) for human consumption and a structured diff for automated processing.
If the tool call is simply allowed to pass, it can be stored for later viewing, however the server also supports a _meta.preview boolean toggle.
This makes use of the MCP v2 addition of _meta keys to standardize a "dry run".
The tool will generate the exact same output but not actually apply the change.
The artifacts it generates can then be used to inform the user of what
would happen were he to allow it.
Once allowed, the tool call can be rerun without the preview parameter.
The screenshots are taken in the mcp-test tool which is also available and makes it easy to test the proposed extensions.
Inspired by MCP apps, there is an MCP bridge (available in mcp-ui): a native web
component that renders HTML inside a sandboxed iframe. It exposes
a standard set of CSS variables that can be configured on the
mcp-view, allowing the MCP UI to blend into the host
application.
For the file server, each edit-file
tool call generates a temporary dynamic resource.
If you can inform the user based solely on input/output or existing tools, static resources are also possible.
The link is currently added to the content array.
MCP servers are frequently black boxes. They manage datasets the user might not be able to easily access, such as a remote or containerized instance.
Sometimes the user needs more information regarding the state of the data. This can help him decide which path to take or understand a larger set of changes.
In the example file server I added this takes the form of a "file browser".
It uses the same mcp-ui bridge to inject resources and call its own mcp tools.
Each application is tagged in resource annotations so the host can detect them.
The file browser itself is a Vue 3 app. The standard build is about 75kb raw javascript, and an initial Vue Vapor build drops it to 57kb with more room left to reduce. The goal is to ship lightweight applications.
The host application that embeds the bridge must register a resolver for resources and tool calls to make the flow work.
mcp-fs
I implemented a rust-based file MCP server that showcases the UI extensions end-to-end. It includes diff views for every file edit and a broader file browser application.
mcp-ui
A MCP-Apps inspired native web component to securely render the HTML artifacts while allowing resolving of additional resources and tool calls. It also has a starting point for standardizing css across tools.
mcp-test
A tool to test MCP servers and specifically the UI extensions. It will dynamically detect the applications and content responses.
I wanted to use a set of permissions that is easy for the user to manage at a high level while also allowing the user to dig deeper and configure it in detail when needed.
The goal is to let users tune permissions per session or per agent without drowning them in hundreds of tool-specific toggles. A flat permission list does not scale when you have dozens of MCP tools.
A hierarchical scope layout solves this. Across all tools, the
root capabilities should collapse into a small, clear set like
read, write and execute.
That lets users quickly tune an agent at a broad level before
deciding whether they need finer control.
For example you might easily set up an agent that has read:* but disallowed write:* for a high level distinction.
Scopes can carry detail, e.g.
write:file:/path/to. This
keeps the base policy simple while still allowing fine-grained
control when a specific tool needs it. It also lets you express
cases like
write:file
allowed but
write:database
denied, or vice-versa.
Example: a file server starts with configured roots. If the LLM
tries to write outside those roots, the server returns an error by
default, but also includes
requested_scopes
in
_meta
such as
write:file:/new/path
.
The agent UI can ask the user to allow or deny the request. If the
user approves, the call is replayed with
granted_scopes
.
The grant can be stored for the session or only for that request.
Permission checks and prompts are not handled by the MCP server and do not pass through the LLM. The agent framework mediates approval and decides when to persist grants per session or per agent, based on what the workflow needs.