mirror of
https://github.com/hoppscotch/hoppscotch.git
synced 2026-04-26 01:06:00 +03:00
[PR #5955] feat: expose collections as MCP HTTP endpoints #5433
Labels
No labels
CodeDay
a11y
browser limited
bug
bug fix
cli
core
critical
design
desktop
discussion
docker
documentation
duplicate
enterprise
feature
feature
fosshack
future
good first issue
hacktoberfest
help wanted
i18n
invalid
major
minor
need information
need testing
not applicable to hoppscotch
not reproducible
pull-request
question
refactor
resolved
sandbox
self-host
spam
stale
testmu
wip
wont fix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/hoppscotch#5433
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/hoppscotch/hoppscotch/pull/5955
Author: @jamesgeorge007
Created: 3/6/2026
Status: 🔄 Open
Base:
next← Head:feat/share-collection-as-mcp📝 Commits (8)
6dc86b7feat(backend,common): add Share as MCP — expose Hoppscotch collections as MCP HTTP endpoints93bdfb8fix(backend): cast McpShare return object to resolve WorkspaceType enum mismatchdca3b4cfix(backend): correct slugify test expectation in mcp-tool-generator spec8e5ba0afix(backend): harden mcp-share — SSRF guard, body routing, bounded cache, migration7528a21fix(backend): fix SSRF regex anchoring and strip internal schema fields from mcp tools/list152b8b4fix(common): rewrite MCP share GQL calls to use proper urql Client APIf2918b3fix(backend): add fetch timeout, use findUnique, guard cache evictiond3b4f2cfix(backend): harden MCP controller — SSRF redirect bypass, response limits, notifications📊 Changes
22 files changed (+1707 additions, -0 deletions)
View changed files
➕
packages/hoppscotch-backend/prisma/migrations/20260306000000_add_mcp_share/migration.sql(+24 -0)📝
packages/hoppscotch-backend/prisma/schema.prisma(+16 -0)📝
packages/hoppscotch-backend/src/app.module.ts(+2 -0)📝
packages/hoppscotch-backend/src/errors.ts(+36 -0)➕
packages/hoppscotch-backend/src/mcp-share/mcp-share.controller.ts(+349 -0)➕
packages/hoppscotch-backend/src/mcp-share/mcp-share.model.ts(+39 -0)➕
packages/hoppscotch-backend/src/mcp-share/mcp-share.module.ts(+14 -0)➕
packages/hoppscotch-backend/src/mcp-share/mcp-share.resolver.ts(+55 -0)➕
packages/hoppscotch-backend/src/mcp-share/mcp-share.service.ts(+194 -0)➕
packages/hoppscotch-backend/src/mcp-share/mcp-tool-generator.spec.ts(+250 -0)➕
packages/hoppscotch-backend/src/mcp-share/mcp-tool-generator.ts(+211 -0)📝
packages/hoppscotch-backend/src/types/InfraConfig.ts(+2 -0)📝
packages/hoppscotch-common/locales/en.json(+14 -0)📝
packages/hoppscotch-common/src/components/collections/Collection.vue(+16 -0)➕
packages/hoppscotch-common/src/components/collections/McpShare.vue(+277 -0)📝
packages/hoppscotch-common/src/components/collections/MyCollections.vue(+14 -0)📝
packages/hoppscotch-common/src/components/collections/TeamCollections.vue(+14 -0)📝
packages/hoppscotch-common/src/components/collections/index.vue(+47 -0)➕
packages/hoppscotch-common/src/composables/mcpShareVisibility.ts(+16 -0)➕
packages/hoppscotch-common/src/helpers/backend/mutations/McpShare.ts(+114 -0)...and 2 more files
📄 Description
Adds "Share as MCP" — users can expose a root Hoppscotch collection as an MCP Streamable HTTP endpoint that AI clients (Claude Desktop, Cursor, Windsurf) connect to directly.
What's changed
Backend (
hoppscotch-backend)McpSharePrisma model with migration — stores share tokens, workspace references, soft-delete supportmcp-share/NestJS module: service, GQL resolver, REST controller, tool generatorPOST /v1/mcp/:shareTokenendpoint handles JSON-RPC (initialize,tools/list,tools/call) — no JWT needed, the share token is the credentialisPrivateUrl) blocks loopback, RFC-1918, link-local, IPv4-mapped IPv6, ULA ranges, and localhost — withredirect: 'manual'to prevent redirect-based bypassbodyKeys,queryKeys,_meta) stripped fromtools/listresponsesMCP_SHARE_WILDCARD_DOMAINinfra config enum valueFrontend (
hoppscotch-common)McpShare.vuemodal — load existing share, generate new, copy URL, client config snippets (Claude/Cursor/Windsurf tabs), revokeMcpShare.ts) usingTE.tryCatch+client.value!.mutation/query().toPromise()patternmcpShareVisibility.tscomposable tied toENABLE_MCP_SHAREsettingisMcpShareVisible && isRootCollectionCollection.vue→MyCollections.vue/TeamCollections.vue→index.vuemcpnamespaceENABLE_MCP_SHARE: falsedefault in settings store + validation schemaNotes to reviewers
The UI entry point is hidden by default (
ENABLE_MCP_SHARE: falsein the client-side settings store). The backend endpoints and GQL resolver are always active once deployed — the setting only controls menu item visibility.The MCP endpoint is unauthenticated by design — the 20-char base64url share token (≈120 bits entropy) acts as the credential, rate-limited via
ThrottlerBehindProxyGuard.The tool generator only infers flat (one-level) JSON body schemas — nested objects become
{ type: 'string' }. This is intentional for v1 and matches how MCP tool parameters typically work.DNS rebinding is a known residual risk (hostname regex doesn't resolve DNS). Mitigated by
redirect: 'manual'— can be hardened withdns.lookup()pre-check before wider rollout.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.