Skip to main content
Glama
README.md
# stashcat-api-mcp

MCP (Model Context Protocol) server for the [Stashcat](https://www.stashcat.com/) / schul.cloud messenger API.

Allows AI assistants (e.g. Claude Desktop) to interact with Stashcat: read and send messages, manage channels and conversations, browse files, and more.

## Requirements

- Node.js 20+
- A Stashcat account

## Installation

```bash
git clone https://github.com/dclausen01/stashcat-api-mcp.git
cd stashcat-api-mcp
npm install
npm run build
```

## Configuration

Copy `.env.example` to `.env` and fill in your credentials:

```bash
cp .env.example .env
```

```env
STASHCAT_BASE_URL=https://api.stashcat.com/
STASHCAT_EMAIL=your-email@example.com
STASHCAT_PASSWORD=your-password
STASHCAT_APP_NAME=stashcat-mcp
STASHCAT_DEVICE_ID=              # Optional; auto-generated if omitted
STASHCAT_SECURITY_PASSWORD=      # Optional; defaults to STASHCAT_PASSWORD
                                 # Enables automatic E2E message decryption

SESSION_FILE_PATH=./stashcat-session.json
```

The server logs in once, unlocks E2E encryption, and persists the session to `SESSION_FILE_PATH`. On subsequent starts it reuses the saved session and only re-authenticates when the session has expired. E2E decryption is re-unlocked automatically on each start.

## Usage with Claude Desktop

Add the server to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "stashcat": {
      "command": "node",
      "args": ["/absolute/path/to/stashcat-api-mcp/dist/index.js"],
      "env": {
        "STASHCAT_EMAIL": "your-email@example.com",
        "STASHCAT_PASSWORD": "your-password",
        "STASHCAT_BASE_URL": "https://api.stashcat.com/"
      }
    }
  }
}
```

## Available Tools

| Tool | Description |
|---|---|
| `get_me` | Profile of the authenticated user |
| `get_user` | Profile of a specific user |
| `list_companies` | Companies the user belongs to |
| `get_company` | Details of a company |
| `list_company_members` | Members of a company |
| `get_all_company_members` | Get all members (no pagination) |
| `list_managed_users` | List managed users (for admins) |
| `list_groups` | List company groups |
| `list_channels` | Subscribed channels of a company |
| `search_channels` | Search visible/joinable channels |
| `get_channel_info` | Detailed info about a channel |
| `get_channel_members` | Members of a channel |
| `join_channel` | Join a channel |
| `quit_channel` | Leave a channel |
| `create_channel` | Create a new channel |
| `edit_channel` | Edit channel settings |
| `delete_channel` | Delete a channel permanently |
| `invite_users_to_channel` | Invite users to a channel |
| `accept_channel_invite` | Accept a channel invitation |
| `decline_channel_invite` | Decline a channel invitation |
| `remove_user_from_channel` | Remove a user from a channel |
| `add_channel_moderator` | Grant moderator status |
| `remove_channel_moderator` | Revoke moderator status |
| `set_channel_favorite` | Mark/unmark channel as favorite |
| `enable_channel_notifications` | Enable push notifications |
| `disable_channel_notifications` | Disable push notifications |
| `list_conversations` | All direct messages and group chats |
| `get_conversation` | Details of a conversation |
| `create_conversation` | Create a new encrypted conversation |
| `archive_conversation` | Archive a conversation |
| `set_conversation_favorite` | Mark/unmark conversation as favorite |
| `get_messages` | Fetch messages from a channel or conversation |
| `send_message` | Send a text message |
| `delete_message` | Delete a message |
| `mark_as_read` | Mark messages as read |
| `like_message` | Like a message |
| `get_flagged_messages` | Get flagged messages |
| `unlike_message` | Remove like from a message |
| `list_likes` | List users who liked a message |
| `flag_message` | Flag a message |
| `unflag_message` | Unflag a message |
| `list_files` | List files and folders |
| `get_file_info` | Metadata for a file |
| `get_storage_quota` | Storage quota info |
| `rename_file` | Rename a file |
| `delete_files` | Delete one or more files |
| `upload_file` | Upload a file to a channel/conversation/personal |
| `download_file` | Download a file as base64 |
| `move_file` | Move a file to another folder |
| `copy_file` | Copy a file to another location |
| `create_folder` | Create a new folder |
| `delete_folder` | Delete a folder |
| `get_notifications` | Recent notifications |
| `get_notification_count` | Number of unread notifications |
| `get_account_settings` | Account settings |
| `list_active_devices` | Active devices |
| `change_status` | Change status message |
| `change_password` | Change account password |
| `deactivate_device` | Deactivate an active device |
| `store_profile_image` | Upload profile image (base64) |
| `reset_profile_image` | Reset profile image to default |
| `delete_notification` | Delete a specific notification |
| `list_events` | List calendar events in a time range |
| `get_event_details` | Details for a specific event |
| `create_event` | Create a new calendar event |
| `edit_event` | Edit an existing event |
| `delete_events` | Delete calendar events |
| `respond_to_event` | Accept/decline event invitation |
| `invite_to_event` | Invite users to an event |
| `list_available_calendars` | CalDAV sync URLs |
| `list_channels_having_events` | Channels with events |
| `list_broadcasts` | List all broadcast lists |
| `create_broadcast` | Create a new broadcast list |
| `delete_broadcast` | Delete a broadcast list |
| `rename_broadcast` | Rename a broadcast list |
| `add_broadcast_members` | Add members to a broadcast list |
| `remove_broadcast_members` | Remove members from a broadcast list |
| `list_broadcast_members` | List members of a broadcast list |
| `get_broadcast_content` | Get messages from a broadcast list |
| `send_broadcast_message` | Send a message to a broadcast list |
| **Polls (Surveys)** | |
| `list_polls` | List polls by constraint (created/invited/archived) |
| `get_poll_details` | Get full poll details with questions |
| `create_poll` | Create a new poll (as draft) |
| `edit_poll` | Edit an existing poll |
| `delete_poll` | Delete a poll |
| `publish_poll` | Publish a draft poll |
| `archive_poll` | Archive or unarchive a poll |
| `invite_to_poll` | Invite users or channels to a poll |
| `list_poll_participants` | List users who answered a poll |
| `create_poll_question` | Create a question in a poll |
| `edit_poll_question` | Edit a question |
| `delete_poll_question` | Delete a question |
| `create_poll_answer` | Create an answer option |
| `list_poll_answers` | List answers with vote counts |
| `vote_poll` | Submit votes for a question |
| `export_poll` | Export poll results as CSV |
| `watch_poll` | Start/stop watching a poll |
| `list_poll_invited_users` | List users invited to a poll |
| `list_poll_invites` | List poll invites with pagination |
| `edit_poll_answer` | Edit an answer option |
| `delete_poll_answer` | Delete an answer option |
| **Realtime** | |
| `create_realtime_connection` | Connect to Socket.io for live events |
| `disconnect_realtime` | Disconnect from realtime |
| `send_typing_indicator` | Send "typing..." indicator |

## Building

```bash
npm run build      # compile with esbuild → dist/index.js
npm run typecheck  # TypeScript type check only
npm run clean      # remove dist/
```

## License

MIT

TDQS

C2.9/5.0

Scored across 104 tools

Disambiguation2/5

Several tools have nearly identical purposes: get_all_company_members and list_company_members are effectively duplicates, and list_poll_invited_users vs list_poll_invites overlap heavily. With 104 tools across 10 domains, an agent will frequently struggle to select the right one, especially for poll and member-management operations.

Naming Consistency4/5

The set overwhelmingly follows a consistent snake_case verb_noun pattern (create_channel, delete_message, list_polls, upload_file). Minor deviations like mark_as_read, invite_users_to_channel, and remove_user_from_channel break the pattern slightly but remain readable and predictable.

Tool Count2/5

104 tools is far too many for an agent to efficiently navigate, even given the broad scope of a full collaboration platform API. The poll subdomain alone contributes 21 tools, and the file/message domains could be consolidated without losing capability.

Completeness4/5

The surface provides strong lifecycle coverage for channels, files, events, broadcasts, and polls, including niche operations like voting, export, and realtime connections. Notable gaps include no message editing, no single-message fetch by ID, and no conversation member management, but agents can work around most of these.

Maintenance

ActivityMaintained
ResponsivenessSyncing