Skip to content

[Idea] Delayed Registration of Instance Methods #175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

strawgate
Copy link
Contributor

Related to: #174

Add delay_registration to the tool decorator (as an example) and a method on the MCP Server to perform delayed registration.

See both objects get their own tools, which are callable, and return data from the data in the corresponding instance.
Screenshot 2025-04-15 at 5 55 22 PM

The prefix implementation is a bit sloppy, ideally prefix would be supported natively on the decorators but anyway

@Copilot Copilot AI review requested due to automatic review settings April 15, 2025 22:56
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (1)

src/fastmcp/server/server.py:359

  • The parameter name 'object' shadows the built-in type. Consider renaming it (e.g., 'instance' or 'obj') for clarity.
def perform_delayed_registration(self, prefix: str, object: object) -> None:

@jlowin
Copy link
Owner

jlowin commented Apr 16, 2025

This feels to me like it has a lot of overloaded responsibility and extremely tight coupling -- the decorators are tied to a specific mcp instance, which needs to be invoked again later to call mcp.perform_delayed_registration. In the given sample, it seems preferable to simply call mcp.tool()(first_sample.first) explicitly which leaves no mystery about what's happening. It feels a bit outside the scope of the actual FastMCP responsibility.

My suggestion instead is to create a class (below, MCPRegisterable) that has its own decorator (mcp_tool) which collects functions to be used as tools, and then have that class have a register_tools() method that applies those tools to any FastMCP instance. This will avoid the tight coupling and require no changes to FastMCP, while achieving the same goal with considerably greater flexibility

The pseudocode would be:

from src.fastmcp import FastMCP
from some_module import MCPRegisterable, mcp_tool

mcp = FastMCP()

class Sample(MCPRegisterable):
    def __init__(self, name):
        self.name = name
        super().__init__()

    @mcp_tool()
    def first_tool(self):
        """First tool description."""
        return f"Executed first tool {self.name}."

    @mcp_tool()
    def second_tool(self):
        """Second tool description."""
        return f"Executed second tool {self.name}."

first_sample = Sample("First")
second_sample = Sample("Second")

first_sample.register_tools(mcp)
second_sample.register_tools(mcp)

def main():
    mcp.run("sse")

if __name__ == "__main__":
    main()

@strawgate
Copy link
Contributor Author

Thanks for taking a look and for the feedback. I'll take a look at making something like McpRegisterable and will follow-up unless you've already got an implementation in mind

@strawgate strawgate closed this Apr 16, 2025
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