From 7b721fce51852849179866d42bb964602ec9b55a Mon Sep 17 00:00:00 2001 From: CodeMash Date: Tue, 13 Oct 2026 12:03:11 +0300 Subject: [PATCH 1/2] chore(types): regenerate hub types from gateway refactoringV2 e011478fe (MCP tool catalog, route 24) Adds GetMarketplaceIntegrationTools, GetMarketplaceIntegrationToolsResponse and MarketplaceMcpToolDto. No type removed. Co-Authored-By: Claude Opus 5.5 --- src/types/hub2.contract.json | 4 +++ src/types/hub2.dtos.ts | 63 +++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/types/hub2.contract.json b/src/types/hub2.contract.json index cf3519e..c79b25c 100644 --- a/src/types/hub2.contract.json +++ b/src/types/hub2.contract.json @@ -1147,6 +1147,10 @@ "requiresAuth": true, "returnsBytes": false }, + "GetMarketplaceIntegrationTools": { + "requiresAuth": true, + "returnsBytes": false + }, "GetMarketplaceIntegrations": { "requiresAuth": true, "returnsBytes": false diff --git a/src/types/hub2.dtos.ts b/src/types/hub2.dtos.ts index 1235f9a..ffe9534 100644 --- a/src/types/hub2.dtos.ts +++ b/src/types/hub2.dtos.ts @@ -1,6 +1,6 @@ // @ts-nocheck /* Options: -Date: 2026-10-13 06:06:10 +Date: 2026-10-13 09:00:52 Version: 10.20 Tip: To override a DTO option, remove "//" prefix before updating BaseUrl: http://localhost:5001 @@ -9430,6 +9430,31 @@ export module CodeMashHub2 { } } + // @DataContract + export class MarketplaceMcpToolDto { + // @DataMember + public name: string; + + // @DataMember + public title?: string; + + // @DataMember + public description?: string; + + // @DataMember + public inputSchema: string; + + // @DataMember + public readOnlyHint?: boolean; + + // @DataMember + public destructiveHint?: boolean; + + public constructor(init?: Partial) { + (Object as any).assign(this, init); + } + } + // @DataContract export class MarketplaceFunctionProjection implements IHasViewId { // @DataMember @@ -12721,6 +12746,18 @@ export module CodeMashHub2 { } } + export class GetMarketplaceIntegrationToolsResponse extends ResponseBase { + public tools: IReadOnlyList; + public listedAt?: string; + public catalogHash?: string; + public truncated: boolean; + + public constructor(init?: Partial) { + super(init); + (Object as any).assign(this, init); + } + } + export class EmptyMarketplaceSecretsResponse extends ResponseBase { public constructor(init?: Partial) { super(init); @@ -23615,6 +23652,30 @@ export module CodeMashHub2 { } } + // @Route("/{version}/code/marketplace/integrations/{IntegrationViewId}/tools", "GET") + export class GetMarketplaceIntegrationTools + extends CodeMashRequestBase + implements IReturn + { + /** @description Integration view id, from get_marketplace_integrations. */ + // @ApiMember(Description="Integration view id, from get_marketplace_integrations.", IsRequired=true) + public integrationViewId: string; + + public constructor(init?: Partial) { + super(init); + (Object as any).assign(this, init); + } + public getTypeName() { + return 'GetMarketplaceIntegrationTools'; + } + public getMethod() { + return 'GET'; + } + public createResponse() { + return new GetMarketplaceIntegrationToolsResponse(); + } + } + // @Route("/{version}/code/marketplace/integrations/{IntegrationViewId}/secrets", "PUT") // @DataContract export class ReplaceMarketplaceIntegrationSecretsRequest From 8aa351952c811d86d36c0c5f58f9b35e439cb239 Mon Sep 17 00:00:00 2001 From: CodeMash Date: Tue, 13 Oct 2026 12:04:30 +0300 Subject: [PATCH 2/2] feat(marketplace): getMarketplaceIntegrationTools, the MCP tool catalog (route 24) GET /{version}/code/marketplace/integrations/{IntegrationViewId}/tools from generate-endpoints (Code module only, other modules untouched), its generated test and doc row, plus a test that pins the id in the path, no body, and the catalog read back. Co-Authored-By: Claude Opus 5.5 --- docs/hub/code.md | 24 ++++++++++++ src/hub/code.ts | 19 ++++++++++ tests/hub/code.test.ts | 26 +++++++++++++ tests/hub/marketplace-mcp-tools.test.ts | 50 +++++++++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 tests/hub/marketplace-mcp-tools.test.ts diff --git a/docs/hub/code.md b/docs/hub/code.md index f9db3be..d10cfc5 100644 --- a/docs/hub/code.md +++ b/docs/hub/code.md @@ -36,6 +36,7 @@ Accessed as `norbix.hub.code` on the [`Norbix`](../../README.md#authentication) | [`invokeMarketplaceFunction`](#invokemarketplacefunction) | `POST` | `/{version}/code/marketplace/functions/{FunctionViewId}/invoke` | `project` | | [`getMarketplaceListing`](#getmarketplacelisting) | `GET` | `/{version}/code/marketplace/listings/{ListingViewId}` | `project` | | [`testMarketplaceIntegration`](#testmarketplaceintegration) | `POST` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/test` | `project` | +| [`getMarketplaceIntegrationTools`](#getmarketplaceintegrationtools) | `GET` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/tools` | `project` | | [`replaceMarketplaceIntegrationSecrets`](#replacemarketplaceintegrationsecrets) | `PUT` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/secrets` | `project` | | [`revealMarketplaceIntegrationSecrets`](#revealmarketplaceintegrationsecrets) | `POST` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/secrets/reveal` | `project` | | [`setMarketplaceIntegrationTokenMappings`](#setmarketplaceintegrationtokenmappings) | `PUT` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/token-mappings` | `project` | @@ -686,6 +687,29 @@ const result = await norbix.hub.code.testMarketplaceIntegration({ [↑ Top](#endpoints) +### getMarketplaceIntegrationTools + +`GET` `/{version}/code/marketplace/integrations/{IntegrationViewId}/tools` + +Fetch a single item by ID. + +**Request DTO**: `CodeMashHub2.GetMarketplaceIntegrationTools` +**Response**: `CodeMashHub2.GetMarketplaceIntegrationToolsResponse` + +```ts +import { Norbix } from '@norbix.ai/ts'; + +const norbix = new Norbix(); + +const result = await norbix.hub.code.getMarketplaceIntegrationTools({ + IntegrationViewId: 'IntegrationViewId-here', + // Other fields: see CodeMash type for the full request shape. +}); +// → typed as CodeMashHub2.GetMarketplaceIntegrationToolsResponse +``` + +[↑ Top](#endpoints) + ### replaceMarketplaceIntegrationSecrets `PUT` `/{version}/code/marketplace/integrations/{IntegrationViewId}/secrets` diff --git a/src/hub/code.ts b/src/hub/code.ts index 06ee4d8..e676306 100644 --- a/src/hub/code.ts +++ b/src/hub/code.ts @@ -545,6 +545,25 @@ export class CodeModule { }); }; + /** + * GET /{version}/code/marketplace/integrations/{IntegrationViewId}/tools + * Request DTO: GetMarketplaceIntegrationTools + */ + getMarketplaceIntegrationTools = ( + request: Partial = {} as Partial, + options: RequestOverrideOptions = {}, + ): Promise => { + return this.transport.send({ + target: 'hub', + path: '/{version}/code/marketplace/integrations/{IntegrationViewId}/tools', + method: 'GET', + request, + pathParams: ['IntegrationViewId'], + scope: 'project', + ...options, + }); + }; + /** * PUT /{version}/code/marketplace/integrations/{IntegrationViewId}/secrets * Request DTO: ReplaceMarketplaceIntegrationSecretsRequest diff --git a/tests/hub/code.test.ts b/tests/hub/code.test.ts index 3855218..9861562 100644 --- a/tests/hub/code.test.ts +++ b/tests/hub/code.test.ts @@ -57,6 +57,7 @@ describe('hub.code', () => { expect(typeof ns['invokeMarketplaceFunction']).toBe('function'); expect(typeof ns['getMarketplaceListing']).toBe('function'); expect(typeof ns['testMarketplaceIntegration']).toBe('function'); + expect(typeof ns['getMarketplaceIntegrationTools']).toBe('function'); expect(typeof ns['replaceMarketplaceIntegrationSecrets']).toBe('function'); expect(typeof ns['revealMarketplaceIntegrationSecrets']).toBe('function'); expect(typeof ns['setMarketplaceIntegrationTokenMappings']).toBe('function'); @@ -737,6 +738,31 @@ describe('hub.code', () => { expect(mock.lastCall?.headers.get('norbix-project-id')).toBe('test-project'); }); + it('getMarketplaceIntegrationTools: GET /{version}/code/marketplace/integrations/{IntegrationViewId}/tools', async () => { + const stub = stubRequestForPath( + '/{version}/code/marketplace/integrations/{IntegrationViewId}/tools', + ); + const expected = expectedUrl({ + baseUrl: 'https://hub.norbix.io', + path: '/{version}/code/marketplace/integrations/{IntegrationViewId}/tools', + version: 'v2', + stub, + }); + const { norbix, mock } = makeClient({}); + const fn = ( + norbix.hub as unknown as Record< + string, + Record Promise> + > + )['code']!['getMarketplaceIntegrationTools']!; + await fn(stub); + expect(mock.lastCall).toBeDefined(); + expect(mock.lastCall?.method).toBe('GET'); + expect(mock.lastCall?.url.startsWith(expected)).toBe(true); + expect(mock.lastCall?.headers.get('Authorization')).toBe('Bearer test-token'); + expect(mock.lastCall?.headers.get('norbix-project-id')).toBe('test-project'); + }); + it('replaceMarketplaceIntegrationSecrets: PUT /{version}/code/marketplace/integrations/{IntegrationViewId}/secrets', async () => { const stub = stubRequestForPath( '/{version}/code/marketplace/integrations/{IntegrationViewId}/secrets', diff --git a/tests/hub/marketplace-mcp-tools.test.ts b/tests/hub/marketplace-mcp-tools.test.ts new file mode 100644 index 0000000..9a4713f --- /dev/null +++ b/tests/hub/marketplace-mcp-tools.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, it } from 'vitest'; + +import type { CodeMashHub2 } from '../../src/types/hub2.dtos.js'; +import { createMockFetch, makeClient } from '../_helpers.js'; + +/** + * GET /{version}/code/marketplace/integrations/{IntegrationViewId}/tools — the + * stored tool catalog of an MCP connection for the request's env. + * + * The generated test in code.test.ts sends a stub request; this case pins that + * the connection id goes into the path (never the query or a body) and that the + * catalog comes back as the gateway sent it. + */ +describe('hub.code.getMarketplaceIntegrationTools', () => { + it('puts the connection id in the path on a GET with no body and returns the catalog', async () => { + const tool = { + name: 'create_issue', + title: 'Create issue', + description: 'Open a new issue in a repository', + inputSchema: + '{"type":"object","properties":{"title":{"type":"string"}},"required":["title"]}', + readOnlyHint: false, + destructiveHint: false, + } as CodeMashHub2.MarketplaceMcpToolDto; + const mock = createMockFetch({ + body: { + tools: [tool], + listedAt: '2026-10-13T08:00:00Z', + catalogHash: '4ce4259bec02f283', + truncated: false, + }, + }); + const { norbix } = makeClient({ fetch: mock.fetch }); + + const response = await norbix.hub.code.getMarketplaceIntegrationTools({ + integrationViewId: 'int_7Hq2mcpServer', + }); + + const call = mock.lastCall!; + const url = new URL(call.url); + expect(call.method).toBe('GET'); + expect(url.pathname).toBe('/v2/code/marketplace/integrations/int_7Hq2mcpServer/tools'); + expect(url.searchParams.has('integrationViewId')).toBe(false); + expect(call.body).toBeUndefined(); + expect(call.headers.get('norbix-project-id')).toBe('test-project'); + expect(response.tools).toEqual([tool]); + expect(response.catalogHash).toBe('4ce4259bec02f283'); + expect(response.truncated).toBe(false); + }); +});