import express from "express"; import puppeteer from "puppeteer"; import fs from "fs"; import path from "path"; const app = express(); app.use(express.json()); const cookiesPath = path.resolve("./cookies.json"); app.post("/tweet", async (req, res) => { const { tweetText, imagePath, username, password } = req.body; if (!tweetText || !imagePath) { return res.status(400).json({ error: "Missing parameters" }); } const browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox", "--disable-setuid-sandbox"], }); try { const page = await browser.newPage(); if (fs.existsSync(cookiesPath)) { const cookiesString = fs.readFileSync(cookiesPath, "utf8"); const cookies = JSON.parse(cookiesString); await page.setCookie(...cookies); console.log("✅ cookies loaded"); } await page.goto("https://twitter.com/home", { waitUntil: "networkidle2" }); if (await page.$('input[name="text"]')) { if (!username || !password) { return res.status(403).json({ error: "cookies expired, please provide username/password" }); } console.log("🔐 need login"); await page.type('input[name="text"]', username, {delay: 100}); await page.keyboard.press('Enter'); await page.waitForTimeout(2000); await page.waitForSelector('input[name="password"]', {timeout: 60000}); await page.type('input[name="password"]', password, {delay: 100}); await page.keyboard.press('Enter'); await page.waitForNavigation({waitUntil: 'networkidle2'}); const cookies = await page.cookies(); fs.writeFileSync(cookiesPath, JSON.stringify(cookies, null, 2)); console.log("✅ cookies saved"); } await page.waitForSelector('a[aria-label="Post"]', { timeout: 60000 }); await page.click('a[aria-label="Post"]'); await page.waitForSelector('div[aria-label="Tweet text"]'); await page.type('div[aria-label="Tweet text"]', tweetText); const [fileChooser] = await Promise.all([ page.waitForFileChooser(), page.click('div[aria-label="Add photos or video"]') ]); await fileChooser.accept([imagePath]); await page.waitForTimeout(3000); await page.click('div[data-testid="tweetButtonInline"]'); await browser.close(); res.json({ success: true, message: "Tweet posted" }); } catch (err) { console.error(err); await browser.close(); res.status(500).json({ error: err.message }); } }); app.get("/", (_, res) => { res.send("✅ MCP Puppeteer Twitter server is running"); }); app.listen(7860, () => { console.log("✅ MCP server on port 7860"); });