Skip to main content
Glama
YesuCS

rock-rms-mcp

by YesuCS
README.md
# rock-rms-mcp

A thin, read-only MCP server for Rock RMS. Lets Claude Desktop / Cowork query
People, Groups, Group Members, and Attendance from your Rock instance over its
REST API. GET-only by design; there is no code path that writes to Rock.

**This is a stopgap.** Native MCP support lands in Rock v21; when you upgrade,
retire this project and switch to the built-in server.

---

## 1. Rock-side setup

The REST key's permissions are the real security boundary here, so set it up
with least privilege:

1. **Create a service person record** in Rock, e.g. "Claude MCP Agent"
   (record type: Business or a regular Person record; either works for REST
   keys). Do NOT attach the key to your own admin account.

2. **Create a security role**, e.g. `RSR - Claude MCP Read Only`, and add the
   service person to it.

3. **Create the REST key:** Admin Tools > Security > REST Keys > add a key
   attached to the service person. Copy the key; you'll put it in the config
   below.

4. **Grant controller permissions:** Admin Tools > Security > REST Controllers.
   Grant the role **View** (only View) on:

   - People
   - Groups
   - GroupMembers
   - Attendances
   - Campuses (optional, cheap and useful)

   Leave everything else, especially all Financial* controllers, unpermitted.

5. Verify default-deny: as long as the service person isn't in any broader
   security roles, controllers you didn't explicitly grant will return 401/403.

## 2. Install and build

Requires Node.js 18+.

```
cd rock-mcp
npm install
npm run build
```

This compiles `src/index.ts` to `dist/index.js`.

## 3. Wire into Claude Desktop / Cowork

Edit `claude_desktop_config.json`:

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

Add (adjust the path and values):

```json
{
  "mcpServers": {
    "rock-rms": {
      "command": "node",
      "args": ["C:\\Users\\[ User ]\\rock-mcp\\dist\\index.js"],
      "env": {
        "ROCK_BASE_URL": "https://rock.[ your church ].org",
        "ROCK_API_KEY": "PASTE-REST-KEY-HERE"
      }
    }
  }
}
```

Fully quit and reopen the Claude app (tab close is not enough).

**Key handling:** the REST key sits in this config file in plain text. That's
normal for local MCP servers, but treat the file accordingly; it's another
reason the key must be least-privilege, not admin-level.

## 4. Test

In a Cowork session, try:

- "Search Rock for people named Smith"
- "List active groups whose name contains 'ESL'"
- "Who are the active members of group 1234?"
- "Show attendance for group 1234 between 2026-06-01 and 2026-07-01"

And confirm the security boundary holds:

- "Use rock_get to fetch /api/FinancialTransactions?$top=1"
  should come back 401/403. If it doesn't, revisit step 1.

## Tools exposed

| Tool                | Purpose                                                   |
| ------------------- | --------------------------------------------------------- |
| `search_people`     | Name search via /api/People/Search                        |
| `get_person`        | Single person by PersonId                                 |
| `list_groups`       | Groups, filterable by GroupTypeId / name fragment         |
| `get_group_members` | Active members of a group, with Person + role expanded    |
| `get_attendance`    | Attendance in a date range, optionally per group          |
| `rock_get`          | Constrained generic GET (must start with /api/, GET only) |

## Notes

- Rock's REST API uses OData v3 query syntax (`$filter`, `$expand`, `$top`,
  `$orderby`, `substringof(...)`).
- Remember many Rock tables join on `PersonAliasId`, not `PersonId`; expand
  through `PersonAlias` when a raw endpoint hands you alias ids.

TDQS

A3.9/5.0

Scored across 8 tools

Disambiguation5/5

Each tool has a clear, distinct purpose. get_person, get_person_groups, get_group_members, list_groups, list_attendance_occurrences, get_attendance, search_people, and rock_get all target different aspects of Rock RMS with minimal overlap. The descriptions clarify any potential ambiguity, such as the use of PersonAliasId vs PersonId.

Naming Consistency4/5

Most tools follow a consistent verb_noun pattern in snake_case (e.g., get_person, list_groups, search_people). The exception is rock_get, which breaks the pattern by not starting with a verb like 'get', but it is still clear and fits the generic purpose. Overall, naming is predictable and readable.

Tool Count5/5

With 8 tools, the server is well-scoped for read-only access to Rock RMS. Each tool covers a core domain entity (people, groups, attendance), and the generic rock_get tool provides an escape hatch for other endpoints. The count feels appropriate for the intended functionality.

Completeness4/5

The tool set covers key read operations: people search, person details, person groups, group listing, group members, attendance occurrences, and attendance records. The generic rock_get tool fills gaps for other entities like campuses or locations. A minor gap is the lack of a direct get_group_by_id tool, but rock_get can handle it.

Maintenance

ActivitySlowing
ResponsivenessSyncing