stashcat-api-mcp
# 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
Scored across 104 tools
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.
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.
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.
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.