Skip to main content
Glama
README.md
# X MCP Server v2.0

A comprehensive Model Context Protocol (MCP) server for X (Twitter) API v2 with **multi-user OAuth 2.0 + PKCE**, encrypted token storage, and automatic token refresh.

## ๐Ÿš€ New in v2.0

- โœ… **Multi-User Support** - Multiple users with isolated tokens and sessions
- โœ… **Dual OAuth Flows** - Loopback (local) + Hosted Pairing Code (remote/multi-user)
- โœ… **Encrypted Token Storage** - SQLite database with OS keychain integration  
- โœ… **Automatic Token Refresh** - Background refresh with scope validation
- โœ… **Session Management** - Secure session handling for different transports
- โœ… **Non-Browser Support** - Works without browser access via pairing codes

## Features

- โœ… OAuth 2.0 Authorization Code + PKCE authentication (both flows)
- โœ… Multi-user support with per-user token isolation
- โœ… Encrypted local token storage (AES-256 + OS keychain)
- โœ… Automatic token refresh and persistence
- โœ… Scope verification and re-auth instructions
- โœ… Rate limiting with retry/backoff logic
- โœ… Bookmark management (list, add, remove)
- โœ… Tweet creation (text, media, replies, quotes)
- โœ… Session-aware MCP resources
- โœ… Comprehensive error handling and logging

## Setup

### 1. X Developer Account Setup

1. Create a [X Developer account](https://developer.x.com/)
2. Create a new app in the [Developer Portal](https://developer.x.com/en/portal/dashboard)
3. Configure OAuth 2.0 settings:
   - **App permissions**: Read and Write
   - **Type of App**: Web App
   - **Callback URI**: `http://localhost:3000/callback` (or your custom URI)
   - **Website URL**: Required (can be placeholder)
4. Note your **Client ID** and **Client Secret**

### 2. Installation

```bash
# Clone or create the project directory
cd x-mcp
npm install
npm run build
```

### 3. Environment Setup

Create a `.env` file or export environment variables:

```bash
export X_CLIENT_ID="your_client_id_here"
export X_CLIENT_SECRET="your_client_secret_here"
export X_REDIRECT_URI="http://localhost:3000/callback"  # Optional
```

### 4. Authentication

Run the authentication helper to complete OAuth flow:

```bash
npm run auth
# or
node dist/auth-helper.js
```

This will:
1. Open your browser to X's authorization page
2. Start a local callback server
3. Exchange the authorization code for tokens
4. Save tokens to `~/.x-mcp/tokens.json`

## Quick Start

### V2.0 Multi-User Server (Recommended)

```bash
npm install
npm run build

# Set environment variables
export X_CLIENT_ID="your_client_id"
export X_CLIENT_SECRET="your_client_secret"

# Start multi-user server
npm start
```

### Authentication Flows

#### Local/Single-User (Loopback)
```bash
# Via MCP tool call
{"method": "tools/call", "params": {"name": "auth/start", "arguments": {"mode": "loopback"}}}
# Opens browser for authorization
```

#### Multi-User/Remote (Hosted Pairing)
```bash
# Enable hosted mode
export X_HOSTED_MODE="true"
export X_BASE_URL="https://yourapp.com"

# Via MCP tool call  
{"method": "tools/call", "params": {"name": "auth/start", "arguments": {"mode": "hosted"}}}
# Returns pairing code + login URL

# Check status
{"method": "tools/call", "params": {"name": "auth/status", "arguments": {"pairing_code": "ABC12345"}}}
```

### Legacy V1.0 Server

```bash
npm run start:legacy
# or
node dist/index.js
```

### MCP Tools

The server provides these tools:

#### `bookmarks.list`
List user bookmarks with pagination support.

**Parameters:**
- `user_id` (optional): User ID (defaults to authenticated user)
- `max_results` (optional): Maximum results per page (1-100, default: 10)
- `pagination_token` (optional): Token for next page of results

**Example:**
```json
{
  "tweets": [
    {
      "id": "1234567890",
      "text": "Great tweet content...",
      "created_at": "2023-01-01T00:00:00.000Z",
      "author_id": "987654321",
      "public_metrics": {
        "retweet_count": 5,
        "like_count": 10,
        "reply_count": 2,
        "quote_count": 1
      }
    }
  ],
  "nextToken": "next_page_token"
}
```

#### `bookmarks.add`
Add a tweet to bookmarks.

**Parameters:**
- `tweet_id` (required): ID of the tweet to bookmark
- `user_id` (optional): User ID (defaults to authenticated user)

**Returns:** `{ "ok": true }`

#### `bookmarks.remove`
Remove a tweet from bookmarks.

**Parameters:**
- `tweet_id` (required): ID of the tweet to remove from bookmarks
- `user_id` (optional): User ID (defaults to authenticated user)

**Returns:** `{ "ok": true }`

#### `tweet.create`
Create a new tweet.

**Parameters:**
- `text` (required): Tweet text content (max 280 characters)
- `media_ids` (optional): Array of media IDs to attach
- `reply` (optional): Object with `in_reply_to_tweet_id` for replies
- `quote_tweet_id` (optional): ID of tweet to quote

**Example:**
```json
{
  "id": "1234567890",
  "createdAt": "2023-01-01T00:00:00.000Z"
}
```

### MCP Resources

#### `mcp://x/user/me`
Current authenticated X user information:
```json
{
  "id": "123456789",
  "username": "example_user",
  "name": "Example User"
}
```

#### `mcp://x/bookmarks/latest`
Last fetched bookmarks page with pagination token:
```json
{
  "tweets": [...],
  "nextToken": "pagination_token"
}
```

## Required Scopes

The server requires these X API scopes:
- `bookmark.read` or `bookmarks.read` - Read bookmarks
- `bookmarks.write` - Modify bookmarks  
- `tweet.write` - Post tweets
- `tweet.read` - Read tweets (for tweet creation responses)
- `users.read` - Read user information
- `offline.access` - Refresh token support

If scopes are missing, the server will provide re-authentication instructions.

## Rate Limiting

The server automatically handles X API rate limits:
- โœ… Retries on 429/5xx responses with exponential backoff
- โœ… Reads `x-rate-limit-*` headers for intelligent throttling
- โœ… Surfaces MCP notifications when limits are low
- โœ… Adapts to actual API limits (doesn't hardcode limits)

Current typical limits (may vary by plan):
- GET bookmarks: ~180 requests per 15 minutes
- POST/DELETE bookmarks: ~50 requests per 15 minutes
- POST tweets: ~300 requests per 15 minutes

## File Structure

```
src/
โ”œโ”€โ”€ index.ts          # Main MCP server
โ”œโ”€โ”€ auth.ts           # OAuth 2.0 + PKCE implementation
โ”œโ”€โ”€ auth-helper.ts    # Interactive authentication flow
โ”œโ”€โ”€ x-client.ts       # X API client with bookmarks/tweets
โ”œโ”€โ”€ http-client.ts    # HTTP client with retry/rate limiting
โ”œโ”€โ”€ storage.ts        # Token persistence
โ””โ”€โ”€ types.ts          # TypeScript type definitions
```

## Scripts

```bash
npm run build          # Compile TypeScript
npm start              # Start v2.0 multi-user server  
npm run start:legacy   # Start v1.0 legacy server
npm run auth           # Interactive OAuth helper (legacy)
npm test               # Run comprehensive test suite
npm run dev            # Development mode
npm run watch          # Watch mode compilation
```

## Configuration

### V2.0 Environment Variables:
- `X_CLIENT_ID` - X app client ID (required)
- `X_CLIENT_SECRET` - X app client secret (required)  
- `X_REDIRECT_URI` - OAuth redirect URI (default: `http://127.0.0.1:3000/auth/x/cb`)
- `X_HOSTED_MODE` - Enable hosted pairing mode (`true`/`false`)
- `X_BASE_URL` - Base URL for hosted mode (e.g., `https://yourapp.com`)
- `X_MCP_ENCRYPTION_KEY` - Manual encryption key (base64, optional)

### Storage Locations:
- **V2.0 Database:** `~/.mcp/x/tokens.db` (SQLite with encryption)
- **V1.0 Tokens:** `~/.x-mcp/tokens.json` (legacy JSON format)
- **Encryption Key:** OS Keychain or `~/.mcp/x/.encryption_key`

## Error Handling

The server provides detailed error messages for:
- โŒ Missing authentication/tokens
- โŒ Insufficient scopes with re-auth instructions
- โŒ API errors with request IDs (in debug mode)
- โŒ Rate limit violations with retry guidance
- โŒ Network errors with retry logic

## Testing

### Comprehensive Test Suite
```bash
npm test  # Runs all tests including encryption, database, OAuth flows
```

### Manual E2E Testing (V2.0)
1. **Start server**: `npm start`
2. **Loopback auth**: Call `auth/start` with `mode: "loopback"`
3. **Complete OAuth**: Open returned URL, authorize
4. **Test bookmarks**: `bookmarks.list`, `bookmarks.add`, `bookmarks.remove`
5. **Test tweets**: `tweet.create`

### Multi-User Testing (V2.0)
1. **Enable hosted mode**: Set `X_HOSTED_MODE=true`, `X_BASE_URL`
2. **Start pairing**: Call `auth/start` with `mode: "hosted"`
3. **Complete auth**: Visit login URL with pairing code
4. **Check status**: Call `auth/status` with pairing code
5. **Test with session**: Include session context in subsequent calls

### Legacy Testing (V1.0)
1. **Authentication**: `npm run auth`
2. **Start legacy server**: `npm run start:legacy`
3. **Test tools**: Use existing MCP tools

## Troubleshooting

### Authentication Issues
- Verify X_CLIENT_ID and X_CLIENT_SECRET are correct
- Check that redirect URI matches your app configuration
- Ensure your X app has correct permissions (Read and Write)

### Scope Issues
- Re-run `npm run auth` to get updated scopes
- Check that your X app is configured for the required permissions

### Rate Limit Issues
- The server will automatically retry and backoff
- Check the logs for rate limit information
- Consider the plan limits for your X developer account

### Token Issues
- Tokens are auto-refreshed when expired
- **V2.0**: Check database at `~/.mcp/x/tokens.db`, run `npm test` for diagnostics
- **V1.0**: Delete `~/.x-mcp/tokens.json` and re-authenticate if needed

## ๐Ÿ“š Detailed Documentation

For comprehensive documentation on the new multi-user OAuth system, architecture, and advanced usage, see:

**[README-MULTIUSER.md](./README-MULTIUSER.md)** - Complete v2.0 documentation with:
- ๐Ÿ—๏ธ Detailed architecture overview
- ๐Ÿ” Security implementation details  
- ๐Ÿ—„๏ธ Database schema and design
- ๐Ÿ“ก Complete API reference
- ๐Ÿงช Advanced testing scenarios
- ๐Ÿ› ๏ธ Development and extension guide

Maintenance

ActivityInactive
ResponsivenessNo issues