File size: 3,338 Bytes
d4adea4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224caf9
d4adea4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224caf9
9cc5eae
d4adea4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc7ce68
 
 
d4adea4
 
224caf9
9cc5eae
d4adea4
 
 
 
 
 
37a07a4
d4adea4
 
 
37a07a4
d4adea4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37a07a4
d4adea4
 
dc7ce68
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
"""Example of mounting FastMCP apps together.

This example demonstrates how to mount FastMCP apps together using
the ToolManager's import_tools functionality. It shows how to:

1. Create sub-applications for different domains
2. Mount those sub-applications to a main application
3. Access tools with prefixed names and resources with prefixed URIs
"""

import asyncio

from fastmcp import FastMCP

# Weather sub-application
weather_app = FastMCP("Weather App")


@weather_app.tool
def get_weather_forecast(location: str) -> str:
    """Get the weather forecast for a location."""
    return f"Sunny skies for {location} today!"


@weather_app.resource(uri="weather://forecast")
async def weather_data():
    """Return current weather data."""
    return {"temperature": 72, "conditions": "sunny", "humidity": 45, "wind_speed": 5}


# News sub-application
news_app = FastMCP("News App")


@news_app.tool
def get_news_headlines() -> list[str]:
    """Get the latest news headlines."""
    return [
        "Tech company launches new product",
        "Local team wins championship",
        "Scientists make breakthrough discovery",
    ]


@news_app.resource(uri="news://headlines")
async def news_data():
    """Return latest news data."""
    return {
        "top_story": "Breaking news: Important event happened",
        "categories": ["politics", "sports", "technology"],
        "sources": ["AP", "Reuters", "Local Sources"],
    }


# Main application
app = FastMCP(
    "Main App", dependencies=["fastmcp@git+https://github.com/jlowin/fastmcp.git"]
)


@app.tool
def check_app_status() -> dict[str, str]:
    """Check the status of the main application."""
    return {"status": "running", "version": "1.0.0", "uptime": "3h 24m"}


# Mount sub-applications
app.mount("weather", weather_app)

app.mount("news", news_app)


async def get_server_details():
    """Print information about mounted resources."""
    # Print available tools
    tools = app._tool_manager.list_tools()
    print(f"\nAvailable tools ({len(tools)}):")
    for tool in tools:
        print(f"  - {tool.name}: {tool.description}")

    # Print available resources
    print("\nAvailable resources:")

    # Distinguish between native and imported resources
    # Native resources would be those directly in the main app (not prefixed)
    native_resources = [
        uri
        for uri in app._resource_manager._resources
        if not (uri.startswith("weather+") or uri.startswith("news+"))
    ]

    # Imported resources - categorized by source app
    weather_resources = [
        uri for uri in app._resource_manager._resources if uri.startswith("weather+")
    ]
    news_resources = [
        uri for uri in app._resource_manager._resources if uri.startswith("news+")
    ]

    print(f"  - Native app resources: {native_resources}")
    print(f"  - Imported from weather app: {weather_resources}")
    print(f"  - Imported from news app: {news_resources}")

    # Let's try to access resources using the prefixed URI
    weather_data = await app.read_resource("weather+weather://forecast")
    print(f"\nWeather data from prefixed URI: {weather_data}")


if __name__ == "__main__":
    # First run our async function to display info
    asyncio.run(get_server_details())

    # Then start the server (uncomment to run the server)
    app.run()