Skip to main content
Glama
EmpathDesign

OfficeRnD MCP Server

by EmpathDesign
README.md
# OfficeRnD MCP Server

A production-ready **Model Context Protocol (MCP) server** that exposes the complete [OfficeRnD](https://www.officernd.com/) REST API as AI-friendly tools. Enables AI clients (Claude Desktop, ChatGPT, Cursor, VS Code, and others) to interact with your coworking space management platform using natural language.

[![CI](https://github.com/EmpathDesign/OfficeRnD_MCP/actions/workflows/ci.yml/badge.svg)](https://github.com/EmpathDesign/OfficeRnD_MCP/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

> **⚡ Full CRUD — not read-only.** This server supports **create, update, and delete** operations across all OfficeRnD resources in addition to reads. Ask your AI assistant to create bookings, update members, delete invoices, or perform any other write operation. Write tools are prefixed with `[WRITE]` in their descriptions. Call `health_check` to get a full list of available read and write tools at any time.

---

## Table of Contents

- [Overview](#overview)
- [Architecture](#architecture)
- [Capabilities at a Glance](#capabilities-at-a-glance)
- [Installation](#installation)
- [Authentication](#authentication)
- [Configuration](#configuration)
- [MCP Tools](#mcp-tools)
- [Client Setup](#client-setup)
  - [VS Code (Copilot)](#vs-code-copilot)
  - [Claude Desktop](#claude-desktop)
  - [Cursor](#cursor)
  - [ChatGPT](#chatgpt)
- [VS Code Extension](#vs-code-extension)
- [Development](#development)
- [Troubleshooting](#troubleshooting)
- [Deferred Endpoints](#deferred-endpoints)
- [Contributing](#contributing)
- [License](#license)

---

## Overview

This monorepo provides everything needed to connect any MCP-compatible AI client to OfficeRnD:

| Package                                   | Description                                                          |
| ----------------------------------------- | -------------------------------------------------------------------- |
| [`@officernd/sdk`](packages/sdk)          | Reusable OfficeRnD REST API SDK — OAuth2, retries, pagination        |
| [`@officernd/core`](packages/core)        | Business logic helpers — available rooms, expiring memberships, etc. |
| [`@officernd/mcp`](packages/mcp)          | MCP server exposing 160+ tools over stdio                            |
| [`officernd-mcp-vscode`](packages/vscode) | VS Code extension for credential management and MCP configuration    |

---

## Architecture

```
AI Client
(Claude Desktop / ChatGPT / Cursor / VS Code)

           │
           │  MCP (stdio)
           ▼

┌─────────────────────────────────────────┐
│           @officernd/mcp                │
│  Tool Registry (160+ CRUD + business)   │
├─────────────────────────────────────────┤
│           @officernd/core               │
│  Business helpers (rooms, members, …)  │
├─────────────────────────────────────────┤
│           @officernd/sdk                │
│  OAuth2 · HTTP Client · Pagination      │
│  Retries · Rate Limiting · Logging      │
└─────────────────────────────────────────┘

           │
           ▼

    OfficeRnD REST API
```

The SDK has **no MCP dependency**, making it reusable in non-MCP contexts.

---

## Capabilities at a Glance

This server is **fully mutation-capable** — it is not limited to read operations.

| Operation type | Tool prefix   | Example                                       |
| -------------- | ------------- | --------------------------------------------- |
| Read (list)    | `list_`       | `list_members`, `list_bookings`               |
| Read (single)  | `get_`        | `get_member`, `get_booking`                   |
| Read (count)   | `count_`      | `count_members`, `count_bookings`             |
| **Write**      | **`create_`** | **`create_booking`**, **`create_member`**     |
| **Write**      | **`update_`** | **`update_booking`**, **`update_member`**     |
| **Write**      | **`delete_`** | **`delete_booking`**, **`delete_member`**     |
| Business       | various       | `find_available_rooms`, `execute_checkout`, … |

Write tools are prefixed with `[WRITE]` in their MCP tool descriptions so that AI agents can identify them at a glance.

Call `health_check` at any time to receive a live JSON summary of every available tool, separated into `readTools` and `writeTools` lists.

---

## Installation

### Prerequisites

- Node.js 22 or later
- An OfficeRnD account with API access
- OAuth2 Client ID and Client Secret ([see Authentication](#authentication))

### Install the MCP Server

```bash
npm install -g @officernd/mcp
```

This installs the `officernd-mcp` command globally.

### Verify Installation

```bash
officernd-mcp --version
```

---

## Authentication

OfficeRnD uses **OAuth2 Client Credentials** for API access.

### Obtain Credentials

1. Log in to your OfficeRnD dashboard
2. Go to **Settings → Integrations → API**
3. Create a new OAuth2 application
4. Copy your **Client ID** and **Client Secret**
5. Note your **Organization Slug** (the subdomain in your OfficeRnD URL, e.g. `my-space` from `my-space.officernd.com`)

### Required Scopes

For the **Flex API v2** (recommended), grant your OAuth2 application the specific scopes it needs. Examples:

```
flex.community.members.read
flex.community.members.create
flex.space.bookings.read
flex.space.bookings.create
flex.billing.charges.read
```

Your OfficeRnD OAuth2 application must be configured with the scopes you want the MCP server to use. You must specify at least one scope — OfficeRnD will reject token requests that do not include a scope. Configure the `OFFICERND_SCOPES` environment variable (space-separated list) for the MCP server, or set `officernd.scopes` in VS Code settings for the extension.

The token endpoint is rate-limited to **5 requests per minute**. The SDK automatically caches tokens and reuses them until 60 seconds before expiry.

---

## Configuration

Configure the server using environment variables:

| Variable                  | Required    | Description                                                                                |
| ------------------------- | ----------- | ------------------------------------------------------------------------------------------ |
| `OFFICERND_CLIENT_ID`     | ✅          | Your OAuth2 Client ID                                                                      |
| `OFFICERND_CLIENT_SECRET` | ✅          | Your OAuth2 Client Secret                                                                  |
| `OFFICERND_ORG`           | Recommended | Organization slug (subdomain)                                                              |
| `OFFICERND_SCOPES`        | ✅          | Space-separated OAuth2 scopes (e.g. `flex.community.members.read`). Required by OfficeRnD. |
| `OFFICERND_API_VERSION`   | No          | API version: `v2` (default) or `v1`                                                        |
| `OFFICERND_LOG_LEVEL`     | No          | Log level: `debug`, `info` (default), `warn`, `error`                                      |

### Example

```bash
export OFFICERND_CLIENT_ID="your_client_id"
export OFFICERND_CLIENT_SECRET="your_client_secret"
export OFFICERND_ORG="my-coworking-space"
export OFFICERND_SCOPES="flex.community.members.read flex.space.bookings.read"
officernd-mcp
```

> **Security note:** Never hardcode credentials in configuration files. Use environment variables or a secrets manager. The VS Code extension generates MCP config with `${env:...}` placeholders so secrets are never written to disk.

---

## MCP Tools

The server automatically generates tools from the resource registry. Every resource supports a consistent set of operations:

### CRUD Tools (per resource)

| Tool Pattern        | Description                          |
| ------------------- | ------------------------------------ |
| `list_{resources}`  | List all items with optional filters |
| `get_{resource}`    | Get a specific item by ID            |
| `count_{resources}` | Count items matching filters         |
| `create_{resource}` | Create a new item                    |
| `update_{resource}` | Update an existing item              |
| `delete_{resource}` | Delete an item                       |

### Supported Resources

| Resource                  | Tools                                                                                                                            |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Members                   | `list_members`, `get_member`, `count_members`, `create_member`, `update_member`, `delete_member`                                 |
| Companies                 | `list_companies`, `get_company`, `count_companies`, `create_company`, `update_company`, `delete_company`                         |
| Teams                     | `list_teams`, `get_team`, `count_teams`, `create_team`, `update_team`, `delete_team`                                             |
| Memberships               | `list_memberships`, `get_membership`, `count_memberships`, `create_membership`, `update_membership`, `delete_membership`         |
| Bookings                  | `list_bookings`, `get_booking`, `count_bookings`, `create_booking`, `update_booking`, `delete_booking`                           |
| Rooms                     | `list_rooms`, `get_room`, `count_rooms`, `create_room`, `update_room`, `delete_room`                                             |
| Desks                     | `list_desks`, `get_desk`, `count_desks`, `create_desk`, `update_desk`, `delete_desk`                                             |
| Resource Types            | `list_resource_types`, `get_resource_type`, `create_resource_type`, `update_resource_type`, `delete_resource_type`               |
| Locations                 | `list_locations`, `get_location`, `create_location`, `update_location`, `delete_location`                                        |
| Floors                    | `list_floors`, `get_floor`, `create_floor`, `update_floor`, `delete_floor`                                                       |
| Amenities                 | `list_amenities`, `get_amenity`, `create_amenity`, `update_amenity`, `delete_amenity`                                            |
| Assignments               | `list_assignments`, `get_assignment`, `count_assignments`, `create_assignment`, `delete_assignment`                              |
| Passes                    | `list_passes`, `get_pass`, `count_passes`, `create_pass`, `update_pass`, `delete_pass`                                           |
| Coins                     | `list_coins`, `get_coin`, `count_coins`                                                                                          |
| Credits                   | `list_credits`, `get_credit`, `create_credit`, `update_credit`, `delete_credit`                                                  |
| Invoices                  | `list_invoices`, `get_invoice`, `count_invoices`, `create_invoice`, `update_invoice`, `delete_invoice`                           |
| Payments                  | `list_payments`, `get_payment`, `count_payments`, `create_payment`, `update_payment`, `delete_payment`                           |
| Charges                   | `list_charges`, `get_charge`, `count_charges`, `create_charge`, `update_charge`, `delete_charge`                                 |
| Payment Details           | `list_payment_details`, `get_payment_detail`, `create_payment_detail`, `delete_payment_detail`                                   |
| Tax Rates                 | `list_tax_rates`, `get_tax_rate`                                                                                                 |
| Revenue Accounts          | `list_revenue_accounts`, `get_revenue_account`                                                                                   |
| Resource Rates            | `list_resource_rates`, `get_resource_rate`                                                                                       |
| Cancellation Policies     | `list_cancellation_policies`, `get_cancellation_policy`                                                                          |
| Plans                     | `list_plans`, `get_plan`, `create_plan`, `update_plan`, `delete_plan`                                                            |
| Billing Plans             | `list_billing_plans`, `get_billing_plan`, `create_billing_plan`, `update_billing_plan`, `delete_billing_plan`                    |
| Visitors                  | `list_visitors`, `get_visitor`, `count_visitors`, `create_visitor`, `update_visitor`, `delete_visitor`                           |
| Visits                    | `list_visits`, `get_visit`, `count_visits`, `create_visit`, `update_visit`, `delete_visit`                                       |
| Events                    | `list_events`, `get_event`, `count_events`, `create_event`, `update_event`, `delete_event`                                       |
| Tickets                   | `list_tickets`, `get_ticket`, `count_tickets`, `create_ticket`, `update_ticket`                                                  |
| Ticket Options            | `list_ticket_options`, `get_ticket_option`                                                                                       |
| Ticket Comments           | `list_ticket_comments`, `get_ticket_comment`, `create_ticket_comment`                                                            |
| Posts                     | `list_posts`, `get_post`, `count_posts`, `create_post`, `delete_post`                                                            |
| Benefits                  | `list_benefits`, `get_benefit`                                                                                                   |
| Opportunities             | `list_opportunities`, `get_opportunity`, `count_opportunities`, `create_opportunity`, `update_opportunity`, `delete_opportunity` |
| Opportunity Statuses      | `list_opportunity_statuses`, `get_opportunity_status`                                                                            |
| Contracts                 | `list_contracts`, `get_contract`, `count_contracts`, `create_contract`, `update_contract`, `delete_contract`                     |
| Check-ins                 | `list_checkins`, `get_checkin`, `count_checkins`, `create_checkin`, `update_checkin`, `delete_checkin`                           |
| Fees                      | `list_fees`, `get_fee`, `create_fee`, `update_fee`, `delete_fee`                                                                 |
| Reception Flows           | `list_reception_flows`, `get_reception_flow`                                                                                     |
| Webhooks                  | `list_webhooks`, `get_webhook`, `create_webhook`, `update_webhook`, `delete_webhook`                                             |
| Secondary Currencies      | `list_secondary_currencies`, `get_secondary_currency`, `update_secondary_currency`                                               |
| … and more resource types |                                                                                                                                  |

### Business / AI Convenience Tools

| Tool                                    | Description                                                                               |
| --------------------------------------- | ----------------------------------------------------------------------------------------- |
| `find_available_rooms`                  | Find available meeting rooms for a time range                                             |
| `find_memberships_expiring_soon`        | Find memberships expiring within N days                                                   |
| `get_todays_visitors`                   | Get all visitors for today                                                                |
| `get_todays_bookings`                   | Get all room bookings for today                                                           |
| `get_unpaid_invoices`                   | Get all outstanding invoices                                                              |
| `get_members_by_company`                | Get all members from a company                                                            |
| `get_active_members`                    | Get all currently active members                                                          |
| `get_inventory`                         | Get a consolidated inventory of resources, resource types, and rates in a single response |
| `get_resource_rate_cancellation_policy` | Get the cancellation policy linked to a specific resource rate                            |
| `preview_checkout`                      | Preview pricing, fees, and taxes for a checkout without committing to it (read-only)      |
| `execute_checkout`                      | Finalize a plan/membership/booking checkout, including billing (write operation)          |

### Setup Tool

| Tool                  | Description                                                                     |
| --------------------- | ------------------------------------------------------------------------------- |
| `configure_officernd` | Configure credentials at runtime — use this if env vars were not set at startup |
| `health_check`        | Check configuration status and verify connectivity to the OfficeRnD API         |

### Example AI Interactions

```
"Show me all members who joined in the last 30 days"
→ list_members with date filters

"Find available meeting rooms tomorrow at 2pm for 8 people"
→ find_available_rooms

"Which memberships are expiring this month?"
→ find_memberships_expiring_soon with daysUntilExpiry: 30

"Show today's visitors"
→ get_todays_visitors

"How many unpaid invoices do we have?"
→ get_unpaid_invoices

"Show me all resources, their types, and pricing rates for our downtown location"
→ get_inventory with locationId

"What's the cancellation policy for this resource rate?"
→ get_resource_rate_cancellation_policy with resourceRateId

"Preview the checkout cost for this member on this plan before charging them"
→ preview_checkout with filters (memberId, planId)

"Is the OfficeRnD connection working?"
→ health_check

"Book the downtown conference room for tomorrow at 2pm for 2 hours"
→ create_booking with resourceId, start, end

"Cancel John's booking"
→ delete_booking with id

"Update the member's email address"
→ update_member with id and data

"Add a new member named Jane Smith"
→ create_member with data

"Create a visitor pass for next Monday"
→ create_visitor with data

"Finalize the checkout for this member's plan"
→ execute_checkout with data

"What write operations can this server perform?"
→ health_check — returns writeTools list with all available mutation tools
```

---

## Client Setup

### VS Code (Copilot)

#### Option A: Using the VS Code Extension (Recommended)

1. Install the **OfficeRnD MCP** extension from the VS Code Marketplace
2. Run command: `OfficeRnD: Configure Connection`
3. Enter your Client ID, Client Secret, and Organization Slug
4. Run command: `OfficeRnD: Generate MCP Configuration`
5. The extension writes `.vscode/mcp.json` with secure environment variable references

> **Note:** The generated config uses `${env:OFFICERND_CLIENT_ID}` references. You must also export those variables in your shell profile (`.bashrc`, `.zshrc`, etc.) so the MCP server process can read them. See [Option B](#option-b-manual-configuration-with-environment-variables) below for details.

#### Option B: Manual Configuration with Environment Variables

Create or edit `.vscode/mcp.json` in your workspace:

```json
{
  "servers": {
    "officernd": {
      "command": "officernd-mcp",
      "env": {
        "OFFICERND_CLIENT_ID": "${env:OFFICERND_CLIENT_ID}",
        "OFFICERND_CLIENT_SECRET": "${env:OFFICERND_CLIENT_SECRET}",
        "OFFICERND_ORG": "your-org-slug"
      }
    }
  }
}
```

Set environment variables in your shell profile (`.bashrc`, `.zshrc`, etc.):

```bash
export OFFICERND_CLIENT_ID="your_client_id"
export OFFICERND_CLIENT_SECRET="your_client_secret"
```

#### Option C: Runtime Configuration via `configure_officernd` (Simplest)

The server can start without any credentials and be configured later through its `configure_officernd` tool. This is the easiest option when you do not want to set environment variables.

Create `.vscode/mcp.json` with just the command — no `env` block required:

```json
{
  "servers": {
    "officernd": {
      "command": "officernd-mcp"
    }
  }
}
```

Then ask your AI assistant to configure the connection:

```
"Configure OfficeRnD with clientId my-client-id, clientSecret my-secret, orgSlug my-org"
→ configure_officernd
```

The AI will call the `configure_officernd` tool and all other tools will become available for the lifetime of that server process.

---

### Claude Desktop

Edit your Claude Desktop configuration file:

- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "officernd": {
      "command": "officernd-mcp",
      "env": {
        "OFFICERND_CLIENT_ID": "your_client_id",
        "OFFICERND_CLIENT_SECRET": "your_client_secret",
        "OFFICERND_ORG": "your-org-slug"
      }
    }
  }
}
```

Restart Claude Desktop. You should see "officernd" in the MCP servers list.

---

### Cursor

Create or edit `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "officernd": {
      "command": "officernd-mcp",
      "env": {
        "OFFICERND_CLIENT_ID": "your_client_id",
        "OFFICERND_CLIENT_SECRET": "your_client_secret",
        "OFFICERND_ORG": "your-org-slug"
      }
    }
  }
}
```

---

### ChatGPT

ChatGPT supports MCP via the OpenAI desktop app. Configure in the app's MCP settings using the same `officernd-mcp` command with the required environment variables.

---

## VS Code Extension

The `officernd-mcp-vscode` extension provides a first-class developer experience:

### Commands

| Command                                 | Description                                                     |
| --------------------------------------- | --------------------------------------------------------------- |
| `OfficeRnD: Configure Connection`       | Guided setup wizard for credentials                             |
| `OfficeRnD: Test Connection`            | Verify credentials and API connectivity                         |
| `OfficeRnD: Show Configuration`         | Display current config (secrets masked)                         |
| `OfficeRnD: Update Credentials`         | Update stored credentials                                       |
| `OfficeRnD: Clear Credentials`          | Remove all stored credentials                                   |
| `OfficeRnD: Generate MCP Configuration` | Write `.vscode/mcp.json` with env var placeholders              |
| `OfficeRnD: Open Logs`                  | Open the output channel for debug logs                          |
| `OfficeRnD: Add All Scopes`             | Populate `officernd.scopes` with all available OfficeRnD scopes |

### Status Bar

The status bar shows the current connection state:

- `$(check) OfficeRnD Connected` — credentials configured
- `$(warning) OfficeRnD Disconnected` — no credentials

### Security

Credentials are stored in VS Code's **SecretStorage** (OS keychain). Secrets are **never** written to:

- `settings.json`
- Workspace settings
- `mcp.json` — env var references (`${env:...}`) are used instead

---

## Development

### Prerequisites

```bash
node --version  # Must be >= 22
npm --version
```

### Clone and Install

```bash
git clone https://github.com/EmpathDesign/OfficeRnD_MCP.git
cd OfficeRnD_MCP
npm install
```

### Build

```bash
npm run build
```

### Test

```bash
npm test
```

### Lint and Format

```bash
npm run lint          # ESLint
npm run format:check  # Prettier check
npm run format        # Prettier fix
```

### Monorepo Structure

```
packages/
├── sdk/          @officernd/sdk     — REST API SDK
├── core/         @officernd/core    — Business helpers
├── mcp/          @officernd/mcp     — MCP server + CLI
└── vscode/       officernd-mcp-vscode — VS Code extension
```

### Adding a New Resource

The resource registry in `packages/sdk/src/resources/registry.ts` is the single source of truth. Add a new entry:

```typescript
{
  name: 'my_resource',
  path: '/my-resources',
  description: 'Description of the resource',
  operations: ['list', 'get', 'create', 'update', 'delete', 'count'],
}
```

The MCP server automatically generates all tools from this registry. No additional code changes are needed.

---

## Troubleshooting

### Tools return "OfficeRnD is not configured"

The server starts without credentials when no environment variables are set. To authenticate, ask your AI assistant to call the `configure_officernd` tool:

```
"Configure OfficeRnD with my credentials"
```

Or set the `OFFICERND_CLIENT_ID` and `OFFICERND_CLIENT_SECRET` environment variables before starting the server (see [Configuration](#configuration)).

### Authentication errors

```
OAuth2 token request failed: 401
```

- Verify your Client ID and Client Secret are correct
- Ensure the OAuth2 application has the Flex API scopes your workflows need (for example `flex.community.members.read`)
- Check that your organization slug matches your OfficeRnD URL

### Rate limiting

The token endpoint is limited to 5 requests/minute. The SDK caches tokens automatically — this should only occur if the server is restarted very frequently.

### 404 errors on API calls

- Verify your `OFFICERND_ORG` is set to the correct organization slug
- Check that the API version (`OFFICERND_API_VERSION`) matches what your account supports

### Enabling debug logging

```bash
OFFICERND_LOG_LEVEL=debug officernd-mcp
```

Logs are written to **stderr** to keep MCP's stdout protocol clean.

---

## Deferred Endpoints

The following OfficeRnD API resources are not yet implemented. They are documented here for follow-up:

| Resource                 | Notes                                                                                                       |
| ------------------------ | ----------------------------------------------------------------------------------------------------------- |
| Access Control           | Badge/door access management                                                                                |
| Occupancy tracking       | Real-time sensor data                                                                                       |
| Multi-org federation     | Cross-organization queries                                                                                  |
| Webhooks delivery status | Delivery/retry status for registered webhooks (CRUD via `list_webhooks`/`create_webhook`/etc. is supported) |
| Document uploads         | Binary file operations                                                                                      |
| OpenAPI code generation  | Automatic SDK regeneration                                                                                  |

> Checkout flows (`preview_checkout` / `execute_checkout`) and resource-rate cancellation policy lookups (`get_resource_rate_cancellation_policy`) are now supported — see [MCP Tools](#mcp-tools).

The `RESOURCES` registry in `packages/sdk/src/resources/registry.ts` is designed for declarative extension — adding a new resource requires a single entry.

---

## Contributing

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/my-feature`
3. Make changes and add tests
4. Verify: `npm run build && npm test && npm run lint`
5. Submit a pull request

All PRs run the CI workflow (lint → format check → build → test) automatically.

---

## License

[MIT](LICENSE) © EmpathDesign

Maintenance

ActivitySlowing
ResponsivenessUnresponsive