From 58a64d6ceedcb46c646bdd6f9adf2e195d6183df Mon Sep 17 00:00:00 2001 From: Gabriel Brown Date: Wed, 23 Sep 2026 08:48:12 -0400 Subject: [PATCH] Register Penpot's MCP server, whose token rides in the URL Penpot's MCP server reads the user key only from the userToken query parameter, never a header. link-mcp now substitutes a {TOKEN} placeholder in a server's URL instead of sending the Authorization header, and the servers list gains a penpot row that uses it. --- setup/scripts/link-mcp | 9 ++++++++- user/agents/mcp/servers | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/setup/scripts/link-mcp b/setup/scripts/link-mcp index dfc1da6..7084048 100755 --- a/setup/scripts/link-mcp +++ b/setup/scripts/link-mcp @@ -69,6 +69,9 @@ while read -r name transport url token_var _rest; do continue fi + # The token normally travels as an Authorization header. A server that only + # reads it from the query string (Penpot's userToken) marks the spot with + # {TOKEN} in its URL instead, and gets no header. header=() if [[ -n "${token_var:-}" ]]; then token="${!token_var:-}" @@ -77,7 +80,11 @@ while read -r name transport url token_var _rest; do skipped=$((skipped + 1)) continue fi - header=(-H "Authorization: $token") + if [[ "$url" == *'{TOKEN}'* ]]; then + url="${url//\{TOKEN\}/$token}" + else + header=(-H "Authorization: $token") + fi fi # Re-registering is how this stays idempotent across upgrades, and how a diff --git a/user/agents/mcp/servers b/user/agents/mcp/servers index 15fe596..169ee52 100644 --- a/user/agents/mcp/servers +++ b/user/agents/mcp/servers @@ -6,7 +6,8 @@ # git. This file carries no secret, so it is tracked like the rest of user/ and # a new machine gets the same servers by dropping its own env file beside it. # -# A row with no token variable registers without an Authorization header. +# A row with no token variable registers without an Authorization header. A URL +# containing {TOKEN} gets the token substituted there instead of as a header. # # Lines beginning with # are comments and blank lines are ignored. @@ -23,3 +24,8 @@ bill-tracker http https://mcp.billtracker.gbrown.org/mcp # Atlassian's hosted MCP server for Jira and Confluence. No token: it is an # OAuth server and Claude Code signs in through /mcp on first use. atlassian http https://mcp.atlassian.com/v1/mcp + +# Penpot's MCP server on the VPS (penpot.gbrown.org). The key is a per-user MCP +# key from Penpot's Account > Integrations, and Penpot only reads it from the +# query string, hence {TOKEN}. The same key connects the in-file MCP plugin. +penpot http https://penpot.gbrown.org/mcp/stream?userToken={TOKEN} PENPOT_MCP_TOKEN