MCP Terminal Server

/** * Copyright 2024 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 { beforeEach, describe, it } from 'node:test'; import { action, defineAction, runInActionRuntimeContext, } from '../src/action.js'; import { Registry } from '../src/registry.js'; describe('registry class', () => { var registry: Registry; beforeEach(() => { registry = new Registry(); }); describe('listActions', () => { it('returns all registered actions', async () => { const fooSomethingAction = action( registry, { name: 'foo_something', actionType: 'util' }, async () => null ); registry.registerAction('model', fooSomethingAction); const barSomethingAction = action( registry, { name: 'bar_something', actionType: 'util' }, async () => null ); registry.registerAction('model', barSomethingAction); assert.deepEqual(await registry.listActions(), { '/model/foo_something': fooSomethingAction, '/model/bar_something': barSomethingAction, }); }); it('returns all registered actions by plugins', async () => { registry.registerPluginProvider('foo', { name: 'foo', async initializer() { registry.registerAction('model', fooSomethingAction); return {}; }, }); const fooSomethingAction = action( registry, { name: { pluginId: 'foo', actionId: 'something', }, actionType: 'util', }, async () => null ); registry.registerPluginProvider('bar', { name: 'bar', async initializer() { registry.registerAction('model', barSomethingAction); registry.registerAction('model', barSubSomethingAction); return {}; }, }); const barSomethingAction = action( registry, { name: { pluginId: 'bar', actionId: 'something', }, actionType: 'util', }, async () => null ); const barSubSomethingAction = action( registry, { name: { pluginId: 'bar', actionId: 'sub/something', }, actionType: 'util', }, async () => null ); assert.deepEqual(await registry.listActions(), { '/model/foo/something': fooSomethingAction, '/model/bar/something': barSomethingAction, '/model/bar/sub/something': barSubSomethingAction, }); }); it('should allow plugin initialization from runtime context', async () => { let fooInitialized = false; registry.registerPluginProvider('foo', { name: 'foo', async initializer() { defineAction( registry, { actionType: 'model', name: 'foo/something', }, async () => null ); fooInitialized = true; return {}; }, }); const action = await runInActionRuntimeContext(registry, () => registry.lookupAction('/model/foo/something') ); assert.ok(action); assert.ok(fooInitialized); }); it('returns all registered actions, including parent', async () => { const child = Registry.withParent(registry); const fooSomethingAction = action( registry, { name: 'foo_something', actionType: 'util' }, async () => null ); registry.registerAction('model', fooSomethingAction); const barSomethingAction = action( registry, { name: 'bar_something', actionType: 'util' }, async () => null ); child.registerAction('model', barSomethingAction); assert.deepEqual(await child.listActions(), { '/model/foo_something': fooSomethingAction, '/model/bar_something': barSomethingAction, }); assert.deepEqual(await registry.listActions(), { '/model/foo_something': fooSomethingAction, }); }); }); describe('lookupAction', () => { it('initializes plugin for action first', async () => { let fooInitialized = false; registry.registerPluginProvider('foo', { name: 'foo', async initializer() { fooInitialized = true; return {}; }, }); let barInitialized = false; registry.registerPluginProvider('bar', { name: 'bar', async initializer() { barInitialized = true; return {}; }, }); await registry.lookupAction('/model/foo/something'); assert.strictEqual(fooInitialized, true); assert.strictEqual(barInitialized, false); await registry.lookupAction('/model/bar/something'); assert.strictEqual(fooInitialized, true); assert.strictEqual(barInitialized, true); }); it('returns registered action', async () => { const fooSomethingAction = action( registry, { name: 'foo_something', actionType: 'util' }, async () => null ); registry.registerAction('model', fooSomethingAction); const barSomethingAction = action( registry, { name: 'bar_something', actionType: 'util' }, async () => null ); registry.registerAction('model', barSomethingAction); const barSubSomethingAction = action( registry, { name: 'sub/bar_something', actionType: 'util' }, async () => null ); registry.registerAction('model', barSubSomethingAction); assert.strictEqual( await registry.lookupAction('/model/foo_something'), fooSomethingAction ); assert.strictEqual( await registry.lookupAction('/model/bar_something'), barSomethingAction ); assert.strictEqual( await registry.lookupAction('/model/sub/bar_something'), barSubSomethingAction ); }); it('returns action registered by plugin', async () => { registry.registerPluginProvider('foo', { name: 'foo', async initializer() { registry.registerAction('model', somethingAction); registry.registerAction('model', subSomethingAction); return {}; }, }); const somethingAction = action( registry, { name: { pluginId: 'foo', actionId: 'something', }, actionType: 'util', }, async () => null ); const subSomethingAction = action( registry, { name: { pluginId: 'foo', actionId: 'sub/something', }, actionType: 'util', }, async () => null ); assert.strictEqual( await registry.lookupAction('/model/foo/something'), somethingAction ); assert.strictEqual( await registry.lookupAction('/model/foo/sub/something'), subSomethingAction ); }); it('returns undefined for unknown action', async () => { assert.strictEqual( await registry.lookupAction('/model/foo/something'), undefined ); }); it('should lookup parent registry when child missing action', async () => { const childRegistry = new Registry(registry); const fooAction = action( registry, { name: 'foo', actionType: 'util' }, async () => null ); registry.registerAction('model', fooAction); assert.strictEqual(await registry.lookupAction('/model/foo'), fooAction); assert.strictEqual( await childRegistry.lookupAction('/model/foo'), fooAction ); }); it('registration on the child registry should not modify parent', async () => { const childRegistry = Registry.withParent(registry); assert.strictEqual(childRegistry.parent, registry); const fooAction = action( registry, { name: 'foo', actionType: 'util' }, async () => null ); childRegistry.registerAction('model', fooAction); assert.strictEqual(await registry.lookupAction('/model/foo'), undefined); assert.strictEqual( await childRegistry.lookupAction('/model/foo'), fooAction ); }); }); });