Skip to content

Commit e7000f7

Browse files
committed
Refactor code formatting and improve consistency across multiple files
- Standardize import statements to use single quotes - Adjust spacing and indentation for better readability - Ensure consistent use of semicolons and line breaks - Miscellaneous style enhancements
1 parent c4a3395 commit e7000f7

File tree

9 files changed

+326
-308
lines changed

9 files changed

+326
-308
lines changed

README.Docker.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ you'll want to build the image for that platform, e.g.:
1616
Then, push it to your registry, e.g. `docker push myregistry.com/apache-ofbiz-mcp-server`.
1717

1818
### References
19-
* [Docker's Node.js guide](https://docs.docker.com/language/nodejs/)
20-
* [Docker's Get Started Sharing guide](https://docs.docker.com/go/get-started-sharing/)
19+
20+
- [Docker's Node.js guide](https://docs.docker.com/language/nodejs/)
21+
- [Docker's Get Started Sharing guide](https://docs.docker.com/go/get-started-sharing/)

README.md

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,55 @@
11
# MCP Server for Apache OFBiz®
22

3-
This project provides a prototype implementation of a Model Context Protocol (MCP) server for Apache OFBiz® that:
4-
3+
This project provides a prototype implementation of a Model Context Protocol (MCP) server for Apache OFBiz® that:
4+
55
- receives requests from an MCP client (usually hosted in a generative AI application such as Claude Desktop) and forwards those requests to a remote backend via RESTful API endpoints,
66
- exposes a template tool that invokes the findProductById OFBiz endpoint.
77

8-
This project can be used as a platform to implement your own tools and enable generative AI applications to interact with any backend system that exposes REST API endpoints, such as [**Apache OFBiz**](https://ofbiz.apache.org) or [**Moqui**](https://www.moqui.org).
8+
This project can be used as a platform to implement your own tools and enable generative AI applications to interact with any backend system that exposes REST API endpoints, such as [**Apache OFBiz**](https://ofbiz.apache.org) or [**Moqui**](https://www.moqui.org).
99

1010
The server is implemented in two versions, one that runs as a local MCP server (stdio transport) and one that runs as a remote MCP server (Streamable HTTP transport).
1111

12-
The project leverages the **Anthropic TypeScript SDK**, and requires:
12+
The project leverages the **Anthropic TypeScript SDK**, and requires:
1313

14-
- Node.js
14+
- Node.js
1515
- npm
1616

1717
This software is licensed under the Apache License, Version 2.0.
1818

19-
Apache OFBiz® is a trademark of the [Apache Software Foundation](https://www.apache.org)
20-
19+
Apache OFBiz® is a trademark of the [Apache Software Foundation](https://www.apache.org)
2120

2221
---
2322

2423
## Table of Contents
25-
1. [Features](#features)
26-
2. [Configuration](#configuration)
27-
3. [Project Structure](#project-structure)
28-
4. [Build the Project](#build-the-project)
29-
5. [Test the Local MCP Server](#test-the-local-mcp-server)
24+
25+
1. [Features](#features)
26+
2. [Configuration](#configuration)
27+
3. [Project Structure](#project-structure)
28+
4. [Build the Project](#build-the-project)
29+
5. [Test the Local MCP Server](#test-the-local-mcp-server)
3030
6. [Test the Remote MCP Server](#test-the-remote-mcp-server)
3131
7. [Inspect the MCP servers](#inspect-the-mcp-servers)
3232

3333
---
3434

3535
## Features
3636

37-
The project includes two alternative MCP servers:
37+
The project includes two alternative MCP servers:
3838

39-
- **Local MCP server** (`src/server-local.ts`) — communicates with the MCP client via stdio transport.
40-
- **Remote MCP server** (`src/server-remote.ts`) — communicates with the MCP client via MCP Streamable HTTP transport.
39+
- **Local MCP server** (`src/server-local.ts`) — communicates with the MCP client via stdio transport.
40+
- **Remote MCP server** (`src/server-remote.ts`) — communicates with the MCP client via MCP Streamable HTTP transport.
4141

42-
The servers dynamically discover MCP tools contained in the `tools` directory.
42+
The servers dynamically discover MCP tools contained in the `tools` directory.
4343

44-
Each tool is defined and implemented in its own file. For example, the sample tool `tools/findProductById.ts` invokes an endpoint in Apache OFBiz to retrieve product information for a given product ID. This works with an out-of-the-box (OOTB) OFBiz instance with the `rest-api` plugin installed.
44+
Each tool is defined and implemented in its own file. For example, the sample tool `tools/findProductById.ts` invokes an endpoint in Apache OFBiz to retrieve product information for a given product ID. This works with an out-of-the-box (OOTB) OFBiz instance with the `rest-api` plugin installed.
4545

4646
New tools can be published by simply including their definition files in the `tools` folder.
4747

4848
The remote server:
49+
4950
- is compliant with the latest MCP specifications (2025-06-18)
5051
- supports authorization according to the MCP recommendations (OAuth Authorization Code Flow with support for Metadata discovery, Dynamic Client Registration, etc...)
51-
- supports the token exchange OAuth flow in order to obtain a valid token for the backend system
52+
- supports the token exchange OAuth flow in order to obtain a valid token for the backend system
5253
- performs token validation with configurable scopes and audience verification
5354
- supports TLS connections (https)
5455
- provides rate limiting features to protect the MCP server and the backend server from denial of service attacks
@@ -58,38 +59,38 @@ The remote server:
5859

5960
## Configuration
6061

61-
Server configuration is managed via `config/config.json`, which defines:
62+
Server configuration is managed via `config/config.json`, which defines:
6263

6364
- **`MCP_SERVER_BASE_URL`** — the base URL of the MCP server (Protected Resource Server in OAuth)
64-
- **`SERVER_PORT`** — the port on which the MCP server listens for client connections (required only for the remote server)
65-
- **`TLS_CERT_PATH`** — path to the file containing the certificate for TLS
66-
- **`TLS_KEY_PATH`** — path to the file containing the private key for TLS
67-
- **`TLS_KEY_PASSPHRASE`** — (optional) passphrase for the **`TLS_KEY_PATH`** file
68-
- **`MCP_SERVER_CORS_ORIGINS`** — CORS origin allowed
65+
- **`SERVER_PORT`** — the port on which the MCP server listens for client connections (required only for the remote server)
66+
- **`TLS_CERT_PATH`** — path to the file containing the certificate for TLS
67+
- **`TLS_KEY_PATH`** — path to the file containing the private key for TLS
68+
- **`TLS_KEY_PASSPHRASE`** — (optional) passphrase for the **`TLS_KEY_PATH`** file
69+
- **`MCP_SERVER_CORS_ORIGINS`** — CORS origin allowed
6970
- **`RATE_LIMIT_WINDOW_MS`** — time window in ms for the requests rate limiting feature
70-
- **`RATE_LIMIT_MAX_REQUESTS`** — max number of requests allowed in the time window
71+
- **`RATE_LIMIT_MAX_REQUESTS`** — max number of requests allowed in the time window
7172
- **`AUTHZ_SERVER_BASE_URL`** — the base URL of the Authorization (Authz) server (OAuth)
72-
- **`SCOPES_SUPPORTED`** — the scopes that the MCP client can request
73-
- **`BACKEND_API_BASE`** — the base URL for backend REST API calls
74-
- **`MCP_SERVER_CLIENT_ID`** — Client ID required for token exchange, as registered in Authz server
75-
- **`MCP_SERVER_CLIENT_SECRET`** — the secret associated with **`MCP_SERVER_CLIENT_ID`**
76-
- **`BACKEND_API_AUDIENCE`** — the OAuth audience paramenter for the backend system
73+
- **`SCOPES_SUPPORTED`** — the scopes that the MCP client can request
74+
- **`BACKEND_API_BASE`** — the base URL for backend REST API calls
75+
- **`MCP_SERVER_CLIENT_ID`** — Client ID required for token exchange, as registered in Authz server
76+
- **`MCP_SERVER_CLIENT_SECRET`** — the secret associated with **`MCP_SERVER_CLIENT_ID`**
77+
- **`BACKEND_API_AUDIENCE`** — the OAuth audience paramenter for the backend system
7778
- **`BACKEND_API_RESOURCE`** — the OAuth resource parameter for the backend system
7879
- **`TOKEN_EXCHANGE_SCOPE`** — the list of scopes requested in the token exchange
7980
- **`BACKEND_API_AUTH`** - the URL to get the OFBiz APIs access token used if token exchange is not enabled
80-
- **`BACKEND_AUTH_TOKEN`** — the token to authorize backend API calls used if token exchange is not enabled
81+
- **`BACKEND_AUTH_TOKEN`** — the token to authorize backend API calls used if token exchange is not enabled
8182

8283
If both **`TLS_CERT_PATH`** and **`TLS_KEY_PATH`** are configured, the MCP server will operate over HTTPS; otherwise, it falls back to HTTP.
8384

8485
If either **`MCP_SERVER_BASE_URL`** or **`AUTHZ_SERVER_BASE_URL`** are not set, authorization is disabled and the MCP server is publicly accessible.
8586

8687
If authorization is enabled, but either **`MCP_SERVER_CLIENT_ID`** or **`MCP_SERVER_CLIENT_SECRET`** are not set, token exchange is disabled.
8788

88-
If token exchange is not enabled, the access token for the OFBiz API can be set **`BACKEND_AUTH_TOKEN`** and can be easily generated and set by running the script:
89+
If token exchange is not enabled, the access token for the OFBiz API can be set **`BACKEND_AUTH_TOKEN`** and can be easily generated and set by running the script:
8990

90-
`update_token.sh <user> <password>`
91+
`update_token.sh <user> <password>`
9192

92-
This script retrieves a JWT for an OOTB OFBiz instance, as specified by **`BACKEND_API_AUTH`** (e.g., `https://demo-stable.ofbiz.apache.org/rest/auth/token`).
93+
This script retrieves a JWT for an OOTB OFBiz instance, as specified by **`BACKEND_API_AUTH`** (e.g., `https://demo-stable.ofbiz.apache.org/rest/auth/token`).
9394

9495
---
9596

@@ -103,13 +104,13 @@ mcp-server-for-apache-ofbiz/
103104
│ ├── server-local.ts # Local MCP server (stdio transport)
104105
│ ├── server-remote.ts # Remote MCP server (Streamable HTTP transport)
105106
│ ├── toolLoader.ts # Loader of tool definitions from "tools/"
106-
│ └── tools/
107+
│ └── tools/
107108
│ └── findProductById.ts # Example tool calling an Apache OFBiz REST endpoint
108109
├── update_token.sh # Script to refresh backend auth token
109110
├── package.json
110111
├── tsconfig.json
111112
└── README.md # This readme file
112-
└── LICENSE # Apache License, Version 2.0
113+
└── LICENSE # Apache License, Version 2.0
113114
```
114115

115116
## Build the Project
@@ -121,14 +122,16 @@ npm run build
121122

122123
## Test the Local MCP Server
123124

124-
You can test the local MCP server with the free version of **Claude Desktop**.
125+
You can test the local MCP server with the free version of **Claude Desktop**.
125126

126127
Edit or create the Claude Desktop configuration file:
127128

128129
```sh
129130
~/Library/Application\ Support/Claude/claude_desktop_config.json
130131
```
132+
131133
Add your local MCP server configuration:
134+
132135
```json
133136
{
134137
"mcpServers": {
@@ -139,29 +142,34 @@ Add your local MCP server configuration:
139142
}
140143
}
141144
```
145+
142146
After updating the configuration file, launch Claude Desktop and try the following sample prompts:
143-
* *"Can you provide some information about the product WG-1111?"*
144-
* *"Create a SEO friendly description for the product with ID GZ-1000"*
145-
* *"Can you provide some information about a product?"*
146-
(Claude will ask for a product ID before invoking the tool.)
147-
* *"Can you compare two products?"*
148-
(Claude will ask for two product IDs, invoke the tool twice, and then compare the results.)
147+
148+
- _"Can you provide some information about the product WG-1111?"_
149+
- _"Create a SEO friendly description for the product with ID GZ-1000"_
150+
- _"Can you provide some information about a product?"_
151+
(Claude will ask for a product ID before invoking the tool.)
152+
- _"Can you compare two products?"_
153+
(Claude will ask for two product IDs, invoke the tool twice, and then compare the results.)
149154

150155
## Test the Remote MCP Server
151156

152157
Start the server:
158+
153159
```sh
154160
node build/server-remote.js
155161
```
156162

157-
You can test the local MCP server with the free version of **Claude Desktop**.
163+
You can test the local MCP server with the free version of **Claude Desktop**.
158164

159165
Edit or create the Claude Desktop configuration file:
160166

161167
```sh
162168
~/Library/Application\ Support/Claude/claude_desktop_config.json
163169
```
170+
164171
Add your local MCP server configuration:
172+
165173
```json
166174
{
167175
"mcpServers": {
@@ -178,7 +186,9 @@ Add your local MCP server configuration:
178186
You can use Anthropic’s **Inspector** to easily test interactions with the local and remote MCP servers. You can do this also when a remote server is executed in your local host or private network, without requiring valid certificates or deploying the server on a publicly accessible host.
179187

180188
Run (and install) the Inspector with:
189+
181190
```sh
182191
npx @modelcontextprotocol/inspector
183192
```
193+
184194
This will open a browser window ready to test your MCP servers.

config/config.json

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"BACKEND_API_BASE": "https://demo-stable.ofbiz.apache.org",
33
"BACKEND_API_AUDIENCE": "https://demo-stable.ofbiz.apache.org",
4-
"BACKEND_API_RESOURCE":"https://demo-stable.ofbiz.apache.org",
4+
"BACKEND_API_RESOURCE": "https://demo-stable.ofbiz.apache.org",
55
"BACKEND_API_AUTH": "https://demo-stable.ofbiz.apache.org/rest/auth/token",
66
"BACKEND_AUTH_TOKEN": "",
77
"AUTHZ_SERVER_BASE_URL": "",
@@ -12,15 +12,9 @@
1212
"TLS_KEY_PATH": "",
1313
"TLS_CERT_PATH": "",
1414
"TLS_KEY_PASSPHRASE": "",
15-
"MCP_SERVER_CORS_ORIGINS": [
16-
"*"
17-
],
18-
"SCOPES_SUPPORTED": [
19-
"mcp:call-tools"
20-
],
15+
"MCP_SERVER_CORS_ORIGINS": ["*"],
16+
"SCOPES_SUPPORTED": ["mcp:call-tools"],
2117
"MCP_SERVER_CLIENT_ID": "",
2218
"MCP_SERVER_CLIENT_SECRET": "",
23-
"TOKEN_EXCHANGE_SCOPE": [
24-
"ofbiz:use-api"
25-
]
19+
"TOKEN_EXCHANGE_SCOPE": ["ofbiz:use-api"]
2620
}

eslint.config.js

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,50 @@
1-
import prettier from "eslint-config-prettier";
2-
import eslintPluginPrettier from "eslint-plugin-prettier";
3-
import tseslint from "@typescript-eslint/eslint-plugin";
4-
import tsParser from "@typescript-eslint/parser";
5-
import importPlugin from "eslint-plugin-import";
1+
import prettier from 'eslint-config-prettier';
2+
import eslintPluginPrettier from 'eslint-plugin-prettier';
3+
import tseslint from '@typescript-eslint/eslint-plugin';
4+
import tsParser from '@typescript-eslint/parser';
5+
import importPlugin from 'eslint-plugin-import';
66

77
export default [
88
{
9-
files: ["**/*.ts"],
10-
ignores: ["build/**", "node_modules/**"],
9+
files: ['**/*.ts'],
10+
ignores: ['build/**', 'node_modules/**'],
1111

1212
languageOptions: {
1313
parser: tsParser,
1414
parserOptions: {
15-
project: "./tsconfig.json",
16-
sourceType: "module",
17-
ecmaVersion: "latest"
18-
}
15+
project: './tsconfig.json',
16+
sourceType: 'module',
17+
ecmaVersion: 'latest',
18+
},
1919
},
2020

2121
plugins: {
22-
"@typescript-eslint": tseslint,
22+
'@typescript-eslint': tseslint,
2323
import: importPlugin,
24-
prettier: eslintPluginPrettier
24+
prettier: eslintPluginPrettier,
2525
},
2626

2727
rules: {
2828
// ---- TypeScript ----
2929
...tseslint.configs.recommended.rules,
30-
"@typescript-eslint/no-unused-vars": [
31-
"warn",
32-
{ argsIgnorePattern: "^_" }
33-
],
30+
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
3431

3532
// ---- Import Rules ----
36-
"import/no-unresolved": "error",
37-
"import/order": [
38-
"warn",
33+
'import/no-unresolved': 'error',
34+
'import/order': [
35+
'warn',
3936
{
40-
groups: ["builtin", "external", "internal", "parent", "sibling", "index"],
41-
"newlines-between": "always"
42-
}
37+
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
38+
'newlines-between': 'always',
39+
},
4340
],
4441

4542
// ---- Prettier ----
4643
// This turns Prettier formatting differences into ESLint errors
47-
"prettier/prettier": "error",
44+
'prettier/prettier': 'error',
4845

4946
// ---- Disable rules overridden by Prettier ----
50-
...prettier.rules
51-
}
52-
}
47+
...prettier.rules,
48+
},
49+
},
5350
];

src/server-local.ts

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,38 @@
1-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3-
import { loadTools } from "./toolLoader.js";
1+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3+
import { loadTools } from './toolLoader.js';
44

55
// Create server instance
66
const server = new McpServer({
7-
name: "Apache OFBiz MCP Server (stdio)",
8-
version: "0.1.0",
7+
name: 'Apache OFBiz MCP Server (stdio)',
8+
version: '0.1.0',
99
});
1010

1111
// Load and register tools from external files
1212
async function registerTools() {
13-
try {
14-
const tools = await loadTools();
15-
16-
for (const tool of tools) {
17-
server.registerTool(
18-
tool.name,
19-
tool.metadata,
20-
tool.handler
21-
);
22-
console.error(`Registered tool: ${tool.name}`);
23-
}
24-
} catch (error) {
25-
console.error("Error loading tools:", error);
26-
throw error;
13+
try {
14+
const tools = await loadTools();
15+
16+
for (const tool of tools) {
17+
server.registerTool(tool.name, tool.metadata, tool.handler);
18+
console.error(`Registered tool: ${tool.name}`);
2719
}
20+
} catch (error) {
21+
console.error('Error loading tools:', error);
22+
throw error;
23+
}
2824
}
2925

3026
// Start the server
3127
async function main() {
32-
await registerTools();
33-
34-
const transport = new StdioServerTransport();
35-
await server.connect(transport);
36-
console.error("Apache OFBiz MCP Server running on stdio");
28+
await registerTools();
29+
30+
const transport = new StdioServerTransport();
31+
await server.connect(transport);
32+
console.error('Apache OFBiz MCP Server running on stdio');
3733
}
3834

3935
main().catch((error) => {
40-
console.error("Fatal error in main():", error);
41-
process.exit(1);
42-
});
36+
console.error('Fatal error in main():', error);
37+
process.exit(1);
38+
});

0 commit comments

Comments
 (0)