HoPe Chatbot MCP Server
by ahmetacn
README.md
# HoPe Chatbot MCP Server
Uses [FastMCP](https://gofastmcp.com/getting-started/welcome) v3.
For code organization reasons MCP functionality is split into logical modules,
MCP sub-servers.
Main MCP server can import/mount sub-domain MCP servers. (`mcp_server/app.py`)
# Development
Define your capabilities separated to composable MCP servers.
Define new MCP tools, resources, prompts...
for `<some>` domain
for `<some>` business capability
in `<some>` MCP sub-server
in `mcp_server/servers/<some>/mcp.py`.
## Expose MCP server capabilities
**Decide** how you want your MCP tools, resources, prompts... to be available:
- in 1 combined MCP server (all-in-one) 🌐
- as separate MCP server only 🔒🪪
- both ✨
### All-in-one MCP server
Include sub-domain MCP server in combined MCP server.
Follow these steps in `mcp_server/app.py`:
- Import your FastMCP app
```py
from mcp_server.servers.some import some_mcp
```
- Find main MCP server defined.
Add capabilities of your MCP server into main MCP server
in startup/setup lifespan phase of main MCP server
```py
async def setup(app: FastMCP):
# Import or mount subservers
app.mount(some_mcp) # dynamic mount
# await app.import_server(some_mcp) # static copy
@contextlib.asynccontextmanager
async def lifespan(app: FastMCP):
# Setup
await setup(app)
yield
# Cleanup
main_mcp = FastMCP(
name="home-of-performance-mcp-server",
lifespan=lifespan
)
- Main combined MCP server contains capabilities of your MCP server at: `BASE_URL/mcp`.
It should be true for main combined MCP server ran in all cases:
- `mcp_server/app.py` ran as a module
- FastMCP.run method
- `mcp_server/app.py` ran with uvicorn
- `FastMCP.http_app`
- ASGI app of your MCP server mount to FastAPI app, uvicorn accessing FastAPI ASGI app
- (uvicorn accessing your ASGI directly will work too)
### Separate MCP server
Expose separate sub-domain MCP server.
Follow these steps in `mcp_server/app.py`:
- Import your FastMCP app
```py
from mcp_server.servers.some import some_mcp
```
- Create ASGI app from your FastMCP app
(no need to redefine `path="/mcp"` kwarg)
```py
some_mcp_app = some_mcp.http_app()
```
- Add lifespan of your FastMCP app to combined lifespan used by FastAPI app
```py
@contextlib.asynccontextmanager
async def combined_lifespan(app: FastAPI):
"""Combine lifespans for FastAPI app"""
# Run all lifespans
async with main_mcp_app.lifespan(app):
async with some_mcp_app.lifespan(app):
# Setup
yield
# Cleanup
fastapi_app = FastAPI(
title="Home of Performance MCP",
lifespan=combined_lifespan
)
```
- Mount ASGI app of your MCP server to FastAPI app under `/some` path
```py
fastapi_app.mount("/some", some_mcp_app)
```
- find your separate MCP server at: `BASE_URL/some/mcp`
## Running locally
- Define environment variables in `.env` according to `.env.template` (do not commit secrets)
- Install required python packages from `requirements.txt`
- Start FastMCP app through `run` method
`python -m mcp_server.app`
or run FastAPI app with MCP server(s) mount into it through gunicorn, uvicorn...
`source .venv/bin/activate && uvicorn src.app:app --host 0.0.0.0 --port 8000 --reload`
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing