telegram-bot-mcp/mcp_bridge/__main__.py
Mikkel Georgsen a71595b9d8 feat: replace custom OAuth with FastMCP built-in OAuthProvider
FastMCP's OAuthProvider handles the full OAuth flow including DCR
(Dynamic Client Registration), authorization code + PKCE, token
issuance, and refresh tokens. No more custom auth code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:18:16 +00:00

90 lines
2.4 KiB
Python

"""Entry point: runs both Telegram bot and MCP server in one process."""
import asyncio
import logging
import signal
import uvicorn
from .config import MCP_HOST, MCP_PORT, MEDIA_DIR, DB_PATH
from .db import Database
from .telegram_bot import BridgeBot
from .mcp_server import mcp, init as init_mcp, custom_routes
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(name)s] %(levelname)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger("mcp_bridge")
async def run_telegram_bot(bot: BridgeBot):
"""Run the telegram bot polling loop."""
app = bot.build_application()
await app.initialize()
await bot._post_init(app)
await app.start()
updater = app.updater
await updater.start_polling(drop_pending_updates=True)
logger.info("Telegram bot polling started")
try:
while True:
await asyncio.sleep(3600)
except asyncio.CancelledError:
logger.info("Telegram bot shutting down...")
await updater.stop()
await app.stop()
await app.shutdown()
async def run_mcp_server():
"""Run the FastMCP HTTP server with built-in OAuth."""
# Get the FastMCP app (includes OAuth routes automatically)
mcp_app = mcp.http_app()
# Add our custom non-auth routes
mcp_app.routes.extend(custom_routes)
logger.info(f"MCP server starting on {MCP_HOST}:{MCP_PORT} (OAuth via FastMCP)")
config = uvicorn.Config(mcp_app, host=MCP_HOST, port=MCP_PORT, log_level="info")
server = uvicorn.Server(config)
await server.serve()
async def main():
"""Start both services."""
MEDIA_DIR.mkdir(parents=True, exist_ok=True)
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
db = Database()
logger.info(f"Database initialized at {DB_PATH}")
init_mcp(db)
bot = BridgeBot(db)
telegram_task = asyncio.create_task(run_telegram_bot(bot))
mcp_task = asyncio.create_task(run_mcp_server())
loop = asyncio.get_event_loop()
def handle_signal():
logger.info("Received shutdown signal")
telegram_task.cancel()
mcp_task.cancel()
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, handle_signal)
try:
await asyncio.gather(telegram_task, mcp_task, return_exceptions=True)
except asyncio.CancelledError:
pass
logger.info("MCP Bridge stopped")
if __name__ == "__main__":
asyncio.run(main())