Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ npx -y di-mcp-server --authentication-mode basic --basic-username <YOUR_USERNAME

Syntax of the command line:
```bash
npx -y di-mcp-server [--authentication-mode <AUTHENTICATION_MODE>] <CREDENTIALS> --url <RUNTIME_BASE_URL> [--transport <TRANSPORT>] [--deployment-spaces <DEPLOYMENT_SPACES>] [--decision-service-ids <DECISION_SERVICE_IDS>]
npx -y di-mcp-server [--authentication-mode <AUTHENTICATION_MODE>] <CREDENTIALS> --url <RUNTIME_BASE_URL> [--transport <TRANSPORT>] [--deployment-spaces <DEPLOYMENT_SPACES>] [--decision-service-ids <DECISION_SERVICE_IDS>] [--poll-interval <POLL_INTERVAL>]
```

where
Expand All @@ -71,6 +71,7 @@ where
- `TRANSPORT` (optional) is the transport protocol, either `stdio` (default) or `http`.
- `DEPLOYMENT_SPACES` (optional) is a comma-separated list of deployment spaces to scan (defaults to `development`).
- `DECISION_SERVICE_IDS` (optional) If defined, comma-separated list of decision service ids to be exposed as tools
- `POLL_INTERVAL` (optional) is the interval in milliseconds for polling tool changes (defaults to `30000` i.e. 30s), minimum: `1000` i.e. 1s)

The following environment variables can be used in addition to the command line options.

Expand All @@ -85,6 +86,7 @@ The following environment variables can be used in addition to the command line
| --decision-service-ids | DECISION_SERVICE_IDS | Optional comma-separated list of decision services (default: fetch all decision services) |
| --deployment-spaces | DEPLOYMENT_SPACES | Optional comma-separated list of deployment spaces to scan (default: `development`) |
| --debug | DEBUG | When the value is `true`, the debug messages are written to the `stderr` of the MCP server |
| --poll-interval | POLL_INTERVAL | Optional interval in milliseconds for polling tool changes (default: `30000` i.e. 30s, minimum: `1000` i.e 1s) |
| --transport | TRANSPORT | Optional transport protocol: `stdio` (default) or `http` |
| --url | URL | Base URL of the decision runtime </br> |

Expand Down Expand Up @@ -246,6 +248,48 @@ If the default naming strategy doesn't meet the requirements of your MCP hosts,
where
- `OPERATION_ID` is the operation unique identifier
- `YourCustomToolName` is the desired tool name for the operation
## Dynamic Tool Updates

The MCP server implements the `listChanged` capability, which allows it to automatically notify connected clients when the list of available tools changes. This feature enables real-time updates without requiring a server restart.

### How it works

1. **Initial Tool Discovery**: When the server starts, it discovers and registers all available decision service operations as MCP tools.

2. **Continuous Monitoring**: The server polls the Decision Intelligence or Automation Decision Services runtime every 30 seconds to check for changes.

3. **Change Detection**: The server detects the following types of changes:
- **New tools**: When a new decision service operation is deployed
- **Removed tools**: When a decision service operation is undeployed
- **Modified tools**: When the input schema of an operation changes

4. **Client Notification**: When changes are detected, the server sends a `notifications/tools/list_changed` notification to all connected clients, prompting them to refresh their tool list.

### Benefits

- **No restart required**: New or updated decision services become available immediately
- **Automatic synchronization**: Clients stay in sync with the latest decision services
- **Seamless updates**: Changes are detected and propagated automatically

### Configuration

The dynamic tool update feature is enabled by default and requires no additional configuration. The polling interval defaults to 30 seconds (30000 milliseconds), which provides a good balance between responsiveness and system load.

You can customize the polling interval using the `--poll-interval` option or the `POLL_INTERVAL` environment variable:

```bash
# Set polling interval to 60 seconds
npx -y di-mcp-server --di-apikey <YOUR_API_KEY> --url <RUNTIME_URL> --poll-interval 60000
```

Or using an environment variable:
```bash
export POLL_INTERVAL=60000
npx -y di-mcp-server --di-apikey <YOUR_API_KEY> --url <RUNTIME_URL>
```

**Note**: The minimum allowed polling interval is 1000 milliseconds (1 second).


## Technical details

Expand Down
30 changes: 27 additions & 3 deletions src/command-line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export class Configuration {
public version: string,
public debugEnabled: boolean,
public deploymentSpaces: string[] = Configuration.defaultDeploymentSpaces(),
public decisionServiceIds: string[] | undefined = undefined
public decisionServiceIds: string[] | undefined = undefined,
public pollInterval: number = Configuration.defaultPollInterval()
) {
}

Expand All @@ -45,6 +46,10 @@ export class Configuration {
return ['development'];
}

static defaultPollInterval(): number {
return 30000; // 30 seconds in milliseconds
}

isStdioTransport(): boolean {
return this.transport !== undefined;
}
Expand Down Expand Up @@ -168,6 +173,23 @@ function parseDecisionServiceIds(decisionServiceIds: string | undefined): string
return undefined;
}

function validatePollInterval(pollInterval: string | undefined): number {
debug("POLL_INTERVAL=" + pollInterval);
if (pollInterval === undefined) {
const defaultPollInterval = Configuration.defaultPollInterval();
debug(`The poll interval is not defined. Using '${defaultPollInterval}' milliseconds`);
return defaultPollInterval;
}
const parsedInterval = parseInt(pollInterval, 10);
if (isNaN(parsedInterval)) {
throw new Error(`Invalid poll interval: '${pollInterval}'. Must be a valid number in milliseconds.`);
}
if (parsedInterval < 1000) {
throw new Error(`Invalid poll interval: '${pollInterval}'. Must be at least 1000 milliseconds (1 second).`);
}
return parsedInterval;
}

export function createConfiguration(version: string, cliArguments?: readonly string[]): Configuration {
const program = new Command();
program
Expand All @@ -184,7 +206,8 @@ export function createConfiguration(version: string, cliArguments?: readonly str
.option('--basic-password <string>', "Password for the basic authentication")
.option('--transport <transport>', "Transport mode: 'stdio' or 'http'")
.option('--deployment-spaces <list>', "Comma-separated list of deployment spaces to scan (default: 'development')")
.option('--decision-service-ids <list>', 'If defined, comma-separated list of decision service ids to be exposed as tools');
.option('--decision-service-ids <list>', 'If defined, comma-separated list of decision service ids to be exposed as tools')
.option('--poll-interval <milliseconds>', 'Interval in milliseconds for polling tool changes (default: 30000, minimum: 1000)');

program.parse(cliArguments);

Expand All @@ -198,7 +221,8 @@ export function createConfiguration(version: string, cliArguments?: readonly str
const url = validateUrl(options.url || process.env.URL);
const deploymentSpaces = validateDeploymentSpaces(options.deploymentSpaces || process.env.DEPLOYMENT_SPACES);
const decisionServiceIds = parseDecisionServiceIds(options.decisionServiceIds || process.env.DECISION_SERVICE_IDS);
const pollInterval = validatePollInterval(options.pollInterval || process.env.POLL_INTERVAL);

// Create and return configuration object
return new Configuration(credentials, transport, url, version, debugFlag, deploymentSpaces, decisionServiceIds);
return new Configuration(credentials, transport, url, version, debugFlag, deploymentSpaces, decisionServiceIds, pollInterval);
}
Loading