During LTI 1.3 launch, inspect the https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice claim in the decoded JWT; extract the context_memberships_url and the versions array.
Request a service-scoped access token from the platform's OAuth 2.0 token endpoint using the scope https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly and your tool's signed JWT assertion.
GET the context_memberships_url with Accept: application/vnd.ims.lti-nrps.v2.membershipcontainer+json; the response body contains a members array with id, name, roles, and optional message payload.
Page through results using the Link: <url>; rel='next' response header until no next link is present; do not assume all members fit in a single response.
Store membership keyed on the sub claim (platform-specific anonymized user ID) rather than name or email; use the sub to correlate with AGS score submissions.
Use the If-None-Match / ETag pattern on subsequent polling calls to receive a 304 Not Modified when membership has not changed, reducing unnecessary processing.
Known gotchas
Some platforms cap NRPS membership responses at a fixed member count (e.g., 1000) regardless of pagination headers; if your course is larger, the membership list will be silently truncated.
The service token scope for NRPS is different from the AGS scope; a token obtained for grade passback cannot be reused for membership calls — request separate tokens per service.
Platform-generated user sub values are pairwise-pseudonymous per tool deployment; the same learner in two different tool deployments will have different sub values, so do not join membership lists across deployments using sub alone.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp