@clawhub-zecurecode-42a5094cb9
Connect OpenClaw and other AI agents to WorkOS — a self-hosted workspace platform with documents, databases, tasks, meeting transcription, and sharing. Expos...
---
name: WorkOS
description: Connect OpenClaw and other AI agents to WorkOS — a self-hosted workspace platform with documents, databases, tasks, meeting transcription, and sharing. Exposes 60+ tools through a remote MCP server with OAuth 2.1.
version: 1.0.0
metadata:
openclaw:
skillKey: workos
homepage: https://workos.no/for-agenter
emoji: "🧠"
requires:
env: []
bins: []
---
# WorkOS
WorkOS is a self-hosted, AI-integrated workspace platform (a Notion
alternative) that exposes its full data model through a remote MCP server.
Use this skill whenever the user talks about their **documents, pages, wiki,
databases, tasks, meetings, transcripts**, or wants the agent to **create,
update, or search** their content on `workos.no`.
## When to use WorkOS
Reach for this skill when the user:
- Refers to "my wiki", "my workspace", "my page", "my database", "my tasks", "my meetings", "my notes".
- Says things like "create a new page about …", "add a task", "update the status field on row X", "find the document about …".
- Wants to search or fetch existing content on workos.no.
- Asks about transcripts, summaries, or attendees from meetings.
- Wants to share a page externally or manage access.
If the user has not yet connected the WorkOS MCP server, **set up the
connection first** (see `docs/connect.md`).
## Connection — once per agent
The WorkOS MCP server lives at:
```
https://workos.no/api/mcp
```
- **Transport:** Streamable HTTP (JSON-RPC 2.0). Not SSE.
- **Auth:** OAuth 2.1 with PKCE — fully automatic via client discovery.
- **Scopes:** `read`, `write`.
OpenClaw and other MCP clients are configured with the URL above and let the
OAuth flow happen in the system browser. Per-client setup is in
[`docs/connect.md`](docs/connect.md). Important: older Cline versions must
set `"type": "streamableHttp"` — the server does not support SSE.
## What the agent can do
After connecting, the server exposes ~60 tools grouped as follows:
| Area | Example tools | Use for |
|---|---|---|
| Account | `get_me`, `list_workspaces`, `get_workspace` | Identity and workspace context |
| Pages | `create_page`, `get_page`, `update_page`, `archive_page`, `restore_page`, `delete_page`, `move_page`, `search_pages`, `list_pages` | Documents, wiki, notes |
| Page blocks | `append_blocks`, `insert_blocks_after`, `update_block`, `delete_blocks` | Granular editing |
| Page groups | `create_page_group`, `update_page_group`, `delete_page_group`, `reorder_page_groups`, `list_page_groups` | Sidebar organization |
| Databases | `list_databases`, `create_database`, `get_database`, `update_database`, `delete_database` | Structured data |
| Properties | `add_db_property`, `update_db_property`, `remove_db_property`, `reorder_db_properties` | Schema |
| Rows | `list_db_rows`, `create_db_row`, `update_db_cell`, `delete_db_row`, `move_db_row` | Content |
| Views | `list_db_views`, `create_db_view`, `update_db_view`, `delete_db_view` | Table / board / list |
| Meetings | `create_meeting`, `append_transcript`, `generate_meeting_summary`, `list_meeting_templates` | Transcription + AI summary |
| Comments | `create_comment`, `update_comment`, `resolve_comment`, `list_comments`, `delete_comment` | Discussion |
| Sharing | `create_share_link`, `list_share_links`, `revoke_share_link` | External links |
| Files | `upload_image` | Image uploads |
The full catalog is in [`docs/tools.md`](docs/tools.md). Always call
`tools/list` after `initialize` to get the authoritative, current set.
## Workflow patterns
Common flows (full examples in [`docs/workflows.md`](docs/workflows.md)):
1. **Search → fetch → show**: `search_pages` → `get_page` → present content.
2. **Create page with structure**: `create_page` (with the right `workspaceId`
and `pageGroupId`) → `append_blocks` for content.
3. **Database update**: `list_databases` → `list_db_rows` (filtered) →
`update_db_cell` per row.
4. **Meeting flow**: `create_meeting` → `append_transcript` (in chunks) →
`generate_meeting_summary`.
5. **Safe edits**: fetch existing content before overwriting, and confirm
destructive operations (delete, archive) with the user.
## Rules and expectations
- **Workspace context first.** If the user has not specified a workspace,
call `list_workspaces` and ask which one is active before writing data.
- **Never guess IDs.** Always fetch them from a list/search call.
- **Write conservatively.** Prefer `update_*` over delete-and-recreate.
Confirm deletes/archives before running them.
- **Mirror the user's language.** WorkOS users are often Norwegian; mirror
whatever language the user is writing in for new pages and comments.
- **Respect roles.** `read` scope only allows fetching. If a write tool
returns 403, tell the user they lack `write` access in the workspace.
## Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| 401 from `/api/mcp` | Token expired or missing | The client should refresh automatically; otherwise remove the server and re-add it |
| 405 on GET | Client is trying SSE | Use Streamable HTTP — set `type: streamableHttp` (Cline) or upgrade the client |
| Empty workspace list | User is not a member of any workspace | Have the user create or join a workspace at workos.no first |
| 403 on write tools | Missing `write` scope | Re-run the OAuth flow with `read write` |
More in [`docs/connect.md`](docs/connect.md) under "Troubleshooting".
## Links
- For agents (public docs): https://workos.no/for-agenter
- Homepage: https://workos.no
- Support: [email protected]
FILE:README.md
# WorkOS for OpenClaw
A ClawHub skill that teaches OpenClaw and other MCP-compatible agents how to
use **WorkOS** — a self-hosted workspace platform with documents, databases,
tasks, meeting transcription, and sharing.
WorkOS exposes its full data model through a remote MCP server at
`https://workos.no/api/mcp` with OAuth 2.1. This skill gives the agent:
- Clear rules for **when** to use WorkOS.
- An overview of the ~60 tools available, grouped by area.
- Connection recipes for OpenClaw, Claude Desktop, Cursor, Cline, and OpenCode.
- Workflow patterns and troubleshooting.
## Contents
```
workos-clawhub-skill-en/
├── SKILL.md # Main agent-facing instructions
├── README.md # This file
├── LICENSE # MIT-0
├── docs/
│ ├── connect.md # Per-client connection setup
│ ├── tools.md # Full tool catalog
│ └── workflows.md # Example flows
└── examples/
└── prompts.md # Sample prompts for testing
```
## License
MIT-0 — free use, no attribution required. See `LICENSE`.
## Maintenance
- Homepage: <https://workos.no>
- For agents: <https://workos.no/for-agenter>
- Issues / contact: [email protected]
FILE:examples/prompts.md
# Sample prompts
Use these to verify the agent picks up the WorkOS skill and connects to the
server correctly.
## Connection
> "Connect to the WorkOS MCP."
> "Set up workos.no in Claude Desktop."
## Reading
> "What open tasks do I have in my workspace?"
> "Find the document I wrote about Q1 strategy."
> "Show me all meetings from last week."
## Writing
> "Create a new page in the Notes group called 'Research ideas 2026'."
> "Add a task to the Tasks database: 'Order webinar equipment', due next Friday."
> "Write a summary of the meeting I uploaded yesterday."
## Organization
> "Move all pages about customer X into a new group called 'Customer X'."
> "Create a kanban view of the Tasks database grouped by Status."
## Sharing
> "Create a shareable link to the page 'Welcome to onboarding' that expires in a week."
> "Revoke share links older than 30 days."
## Expected behavior
For every prompt above, the agent should:
1. Confirm which workspace if there is more than one.
2. Fetch IDs through list/search tools before writing.
3. Confirm destructive operations with the user.
4. Return a short summary with a URL/ID after the action.
FILE:docs/connect.md
# Connecting
The WorkOS MCP server lives at:
```
https://workos.no/api/mcp
```
- **Transport:** Streamable HTTP (JSON-RPC 2.0). Stateless. GET returns 405.
- **Auth:** OAuth 2.1 (Authorization Code + PKCE). Bearer token.
- **Scopes:** `read`, `write`.
- **Discovery:** `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`, advertised via 401 + `WWW-Authenticate`.
- **Token lifetimes:** Access 60 min, refresh 30 days.
## OpenClaw
OpenClaw discovers remote MCP via URL and runs the OAuth flow in the system
browser:
```bash
openclaw mcp add workos --url https://workos.no/api/mcp
```
Or manually in `~/.config/openclaw/config.json`:
```json
{
"mcp": {
"workos": {
"type": "remote",
"url": "https://workos.no/api/mcp"
}
}
}
```
The first call triggers a browser consent dialog and stores tokens in the
client's secure store.
## Claude Desktop
`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
`%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"workos": {
"url": "https://workos.no/api/mcp"
}
}
}
```
## Claude.ai (web)
Settings → Connectors → **Add custom connector** → paste the URL.
## Cursor
Settings → MCP → **Add new MCP server**, or `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"workos": {
"url": "https://workos.no/api/mcp"
}
}
}
```
## Cline (VS Code)
Cline must be told explicitly that the transport is Streamable HTTP — it
defaults to SSE:
```json
{
"mcpServers": {
"workos": {
"type": "streamableHttp",
"url": "https://workos.no/api/mcp"
}
}
}
```
## OpenCode (sst)
`opencode.json` in the project root or `~/.config/opencode/config.json`:
```json
{
"mcp": {
"workos": {
"type": "remote",
"url": "https://workos.no/api/mcp"
}
}
}
```
## Generic MCP client (manual OAuth)
1. POST `/api/oauth/register` with `client_name`, `redirect_uris`, `scope: "read write"` → receive `client_id`.
2. Send the user to `/oauth/authorize?client_id=...&response_type=code&redirect_uri=...&code_challenge=...&code_challenge_method=S256&scope=read+write`.
3. POST `/api/oauth/token` with `grant_type=authorization_code`, `code`, `redirect_uri`, `code_verifier` → receive `access_token` + `refresh_token`.
4. POST `/api/mcp` with `Authorization: Bearer <token>` and a JSON-RPC 2.0 payload.
Refresh: POST `/api/oauth/token` with `grant_type=refresh_token`.
## Troubleshooting
**`405 Method Not Allowed` on GET** — the client is trying SSE. Switch to
Streamable HTTP. For Cline: set `"type": "streamableHttp"`.
**`401 Unauthorized` after an hour** — the access token expired. The client
should refresh automatically. If not, remove the server and re-add it.
**Discovery fails** — the `.well-known` URLs are served by Next.js
(overriding nginx). If you sit behind a proxy that strips them, open them
explicitly or use the metadata URLs directly:
`/api/mcp-metadata/authorization-server` and
`/api/mcp-metadata/protected-resource`.
**Wrong workspace** — the token binds to the account's primary workspace. To
switch: remove the server in the client, log in with the right account in a
browser, and add it again. Or use `list_workspaces` and pass `workspaceId`
on each call where supported.
**OAuth window does not open (headless)** — copy the authorization URL
manually and paste it into a local browser; the redirect URL contains the
`code` you can hand back to the client.
FILE:docs/tools.md
# Tool catalog
Always call `tools/list` after `initialize` for the authoritative list — the
table below may lag. Tools are grouped by topic.
## Account and workspace
| Tool | Purpose |
|---|---|
| `get_me` | Logged-in user (id, name, email, role) |
| `list_workspaces` | All workspaces the user belongs to |
| `get_workspace` | Detailed info about one workspace |
| `list_workspace_members` | Members and roles |
## Pages (documents, wiki, notes)
| Tool | Purpose |
|---|---|
| `list_pages` | Pages in a workspace or group |
| `search_pages` | Full-text search |
| `get_page` | Fetch one page with blocks |
| `create_page` | Create page (workspaceId, optional pageGroupId, parentPageId) |
| `update_page` | Change title, icon, group |
| `move_page` | Move between groups / hierarchy |
| `archive_page` | Soft delete (recoverable) |
| `restore_page` | Restore archived |
| `delete_page` | Permanent delete |
## Page blocks (content)
| Tool | Purpose |
|---|---|
| `append_blocks` | Append blocks to the end of a page |
| `insert_blocks_after` | Insert after a given block ID |
| `update_block` | Edit one block |
| `delete_blocks` | Delete multiple blocks |
Blocks use the BlockNote schema (heading, paragraph, bulletListItem,
numberedListItem, table, code, image, …). Call `get_page` to inspect the
current structure before editing.
## Page groups (sidebar organization)
| Tool | Purpose |
|---|---|
| `list_page_groups` | Groups in a workspace |
| `create_page_group` | New group |
| `update_page_group` | Name / icon |
| `delete_page_group` | Delete (pages move to ungrouped) |
| `reorder_page_groups` | Change order |
## Databases
| Tool | Purpose |
|---|---|
| `list_databases` | Databases in a workspace |
| `create_database` | New database (with starting schema) |
| `get_database` | Schema + views |
| `update_database` | Name, description |
| `delete_database` | Delete |
### Properties
| Tool | Purpose |
|---|---|
| `add_db_property` | New property (TITLE, TEXT, NUMBER, SELECT, MULTI_SELECT, DATE, CHECKBOX, URL, EMAIL, PHONE, USER, RELATION, FILE) |
| `update_db_property` | Rename / config |
| `remove_db_property` | Delete property |
| `reorder_db_properties` | Reorder |
### Rows
| Tool | Purpose |
|---|---|
| `list_db_rows` | Fetch rows (filter, sort, pagination) |
| `create_db_row` | New row |
| `update_db_cell` | Set value in one cell |
| `delete_db_row` | Delete row |
| `move_db_row` | Move between databases / position |
### Views
| Tool | Purpose |
|---|---|
| `list_db_views` | Views in a database |
| `create_db_view` | New TABLE / BOARD / LIST / GALLERY view |
| `update_db_view` | Filters, sort, visible properties |
| `delete_db_view` | Delete view |
### Import
| Tool | Purpose |
|---|---|
| `import_table_to_database` | Convert a block-level table into a database |
## Meetings
| Tool | Purpose |
|---|---|
| `list_meeting_templates` | Templates for transcription / summary |
| `create_meeting` | New meeting (linked to a page) |
| `append_transcript` | Append transcript segments |
| `generate_meeting_summary` | AI summary using a template |
## Comments
| Tool | Purpose |
|---|---|
| `list_comments` | Comments on page / block / row |
| `create_comment` | New comment (starts a thread) |
| `update_comment` | Edit |
| `resolve_comment` | Mark as resolved |
| `delete_comment` | Delete |
## Sharing
| Tool | Purpose |
|---|---|
| `list_share_links` | Active external links |
| `create_share_link` | New link (read-only / password / expiry) |
| `revoke_share_link` | Disable a link |
## Files
| Tool | Purpose |
|---|---|
| `upload_image` | Upload an image for use in blocks (returns URL) |
## Conventions
- **IDs** are strings (cuid). Never construct them by hand.
- **`workspaceId`** is required on most write tools. Get it from
`list_workspaces` or context.
- **Dates** are ISO-8601 in UTC.
- **Pagination** uses `cursor` (opaque) + `limit` (default 50, max 100).
- **Errors** follow JSON-RPC: `error.code` and `error.message`. Common
codes: -32601 (unknown method), -32602 (bad params), -32603 (internal
error), 401 (unauthorized), 403 (missing scope/role).
FILE:docs/workflows.md
# Example flows
Practical patterns for common tasks. All examples assume OAuth has completed
and the MCP client has access to the tools.
## 1. Search → fetch → show
User asks: *"What did I write about the onboarding process?"*
```
search_pages({ query: "onboarding", workspaceId })
→ pick the top hit
get_page({ pageId })
→ present title + relevant excerpt
```
## 2. Create a page with structure
User asks: *"Create a page about the Q2 plan in the Strategy group."*
```
list_workspaces() # confirm workspace
list_page_groups({ workspaceId }) # find the "Strategy" id
create_page({ workspaceId, pageGroupId, title: "Q2 plan" })
append_blocks({ pageId, blocks: [
{ type: "heading", level: 1, text: "Q2 plan" },
{ type: "paragraph", text: "..." },
{ type: "bulletListItem", text: "Goal 1" },
...
]})
```
## 3. Update rows in a database
User asks: *"Mark all open tasks from last week as overdue."*
```
list_databases({ workspaceId }) # find "Tasks"
get_database({ databaseId }) # find property ids for Status, Due
list_db_rows({
databaseId,
filter: { and: [
{ property: statusId, equals: "OPEN" },
{ property: dueId, before: "2026-04-21" },
]},
limit: 100,
})
for each row:
update_db_cell({ rowId: row.id, propertyId: statusId, value: "OVERDUE" })
```
Confirm the count with the user before running mass updates.
## 4. Meeting flow
User has a meeting recording and wants a summary:
```
create_meeting({ workspaceId, title, startedAt })
# Send the transcript in chunks for larger recordings:
for each chunk:
append_transcript({ meetingId, segments: [...] })
list_meeting_templates({ workspaceId }) # pick "Standup" or "Sales call"
generate_meeting_summary({ meetingId, templateId })
# The result is added as blocks on the linked page.
```
## 5. Safe edits to an existing page
Before overwriting:
```
get_page({ pageId }) # load current blocks
# Show the user a diff or change suggestion
# After confirmation:
update_block({ blockId, ... }) or append_blocks(...)
```
Prefer `update_block` over `delete_blocks` + `append_blocks`.
## 6. Share a page externally
```
create_share_link({
pageId,
expiresAt: "2026-05-01T00:00:00Z",
password: null, # or string
})
→ returns { url, token }
# Show the URL to the user. Use revoke_share_link({ linkId }) to disable.
```
## 7. Image in a page
```
upload_image({ workspaceId, filename, dataBase64 })
→ { url }
append_blocks({ pageId, blocks: [
{ type: "image", url, caption: "..." }
]})
```
## General rules
1. **Fetch IDs from list/search calls**, never guess.
2. **Confirm destructive actions** (delete, archive, revoke) explicitly.
3. **Mirror the user's language** — many WorkOS users write in Norwegian.
4. **Tell the user what you did**: after a write, give a short confirmation
with a page/row ID or URL.