Skip to content
Merged
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
62 changes: 62 additions & 0 deletions docs/webmcp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* WebMCP tool for agents running in the visitor's browser
* (https://webmachinelearning.github.io/webmcp/).
*
* Mintlify already registers search_docs, read_page, navigate_page,
* get_site_overview, and read_skill on every docs page. This adds the one
* thing those don't cover: how to connect to the Terminal49 MCP server.
* The tool name must not collide with Mintlify's, or registration fails.
*
* Mintlify loads every .js file in docs/ on every page, so this is plain
* browser JavaScript with no build step.
*/
(function () {
var MCP_URL = 'https://mcp.terminal49.com';

// Older Chrome builds expose the API on navigator instead of document.
var modelContext = document.modelContext || navigator.modelContext;
if (!modelContext || typeof modelContext.registerTool !== 'function') return;

// Top-level page only, once: Mintlify navigates client-side and may run
// custom scripts again, and embedded frames would register a duplicate.
if (window.top !== window || window.__t49WebMcpRegistered) return;
window.__t49WebMcpRegistered = true;

var tool = {
name: 'get_terminal49_mcp_connection',
title: 'Get Terminal49 MCP server connection details',
description:
'Get the URL, transport, and sign-in details for the Terminal49 MCP server, plus setup guides for Claude, ChatGPT, Cursor, VS Code, and other MCP clients. Use this to connect an agent to a Terminal49 account to search, track, and monitor shipments.',
inputSchema: { type: 'object', properties: {} },
annotations: { readOnlyHint: true },
execute: function () {
var docs = window.location.origin + '/docs/mcp';
return Promise.resolve({
url: MCP_URL,
transport: 'streamable-http',
authentication:
'OAuth 2.1 through auth.terminal49.com, discovered from the protected resource metadata; or send a Terminal49 API key as "Authorization: Token YOUR_API_KEY".',
protected_resource_metadata: MCP_URL + '/.well-known/oauth-protected-resource',
docs: docs + '/home',
setup_guides: {
claude: docs + '/setup/claude',
claude_code: docs + '/setup/claude-code',
chatgpt: docs + '/setup/chatgpt',
cursor: docs + '/setup/cursor',
vs_code: docs + '/setup/vs-code',
microsoft_copilot: docs + '/setup/microsoft-copilot',
other_clients: docs + '/setup/other-clients',
},
});
},
};

// The executor catches a synchronous throw (e.g. InvalidStateError) as well
// as a rejection, so a failed attempt always clears the flag for a retry.
new Promise(function (resolve) {
resolve(modelContext.registerTool(tool));
}).catch(function (error) {
window.__t49WebMcpRegistered = false;
if (window.console && console.warn) console.warn('WebMCP: could not register tool', error);
});
})();
7 changes: 4 additions & 3 deletions packages/mcp/WORKOS_MCP_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ In the WorkOS environment referenced by `WORKOS_AUTHORIZATION_SERVER_URL`:
| `T49_MCP_AUTHKIT_ENABLED` | `true` | Otherwise a WorkOS `Bearer` token is treated as a passthrough API key and fails |
| `T49_CONNECTED_CLIENTS_RESOLVE_SECRET` | the resolve shared secret | Required to call `/connected-clients/resolve` |
| `T49_MCP_ALLOWED_HOSTS` | include `mcp.terminal49.com` (if set at all) | Host allowlist; missing host → 403 |
| `T49_MCP_SCOPES_SUPPORTED` | **leave unset** | WorkOS only issues `openid/profile/email/offline_access`; advertising `mcp:tools` etc. causes `invalid_scope` |
| `T49_MCP_SCOPES_SUPPORTED` | `openid,profile,email,offline_access` | Advertised as `scopes_supported` in the PRM document. Must match what WorkOS issues (the AS metadata's `scopes_supported`); advertising scopes it doesn't issue, such as `mcp:tools`, causes `invalid_scope` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not advertise offline_access as a resource scope

When production is configured with this value, the Protected Resource Metadata makes clients treat offline_access as required for basic MCP access. The MCP 2026-07-28 authorization specification explicitly says protected resources SHOULD NOT include offline_access in scopes_supported, because clients that want refresh tokens add it independently after finding it in the authorization-server metadata; remove it from this PRM value and the smoke assertion. MCP authorization specification

AGENTS.md reference: AGENTS.md:L76-L79

Useful? React with 👍 / 👎.

| `POSTHOG_PROJECT_API_KEY` | the PostHog project API key | Enables MCP tool-usage analytics. **Leave unset and the integration is inert** — no client, no network call |
| `POSTHOG_HOST` | optional; defaults to `https://f.terminal49.com` | First-party ingestion proxy, same host the docs site uses (`docs/docs.json`) |
| `POSTHOG_ENABLED` | optional; defaults to `true` | Set `false` to kill-switch analytics without removing the key |
Expand Down Expand Up @@ -83,8 +83,9 @@ curl --fail --silent --show-error -X POST "$ISSUER/oauth2/register" \
-d '{"client_name":"smoke","redirect_uris":["https://example.com/cb"],"grant_types":["authorization_code","refresh_token"],"response_types":["code"],"token_endpoint_auth_method":"none"}' \
| jq --exit-status '.client_id != null' > /dev/null

# PRM: resource + authorization_servers
curl -s https://mcp.terminal49.com/.well-known/oauth-protected-resource | jq
# PRM: resource, authorization_servers, and the WorkOS scopes
curl -s https://mcp.terminal49.com/.well-known/oauth-protected-resource \
| jq --exit-status '.scopes_supported == ["openid","profile","email","offline_access"]'

# 401 challenge points at the PRM (must be POST — a GET to /mcp returns 405)
curl -si -X POST https://mcp.terminal49.com/mcp \
Expand Down
Loading