[project] name = "twscrape-twitter-mcp" version = "0.1.5" description = "Read-optimized MCP server for Twitter/X, wrapping twscrape. BYO cookies, multi-account pool, agent-friendly tools." readme = "README.md" license = { text = "MIT" } requires-python = ">=3.10" authors = [{ name = "Josh Silets" }] keywords = [ "mcp", "model-context-protocol", "twitter", "x", "twscrape", "scraper", "agent", "fastmcp", "claude", "codex", ] classifiers = [ "Development Status :: 3 - Alpha", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Internet", "Topic :: Software Development :: Libraries", ] # twscrape is PINNED on purpose: it owns the brittle scraping layer # (GraphQL endpoints, x-client-transaction-id signing, TLS impersonation). # When X breaks it, bump this pin, run the unit tests + `smoke` locally, then # release. See CONTRIBUTING.md ("Bumping twscrape") for the ritual. Dependabot # does not watch this pin: its pip ecosystem skips [project] dependencies and # only updates the dev extra below. The twscrape-watch workflow files the issue # instead. dependencies = [ "twscrape==0.20.1", "fastmcp>=3.4.2,<5", "uvicorn>=0.30", "websockets>=15", # Drives the browser-based login flow (Mac/Linux/Windows). Bundled Chromium is # fetched on first `twscrape-twitter-mcp login` via `playwright install chromium`. "playwright>=1.45", ] [project.optional-dependencies] # Stealthier login (undetected Chromium), used automatically if installed. stealth = ["patchright>=1.45"] dev = ["pytest==9.1.1", "pytest-asyncio==1.4.0", "ruff==0.16.6"] [project.urls] Homepage = "https://github.com/jsilets/twscrape-twitter-mcp" Documentation = "https://github.com/jsilets/twscrape-twitter-mcp#readme" Repository = "https://github.com/jsilets/twscrape-twitter-mcp" Issues = "https://github.com/jsilets/twscrape-twitter-mcp/issues" [project.scripts] twscrape-twitter-mcp = "twscrape_twitter_mcp.cli:main" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/twscrape_twitter_mcp"] [tool.pytest.ini_options] asyncio_mode = "auto" [tool.ruff] line-length = 100 [tool.ruff.lint] # Pin the rule surface to ruff's historical default (pyflakes + pycodestyle # errors). Without this, an unpinned ruff bumps its default rule set from under # CI: 0.16.0 added bugbear/bandit/blind-except lints that flag the intentional # broad excepts (tools return markdown instead of raising). select = ["E4", "E7", "E9", "F"]