fix(hubspot): re-sync to HubSpot's replaced MCP tool catalog + RFC 6749 scope fallback on OAuth callback#428
Merged
Conversation
… requested scopes when /token omits scope
HubSpot's remote MCP (mcp.hubspot.com) replaced its entire tool catalog:
the hubspot-list-objects-style tools the shipped template was authored
against no longer exist, so every call answered JSON-RPC -32603
"Unknown tool" and surfaced as a 502 from /v1/actions/call. Verified
live via tools/list (17 new tools) and re-authored services/hubspot.yaml
against it: CRM search/read/SQL-query tools, property metadata, owners,
campaign/content analytics, and manage_crm_objects as the single write
tool with disclose declarations. Connector-internal tools and the
landing-page CMS editor are intentionally not exposed.
Separately, HubSpot's token endpoint never echoes `scope`, so
connections landed with a known-empty scopes set ({}) even after a full
grant. Per RFC 6749 §5.1 an omitted scope means "granted as requested" —
the callback now records the flow row's requested set in that case
(TokenResponse::granted_scopes_or_requested). A present-but-empty scope
is still honored verbatim, and refresh reconciliation is unchanged.
Tests: the hubspot fake now pins a LIVE_CATALOG snapshot and rejects
unknown names with HubSpot's exact -32603 error, so catalog drift fails
CI instead of 502ing in prod; new tests cover template↔catalog sync,
drift → 502 with the RPC code preserved, and the callback scope
fallback end-to-end (plus unit tests for the fallback semantics).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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.
Problem
Two dev-environment failures on the HubSpot connector (debugged live against
overslash-devand mcp.hubspot.com):Every "Try it" call 502'd. HubSpot replaced its remote-MCP tool catalog: the
hubspot-list-objects-style tools thatservices/hubspot.yamlwas authored against no longer exist. The audit log proved Overslash sent the correct per-template name (hubspot-list-objects), and the server answered JSON-RPC-32603 "Unknown tool: invalid_tool_name"→ mapped to 502. A livetools/list(with the real connection token) shows a completely new 17-tool catalog (search_crm_objects,manage_crm_objects,query_crm_data, …).Connections landed with
scopes = {}after a full grant. HubSpot's/oauth/v1/tokenresponse never includes ascopefield. The callback treated that as "no scopes granted" and recorded a known-empty set — while introspection (GET /oauth/v1/access-tokens/{token}) shows the token actually carries the app's full ~40-scope grant.Fix
services/hubspot.yamlre-authored against the live catalog (verified 2026-07-05): CRM search/read + SQL query, property metadata, owners, campaign/content analytics,tool_guidance, andmanage_crm_objectsas the single write tool withdisclosedeclarations (operation, object type, truncated payload). Connector-internal tools (submit_feedback,render_landing_page_ui) and the landing-page CMS editor are intentionally not exposed. New names are valid action keys, so themcp_tooldash-aliasing is gone.scopeentirely, the granted set is by definition the requested set — the callback now records the flow row's requested scopes (TokenResponse::granted_scopes_or_requested). A present-but-emptyscopeis still honored verbatim as "nothing granted", and refresh reconciliation is unchanged (a no-echo refresh still never clobbers).Tests
LIVE_CATALOGsnapshot and rejects unknown names with HubSpot's exact-32603error, so catalog drift fails CI instead of 502ing in prod.scopefield) records the requested scopes, and unit tests for the three fallback semantics (omitted / echoed-narrower / explicit-empty).hubspot(6/6),oauth_x,oauth_return_url,connection_webhooks,approval_disclosure,actions_reauth_return_url,connection_credential_source,overslash-core(incl.shipped_services_validate_clean).Notes
account_emailset,scopes = NULL), so "Try it" works immediately after deploy without a reconnect — the token was always fully scoped.🤖 Generated with Claude Code