Skip to main content
Glama
clue2solve

clue2app-user-mcp

Official
by clue2solve
README.md
# clue2app-user-mcp

MCP server exposing coordinator's user/membership/role admin operations as
tools for LLM callers (agents, Claude Desktop, etc.). Every tool is a thin
passthrough to coordinator's `/api/users/*` endpoints — RBAC is enforced
entirely by coordinator using the caller's bearer token; this service does
not validate or interpret tokens itself.

## Tool catalog

| Group | Tool | Coordinator endpoint |
|---|---|---|
| users | `list_users` | `GET /api/users` |
| users | `get_user` | `GET /api/users/{id}` |
| users | `disable_user` | `POST /api/users/{id}/disable` |
| users | `enable_user` | `POST /api/users/{id}/enable` |
| users | `resolve_duplicate_users` | `POST /api/users/resolve-duplicates` |
| memberships | `list_user_memberships` | `GET /api/users/{id}/memberships` |
| roles | `grant_role` | `POST /api/users/{id}/roles` |
| roles | `revoke_role` | `DELETE /api/users/{id}/roles/{role}` |

## Local dev (stdio transport)

```bash
cd clue2app-user-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e .

export COORDINATOR_URL=http://localhost:8081       # or your coordinator base URL
export COORDINATOR_TOKEN=<a coordinator-issued bearer token>

user-mcp                     # defaults to --transport=stdio
# or: python -m user_mcp.server --transport=stdio
```

Point an MCP-capable client (Claude Desktop, `mcp dev`, etc.) at the
`user-mcp` command with those two env vars set. stdio has no per-request
auth header, so the token is read once from `COORDINATOR_TOKEN` at startup
and reused for every tool call in that session.

### Quick smoke test

```bash
python -c "
import sys; sys.path.insert(0, 'src')
from user_mcp import server
print([t for t in dir(server) if not t.startswith('_')][:5])
"
```

## Hosted deploy (SSE transport)

The Knative/kpack deployment runs the SSE transport, which reads the bearer
token per-request from the inbound `Authorization: Bearer <token>` header —
each caller supplies their own token, so a single instance safely serves
many callers at different privilege levels.

```bash
python -m user_mcp.server --transport=sse --port=$PORT
```

This is exactly what `Procfile` runs. Paketo's Python buildpack detects
`pyproject.toml` directly (no `requirements.txt` needed, no `Dockerfile`
needed) and uses `python -m` so we don't depend on where the buildpack
places console-script shims in the launch image.

**Env vars**

| Var | Required | Notes |
|---|---|---|
| `COORDINATOR_URL` | yes | e.g. `http://coordinator.control.svc.cluster.local` in-cluster |
| `COORDINATOR_TOKEN` | stdio only | ignored by the SSE transport |
| `PORT` | no | Knative-injected; defaults to 8080 |

No secrets are baked into this service — every tool call carries its own
token, and the service holds nothing longer than the lifetime of a single
request.

## Endpoints

* `GET /sse` — MCP session endpoint (SSE transport)
* `POST /messages` — MCP message endpoint (SSE transport)
* `GET /health` — `200 {"status": "ok"}`, no coordinator round-trip. Wire
  both `readinessProbe` and `livenessProbe` to this path — a coordinator
  outage must not cascade into MCP pod restarts.

## Layout

```
src/user_mcp/
├── server.py            # FastMCP init, CLI dispatch, /health, transport wiring
├── coord_client.py       # httpx.AsyncClient wrapper, bearer passthrough
├── auth.py               # bearer_from_context() using a contextvar
└── tools/
    ├── users.py          # list/get/disable/enable/resolve_duplicates
    ├── memberships.py    # list_user_memberships
    └── roles.py          # grant/revoke_role
```

TDQS

A3.9/5.0

Scored across 8 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: disabling, enabling, fetching, granting roles, listing memberships, listing users, resolving duplicates, and revoking roles. No overlap or ambiguity.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern using snake_case (e.g., disable_user, grant_role). Naming is predictable and uniform.

Tool Count5/5

8 tools is well-scoped for user management, covering core operations without unnecessary bloat.

Completeness4/5

The set covers enable/disable, role management, and listing, but lacks create_user and delete_user, which are minor gaps for a user management server.

Maintenance

ActivityStale
ResponsivenessNo issues