feat(plugin): ship the Agent Gateway connector as a Claude Code plugin - #140
Merged
Conversation
Spec for a connector-only Claude Code plugin exposing the Workday Agent
Gateway over HTTP MCP, installed from a marketplace manifest at the repo
root. Additive: the npm package and SDK surface are untouched.
Records the constraint that drove the auth design — ${user_config.*} and
env-var expansion do not apply inside the MCP oauth object, so a templated
client ID is not expressible and sign-in relies on discovery plus dynamic
client registration instead.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Six TDD tasks: plugin manifest, connector, marketplace manifest, README, Cowork packaging recipe, and full verification. Ordered so the plugin directory exists before the marketplace points at it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The ?? {} fallback let 'runs no local command' and 'commits no OAuth
client material' pass against an empty object when the server was
renamed or missing. The https:// substring check passed on http:// and
on bare hostnames.
Replace both with a guard that throws when no workday server is
declared, and an allow-list assertion requiring every connector value
to be a user_config template apart from the fixed interaction channel.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The previous value, https://anthropic.com/claude-code/marketplace.schema.json, returns 404. Replace it with the SchemaStore definition, which resolves and matches this file's shape (required name/owner/plugins; entries keyed on name/source). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dynamic client registration support is unverified, so the Connect section now names the failure case and points at the fallback instead of stating that no client ID is ever needed. Also puts the redirect-URI prerequisite ahead of the command that depends on it, and replaces the unactionable 'reconfigure the plugin options' fix with the settings file the values are actually read from.
The -x '.DS_Store' pattern only matched at the archive root, so a .DS_Store inside .claude-plugin/ shipped in the uploaded bundle. And jq returned the string "null" for a missing version field, silently producing everywhere-plugin-null.zip instead of failing. Switch to the shebang-block form the other multi-line recipes use, so the version guard reads without continuations.
The spec is committed to a public repository, so it should not name internal repositories or codenames. Describe the two prior prototypes by what they do instead. No design decision changes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The spec's connector list predated the safety-test hardening: it still described a literal https:// substring check and omitted the allow-list assertion and the throwing server guard that replaced it. The plan's Task 3 block still showed the vacuous entry?.source ?? '' form that the implementation never used. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mpfilbin
approved these changes
Aug 21, 2026
mpfilbin
left a comment
Collaborator
There was a problem hiding this comment.
Couple of small observations - nothing blocking.
The gateway team removed the requirement for WD-Tenant, WD-Agent-Tenant-Alias, and wd-agent-interaction-channel, so the connector is now just a transport and a URL. Tenant routing rests on the tenant-scoped URL path. Removes the two userConfig fields that existed only to populate those headers, taking the configuration surface from three prompts to one. The allow-list safety test gets stricter as a result: with no fixed channel value to permit, every connector value must now be a user_config template with no literals allowed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A proof of concept for repositioning this repo toward agent integrations: it now additionally works as a Claude Code plugin marketplace, shipping one connector-only plugin that reaches the Workday Agent Gateway over HTTP MCP.
Enabling prompts for a single value — the gateway's MCP endpoint — and sign-in happens through
/mcp. Tools come from the gateway at runtime; the plugin ships no skills, commands, or agents.What's added
.claude-plugin/marketplace.jsonworkday, advertising one pluginplugins/everywhere/.claude-plugin/plugin.jsonuserConfigfield, no defaultplugins/everywhere/.mcp.jsonplugins/everywhere/README.mdtests/claude-plugin/manifest.test.ts.justfilebundle-pluginrecipe for Cowork uploadTwo properties the tests enforce mechanically
Nothing about a gateway is hard-coded. The
gateway_urlfield declares nodefault, and an allow-list assertion requires every value in the connector to be a${user_config.*}template, with no literals permitted at all. A hard-coded hostname, tenant, or token fails the suite.No credential material is committed. The connector declares no
oauthblock. This is not just preference:${user_config.*}and environment-variable expansion apply toenv,url, andheaders, but not insideoauth, so a client ID there could only ever be a committed constant. Sign-in instead uses OAuth discovery plus dynamic client registration.Additive by construction
src/,cli/,bin/, andpackage.jsonare untouched.package.jsonuses an explicitfilesallowlist, andnpm pack --dry-runconfirms no plugin files enter the published tarball. Downstream@workday/everywhereconsumers are unaffected.Verification
just checkandjust testpass — 557 tests, 20 of them newclaude plugin validatepasses for both the plugin and the marketplace manifestnpm pack --dry-runshows no plugin files in the tarballOpen question this POC exists to answer
Whether the gateway supports dynamic client registration. Prior internal work disagrees on this, and it decides whether sign-in works out of the box. If DCR is unsupported, the plugin still works via the manual
claude mcp add --client-id … --callback-port …path documented in the plugin README — that would be a docs change, not a redesign.For reviewers
WD-Tenant,WD-Agent-Tenant-Alias, andwd-agent-interaction-channelare no longer required, so they and their two config fields are gone and tenant routing now rests entirely on the tenant-scoped URL path. That matches what one of the two prior prototypes has always done. Still worth confirming with the AF team before merge — restoring them means re-adding the two fields, theheadersblock, and a permitted-literal exception in the allow-list test.README.mdis deliberately untouched, so nothing yet tells a reader this marketplace exists. Intentional for a POC; worth a decision before any merge.🤖 Generated with Claude Code