Description
As per FastMCP's documentation:
Some MCP clients only support tools. They cannot list or read resources directly because they lack resource protocol support.
An example of this is Cursor.
A workaround for this is that FastMCP provides the ResourcesAsTools transform to bridge this gap by exposing list_resources and read_resource as tools.
It would be great if we support this feature here. Would love to open & scope a PR here if it's something we should support.
Additional Implementation Considerations
However, the above still requires tool-only clients (and the LLM using them) to:
- Call
list_resources to discover available resources/templates.
- Identify the relevant URI or URI template.
- Construct the resource URI manually for templates.
- Call
read_resource with that URI.
This is particularly awkward for resource templates, where the parameters are already known by the resource definition but are not exposed as a tool input schema.
For example:
@mcp.resource("user://{user_id}/profile")
def user_profile(user_id: str) -> str:
...
A tool-only client currently has to discover the template and construct:
before calling read_resource.
It would be great if ResourcesAsTools could optionally expose each resource and resource template as an individual tool.
For example:
@mcp.resource("config://app")
def app_config() -> str:
...
@mcp.resource("user://{user_id}/profile")
def user_profile(user_id: str) -> str:
...
mcp.add_transform(ResourcesAsTools(mcp, individual_tools=True))
could expose tools resembling:
app_config()
user_profile(user_id: str)
The generated tools would:
- Reuse the resource's name, description, MIME type, and other metadata where appropriate.
- Derive their input schema from the resource template parameters.
- Internally resolve/read the corresponding resource.
- Preserve the resource URI in the tool result where possible.
- Continue to respect the server's existing middleware, authorization, visibility, and other resource-level behavior.
This would make resources much more natural to consume from clients that only support tools/list / tools/call, while keeping the existing ResourcesAsTools behavior available for applications that prefer the generic list_resources / read_resource interface.
Example
Given:
@mcp.resource("data://{dataset}/{year}")
def dataset(dataset: str, year: int) -> str:
...
a generated tool could look conceptually like:
{
"name": "dataset",
"description": "...",
"inputSchema": {
"type": "object",
"properties": {
"dataset": {"type": "string"},
"year": {"type": "integer"}
},
"required": ["dataset", "year"]
}
}
The client could then simply call:
await client.call_tool(
"dataset",
{"dataset": "election_results", "year": 2022}
)
without needing to know how the underlying resource URI is constructed.
Alternatives considered
If maintainer's want to support this, the existing list_resources + read_resource approach works, but it exposes the resource protocol's URI-oriented abstraction directly to the model. Generating tools would instead let tool-only clients consume the same resources through the interface they already understand.
Proposed Scope
We should PR iteratively:
- Add FastMCP-stype
list_resources and read_resource tools.
- Optional Add
individual_tool=True. This allows for one tool per resource/template with an InputSchema.
Other
References
No response
Description
As per FastMCP's documentation:
An example of this is Cursor.
A workaround for this is that FastMCP provides the
ResourcesAsToolstransform to bridge this gap by exposinglist_resourcesandread_resourceas tools.It would be great if we support this feature here. Would love to open & scope a PR here if it's something we should support.
Additional Implementation Considerations
However, the above still requires tool-only clients (and the LLM using them) to:
list_resourcesto discover available resources/templates.read_resourcewith that URI.This is particularly awkward for resource templates, where the parameters are already known by the resource definition but are not exposed as a tool input schema.
For example:
A tool-only client currently has to discover the template and construct:
before calling
read_resource.It would be great if
ResourcesAsToolscould optionally expose each resource and resource template as an individual tool.For example:
could expose tools resembling:
The generated tools would:
This would make resources much more natural to consume from clients that only support
tools/list/tools/call, while keeping the existingResourcesAsToolsbehavior available for applications that prefer the genericlist_resources/read_resourceinterface.Example
Given:
a generated tool could look conceptually like:
{ "name": "dataset", "description": "...", "inputSchema": { "type": "object", "properties": { "dataset": {"type": "string"}, "year": {"type": "integer"} }, "required": ["dataset", "year"] } }The client could then simply call:
without needing to know how the underlying resource URI is constructed.
Alternatives considered
If maintainer's want to support this, the existing
list_resources+read_resourceapproach works, but it exposes the resource protocol's URI-oriented abstraction directly to the model. Generating tools would instead let tool-only clients consume the same resources through the interface they already understand.Proposed Scope
We should PR iteratively:
list_resourcesandread_resourcetools.individual_tool=True. This allows for one tool per resource/template with anInputSchema.Other
References
No response