Repository navigation
🎃 Export a single connector as JSON or YAML, and accept YAML on import #1004
Copy link
Copy link
Open
Labels
enhancementNew feature or requestNew feature or requesthacktoberfestGood for Hacktoberfest contributorsGood for Hacktoberfest contributorshelp wantedExtra attention is neededExtra attention is needed
Description
Part of the October Challenge #997.
Why
People who build a connector by hand want to move it: from a test instance to production, from one workspace to another, from self-hosted to Cloud, or into a Git repository so a colleague can review it. Today export and import only work for all connectors of a workspace at once, and only as JSON. YAML is easier to read and to diff in a pull request, especially with long tool descriptions and request templates.
What already exists (do not rebuild it):
GET /api/connectors/export-all(connectors.controller.ts:867-917) returns{ version, exportedAt, secretsIncluded, connectors: [...] }.authConfigis never exported. Secret env vars and headers are exported only to admins; for other roles they are blanked and named inmaskedEnvVars/maskedHeaders(toPublicConnector,connector-secrets.util.ts:267).POST /api/connectors/import-all(:1461-1553) skips a connector whose name already exists in the organization, checks the licence and trial limit per connector, and reloads tools.ImportAllDto(:505-535) accepts the export envelope as downloaded. The global ValidationPipe rejects unknown properties, so a single-connector file must have exactly the shape of oneexport-allentry.- The Connectors page has "Export" and "Import" buttons (
connectors/page.tsx:139-181,:219-243). The connector detail page has no export. js-yaml4 is already a backend dependency (packages/backend/package.json:64), used by the OpenAPI parser to accept JSON or YAML (parsers/openapi.parser.ts:7,:166-185). The frontend has no YAML library.
Self-hosted vs Cloud
- Self-hosted: enabled in Community and Business. No
ee/code. - Cloud (
DEPLOYMENT_MODE=cloud): enabled, with the same rules asexport-all/import-all. Each imported connector counts against the workspace's licence or trial limit throughlicenseGuard.checkCanCreateConnector, exactly as inimport-all. YAML is parsed on the backend, within the 10 MB body limit (main.ts:53). - Who can use it: export, any member of the connector's organization (
assertOrgMatch,:583-587), with secret values only forADMIN, as inexport-all. Import, any role exceptVIEWER(assertCanCreate,:589-593). When an admin's file contains secrets (secretsIncluded: true), the UI says that the file holds plaintext credentials and must be stored like a password.
What to build
- One mapping: extract the per-connector object built in
exportAllinto a function (for exampletoExportEntry(connector, includeSecrets)) used by both export endpoints, so the formats cannot drift. - Export:
GET /api/connectors/:id/export?format=json|yaml(defaultjson). It returns the same envelope asexport-allwith one entry inconnectors, so the file is accepted by every import path. YAML viayaml.dump(data, { schema: CORE_SCHEMA, noRefs: true, lineWidth: -1 })withContent-Type: application/yaml. Both formats withContent-Disposition: attachment; filename="<connector-slug>.anythingmcp.<json|yaml>". - Import of JSON or YAML text:
POST /api/connectors/importwith{ content: string }, holding anexport-allfile or a single-connector file. Parse withyaml.load(content, { schema: CORE_SCHEMA }): JSON is valid YAML, so one parser covers both, andCORE_SCHEMAkeepsexportedAta string instead of turning it into aDate. Validate the result againstImportAllDtowithplainToInstance+validate(whitelist,forbidNonWhitelisted), then run the same logic asimport-all: move its loop into a method both endpoints call, and return the same result (message,created,skipped,tools,errors). A parse error returns 400 with the line and column. - UI:
- Connector detail page header (
connectors/[id]/page.tsx:768-780): an "Export" menu with "JSON" and "YAML". Download withfetch+blob()likehandleExportAll(connectors/page.tsx:139-160), and show the same message when secrets were withheld. - Connectors page import dialog (
connectors/page.tsx:162-181,:271-300): the file input (:288) accepts.json,.yaml,.yml, and the dialog sends the raw text to the new endpoint instead of callingJSON.parsein the browser. Rename "Import from JSON" (:220,:241) to "Import from file".
- Connector detail page header (
- Docs: add
export-all,import-alland the two new endpoints to the Connector Endpoints table indocs/api-reference.md:75-90, with a short YAML example.
Where to look
packages/backend/src/connectors/connectors.controller.ts:430-503(ImportConnectorDto),:505-535(ImportAllDto),:583-603(assertOrgMatch,assertCanCreate,assertCanWrite),:867-917(exportAll),:1461-1553(importAll).packages/backend/src/connectors/connector-secrets.util.ts:267:toPublicConnector()masking.packages/backend/src/connectors/parsers/openapi.parser.ts:166-185: existing JSON-or-YAML decoding.packages/backend/src/connectors/connectors.import-all.spec.ts:116,:178: tests that anexport-allfile imports as downloaded and stays in the caller's organization; copy them for the new endpoints.packages/frontend/src/app/connectors/page.tsx:139-181,:219-243,:271-300;packages/frontend/src/app/connectors/[id]/page.tsx:768-780.packages/frontend/src/lib/api.ts:422-425:exportAll/importAllclients.
Acceptance criteria
- Round-trip spec: export one connector as JSON and as YAML, import both into a second organization, and get the same name, type, base URL, config, headers, env vars (admin export) and tools.
- A single-connector JSON file is also accepted by the existing
POST /api/connectors/import-all. - For non-admins, secrets are blanked and listed in
maskedEnvVars/maskedHeaders;authConfignever appears in either format (asserted in a spec). - Exporting another organization's connector returns 403; a viewer gets 403 on import; invalid YAML returns 400 with line information; a file with an unknown property is rejected in YAML as it is in JSON.
-
cd packages/backend && npx jest src/connectorspasses. - Playwright test: the Export menu on the connector page requests
format=yaml, and the import dialog accepts a.yamlfile (cd packages/frontend && npm run test:e2e). -
docs/api-reference.mdupdated.
Out of scope
- A collision policy (rename or replace on a name clash). Import keeps today's behaviour: a connector whose name exists is skipped.
- Exporting more fields than
export-alldoes today (non-secretauthConfigkeys,healthcheckPath,instructions, tool annotations). That changes the DTO and needs its own design. - Duplicating a connector or a tool within a workspace.
- YAML output for
export-all.
Size
M (1–2 days)
How to claim
Comment "I'd like to work on this" and we'll assign you. Rules in #997.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requesthacktoberfestGood for Hacktoberfest contributorsGood for Hacktoberfest contributorshelp wantedExtra attention is neededExtra attention is needed
Activity
GallaGit commentedon Oct 20, 2026
Hi! I'd like to work on this one. I'll follow the single-connector export/import approach outlined in the design doc (#979), reuse the existing
export-alllogic andconnector-secrets.util.ts, add YAML export plus YAML import, and include tests. Could you assign it to me? Thanks!