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:
196
README.md
196
README.md
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user