Add person resolver: email → LookupId for writing person columns
Person/group columns store a numeric LookupId into each site's hidden User Information List, and SPO's ensureUser needs certificate auth that client secrets can't provide — so resolve by querying the hidden list directly via Graph (item id IS the LookupId). New resolvePersonByEmail() in graph.mjs (server-side EMail/UserName filter with a paged case-insensitive scan fallback), a 'person' CLI command, and a sharepoint_resolve_person MCP tool (9 tools now). Verified live against known ground truth (LookupIds 53 and 136) plus the not-found path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ on a different machine.
|
||||
| `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_resolve_person` | read | Email → the LookupId person columns store (for writes) |
|
||||
| `sharepoint_create_item` | write | Create an item |
|
||||
| `sharepoint_update_item` | write | Update an item (partial) |
|
||||
| `sharepoint_delete_item` | write | Delete an item (irreversible) |
|
||||
|
||||
@@ -196,6 +196,27 @@ function buildServer() {
|
||||
},
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
"sharepoint_resolve_person",
|
||||
{
|
||||
title: "Resolve a person to their LookupId",
|
||||
description:
|
||||
"Look up the numeric LookupId a person/group column stores, by email. Use the result when writing person fields, e.g. fields {\"ProjectManagerLookupId\": 53}. Only finds people who have accessed the site before; if not found, grant them site access first and retry.",
|
||||
inputSchema: {
|
||||
site: SITE,
|
||||
email: z.string().describe("The person's email address (case-insensitive)."),
|
||||
},
|
||||
annotations: { readOnlyHint: true },
|
||||
},
|
||||
async ({ site, email }) => {
|
||||
try {
|
||||
return ok(await client.resolvePersonByEmail(await siteId(site), email));
|
||||
} catch (e) {
|
||||
return fail(e);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (!READONLY) {
|
||||
const FIELDS = z
|
||||
.record(z.any())
|
||||
|
||||
Reference in New Issue
Block a user