Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/retire-serve-preview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@transloadit/mcp-server': patch
---

Stop recommending the retired `builtin/serve-preview` Template for URL inputs.
2 changes: 1 addition & 1 deletion packages/mcp-server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ export const createTransloaditMcpServer = (
warnings.push({
code: 'mcp_url_inputs_ignored',
message: 'URL inputs were ignored because the template does not require input files.',
hint: 'If you meant to process a URL, use a template that imports URLs (e.g. builtin/serve-preview@0.0.1), or call transloadit_list_templates with include_builtin: "exclusively-latest" to discover builtins.',
hint: 'If you meant to process a URL, add an /http/import step or choose a workspace template that contains one. Call transloadit_list_templates to discover available templates.',
path: templatePathHint ?? 'instructions',
})
} else if (analysis.hasHttpImport) {
Expand Down
5 changes: 3 additions & 2 deletions packages/mcp-server/test/e2e/template-inputs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,9 @@ maybeDescribe('mcp-server template URL handling', { timeout: 60000 }, () => {
const warnings = Array.isArray(payload.warnings) ? payload.warnings : []
const ignored = warnings.find((warning) => warning.code === 'mcp_url_inputs_ignored')
expect(ignored).toBeDefined()
expect(typeof ignored?.hint).toBe('string')
expect(String(ignored?.hint)).toContain('transloadit_list_templates')
expect(ignored?.hint).toBe(
'If you meant to process a URL, add an /http/import step or choose a workspace template that contains one. Call transloadit_list_templates to discover available templates.',
)
})

it('errors when required fields are missing', async () => {
Expand Down
60 changes: 39 additions & 21 deletions packages/node/test/e2e/cli/assemblies-create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,33 +313,51 @@ describeLive('assemblies', { retry: 1 }, () => {
)

it(
'should allow output directory for no-input templates (downloads into directory)',
'should allow output directory for no-input workspace templates',
testCase(async (client) => {
await fsp.mkdir('out')

const output = new OutputCtl()
await assembliesCreate(output, client, {
template: 'builtin/serve-preview@0.0.1',
fields: {
input: genericImg,
w: '256',
h: '256',
f: 'png',
const template = await client.createTemplate({
name: `node-sdk-no-input-${crypto.randomUUID()}`,
template: {
steps: {
import: {
robot: '/http/import',
url: genericImg,
},
resize: {
robot: '/image/resize',
use: 'import',
result: true,
width: 256,
height: 256,
format: 'png',
},
},
},
inputs: [],
output: 'out',
})

const files = await rreaddirAsync('out')
expect(files.length).to.be.greaterThan(0)

// Ensure at least one output file is a valid image.
const first = files[0]
expect(first).to.be.a('string')
const buf = await fsp.readFile(first)
const dim = imageSize(new Uint8Array(buf))
expect(dim.width).to.be.greaterThan(0)
expect(dim.height).to.be.greaterThan(0)
try {
const output = new OutputCtl()
await assembliesCreate(output, client, {
template: template.id,
inputs: [],
output: 'out',
})

const files = await rreaddirAsync('out')
expect(files.length).to.be.greaterThan(0)

// Ensure at least one output file is a valid image.
const first = files[0]
expect(first).to.be.a('string')
const buf = await fsp.readFile(first)
const dim = imageSize(new Uint8Array(buf))
expect(dim.width).to.be.greaterThan(0)
expect(dim.height).to.be.greaterThan(0)
} finally {
await client.deleteTemplate(template.id)
}
}),
180_000,
)
Expand Down
14 changes: 7 additions & 7 deletions packages/node/test/unit/cli/templates-list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ describe('cli templates list', () => {
.mockResolvedValueOnce({
items: [
{
id: 'builtin/serve-preview@0.0.1',
name: 'Serve preview',
id: 'builtin/encode-hls-video@0.0.1',
name: 'Encode HLS video',
// minimal shape for CLI printing
content: {},
require_signature_auth: 0,
Expand Down Expand Up @@ -57,8 +57,8 @@ describe('cli templates list', () => {
.mockResolvedValueOnce({
items: [
{
id: 'builtin/serve-preview@0.0.1',
name: 'Serve preview',
id: 'builtin/encode-hls-video@0.0.1',
name: 'Encode HLS video',
content: {},
require_signature_auth: 0,
},
Expand All @@ -70,8 +70,8 @@ describe('cli templates list', () => {
const getSpy = vi.spyOn(Transloadit.prototype, 'getTemplate').mockResolvedValue({
ok: 'ok',
message: 'OK',
id: 'builtin/serve-preview@0.0.1',
name: 'Serve preview',
id: 'builtin/encode-hls-video@0.0.1',
name: 'Encode HLS video',
require_signature_auth: 0,
content: {
steps: {
Expand All @@ -86,7 +86,7 @@ describe('cli templates list', () => {
await main(['templates', 'list', '--include-content', '--include-builtin', 'latest'])

expect(process.exitCode).toBeUndefined()
expect(getSpy).toHaveBeenCalledWith('builtin/serve-preview@0.0.1')
expect(getSpy).toHaveBeenCalledWith('builtin/encode-hls-video@0.0.1')
})

it('fails with an invalid --include-builtin value', async () => {
Expand Down