Update root README: document the MCP server, transports, and Docker hosting

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ang3l12
2026-06-16 14:23:27 -06:00
parent 540a49d94c
commit 6704122599

196
README.md
View File

@@ -1,39 +1,187 @@
# Claude-SharepointLists
A [Claude Code](https://claude.com/claude-code) skill for connecting to
**Microsoft SharePoint Lists** via the Microsoft Graph API, with full read/write
(CRUD) over list items using **app-only (client-credentials)** authentication.
Connect Claude to **Microsoft SharePoint Lists** via the Microsoft Graph API, with
full read/write (CRUD) over list items using **app-only (client-credentials)**
authentication.
## What's here
The repo ships the same capability in two forms, sharing one core Graph client
([`graph.mjs`](.claude/skills/sharepoint-lists/scripts/lib/graph.mjs)):
| Form | Best for | Entry point |
|---|---|---|
| **Skill** | Claude Code on your own machine | `.claude/skills/sharepoint-lists/` |
| **MCP server** | Claude Desktop, or self-hosted in Docker | `mcp-server/` |
## Repo layout
```
.claude/skills/sharepoint-lists/
├── SKILL.md # how the skill works + usage
├── .env.example # credential template (copy to .env; .env is git-ignored)
├── scripts/
│ ├── sp.mjs # CLI: test | lists | columns | items | get | create | update | delete
└── lib/graph.mjs # reusable, dependency-free Graph client (SharePointListsClient)
└── references/
── setup.md # Azure AD (Entra) app registration walkthrough
└── graph-api.md # field-type formats + OData query reference
.
├── .claude/skills/sharepoint-lists/ # the skill (Claude Code)
│ ├── SKILL.md # how the skill works + usage
│ ├── .env.example # credential template (.env is git-ignored)
│ ├── scripts/
│ ├── sp.mjs # CLI: test|lists|columns|items|get|create|update|delete
│ │ └── lib/graph.mjs # shared, dependency-free Graph client (single source of truth)
── references/
├── setup.md # Azure AD (Entra) app registration walkthrough
│ └── graph-api.md # field-type formats + OData query reference
├── mcp-server/ # the MCP server (imports the same graph.mjs)
│ ├── index.mjs # stdio + Streamable HTTP transports
│ ├── Dockerfile
│ ├── .env.example
│ └── README.md # full MCP server + hosting docs
├── docker-compose.yml # run the MCP server as a container
└── .mcp.json # registers the server for Claude Code
```
## Quick start
## Prerequisites (one-time)
1. Create an Entra app registration and grant it a SharePoint Graph permission
(`Sites.Selected` preferred). See
[`references/setup.md`](.claude/skills/sharepoint-lists/references/setup.md).
2. Copy `.env.example` to `.env` and fill in `SP_TENANT_ID`, `SP_CLIENT_ID`,
`SP_CLIENT_SECRET` (optionally `SP_SITE_URL`).
3. Verify connectivity:
An Entra (Azure AD) **app registration** with an *application* Graph permission
(`Sites.Selected` preferred over `Sites.ReadWrite.All`) and admin consent. The
full walkthrough is in
[`references/setup.md`](.claude/skills/sharepoint-lists/references/setup.md). You
end up with three secrets: `SP_TENANT_ID`, `SP_CLIENT_ID`, `SP_CLIENT_SECRET`.
Credentials live only in git-ignored `.env` files — **never commit secrets.**
---
## Option A — the skill (Claude Code)
```bash
cp .claude/skills/sharepoint-lists/.env.example .claude/skills/sharepoint-lists/.env
# fill in SP_TENANT_ID / SP_CLIENT_ID / SP_CLIENT_SECRET (optionally SP_SITE_URL)
cd .claude/skills/sharepoint-lists/scripts
node sp.mjs test --site "https://<tenant>.sharepoint.com/sites/<SiteName>"
node sp.mjs items --site "<SITE_URL>" --list "Projects" --filter "fields/Status eq 'Open'"
```
## Security
See [SKILL.md](.claude/skills/sharepoint-lists/SKILL.md) for the full command set.
Credentials live only in `.env`, which is git-ignored — **never commit secrets**.
The Graph + auth logic is isolated in `scripts/lib/graph.mjs` so it can later be
wrapped as a standalone MCP server without a rewrite.
---
## Option B — the MCP server
Exposes the Lists as MCP tools. The Graph/auth logic is the same `graph.mjs` the
skill uses, so there is one source of truth.
### Tools
| Tool | Access | Purpose |
|---|---|---|
| `sharepoint_test` | read | Verify credentials; with a site, list its lists |
| `sharepoint_list_lists` | read | Enumerate lists in a site |
| `sharepoint_get_columns` | read | Column internal names + types (call before writing) |
| `sharepoint_list_items` | read | Query items (filter/select/orderby/top/all) |
| `sharepoint_get_item` | read | Get one item by id |
| `sharepoint_create_item` | write | Create an item |
| `sharepoint_update_item` | write | Update an item (partial) |
| `sharepoint_delete_item` | write | Delete an item (irreversible) |
Set `SP_READONLY=true` to register only the read tools.
### Transports
| Transport | Use | How the client connects |
|---|---|---|
| **stdio** (default) | client and server on the same machine | the app launches `node index.mjs` |
| **Streamable HTTP** (`--http`) | server hosted elsewhere (e.g. Docker) | client → `POST /mcp` with a bearer token |
stdio can't cross machines (the client launches the server as a child process), so
a containerized/remote deployment **must** use the HTTP transport.
### Environment
| Var | Required | Notes |
|---|---|---|
| `SP_TENANT_ID` / `SP_CLIENT_ID` / `SP_CLIENT_SECRET` | yes | from the app registration |
| `SP_SITE_URL` | no | default site so tools can omit the `site` argument |
| `SP_READONLY` | no | `true` → read-only tool set |
| `MCP_AUTH_TOKEN` | HTTP only | shared bearer token required on `/mcp`; empty = unauthenticated |
| `PORT` | HTTP only | listen port (default 3838) |
### Run locally
```bash
cd mcp-server
npm install
cp .env.example .env # fill in credentials
npm start # stdio
npm run start:http # Streamable HTTP on :3838
```
### Host it in Docker (Compose)
Run from the **repo root** (the build context needs the shared `graph.mjs`):
```bash
# 1) create mcp-server/.env with SP_* creds + a strong token:
echo "MCP_AUTH_TOKEN=$(openssl rand -hex 32)" >> mcp-server/.env
# 2) build + start:
docker compose up -d --build
# 3) check:
curl -s http://localhost:3838/health # -> {"ok":true,...}
```
The service has `restart: unless-stopped` and a healthcheck. The port publishes on
all host interfaces; restrict it to a LAN IP in `docker-compose.yml` (or via
firewall) if desired — the bearer token guards `/mcp` regardless. `/health` is
intentionally open (liveness only, returns no data).
Full hosting details: [mcp-server/README.md](mcp-server/README.md).
### Connect a client
**Claude Code** — the repo-root [`.mcp.json`](.mcp.json) registers the local stdio
server automatically.
**Claude Desktop → local stdio** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"sharepoint-lists": {
"command": "/opt/homebrew/bin/node",
"args": ["/absolute/path/to/Claude-SharepointLists/mcp-server/index.mjs"]
}
}
}
```
**Claude Desktop → remote container** (bridges local stdio to the HTTP server with
[`mcp-remote`](https://www.npmjs.com/package/mcp-remote)):
```json
{
"mcpServers": {
"sharepoint-lists": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"http://<host>:3838/mcp",
"--allow-http",
"--header", "Authorization: Bearer ${SP_MCP_TOKEN}"
],
"env": { "SP_MCP_TOKEN": "<your MCP_AUTH_TOKEN>" }
}
}
}
```
`--allow-http` permits a plain-HTTP LAN URL; the token must match the container's
`MCP_AUTH_TOKEN`. Fully quit and reopen Claude Desktop after editing the config.
---
## Security notes
- **App-only auth has no per-user check** — the server acts as the app and can
reach every granted SharePoint site. Anyone who can call an unauthenticated
`/mcp` gets that access, so always set `MCP_AUTH_TOKEN` for the HTTP transport
and keep the endpoint on a trusted network (this is not meant for public web
chat).
- Secrets (`SP_CLIENT_SECRET`, `MCP_AUTH_TOKEN`) live only in git-ignored `.env`
files and are never baked into the Docker image.
- Field formats for writes (person/lookup/choice/date) are documented in
[`references/graph-api.md`](.claude/skills/sharepoint-lists/references/graph-api.md).