Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
cache: npm

- run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/markdown-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'

- name: Install dependencies
run: npm ci
Expand Down
61 changes: 61 additions & 0 deletions .github/workflows/render-seps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Render SEPs

on:
push:
branches:
- main
paths:
- "seps/**/*.md"
- "scripts/render-seps.ts"

pull_request:
paths:
- "seps/**/*.md"
- "scripts/render-seps.ts"

# Allow manual trigger
workflow_dispatch:

permissions:
contents: write

jobs:
render-seps:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm

- run: npm ci

- name: Render SEPs
run: npm run generate:seps

- name: Check for changes
id: changes
run: |
if [[ -n "$(git status --porcelain docs/community/seps/ docs/snippets/badge.mdx docs/docs.json)" ]]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
else
echo "has_changes=false" >> $GITHUB_OUTPUT
fi

# On push to main, commit any changes
- name: Commit changes
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.changes.outputs.has_changes == 'true'
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add docs/community/seps/ docs/snippets/badge.mdx docs/docs.json
git commit -m "docs: auto-render SEPs documentation"
git push

# On PR, verify docs are up to date
- name: Verify SEPs are up to date
if: github.event_name == 'pull_request'
run: npm run check:seps
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20.18.1
v24.2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: "SEP-1046: Support OAuth client credentials flow in authorization"
sidebarTitle: "SEP-1046: Support OAuth client credentials flow i…"
description: "Support OAuth client credentials flow in authorization"
---

import { Badge } from "/snippets/badge.mdx";

<div className="flex items-center gap-2 mb-4">
<Badge color="green">Final</Badge>
<Badge color="gray">Standards Track</Badge>
</div>

| Field | Value |
| ------------- | ------------------------------------------------------------------------ |
| **SEP** | 1046 |
| **Title** | Support OAuth client credentials flow in authorization |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2025-07-23 |
| **Author(s)** | Darin McAdams ([@D-McAdams](https://github.com/D-McAdams) ) |
| **Sponsor** | None |
| **PR** | [#1046](https://github.com/modelcontextprotocol/specification/pull/1046) |

---

## Abstract

Recommends adding the OAuth client credentials flow to the authorization spec to enable machine-to-machine scenarios.

### Motivation

The original authorization spec mentioned the client credentials flow, but it was dropped in subsequent revisions. Therefore, the spec is currently silent on how to solve machine-to-machine scenarios where an end-user is unavailable for interactive authorization.

### Specification

The authorization spec would be amended to list the OAuth client credentials flow as being allowed. Adhering to the patterns established by OAuth 2.1, the specification would RECOMMEND the use of asymmetric methods defined in RFC 753 (JWT Assertions), but also allow client secrets.

As guidance to implementors, the spec overview would also be updated to describe the different flows and when each is applicable. In addition, to address a common question, the spec would be updated to indicate that implementors may implement other authorization scenarios beyond what's defined; emphasizing that the specification defines the baseline requirements.

### Rationale

To maximize interoperability (and minimize SDK complexity), this change would intentionally constrain the client credentials flow to two options:

1. JWT Assertions as per RFC 7523 (RECOMMENDED)
2. Client Secrets via HTTP Basic authentication (Allowed for maximum compatibility with existing systems)

Other options, such as mTLS, are not included.

While the spec encourages the use of RFC 7523 (JWT Assertions), it does not yet specify how to populate the JWT contents nor how to discover the client's JWKS URI to validate the JWT. In future iterations of the spec, it will be beneficial to do so. However, this was currently left unspecified pending maturity of other RFCs that can define these profiles. The other RFCs include [WIMSE Headless JWT Authentication](https://www.ietf.org/archive/id/draft-levy-wimse-headless-jwt-authentication-01.html) (for specifying JWT contents) and [Client ID Metadata](https://datatracker.ietf.org/doc/draft-parecki-oauth-client-id-metadata-document/) (for specifying the JWKS URI). This revision intentionally leaves extensibility for these future profiles. As a practical matter, this means implementers needing to ship solutions ASAP will most likely use client secrets which are widely supported today, whereas the JWT Assertion pattern represents the longer-term direction.

### Backward Compatibility

This change is fully backward compatible. It introduces a new authorization flow, but does not alter the existing flows.

### Security Implications

The specification refers to the existing OAuth security guidance.
Loading