docs: document ChatGPT MCP OAuth
Validate SHD MCP plugin / validate (push) Has been cancelled

This commit is contained in:
2026-08-24 19:17:52 +03:00
parent 08cf3672a4
commit 2f82ab5f6b
3 changed files with 94 additions and 11 deletions
+16 -4
View File
@@ -14,13 +14,25 @@ app inside another persons ChatGPT account and never stores OAuth tokens.
4. Start a new chat or refresh the app connection.
5. Test with: `Покажи активные проекты с датой завершения и статусом.`
The server publishes OAuth 2.1 discovery for the root resource and supports
ChatGPT Client ID Metadata Documents (CIMD), PKCE S256 and the
`private_key_jwt` token-endpoint authentication method. Keep the app URL as
`https://shd.xyz.su/mcp`; the retired `/mcp/system-data` resource is not a
valid replacement for the root MCP resource.
The expected flow is:
1. ChatGPT calls `shd_list_projects` with `archived: false`.
2. ChatGPT may call `shd_render_projects_widget` with the returned project
array.
3. The widget renders the sorted register and can call `shd_get_project` for
a selected row.
2. ChatGPT may call a module render tool after the corresponding list tool:
`shd_render_projects_widget`, `shd_render_documents_widget`,
`shd_render_tasks_widget`, `shd_render_finance_widget` or
`shd_render_crm_widget`.
3. The selected widget renders a read-only register and can call the matching
detail tool for one selected row.
The widget resources are versioned at `ui://shd/active-projects/v1.html`,
`ui://shd/documents/v1.html`, `ui://shd/tasks/v1.html`,
`ui://shd/finance/v1.html` and `ui://shd/crm/v1.html`.
The MCP tools remain usable without the widget. A failed OAuth connection is
an account/endpoint configuration problem, not a missing token in this repo.
+54 -2
View File
@@ -35,7 +35,7 @@ codex plugin add shd-mcp-plugin@shd-public
The same commands work with the Gitea clone URL:
```bash
git clone https://git.xyz.su/shd/shd-mcp-plugin.git
git clone https://git.xyz.su/markkats/shd-mcp-plugin.git
```
After installation, start a new Codex thread so the plugin Skills are loaded.
@@ -62,6 +62,18 @@ The backend serves the checked-in widget artifact at
`ui://shd/active-projects/v1.html`; its manifest and `SHA256SUMS` are kept next
to the HTML resource under `plugins/shd-mcp-plugin/widgets/active-projects/v1/`.
The same read-only data/render contract is available for Documents, Tasks,
Finance and CRM:
- `shd_render_documents_widget``ui://shd/documents/v1.html`;
- `shd_render_tasks_widget``ui://shd/tasks/v1.html`;
- `shd_render_finance_widget``ui://shd/finance/v1.html`;
- `shd_render_crm_widget``ui://shd/crm/v1.html`.
Each widget accepts normalized records from its list tool, keeps the plain
structured response as a fallback and uses the MCP Apps bridge before the
`window.openai` compatibility API.
The official OpenAI directory is optional. It is useful for public discovery,
one-click installation and review of a public app; it is not required for an
internal team or a manually added ChatGPT custom app. See the official
@@ -85,6 +97,11 @@ token may be used only if the selected MCP client and SHD deployment
explicitly support it; enter it in that client's secure connection settings,
never in `.mcp.json`, Skills or an issue.
SHD OAuth supports ChatGPT CIMD clients with PKCE S256 and
`private_key_jwt` client authentication. The server validates the client
assertion against ChatGPT's published JWKS; the plugin package never stores
the assertion, access token or refresh token.
For ChatGPT or another MCP client without Codex plugin installation, add the
same HTTPS endpoint as a custom MCP app and complete OAuth there. The public
repository packages the workflows; it does not grant access to the server.
@@ -109,9 +126,44 @@ From the repository root:
```bash
python3 -m unittest discover -s tests -v
sha256sum --check plugins/shd-mcp-plugin/widgets/active-projects/v1/SHA256SUMS
python3 scripts/check_skill_mcp_parity.py --strict
for checksum in plugins/shd-mcp-plugin/widgets/*/v1/SHA256SUMS; do
(cd "$(dirname "$checksum")" && sha256sum --check SHA256SUMS)
done
```
Refresh the catalog snapshot after a backend MCP catalog change:
```bash
node /var/www/admin/scripts/mcp/mcp-catalog.mjs | \
python3 scripts/update_mcp_tool_catalog.py
```
The runtime smoke harness checks OAuth metadata, PKCE S256 support, the
authenticated MCP handshake and all five widget resources. It never assumes
an endpoint or prints a token:
```bash
SHD_MCP_RUNTIME_URL=https://approved-host.example/mcp \
SHD_MCP_ACCESS_TOKEN="$TOKEN" \
node scripts/mcp-runtime-smoke.mjs --require-auth
```
For a full authorization-code/PKCE browser check, provide an already
authenticated Playwright storage state and the client redirect registered with
SHD:
```bash
SHD_MCP_RUNTIME_URL=https://approved-host.example/mcp \
SHD_OAUTH_E2E_STORAGE_STATE=/secure/oauth-state.json \
SHD_OAUTH_E2E_CLIENT_ID="$OAUTH_CLIENT_ID" \
SHD_OAUTH_E2E_REDIRECT_URI="$OAUTH_REDIRECT_URI" \
node scripts/mcp-oauth-e2e.mjs
```
The browser/OAuth checks are opt-in deployment checks and are not run in the
public static-package workflow.
The full release boundary, including backend deployment and authenticated
ChatGPT/browser checks, is documented in [RELEASE.md](RELEASE.md).
+24 -5
View File
@@ -9,7 +9,10 @@ Run from the repository root:
```bash
python3 -m unittest discover -s tests -v
sha256sum --check plugins/shd-mcp-plugin/widgets/active-projects/v1/SHA256SUMS
python3 scripts/check_skill_mcp_parity.py --strict
for checksum in plugins/shd-mcp-plugin/widgets/*/v1/SHA256SUMS; do
(cd "$(dirname "$checksum")" && sha256sum --check SHA256SUMS)
done
```
The Codex plugin validator is an additional environment check when available:
@@ -21,12 +24,27 @@ python3 /home/vscode/.codex/skills/.system/plugin-creator/scripts/validate_plugi
## Widget changes
The URI `ui://shd/active-projects/v1.html` is a cache key. For a breaking HTML,
Every `ui://shd/<module>/v1.html` URI is a cache key. For a breaking HTML,
JavaScript or CSS change, create `v2/`, update the manifest and backend resource
registration together, then regenerate `SHA256SUMS`. Keep the widget useful
registration together, then regenerate `SHA256SUMS`. Keep each widget useful
without ChatGPT-specific APIs: the MCP Apps bridge is the baseline and
`window.openai` is only a compatibility extension.
The public package also contains a one-way Skill-to-catalog parity check. The
catalog is a checked-in name snapshot, so a Skill cannot silently reference an
unpublished MCP tool. Refresh it from the backend catalog before publishing.
`scripts/mcp-runtime-smoke.mjs` checks OAuth metadata, authenticated MCP
negotiation and the active-projects/Documents/Tasks/Finance/CRM resources.
`scripts/mcp-oauth-e2e.mjs` is an opt-in Playwright check for the complete
authorization-code + PKCE exchange using an already authenticated storage
state. Neither script stores credentials or belongs in the static CI job.
The OAuth server metadata must advertise the token-endpoint methods used by the
ChatGPT CIMD document (`none` and `private_key_jwt`). Before a release, verify
that the server accepts the ChatGPT `RS256` client assertion, validates its
JWKS signature and rejects a repeated `jti`.
## Publish and deploy gates
1. Commit and push the same reviewed revision to the GitHub and Gitea mirrors.
@@ -34,8 +52,9 @@ without ChatGPT-specific APIs: the MCP Apps bridge is the baseline and
used by `SHD_MCP_WIDGET_ROOT`, or at the repository path documented by the
backend loader.
3. Run the backend MCP verification and a real authenticated OAuth/tool call.
4. Reconnect the custom ChatGPT app and test the active-projects flow, including
the plain structured fallback and widget actions.
4. Reconnect the custom ChatGPT app and test active projects, Documents, Tasks,
Finance and CRM, including the plain structured fallback and each widgets
refresh/detail action.
5. Record the exact revision and any runtime/browser checks. Static tests do
not prove OAuth, ACLs, production hosting or ChatGPT rendering.