Skip to main content

Create a Custom MCP Tool

In this lesson we will turn the getCourseByTitle backend script that came with the template package into a Custom MCP Tool. A Custom MCP Tool needs three things: a backend script function to run, a clear name and description so the AI model knows what the tool does, and an input schema so the AI Service can validate the arguments the tool receives.

Review the Backend Script#

Before creating the tool, open the course-tools script from the template package and review the getCourseByTitle function. It is a backend Item Service script: it receives the tool's input, uses the platform APIs to find the Computer Science Course Collection, and returns any course whose title matches the supplied text.

async function getCourseByTitle(input, libraries, ctx, callback) {  const { PlatformApi } = libraries;  const { IafItemSvc } = PlatformApi;
  const title = input.title;
  // Find the Computer Science Course Collection  const colResponse = await IafItemSvc.getNamedUserItems(    { query: { _itemClass: "NamedUserCollection", _name: "Computer Science Course Collection" } },    ctx,    { page: { _offset: 0, _pageSize: 1 } }  );
  const collection = colResponse && colResponse._list && colResponse._list[0];  if (!collection) {    return { success: false, message: "Course collection not found" };  }
  // Find courses whose title matches the supplied text (case-insensitive)  const response = await IafItemSvc.getRelatedItems(    collection._id,    { query: { "properties.courseTitle.val": { "$regex": title, "$options": "i" } } },    ctx,    { page: { _offset: 0, _pageSize: input.limit || 5 } }  );
  return { success: true, courses: response._list };}
  • input – the arguments supplied by the AI model, validated against the schema we define below.
  • libraries – provides the platform APIs. Here we destructure IafItemSvc from PlatformApi to query the Item Service.
  • ctx – the execution context passed automatically by the platform; it carries the request's authorisation and namespace.

Now we will register this function as a Custom MCP Tool. Choose your preferred workflow below.

The template package includes a mcp-setup script so you do not have to write this code yourself. It uses the IafAISvc JavaScript platform library to create and inspect the Custom MCP Tool. Open the mcp-setup script and follow along.

Review the createTool Function#

Locate the createTool function in the mcp-setup script. It calls IafAISvc.createMcpTools with a single tool definition that describes our course lookup tool and points at the backend function you just reviewed.

async function createTool(input, libraries, ctx, callback) {  const { PlatformApi } = libraries;  const { IafAISvc } = PlatformApi;
  const mcpTools = [    {      _namespaces: ctx.project._namespaces,      _name: "GetCourseByTitle",      _description: "Looks up Computer Science courses by title and returns the matching course details, including the course title, description, and instructor. Use this tool whenever the user asks about a specific course by name.",      _schema: {        type: "object",        properties: {          title: { type: "string", description: "The full or partial course title to search for. Matching is case-insensitive." },          limit: { type: "integer", description: "Maximum number of courses to return." }        },        required: ["title"]      },      _script: { _userType: "course_tools", _scriptName: "getCourseByTitle" }    }  ];
  return await IafAISvc.createMcpTools(mcpTools, ctx);}
  • _name – the tool name the AI model uses to identify the tool. It must match ^[a-zA-Z0-9_-]{1,64}$ (letters, numbers, underscores, and hyphens only, no spaces).
  • _description – a detailed explanation of what the tool does and when to use it. This is the single most important field for reliable tool usage, the model reads it to decide whether to call the tool.
  • _namespaces – the namespace(s) the tool belongs to. Here it is read from ctx.project._namespaces, so you do not need to look it up.
  • _schema – a JSON Schema object describing the tool's input arguments. Give every property a clear description; this is how the model knows how to fill in the arguments.
  • _script – points to the backend script that backs the tool, by its _userType and the function name in _scriptName. This is what ties the tool to the getCourseByTitle function.

After reading through the createTool function, run it from the mcp-setup script and review the results. The response contains the created MCP Tool, including its _id.

Verify the Tool#

Locate the getTools function in the same script. It uses IafAISvc.getMcpTools to list the custom (user) MCP tools in your namespace.

async function getTools(input, libraries, ctx, callback) {  const { PlatformApi } = libraries;  const { IafAISvc } = PlatformApi;
  return await IafAISvc.getMcpTools({ _type: "user_mcp_tool" }, ctx);}

Run the getTools function and confirm that GetCourseByTitle appears in the results.

With the Custom MCP Tool created, we are ready to expose it through the AI Service MCP endpoint and call it from an MCP client.