Repository: jlowin/fastmcp
Pull request #144 (2025-04-14 01:55:13)

Update docs and add_resource_fn


Patch:
diff --git a/docs/getting-started/welcome.mdx b/docs/getting-started/welcome.mdx
index b0b1166..b8d80de 100644
--- a/docs/getting-started/welcome.mdx
+++ b/docs/getting-started/welcome.mdx
@@ -27,9 +27,9 @@ if __name__ == "__main__":
 ## What is MCP?
 The Model Context Protocol lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. It is often described as "the USB-C port for AI", providing a uniform way to connect LLMs to resources they can use. It may be easier to think of it as an API, but specifically designed for LLM interactions. MCP servers can:
 
-- Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
-- Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
-- Define interaction patterns through **Prompts** (reusable templates for LLM interactions)
+- Expose data through `Resources` (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
+- Provide functionality through `Tools` (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
+- Define interaction patterns through `Prompts` (reusable templates for LLM interactions)
 - And more!
 
 There is a low-level Python SDK available for implementing the protocol directly, but FastMCP aims to make that easier by providing a high-level, Pythonic interface.
diff --git a/docs/patterns/decorating-methods.mdx b/docs/patterns/decorating-methods.mdx
index c49fe07..906142c 100644
--- a/docs/patterns/decorating-methods.mdx
+++ b/docs/patterns/decorating-methods.mdx
@@ -5,11 +5,11 @@ description: Properly use instance methods, class methods, and static methods wi
 icon: at
 ---
 
-FastMCP's decorator system is designed to work with functions, but you may see unexpected behavior if you try to decorate an instance or class method. This guide explains the correct approach for using methods with all FastMCP decorators (`@mcp.tool()`, `@mcp.resource()`, and `@mcp.prompt()`).
+FastMCP's decorator system is designed to work with functions, but you may see unexpected behavior if you try to decorate an instance or class method. This guide explains the correct approach for using methods with all FastMCP decorators (`@tool()`, `@resource()`, and `@prompt()`).
 
 ## Why Are Methods Hard?
 
-When you apply a FastMCP decorator like `@mcp.tool()`, `@mcp.resource()`, or `@mcp.prompt()` to a method, the decorator captures the function at decoration time. For instance methods and class methods, this poses a challenge because:
+When you apply a FastMCP decorator like `@tool()`, `@resource()`, or `@prompt()` to a method, the decorator captures the function at decoration time. For instance methods and class methods, this poses a challenge because:
 
 1. For instance methods: The decorator gets the unbound method before any instance exists
 2. For class methods: The decorator gets the function before it's bound to the class
@@ -56,7 +56,10 @@ class MyClass:
 # Create an instance first, then add the bound methods
 obj = MyClass()
 mcp.add_tool(obj.add)
-mcp.add_resource(obj.get_resource, uri="resource://{param}")  # For resources
+mcp.add_resource_fn(obj.get_resource, uri="resource://{param}")  # For resources or templates
+
+# Note: FastMCP provides add_resource() for adding Resource objects directly and
+# add_resource_fn() for adding functions that generate resources or templates
 
 # Now you can call it without 'self' showing up as a parameter
 await mcp.call_tool('add', {'x': 1, 'y': 2})  # Returns 3
@@ -167,7 +170,7 @@ class ComponentProvider:
     def __init__(self, mcp_instance):
         # Register methods
         mcp_instance.add_tool(self.tool_method)
-        mcp_instance.add_resource(self.resource_method, uri="resource://data")
+        mcp_instance.add_resource_fn(self.resource_method, uri="resource://data")
     
     def tool_method(self, x):
         return x * 2
@@ -191,8 +194,8 @@ The class automatically registers its methods during initialization, ensuring th
 While FastMCP's decorator pattern works seamlessly with regular functions and static methods, for instance methods and class methods, you should add them after creating the instance or class. This ensures that the methods are properly bound before being registered.
 
 These patterns apply to all FastMCP decorators and registration methods:
-- `@mcp.tool()` and `mcp.add_tool()`
-- `@mcp.resource()` and `mcp.add_resource()`
-- `@mcp.prompt()` and `mcp.add_prompt()`
+- `@tool()` and `add_tool()`
+- `@resource()` and `add_resource_fn()`
+- `@prompt()` and `add_prompt()`
 
 Understanding these patterns allows you to effectively organize your components into classes while maintaining proper method binding, giving you the benefits of object-oriented design without sacrificing the simplicity of FastMCP's decorator system.
diff --git a/examples/smart_home/src/smart_home/hub.py b/examples/smart_home/src/smart_home/hub.py
index 55239b8..41aba82 100644
--- a/examples/smart_home/src/smart_home/hub.py
+++ b/examples/smart_home/src/smart_home/hub.py
@@ -7,7 +7,7 @@ from smart_home.settings import settings
 hub_mcp = FastMCP(
     "Smart Home Hub (phue2)",
     dependencies=[
-        "smart_home@git+https://github.com/jlowin/fastmcp.git#subdirectory=examples/smart_home",
+        "smart_home@git+https://github.com/jlowin/fastmcp.git@n8example#subdirectory=examples/smart_home",
     ],
 )
 
diff --git a/examples/smart_home/src/smart_home/lights/server.py b/examples/smart_home/src/smart_home/lights/server.py
index bd4d0fc..e9946ac 100644
--- a/examples/smart_home/src/smart_home/lights/server.py
+++ b/examples/smart_home/src/smart_home/lights/server.py
@@ -25,7 +25,7 @@ class HueAttributes(TypedDict, total=False):
 lights_mcp = FastMCP(
     "Hue Lights Service (phue2)",
     dependencies=[
-        "smart_home@git+https://github.com/jlowin/fastmcp.git#subdirectory=examples/smart_home",
+        "smart_home@git+https://github.com/jlowin/fastmcp.git@n8example#subdirectory=examples/smart_home",
     ],
 )
 
diff --git a/src/fastmcp/server/server.py b/src/fastmcp/server/server.py
index 1633e9d..a6e7119 100644
--- a/src/fastmcp/server/server.py
+++ b/src/fastmcp/server/server.py
@@ -372,7 +372,7 @@ class FastMCP(Generic[LifespanResultT]):
 
         self._resource_manager.add_resource(resource)
 
-    def add_resource_from_fn(
+    def add_resource_fn(
         self,
         fn: AnyFunction,
         uri: str,


Test patch:
diff --git a/tests/server/test_server.py b/tests/server/test_server.py
index 9c479a6..004e113 100644
--- a/tests/server/test_server.py
+++ b/tests/server/test_server.py
@@ -269,7 +269,7 @@ class TestResourceDecorator:
                 return f"{self.prefix} Hello, world!"
 
         obj = MyClass("My prefix:")
-        mcp.add_resource_from_fn(
+        mcp.add_resource_fn(
             obj.get_data, uri="resource://data", name="instance-resource"
         )
 
@@ -286,7 +286,7 @@ class TestResourceDecorator:
             def get_data(cls) -> str:
                 return f"{cls.prefix} Hello, world!"
 
-        mcp.add_resource_from_fn(
+        mcp.add_resource_fn(
             MyClass.get_data, uri="resource://data", name="class-resource"
         )
 
@@ -390,7 +390,7 @@ class TestTemplateDecorator:
 
         obj = MyClass("My prefix:")
 
-        mcp.add_resource_from_fn(
+        mcp.add_resource_fn(
             obj.get_data, uri="resource://{name}/data", name="instance-template"
         )
 
@@ -407,7 +407,7 @@ class TestTemplateDecorator:
             def get_data(cls, name: str) -> str:
                 return f"{cls.prefix} Data for {name}"
 
-        mcp.add_resource_from_fn(
+        mcp.add_resource_fn(
             MyClass.get_data, uri="resource://{name}/data", name="class-template"
         )