Skip to content

Commit 3deae32

Browse files
cpoderclaude
andcommitted
Enrich RAG resources with advanced patterns from 30+ GitHub repos (v2.8.0)
New patterns from Tundra, CloudGenSys, IBM WxMCPServer, supporttestsamples: Flow language reference additions: - REPEAT step: retry with count/interval/backoff, polling with LOOP-ON - BRANCH with label-expressions: complex boolean/regex expression routing - BRANCH with expression-guarded EXIT for conditional loop breaks - SEQUENCE scope attribute for pipeline isolation - Try-alternatives pattern (SEQUENCE EXIT-ON="SUCCESS") New putNode examples (now 20 total): - Example 16: REPEAT retry with backoff - Example 17: LOOP with conditional limit (process-at-most-N) - Example 18: BRANCH with expression labels (multi-condition routing) - Example 19: SOAP client call (WSD connector pattern with soapStatus) Built-in services additions: - pub.client:soapClient (SOAP invocation with fault handling) - pub.client:http (generic HTTP client) - pub.client.ftp:login/get/put/logout (FTP operations) - pub.client.sftp (SFTP operations) Sources: Permafrost/Tundra, Permafrost/TundraTN, CloudGenSys/DevOps, IBM/WxMCPServer, miropacheco/supporttestsamples, mfyasykur/wm-BankTransaction, igtconsulting/messaging-hub, and 20+ other webMethods repos. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b57eab2 commit 3deae32

4 files changed

Lines changed: 245 additions & 3 deletions

File tree

mcp-server-rs/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mcp-server-rs/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "wm-mcp-server"
3-
version = "2.7.0"
3+
version = "2.8.0"
44
edition = "2024"
55
description = "MCP server for webMethods Integration Server — 336 tools replacing Designer for development and administration"
66
license = "MIT"

mcp-server-rs/src/resources.rs

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,53 @@ Conditional execution based on a field value.
180180
"switch": "/fieldName",
181181
"nodes": [
182182
{"type": "SEQUENCE", "label": "value1", "nodes": [/* steps */]},
183+
{"type": "SEQUENCE", "label": "$null", "nodes": [/* null handling */]},
183184
{"type": "SEQUENCE", "label": "$default", "nodes": [/* default steps */]}
184185
]
185186
}
186187
```
188+
Special labels: `$null` (value is null), `$default` (fallback), blank (empty string match).
189+
190+
#### BRANCH with label expressions (expression-based branching)
191+
```json
192+
{
193+
"type": "BRANCH",
194+
"label-expressions": "true",
195+
"nodes": [
196+
{"type": "SEQUENCE", "label": "code = 200", "nodes": [/* success */]},
197+
{"type": "SEQUENCE", "label": "code = 400", "nodes": [/* bad request */]},
198+
{"type": "SEQUENCE", "label": "name != null && status != null", "nodes": [/* both set */]},
199+
{"type": "SEQUENCE", "label": "$default", "nodes": [/* fallback */]}
200+
]
201+
}
202+
```
203+
Expressions support: `=`, `!=`, `null`, `$null`, `&&` (use `&amp;&amp;` in XML), `||`, regex (`/^pattern/`).
204+
205+
#### BRANCH with expression-guarded EXIT (conditional loop break)
206+
```json
207+
{
208+
"type": "BRANCH", "label-expressions": "true",
209+
"nodes": [
210+
{"type": "EXIT", "label": "%count% >= %limit%", "from": "$loop", "signal": "SUCCESS"}
211+
]
212+
}
213+
```
214+
215+
### REPEAT
216+
Retry/polling step. Re-executes children up to `count` times.
217+
```json
218+
{
219+
"type": "REPEAT",
220+
"count": "3",
221+
"repeat-interval": "5",
222+
"repeat-on": "FAILURE",
223+
"nodes": [/* steps to retry */]
224+
}
225+
```
226+
- `repeat-on`: `FAILURE` (retry on error) or `SUCCESS` (poll while succeeding)
227+
- `count`: max retries (`-1` = unlimited). Supports `%variable%` substitution.
228+
- `repeat-interval`: seconds between retries
229+
- `back-off`: multiplier for increasing delay between retries
187230
188231
### SEQUENCE
189232
Group steps with a label and exit condition.
@@ -193,6 +236,23 @@ Group steps with a label and exit condition.
193236
194237
Exit-on values: `FAILURE` (stop on first failure, default), `SUCCESS` (stop on first success), `DONE` (run all regardless).
195238
239+
Optional `scope` attribute restricts pipeline visibility:
240+
```json
241+
{"type": "SEQUENCE", "scope": "$myScope", "exit-on": "FAILURE", "nodes": [/* steps */]}
242+
```
243+
244+
#### Try-alternatives pattern (SEQUENCE EXIT-ON="SUCCESS")
245+
Older alternative to FORM="TRY"/"CATCH". The outer SEQUENCE exits on first success — if the try block succeeds, skip catch:
246+
```json
247+
{
248+
"type": "SEQUENCE", "exit-on": "SUCCESS",
249+
"nodes": [
250+
{"type": "SEQUENCE", "label": "try", "exit-on": "FAILURE", "nodes": [/* business logic */]},
251+
{"type": "INVOKE", "label": "catch", "service": "pub.flow:getLastError"}
252+
]
253+
}
254+
```
255+
196256
### TRY/CATCH (CRITICAL for production services)
197257
198258
TRY/CATCH is implemented using SEQUENCE elements with a `form` attribute. The TRY and CATCH are **sibling** elements (NOT nested).
@@ -962,6 +1022,150 @@ Clean pipeline keeping only specified variables:
9621022
9631023
- `preserve` is a String array (field type `1;1`) listing variable names to keep
9641024
- Everything else is removed from the pipeline
1025+
1026+
## Example 16: REPEAT step (retry on failure with backoff)
1027+
1028+
Retry a service call up to 3 times with 5-second intervals:
1029+
1030+
```json
1031+
{
1032+
"type": "REPEAT", "count": "3", "repeat-interval": "5", "repeat-on": "FAILURE",
1033+
"nodes": [
1034+
{"type": "INVOKE", "service": "mypkg.services:callExternalAPI", "validate-in": "$none", "validate-out": "$none"},
1035+
{"type": "BRANCH", "switch": "/responseCode", "nodes": [
1036+
{"type": "SEQUENCE", "label": "200", "exit-on": "FAILURE", "nodes": []},
1037+
{"type": "SEQUENCE", "label": "$default", "exit-on": "FAILURE", "nodes": [
1038+
{"type": "EXIT", "from": "$parent", "signal": "FAILURE", "failure-message": "API call failed with code %responseCode%"}
1039+
]}
1040+
]}
1041+
]
1042+
}
1043+
```
1044+
1045+
**REPEAT rules:**
1046+
- `repeat-on: "FAILURE"` = retry when a child fails (retry pattern for transient errors)
1047+
- `repeat-on: "SUCCESS"` = repeat while children succeed (polling pattern, e.g., JMS receive loop)
1048+
- `count`: max retries. `-1` = unlimited. Supports `%variable%` substitution.
1049+
- EXIT inside REPEAT with `from: "$loop"` breaks out of the retry loop
1050+
1051+
## Example 17: LOOP with conditional limit (process at most N items)
1052+
1053+
Process items from an array but stop after a configurable limit:
1054+
1055+
```json
1056+
{
1057+
"type": "LOOP", "in-array": "/files", "out-array": "/results",
1058+
"nodes": [
1059+
{"type": "BRANCH", "label-expressions": "true", "nodes": [
1060+
{"type": "EXIT", "label": "%processedCount% >= %limit%", "from": "$loop", "signal": "SUCCESS"}
1061+
]},
1062+
{"type": "SEQUENCE", "exit-on": "FAILURE", "nodes": [
1063+
{"type": "INVOKE", "service": "mypkg.services:processFile", "validate-in": "$none", "validate-out": "$none"},
1064+
{"type": "MAP", "mode": "STANDALONE", "nodes": [
1065+
{"type": "MAPINVOKE", "service": "pub.math:addInts", "validate-in": "$none", "validate-out": "$none", "invoke-order": "0",
1066+
"nodes": [
1067+
{"type": "MAP", "mode": "INVOKEINPUT", "nodes": [
1068+
{"type": "MAPCOPY", "from": "/processedCount;1;0", "to": "/num1;1;0"},
1069+
{"type": "MAPSET", "field": "/num2;1;0", "overwrite": "true",
1070+
"d_enc": "XMLValues", "mapseti18n": "true",
1071+
"data": "<Values version=\"2.0\"><value name=\"xml\">1</value></Values>"}
1072+
]},
1073+
{"type": "MAP", "mode": "INVOKEOUTPUT", "nodes": [
1074+
{"type": "MAPCOPY", "from": "/value;1;0", "to": "/processedCount;1;0"}
1075+
]}
1076+
]
1077+
}
1078+
]}
1079+
]}
1080+
]
1081+
}
1082+
```
1083+
1084+
**Pattern:** BRANCH with `label-expressions: "true"` at the top of the LOOP body acts as a guard. The EXIT label is evaluated as an expression — when it matches, the loop breaks.
1085+
1086+
## Example 18: BRANCH with expression labels (multi-condition routing)
1087+
1088+
Route processing based on complex conditions:
1089+
1090+
```json
1091+
{
1092+
"type": "BRANCH", "label-expressions": "true",
1093+
"nodes": [
1094+
{"type": "SEQUENCE", "label": "name != null &amp;&amp; status != null", "exit-on": "FAILURE",
1095+
"comment": "both name and status provided",
1096+
"nodes": [{"type": "INVOKE", "service": "mypkg.services:searchByNameAndStatus"}]},
1097+
{"type": "SEQUENCE", "label": "name != null", "exit-on": "FAILURE",
1098+
"comment": "only name provided",
1099+
"nodes": [{"type": "INVOKE", "service": "mypkg.services:searchByName"}]},
1100+
{"type": "SEQUENCE", "label": "status != null", "exit-on": "FAILURE",
1101+
"comment": "only status provided",
1102+
"nodes": [{"type": "INVOKE", "service": "mypkg.services:searchByStatus"}]},
1103+
{"type": "SEQUENCE", "label": "$default", "exit-on": "FAILURE",
1104+
"nodes": [{"type": "INVOKE", "service": "mypkg.services:searchAll"}]}
1105+
]
1106+
}
1107+
```
1108+
1109+
**Expression syntax:** `= value`, `!= null`, `== $null`, `&amp;&amp;` (AND), `||` (OR), regex `/^pattern/`.
1110+
First matching expression wins. `$default` is the fallback.
1111+
1112+
## Example 19: SOAP client call (WSD connector pattern)
1113+
1114+
Structure generated by IS when consuming a WSDL:
1115+
1116+
```json
1117+
{
1118+
"type": "SEQUENCE", "exit-on": "FAILURE",
1119+
"nodes": [
1120+
{"type": "MAP", "mode": "STANDALONE", "comment": "set operation",
1121+
"nodes": [
1122+
{"type": "MAPSET", "field": "/wsdOperationName;1;0", "overwrite": "true",
1123+
"d_enc": "XMLValues", "mapseti18n": "true",
1124+
"data": "<Values version=\"2.0\"><value name=\"xml\">getCustomer</value></Values>"}
1125+
]},
1126+
{"type": "MAP", "mode": "STANDALONE", "comment": "map request to SOAP body",
1127+
"nodes": [
1128+
{"type": "MAPCOPY", "from": "/request;4;0;mypkg.docTypes:getCustomerInput", "to": "/request;2;0/getCustomer;2;0"},
1129+
{"type": "MAPSET", "field": "/soapProtocol;1;0", "overwrite": "true",
1130+
"d_enc": "XMLValues", "mapseti18n": "true",
1131+
"data": "<Values version=\"2.0\"><value name=\"xml\">SOAP 1.1 Protocol</value></Values>"}
1132+
]},
1133+
{"type": "INVOKE", "service": "pub.client:soapClient", "validate-in": "$none", "validate-out": "$none",
1134+
"nodes": [
1135+
{"type": "MAP", "mode": "INPUT", "nodes": [
1136+
{"type": "MAPSET", "field": "/method;2;0/localName;1;0", "overwrite": "true",
1137+
"d_enc": "XMLValues", "mapseti18n": "true",
1138+
"data": "<Values version=\"2.0\"><value name=\"xml\">getCustomer</value></Values>"}
1139+
]}
1140+
]},
1141+
{"type": "BRANCH", "switch": "/soapStatus", "comment": "check SOAP success/fault",
1142+
"nodes": [
1143+
{"type": "SEQUENCE", "label": "0", "exit-on": "FAILURE", "comment": "success",
1144+
"nodes": [
1145+
{"type": "MAP", "mode": "STANDALONE", "nodes": [
1146+
{"type": "MAPCOPY", "from": "/response;2;0/getCustomerResponse;2;0", "to": "/result;4;0;mypkg.docTypes:getCustomerOutput"},
1147+
{"type": "MAPDELETE", "field": "/response;2;0"},
1148+
{"type": "MAPDELETE", "field": "/soapStatus;1;0"}
1149+
]}
1150+
]},
1151+
{"type": "SEQUENCE", "label": "$default", "exit-on": "FAILURE", "comment": "SOAP fault",
1152+
"nodes": [
1153+
{"type": "MAP", "mode": "STANDALONE", "nodes": [
1154+
{"type": "MAPCOPY", "from": "/response;2;0/fault;2;0", "to": "/fault;2;0"},
1155+
{"type": "MAPDELETE", "field": "/response;2;0"}
1156+
]}
1157+
]}
1158+
]}
1159+
]
1160+
}
1161+
```
1162+
1163+
**SOAP client pattern (from Tundra, IBM WxMCPServer):**
1164+
- `pub.client:soapClient` is the IS built-in SOAP invoker
1165+
- `soapStatus=0` means success, anything else is a SOAP fault
1166+
- Request: map typed doc -> `/request;2;0/operationName;2;0`
1167+
- Response: extract from `/response;2;0/operationNameResponse;2;0`
1168+
- Fault: extract from `/response;2;0/fault;2;0`
9651169
"#;
9661170

9671171
const ADAPTER_SERVICE_REF: &str = r#"# Adapter Service Configuration Reference
@@ -1841,6 +2045,44 @@ Parses a JSON string into an IData document.
18412045
18422046
---
18432047
2048+
## pub.client (HTTP/SOAP/FTP Client Services)
2049+
2050+
### pub.client:soapClient
2051+
Invokes a SOAP web service endpoint.
2052+
- **In:** `request` (Document - SOAP body), `method` (Document - `localName`, `nsURI`), `soapAction` (String), `address` (String, opt - endpoint URL), `soapProtocol` (String - "SOAP 1.1 Protocol" or "SOAP 1.2 Protocol"), `wsdBinderName` (String, opt)
2053+
- **Out:** `response` (Document - SOAP response body), `soapStatus` (String - "0"=success, "1"=fault), `header` (Document - HTTP headers)
2054+
- **Note:** `soapStatus=0` is success. Check via BRANCH on `/soapStatus`. Fault details in `/response/fault`.
2055+
2056+
### pub.client:http
2057+
Sends an HTTP request (GET, POST, PUT, DELETE, etc.).
2058+
- **In:** `url` (String, req), `method` (String - GET/POST/PUT/DELETE), `data` (Object/String/InputStream), `headers` (Document), `auth` (Document - `type`, `user`, `pass`), `encodingType` (String)
2059+
- **Out:** `header` (Document), `body` (Object), `statusCode` (String), `statusMessage` (String)
2060+
2061+
### pub.client.ftp:login
2062+
Opens FTP connection.
2063+
- **In:** `serverhost` (String), `serverport` (String, default "21"), `username` (String), `password` (String), `transfertype` (String - "ascii"/"binary"), `newSession` (String - "true"/"false"), `secure` (String - "true" for FTPS)
2064+
- **Out:** (session is stored internally)
2065+
2066+
### pub.client.ftp:get
2067+
Downloads file via FTP.
2068+
- **In:** `remoteFile` (String - path on server), `localFile` (String, opt - local path)
2069+
- **Out:** `content` (InputStream if no localFile), `status` (String)
2070+
2071+
### pub.client.ftp:put
2072+
Uploads file via FTP.
2073+
- **In:** `remoteFile` (String), `content` (InputStream/String/bytes), `mode` (String - "ascii"/"binary")
2074+
- **Out:** `status` (String)
2075+
2076+
### pub.client.ftp:logout
2077+
Closes FTP session.
2078+
- **In:** (none)
2079+
- **Out:** (none)
2080+
2081+
### pub.client.sftp:login / put / get / logout
2082+
Same pattern as FTP but for SFTP connections. Uses `serverAlias` or explicit credentials.
2083+
2084+
---
2085+
18442086
## Kafka / Streaming Integration
18452087
18462088
### Kafka Listener Configuration

npm/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@wm-mcp-server/cli",
3-
"version": "2.7.0",
3+
"version": "2.8.0",
44
"description": "MCP server for webMethods Integration Server — 336 tools replacing Designer for development and administration",
55
"license": "MIT",
66
"repository": {

0 commit comments

Comments
 (0)