Merge pull request #35 from uriyyo/main

Add ability to run telegram-mcp using uvx
This commit is contained in:
Eugene Evstafev 2025-12-19 09:08:31 +00:00 committed by GitHub
commit 83c2c73a3b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 100 additions and 83 deletions

1
__init__.py Normal file
View file

@ -0,0 +1 @@
# Telegram MCP Package

42
main.py
View file

@ -3129,25 +3129,29 @@ async def create_poll(
) )
if __name__ == "__main__": async def _main() -> None:
try:
# Start the Telethon client non-interactively
print("Starting Telegram client...")
await client.start()
print("Telegram client started. Running MCP server...")
# Use the asynchronous entrypoint instead of mcp.run()
await mcp.run_stdio_async()
except Exception as e:
print(f"Error starting client: {e}", file=sys.stderr)
if isinstance(e, sqlite3.OperationalError) and "database is locked" in str(e):
print(
"Database lock detected. Please ensure no other instances are running.",
file=sys.stderr,
)
sys.exit(1)
def main() -> None:
nest_asyncio.apply() nest_asyncio.apply()
asyncio.run(_main())
async def main() -> None:
try:
# Start the Telethon client non-interactively
print("Starting Telegram client...")
await client.start()
print("Telegram client started. Running MCP server...") if __name__ == "__main__":
# Use the asynchronous entrypoint instead of mcp.run() main()
await mcp.run_stdio_async()
except Exception as e:
print(f"Error starting client: {e}", file=sys.stderr)
if isinstance(e, sqlite3.OperationalError) and "database is locked" in str(e):
print(
"Database lock detected. Please ensure no other instances are running.",
file=sys.stderr,
)
sys.exit(1)
asyncio.run(main())

View file

@ -1,7 +1,6 @@
[build-system] [build-system]
requires = ["setuptools>=42", "wheel"] requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
package-mode = false
[project] [project]
name = "telegram-mcp" name = "telegram-mcp"
@ -26,7 +25,7 @@ requires-python = ">=3.10"
dependencies = [ dependencies = [
"dotenv>=0.9.9", "dotenv>=0.9.9",
"httpx>=0.28.1", "httpx>=0.28.1",
"mcp[cli]>=1.4.1", "mcp[cli]>=1.8.0",
"nest-asyncio>=1.6.0", "nest-asyncio>=1.6.0",
"python-dotenv>=1.1.0", "python-dotenv>=1.1.0",
"python-json-logger>=3.3.0", "python-json-logger>=3.3.0",
@ -37,6 +36,13 @@ dependencies = [
"Homepage" = "https://github.com/chigwell/telegram-mcp" "Homepage" = "https://github.com/chigwell/telegram-mcp"
"Bug Tracker" = "https://github.com/chigwell/telegram-mcp/issues" "Bug Tracker" = "https://github.com/chigwell/telegram-mcp/issues"
[tool.setuptools]
py-modules = ["main", "session_string_generator"]
[project.scripts]
telegram-mcp = "main:main"
telegram-mcp-generate-session = "session_string_generator:main"
[tool.black] [tool.black]
line-length = 99 line-length = 99
target-version = ['py311'] target-version = ['py311']

View file

@ -28,75 +28,81 @@ import sys
# Load environment variables from .env file # Load environment variables from .env file
load_dotenv() load_dotenv()
API_ID = os.getenv("TELEGRAM_API_ID")
API_HASH = os.getenv("TELEGRAM_API_HASH")
if not API_ID or not API_HASH: def main() -> None:
print("Error: TELEGRAM_API_ID and TELEGRAM_API_HASH must be set in .env file") API_ID = os.getenv("TELEGRAM_API_ID")
print("Create an .env file with your credentials from https://my.telegram.org/apps") API_HASH = os.getenv("TELEGRAM_API_HASH")
sys.exit(1)
# Convert API_ID to integer if not API_ID or not API_HASH:
try: print("Error: TELEGRAM_API_ID and TELEGRAM_API_HASH must be set in .env file")
API_ID = int(API_ID) print("Create an .env file with your credentials from https://my.telegram.org/apps")
except ValueError: sys.exit(1)
print("Error: TELEGRAM_API_ID must be an integer")
sys.exit(1)
print("\n----- Telegram Session String Generator -----\n") # Convert API_ID to integer
print("This script will generate a session string for your Telegram account.") try:
print( API_ID = int(API_ID)
"You will be asked to enter your phone number and the verification code sent to your Telegram app." except ValueError:
) print("Error: TELEGRAM_API_ID must be an integer")
print("The generated session string can be added to your .env file.") sys.exit(1)
print(
"\nYour credentials will NOT be stored on any server and are only used for local authentication.\n"
)
try: print("\n----- Telegram Session String Generator -----\n")
# Connect to Telegram and generate the session string print("This script will generate a session string for your Telegram account.")
with TelegramClient(StringSession(), API_ID, API_HASH) as client: print(
# The client.session.save() function from StringSession returns the session string "You will be asked to enter your phone number and the verification code sent to your Telegram app."
session_string = StringSession.save(client.session) )
print("The generated session string can be added to your .env file.")
print(
"\nYour credentials will NOT be stored on any server and are only used for local authentication.\n"
)
print("\nAuthentication successful!") try:
print("\n----- Your Session String -----") # Connect to Telegram and generate the session string
print(f"\n{session_string}\n") with TelegramClient(StringSession(), API_ID, API_HASH) as client:
print("Add this to your .env file as:") # The client.session.save() function from StringSession returns the session string
print(f"TELEGRAM_SESSION_STRING={session_string}") session_string = StringSession.save(client.session)
print("\nIMPORTANT: Keep this string private and never share it with anyone!")
# Optional: auto-update the .env file print("\nAuthentication successful!")
choice = input( print("\n----- Your Session String -----")
"\nWould you like to automatically update your .env file with this session string? (y/N): " print(f"\n{session_string}\n")
) print("Add this to your .env file as:")
if choice.lower() == "y": print(f"TELEGRAM_SESSION_STRING={session_string}")
try: print("\nIMPORTANT: Keep this string private and never share it with anyone!")
# Read the current .env file
with open(".env", "r") as file:
env_contents = file.readlines()
# Update or add the SESSION_STRING line # Optional: auto-update the .env file
session_string_line_found = False choice = input(
for i, line in enumerate(env_contents): "\nWould you like to automatically update your .env file with this session string? (y/N): "
if line.startswith("TELEGRAM_SESSION_STRING="): )
env_contents[i] = f"TELEGRAM_SESSION_STRING={session_string}\n" if choice.lower() == "y":
session_string_line_found = True try:
break # Read the current .env file
with open(".env", "r") as file:
env_contents = file.readlines()
if not session_string_line_found: # Update or add the SESSION_STRING line
env_contents.append(f"TELEGRAM_SESSION_STRING={session_string}\n") session_string_line_found = False
for i, line in enumerate(env_contents):
if line.startswith("TELEGRAM_SESSION_STRING="):
env_contents[i] = f"TELEGRAM_SESSION_STRING={session_string}\n"
session_string_line_found = True
break
# Write back to the .env file if not session_string_line_found:
with open(".env", "w") as file: env_contents.append(f"TELEGRAM_SESSION_STRING={session_string}\n")
file.writelines(env_contents)
print("\n.env file updated successfully!") # Write back to the .env file
except Exception as e: with open(".env", "w") as file:
print(f"\nError updating .env file: {e}") file.writelines(env_contents)
print("Please manually add the session string to your .env file.")
except Exception as e: print("\n.env file updated successfully!")
print(f"\nError: {e}") except Exception as e:
print("Failed to generate session string. Please try again.") print(f"\nError updating .env file: {e}")
sys.exit(1) print("Please manually add the session string to your .env file.")
except Exception as e:
print(f"\nError: {e}")
print("Failed to generate session string. Please try again.")
sys.exit(1)
if __name__ == "__main__":
main()

View file

@ -995,7 +995,7 @@ dev = [
requires-dist = [ requires-dist = [
{ name = "dotenv", specifier = ">=0.9.9" }, { name = "dotenv", specifier = ">=0.9.9" },
{ name = "httpx", specifier = ">=0.28.1" }, { name = "httpx", specifier = ">=0.28.1" },
{ name = "mcp", extras = ["cli"], specifier = ">=1.4.1" }, { name = "mcp", extras = ["cli"], specifier = ">=1.8.0" },
{ name = "nest-asyncio", specifier = ">=1.6.0" }, { name = "nest-asyncio", specifier = ">=1.6.0" },
{ name = "python-dotenv", specifier = ">=1.1.0" }, { name = "python-dotenv", specifier = ">=1.1.0" },
{ name = "python-json-logger", specifier = ">=3.3.0" }, { name = "python-json-logger", specifier = ">=3.3.0" },