oase-mcp
OfficialClick on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@oase-mcpsend a message to the oase saying I'm on my way"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
oase-mcp
An MCP server that lets Claude chat inside an Oase. Give Claude an invite link and it can post into that oase's group chat, publish posts (opslag) to the oase's feed, read the conversation, and react ā handy for status updates, "I finished X", or dropping a note where you'll see it.
It's a REST client: every tool is a plain request/response HTTP call.
š Documentation: https://dev.oase.app/mcp/
Status / disclaimer
This is experimental and provided as-is. It builds on Oase's internal API, which can change without notice ā so it may break, change, or be discontinued at any time, and there's no guarantee it works today or will keep working tomorrow. There's no support commitment: issues are welcome (see SUPPORT.md) but may go unanswered. If you need a supported integration path, use the identity & SCIM integration instead.
Talks to the production Oase backend (api.oase.app) exactly like the app does:
sign in ā join via invite link ā fetch the oase key from KMS ā AES-256-GCM
encrypt ā POST .../messaging/messages. Messages are encrypted client-side
with the oase's symmetric AES-256-GCM key (fetched from the KMS via a
mainframe-signed proof), so they render normally in the app.
Related MCP server: WAHA WhatsApp MCP Server
Architecture
The codebase is a passive REST client with an MCP server on top:
Passive REST client ā
src/client/. Everything that knows how to talk to Oase over HTTP: Promise login/auth (promiseLogin.ts), token refresh and the shared config file (config.ts), and the full REST client (oaseClient.ts) ā joining via invite link, KMS key fetching, AES-256-GCM encrypt/decrypt, and sending/reading messages and feed posts, reactions, and media. No agent behavior, no MCP dependency: it does something only when called. Importable by other consumers via the package root oroase-mcp/client(import { OaseClient, loadConfig } from "oase-mcp"), without pulling in the MCP layer.MCP server ā
src/mcp/. The MCP tool surface over the REST client (server.ts). Every tool is an on-demand request/response wrapper. Entry point:dist/index.js(claude mcp add oase -- node /path/to/dist/index.js).
How it works
Identity. Claude signs in as a persistent Promise user (the identity provider the Oase app uses) via a one-time browser login ā see Logging in. The resulting long-lived Oase refresh token is stored in
~/.oase-mcp/config.json(mode 0600); short-lived access tokens are kept in memory and refreshed automatically.Encryption. Oase encrypts message content with a per-oase symmetric AES-256-GCM key held in escrow by the backend. Any participant can fetch the raw oase key from the KMS via a mainframe-signed proof, so encrypting/decrypting is straightforward ā no device keypairs or enrollment. We produce the exact cipher-bundle shape the app expects.
No message is sent in plaintext ā the send endpoint requires a cipher bundle.
Setup
npm install
npm run buildRegister it with Claude Code (use the absolute path to this checkout):
claude mcp add oase -- node /path/to/oase-mcp/dist/index.jsOr add to your MCP client config manually:
{
"mcpServers": {
"oase": {
"command": "node",
"args": ["/path/to/oase-mcp/dist/index.js"]
}
}
}Logging in
Claude signs in as a persistent Promise user ā a one-time setup:
Call
promise_login_startā it returns a URL. Open it in a browser (incognito is safest so an existing Promise session isn't reused).Sign in to (or create) the Promise account for Claude. The page will say "Token captured".
Call
promise_login_finishā it exchanges the token for a persistent Oase identity.
Under the hood the server hosts a localhost OIDC callback and captures the
single-use id_token from the redirect ā no copy-pasting. (If you already have
an id_token, login_with_promise takes it directly.)
The exchange returns Oase's own long-lived refresh token (keyed to the Promise
person_id), so Promise is never contacted again ā no Promise credentials
are stored, only the resulting Oase refresh token.
Login is required: every other tool (join, send, read, ask) refuses until a Promise identity is established.
Tools
Tool | Args | What it does |
| ā | Start the one-time browser login for a persistent Promise identity; returns a URL to open. |
| ā | Complete the Promise login after signing in in the browser. |
|
| Exchange a Promise |
|
| Join an oase from an invite link ( |
|
| Post a markdown message. With |
|
| Edit the text of a message you sent (only your own). Attachments are kept; only the text changes. |
|
| Delete a message (soft delete). Your own, or anyone's if you're an oase admin/owner. |
|
| Publish a post (opslag) to the oase's feed/wall ā the front-page items in the app, distinct from chat. Markdown body, optional title (shown as the headline). Comments on the post are thread replies: |
|
| Edit a feed post's body (and optionally title; omit |
|
| Delete a feed post. Your own, or anyone's if you're an oase admin/owner. |
|
| Read recent feed posts (decrypted), oldest first, each line prefixed with the post id and tagged |
|
| Add an emoji reaction to a message (one per participant per message). |
|
| Download and decrypt a message attachment (image, voice message / sound bite, file). Images are returned inline so the agent can view and analyze them; every attachment is also saved to a local temp file whose path is returned (e.g. for transcribing audio). |
|
| Read recent messages (decrypted), oldest first, each line prefixed with its message id and tagged |
| ā | Show Claude's Oase identity and joined oases. |
|
| Change the display name Claude posts under. |
Threads and replies
Threads in Oase are one level: every reply to a message lives under that
message's resource id (chat_id <oaseId>/m/<messageId>), and you cannot reply
to a reply ā a nested thread would never be shown in the app. The server
enforces this: a thread_id that points at a reply is auto-resolved to the
thread's root message, so nothing ever lands in an invisible nested chat. To
reply to a message, pass its id as thread_id to send_message; use
read_messages to catch up on context and get the ids.
Attachments (images, voice messages, files)
Messages with attachments show them as [attachment <n>: <mime> "<name>"]
tags in every read result (a voice message is simply an audio/*
attachment, usually audio/mp4). read_media downloads the blob and, for
modern uploads, decrypts it: the app uploads media as an encrypted .oase
container ā [4-byte length][metadata JSON {alg, kid, oaseId, ivBase64}] [ciphertext][16-byte GCM tag] ā encrypted with the same server-escrowed oase
key as text, while the original filename/mime travel as cipher bundles on the
media item (legacy attachments are plaintext blobs behind signed CDN URLs and
pass through unchanged; giphy attachments resolve via their encrypted giphy
object).
What the agent gets back:
Images (jpeg/png/gif/webp up to 3 MB) are returned inline as MCP image content, so the agent can look at them directly and use what it sees in its response. Larger images fall back to the saved file.
Everything is also written to
<tmpdir>/oase-mcp/media/<messageId>-<n>-<name>and the path returned. For audio (Claude can't listen natively) the agent is nudged to transcribe the saved file with a local speech-to-text tool (e.g.hearon macOS orwhisper) and work from the transcript; documents can be opened with normal file tools.
Blob download URLs are provider-signed and expire after ~2 days; read_media
refreshes the chat projection and retries once if a URL has gone stale. Voice
messages / media-only messages have an empty text body and are shown by
read_messages like any other message.
Typical flow
Log Claude in:
promise_login_startā open the URL āpromise_login_finish.In the Oase app, open your oase ā invite ā copy the join link.
Ask Claude: "Join this oase: https://oase.app/oase/ā¦/join/ā¦" ā
join_oase.Ask Claude to "send a message to the oase saying ā¦" ā
send_message, "post an update to the feed" āsend_post, or "what's new in the oase?" āread_messages/read_posts.
Configuration
Environment variables (all optional):
OASE_MCP_CONFIG_DIRā where to storeconfig.json(default~/.oase-mcp).OASE_API_ROOTā mainframe API root (defaulthttps://api.oase.app), e.g. point at staging.OASE_KMS_ROOTā KMS root (defaulthttps://kms.oase.app/, trailing slash required).
Notes & limitations
Works on an oase's group chat (and per-message reply threads) and its feed posts (
send_post/read_postsā text only when sending; a post's title and body are separate cipher bundles under the same oase key). It can read/decrypt media attachments (read_media) but not send them; it doesn't handle private 1:1 chats or realm join-approval flows.Replies can't be nested ā threads are one level deep. A
thread_idthat is itself a reply is silently resolved to the thread's root message (best effort: for a message older than the latest chat page the id is used as-is).Signing in as a different Promise account clears joined oases, since memberships are per-person ā re-invite Claude afterward.
Deleting
~/.oase-mcp/config.jsonforgets the identity (Claude must log in and be re-invited).Many server processes (one per Claude session) share the identity in
~/.oase-mcp/config.json. The backend rotates the refresh token on everyoauth2/refreshand deletes the session if it ever sees a stale one (anti-replay) ā so the access token is persisted for reuse, and refreshes are serialized across processes via~/.oase-mcp/auth.lockwith a re-read under the lock. Don't hitoauth2/refreshout-of-band while servers are running; if the session does get revoked, tools will say so ā log in again withpromise_login_start.
License
MIT ā see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables Claude to read and send WhatsApp messages, including media and call history, via a local bridge.MIT
- AlicenseAqualityCmaintenanceEnables Claude to interact with WhatsApp through a unified backend API, providing 20 tools for messaging, media, groups, contacts, and chat management.22107MIT
- FlicenseNot gradedqualityCmaintenanceConnects Claude to OpenNMS, allowing plain language interaction with alarms, nodes, events, asset records, categories, and service collection.1
- AlicenseAqualityDmaintenanceConnects Claude to Open WebUI, enabling chat management, RAG knowledge bases, files, functions, and prompts directly from Claude.26252MIT
Related MCP Connectors
Publish pages straight from Claude as private, branded, tracked links.
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Connect Claude to Fathom meeting recordings, transcripts, and summaries
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/oase-app/oase-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server