feat: Twitter/X integration (read-only free tier)

- New client: src/clients/twitter.ts
- Tools: twitter_search_tweets, twitter_get_user_profile, twitter_get_user_tweets, twitter_create_tweet
- REST endpoints: GET /api/twitter/search, /api/twitter/user, /api/twitter/tweets, POST /api/twitter/tweet
- Multi-account env var: TWITTER_{ACCOUNT}_BEARER_TOKEN
- twitter_create_tweet returns clear error about paid tier requirement

Total tools: 36
This commit is contained in:
Garfield
2026-05-05 22:11:19 -04:00
parent 136bc257d1
commit 59501f11f1
5 changed files with 394 additions and 0 deletions

View File

@@ -911,6 +911,115 @@ export function getManifest(serverUrl: string, authEnabled: boolean) {
examples: [{ image_url: 'https://example.com/photo.jpg', caption: 'New post!', account: 'default' }],
},
// ── Twitter/X tools ────────────────────────────────────────────────────
{
name: 'twitter_search_tweets',
category: 'twitter',
description: 'Search recent tweets on Twitter/X',
when_to_use:
'User wants to find tweets about a topic, hashtag, keyword, or trend.',
input_schema: {
type: 'object',
required: ['query'],
properties: {
query: { type: 'string', description: 'Search query (keyword, hashtag #xxx, from:username)' },
max_results: { type: 'number', description: 'Max tweets (default: 10, max: 100)' },
account: { type: 'string', description: 'Which Twitter account to use (default: "default")' },
},
},
returns: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'string', description: 'Tweet ID' },
text: { type: 'string' },
author_id: { type: 'string' },
created_at: { type: 'string', format: 'date-time' },
},
},
},
examples: [{ query: '#AI', max_results: 10, account: 'default' }],
},
{
name: 'twitter_get_user_profile',
category: 'twitter',
description: 'Get a Twitter/X user profile and stats',
when_to_use:
'User wants follower count, bio, or profile info for a specific Twitter account.',
input_schema: {
type: 'object',
required: ['username'],
properties: {
username: { type: 'string', description: 'Twitter username without @' },
account: { type: 'string', description: 'Which Twitter account to use (default: "default")' },
},
},
returns: {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
username: { type: 'string' },
description: { type: 'string' },
followers_count: { type: 'number' },
following_count: { type: 'number' },
tweet_count: { type: 'number' },
},
},
examples: [{ username: 'elonmusk', account: 'default' }],
},
{
name: 'twitter_get_user_tweets',
category: 'twitter',
description: 'Get recent tweets from a specific user',
when_to_use:
'User wants to read someones recent tweets or timeline.',
input_schema: {
type: 'object',
required: ['username'],
properties: {
username: { type: 'string', description: 'Twitter username without @' },
max_results: { type: 'number', description: 'Max tweets (default: 10, max: 100)' },
account: { type: 'string', description: 'Which Twitter account to use (default: "default")' },
},
},
returns: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'string' },
text: { type: 'string' },
created_at: { type: 'string', format: 'date-time' },
},
},
},
examples: [{ username: 'elonmusk', max_results: 5, account: 'default' }],
},
{
name: 'twitter_create_tweet',
category: 'twitter',
description: 'Post a tweet [REQUIRES PAID TIER]',
when_to_use:
'User wants to post a tweet. NOTE: Free tier is read-only. Paid upgrade required.',
input_schema: {
type: 'object',
required: ['text'],
properties: {
text: { type: 'string', description: 'Tweet text (max 280 chars)' },
account: { type: 'string', description: 'Which Twitter account to use (default: "default")' },
},
},
returns: {
type: 'object',
properties: {
message: { type: 'string', description: 'Error or confirmation' },
},
},
examples: [{ text: 'Hello from Hermes MCP!', account: 'default' }],
},
// ── Obsidian tools ──────────────────────────────────────────────────────
{
name: 'obsidian_search_notes',
@@ -1090,6 +1199,10 @@ export function getManifest(serverUrl: string, authEnabled: boolean) {
description: 'Instagram Business/Creator account via Graph API',
icon: '📸',
},
twitter: {
description: 'Twitter/X search and profile lookup (read-only on free tier)',
icon: '🐦',
},
},
};
}