Skip to content

Commit b0a6ae7

Browse files
committed
feat(mcp-server): fetch golden templates from api
1 parent 7b9d69f commit b0a6ae7

8 files changed

Lines changed: 146 additions & 222 deletions

File tree

docs/fingerprint/transloadit-baseline.json

Lines changed: 25 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"packageDir": "/home/kvz/code/node-sdk/packages/transloadit",
33
"tarball": {
44
"filename": "transloadit-4.4.0.tgz",
5-
"sizeBytes": 1232789,
6-
"sha256": "3e3adec236c195b51647b80d9b9bb0dbfa3289236ad0744fc5d2aefbb21b63b0"
5+
"sizeBytes": 1231681,
6+
"sha256": "ec460c59a74d8d0e3ae826819f16b8a12e2134975995341461f99711b58dfd93"
77
},
88
"packageJson": {
99
"name": "transloadit",
@@ -311,11 +311,6 @@
311311
"sizeBytes": 3534,
312312
"sha256": "c4bd648bb097acadbc349406192105367b9d94c516700b99c9f4d7a4b6c7a6f0"
313313
},
314-
{
315-
"path": "dist/alphalib/goldenTemplates.js",
316-
"sizeBytes": 1462,
317-
"sha256": "73213f340a82273eefd58585345af6b4237a136ec97fe2946893ab933feab659"
318-
},
319314
{
320315
"path": "dist/alphalib/types/robots/google-import.js",
321316
"sizeBytes": 3748,
@@ -533,8 +528,8 @@
533528
},
534529
{
535530
"path": "dist/cli/template-last-modified.js",
536-
"sizeBytes": 4183,
537-
"sha256": "26fb01b74d324df74e120cd7640a64d221214879e44dd695903602afbc01ee58"
531+
"sizeBytes": 4265,
532+
"sha256": "a2dc86a7b0d8b223629e62ddf10d175c70019d57ad4c0de8cf00a048aa26ebbe"
538533
},
539534
{
540535
"path": "dist/alphalib/types/template.js",
@@ -583,8 +578,8 @@
583578
},
584579
{
585580
"path": "dist/Transloadit.js",
586-
"sizeBytes": 36883,
587-
"sha256": "ef4717bcc8930b750f5d8466097eec96b5f636eeeffe314cb5bde141562ae4d5"
581+
"sizeBytes": 36818,
582+
"sha256": "087f9df70023ddf5dc82fe14831dcf7bd974967d036dbfde164faf7bea480db1"
588583
},
589584
{
590585
"path": "dist/alphalib/tryCatch.js",
@@ -728,8 +723,8 @@
728723
},
729724
{
730725
"path": "dist/apiTypes.d.ts.map",
731-
"sizeBytes": 3499,
732-
"sha256": "afccc6e3b08e1a87a42a680ffa1439d4cf0e883a1ebc3b19832b2f25db939987"
726+
"sizeBytes": 3668,
727+
"sha256": "f3812c67e402777b133ee0676e5b89a569c5e172b15c1322b0a71797793cdbda"
733728
},
734729
{
735730
"path": "dist/apiTypes.js.map",
@@ -1266,16 +1261,6 @@
12661261
"sizeBytes": 2145,
12671262
"sha256": "ce1bf48c1cc713ae843061cba3c3b119475baa5cb6b62ac4b575e50b297bcf71"
12681263
},
1269-
{
1270-
"path": "dist/alphalib/goldenTemplates.d.ts.map",
1271-
"sizeBytes": 372,
1272-
"sha256": "9d03bb8544e479187f7cc025e510299f7c8c4a7605f6387799c3d6e0d677e205"
1273-
},
1274-
{
1275-
"path": "dist/alphalib/goldenTemplates.js.map",
1276-
"sizeBytes": 965,
1277-
"sha256": "4c179dfd32215c7ecc51885928c5449486ae90b0653485624466390401384e5c"
1278-
},
12791264
{
12801265
"path": "dist/alphalib/types/robots/google-import.d.ts.map",
12811266
"sizeBytes": 960,
@@ -1709,12 +1694,12 @@
17091694
{
17101695
"path": "dist/cli/template-last-modified.d.ts.map",
17111696
"sizeBytes": 492,
1712-
"sha256": "927f06c6c3ac447c7459f881ad4150ed0cbec8c199b114452590e25df57d6f44"
1697+
"sha256": "1b05f82877fe136d02bc76b0e9fdfef999c54c1bead854f6317ed5c10be4b25b"
17131698
},
17141699
{
17151700
"path": "dist/cli/template-last-modified.js.map",
1716-
"sizeBytes": 4406,
1717-
"sha256": "ecf48762d1c4275b90bab7da82b44a9e0c31b2cf8bb62a2f1381c34ceced91c9"
1701+
"sizeBytes": 4493,
1702+
"sha256": "4be11f42407054045ec1512dd4150bff48c5dcea2f802e82b7f0f734a0040e9d"
17181703
},
17191704
{
17201705
"path": "dist/alphalib/types/template.d.ts.map",
@@ -1808,13 +1793,13 @@
18081793
},
18091794
{
18101795
"path": "dist/Transloadit.d.ts.map",
1811-
"sizeBytes": 6406,
1812-
"sha256": "51f9faaa4e12826a77c2ab0818cbb850a044e6d27d686c02578b8ff14c414313"
1796+
"sizeBytes": 6363,
1797+
"sha256": "fcec91b2f7b7319de1a04d5d113502ce8ac62b9033e67ce511e3a9c5b8b84386"
18131798
},
18141799
{
18151800
"path": "dist/Transloadit.js.map",
1816-
"sizeBytes": 26946,
1817-
"sha256": "33b7676224bfd7d0b2a6c6e448cce67d0929eda5fefc05beb70f57550e6a93d5"
1801+
"sizeBytes": 26903,
1802+
"sha256": "55c8cf1fbb2565b1acbd81217512c6e27f85a2e126e1bf549a357b258f8cf9f3"
18181803
},
18191804
{
18201805
"path": "dist/alphalib/tryCatch.d.ts.map",
@@ -2053,13 +2038,13 @@
20532038
},
20542039
{
20552040
"path": "dist/apiTypes.d.ts",
2056-
"sizeBytes": 3730,
2057-
"sha256": "5c69b795640fa02650cf0733d262b28488a049848863392bf33a3992eb0049eb"
2041+
"sizeBytes": 3864,
2042+
"sha256": "326478834139f0974e5f5a37263b3fae8b95622847e87cf4f2c2bc9b48d0bd2a"
20582043
},
20592044
{
20602045
"path": "src/apiTypes.ts",
2061-
"sizeBytes": 4042,
2062-
"sha256": "6be2494c40b5cee641b33329b6e2bc495c0357ffa3509228c4c531d59dbc0c5a"
2046+
"sizeBytes": 4167,
2047+
"sha256": "ad038624f0b527b4f406b76a6120a6e27c1659dde28c22cbaee7e3d85f2e99e7"
20632048
},
20642049
{
20652050
"path": "dist/cli/commands/assemblies.d.ts",
@@ -2591,16 +2576,6 @@
25912576
"sizeBytes": 4197,
25922577
"sha256": "1bbaa2361cc3675a29178cbd0f4fcecaad1033032f154a6da36c5c677a9c9447"
25932578
},
2594-
{
2595-
"path": "dist/alphalib/goldenTemplates.d.ts",
2596-
"sizeBytes": 1405,
2597-
"sha256": "119113a122aff76eb1940fd1965ae543f882bee68c558a408a8ee2879666ccf8"
2598-
},
2599-
{
2600-
"path": "src/alphalib/goldenTemplates.ts",
2601-
"sizeBytes": 1291,
2602-
"sha256": "8aee08c17888c3ebb7dd83a096f75d3517ce565c2d2ae518ca229e6e9e0d84e1"
2603-
},
26042579
{
26052580
"path": "dist/alphalib/types/robots/google-import.d.ts",
26062581
"sizeBytes": 9781,
@@ -3043,8 +3018,8 @@
30433018
},
30443019
{
30453020
"path": "src/cli/template-last-modified.ts",
3046-
"sizeBytes": 3925,
3047-
"sha256": "c319bb83a5a3e24fb9998976eeae74a2e9094356e2ac1495d8519df7aaa371d6"
3021+
"sizeBytes": 3996,
3022+
"sha256": "712f3b9de444fe006df011432e9151d57d47960c711158fac0cb861e5b7a098a"
30483023
},
30493024
{
30503025
"path": "dist/alphalib/types/template.d.ts",
@@ -3138,13 +3113,13 @@
31383113
},
31393114
{
31403115
"path": "dist/Transloadit.d.ts",
3141-
"sizeBytes": 11847,
3142-
"sha256": "5a280d61733d751cb2c9137fb19557dab9e4b2cc8e48c89bfad7474ce0bc0e06"
3116+
"sizeBytes": 11782,
3117+
"sha256": "47f99188709da4e2ca9b1f83f0e97eb6de3e17474c3d25d25274000b3b5a6337"
31433118
},
31443119
{
31453120
"path": "src/Transloadit.ts",
3146-
"sizeBytes": 41433,
3147-
"sha256": "02d6ca96421b0ec39e31c4fb40a06537f2a61ba87787f9e904907f6463f854ea"
3121+
"sizeBytes": 41369,
3122+
"sha256": "c566e266a55bf0ea280b44e1d0ff63c863be1296d5577e1dcb9266631577aea0"
31483123
},
31493124
{
31503125
"path": "dist/alphalib/tryCatch.d.ts",

packages/mcp-server/src/server.ts

Lines changed: 112 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import type {
77
} from '@transloadit/node'
88
import {
99
getRobotHelp,
10-
goldenTemplates,
1110
listRobots,
1211
mergeTemplateContent,
1312
prepareInputFiles,
@@ -58,8 +57,6 @@ type GoldenTemplate = {
5857

5958
type LintAssemblyInstructionsInput = Parameters<Transloadit['lintAssemblyInstructions']>[0]
6059

61-
const goldenTemplatesMap = goldenTemplates as Record<string, GoldenTemplate>
62-
6360
const lintIssueSchema = z.object({
6461
path: z.string(),
6562
message: z.string(),
@@ -341,6 +338,9 @@ const createLiveClient = (
341338
const isRecord = (value: unknown): value is Record<string, unknown> =>
342339
typeof value === 'object' && value !== null
343340

341+
const isNonEmptyString = (value: unknown): value is string =>
342+
typeof value === 'string' && value.length > 0
343+
344344
const isErrnoException = (value: unknown): value is NodeJS.ErrnoException =>
345345
isRecord(value) && typeof value.code === 'string'
346346

@@ -383,19 +383,78 @@ const resolveAssemblyAccess = (
383383
}
384384
}
385385

386-
const resolveGoldenTemplate = (slug: string, version?: string): GoldenTemplate | undefined => {
387-
if (slug.includes('@')) {
388-
return goldenTemplatesMap[slug]
386+
type ApiTemplateRecord = {
387+
id?: unknown
388+
name?: unknown
389+
description?: unknown
390+
golden_version?: unknown
391+
content?: unknown
392+
}
393+
394+
const buildGoldenTemplateId = (slug: string, version?: string): string => {
395+
if (slug.includes('@')) return slug
396+
if (version) return `${slug}@${version}`
397+
return slug
398+
}
399+
400+
const extractTemplateSteps = (content: unknown): Record<string, unknown> | undefined => {
401+
if (!isRecord(content)) return undefined
402+
const steps = content.steps
403+
return isRecord(steps) ? (steps as Record<string, unknown>) : undefined
404+
}
405+
406+
const mapGoldenTemplate = (template: ApiTemplateRecord): GoldenTemplate | undefined => {
407+
const slug = isNonEmptyString(template.name)
408+
? template.name
409+
: isNonEmptyString(template.id)
410+
? template.id
411+
: undefined
412+
413+
if (!slug || !slug.startsWith('~')) return undefined
414+
415+
const steps = extractTemplateSteps(template.content)
416+
if (!steps) return undefined
417+
418+
const version = isNonEmptyString(template.golden_version)
419+
? template.golden_version
420+
: slug.includes('@')
421+
? (slug.split('@')[1] ?? '')
422+
: ''
423+
424+
return {
425+
slug,
426+
version,
427+
description: isNonEmptyString(template.description) ? template.description : '',
428+
steps,
389429
}
430+
}
390431

391-
if (version) {
392-
return goldenTemplatesMap[`${slug}@${version}`]
432+
const fetchGoldenTemplates = async (client: Transloadit): Promise<GoldenTemplate[]> => {
433+
const response = (await client.listTemplates({
434+
include_golden: 'latest',
435+
page: 1,
436+
pagesize: 100,
437+
})) as {
438+
items?: ApiTemplateRecord[]
393439
}
394440

395-
const matches = Object.keys(goldenTemplatesMap).filter((key) => key.startsWith(`${slug}@`))
396-
if (matches.length === 0) return undefined
397-
const latest = matches.sort().at(-1)
398-
return latest ? goldenTemplatesMap[latest] : undefined
441+
const items = Array.isArray(response.items) ? response.items : []
442+
return items
443+
.map((template) => mapGoldenTemplate(template))
444+
.filter((template): template is GoldenTemplate => Boolean(template))
445+
}
446+
447+
const fetchGoldenTemplateContent = async (
448+
client: Transloadit,
449+
slug: string,
450+
version?: string,
451+
): Promise<TemplateContent | undefined> => {
452+
const templateId = buildGoldenTemplateId(slug, version)
453+
const template = (await client.getTemplate(templateId)) as {
454+
content?: unknown
455+
}
456+
if (!template?.content || !isRecord(template.content)) return undefined
457+
return template.content as TemplateContent
399458
}
400459

401460
const parseInstructions = (input: unknown): CreateAssemblyParams | undefined => {
@@ -496,9 +555,13 @@ export const createTransloaditMcpServer = (
496555
let params = parseInstructions(instructions) ?? ({} as CreateAssemblyParams)
497556

498557
if (golden_template) {
499-
const template = resolveGoldenTemplate(golden_template.slug, golden_template.version)
558+
const templateContent = await fetchGoldenTemplateContent(
559+
client,
560+
golden_template.slug,
561+
golden_template.version,
562+
)
500563

501-
if (!template) {
564+
if (!templateContent) {
502565
return buildToolError(
503566
'mcp_unknown_template',
504567
`Unknown golden template: ${golden_template.slug}`,
@@ -507,9 +570,6 @@ export const createTransloaditMcpServer = (
507570
}
508571

509572
const overrides = golden_template.overrides
510-
const templateContent = {
511-
steps: template.steps,
512-
} as TemplateContent
513573
params = mergeTemplateContent(
514574
templateContent,
515575
overrides && isRecord(overrides) ? (overrides as Record<string, unknown>) : undefined,
@@ -722,11 +782,41 @@ export const createTransloaditMcpServer = (
722782
inputSchema: listGoldenTemplatesInputSchema,
723783
outputSchema: listGoldenTemplatesOutputSchema,
724784
},
725-
() => {
726-
return buildToolResponse({
727-
status: 'ok',
728-
templates: Object.values(goldenTemplatesMap),
729-
})
785+
async (_args, extra) => {
786+
const liveClient = createLiveClient(options, extra)
787+
if ('error' in liveClient) {
788+
return buildToolResponse({
789+
status: 'error',
790+
templates: [],
791+
errors: [
792+
{
793+
code: 'mcp_missing_auth',
794+
message:
795+
'Missing TRANSLOADIT_KEY/TRANSLOADIT_SECRET or Authorization: Bearer token for live API calls.',
796+
},
797+
],
798+
})
799+
}
800+
801+
try {
802+
const templates = await fetchGoldenTemplates(liveClient.client)
803+
return buildToolResponse({
804+
status: 'ok',
805+
templates,
806+
})
807+
} catch (error) {
808+
const message = error instanceof Error ? error.message : 'Failed to fetch golden templates.'
809+
return buildToolResponse({
810+
status: 'error',
811+
templates: [],
812+
errors: [
813+
{
814+
code: 'mcp_golden_templates_failed',
815+
message,
816+
},
817+
],
818+
})
819+
}
730820
},
731821
)
732822

packages/node/src/Transloadit.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ export {
6666
TimeoutError,
6767
UploadError,
6868
} from 'got'
69-
export { goldenTemplates } from './alphalib/goldenTemplates/index.ts'
7069
export type { AssemblyStatus } from './alphalib/types/assemblyStatus.ts'
7170
export * from './apiTypes.ts'
7271
export { InconsistentResponseError, ApiError }

0 commit comments

Comments
 (0)