Repository: wrtnlabs/agentica
Pull request #337: feat(core): implement mcp interface and execute
Author: login: sunrabbit123
Labels: name: documentation
description: Improvements or additions to documentation
name: enhancement
description: New feature or request
Created: 2025-04-07T10:09:21Z | Merged: 2025-04-10T07:59:59Z

~~tommorow i will add test code and fix detail bugs~~ failed


This pull request includes several changes to the `packages/core` and `packages/benchmark` directories, focusing on adding support for a new protocol (`mcp`), updating dependencies, and enhancing the test suite.

### Support for MCP Protocol:
* [`packages/core/src/context/AgenticaOperation.ts`](diffhunk://#diff-6a2722e6d6012113ff3f18fe98e2e85c38d6865232e460da35954776731e808aL23-R25): Added the `Mcp` type to the `AgenticaOperation` union and defined the `Mcp` type in the `AgenticaOperation` namespace. [[1]](diffhunk://#diff-6a2722e6d6012113ff3f18fe98e2e85c38d6865232e460da35954776731e808aL23-R25) [[2]](diffhunk://#diff-6a2722e6d6012113ff3f18fe98e2e85c38d6865232e460da35954776731e808aR37-R44)
* [`packages/core/src/context/internal/AgenticaOperationComposer.ts`](diffhunk://#diff-291ac3f797c50895cb7a5bdc53d01f2ba5572980796f54d9daef191246b55c17L90-R153): Refactored the `compose` function to handle `mcp` protocol operations and added helper functions for `mcp` operations.
* [`packages/core/src/functional/assertMcpLlmApplication.ts`](diffhunk://#diff-0289f515f9c47c5638f62937ec2d6c4a2c4cc5f7ffdd149717e891bdfb6aa714R1-R50): Added a new function `assertMcpLlmApplication` to create an MCP LLM application instance with type assertion.

### Dependency Updates:
* [`packages/benchmark/package.json`](diffhunk://#diff-03d34ead8faa24fcf5b6d74b52eaf57db4400f375b60698e3f5024e28b29b0e1R48-R50): Added `@agentica/core` to `peerDependencies`.
* [`packages/core/package.json`](diffhunk://#diff-0b810c38f3c138a3d5e44854edefd5eb966617ca84e62f06511f60acc40546c7L51-R78): Updated `peerDependencies` and `devDependencies` to use catalog references and added `vitest` for testing.

### Test Suite Enhancements:
* [`packages/core/src/context/internal/AgenticaOperationComposer.spec.ts`](diffhunk://#diff-a5be44fc10cc0673b4a307cb278d0e881ba130ad9ead085ca1970c9d54173adaR1-R318): Added comprehensive tests for the `AgenticaOperationComposer` including tests for `compose`, `getOperations`, `toHttpOperations`, `toClassOperations`, `toMcpOperations`, and `divide` functions.

### Miscellaneous Changes:
* [`packages/core/eslint.config.mts`](diffhunk://#diff-f9d3f725f675c24b0db67c4d6eebad922f6cac8e446304716a6aa414505acaeaL4-R4): Updated the `ignores` list to include `vitest.config.mts`.
* [`packages/core/src/index.ts`](diffhunk://#diff-9a4ceebe7c6f86856371906c3f061d3b56b7457022b05179884a113e7ced67e8R22-R28): Added exports for `assertMcpLlmApplication` and reordered some export statements for better organization.

These changes collectively enhance the functionality and maintainability of the codebase, particularly by introducing support for the new `mcp` protocol and improving the test coverage.


Diff:
diff --git a/packages/benchmark/package.json b/packages/benchmark/package.json
index 0e37a93494..9ee72f8f2d 100644
--- a/packages/benchmark/package.json
+++ b/packages/benchmark/package.json
@@ -45,6 +45,9 @@
     "lint": "eslint .",
     "lint:fix": "eslint --fix ."
   },
+  "peerDependencies": {
+    "@agentica/core": "workspace:^"
+  },
   "dependencies": {
     "@agentica/core": "workspace:^",
     "@samchon/openapi": "catalog:typia",
diff --git a/packages/core/eslint.config.mts b/packages/core/eslint.config.mts
index 0b2d37e704..be113655b1 100644
--- a/packages/core/eslint.config.mts
+++ b/packages/core/eslint.config.mts
@@ -1,5 +1,5 @@
 import { wrtnlabs } from "@wrtnlabs/eslint-config";
 
 export default wrtnlabs({
-  ignores: ["eslint.config.mts","lib"],
+  ignores: ["eslint.config.mts","lib", "vitest.config.mts"],
 });
diff --git a/packages/core/package.json b/packages/core/package.json
index 3f347e1fc0..60f8959a05 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -39,7 +39,8 @@
     "dev": "rimraf lib && tsc --watch",
     "prepack": "pnpm run build",
     "lint": "eslint .",
-    "format": "eslint --fix ."
+    "format": "eslint --fix .",
+    "test": "vitest"
   },
   "publishConfig": {
     "main": "lib/index.js",
@@ -48,9 +49,10 @@
     "access": "public"
   },
   "peerDependencies": {
-    "@samchon/openapi": ">=4.0.0 <5.0.0",
-    "openai": ">=4.80.0",
-    "typia": ">=9.0.1 <10.0.0"
+    "@modelcontextprotocol/sdk": "catalog:libs",
+    "@samchon/openapi": "catalog:typia",
+    "openai": "catalog:libs",
+    "typia": "catalog:typia"
   },
   "dependencies": {
     "@samchon/openapi": "catalog:typia",
@@ -58,9 +60,11 @@
     "uuid": "^11.0.4"
   },
   "devDependencies": {
+    "@modelcontextprotocol/sdk": "catalog:libs",
     "@nestia/e2e": "^6.0.1",
     "@rollup/plugin-terser": "^0.4.4",
     "@rollup/plugin-typescript": "^12.1.2",
+    "@ryoppippi/unplugin-typia": "catalog:typia",
     "@types/node": "^22.13.4",
     "@types/uuid": "^10.0.0",
     "openai": "catalog:libs",
@@ -69,6 +73,7 @@
     "ts-node": "^10.9.2",
     "ts-patch": "catalog:typescript",
     "typedoc": "^0.27.7",
-    "typescript": "catalog:typescript"
+    "typescript": "catalog:typescript",
+    "vitest": "catalog:vite"
   }
 }
diff --git a/packages/core/src/context/AgenticaOperation.ts b/packages/core/src/context/AgenticaOperation.ts
index 5bc2879c58..e313b38a39 100644
--- a/packages/core/src/context/AgenticaOperation.ts
+++ b/packages/core/src/context/AgenticaOperation.ts
@@ -2,6 +2,7 @@ import type { IHttpLlmFunction, ILlmFunction, ILlmSchema } from "@samchon/openap
 
 import type { IAgenticaOperationJson } from "../json/IAgenticaOperationJson";
 import type { IAgenticaController } from "../structures/IAgenticaController";
+import type { IMcpLlmFunction } from "../structures/mcp/IMcpLlmFunction";
 
 /**
  * Operation information in the Agentica Agent.
@@ -20,7 +21,8 @@ import type { IAgenticaController } from "../structures/IAgenticaController";
  */
 export type AgenticaOperation<Model extends ILlmSchema.Model> =
   | AgenticaOperation.Class<Model>
-  | AgenticaOperation.Http<Model>;
+  | AgenticaOperation.Http<Model>
+  | AgenticaOperation.Mcp;
 export namespace AgenticaOperation {
   export type Class<Model extends ILlmSchema.Model> = Base<
     "class",
@@ -32,9 +34,14 @@ export namespace AgenticaOperation {
     IAgenticaController.IHttp<Model>,
     IHttpLlmFunction<Model>
   >;
+  export type Mcp = Base<
+    "mcp",
+    IAgenticaController.IMcp,
+    IMcpLlmFunction
+  >;
 
   interface Base<
-    Protocol extends "http" | "class",
+    Protocol extends "http" | "class" | "mcp",
     Controller extends object,
     Function extends object,
   > {
diff --git a/packages/core/src/context/internal/AgenticaOperationComposer.spec.ts b/packages/core/src/context/internal/AgenticaOperationComposer.spec.ts
new file mode 100644
index 0000000000..c70159a7bf
--- /dev/null
+++ b/packages/core/src/context/internal/AgenticaOperationComposer.spec.ts
@@ -0,0 +1,314 @@
+import type { IHttpLlmFunction, ILlmFunction, IValidation } from "@samchon/openapi";
+
+import type { IAgenticaConfig } from "../../structures/IAgenticaConfig";
+import type { IAgenticaController } from "../../structures/IAgenticaController";
+import type { IMcpLlmFunction } from "../../structures/mcp/IMcpLlmFunction";
+
+import { compose, divide, getOperations, toClassOperations, toHttpOperations, toMcpOperations } from "./AgenticaOperationComposer";
+
+// test helper functions
+function createMockHttpFunction(name: string, method: "get" | "post" | "patch" | "put" | "delete", path: string): IHttpLlmFunction<any> {
+  return {
+    name,
+    method,
+    path,
+    validate: () => ({ success: true, data: {} } as IValidation<unknown>),
+    operation: () => ({}),
+    route: () => ({
+      method,
+      path,
+      emendedPath: path,
+      accessor: [name],
+      body: null,
+      query: null,
+      parameters: [],
+      headers: null,
+      success: null,
+      exceptions: {},
+      comment: () => "OK",
+      operation: () => ({}),
+    }),
+    parameters: {},
+    output: {},
+  };
+}
+
+function createMockHttpController(name: string, functions: IHttpLlmFunction<any>[]): IAgenticaController.IHttp<any> {
+  return {
+    name,
+    protocol: "http",
+    connection: { host: "https://example.com" },
+    application: {
+      model: "chatgpt",
+      options: {},
+      functions,
+      errors: [],
+    },
+  };
+}
+
+function createMockClassController(name: string, functions: ILlmFunction<any>[]): IAgenticaController.IClass<any> {
+  return {
+    name,
+    protocol: "class",
+    application: {
+      model: "chatgpt",
+      options: {},
+      functions,
+    },
+    execute: {},
+  };
+}
+
+function createMockMcpController(name: string, functions: IMcpLlmFunction[]): IAgenticaController.IMcp {
+  return {
+    name,
+    protocol: "mcp",
+    application: {
+      transport: {
+        type: "sse",
+        url: new URL("https://example.com"),
+      },
+      functions,
+    },
+  };
+}
+
+describe("a AgenticaOperationComposer", () => {
+  describe("compose", () => {
+    it("should compose operations from controllers", () => {
+      // Mock controllers
+      const mockHttpController = createMockHttpController("httpController", [
+        createMockHttpFunction("function1", "get", "/api/function1"),
+        createMockHttpFunction("function2", "post", "/api/function2"),
+      ]);
+
+      const mockClassController = createMockClassController("classController", [
+        {
+          name: "function3",
+          validate: () => ({ success: true, data: {} } as IValidation<unknown>),
+          parameters: {},
+          output: {},
+        },
+      ]);
+
+      const mockMcpController = createMockMcpController("mcpController", [
+        {
+          name: "function4",
+          parameters: {},
+        },
+      ]);
+
+      const controllers = [mockHttpController, mockClassController, mockMcpController];
+
+      const result = compose({ controllers });
+
+      expect(result.array).toHaveLength(4);
+      expect(result.flat).toBeInstanceOf(Map);
+      expect(result.group).toBeInstanceOf(Map);
+      expect(result.divided).toBeUndefined();
+    });
+
+    it("should divide operations when capacity is provided", () => {
+      // Mock controllers
+      const mockController = createMockHttpController("httpController", [
+        createMockHttpFunction("function1", "get", "/api/function1"),
+        createMockHttpFunction("function2", "post", "/api/function2"),
+        createMockHttpFunction("function3", "put", "/api/function3"),
+        createMockHttpFunction("function4", "delete", "/api/function4"),
+        createMockHttpFunction("function5", "patch", "/api/function5"),
+      ]);
+
+      const config: IAgenticaConfig<any> = {
+        capacity: 2,
+      };
+
+      const result = compose({ controllers: [mockController], config });
+
+      expect(result.array).toHaveLength(5);
+      expect(result.divided).toBeDefined();
+      expect(result.divided).toHaveLength(3); // 5 items with capacity 2 should be divided into 3 groups
+    });
+  });
+
+  describe("getOperations", () => {
+    it("should get operations from http controllers", () => {
+      const mockController = createMockHttpController("httpController", [
+        createMockHttpFunction("function1", "get", "/api/function1"),
+        createMockHttpFunction("function2", "post", "/api/function2"),
+      ]);
+
+      const result = getOperations({ controllers: [mockController], naming: (func, idx) => `_${idx}_${func}` });
+
+      expect(result).toHaveLength(2);
+      expect(result[0]?.protocol).toBe("http");
+      expect(result[0]?.name).toBe("_0_function1");
+      expect(result[1]?.name).toBe("_0_function2");
+    });
+
+    it("should get operations from class controllers", () => {
+      const mockController = createMockClassController("classController", [
+        {
+          name: "function1",
+          validate: () => ({ success: true, data: {} } as IValidation<unknown>),
+          parameters: {},
+          output: {},
+        },
+      ]);
+
+      const result = getOperations({ controllers: [mockController], naming: (func, idx) => `_${idx}_${func}` });
+
+      expect(result).toHaveLength(1);
+      expect(result[0]?.protocol).toBe("class");
+      expect(result[0]?.name).toBe("_0_function1");
+    });
+
+    it("should get operations from mcp controllers", () => {
+      const mockController = createMockMcpController("mcpController", [
+        {
+          name: "function1",
+          parameters: {},
+        },
+      ]);
+
+      const result = getOperations({ controllers: [mockController], naming: (func, idx) => `_${idx}_${func}` });
+
+      expect(result).toHaveLength(1);
+      expect(result[0]?.protocol).toBe("mcp");
+      expect(result[0]?.name).toBe("_0_function1");
+    });
+
+    it("should throw error for unsupported protocol", () => {
+      const mockController: IAgenticaController.IHttp<any> = {
+        name: "unsupportedController",
+        protocol: "unsupported" as unknown as "http",
+        connection: { host: "https://example.com" },
+        application: { } as unknown as IAgenticaController.IHttp<any>["application"],
+      };
+
+      expect(() => getOperations({ controllers: [mockController], naming: (func, idx) => `_${idx}_${func}` })).toThrow("Unsupported protocol: unsupported");
+    });
+  });
+
+  describe("toHttpOperations", () => {
+    it("should convert http controller to operations", () => {
+      const mockController = createMockHttpController("httpController", [
+        createMockHttpFunction("function1", "get", "/api/function1"),
+        createMockHttpFunction("function2", "post", "/api/function2"),
+      ]);
+
+      const result = toHttpOperations({ controller: mockController, index: 0, naming: (func, idx) => `_${idx}_${func}` });
+
+      expect(result).toHaveLength(2);
+      expect(result[0]?.protocol).toBe("http");
+      expect(result[0]?.name).toBe("_0_function1");
+      expect(result[1]?.name).toBe("_0_function2");
+    });
+  });
+
+  describe("toClassOperations", () => {
+    it("should convert class controller to operations", () => {
+      const mockController = createMockClassController("classController", [
+        {
+          name: "function1",
+          validate: () => ({ success: true, data: {} } as IValidation<unknown>),
+          parameters: {},
+          output: {},
+        },
+      ]);
+
+      const result = toClassOperations({ controller: mockController, index: 0, naming: (func, idx) => `_${idx}_${func}` });
+
+      expect(result).toHaveLength(1);
+      expect(result[0]?.protocol).toBe("class");
+      expect(result[0]?.name).toBe("_0_function1");
+    });
+  });
+
+  describe("toMcpOperations", () => {
+    it("should convert mcp controller to operations", () => {
+      const mockController = createMockMcpController("mcpController", [
+        {
+          name: "function1",
+          parameters: {},
+        },
+      ]);
+
+      const result = toMcpOperations({ controller: mockController, index: 0, naming: (func, idx) => `_${idx}_${func}` });
+
+      expect(result).toHaveLength(1);
+      expect(result[0]?.protocol).toBe("mcp");
+      expect(result[0]?.name).toBe("_0_function1");
+    });
+  });
+  describe("divide with invalid capacity", () => {
+    it("should throw error when capacity is 0", () => {
+      const array = [1, 2, 3, 4, 5];
+      const capacity = 0;
+
+      expect(() => divide({ array, capacity })).toThrow("Capacity must be a positive integer");
+    });
+
+    it("should throw error when capacity is negative", () => {
+      const array = [1, 2, 3, 4, 5];
+      const capacity = -3;
+
+      expect(() => divide({ array, capacity })).toThrow("Capacity must be a positive integer");
+    });
+
+    it("should throw error when capacity is decimal", () => {
+      const array = [1, 2, 3, 4, 5];
+      const capacity = 2.5;
+      const result = divide({ array, capacity });
+      expect(result).toEqual([[1, 2, 3], [4, 5]]);
+    });
+
+    it("should throw error when capacity is Infinity", () => {
+      const array = [1, 2, 3, 4, 5];
+      const capacity = Infinity;
+
+      expect(() => divide({ array, capacity })).toThrow("Capacity must be a positive integer");
+    });
+
+    it("should throw error when capacity is NaN", () => {
+      const array = [1, 2, 3, 4, 5];
+      const capacity = Number.NaN;
+
+      expect(() => divide({ array, capacity })).toThrow("Capacity must be a positive integer");
+    });
+  });
+
+  describe("divide", () => {
+    it("should divide array into chunks based on capacity", () => {
+      const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+      const capacity = 3;
+
+      const result = divide({ array, capacity });
+
+      expect(result).toHaveLength(4); // 10 items with capacity 3 should be divided into 4 groups
+      expect(result[0]).toEqual([1, 2, 3]);
+      expect(result[1]).toEqual([4, 5, 6]);
+      expect(result[2]).toEqual([7, 8, 9]);
+      expect(result[3]).toEqual([10]);
+    });
+
+    it("should handle empty array", () => {
+      const array: number[] = [];
+      const capacity = 3;
+
+      const result = divide({ array, capacity });
+
+      expect(result).toHaveLength(0);
+    });
+
+    it("should handle array smaller than capacity", () => {
+      const array = [1, 2];
+      const capacity = 3;
+
+      const result = divide({ array, capacity });
+
+      expect(result).toHaveLength(1);
+      expect(result[0]).toEqual([1, 2]);
+    });
+  });
+});
diff --git a/packages/core/src/context/internal/AgenticaOperationComposer.ts b/packages/core/src/context/internal/AgenticaOperationComposer.ts
index ed14498427..230303b1a4 100644
--- a/packages/core/src/context/internal/AgenticaOperationComposer.ts
+++ b/packages/core/src/context/internal/AgenticaOperationComposer.ts
@@ -8,59 +8,27 @@ import type { AgenticaOperationCollection } from "../AgenticaOperationCollection
 
 import { __map_take } from "../../utils/__map_take";
 
+/**
+ * Compose the agentica operation collection.
+ *
+ * Compose the {@link AgenticaOperationCollection} from the given
+ * controllers and config.
+ *
+ * @internal
+ */
 export function compose<Model extends ILlmSchema.Model>(props: {
   controllers: IAgenticaController<Model>[];
   config?: IAgenticaConfig<Model> | IMicroAgenticaConfig<Model> | undefined;
 }): AgenticaOperationCollection<Model> {
-  const unique: boolean
-      = props.controllers.length === 1
-        || (() => {
-          const names: string[] = props.controllers
-            .map(controller =>
-              controller.application.functions.map(func => func.name),
-            )
-            .flat();
-          return new Set(names).size === names.length;
-        })();
-  const naming = (func: string, ci: number) =>
-    unique ? func : `_${ci}_${func}`;
-
-  const array: AgenticaOperation<Model>[] = props.controllers
-    .map((controller, ci) =>
-      controller.protocol === "http"
-        ? controller.application.functions.map(
-            func =>
-                ({
-                  protocol: "http",
-                  controller,
-                  function: func,
-                  name: naming(func.name, ci),
-                  toJSON: () => ({
-                    protocol: "http",
-                    controller: controller.name,
-                    function: func.name,
-                    name: naming(func.name, ci),
-                  }),
-                }) satisfies AgenticaOperation.Http<Model>,
-          )
-        : controller.application.functions.map(
-            func =>
-                ({
-                  protocol: "class",
-                  controller,
-                  function: func,
-                  name: naming(func.name, ci),
-                  toJSON: () => ({
-                    protocol: "class",
-                    controller: controller.name,
-                    function: func.name,
-                    name: naming(func.name, ci),
-                  }),
-                }) satisfies AgenticaOperation.Class<Model>,
-          ),
-    )
-    .flat();
+  const unique: boolean = (props.controllers.length === 1 || (() => {
+    const names = props.controllers.map(controllers => controllers.application.functions.map(func => func.name)).flat();
+    return new Set(names).size === names.length;
+  })());
 
+  const array: AgenticaOperation<Model>[] = getOperations({
+    controllers: props.controllers,
+    naming: (func: string, controllerIndex: number) => unique ? func : `_${controllerIndex}_${func}`,
+  });
   const capacity: number | undefined = (props.config as IAgenticaConfig<Model>)?.capacity;
   const divided: AgenticaOperation<Model>[][] | undefined
       = capacity !== undefined && array.length > capacity
@@ -87,10 +55,112 @@ export function compose<Model extends ILlmSchema.Model>(props: {
   };
 }
 
-function divide<T>(props: {
+/**
+ * @internal
+ */
+export function getOperations<Model extends ILlmSchema.Model>(props: {
+  controllers: IAgenticaController<Model>[];
+  naming: (func: string, controllerIndex: number) => string;
+}): AgenticaOperation<Model>[] {
+  return props.controllers.flatMap((controller, idx) => {
+    switch (controller.protocol) {
+      case "http":{
+        return toHttpOperations({ controller, index: idx, naming: props.naming }); }
+      case "class":{
+        return toClassOperations({ controller, index: idx, naming: props.naming }); }
+      case "mcp": {
+        return toMcpOperations({ controller, index: idx, naming: props.naming });
+      }
+      default:
+        controller satisfies never;
+        throw new Error(`Unsupported protocol: ${(controller as { protocol: string }).protocol}`);
+    }
+  });
+}
+
+/**
+ * @internal
+ */
+export function toHttpOperations<Model extends ILlmSchema.Model>(props: {
+  controller: IAgenticaController.IHttp<Model>;
+  index: number;
+  naming: (func: string, controllerIndex: number) => string;
+}): AgenticaOperation<Model>[] {
+  return props.controller.application.functions.map(func => ({
+    protocol: "http",
+    controller: props.controller,
+    function: func,
+    name: props.naming(func.name, props.index),
+    toJSON: () => ({
+      protocol: "http",
+      controller: props.controller.name,
+      function: func.name,
+      name: props.naming(func.name, props.index),
+    }),
+  }));
+}
+
+/**
+ * @internal
+ */
+export function toClassOperations<Model extends ILlmSchema.Model>(props: {
+  controller: IAgenticaController.IClass<Model>;
+  index: number;
+  naming: (func: string, controllerIndex: number) => string;
+}): AgenticaOperation<Model>[] {
+  return props.controller.application.functions.map(func => ({
+    protocol: "class",
+    controller: props.controller,
+    function: func,
+    name: props.naming(func.name, props.index),
+    toJSON: () => ({
+      protocol: "class",
+      controller: props.controller.name,
+      function: func.name,
+      name: props.naming(func.name, props.index),
+    }),
+  }));
+}
+
+/**
+ * @internal
+ */
+export function toMcpOperations<Model extends ILlmSchema.Model>(props: {
+  controller: IAgenticaController.IMcp;
+  index: number;
+  naming: (func: string, controllerIndex: number) => string;
+}): AgenticaOperation<Model>[] {
+  return props.controller.application.functions.map(func => ({
+    protocol: "mcp",
+    controller: props.controller,
+    function: func,
+    name: props.naming(func.name, props.index),
+    toJSON: () => ({
+      protocol: "mcp",
+      controller: props.controller.name,
+      function: func.name,
+      name: props.naming(func.name, props.index),
+    }),
+  }));
+}
+
+/**
+ * @internal
+ */
+export function divide<T>(props: {
   array: T[];
   capacity: number;
 }): T[][] {
+  if (props.capacity <= 0) {
+    throw new Error("Capacity must be a positive integer");
+  }
+  if (Number.isNaN(props.capacity)) {
+    throw new TypeError("Capacity must be a positive integer");
+  }
+  if (props.capacity === Infinity) {
+    throw new Error("Capacity must be a positive integer");
+  }
+
   const size: number = Math.ceil(props.array.length / props.capacity);
   const capacity: number = Math.ceil(props.array.length / size);
   const replica: T[] = props.array.slice();
diff --git a/packages/core/src/functional/assertMcpLlmApplication.ts b/packages/core/src/functional/assertMcpLlmApplication.ts
new file mode 100644
index 0000000000..ebeb0172f3
--- /dev/null
+++ b/packages/core/src/functional/assertMcpLlmApplication.ts
@@ -0,0 +1,48 @@
+import { Client } from "@modelcontextprotocol/sdk/client/index.js";
+import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
+import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
+import { ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
+
+import type { IMcpLlmApplication, IMcpLlmTransportProps } from "../structures/mcp";
+/**
+ * Create an MCP LLM application instance with type assertion.
+ *
+ * Create an {@link IMcpLlmApplication} instance which represents
+ * an MCP (Model Context Protocol) LLM application.
+ *
+ * @param props Properties to create the MCP LLM application instance
+ * @param props.name Name of the MCP implementation.
+ * @param props.url URL of the MCP server.
+ * @param props.version Describes version of an MCP implementation.
+ * @returns MCP LLM application instance
+ * @author Samchon
+ */
+export async function assertMcpLlmApplication(props: IMcpLlmTransportProps): Promise<IMcpLlmApplication> {
+  const client = new Client({
+    name: "get_tool_list",
+    version: "1.0.0",
+  });
+
+  const transport = (() => {
+    switch (props.type) {
+      case "sse":
+        return new SSEClientTransport(props.url);
+      case "stdio":
+        return new StdioClientTransport(props);
+      default:
+        props satisfies never;
+        throw new Error("Invalid transport type");
+    }
+  })();
+  await client.connect(transport);
+
+  const toolList = await client.request({ method: "tools/list" }, ListToolsResultSchema);
+  return {
+    functions: toolList.tools.map(tool => ({
+      name: tool.name,
+      description: tool.description,
+      parameters: tool.inputSchema,
+    })),
+    transport: props,
+  };
+}
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 67fd4b804a..5cf8e49638 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -6,9 +6,9 @@ export * from "./context/AgenticaOperation";
 export * from "./context/AgenticaOperationCollection";
 export * from "./context/AgenticaOperationSelection";
 export * from "./context/AgenticaTokenUsage";
+
 export * from "./events/AgenticaCallEvent";
 export * from "./events/AgenticaCancelEvent";
-
 export * from "./events/AgenticaDescribeEvent";
 export * from "./events/AgenticaEvent";
 export * from "./events/AgenticaEventSource";
@@ -19,10 +19,14 @@ export * from "./events/AgenticaSelectEvent";
 export * from "./events/AgenticaTextEvent";
 export * from "./events/AgenticaValidateEvent";
 export * from "./events/MicroAgenticaEvent";
+
 export * as factory from "./factory";
-export * from "./functional/assertHttpLlmApplication";
 
+export * from "./functional/assertHttpLlmApplication";
+export * from "./functional/assertMcpLlmApplication";
 export * from "./functional/validateHttpLlmApplication";
+// @TODO: implement validateMcpLlmApplication
+
 export * from "./histories/AgenticaCancelHistory";
 export * from "./histories/AgenticaDescribeHistory";
 export * from "./histories/AgenticaExecuteHistory";
diff --git a/packages/core/src/json/IAgenticaOperationJson.ts b/packages/core/src/json/IAgenticaOperationJson.ts
index 1b1dad3530..40092a7a15 100644
--- a/packages/core/src/json/IAgenticaOperationJson.ts
+++ b/packages/core/src/json/IAgenticaOperationJson.ts
@@ -17,7 +17,7 @@ export interface IAgenticaOperationJson {
   /**
    * Protocol discriminator.
    */
-  protocol: "class" | "http";
+  protocol: "class" | "http" | "mcp";
 
   /**
    * Belonged controller of the target function.
diff --git a/packages/core/src/orchestrate/call.ts b/packages/core/src/orchestrate/call.ts
index ba53631895..1479048c7f 100644
--- a/packages/core/src/orchestrate/call.ts
+++ b/packages/core/src/orchestrate/call.ts
@@ -73,16 +73,18 @@ export async function call<Model extends ILlmSchema.Model>(
           function: {
             name: s.name,
             description: s.function.description,
-            parameters: (s.function.separated !== undefined
-              ? (s.function.separated.llm
-                ?? ({
-                  type: "object",
-                  properties: {},
-                  required: [],
-                  additionalProperties: false,
-                  $defs: {},
-                } satisfies IChatGptSchema.IParameters))
-              : s.function.parameters) as Record<string, any>,
+            parameters: (
+              "separated" in s.function
+              && s.function.separated !== undefined
+                ? (s.function.separated.llm
+                  ?? ({
+                    type: "object",
+                    properties: {},
+                    required: [],
+                    additionalProperties: false,
+                    $defs: {},
+                  } satisfies IChatGptSchema.IParameters))
+                : s.function.parameters) as Record<string, any>,
           },
         }) as OpenAI.ChatCompletionTool,
     ),
@@ -200,126 +202,93 @@ async function propagate<Model extends ILlmSchema.Model>(
   call: AgenticaCallEvent<Model>,
   retry: number,
 ): Promise<AgenticaExecuteHistory<Model>> {
-  if (call.operation.protocol === "http") {
-    // ----
-    // HTTP PROTOCOL
-    // ----
-    // NESTED VALIDATOR
-    const check: IValidation<unknown> = call.operation.function.validate(
-      call.arguments,
-    );
-    if (check.success === false) {
-      ctx.dispatch(
-        createValidateEvent({
-          id: call.id,
-          operation: call.operation,
-          result: check,
-        }),
-      ).catch(() => {});
-      if (retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)) {
-        const trial: AgenticaExecuteHistory<Model> | null = await correct(
-          ctx,
-          call,
-          retry,
-          check.errors,
-        );
-        if (trial !== null) {
-          return trial;
-        }
+  switch (call.operation.protocol) {
+    case "http": {
+      return propagateHttp({ ctx, operation: call.operation, call, retry });
+    }
+    case "class": {
+      return propagateClass({ ctx, operation: call.operation, call, retry });
+    }
+    case "mcp": {
+      return propagateMcp({ ctx, operation: call.operation, call, retry });
+    }
+    default: {
+      call.operation satisfies never;
+      throw new Error("Unsupported protocol");
+    }
+  }
+}
+
+async function propagateHttp<Model extends ILlmSchema.Model>(
+  props: {
+    ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
+    operation: AgenticaOperation.Http<Model>;
+    call: AgenticaCallEvent<Model>;
+    retry: number;
+  },
+): Promise<AgenticaExecuteHistory<Model>> {
+  // ----
+  // HTTP PROTOCOL
+  // ----
+  // NESTED VALIDATOR
+  const check: IValidation<unknown> = props.operation.function.validate(
+    props.call.arguments,
+  );
+  if (check.success === false) {
+    props.ctx.dispatch(
+      createValidateEvent({
+        id: props.call.id,
+        operation: props.operation,
+        result: check,
+      }),
+    ).catch(() => {});
+
+    if (props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)) {
+      const trial: AgenticaExecuteHistory<Model> | null = await correct(
+        props.ctx,
+        props.call,
+        props.retry,
+        check.errors,
+      );
+      if (trial !== null) {
+        return trial;
       }
     }
-    try {
-      // CALL HTTP API
-      const response: IHttpResponse = await executeHttpOperation(call.operation, call.arguments);
-      // CHECK STATUS
-      const success: boolean
+  }
+
+  try {
+    // CALL HTTP API
+    const response: IHttpResponse = await executeHttpOperation(props.operation, props.call.arguments);
+    // CHECK STATUS
+    const success: boolean
           = ((response.status === 400
             || response.status === 404
             || response.status === 422)
-          && retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)
+          && props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)
           && typeof response.body) === false;
-        // DISPATCH EVENT
-      return (
-        (success === false
-          ? await correct(ctx, call, retry, response.body)
-          : null)
-        ?? createExecuteHistory({
-          operation: call.operation,
-          id: call.id,
-          arguments: call.arguments,
-          value: response,
-        })
-      );
-    }
-    catch (error) {
-      // DISPATCH ERROR
-      return createExecuteHistory({
-        operation: call.operation,
-        id: call.id,
-        arguments: call.arguments,
-        value: {
-          status: 500,
-          headers: {},
-          body:
-              error instanceof Error
-                ? {
-                    ...error,
-                    name: error.name,
-                    message: error.message,
-                  }
-                : error,
-        },
-      });
-    }
-  }
-  else {
-    // ----
-    // CLASS FUNCTION
-    // ----
-    // VALIDATE FIRST
-    const check: IValidation<unknown> = call.operation.function.validate(
-      call.arguments,
+      // DISPATCH EVENT
+    return (
+      (success === false
+        ? await correct(props.ctx, props.call, props.retry, response.body)
+        : null)
+      ?? createExecuteHistory({
+        operation: props.call.operation,
+        id: props.call.id,
+        arguments: props.call.arguments,
+        value: response,
+      })
     );
-    if (check.success === false) {
-      ctx.dispatch(
-        createValidateEvent({
-          id: call.id,
-          operation: call.operation,
-          result: check,
-        }),
-      ).catch(() => {});
-      return (
-        (retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)
-          ? await correct(ctx, call, retry, check.errors)
-          : null)
-        ?? createExecuteHistory({
-          id: call.id,
-          operation: call.operation,
-          arguments: call.arguments,
-          value: {
-            name: "TypeGuardError",
-            message: "Invalid arguments.",
-            errors: check.errors,
-          },
-        })
-      );
-    }
-    // EXECUTE FUNCTION
-    try {
-      const value = await executeClassOperation(call.operation, call.arguments);
-      return createExecuteHistory({
-        id: call.id,
-        operation: call.operation,
-        arguments: call.arguments,
-        value,
-      });
-    }
-    catch (error) {
-      return createExecuteHistory({
-        id: call.id,
-        operation: call.operation,
-        arguments: call.arguments,
-        value:
+  }
+  catch (error) {
+    // DISPATCH ERROR
+    return createExecuteHistory({
+      operation: props.call.operation,
+      id: props.call.id,
+      arguments: props.call.arguments,
+      value: {
+        status: 500,
+        headers: {},
+        body:
           error instanceof Error
             ? {
                 ...error,
@@ -327,8 +296,109 @@ async function propagate<Model extends ILlmSchema.Model>(
                 message: error.message,
               }
             : error,
-      });
-    }
+      },
+    });
+  }
+}
+
+async function propagateClass<Model extends ILlmSchema.Model>(props: {
+  ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
+  operation: AgenticaOperation.Class<Model>;
+  call: AgenticaCallEvent<Model>;
+  retry: number;
+}): Promise<AgenticaExecuteHistory<Model>> {
+// ----
+  // CLASS FUNCTION
+  // ----
+  // VALIDATE FIRST
+  const check: IValidation<unknown> = props.operation.function.validate(
+    props.call.arguments,
+  );
+
+  if (check.success === false) {
+    props.ctx.dispatch(
+      createValidateEvent({
+        id: props.call.id,
+        operation: props.call.operation,
+        result: check,
+      }),
+    ).catch(() => {});
+    return (
+      (props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)
+        ? await correct(props.ctx, props.call, props.retry, check.errors)
+        : null)
+      ?? createExecuteHistory({
+        id: props.call.id,
+        operation: props.call.operation,
+        arguments: props.call.arguments,
+        value: {
+          name: "TypeGuardError",
+          message: "Invalid arguments.",
+          errors: check.errors,
+        },
+      })
+    );
+  }
+  // EXECUTE FUNCTION
+  try {
+    const value = await executeClassOperation(props.operation, props.call.arguments);
+    return createExecuteHistory({
+      id: props.call.id,
+      operation: props.call.operation,
+      arguments: props.call.arguments,
+      value,
+    });
+  }
+  catch (error) {
+    return createExecuteHistory({
+      id: props.call.id,
+      operation: props.call.operation,
+      arguments: props.call.arguments,
+      value:
+        error instanceof Error
+          ? {
+              ...error,
+              name: error.name,
+              message: error.message,
+            }
+          : error,
+    });
+  }
+}
+
+async function propagateMcp<Model extends ILlmSchema.Model>(props: {
+  ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
+  operation: AgenticaOperation.Mcp;
+  call: AgenticaCallEvent<Model>;
+  retry: number;
+}): Promise<AgenticaExecuteHistory<Model>> {
+  // ----
+  // MCP PROTOCOL
+  // ----
+  // @TODO: implement argument validation logic
+  try {
+    const value = await executeMcpOperation(props.operation, props.call.arguments);
+    return createExecuteHistory({
+      id: props.call.id,
+      operation: props.call.operation,
+      arguments: props.call.arguments,
+      value,
+    });
+  }
+  catch (error) {
+    return createExecuteHistory({
+      id: props.call.id,
+      operation: props.call.operation,
+      arguments: props.call.arguments,
+      value:
+        error instanceof Error
+          ? {
+              ...error,
+              name: error.name,
+              message: error.message,
+            }
+          : error,
+    });
   }
 }
 
@@ -365,6 +435,36 @@ async function executeClassOperation<Model extends ILlmSchema.Model>(operation:
   return ((execute as Record<string, unknown>)[operation.function.name] as (...args: unknown[]) => Promise<unknown>)(operationArguments);
 }
 
+async function executeMcpOperation(operation: AgenticaOperation.Mcp, operationArguments: Record<string, unknown>): Promise<unknown> {
+  // for peerDependencies
+  const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
+  const { SSEClientTransport } = await import("@modelcontextprotocol/sdk/client/sse.js");
+  const { StdioClientTransport } = await import("@modelcontextprotocol/sdk/client/stdio.js");
+
+  const client = new Client({
+    name: operation.name,
+    version: "1.0.0",
+  });
+
+  const transport = (() => {
+    switch (operation.controller.application.transport.type) {
+      case "sse":
+        return new SSEClientTransport(operation.controller.application.transport.url);
+      case "stdio":
+        // @TODO: implement StdioClientTransport cache
+        // StdioClientTransport and connects a new child process every time it is initialized and connected.
+        // This results in significant latency and resource waste.
+        return new StdioClientTransport(operation.controller.application.transport);
+      default:
+        operation.controller.application.transport satisfies never;
+        throw new Error("Unsupported transport type");
+    }
+  })();
+  await client.connect(transport);
+  const result = await client.callTool({ method: operation.function.name, name: operation.function.name, arguments: operationArguments });
+  return result.content;
+}
+
 async function correct<Model extends ILlmSchema.Model>(
   ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
   call: AgenticaCallEvent<Model>,
@@ -436,16 +536,18 @@ async function correct<Model extends ILlmSchema.Model>(
            * @TODO fix it
            * The property and value have a type mismatch, but it works.
            */
-          parameters: (call.operation.function.separated !== undefined
-            ? (call.operation.function.separated?.llm
-              ?? ({
-                $defs: {},
-                type: "object",
-                properties: {},
-                additionalProperties: false,
-                required: [],
-              } satisfies IChatGptSchema.IParameters))
-            : call.operation.function.parameters) as unknown as Record<string, unknown>,
+          parameters: (
+            "separated" in call.operation.function
+            && call.operation.function.separated !== undefined
+              ? (call.operation.function.separated?.llm
+                ?? ({
+                  $defs: {},
+                  type: "object",
+                  properties: {},
+                  additionalProperties: false,
+                  required: [],
+                } satisfies IChatGptSchema.IParameters))
+              : call.operation.function.parameters) as unknown as Record<string, unknown>,
         },
       },
     ],
diff --git a/packages/core/src/structures/IAgenticaController.ts b/packages/core/src/structures/IAgenticaController.ts
index dde1a70ab3..e6347760be 100644
--- a/packages/core/src/structures/IAgenticaController.ts
+++ b/packages/core/src/structures/IAgenticaController.ts
@@ -8,6 +8,8 @@ import type {
   ILlmSchema,
 } from "@samchon/openapi";
 
+import type { IMcpLlmApplication } from "./mcp/IMcpLlmApplication";
+
 /**
  * Controller of the Agentica Agent.
  *
@@ -18,14 +20,17 @@ import type {
  * Also, `IAgenticaController` is an union type which can specify
  * a subtype by checking the {@link protocol} property.
  *
- * - HTTP server: {@link IAgenticaController..IHttp}
+ * - HTTP server: {@link IAgenticaController.IHttp}
  * - TypeScript class: {@link IAgenticaController.IClass}
+ * - MCP Server: {@link IAgenticaController.IMcp}
  *
  * @author Samchon
  */
 export type IAgenticaController<Model extends ILlmSchema.Model> =
   | IAgenticaController.IHttp<Model>
-  | IAgenticaController.IClass<Model>;
+  | IAgenticaController.IClass<Model>
+  | IAgenticaController.IMcp;
+
 export namespace IAgenticaController {
   /**
    * HTTP controller.
@@ -114,6 +119,11 @@ export namespace IAgenticaController {
       }) => Promise<unknown>);
   }
 
+  /**
+   * MCP Server controller.
+   */
+  export interface IMcp extends IBase<"mcp", IMcpLlmApplication> { }
+
   interface IBase<Protocol, Application> {
     /**
      * Protocol discrminator.
diff --git a/packages/core/src/structures/mcp/IMcpLlmApplication.ts b/packages/core/src/structures/mcp/IMcpLlmApplication.ts
new file mode 100644
index 0000000000..4ef2b0ca1b
--- /dev/null
+++ b/packages/core/src/structures/mcp/IMcpLlmApplication.ts
@@ -0,0 +1,17 @@
+import type { IMcpLlmFunction } from "./IMcpLlmFunction";
+import type { IMcpLlmTransportProps } from "./IMcpLlmTransportProps";
+
+/**
+ * MCP LLM application.
+ */
+export interface IMcpLlmApplication {
+  /**
+   * Functions of the MCP server.
+   */
+  functions: IMcpLlmFunction[];
+
+  /**
+   * Transport properties of the MCP server.
+   */
+  transport: IMcpLlmTransportProps;
+}
diff --git a/packages/core/src/structures/mcp/IMcpLlmFunction.ts b/packages/core/src/structures/mcp/IMcpLlmFunction.ts
new file mode 100644
index 0000000000..57c6e8608c
--- /dev/null
+++ b/packages/core/src/structures/mcp/IMcpLlmFunction.ts
@@ -0,0 +1,19 @@
+/**
+ * MCP LLM function.
+ */
+export interface IMcpLlmFunction {
+  /**
+   * Name of the function.
+   */
+  name: string;
+
+  /**
+   * Description of the function.
+   */
+  description?: string;
+
+  /**
+   * Parameters of the function.
+   */
+  parameters: object;
+}
diff --git a/packages/core/src/structures/mcp/IMcpLlmTransportProps.ts b/packages/core/src/structures/mcp/IMcpLlmTransportProps.ts
new file mode 100644
index 0000000000..292f6bae7e
--- /dev/null
+++ b/packages/core/src/structures/mcp/IMcpLlmTransportProps.ts
@@ -0,0 +1,13 @@
+import type { SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.d.ts";
+import type { StdioServerParameters } from "@modelcontextprotocol/sdk/client/stdio.d.ts";
+
+export type IMcpLlmTransportProps = IMcpLlmTransportPropsHttp | IMcpLlmTransportPropsStdio;
+
+export interface IMcpLlmTransportPropsHttp extends IMcpLlmTransportPropsBase<"sse">, SSEClientTransportOptions {
+  url: URL;
+}
+export interface IMcpLlmTransportPropsStdio extends IMcpLlmTransportPropsBase<"stdio">, StdioServerParameters {}
+
+export interface IMcpLlmTransportPropsBase<T extends string> {
+  type: T;
+}
diff --git a/packages/core/src/structures/mcp/index.ts b/packages/core/src/structures/mcp/index.ts
new file mode 100644
index 0000000000..5fd878766c
--- /dev/null
+++ b/packages/core/src/structures/mcp/index.ts
@@ -0,0 +1,3 @@
+export * from "./IMcpLlmApplication";
+export * from "./IMcpLlmFunction";
+export * from "./IMcpLlmTransportProps";
diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json
index 846d0c8c87..cc0365cd56 100644
--- a/packages/core/tsconfig.json
+++ b/packages/core/tsconfig.json
@@ -26,6 +26,12 @@
     // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
     /* Modules */
     "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./",                                  /* Specify the root folder within your source files. */
+    // "moduleResolution": "node10",                     /* Specify how TypeScript looks up a file from a given module specifier. */
+    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
+    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
+    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
+    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
+    "types": ["vitest/globals"], /* Specify type package names to be included without being referenced in a source file. */
     "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
     "strictNullChecks": true,
     // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
@@ -42,12 +48,6 @@
     // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
     "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
     "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
-    // "moduleResolution": "node10",                     /* Specify how TypeScript looks up a file from a given module specifier. */
-    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
-    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
-    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
-    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
-    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
     // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
     // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
     // "allowImportingTsExtensions": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
diff --git a/packages/core/vitest.config.mts b/packages/core/vitest.config.mts
new file mode 100644
index 0000000000..087cf1855b
--- /dev/null
+++ b/packages/core/vitest.config.mts
@@ -0,0 +1,12 @@
+import UnpluginTypia from "@ryoppippi/unplugin-typia/vite";
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+  plugins: [
+    UnpluginTypia({ cache: false }),
+  ],
+  test: {
+    globals: true,
+    exclude: ["**/node_modules/**", "**/dist/**", "**/prompts/**", "**/build/**", "**/examples/**", "**/lib/**"],
+  },
+});
diff --git a/packages/rpc/package.json b/packages/rpc/package.json
index ac6e020691..9172edb30b 100644
--- a/packages/rpc/package.json
+++ b/packages/rpc/package.json
@@ -45,6 +45,9 @@
     "lint": "eslint .",
     "format": "eslint --fix ."
   },
+  "peerDependencies": {
+    "@agentica/core": "workspace:^"
+  },
   "dependencies": {
     "@agentica/core": "workspace:^",
     "@samchon/openapi": "catalog:typia",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9dbc20b84d..4ea81924dc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -6,6 +6,9 @@ settings:
 
 catalogs:
   libs:
+    '@modelcontextprotocol/sdk':
+      specifier: ^1.9.0
+      version: 1.9.0
     openai:
       specifier: ^4.80.0
       version: 4.91.1
@@ -26,6 +29,10 @@ catalogs:
     typia:
       specifier: ^9.0.1
       version: 9.0.1
+  vite:
+    vitest:
+      specifier: ^3.0.9
+      version: 3.1.1
 
 overrides:
   '@types/react': 19.0.0
@@ -287,6 +294,9 @@ importers:
         specifier: ^11.0.4
         version: 11.1.0
     devDependencies:
+      '@modelcontextprotocol/sdk':
+        specifier: catalog:libs
+        version: 1.9.0
       '@nestia/e2e':
         specifier: ^6.0.1
         version: 6.0.1
@@ -296,6 +306,9 @@ importers:
       '@rollup/plugin-typescript':
         specifier: ^12.1.2
         version: 12.1.2(rollup@4.39.0)(tslib@2.8.1)(typescript@5.8.3)
+      '@ryoppippi/unplugin-typia':
+        specifier: catalog:typia
+        version: 2.1.4(rollup@4.39.0)(typescript@5.8.3)(typia@9.0.1(@samchon/openapi@4.0.0)(typescript@5.8.3))(vite@5.4.17(@types/node@22.13.9)(lightningcss@1.29.2)(terser@5.39.0))
       '@types/node':
         specifier: ^22.13.4
         version: 22.13.9
@@ -323,6 +336,9 @@ importers:
       typescript:
         specifier: catalog:typescript
         version: 5.8.3
+      vitest:
+        specifier: catalog:vite
+        version: 3.1.1(@types/debug@4.1.12)(@types/node@22.13.9)(lightningcss@1.29.2)(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.3))(terser@5.39.0)
 
   packages/create-agentica:
     dependencies:
@@ -1487,6 +1503,10 @@ packages:
   '@mermaid-js/parser@0.4.0':
     resolution: {integrity: sha512-wla8XOWvQAwuqy+gxiZqY+c7FokraOTHRWMsbB4AgRx9Sy7zKslNyejy7E+a77qHfey5GXw/ik3IXv/NHMJgaA==}
 
+  '@modelcontextprotocol/sdk@1.9.0':
+    resolution: {integrity: sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==}
+    engines: {node: '>=18'}
+
   '@mswjs/interceptors@0.37.6':
     resolution: {integrity: sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w==}
     engines: {node: '>=18'}
@@ -2912,6 +2932,10 @@ packages:
     resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
     engines: {node: '>=6.5'}
 
+  accepts@2.0.0:
+    resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
+    engines: {node: '>= 0.6'}
+
   acorn-jsx@5.3.2:
     resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
     peerDependencies:
@@ -3084,6 +3108,10 @@ packages:
   bl@4.1.0:
     resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
 
+  body-parser@2.2.0:
+    resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
+    engines: {node: '>=18'}
+
   boolbase@1.0.0:
     resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
 
@@ -3121,6 +3149,10 @@ packages:
     resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
     engines: {node: '>=10.16.0'}
 
+  bytes@3.1.2:
+    resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+    engines: {node: '>= 0.8'}
+
   c12@3.0.3:
     resolution: {integrity: sha512-uC3MacKBb0Z15o5QWCHvHWj5Zv34pGQj9P+iXKSpTuSGFS0KKhUWf4t9AJ+gWjYOdmWCPEGpEzm8sS0iqbpo1w==}
     peerDependencies:
@@ -3334,12 +3366,24 @@ packages:
     resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
     engines: {node: ^14.18.0 || >=16.10.0}
 
+  content-disposition@1.0.0:
+    resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==}
+    engines: {node: '>= 0.6'}
+
+  content-type@1.0.5:
+    resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
+    engines: {node: '>= 0.6'}
+
   convert-source-map@1.9.0:
     resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
 
   convert-source-map@2.0.0:
     resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
 
+  cookie-signature@1.2.2:
+    resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
+    engines: {node: '>=6.6.0'}
+
   cookie@0.7.2:
     resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
     engines: {node: '>= 0.6'}
@@ -3353,6 +3397,10 @@ packages:
   core-util-is@1.0.3:
     resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
 
+  cors@2.8.5:
+    resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
+    engines: {node: '>= 0.10'}
+
   cose-base@1.0.3:
     resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==}
 
@@ -3657,6 +3705,10 @@ packages:
     resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
     engines: {node: '>=0.4.0'}
 
+  depd@2.0.0:
+    resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+    engines: {node: '>= 0.8'}
+
   dequal@2.0.3:
     resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
     engines: {node: '>=6'}
@@ -3734,6 +3786,9 @@ packages:
   eastasianwidth@0.2.0:
     resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
 
+  ee-first@1.1.1:
+    resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
   electron-to-chromium@1.5.132:
     resolution: {integrity: sha512-QgX9EBvWGmvSRa74zqfnG7+Eno0Ak0vftBll0Pt2/z5b3bEGYL6OUXLgKPtvx73dn3dvwrlyVkjPKRRlhLYTEg==}
 
@@ -3752,6 +3807,10 @@ packages:
   emoji-regex@9.2.2:
     resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
 
+  encodeurl@2.0.0:
+    resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+    engines: {node: '>= 0.8'}
+
   enhanced-resolve@5.18.1:
     resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
     engines: {node: '>=10.13.0'}
@@ -3821,6 +3880,9 @@ packages:
     resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
     engines: {node: '>=6'}
 
+  escape-html@1.0.3:
+    resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
   escape-string-regexp@1.0.5:
     resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
     engines: {node: '>=0.8.0'}
@@ -4151,10 +4213,22 @@ packages:
     resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
     engines: {node: '>=0.10.0'}
 
+  etag@1.8.1:
+    resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+    engines: {node: '>= 0.6'}
+
   event-target-shim@5.0.1:
     resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
     engines: {node: '>=6'}
 
+  eventsource-parser@3.0.1:
+    resolution: {integrity: sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==}
+    engines: {node: '>=18.0.0'}
+
+  eventsource@3.0.6:
+    resolution: {integrity: sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==}
+    engines: {node: '>=18.0.0'}
+
   execa@8.0.1:
     resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
     engines: {node: '>=16.17'}
@@ -4163,6 +4237,16 @@ packages:
     resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==}
     engines: {node: '>=12.0.0'}
 
+  express-rate-limit@7.5.0:
+    resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==}
+    engines: {node: '>= 16'}
+    peerDependencies:
+      express: ^4.11 || 5 || ^5.0.0-beta.1
+
+  express@5.1.0:
+    resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==}
+    engines: {node: '>= 18'}
+
   exsolve@1.0.4:
     resolution: {integrity: sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==}
 
@@ -4233,6 +4317,10 @@ packages:
     resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
     engines: {node: '>=8'}
 
+  finalhandler@2.1.0:
+    resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
+    engines: {node: '>= 0.8'}
+
   find-cache-dir@3.3.2:
     resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
     engines: {node: '>=8'}
@@ -4293,6 +4381,10 @@ packages:
     resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
     engines: {node: '>= 12.20'}
 
+  forwarded@0.2.0:
+    resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
+    engines: {node: '>= 0.6'}
+
   fraction.js@4.3.7:
     resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
 
@@ -4310,6 +4402,10 @@ packages:
       react-dom:
         optional: true
 
+  fresh@2.0.0:
+    resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
+    engines: {node: '>= 0.8'}
+
   fs-extra@11.3.0:
     resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==}
     engines: {node: '>=14.14'}
@@ -4532,6 +4628,10 @@ packages:
   html-void-elements@3.0.0:
     resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
 
+  http-errors@2.0.0:
+    resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
+    engines: {node: '>= 0.8'}
+
   human-signals@5.0.0:
     resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
     engines: {node: '>=16.17.0'}
@@ -4608,6 +4708,10 @@ packages:
     resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
     engines: {node: '>=12'}
 
+  ipaddr.js@1.9.1:
+    resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
+    engines: {node: '>= 0.10'}
+
   is-alphabetical@2.0.1:
     resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
 
@@ -4729,6 +4833,9 @@ packages:
     resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
     engines: {node: '>=12'}
 
+  is-promise@4.0.0:
+    resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
+
   is-reference@1.2.1:
     resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
 
@@ -5164,10 +5271,18 @@ packages:
   mdurl@2.0.0:
     resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
 
+  media-typer@1.1.0:
+    resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
+    engines: {node: '>= 0.8'}
+
   memfs@4.17.0:
     resolution: {integrity: sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==}
     engines: {node: '>= 4.0.0'}
 
+  merge-descriptors@2.0.0:
+    resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
+    engines: {node: '>=18'}
+
   merge-stream@2.0.0:
     resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
 
@@ -5303,10 +5418,18 @@ packages:
     resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
     engines: {node: '>= 0.6'}
 
+  mime-db@1.54.0:
+    resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+    engines: {node: '>= 0.6'}
+
   mime-types@2.1.35:
     resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
     engines: {node: '>= 0.6'}
 
+  mime-types@3.0.1:
+    resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
+    engines: {node: '>= 0.6'}
+
   mimic-fn@2.1.0:
     resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
     engines: {node: '>=6'}
@@ -5567,6 +5690,13 @@ packages:
   ohash@2.0.11:
     resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
 
+  on-finished@2.4.1:
+    resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+    engines: {node: '>= 0.8'}
+
+  once@1.4.0:
+    resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
   onetime@5.1.2:
     resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
     engines: {node: '>=6'}
@@ -5678,6 +5808,10 @@ packages:
   parse5@7.2.1:
     resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==}
 
+  parseurl@1.3.3:
+    resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+    engines: {node: '>= 0.8'}
+
   path-data-parser@0.1.0:
     resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==}
 
@@ -5707,6 +5841,10 @@ packages:
   path-to-regexp@6.3.0:
     resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
 
+  path-to-regexp@8.2.0:
+    resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
+    engines: {node: '>=16'}
+
   path-type@4.0.0:
     resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
     engines: {node: '>=8'}
@@ -5732,6 +5870,10 @@ packages:
     resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
     engines: {node: '>=12'}
 
+  pkce-challenge@5.0.0:
+    resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==}
+    engines: {node: '>=16.20.0'}
+
   pkg-dir@4.2.0:
     resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
     engines: {node: '>=8'}
@@ -5981,6 +6123,10 @@ packages:
   property-information@7.0.0:
     resolution: {integrity: sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==}
 
+  proxy-addr@2.0.7:
+    resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
+    engines: {node: '>= 0.10'}
+
   psl@1.15.0:
     resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
 
@@ -5997,6 +6143,10 @@ packages:
     resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
     engines: {node: '>=6'}
 
+  qs@6.14.0:
+    resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
+    engines: {node: '>=0.6'}
+
   quansync@0.2.10:
     resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==}
 
@@ -6013,6 +6163,14 @@ packages:
   randombytes@2.1.0:
     resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
 
+  range-parser@1.2.1:
+    resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
+    engines: {node: '>= 0.6'}
+
+  raw-body@3.0.0:
+    resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
+    engines: {node: '>= 0.8'}
+
   rc9@2.1.2:
     resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
 
@@ -6315,6 +6473,10 @@ packages:
   roughjs@4.6.6:
     resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==}
 
+  router@2.2.0:
+    resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
+    engines: {node: '>= 18'}
+
   rtl-css-js@1.16.1:
     resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==}
 
@@ -6379,9 +6541,17 @@ packages:
     engines: {node: '>=10'}
     hasBin: true
 
+  send@1.2.0:
+    resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
+    engines: {node: '>= 18'}
+
   serialize-javascript@6.0.2:
     resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
 
+  serve-static@2.2.0:
+    resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
+    engines: {node: '>= 18'}
+
   set-function-length@1.2.2:
     resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
     engines: {node: '>= 0.4'}
@@ -6398,6 +6568,9 @@ packages:
     resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
     engines: {node: '>= 0.4'}
 
+  setprototypeof@1.2.0:
+    resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
   sharp@0.33.5:
     resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -6737,6 +6910,10 @@ packages:
   toggle-selection@1.0.6:
     resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==}
 
+  toidentifier@1.0.1:
+    resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+    engines: {node: '>=0.6'}
+
   toml-eslint-parser@0.10.0:
     resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -6824,6 +7001,10 @@ packages:
     resolution: {integrity: sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==}
     engines: {node: '>=16'}
 
+  type-is@2.0.1:
+    resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
+    engines: {node: '>= 0.6'}
+
   typed-array-buffer@1.0.3:
     resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
     engines: {node: '>= 0.4'}
@@ -6969,6 +7150,10 @@ packages:
     resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
     engines: {node: '>= 10.0.0'}
 
+  unpipe@1.0.0:
+    resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+    engines: {node: '>= 0.8'}
+
   unplugin@2.2.2:
     resolution: {integrity: sha512-Qp+iiD+qCRnUek+nDoYvtWX7tfnYyXsrOnJ452FRTgOyKmTM7TUJ3l+PLPJOOWPTUyKISKp4isC5JJPSXUjGgw==}
     engines: {node: '>=18.12.0'}
@@ -7034,6 +7219,10 @@ packages:
   validate-npm-package-license@3.0.4:
     resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
 
+  vary@1.1.2:
+    resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+    engines: {node: '>= 0.8'}
+
   vfile-location@5.0.3:
     resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
 
@@ -7211,6 +7400,9 @@ packages:
     resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
     engines: {node: '>=12'}
 
+  wrappy@1.0.2:
+    resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
   ws@7.5.10:
     resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==}
     engines: {node: '>=8.3.0'}
@@ -7278,6 +7470,11 @@ packages:
     resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
     engines: {node: '>=18'}
 
+  zod-to-json-schema@3.24.5:
+    resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==}
+    peerDependencies:
+      zod: ^3.24.1
+
   zod-validation-error@3.4.0:
     resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==}
     engines: {node: '>=18.0.0'}
@@ -8166,6 +8363,21 @@ snapshots:
     dependencies:
       langium: 3.3.1
 
+  '@modelcontextprotocol/sdk@1.9.0':
+    dependencies:
+      content-type: 1.0.5
+      cors: 2.8.5
+      cross-spawn: 7.0.6
+      eventsource: 3.0.6
+      express: 5.1.0
+      express-rate-limit: 7.5.0(express@5.1.0)
+      pkce-challenge: 5.0.0
+      raw-body: 3.0.0
+      zod: 3.24.2
+      zod-to-json-schema: 3.24.5(zod@3.24.2)
+    transitivePeerDependencies:
+      - supports-color
+
   '@mswjs/interceptors@0.37.6':
     dependencies:
       '@open-draft/deferred-promise': 2.2.0
@@ -9602,6 +9814,11 @@ snapshots:
     dependencies:
       event-target-shim: 5.0.1
 
+  accepts@2.0.0:
+    dependencies:
+      mime-types: 3.0.1
+      negotiator: 1.0.0
+
   acorn-jsx@5.3.2(acorn@8.14.1):
     dependencies:
       acorn: 8.14.1
@@ -9779,6 +9996,20 @@ snapshots:
       inherits: 2.0.4
       readable-stream: 3.6.2
 
+  body-parser@2.2.0:
+    dependencies:
+      bytes: 3.1.2
+      content-type: 1.0.5
+      debug: 4.4.0
+      http-errors: 2.0.0
+      iconv-lite: 0.6.3
+      on-finished: 2.4.1
+      qs: 6.14.0
+      raw-body: 3.0.0
+      type-is: 2.0.1
+    transitivePeerDependencies:
+      - supports-color
+
   boolbase@1.0.0: {}
 
   brace-expansion@1.1.11:
@@ -9830,6 +10061,8 @@ snapshots:
     dependencies:
       streamsearch: 1.1.0
 
+  bytes@3.1.2: {}
+
   c12@3.0.3:
     dependencies:
       chokidar: 4.0.3
@@ -10030,10 +10263,18 @@ snapshots:
 
   consola@3.4.2: {}
 
+  content-disposition@1.0.0:
+    dependencies:
+      safe-buffer: 5.2.1
+
+  content-type@1.0.5: {}
+
   convert-source-map@1.9.0: {}
 
   convert-source-map@2.0.0: {}
 
+  cookie-signature@1.2.2: {}
+
   cookie@0.7.2: {}
 
   copy-to-clipboard@3.3.3:
@@ -10046,6 +10287,11 @@ snapshots:
 
   core-util-is@1.0.3: {}
 
+  cors@2.8.5:
+    dependencies:
+      object-assign: 4.1.1
+      vary: 1.1.2
+
   cose-base@1.0.3:
     dependencies:
       layout-base: 1.0.2
@@ -10408,6 +10654,8 @@ snapshots:
 
   delayed-stream@1.0.0: {}
 
+  depd@2.0.0: {}
+
   dequal@2.0.3: {}
 
   destr@2.0.5: {}
@@ -10481,6 +10729,8 @@ snapshots:
 
   eastasianwidth@0.2.0: {}
 
+  ee-first@1.1.1: {}
+
   electron-to-chromium@1.5.132: {}
 
   elkjs@0.8.2: {}
@@ -10493,6 +10743,8 @@ snapshots:
 
   emoji-regex@9.2.2: {}
 
+  encodeurl@2.0.0: {}
+
   enhanced-resolve@5.18.1:
     dependencies:
       graceful-fs: 4.2.11
@@ -10678,6 +10930,8 @@ snapshots:
 
   escalade@3.2.0: {}
 
+  escape-html@1.0.3: {}
+
   escape-string-regexp@1.0.5: {}
 
   escape-string-regexp@4.0.0: {}
@@ -11163,8 +11417,16 @@ snapshots:
 
   esutils@2.0.3: {}
 
+  etag@1.8.1: {}
+
   event-target-shim@5.0.1: {}
 
+  eventsource-parser@3.0.1: {}
+
+  eventsource@3.0.6:
+    dependencies:
+      eventsource-parser: 3.0.1
+
   execa@8.0.1:
     dependencies:
       cross-spawn: 7.0.6
@@ -11179,6 +11441,42 @@ snapshots:
 
   expect-type@1.2.1: {}
 
+  express-rate-limit@7.5.0(express@5.1.0):
+    dependencies:
+      express: 5.1.0
+
+  express@5.1.0:
+    dependencies:
+      accepts: 2.0.0
+      body-parser: 2.2.0
+      content-disposition: 1.0.0
+      content-type: 1.0.5
+      cookie: 0.7.2
+      cookie-signature: 1.2.2
+      debug: 4.4.0
+      encodeurl: 2.0.0
+      escape-html: 1.0.3
+      etag: 1.8.1
+      finalhandler: 2.1.0
+      fresh: 2.0.0
+      http-errors: 2.0.0
+      merge-descriptors: 2.0.0
+      mime-types: 3.0.1
+      on-finished: 2.4.1
+      once: 1.4.0
+      parseurl: 1.3.3
+      proxy-addr: 2.0.7
+      qs: 6.14.0
+      range-parser: 1.2.1
+      router: 2.2.0
+      send: 1.2.0
+      serve-static: 2.2.0
+      statuses: 2.0.1
+      type-is: 2.0.1
+      vary: 1.1.2
+    transitivePeerDependencies:
+      - supports-color
+
   exsolve@1.0.4: {}
 
   extend@3.0.2: {}
@@ -11249,6 +11547,17 @@ snapshots:
     dependencies:
       to-regex-range: 5.0.1
 
+  finalhandler@2.1.0:
+    dependencies:
+      debug: 4.4.0
+      encodeurl: 2.0.0
+      escape-html: 1.0.3
+      on-finished: 2.4.1
+      parseurl: 1.3.3
+      statuses: 2.0.1
+    transitivePeerDependencies:
+      - supports-color
+
   find-cache-dir@3.3.2:
     dependencies:
       commondir: 1.0.1
@@ -11317,6 +11626,8 @@ snapshots:
       node-domexception: 1.0.0
       web-streams-polyfill: 4.0.0-beta.3
 
+  forwarded@0.2.0: {}
+
   fraction.js@4.3.7: {}
 
   framer-motion@12.6.3(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
@@ -11329,6 +11640,8 @@ snapshots:
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
 
+  fresh@2.0.0: {}
+
   fs-extra@11.3.0:
     dependencies:
       graceful-fs: 4.2.11
@@ -11654,6 +11967,14 @@ snapshots:
 
   html-void-elements@3.0.0: {}
 
+  http-errors@2.0.0:
+    dependencies:
+      depd: 2.0.0
+      inherits: 2.0.4
+      setprototypeof: 1.2.0
+      statuses: 2.0.1
+      toidentifier: 1.0.1
+
   human-signals@5.0.0: {}
 
   humanize-ms@1.2.1:
@@ -11727,6 +12048,8 @@ snapshots:
 
   internmap@2.0.3: {}
 
+  ipaddr.js@1.9.1: {}
+
   is-alphabetical@2.0.1: {}
 
   is-alphanumerical@2.0.1:
@@ -11837,6 +12160,8 @@ snapshots:
 
   is-plain-obj@4.1.0: {}
 
+  is-promise@4.0.0: {}
+
   is-reference@1.2.1:
     dependencies:
       '@types/estree': 1.0.7
@@ -12346,6 +12671,8 @@ snapshots:
 
   mdurl@2.0.0: {}
 
+  media-typer@1.1.0: {}
+
   memfs@4.17.0:
     dependencies:
       '@jsonjoy.com/json-pack': 1.2.0(tslib@2.8.1)
@@ -12353,6 +12680,8 @@ snapshots:
       tree-dump: 1.0.2(tslib@2.8.1)
       tslib: 2.8.1
 
+  merge-descriptors@2.0.0: {}
+
   merge-stream@2.0.0: {}
 
   merge2@1.4.1: {}
@@ -12691,10 +13020,16 @@ snapshots:
 
   mime-db@1.52.0: {}
 
+  mime-db@1.54.0: {}
+
   mime-types@2.1.35:
     dependencies:
       mime-db: 1.52.0
 
+  mime-types@3.0.1:
+    dependencies:
+      mime-db: 1.54.0
+
   mimic-fn@2.1.0: {}
 
   mimic-fn@4.0.0: {}
@@ -13034,6 +13369,14 @@ snapshots:
 
   ohash@2.0.11: {}
 
+  on-finished@2.4.1:
+    dependencies:
+      ee-first: 1.1.1
+
+  once@1.4.0:
+    dependencies:
+      wrappy: 1.0.2
+
   onetime@5.1.2:
     dependencies:
       mimic-fn: 2.1.0
@@ -13176,6 +13519,8 @@ snapshots:
     dependencies:
       entities: 4.5.0
 
+  parseurl@1.3.3: {}
+
   path-data-parser@0.1.0: {}
 
   path-exists@4.0.0: {}
@@ -13195,6 +13540,8 @@ snapshots:
 
   path-to-regexp@6.3.0: {}
 
+  path-to-regexp@8.2.0: {}
+
   path-type@4.0.0: {}
 
   pathe@2.0.3: {}
@@ -13209,6 +13556,8 @@ snapshots:
 
   picomatch@4.0.2: {}
 
+  pkce-challenge@5.0.0: {}
+
   pkg-dir@4.2.0:
     dependencies:
       find-up: 4.1.0
@@ -13448,6 +13797,11 @@ snapshots:
 
   property-information@7.0.0: {}
 
+  proxy-addr@2.0.7:
+    dependencies:
+      forwarded: 0.2.0
+      ipaddr.js: 1.9.1
+
   psl@1.15.0:
     dependencies:
       punycode: 2.3.1
@@ -13463,6 +13817,10 @@ snapshots:
 
   punycode@2.3.1: {}
 
+  qs@6.14.0:
+    dependencies:
+      side-channel: 1.1.0
+
   quansync@0.2.10: {}
 
   querystringify@2.2.0: {}
@@ -13478,6 +13836,15 @@ snapshots:
     dependencies:
       safe-buffer: 5.2.1
 
+  range-parser@1.2.1: {}
+
+  raw-body@3.0.0:
+    dependencies:
+      bytes: 3.1.2
+      http-errors: 2.0.0
+      iconv-lite: 0.6.3
+      unpipe: 1.0.0
+
   rc9@2.1.2:
     dependencies:
       defu: 6.1.4
@@ -13935,6 +14302,16 @@ snapshots:
       points-on-curve: 0.2.0
       points-on-path: 0.2.1
 
+  router@2.2.0:
+    dependencies:
+      debug: 4.4.0
+      depd: 2.0.0
+      is-promise: 4.0.0
+      parseurl: 1.3.3
+      path-to-regexp: 8.2.0
+    transitivePeerDependencies:
+      - supports-color
+
   rtl-css-js@1.16.1:
     dependencies:
       '@babel/runtime': 7.27.0
@@ -14000,10 +14377,35 @@ snapshots:
 
   semver@7.7.1: {}
 
+  send@1.2.0:
+    dependencies:
+      debug: 4.4.0
+      encodeurl: 2.0.0
+      escape-html: 1.0.3
+      etag: 1.8.1
+      fresh: 2.0.0
+      http-errors: 2.0.0
+      mime-types: 3.0.1
+      ms: 2.1.3
+      on-finished: 2.4.1
+      range-parser: 1.2.1
+      statuses: 2.0.1
+    transitivePeerDependencies:
+      - supports-color
+
   serialize-javascript@6.0.2:
     dependencies:
       randombytes: 2.1.0
 
+  serve-static@2.2.0:
+    dependencies:
+      encodeurl: 2.0.0
+      escape-html: 1.0.3
+      parseurl: 1.3.3
+      send: 1.2.0
+    transitivePeerDependencies:
+      - supports-color
+
   set-function-length@1.2.2:
     dependencies:
       define-data-property: 1.1.4
@@ -14028,6 +14430,8 @@ snapshots:
       es-errors: 1.3.0
       es-object-atoms: 1.1.1
 
+  setprototypeof@1.2.0: {}
+
   sharp@0.33.5:
     dependencies:
       color: 4.2.3
@@ -14415,6 +14819,8 @@ snapshots:
 
   toggle-selection@1.0.6: {}
 
+  toidentifier@1.0.1: {}
+
   toml-eslint-parser@0.10.0:
     dependencies:
       eslint-visitor-keys: 3.4.3
@@ -14522,6 +14928,12 @@ snapshots:
 
   type-fest@4.39.1: {}
 
+  type-is@2.0.1:
+    dependencies:
+      content-type: 1.0.5
+      media-typer: 1.1.0
+      mime-types: 3.0.1
+
   typed-array-buffer@1.0.3:
     dependencies:
       call-bound: 1.0.4
@@ -14749,6 +15161,8 @@ snapshots:
 
   universalify@2.0.1: {}
 
+  unpipe@1.0.0: {}
+
   unplugin@2.2.2:
     dependencies:
       acorn: 8.14.1
@@ -14827,6 +15241,8 @@ snapshots:
       spdx-correct: 3.2.0
       spdx-expression-parse: 3.0.1
 
+  vary@1.1.2: {}
+
   vfile-location@5.0.3:
     dependencies:
       '@types/unist': 3.0.3
@@ -15109,6 +15525,8 @@ snapshots:
       string-width: 5.1.2
       strip-ansi: 7.1.0
 
+  wrappy@1.0.2: {}
+
   ws@7.5.10: {}
 
   xml-name-validator@4.0.0: {}
@@ -15150,6 +15568,10 @@ snapshots:
 
   yoctocolors-cjs@2.1.2: {}
 
+  zod-to-json-schema@3.24.5(zod@3.24.2):
+    dependencies:
+      zod: 3.24.2
+
   zod-validation-error@3.4.0(zod@3.24.2):
     dependencies:
       zod: 3.24.2
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 11a3f08d16..86fd5d2997 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -5,6 +5,7 @@ packages:
 
 catalogs:
   libs:
+    "@modelcontextprotocol/sdk": ^1.9.0
     openai: ^4.80.0
     type-fest: ^4.37.0
   typescript:
diff --git a/test/src/features/test_base_mcp_work_describe.ts b/test/src/features/test_base_mcp_work_describe.ts
new file mode 100644
index 0000000000..9ad5f5b9c8
--- /dev/null
+++ b/test/src/features/test_base_mcp_work_describe.ts
@@ -0,0 +1,77 @@
+import type { AgenticaEvent, IAgenticaController } from "@agentica/core";
+
+import { Agentica, assertMcpLlmApplication } from "@agentica/core";
+import OpenAI from "openai";
+import typia from "typia";
+
+import { TestGlobal } from "../TestGlobal";
+
+export async function test_base_mcp_work_describe(): Promise<void | false> {
+  if (TestGlobal.chatgptApiKey.length === 0) {
+    return false;
+  }
+
+  // for trace event
+  const events: AgenticaEvent<"chatgpt">[] = [];
+  let functionCalled = false;
+
+  // calculator controller
+  const calculatorController: IAgenticaController<"chatgpt"> = {
+    protocol: "mcp",
+    name: "calculator",
+    application: await assertMcpLlmApplication({ type: "stdio", command: "npx", args: ["-y", "@wrtnlabs/calculator-mcp"] }),
+  };
+
+  // Agentica instance
+  const agent: Agentica<"chatgpt"> = new Agentica({
+    model: "chatgpt",
+    vendor: {
+      model: "gpt-4o-mini",
+      api: new OpenAI({
+        apiKey: TestGlobal.env.CHATGPT_API_KEY,
+      }),
+    },
+    controllers: [calculatorController],
+  });
+
+  // event listener
+  agent.on("select", (event) => {
+    events.push(event);
+  });
+
+  agent.on("call", (event) => {
+    events.push(event);
+    if (event.operation.name.includes("add") || event.operation.name.includes("subtract")) {
+      functionCalled = true;
+    }
+  });
+
+  agent.on("execute", (event) => {
+    events.push(event);
+  });
+
+  const a = 5123123123;
+  const b = 3412342134;
+  // start conversation - induce function call
+  await agent.conversate(
+    `Could you add ${a} and ${b} for me?; You should use calculator`,
+  );
+
+  // check function call
+  if (!functionCalled) {
+    throw new Error("Function was not called during conversation");
+  }
+
+  // check result
+  const executeEvent = events.find(e => e.type === "execute");
+
+  if (executeEvent === undefined) {
+    throw new Error("Execute event not found");
+  }
+
+  if (!typia.is<[{ type: "text"; text: string }]>(executeEvent.value) || !executeEvent.value[0].text.includes(`${a + b}`)) {
+    throw new TypeError(
+      `Expected result to be ${a + b}, but got ${JSON.stringify(executeEvent.value)}`,
+    );
+  }
+}
diff --git a/test/src/features/test_base_streaming_describe.ts b/test/src/features/test_base_streaming_describe.ts
index b1b96146bc..ff31742c40 100644
--- a/test/src/features/test_base_streaming_describe.ts
+++ b/test/src/features/test_base_streaming_describe.ts
@@ -74,7 +74,7 @@ export async function test_base_streaming_describe(): Promise<void | false> {
 
   agent.on("call", (event) => {
     events.push(event);
-    if (event.operation.name === "add" || event.operation.name === "subtract") {
+    if (event.operation.name.includes("add") || event.operation.name.includes("subtract")) {
       functionCalled = true;
     }
   });
@@ -192,7 +192,7 @@ export async function test_base_streaming_describe(): Promise<void | false> {
 
   const hasCalculatorExecution = describeEvent.executes.some(
     exec =>
-      exec.operation.name === "add" || exec.operation.name === "subtract",
+      exec.operation.name.includes("add") || exec.operation.name.includes("subtract"),
   );
   if (!hasCalculatorExecution) {
     throw new Error(
diff --git a/test/src/features/test_base_work_describe.ts b/test/src/features/test_base_work_describe.ts
index 302316fa25..d4696280cd 100644
--- a/test/src/features/test_base_work_describe.ts
+++ b/test/src/features/test_base_work_describe.ts
@@ -65,7 +65,7 @@ export async function test_base_work_describe(): Promise<void | false> {
 
   agent.on("call", (event) => {
     events.push(event);
-    if (event.operation.name === "add" || event.operation.name === "subtract") {
+    if (event.operation.name.includes("add") || event.operation.name.includes("subtract")) {
       functionCalled = true;
     }
   });
diff --git a/website/content/docs/core/facade.mdx b/website/content/docs/core/facade.mdx
index 38f7441c28..72e0f9f6ee 100644
--- a/website/content/docs/core/facade.mdx
+++ b/website/content/docs/core/facade.mdx
@@ -222,8 +222,8 @@ flowchart
   <code>IAgenticaController</code>,
 ]}>
   <Tabs.Tab>
-```typescript filename="src/main.ts" showLineNumbers {12-50}
-import { Agentica, assertHttpLlmApplication } from "@agentica/core";
+```typescript filename="src/main.ts" showLineNumbers {12-53}
+import { Agentica, assertHttpLlmApplication, assertMcpLlmApplication } from "@agentica/core";
 import { AgenticaPgVectorSelector } from "@agentica/pg-vector-selector";
 import typia from "typia";
 
@@ -259,19 +259,22 @@ const main = async (): Promise<void> => {
         execute: new ShoppingCounselor(),
       },
       {
-        protocol: "class",
+        protocol: "mcp",
         name: "policy",
-        application: 
-          typia.llm.application<ShoppingPolicy, "chatgpt">(),
-        execute: new ShoppingPolicy(),
+        application: await assertMcpLlmApplication({
+          type: "stdio",
+          command: "npx",
+          args: ["-y", "@wrtnlabs/shopping-policy-mcp"],
+        }),
       },
       {
-        protocol: "class",
+        protocol: "mcp",
         name: "rag",
-        application: 
-          typia.llm.application<ShoppingSearchRag, "chatgpt">(),
-        execute: new ShoppingSearchRag(),
-      },
+        application: await assertMcpLlmApplication({
+          type: "sse",
+          url: new URL("http://localhost:8931/sse"),
+        }),
+      }
     ],
     config: {
       executor: {
@@ -304,6 +307,10 @@ In `@agentica/core`, there is a concept of controller, a set LLM function callin
 
 When you're using HTTP server controller, create LLM application schema from `assertHttpLlmApplication()` or `validateHttpLlmApplication()` function. These functions will validate whether the target Swagger/OpenAPI document is correct or not. And then, configure connection information to the HTTP server with destination URL and headers. 
 
+When you want to serve the function calling from a MCP (Model Context Protocol) application, create LLM application schema from `assertMcpLlmApplication()`.  
+These functions will validate whether the target MCP application is correct or not. And then, configure the MCP application with type, command and arguments.  
+Currently, we support `stdio` and `sse` types of MCP applications.
+
 Otherwise you want to serve the function calling from a TypeScript class, create LLM application schema from `typia.llm.application<Class, Model>()` function. And provide the class instance for the actual function calling.
 
 For reference, `IAgenticaController.name` must be unique, because it is used to identify the controller in the agent. Also, if number of your controller functions are too many, it would better to configure `executor.selector` as vector selector of plugin. If you don't do it, too much LLM token costs would be consumed.


Reviews:
user: login: kakasoo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T11:13:28Z
user: login: sunrabbit123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T11:16:40Z
user: login: ryoppippi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T15:27:34Z
user: login: ryoppippi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T16:07:42Z
user: login: sunrabbit123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-09T05:21:04Z
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 19 out of 23 changed files in this pull request and generated 1 comment.

<details>
<summary>Files not reviewed (4)</summary>

* **packages/benchmark/package.json**: Language not supported
* **packages/core/package.json**: Language not supported
* **packages/core/tsconfig.json**: Language not supported
* **packages/rpc/package.json**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**packages/core/src/context/internal/AgenticaOperationComposer.ts:75**
* [nitpick] Consider replacing 'controller satisfies never' with a conventional exhaustive check to make the default branch clearer and more idiomatic.
```
        controller satisfies never;
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T09:39:09Z
user: login: samchon
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-10T07:53:31Z

Review comments:
diff_hunk: @@ -0,0 +1,314 @@
+import type { IHttpLlmFunction, ILlmFunction, IValidation } from "@samchon/openapi";
+
+import { describe, expect, it } from "vitest";
+
+import type { IAgenticaConfig } from "../../structures/IAgenticaConfig";
+import type { IAgenticaController } from "../../structures/IAgenticaController";
+import type { IMcpLlmFunction } from "../../structures/IMcpLlmFunction";
+
+import { compose, divide, getOperations, toClassOperations, toHttpOperations, toMcpOperations } from "./AgenticaOperationComposer";
+
+// 테스트 헬퍼 함수들
path: packages/core/src/context/internal/AgenticaOperationComposer.spec.ts
user: login: kakasoo
body: Korean.
created_at: 2025-04-07T11:13:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,314 @@
+import type { IHttpLlmFunction, ILlmFunction, IValidation } from "@samchon/openapi";
+
+import { describe, expect, it } from "vitest";
+
+import type { IAgenticaConfig } from "../../structures/IAgenticaConfig";
+import type { IAgenticaController } from "../../structures/IAgenticaController";
+import type { IMcpLlmFunction } from "../../structures/IMcpLlmFunction";
+
+import { compose, divide, getOperations, toClassOperations, toHttpOperations, toMcpOperations } from "./AgenticaOperationComposer";
+
+// 테스트 헬퍼 함수들
path: packages/core/src/context/internal/AgenticaOperationComposer.spec.ts
user: login: sunrabbit123
body: yeah it's so sad, it's target for to fix....

created_at: 2025-04-07T11:16:40Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,320 @@
+import type { IHttpLlmFunction, ILlmFunction, IValidation } from "@samchon/openapi";
+
+import { describe, expect, it } from "vitest";
path: packages/core/src/context/internal/AgenticaOperationComposer.spec.ts
user: login: ryoppippi
body: [nits] we use global import for vitest so we can remove it!
created_at: 2025-04-08T15:27:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,320 @@
+import type { IHttpLlmFunction, ILlmFunction, IValidation } from "@samchon/openapi";
+
+import { describe, expect, it } from "vitest";
+
+import type { IAgenticaConfig } from "../../structures/IAgenticaConfig";
+import type { IAgenticaController } from "../../structures/IAgenticaController";
+import type { IMcpLlmFunction } from "../../structures/mcp/IMcpLlmFunction";
+
+import { compose, divide, getOperations, toClassOperations, toHttpOperations, toMcpOperations } from "./AgenticaOperationComposer";
+
+// 테스트 헬퍼 함수들
+function createMockHttpFunction(name: string, method: "get" | "post" | "patch" | "put" | "delete", path: string): IHttpLlmFunction<any> {
+  return {
+    name,
+    method,
+    path,
+    validate: () => ({ success: true, data: {} } as IValidation<unknown>),
+    operation: () => ({}),
+    route: () => ({
+      method,
+      path,
+      emendedPath: path,
+      accessor: [name],
+      body: null,
+      query: null,
+      parameters: [],
+      headers: null,
+      success: null,
+      exceptions: {},
+      comment: () => "OK",
+      operation: () => ({}),
+    }),
+    parameters: {},
+    output: {},
+  };
+}
+
+function createMockHttpController(name: string, functions: IHttpLlmFunction<any>[]): IAgenticaController.IHttp<any> {
+  return {
+    name,
+    protocol: "http" as const,
+    connection: { host: "https://example.com" },
+    application: {
+      model: "chatgpt",
+      options: {},
+      functions,
+      errors: [],
+    },
+  };
+}
+
+function createMockClassController(name: string, functions: ILlmFunction<any>[]): IAgenticaController.IClass<any> {
+  return {
+    name,
+    protocol: "class" as const,
path: packages/core/src/context/internal/AgenticaOperationComposer.spec.ts
user: login: ryoppippi
body: [tips] you can use a literal string instead of using `as const`!
created_at: 2025-04-08T16:07:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,320 @@
+import type { IHttpLlmFunction, ILlmFunction, IValidation } from "@samchon/openapi";
+
+import { describe, expect, it } from "vitest";
+
+import type { IAgenticaConfig } from "../../structures/IAgenticaConfig";
+import type { IAgenticaController } from "../../structures/IAgenticaController";
+import type { IMcpLlmFunction } from "../../structures/mcp/IMcpLlmFunction";
+
+import { compose, divide, getOperations, toClassOperations, toHttpOperations, toMcpOperations } from "./AgenticaOperationComposer";
+
+// 테스트 헬퍼 함수들
+function createMockHttpFunction(name: string, method: "get" | "post" | "patch" | "put" | "delete", path: string): IHttpLlmFunction<any> {
+  return {
+    name,
+    method,
+    path,
+    validate: () => ({ success: true, data: {} } as IValidation<unknown>),
+    operation: () => ({}),
+    route: () => ({
+      method,
+      path,
+      emendedPath: path,
+      accessor: [name],
+      body: null,
+      query: null,
+      parameters: [],
+      headers: null,
+      success: null,
+      exceptions: {},
+      comment: () => "OK",
+      operation: () => ({}),
+    }),
+    parameters: {},
+    output: {},
+  };
+}
+
+function createMockHttpController(name: string, functions: IHttpLlmFunction<any>[]): IAgenticaController.IHttp<any> {
+  return {
+    name,
+    protocol: "http" as const,
+    connection: { host: "https://example.com" },
+    application: {
+      model: "chatgpt",
+      options: {},
+      functions,
+      errors: [],
+    },
+  };
+}
+
+function createMockClassController(name: string, functions: ILlmFunction<any>[]): IAgenticaController.IClass<any> {
+  return {
+    name,
+    protocol: "class" as const,
path: packages/core/src/context/internal/AgenticaOperationComposer.spec.ts
user: login: sunrabbit123
body: thank you for your advice!
I applied it!
created_at: 2025-04-09T05:21:04Z
author_association: MEMBER
diff_hunk: @@ -207,135 +209,203 @@ async function propagate<Model extends ILlmSchema.Model>(
   call: AgenticaCallEvent<Model>,
   retry: number,
 ): Promise<AgenticaExecuteHistory<Model>> {
-  if (call.operation.protocol === "http") {
-    // ----
-    // HTTP PROTOCOL
-    // ----
-    // NESTED VALIDATOR
-    const check: IValidation<unknown> = call.operation.function.validate(
-      call.arguments,
-    );
-    if (check.success === false) {
-      ctx.dispatch(
-        createValidateEvent({
-          id: call.id,
-          operation: call.operation,
-          result: check,
-        }),
-      ).catch(() => {});
-      if (retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)) {
-        const trial: AgenticaExecuteHistory<Model> | null = await correct(
-          ctx,
-          call,
-          retry,
-          check.errors,
-        );
-        if (trial !== null) {
-          return trial;
-        }
+  switch (call.operation.protocol) {
+    case "http": {
+      return propagateHttp({ ctx, operation: call.operation, call, retry });
+    }
+    case "class": {
+      return propagateClass({ ctx, operation: call.operation, call, retry });
+    }
+    case "mcp": {
+      return propagateMcp({ ctx, operation: call.operation, call, retry });
+    }
+    default: {
+      call.operation satisfies never;
+      throw new Error("Unsupported protocol");
+    }
+  }
+}
+
+async function propagateHttp<Model extends ILlmSchema.Model>(
+  props: {
+    ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
+    operation: AgenticaOperation.Http<Model>;
+    call: AgenticaCallEvent<Model>;
+    retry: number;
+  },
+): Promise<AgenticaExecuteHistory<Model>> {
+  // ----
+  // HTTP PROTOCOL
+  // ----
+  // NESTED VALIDATOR
+  const check: IValidation<unknown> = props.operation.function.validate(
+    props.call.arguments,
+  );
+  if (check.success === false) {
+    props.ctx.dispatch(
+      createValidateEvent({
+        id: props.call.id,
+        operation: props.operation,
+        result: check,
+      }),
+    ).catch(() => {});
+
+    if (props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)) {
+      const trial: AgenticaExecuteHistory<Model> | null = await correct(
+        props.ctx,
+        props.call,
+        props.retry,
+        check.errors,
+      );
+      if (trial !== null) {
+        return trial;
       }
     }
-    try {
-      // CALL HTTP API
-      const response: IHttpResponse = await executeHttpOperation(call.operation, call.arguments);
-      // CHECK STATUS
-      const success: boolean
+  }
+
+  try {
+    // CALL HTTP API
+    const response: IHttpResponse = await executeHttpOperation(props.operation, props.call.arguments);
+    // CHECK STATUS
+    const success: boolean
           = ((response.status === 400
             || response.status === 404
             || response.status === 422)
-          && retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)
+          && props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)
           && typeof response.body) === false;
-        // DISPATCH EVENT
-      return (
-        (success === false
-          ? await correct(ctx, call, retry, response.body)
-          : null)
-        ?? createExecuteHistory({
-          operation: call.operation,
-          id: call.id,
-          arguments: call.arguments,
-          value: response,
-        })
-      );
-    }
-    catch (error) {
-      // DISPATCH ERROR
-      return createExecuteHistory({
-        operation: call.operation,
-        id: call.id,
-        arguments: call.arguments,
-        value: {
-          status: 500,
-          headers: {},
-          body:
-              error instanceof Error
-                ? {
-                    ...error,
-                    name: error.name,
-                    message: error.message,
-                  }
-                : error,
-        },
-      });
-    }
-  }
-  else {
-    // ----
-    // CLASS FUNCTION
-    // ----
-    // VALIDATE FIRST
-    const check: IValidation<unknown> = call.operation.function.validate(
-      call.arguments,
+      // DISPATCH EVENT
+    return (
+      (success === false
+        ? await correct(props.ctx, props.call, props.retry, response.body)
+        : null)
+      ?? createExecuteHistory({
+        operation: props.call.operation,
+        id: props.call.id,
+        arguments: props.call.arguments,
+        value: response,
+      })
     );
-    if (check.success === false) {
-      ctx.dispatch(
-        createValidateEvent({
-          id: call.id,
-          operation: call.operation,
-          result: check,
-        }),
-      ).catch(() => {});
-      return (
-        (retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)
-          ? await correct(ctx, call, retry, check.errors)
-          : null)
-        ?? createExecuteHistory({
-          id: call.id,
-          operation: call.operation,
-          arguments: call.arguments,
-          value: {
-            name: "TypeGuardError",
-            message: "Invalid arguments.",
-            errors: check.errors,
-          },
-        })
-      );
-    }
-    // EXECUTE FUNCTION
-    try {
-      const value = await executeClassOperation(call.operation, call.arguments);
-      return createExecuteHistory({
-        id: call.id,
-        operation: call.operation,
-        arguments: call.arguments,
-        value,
-      });
-    }
-    catch (error) {
-      return createExecuteHistory({
-        id: call.id,
-        operation: call.operation,
-        arguments: call.arguments,
-        value:
+  }
+  catch (error) {
+    // DISPATCH ERROR
+    return createExecuteHistory({
+      operation: props.call.operation,
+      id: props.call.id,
+      arguments: props.call.arguments,
+      value: {
+        status: 500,
+        headers: {},
+        body:
           error instanceof Error
             ? {
                 ...error,
                 name: error.name,
                 message: error.message,
               }
             : error,
-      });
-    }
+      },
+    });
+  }
+}
+
+async function propagateClass<Model extends ILlmSchema.Model>(props: {
+  ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
+  operation: AgenticaOperation.Class<Model>;
+  call: AgenticaCallEvent<Model>;
+  retry: number;
+}): Promise<AgenticaExecuteHistory<Model>> {
+// ----
+  // CLASS FUNCTION
+  // ----
+  // VALIDATE FIRST
+  const check: IValidation<unknown> = props.operation.function.validate(
+    props.call.arguments,
+  );
+
+  if (check.success === false) {
+    props.ctx.dispatch(
+      createValidateEvent({
+        id: props.call.id,
+        operation: props.call.operation,
+        result: check,
+      }),
+    ).catch(() => {});
+    return (
+      (props.retry++ < (props.ctx.config?.retry ?? AgenticaConstant.RETRY)
+        ? await correct(props.ctx, props.call, props.retry, check.errors)
+        : null)
+      ?? createExecuteHistory({
+        id: props.call.id,
+        operation: props.call.operation,
+        arguments: props.call.arguments,
+        value: {
+          name: "TypeGuardError",
+          message: "Invalid arguments.",
+          errors: check.errors,
+        },
+      })
+    );
+  }
+  // EXECUTE FUNCTION
+  try {
+    const value = await executeClassOperation(props.operation, props.call.arguments);
+    return createExecuteHistory({
+      id: props.call.id,
+      operation: props.call.operation,
+      arguments: props.call.arguments,
+      value,
+    });
+  }
+  catch (error) {
+    return createExecuteHistory({
+      id: props.call.id,
+      operation: props.call.operation,
+      arguments: props.call.arguments,
+      value:
+        error instanceof Error
+          ? {
+              ...error,
+              name: error.name,
+              message: error.message,
+            }
+          : error,
+    });
+  }
+}
+
+async function propagateMcp<Model extends ILlmSchema.Model>(props: {
+  ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>;
+  operation: AgenticaOperation.Mcp;
+  call: AgenticaCallEvent<Model>;
+  retry: number;
+}): Promise<AgenticaExecuteHistory<Model>> {
+  // ----
+  // MCP PROTOCOL
+  // ----
+  // @TODO: implement argument validation logic
path: packages/core/src/orchestrate/call.ts
user: login: Copilot
body: The MCP propagation currently lacks argument validation logic unlike the http and class cases. Please implement or remove the TODO to ensure consistent validation across protocols.
created_at: 2025-04-09T09:39:09Z
author_association: CONTRIBUTOR

PR comments:
user: login: pkg-pr-new[bot]
created_at: 2025-04-08T10:40:53Z
body: 
[Open in StackBlitz](https://pkg.pr.new/template/665d656f-f661-4714-bc25-561fcd5547f6)


<details><summary><b>@agentica/benchmark</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/benchmark@337
```

</p></details>
      
    

<details><summary><b>@agentica/chat</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/chat@337
```

</p></details>
      
    

<details><summary><b>@agentica/core</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/core@337
```

</p></details>
      
    

<details><summary><b>agentica</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica@337
```

</p></details>
      
    

<details><summary><b>create-agentica</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/create-agentica@337
```

</p></details>
      
    

<details><summary><b>@agentica/pg-vector-selector</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/pg-vector-selector@337
```

</p></details>
      
    

<details><summary><b>pg-vector-selector-benchmark</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/pg-vector-selector-benchmark@337
```

</p></details>
      
    

<details><summary><b>@agentica/rpc</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/rpc@337
```

</p></details>
      
    

_commit: <a href="https://github.com/wrtnlabs/agentica/runs/40303520311"><code>38ad80d</code></a>_

author_association: NONE
user: login: pkg-pr-new[bot]
created_at: 2025-04-08T10:40:53Z
body: 
[Open in StackBlitz](https://pkg.pr.new/template/dee249c2-01df-46c2-a117-7f3ee2217b07)


<details><summary><b>@agentica/benchmark</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/benchmark@337
```

</p></details>
      
    

<details><summary><b>@agentica/chat</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/chat@337
```

</p></details>
      
    

<details><summary><b>@agentica/core</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/core@337
```

</p></details>
      
    

<details><summary><b>agentica</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica@337
```

</p></details>
      
    

<details><summary><b>create-agentica</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/create-agentica@337
```

</p></details>
      
    

<details><summary><b>@agentica/pg-vector-selector</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/pg-vector-selector@337
```

</p></details>
      
    

<details><summary><b>pg-vector-selector-benchmark</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/pg-vector-selector-benchmark@337
```

</p></details>
      
    

<details><summary><b>@agentica/rpc</b></summary><p>

```
npm i https://pkg.pr.new/wrtnlabs/agentica/@agentica/rpc@337
```

</p></details>
      
    

_commit: <a href="https://github.com/wrtnlabs/agentica/runs/40168286518"><code>6b5771d</code></a>_

author_association: NONE
user: login: sunrabbit123
created_at: 2025-04-09T07:50:33Z
body: I have manually tested that the module works in both CommonJS and ESM environments, but I haven’t written automated test code for it yet.
I’d like to know how to write proper tests to verify compatibility across both module systems.


author_association: MEMBER
user: login: sunrabbit123
created_at: 2025-04-09T12:15:12Z
body: first. i changed the example code snippet on facade controller chapter

<img width="700" alt="스크린샷 2025-04-09 오후 9 13 10" src="https://github.com/user-attachments/assets/b1a4cdc8-6ecc-4f5c-a59b-de0be35b7f6e" />

second. i changed the description of controller code snippet
<img width="819" alt="스크린샷 2025-04-09 오후 9 14 08" src="https://github.com/user-attachments/assets/2e6017aa-7201-4ae8-98c4-1ffa4f3ce6dd" />

---
How should I explain MCP? @samchon 

We just need to connect them like in the two examples above, and the MCP server will automatically fetch the tool list and handle the calls for us.

The prompt and resources haven't been implemented yet.
author_association: MEMBER
user: login: ryoppippi
created_at: 2025-04-09T12:41:13Z
body: > I have manually tested that the module works in both CommonJS and ESM environments, but I haven’t written automated test code for it yet.
I’d like to know how to write proper tests to verify compatibility across both module systems.

@sunrabbit123 One of the option is mocking api, but it is hard.
Which part is the e2e test ?


author_association: CONTRIBUTOR
user: login: sunrabbit123
created_at: 2025-04-09T12:49:29Z
body: We use a variety of third-party packages, but some of them may only support ESM.
Therefore, when using such packages, we need to ensure our implementation works in both environments.

For example, this was the case with MCP SDK version 4.8.0.
Fortunately, this issue was resolved in SDK version 4.9.0.

umm....
Since it was fixed in version 4.9.0, the test may not be immediately necessary,
but it still seems like something we'll need eventually.
author_association: MEMBER
user: login: ryoppippi
created_at: 2025-04-09T23:22:40Z
body: @sunrabbit123 I saw the top-level-await problems before
good job man... I don't want to support cjs..
author_association: CONTRIBUTOR
user: login: sunrabbit123
created_at: 2025-04-10T02:21:20Z
body: yeah, It is a very convenient path
but we are open-source developer, so support it..
author_association: MEMBER