From 2f82ab5f6b4ede93fb16e4da69cb0b89318323f3 Mon Sep 17 00:00:00 2001 From: Mark Kats Date: Mon, 24 Aug 2026 19:17:52 +0300 Subject: [PATCH] docs: document ChatGPT MCP OAuth --- CHATGPT-SETUP.md | 20 +++++++++++++---- README.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++-- RELEASE.md | 29 ++++++++++++++++++++----- 3 files changed, 94 insertions(+), 11 deletions(-) diff --git a/CHATGPT-SETUP.md b/CHATGPT-SETUP.md index b9412ad..9f45d08 100644 --- a/CHATGPT-SETUP.md +++ b/CHATGPT-SETUP.md @@ -14,13 +14,25 @@ app inside another person’s 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. diff --git a/README.md b/README.md index 2dbb53c..18ddf82 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/RELEASE.md b/RELEASE.md index 6bd0eca..0fba466 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -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//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 widget’s + 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.