Skip to main content
Glama

Genkit MCP

Official
by firebase
utils_test.ts15.5 kB
/** * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import * as assert from 'assert'; import { GenkitError, embedderRef, modelRef } from 'genkit'; import { GenerateRequest } from 'genkit/model'; import { describe, it } from 'node:test'; import { checkModelName, checkSupportedMimeType, cleanSchema, displayUrl, extractErrMsg, extractMedia, extractMimeType, extractText, extractVersion, modelName, } from '../../src/common/utils.js'; describe('Common Utils', () => { describe('extractErrMsg', () => { it('extracts message from an Error object', () => { const error = new Error('This is a test error.'); assert.strictEqual(extractErrMsg(error), 'This is a test error.'); }); it('returns the string if error is a string', () => { const error = 'A simple string error.'; assert.strictEqual(extractErrMsg(error), 'A simple string error.'); }); it('stringifies other error types', () => { const error = { code: 500, message: 'Object error' }; assert.strictEqual( extractErrMsg(error), '{"code":500,"message":"Object error"}' ); }); }); describe('extractVersion', () => { it('should return version from modelRef if present', () => { const ref = modelRef({ name: 'vertexai/gemini-1.5-pro', version: 'gemini-1.5-pro-001', }); assert.strictEqual(extractVersion(ref), 'gemini-1.5-pro-001'); }); it('should extract version from name if version field is missing', () => { const ref = modelRef({ name: 'vertexai/gemini-1.5-flash' }); assert.strictEqual(extractVersion(ref), 'gemini-1.5-flash'); }); it('should work with embedderRef', () => { const ref = embedderRef({ name: 'vertexai/text-embedding-004' }); assert.strictEqual(extractVersion(ref), 'text-embedding-004'); }); }); describe('modelName', () => { it('extracts model name from a full path', () => { assert.strictEqual( modelName('models/googleai/gemini-1.5-pro'), 'gemini-1.5-pro' ); assert.strictEqual( modelName('vertexai/gemini-1.5-flash'), 'gemini-1.5-flash' ); assert.strictEqual(modelName('model/foo'), 'foo'); assert.strictEqual(modelName('embedders/bar'), 'bar'); assert.strictEqual(modelName('background-model/baz'), 'baz'); }); it('returns the name if no known prefix is present', () => { assert.strictEqual(modelName('gemini-1.0-ultra'), 'gemini-1.0-ultra'); }); it('handles undefined input', () => { assert.strictEqual(modelName(undefined), undefined); }); it('handles empty string input', () => { assert.strictEqual(modelName(''), ''); }); }); describe('checkModelName', () => { it('extracts model name from a full path', () => { const name = 'models/vertexai/gemini-1.5-pro'; assert.strictEqual(checkModelName(name), 'gemini-1.5-pro'); }); it('returns name if no prefix', () => { assert.strictEqual(checkModelName('foo-bar'), 'foo-bar'); }); it('throws an error for undefined input', () => { assert.throws( () => checkModelName(undefined), (err: any) => { assert.ok(err instanceof GenkitError, 'Expected GenkitError'); assert.strictEqual(err.status, 'INVALID_ARGUMENT'); assert.strictEqual( err.message, 'INVALID_ARGUMENT: Model name is required.' ); return true; } ); }); it('throws an error for an empty string', () => { assert.throws( () => checkModelName(''), (err: any) => { assert.ok(err instanceof GenkitError, 'Expected GenkitError'); assert.strictEqual(err.status, 'INVALID_ARGUMENT'); assert.strictEqual( err.message, 'INVALID_ARGUMENT: Model name is required.' ); return true; } ); }); }); describe('extractText', () => { it('extracts text from the last message', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [{ text: 'Hello there.' }] }, { role: 'model', content: [{ text: 'How can I help?' }] }, { role: 'user', content: [{ text: 'Tell me a joke.' }] }, ], }; assert.strictEqual(extractText(request), 'Tell me a joke.'); }); it('concatenates multiple text parts in the last message', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [{ text: 'Part 1. ' }, { text: 'Part 2.' }], }, ], }; assert.strictEqual(extractText(request), 'Part 1. Part 2.'); }); it('ignores non-text parts in the last message', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [ { text: 'A ' }, { media: { url: 'data:image/jpeg;base64,IMAGEDATA' } }, { text: 'B' }, ], }, ], }; assert.strictEqual(extractText(request), 'A B'); }); it('returns an empty string if there are no text parts in the last message', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [{ media: { url: 'data:image/jpeg;base64,IMAGEDATA' } }], }, ], }; assert.strictEqual(extractText(request), ''); }); it('returns an empty string if there are no messages', () => { const request: GenerateRequest = { messages: [], }; assert.strictEqual(extractText(request), ''); }); }); describe('extractMimeType', () => { it('extracts from data URL with base64', () => { assert.strictEqual( extractMimeType('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA...'), 'image/png' ); assert.strictEqual( extractMimeType('data:application/pdf;base64,JVBERi0xLjQKJ...'), 'application/pdf' ); }); it('returns empty string for invalid data URL format', () => { assert.strictEqual(extractMimeType('data:image/png'), ''); assert.strictEqual(extractMimeType('data:,text'), ''); }); it('extracts from known file extensions', () => { assert.strictEqual(extractMimeType('image.jpg'), 'image/jpeg'); assert.strictEqual(extractMimeType('path/to/document.png'), 'image/png'); assert.strictEqual(extractMimeType('video.mp4'), 'video/mp4'); }); it('returns empty string for unknown file extensions', () => { assert.strictEqual(extractMimeType('file.unknown'), ''); assert.strictEqual(extractMimeType('archive.zip'), ''); }); it('returns empty string for URL without extension', () => { assert.strictEqual(extractMimeType('http://example.com/image'), ''); }); it('returns empty string for undefined or empty input', () => { assert.strictEqual(extractMimeType(undefined), ''); assert.strictEqual(extractMimeType(''), ''); }); }); describe('checkSupportedMimeType', () => { const supported = ['image/jpeg', 'image/png']; it('should not throw for supported mime types', () => { assert.doesNotThrow(() => checkSupportedMimeType( { url: 'test.jpg', contentType: 'image/jpeg' }, supported ) ); assert.doesNotThrow(() => checkSupportedMimeType( { url: 'test.png', contentType: 'image/png' }, supported ) ); }); it('should throw GenkitError for unsupported mime types', () => { try { checkSupportedMimeType( { url: 'test.gif', contentType: 'image/gif' }, supported ); assert.fail('Should have thrown'); } catch (e: any) { assert.ok(e instanceof GenkitError, 'Expected GenkitError'); assert.strictEqual(e.status, 'INVALID_ARGUMENT'); assert.ok( e.message.includes('Invalid mimeType for test.gif: "image/gif"') ); assert.ok( e.message.includes('Supported mimeTypes: image/jpeg, image/png') ); } }); it('should throw GenkitError if contentType is missing', () => { try { checkSupportedMimeType({ url: 'test.jpg' }, supported); assert.fail('Should have thrown'); } catch (e: any) { assert.ok(e instanceof GenkitError, 'Expected GenkitError'); assert.strictEqual(e.status, 'INVALID_ARGUMENT'); assert.ok( e.message.includes('Invalid mimeType for test.jpg: "undefined"') ); } }); }); describe('displayUrl', () => { it('should return the full URL if short', () => { const url = 'http://example.com/short'; assert.strictEqual(displayUrl(url), url); }); it('should truncate long URLs', () => { const longUrl = 'http://example.com/this/is/a/very/long/url/that/needs/truncation/to/fit'; const expected = 'http://example.com/this/i...t/needs/truncation/to/fit'; assert.strictEqual(displayUrl(longUrl), expected); }); it('should handle URLs exactly at the limit', () => { const url = 'a'.repeat(50); assert.strictEqual(displayUrl(url), url); }); }); describe('extractMedia', () => { const imageMedia = { url: 'data:image/png;base64,IMAGEDATA', contentType: 'image/png', }; const videoMedia = { url: 'data:video/mp4;base64,VIDEODATA', contentType: 'video/mp4', }; it('extracts any media from the last message if no params', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [{ text: 'A ' }, { media: imageMedia }] }, ], }; assert.deepStrictEqual(extractMedia(request, {}), imageMedia); }); it('extracts media matching metadataType', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [ { media: imageMedia, metadata: { type: 'image' } }, { media: videoMedia, metadata: { type: 'video' } }, ], }, ], }; assert.deepStrictEqual( extractMedia(request, { metadataType: 'video' }), videoMedia ); assert.deepStrictEqual( extractMedia(request, { metadataType: 'image' }), imageMedia ); }); it('extracts media with no metadata type if isDefault is true', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [ { media: imageMedia }, { media: videoMedia, metadata: { type: 'video' } }, ], }, ], }; assert.deepStrictEqual( extractMedia(request, { metadataType: 'image', isDefault: true }), imageMedia ); }); it('does not extract media with different metadataType even if isDefault is true', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [{ media: videoMedia, metadata: { type: 'video' } }], }, ], }; assert.strictEqual( extractMedia(request, { metadataType: 'image', isDefault: true }), undefined ); }); it('returns undefined if no media matches metadataType', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [{ media: imageMedia, metadata: { type: 'image' } }], }, ], }; assert.strictEqual( extractMedia(request, { metadataType: 'video' }), undefined ); }); it('infers contentType if missing', () => { const request: GenerateRequest = { messages: [ { role: 'user', content: [{ media: { url: 'data:image/jpeg;base64,DATA' } }], }, ], }; const result = extractMedia(request, {}); assert.deepStrictEqual(result, { url: 'data:image/jpeg;base64,DATA', contentType: 'image/jpeg', }); }); it('returns undefined if no media parts in the last message', () => { const request: GenerateRequest = { messages: [{ role: 'user', content: [{ text: 'No media' }] }], }; assert.strictEqual(extractMedia(request, {}), undefined); }); it('returns undefined for empty messages array', () => { const request: GenerateRequest = { messages: [] }; assert.strictEqual(extractMedia(request, {}), undefined); }); }); describe('cleanSchema', () => { it('strips $schema and additionalProperties', () => { const schema = { type: 'object', properties: { name: { type: 'string' } }, $schema: 'http://json-schema.org/draft-07/schema#', additionalProperties: false, }; const cleaned = cleanSchema(schema); assert.deepStrictEqual(cleaned, { type: 'object', properties: { name: { type: 'string' } }, }); }); it('handles nested objects', () => { const schema = { type: 'object', properties: { user: { type: 'object', properties: { id: { type: 'number' } }, additionalProperties: true, }, }, }; const cleaned = cleanSchema(schema); assert.deepStrictEqual(cleaned, { type: 'object', properties: { user: { type: 'object', properties: { id: { type: 'number' } }, }, }, }); }); it('converts type ["string", "null"] to "string"', () => { const schema = { type: 'object', properties: { name: { type: ['string', 'null'] }, age: { type: ['number', 'null'] }, }, }; const cleaned = cleanSchema(schema); assert.deepStrictEqual(cleaned, { type: 'object', properties: { name: { type: 'string' }, age: { type: 'number' }, }, }); }); it('converts type ["null", "boolean"] to "boolean"', () => { const schema = { type: 'object', properties: { isActive: { type: ['null', 'boolean'] }, }, }; const cleaned = cleanSchema(schema); assert.deepStrictEqual(cleaned, { type: 'object', properties: { isActive: { type: 'boolean' }, }, }); }); it('leaves other properties untouched', () => { const schema = { type: 'string', description: 'A name', maxLength: 100, }; const cleaned = cleanSchema(schema); assert.deepStrictEqual(cleaned, schema); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/firebase/genkit'

If you have feedback or need assistance with the MCP directory API, please join our Discord server