-
Notifications
You must be signed in to change notification settings - Fork 9
Quick‐start guide for tools developers
The MCP server for Apache OFBiz is a platform to run custom tools that invoke remote services exposed through API endpoints. In this guide we will describe how to implement tools in TypeScript. The only requirement is to have Node.js installed in your system.
Create an empty folder for the project
mkdir my_toolsMove into the newly created folder
cd my_toolsand create the folder that will contain the source files
mkdir srcUsing a text editor, create the tsconfig.json file to configure the TypeScript compilation. The following template is provided as a ready to use sample that you can customize to fit your needs
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"verbatimModuleSyntax": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}Moreover, create the package.json file for the project. The following template is provided as a ready to use sample that you can customize to fit your needs.
{
"name": "my_tools",
"version": "1.0.0",
"description": "Custom tools for the MCP server for Apache OFBiz",
"license": "",
"type": "module",
"files": [
"build"
],
"dependencies": {
"zod": "^4.3.5"
},
"devDependencies": {
"mcp-server-for-apache-ofbiz": "github:jacopoc/mcp-server-for-apache-ofbiz#main",
"@types/express": "^5.0.6",
"typescript": "^5.9.3"
},
"scripts": {
"clean": "rm -r ./build",
"build": "tsc"
}
}Note that, according to the sample files above, the TypeScript files in the ./src folder will be transpiled (compiled) into Javascript files and placed in the ./build folder.
There are no mandatory runtime dependencies. However, we have included zod because it is commonly used for the definition of tools metadata.
Among the dev dependencies, that are required only because we are implementing the tools in TypeScript and not directly in JavaScript, there is the MCP server package mcp-server-for-apache-ofbiz. You can edit the associated url in order to implement your tools using a specific release of the MCP server, e.g., github:jacopoc/mcp-server-for-apache-ofbiz#v1.7.0.
As usual, dependencies can be installed by running the command
npm installThe sample package.json file defines two utility scripts, i.e., clean and build, that, respectively, delete the ./buildfolder and compile the TypeScript files, by running
npm run clean
npm run buildThe location of the tool files, ./src in our example, is specified as a command line argument when the MCP server is run. The MCP server reads all the tools definitions contained in the folder's files.
The easiest way to define tools is to create one file per tool.
In this guide we will reference the sample tool definition file findProductById.ts, available under the ./examples/toolsfolder of the MCP server project.
The tool receives a product id string as input and performs a remote call to an OFBiz API to fetch product's information, that is provided as output.
The file's import statements are
import { z } from 'zod';
import type express from 'express';
import type { ServerConfig, ToolDefinition } from 'mcp-server-for-apache-ofbiz/config';In particular, zod is used to specify the input and output schema of the tool.
The MCP server loads only the default function contained in each tool file. In the case of one file per tool, the function should take as input a parameter of type ServerConfig and should return an object of type ToolDefinition, both imported from the MCP server package.
export default function (serverConfig: ServerConfig): ToolDefinition {Alternatively, the return type can be a list of ToolDefinition objects, one for each tool.
ToolDefinition contains three fields
-
name- the name of the tool -
metadata- an object containing-
titleanddescription, whose content is used to inform the Larga Language Model (LLM) about the purpose of the tool; the more accurate and complete the information is, the better the LLM will be able to decide whether to call the tool -
inputSchemaandoutputSchema, which define and describe the input and output parameters of the tool; the parameters' descriptions are also informative for the LLM and have to be defined with care
-
-
handler, which defines the function that is actually executed when the tool is invoked.
Within the handler, the server configuration options can be accessed through the serverConfig object. For example, the base url of the downstream API system is retrieved by means of the BACKEND_API_BASE parameter
const idParam = { idToFind: id };
const inParams = encodeURIComponent(JSON.stringify(idParam));
const backendUrl = `${serverConfig.BACKEND_API_BASE}/rest/services/findProductById?inParams=${inParams}`;If the access to the downstream API system is restricted, the downstream token can be retrieved and set in the request header as follows
if ((request as any).authInfo?.downstreamToken) {
requestOptions.headers['Authorization'] = `Bearer ${(request as any).authInfo.downstreamToken}`;
}For more information on how to setup OAuth authorization, refer to the OAuth/Keycloak concepts guide.
The following code snippet shows how to return a successful response from the tool. The information returned by the API call is structured according to the output schema defined for the tool
const structuredContent = {
productId: responseData.data.product.productId || '',
productName: responseData.data.product.productName || '',
internalName: responseData.data.product.internalName || '',
description: responseData.data.product.description || '',
productTypeId: responseData.data.product.productTypeId || ''
};
return {
content: [
{
type: 'text',
text: JSON.stringify(structuredContent)
}
],
structuredContent: structuredContent
};The following code snippet shows how to return an error
return {
content: [
{
type: 'text',
text: `Error finding product: ${error instanceof Error ? error.message : 'Unknown error'}`
}
],
isError: true
};Create a configuration folder
mkdir configNote that the config folder can be placed anywhere, since its path is specified as a command line argument when the MCP server is executed. In this example, the config folder has been created inside of the main tools folder my_tools.
Inside it, create and edit a config.json file. You can use the config.json file under the examples/config folder of the MCP server project as a template.
With the default configuration provided by the sample config.json file, the MCP server will run with open access and the tool will connect to one of the demo instances hosted by the Apache OFBiz project. Since the OFBiz demo instance restricts access to its API, a downstream access token is required. For simplicity, the following script can be used to get a new token. Place the script inside the folder containing the config folder, in our case inside of my_tools. You can run the script with the command
./update_token.sh admin ofbizwhere admin and ofbiz are the default user and password of the demo OFBiz instance. The script retrieves a token for OFBiz and stores it in the config.json file.
For more details on the available configuration options, refer to the README file.
Once the config.json file is ready, and the tools have been compiled, you can build and run the MCP server
> git clone https://github.com/jacopoc/mcp-server-for-apache-ofbiz.git mcp-server
> cd mcp-server
mcp-server> npm install
mcp-server> npm run build
mcp-server> node build/server.js PATH_TO/my_tools/config PATH_TO/my_tools/buildYou can then use the MCP Inspector to test your tools
npx @modelcontextprotocol/inspector