Skip to main content
Glama
README.md
# companycam-mcp

Remote [MCP](https://modelcontextprotocol.io) server for the [CompanyCam API](https://docs.companycam.com/reference), built for use as a **claude.ai custom connector** (and any other MCP client that speaks Streamable HTTP).

- **Transport:** MCP Streamable HTTP (stateless JSON-RPC over POST) — no SSE stream, no sessions
- **Runtime:** single zero-dependency Vercel serverless function ([api/_lib/mcp-core.ts](api/_lib/mcp-core.ts))
- **Auth to CompanyCam:** server-side `COMPANYCAM_API_TOKEN` (Bearer)
- **Auth to the endpoint** (two equivalent modes, same `MCP_SHARED_SECRET`):
  - Secret path: `https://<deployment>/mcp/<MCP_SHARED_SECRET>` — for the claude.ai custom-connector dialog
  - Bearer header: `https://<deployment>/mcp` with `Authorization: Bearer <MCP_SHARED_SECRET>` — for Claude Tag "Connect an app" credentials (see [.mcp.json](.mcp.json), which registers this repo as a Claude Tag plugin pointing at `/mcp`)

## Tools (26)

No delete tools are exposed by design — the shared server-side token means every connector user acts as the token owner, so destructive operations are limited to archiving (reversible).

| Area | Tools |
|---|---|
| Company / users | `get_company`, `get_current_user`, `list_users` |
| Projects | `list_projects`, `get_project`, `create_project`, `update_project`, `archive_project`, `restore_project`, `update_project_notepad` |
| Project people | `list_project_assigned_users`, `assign_user_to_project` |
| Project content | `list_project_documents`, `list_project_comments`, `add_project_comment` |
| Photos | `list_project_photos`, `list_photos`, `get_photo`, `add_photo`, `update_photo_description` |
| Photo metadata | `list_photo_tags`, `add_photo_tags`, `list_photo_comments`, `add_photo_comment` |
| Tags | `list_tags`, `create_tag` |

Notes:
- `add_photo` requires the image to already be hosted at a **publicly accessible URL** — that's how the CompanyCam API works (it downloads from `uri`).
- Write tools accept `acting_user_email` to attribute the action to a specific CompanyCam user (`X-CompanyCam-User` header).
- Photo responses collapse the `uris` renditions array into a `{type: url}` map to keep chat context small.

## Environment variables (Vercel)

| Var | Purpose |
|---|---|
| `COMPANYCAM_API_TOKEN` | CompanyCam API access token (CompanyCam → Settings → API) |
| `MCP_SHARED_SECRET` | Random string that becomes the secret path segment of the connector URL |

## Add to claude.ai

Settings → Connectors → **Add custom connector**:
- **Name:** CompanyCam
- **Remote MCP server URL:** `https://<production-domain>/mcp/<MCP_SHARED_SECRET>`
- Leave OAuth fields empty (auth is the secret URL + server-side token).

## Develop

```bash
npm install
npm test          # local protocol smoke tests, no network needed
vercel deploy     # preview
vercel deploy --prod
```

Smoke-test a deployment:

```bash
curl -s https://<domain>/mcp/<secret> -X POST -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```