Files
Claude-SharepointLists/.claude/skills/sharepoint-lists/SKILL.md
ang3l12 fd957177b9 Initial import: SharePoint Lists skill
Claude Code skill for SharePoint Lists CRUD via Microsoft Graph (app-only auth): reusable graph.mjs client, sp.mjs CLI, and setup + API reference docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 11:12:50 -06:00

156 lines
6.3 KiB
Markdown

---
name: sharepoint-lists
description: >-
Read and write Microsoft SharePoint Lists via the Microsoft Graph API using
app-only (client-credentials) authentication. Use this skill whenever the user
wants to query, search, list, create, add, update, edit, or delete items in a
SharePoint List, inspect a list's columns, or enumerate the lists in a
SharePoint site — even if they just refer to "our SharePoint", "the list",
"the tracker", or a specific list/site name rather than saying "SharePoint
List" explicitly. Also use it for bulk operations over list items (export,
reporting, batch updates) and for connectivity/credential troubleshooting
against SharePoint. This is for SharePoint *Lists* (structured rows/columns),
not document libraries or files — for documents use the SharePoint search
connector instead.
---
# SharePoint Lists
Connect to Microsoft SharePoint Lists and perform full CRUD (create, read,
update, delete) on list items through the Microsoft Graph API. Authentication is
**app-only** (OAuth2 client credentials) — no interactive login.
All operations go through one CLI, `scripts/sp.mjs`, which wraps the reusable
core client in `scripts/lib/graph.mjs`. Run it with Node (already available):
```bash
node scripts/sp.mjs <command> [flags]
```
> Paths above are relative to this skill's directory. From elsewhere, use the
> absolute path, e.g. `node "<skill-dir>/scripts/sp.mjs" ...`.
## Prerequisites (one-time)
The skill needs three credentials from an Azure AD (Entra) **app registration**
with an *application* permission for SharePoint and admin consent granted:
- `SP_TENANT_ID` — Directory (tenant) ID
- `SP_CLIENT_ID` — Application (client) ID
- `SP_CLIENT_SECRET` — a client secret value
Set them as environment variables, or copy `.env.example` to `.env` in this
skill's directory and fill it in (the CLI loads `.env` automatically; `.env` is
git-ignored). Optionally set `SP_SITE_URL` to a default site so `--site` can be
omitted.
**If credentials are not yet set up**, do not guess — point the user to
[references/setup.md](references/setup.md), which is a step-by-step walkthrough
of creating the app registration, choosing least-privilege permissions
(`Sites.Selected` is strongly preferred over `Sites.ReadWrite.All`), and granting
consent. Then come back and run `test`.
## First step in any task: verify connectivity
Before doing real work, confirm auth works. This fails fast with a clear message
if credentials or permissions are wrong:
```bash
node scripts/sp.mjs test --site "https://contoso.sharepoint.com/sites/Marketing"
```
A successful response includes the resolved site id and the names of the lists
in that site.
## Identifying a site and a list
- **Site** is given by URL: `https://{tenant}.sharepoint.com/sites/{SiteName}`.
The client resolves it to a Graph site id for you. A bare hostname means the
root site.
- **List** can be given by display name (e.g. `"Project Tracker"`), internal
name, or GUID — the client resolves names to ids and, on a typo, lists the
available names so you can correct it.
When unsure what lists or columns exist, discover first rather than guessing:
```bash
node scripts/sp.mjs lists --site "<SITE_URL>"
node scripts/sp.mjs columns --site "<SITE_URL>" --list "Project Tracker"
```
`columns` is important before writing: SharePoint **internal** column names
often differ from their display names (a column shown as "Due Date" may be
`DueDate` or even `OData__x0044_ue...`). Always write to internal names. See
[references/graph-api.md](references/graph-api.md) for field-type formats
(person, lookup, choice, date, etc.) and OData query details.
## Reading items
```bash
# Everything (follows pagination):
node scripts/sp.mjs items --site "<SITE_URL>" --list "Project Tracker" --all
# Filtered + sorted + projected:
node scripts/sp.mjs items --site "<SITE_URL>" --list "Project Tracker" \
--filter "fields/Status eq 'Open'" \
--select "Title,Status,AssignedTo" \
--orderby "fields/DueDate asc" --top 50
# One item by id:
node scripts/sp.mjs get --site "<SITE_URL>" --list "Project Tracker" --id 42
```
Items come back simplified as `{ id, webUrl, createdDateTime, lastModifiedDateTime, fields }`.
## Writing items
`--fields` takes a JSON object of internal column name → value. It also accepts
`@file.json` or `-` (read JSON from stdin), which is cleaner for large or
quote-heavy payloads.
```bash
# Create
node scripts/sp.mjs create --site "<SITE_URL>" --list "Project Tracker" \
--fields '{"Title":"Migrate database","Status":"Open","Priority":2}'
# Update (partial — only the fields you pass change)
node scripts/sp.mjs update --site "<SITE_URL>" --list "Project Tracker" \
--id 42 --fields '{"Status":"Done"}'
# Delete
node scripts/sp.mjs delete --site "<SITE_URL>" --list "Project Tracker" --id 42
```
**Deletes are irreversible (items go to the site Recycle Bin). Confirm the item
id with the user before deleting**, and prefer showing them the item via `get`
first. For bulk deletes, confirm the full set once, then proceed.
## Bulk operations
For exports or batch edits, fetch with `--all`, transform the JSON however the
task needs (jq, a quick script), then loop the relevant `create`/`update`/
`delete` calls. Keep concurrency modest — Graph throttles with HTTP 429; the
client already retries with backoff, but don't fan out hundreds of parallel
writes.
## Handling errors
The CLI prints a JSON error to stderr and exits non-zero. Common cases:
- `401` / token failure → bad client id/secret or tenant; re-check `.env`.
- `403` (`accessDenied`) → the app lacks permission on this site. With
`Sites.Selected`, the site must be explicitly granted to the app — see
[references/setup.md](references/setup.md).
- `404` on a list → wrong name; run `lists` to see valid names.
- `400` on write → usually a wrong internal field name or value format; run
`columns` and check [references/graph-api.md](references/graph-api.md).
## Extending to an MCP server
The core logic is isolated in `scripts/lib/graph.mjs` (the
`SharePointListsClient` class, zero dependencies). To graduate this into a
standalone MCP server later, import that class and expose its methods
(`listItems`, `getItem`, `createItem`, `updateItem`, `deleteItem`, etc.) as MCP
tools — no rewrite of the Graph logic needed. See the note at the bottom of
[references/setup.md](references/setup.md).