Skip to main content
Glama

MCP Server

libs.test.ts16.8 kB
import { assert } from 'chai' import { describe, it } from 'mocha' import { annotatedFunction, createErrorObject, CrossLayerProps, } from '@node-in-layers/core' import z from 'zod' import { commonMcpExecute, createMcpResponse, nilAnnotatedFunctionToOpenApi, zodToJson, } from '../../src/libs.js' const errorObjectJson = { type: 'object', additionalProperties: false, properties: { error: { type: 'object', additionalProperties: false, properties: { cause: {}, code: { type: 'string' }, data: { type: 'object', additionalProperties: {} }, details: { type: 'string' }, message: { type: 'string' }, trace: { type: 'string' }, }, required: ['code', 'message'], }, }, required: ['error'], } describe('/src/libs.ts', () => { describe('#commonMcpExecute()', () => { it('should return the same response if its already an MCP response', async () => { const fn = () => Promise.resolve(createMcpResponse({})) const actual = await commonMcpExecute(fn)() const expected = { content: [{ type: 'text', text: '{}' }], } // @ts-ignore assert.deepEqual(actual, expected) }) it('should format properly format a response when its just an object', async () => { const fn = () => Promise.resolve({}) const actual = await commonMcpExecute(fn)() const expected = { content: [{ type: 'text', text: '{}' }], } // @ts-ignore assert.deepEqual(actual, expected) }) it('should format properly format a response when its an error object', async () => { const fn = () => Promise.resolve(createErrorObject('TEST_ERROR', 'Test error')) const actual = await commonMcpExecute(fn)() const expected = { isError: true, content: [ { type: 'text', text: '{"error":{"code":"TEST_ERROR","message":"Test error"}}', }, ], } // @ts-ignore assert.deepEqual(actual, expected) }) it('should format properly format a response when its an error object with a cause', async () => { const fn = () => Promise.resolve( createErrorObject('TEST_ERROR', 'Test error', new Error('Test cause')) ) const actual = await commonMcpExecute(fn)() const expected = { isError: true, content: [ { type: 'text', text: '{"error":{"code":"TEST_ERROR","message":"Test error","details":"Test cause","errorDetails":"Error: Test cause"}}', }, ], } // @ts-ignore assert.deepEqual(actual, expected) }) it('should properly format if there is an exception thrown', async () => { const fn = () => Promise.reject(new Error('Test exception')) const actual = await commonMcpExecute(fn)() const expected = { isError: true, content: [ { type: 'text', text: '{"error":{"code":"UNCAUGHT_EXCEPTION","message":"An uncaught exception occurred while executing the feature."}}', }, ], } }) it('should properly format if there is an exception thrown', async () => { const fn = () => Promise.reject(new Error('Test exception')) const actual = await commonMcpExecute(fn)() const expected = { isError: true, content: [ { type: 'text', text: '{"error":{"code":"UNCAUGHT_EXCEPTION","message":"An uncaught exception occurred while executing the feature.","details":"Test exception","errorDetails":"Error: Test exception"}}', }, ], } // @ts-ignore assert.deepEqual(actual, expected) }) }) describe('#nilAnnotatedFunctionToOpenApi()', () => { it('should convert a realworld function to an OpenAPI function description', () => { const myFunc = annotatedFunction( { description: 'A description to convert', args: z.object({ organizationId: z.string(), from: z.string().optional(), to: z.string().optional(), daysBack: z.number().optional(), }), }, async (params, crossLayerProps?: CrossLayerProps) => { return } ) const actual = nilAnnotatedFunctionToOpenApi('myFunc', myFunc) const expected = { name: 'myFunc', description: 'A description to convert', input: { type: 'object', additionalProperties: false, properties: { args: { type: 'object', additionalProperties: false, properties: { organizationId: { type: 'string' }, from: { type: 'string' }, to: { type: 'string' }, daysBack: { type: 'number' }, }, required: ['organizationId'], }, crossLayerProps: { type: 'object', additionalProperties: true, properties: { logging: { type: 'object', additionalProperties: true, properties: { ids: { type: 'array', items: { type: 'object', additionalProperties: { type: 'string' }, }, }, }, }, }, }, }, required: ['args'], }, output: { anyOf: [{ type: 'null' }, errorObjectJson] }, } assert.deepEqual(actual, expected) }) it('should convert a nil annotated function to an OpenAPI function description', () => { const fn = annotatedFunction( { description: 'Hello World', args: z.object({ name: z.string(), }), returns: z.object({ out: z.string(), }), }, (args: { name: string }) => ({ out: `Hello ${args.name}`, }) ) const openApi = nilAnnotatedFunctionToOpenApi('hello', fn) const expected = { name: 'hello', description: 'Hello World', input: { type: 'object', additionalProperties: false, properties: { args: { type: 'object', additionalProperties: false, properties: { name: { type: 'string' }, }, required: ['name'], }, crossLayerProps: { type: 'object', additionalProperties: true, properties: { logging: { type: 'object', additionalProperties: true, properties: { ids: { type: 'array', items: { type: 'object', additionalProperties: { type: 'string' }, }, }, }, }, }, }, }, required: ['args'], }, output: { anyOf: [ { type: 'object', additionalProperties: false, properties: { out: { type: 'string' } }, required: ['out'], }, errorObjectJson, ], }, } assert.deepEqual(openApi, expected) }) it('should convert complex inputs and outputs for nil annotated functions', () => { const fn = annotatedFunction( { description: 'Hello World', args: z .object({ innerObj: z .object({ name: z.string(), }) .describe('This is a fully loaded props object'), innerArray: z .array(z.string()) .optional() .describe('Another argument'), innerEnum: z.enum(['a', 'b', 'c']), innerLiteral: z.literal('a'), innerNumber: z.number().describe('A number'), preferences: z .object({ theme: z .enum(['light', 'dark', 'system']) .describe('Preferred application theme'), notifications: z .object({ marketing: z .boolean() .describe('Receives marketing emails'), alerts: z .boolean() .optional() .describe('Receives alert emails'), }) .describe('Notification preferences'), }) .describe('Application preferences'), tags: z .array(z.string()) .optional() .describe('User-defined tags'), metadata: z .record(z.string(), z.string()) .optional() .describe('Freeform metadata'), status: z.literal('active').describe('Current account status'), age: z.number().optional().describe('Age in years'), }) .describe('This is a fully loaded props object'), returns: z.object({ complex: z.object({ innerObj: z.object({ name: z.string(), innerArray: z.array(z.string()), innerEnum: z.enum(['a', 'b', 'c']), innerLiteral: z.literal('a'), innerNumber: z.number(), }), }), }), }, args => ({ complex: { innerObj: { name: 'The name', innerArray: ['a', 'b', 'c'], innerEnum: 'a', innerLiteral: 'a', innerNumber: 1, }, }, }) ) const actual = nilAnnotatedFunctionToOpenApi('hello', fn) const expected = { name: 'hello', description: 'Hello World', input: { type: 'object', additionalProperties: false, properties: { args: { type: 'object', description: 'This is a fully loaded props object', additionalProperties: false, properties: { innerObj: { type: 'object', description: 'This is a fully loaded props object', additionalProperties: false, properties: { name: { type: 'string' } }, required: ['name'], }, innerArray: { type: 'array', items: { type: 'string' }, description: 'Another argument', }, innerEnum: { type: 'string', enum: ['a', 'b', 'c'] }, innerLiteral: { type: 'string', const: 'a' }, innerNumber: { type: 'number', description: 'A number' }, preferences: { type: 'object', description: 'Application preferences', additionalProperties: false, properties: { theme: { type: 'string', enum: ['light', 'dark', 'system'], description: 'Preferred application theme', }, notifications: { type: 'object', description: 'Notification preferences', additionalProperties: false, properties: { marketing: { type: 'boolean', description: 'Receives marketing emails', }, alerts: { type: 'boolean', description: 'Receives alert emails', }, }, required: ['marketing'], }, }, required: ['theme', 'notifications'], }, tags: { type: 'array', items: { type: 'string' }, description: 'User-defined tags', }, metadata: { type: 'object', additionalProperties: { type: 'string' }, description: 'Freeform metadata', }, status: { type: 'string', const: 'active', description: 'Current account status', }, age: { type: 'number', description: 'Age in years' }, }, required: [ 'innerObj', 'innerEnum', 'innerLiteral', 'innerNumber', 'preferences', 'status', ], }, crossLayerProps: { type: 'object', additionalProperties: true, properties: { logging: { type: 'object', additionalProperties: true, properties: { ids: { type: 'array', items: { type: 'object', additionalProperties: { type: 'string' }, }, }, }, }, }, }, }, required: ['args'], }, output: { anyOf: [ { type: 'object', additionalProperties: false, properties: { complex: { type: 'object', additionalProperties: false, properties: { innerObj: { type: 'object', additionalProperties: false, properties: { name: { type: 'string' }, innerArray: { type: 'array', items: { type: 'string' }, }, innerEnum: { type: 'string', enum: ['a', 'b', 'c'] }, innerLiteral: { type: 'string', const: 'a' }, innerNumber: { type: 'number' }, }, required: [ 'name', 'innerArray', 'innerEnum', 'innerLiteral', 'innerNumber', ], }, }, required: ['innerObj'], }, }, required: ['complex'], }, errorObjectJson, ], }, } assert.deepEqual(actual, expected) }) it('should handle empty args object and undefined output', () => { const fn = annotatedFunction( { description: 'No-op function', args: z.object({}), }, () => undefined ) const actual = nilAnnotatedFunctionToOpenApi('noop', fn) const expected = { name: 'noop', description: 'No-op function', input: { type: 'object', additionalProperties: false, properties: { args: { type: 'object', additionalProperties: false, properties: {}, }, crossLayerProps: { type: 'object', additionalProperties: true, properties: { logging: { type: 'object', additionalProperties: true, properties: { ids: { type: 'array', items: { type: 'object', additionalProperties: { type: 'string' }, }, }, }, }, }, }, }, required: ['args'], }, output: { anyOf: [{ type: 'null' }, errorObjectJson] }, } assert.deepEqual(actual, expected) }) }) })

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/Node-In-Layers/mcp-server'

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