From dbefd9c45500bb41d318bc7e5d9f55c6394ba735 Mon Sep 17 00:00:00 2001 From: staillanibm Date: Mon, 20 Jul 2026 13:10:33 +0200 Subject: [PATCH 1/3] Flow service generation using flow service language --- mcp-server-rs/src/client/flow_gen.rs | 62 ++++++++++++++++++++++++++++ mcp-server-rs/src/client/mod.rs | 1 + mcp-server-rs/src/params/flow_gen.rs | 38 +++++++++++++++++ mcp-server-rs/src/params/mod.rs | 2 + mcp-server-rs/src/scopes.rs | 18 +++++--- mcp-server-rs/src/server.rs | 47 +++++++++++++++++++++ 6 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 mcp-server-rs/src/client/flow_gen.rs create mode 100644 mcp-server-rs/src/params/flow_gen.rs diff --git a/mcp-server-rs/src/client/flow_gen.rs b/mcp-server-rs/src/client/flow_gen.rs new file mode 100644 index 0000000..35c0649 --- /dev/null +++ b/mcp-server-rs/src/client/flow_gen.rs @@ -0,0 +1,62 @@ +use serde_json::json; + +impl super::ISClient { + // ── DSL Validation ────────────────────────────────────────────────── + // wm.dsl:validate checks DSL source text against its grammar without + // deploying anything. FSL is currently the only DSL implementation on + // IS, but the service is DSL-agnostic — more DSLs may be added later. + + pub async fn dsl_validate(&self, dsl_text: &str) -> Result { + self.invoke_post("wm.dsl:validate", &json!({"dslText": dsl_text})) + .await + } + + // ── FSL Deployment ─────────────────────────────────────────────────── + // wm.server.flowGen:generateFromFSLString compiles FSL source and + // deploys the resulting flow service on IS in a single atomic call. + // The returned `node` field is IS's internal Values/FlowElement tree — + // it is informational only. NEVER repost it via put_node: round-tripping + // it through IS's generic JSON REST serialization flattens the nested + // `flow.nodes` array into a string (e.g. "[INVOKE]"), silently producing + // a service with no logic. generateFromFSLString already deploys the + // service; no follow-up put_node call is needed or safe. + // + // packageName must already exist on IS (use package_create first) — + // this call does not create packages implicitly. + + pub async fn fsl_deploy( + &self, + fsl_string: &str, + package_name: &str, + ifc_name: &str, + flow_name: &str, + ) -> Result { + self.invoke_post( + "wm.server.flowGen:generateFromFSLString", + &json!({ + "fslString": fsl_string, + "packageName": package_name, + "ifcName": ifc_name, + "flowName": flow_name, + }), + ) + .await + } + + // ── FSL Extraction ─────────────────────────────────────────────────── + // wm.server.flowGen:generateFSLFromFlow decompiles an existing flow + // service back into FSL source. The regenerated FSL is semantically + // equivalent but not always textually identical to any FSL originally + // used to create the service (e.g. it may add an explicit `properties` + // block or reformat mappings). On failure for a nonexistent service, + // the IS-side `message` may be a raw internal exception string rather + // than a clean validation message — surface it as-is. + + pub async fn fsl_extract(&self, service_name: &str) -> Result { + self.invoke_post( + "wm.server.flowGen:generateFSLFromFlow", + &json!({"serviceName": service_name}), + ) + .await + } +} diff --git a/mcp-server-rs/src/client/mod.rs b/mcp-server-rs/src/client/mod.rs index 7f7ed9a..7111286 100644 --- a/mcp-server-rs/src/client/mod.rs +++ b/mcp-server-rs/src/client/mod.rs @@ -8,6 +8,7 @@ mod alerts; mod auditing; mod enterprise_gw; mod flow_debug; +mod flow_gen; mod global_vars; mod health; mod ip_access; diff --git a/mcp-server-rs/src/params/flow_gen.rs b/mcp-server-rs/src/params/flow_gen.rs new file mode 100644 index 0000000..c0589dd --- /dev/null +++ b/mcp-server-rs/src/params/flow_gen.rs @@ -0,0 +1,38 @@ +use rmcp::schemars; +use serde::Deserialize; + +#[derive(Debug, Deserialize, schemars::JsonSchema)] +pub struct DslValidateParam { + #[schemars( + description = "DSL source text to validate (FSL is the only DSL currently supported)" + )] + pub dsl_text: String, + #[schemars(description = "Target IS instance name (omit for default)")] + pub instance: Option, +} + +#[derive(Debug, Deserialize, schemars::JsonSchema)] +pub struct FslDeployParam { + #[schemars(description = "FSL source text to compile and deploy")] + pub fsl_string: String, + #[schemars( + description = "Target package name. Must already exist on IS (use package_create first)." + )] + pub package_name: String, + #[schemars(description = "Folder path within the package (e.g. \"services.utils\")")] + pub ifc_name: String, + #[schemars(description = "Unqualified service name to create/update")] + pub flow_name: String, + #[schemars(description = "Target IS instance name (omit for default)")] + pub instance: Option, +} + +#[derive(Debug, Deserialize, schemars::JsonSchema)] +pub struct FslExtractParam { + #[schemars( + description = "Full namespace path of an existing flow service (e.g. \"folder:serviceName\")" + )] + pub service_name: String, + #[schemars(description = "Target IS instance name (omit for default)")] + pub instance: Option, +} diff --git a/mcp-server-rs/src/params/mod.rs b/mcp-server-rs/src/params/mod.rs index 095564c..10c4b20 100644 --- a/mcp-server-rs/src/params/mod.rs +++ b/mcp-server-rs/src/params/mod.rs @@ -2,6 +2,7 @@ pub mod adapters; pub mod auditing; pub mod common; pub mod flow_debug; +pub mod flow_gen; pub mod global_vars; pub mod jar_installer; pub mod jdbc_pools; @@ -28,6 +29,7 @@ pub use adapters::*; pub use auditing::*; pub use common::*; pub use flow_debug::*; +pub use flow_gen::*; pub use global_vars::*; pub use jar_installer::*; pub use jdbc_pools::*; diff --git a/mcp-server-rs/src/scopes.rs b/mcp-server-rs/src/scopes.rs index fb16adf..a241e24 100644 --- a/mcp-server-rs/src/scopes.rs +++ b/mcp-server-rs/src/scopes.rs @@ -26,18 +26,24 @@ pub fn tool_scope(name: &str) -> &'static [&'static str] { n if n.starts_with("password_policy_") => &["admin"], n if n.starts_with("quiesce_") => &["admin"], + // ── fsl-develop ───────────────────────────────────────── + // Narrow scope for the FSL generate/validate/deploy/test cycle + // (a subset of "develop", tagged separately so it can be + // requested on its own without pulling in SAP/flat-file/doc-type + // generation/debugging/testing tools that "develop" also covers). + "dsl_validate" | "fsl_deploy" | "fsl_extract" | "service_invoke" | "node_list" + | "node_get" | "node_delete" | "folder_create" | "package_create" | "package_list" + | "package_reload" | "package_info" => &["fsl-develop", "develop"], + // ── develop ───────────────────────────────────────────── - "flow_service_create" - | "put_node" - | "service_invoke" - | "document_type_create" - | "mapset_value" => &["develop"], + "flow_service_create" | "put_node" | "document_type_create" | "mapset_value" => { + &["develop"] + } n if n.starts_with("flow_debug_") => &["develop"], n if n.starts_with("test_") || n.starts_with("mock_") => &["develop"], n if n.starts_with("doctype_gen_") || n.starts_with("sap_") => &["develop"], n if n.starts_with("ns_dep_") => &["develop"], n if n.starts_with("flatfile_") => &["develop"], - "node_list" | "node_get" | "node_delete" | "folder_create" => &["develop"], n if n.starts_with("package_") => &["develop", "deploy"], // ── adapters ──────────────────────────────────────────── diff --git a/mcp-server-rs/src/server.rs b/mcp-server-rs/src/server.rs index 50d0be5..7815516 100644 --- a/mcp-server-rs/src/server.rs +++ b/mcp-server-rs/src/server.rs @@ -272,6 +272,53 @@ impl WmServer { } } + // ── DSL / FSL Generation ──────────────────────────────────────────── + + #[tool( + description = "Validate DSL source text against its grammar without deploying anything. FSL is currently the only supported DSL. Returns status (SUCCESS/FAILED), validationErrors (list of syntax error messages), and errorCount." + )] + async fn dsl_validate( + &self, + Parameters(p): Parameters, + ) -> Result { + let c = self.get_client(&p.instance)?; + match c.dsl_validate(&p.dsl_text).await { + Ok(v) => json_result(&v), + Err(e) => text_result(&format!("dsl_validate failed: {e}")), + } + } + + #[tool( + description = "Compile FSL source and deploy it as a flow service on IS in a single atomic call. The target package_name must already exist (use package_create first). Returns status (SUCCESS/FAILED), message, and the compiled node (informational only — do not repost it via put_node, this call already deploys the service)." + )] + async fn fsl_deploy( + &self, + Parameters(p): Parameters, + ) -> Result { + let c = self.get_client(&p.instance)?; + match c + .fsl_deploy(&p.fsl_string, &p.package_name, &p.ifc_name, &p.flow_name) + .await + { + Ok(v) => json_result(&v), + Err(e) => text_result(&format!("fsl_deploy failed: {e}")), + } + } + + #[tool( + description = "Decompile an existing flow service back into FSL source. Returns status (SUCCESS/FAILED), fslText, and on failure a message that may be a raw IS-side exception (e.g. for a nonexistent service). The regenerated FSL is semantically equivalent to the deployed service but not always textually identical to any FSL originally used to create it." + )] + async fn fsl_extract( + &self, + Parameters(p): Parameters, + ) -> Result { + let c = self.get_client(&p.instance)?; + match c.fsl_extract(&p.service_name).await { + Ok(v) => json_result(&v), + Err(e) => text_result(&format!("fsl_extract failed: {e}")), + } + } + // ── Document Type Management ─────────────────────────────────────── #[tool(description = "Create a document type. Create parent folders first if needed.")] From ca1f39fcf601c2c74db4732b24506db04cf089bc Mon Sep 17 00:00:00 2001 From: staillanibm Date: Tue, 28 Jul 2026 13:11:30 +0200 Subject: [PATCH 2/3] Fix of deploy scope + documentation enhancements --- README.md | 8 +- mcp-server-rs/Cargo.toml | 2 +- mcp-server-rs/README.md | 5 +- mcp-server-rs/src/config.rs | 2 +- mcp-server-rs/src/resources.rs | 235 +++++++++++++++++++++++++++++++++ mcp-server-rs/src/scopes.rs | 8 +- npm/README.md | 2 +- npm/package.json | 2 +- 8 files changed, 255 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 729a489..cdba735 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Compatible with any MCP client: [IBM Bob](https://www.ibm.com/products/bob), [Cl | Area | What the AI can do | Tools | |---|---|---| | **Flow services** | Create services with full logic (INVOKE, MAP, BRANCH, LOOP, TRY/CATCH), signatures, test them | 5 | +| **FSL generation** | Validate, compile/deploy, and decompile flow services from Flow Service Language (FSL) source text | 3 | | **Flow debugging** | Step-by-step execution, inspect pipeline at each step, set breakpoints, modify variables | 7 | | **Unit testing** | Run test suites, get JUnit/text reports, mock services for isolated testing | 10 | | **Namespace dependencies** | Find dependents, references, unresolved refs, search nodes, refactor/rename | 6 | @@ -56,7 +57,7 @@ Compatible with any MCP client: [IBM Bob](https://www.ibm.com/products/bob), [Cl | **IP access** | Global IP allow/deny rules | 4 | | **WebSocket** | Session management, endpoint creation, broadcast | 4 | -**336 tools + 9 interactive prompts + 5 RAG resources** in total. **184 end-to-end tests** validated against a live IS with real infrastructure (Mosquitto MQTT broker, ActiveMQ JMS, MySQL). +**339 tools + 9 interactive prompts + 5 RAG resources** in total. **184 end-to-end tests** validated against a live IS with real infrastructure (Mosquitto MQTT broker, ActiveMQ JMS, MySQL). ### Interactive setup wizards (prompts) @@ -210,9 +211,12 @@ Set `WM_SCOPES` to restrict which tools are exposed (useful for MCP gateways): ```bash WM_SCOPES=develop,monitor # Only development and monitoring tools WM_SCOPES=readonly # Only read-only tools (list, get, status) +WM_SCOPES=fsl-develop # Only the FSL generate/validate/deploy/test cycle ``` -Available scopes: `admin`, `develop`, `deploy`, `adapters`, `messaging`, `monitor`, `network`, `readonly`. +Available scopes: `admin`, `develop`, `fsl-develop`, `deploy`, `adapters`, `messaging`, `monitor`, `network`, `readonly`. + +`fsl-develop` is a narrow subset of `develop` scoped to the FSL workflow (`dsl_validate`, `fsl_deploy`, `fsl_extract`, `service_invoke`, `node_list`, `node_get`, `node_delete`, `folder_create`, `package_create`, `package_list`, `package_reload`, `package_info`) — use it to expose FSL generation without pulling in SAP, flat-file, doc-type generation, debugging, or unit-testing tools that `develop` also covers. ## Requirements diff --git a/mcp-server-rs/Cargo.toml b/mcp-server-rs/Cargo.toml index 5b83075..c398bdc 100644 --- a/mcp-server-rs/Cargo.toml +++ b/mcp-server-rs/Cargo.toml @@ -2,7 +2,7 @@ name = "wm-mcp-server" version = "2.9.1" edition = "2024" -description = "MCP server for webMethods Integration Server — 336 tools replacing Designer for development and administration" +description = "MCP server for webMethods Integration Server — 339 tools replacing Designer for development and administration" license = "MIT" repository = "https://github.com/cpoder/wm-mcp-server" keywords = ["mcp", "webmethods", "integration-server"] diff --git a/mcp-server-rs/README.md b/mcp-server-rs/README.md index ab637c4..317e4b2 100644 --- a/mcp-server-rs/README.md +++ b/mcp-server-rs/README.md @@ -34,7 +34,7 @@ Set `WM_CONFIG=/path/to/config.json`: } ``` -## Tools Reference (336 tools) +## Tools Reference (339 tools) ### Server & Instances (3) `list_instances`, `is_status`, `is_shutdown` @@ -45,6 +45,9 @@ Set `WM_CONFIG=/path/to/config.json`: ### Flow Services (5) `flow_service_create`, `put_node`, `service_invoke`, `document_type_create`, `mapset_value` +### FSL Generation (3) +`dsl_validate`, `fsl_deploy`, `fsl_extract` + ### Flow Debugging (7) `flow_debug_start`, `flow_debug_execute` (stepOver/stepIn/stepOut/resume/stop), `flow_debug_close`, `flow_debug_insert_breakpoints`, `flow_debug_remove_all_breakpoints`, `flow_debug_set_pipeline`, `flow_debug_stop_service` diff --git a/mcp-server-rs/src/config.rs b/mcp-server-rs/src/config.rs index 9695d45..927a50d 100644 --- a/mcp-server-rs/src/config.rs +++ b/mcp-server-rs/src/config.rs @@ -39,7 +39,7 @@ pub struct AppConfig { pub instances: HashMap, pub default_instance: String, /// Tool scopes to expose. Empty = all tools. Set via WM_SCOPES env var (comma-separated). - /// Valid scopes: admin, develop, adapters, messaging, monitor, deploy, network, readonly + /// Valid scopes: admin, develop, fsl-develop, adapters, messaging, monitor, deploy, network, readonly pub scopes: Vec, } diff --git a/mcp-server-rs/src/resources.rs b/mcp-server-rs/src/resources.rs index 4969111..25cc56d 100644 --- a/mcp-server-rs/src/resources.rs +++ b/mcp-server-rs/src/resources.rs @@ -46,6 +46,12 @@ pub const RESOURCES: &[DocResource] = &[ description: "How to install add-on products (Trading Networks, EDIINT/AS2, EDI) with the IBM Installer in CLI mode, apply fixes with Update Manager (SUM), create database components with the Database Configurator (DCC) for PostgreSQL, and wire JDBC pools + functional aliases. Captures non-obvious gotchas: the PTY-required installer password prompt, the updateFunctionalAlias isolationlevel requirement, and the IS-restart-required rule for Trading Networks.", content: ONPREM_PROVISIONING_REF, }, + DocResource { + uri: "wm://docs/fsl-language-reference", + name: "FSL (Flow Service Language) Reference", + description: "Text-based DSL syntax for authoring flow services with dsl_validate/fsl_deploy/fsl_extract: interface/service/properties structure, copy vs set, reserved-keyword backtick escaping, semicolon placement rules, EXIT/TRY-CATCH, and a complete worked example.", + content: FSL_LANGUAGE_REF, + }, ]; const ONPREM_PROVISIONING_REF: &str = r#"# On-Prem Provisioning, Database & JDBC Configuration @@ -2343,3 +2349,232 @@ webMethods supports publish-and-subscribe, request/reply, and publish-and-wait p - **Universal Messaging:** Self-hosted webMethods messaging broker - **External:** JMS connectors for IBM MQ, Apache Kafka, etc. "#; + +const FSL_LANGUAGE_REF: &str = r#"# FSL (Flow Service Language) Reference + +FSL is a text-based DSL for authoring flow services, used with the +`dsl_validate` / `fsl_deploy` / `fsl_extract` tools as an alternative to +building a service field-by-field via `put_node`. Prefer FSL for anything +beyond a trivial one-step service -- it is far less error-prone than hand +building a putNode tree, and `dsl_validate` lets you catch syntax errors +before touching the server. + +## Workflow + +1. `package_create` the target package if it doesn't already exist (or + confirm with `package_list` / `package_info`) -- `fsl_deploy` does NOT + create the package for you. +2. Write FSL source text (see structure below). +3. `dsl_validate` it -- returns `status` (SUCCESS/FAILED), `validationErrors`, + `errorCount`. Iterate until clean; this is a pure syntax check, no server + mutation. +4. `fsl_deploy` it with `package_name`, `ifc_name` (folder path), and + `flow_name`. This compiles AND deploys in one atomic call -- there is no + separate "create shell then fill it" step like `put_node` requires. The + compiled node returned in the response is informational only; do not + repost it via `put_node`. +5. Verify with `node_get` and a `service_invoke` test call. `fsl_extract` can + decompile an existing service back to FSL (useful to see the canonical + form of something built via `put_node`, or to diff after a redeploy) -- + the round-tripped FSL is semantically equivalent but not always textually + identical to the original source. + +Deploying a `.flow` via `fsl_deploy` does NOT deploy any IS Unit Test suite +associated with it -- test suite files are a separate, filesystem-level +concern outside what this HTTP-only tool surface can reach. + +## File Structure + +Every FSL file starts with an interface declaration (folder path ONLY, never +the package name -- the package goes in `fsl_deploy`'s `package_name` param, +not in the source text), followed by the service declaration and body. + +```fsl +interface orders.receive + +service processOrder ( + input { + String customerId; + Double[] priceList; + } + output { + String status; + } +) +properties { + comment: "Validates and totals an incoming order."; + visible: private; +} +{ + MAP { + mapTarget { + String status; + } + set status = "PENDING"; + } +} +``` + +- No semicolon after the `interface` line. +- `service` declares the name ONLY -- no package, no folder path. +- The `properties { ... }` block (comment, visible, prefetch, validateInput, + validateOutput, ...) goes AFTER the signature and BEFORE the body's `{`. + Every property line inside `properties { }` ends with `;`. +- The body is the last top-level `{ ... }` block, containing the actual steps + (INVOKE, MAP, BRANCH, LOOP, IF, TRY, EXIT, ...). +- No markdown fences, no conversational text -- FSL is raw plain text. + +## copy vs set (do not confuse these) + +- **`copy source -> target;`** -- moves a value already in the pipeline. +- **`set target = "literal";`** -- assigns a hardcoded literal. +- Never `<-`. Never `set "value" -> target;`. Never bare `target = "value";` + without `set`. Never `set` and `copy` the same target in the same block -- + IS runs statements in order, so whichever runs second silently wins and the + other becomes dead code. +- Record/recordList literals are whole-block JSON, never partial slash paths: + `set items = [{"sku": "A1", "qty": "1"}];` -- NOT + `set items/sku = "A1";` for an initial assignment. + +## Reserved keywords need backticks + +If a pipeline variable or schema field name collides with an FSL keyword, it +must be backtick-escaped wherever it's declared or referenced as an +identifier: `pattern`, `value`, `properties`, `type`, `service`, `interface`, +`input`, `output`, `record`, `recordList`, `document`, `branch`, `sequence`, +`loop`, `map`, `mapSource`, `mapTarget`, `copy`, `set`, `drop`. + +This shows up constantly on `pub.math:*`/`pub.string:*` output mappings, +whose return parameter is literally named `value`: + +```fsl +INVOKE pub.math:addInts { + input { + mapSource { + String a; + String b; + } + mapTarget { + String num1; + String num2; + } + copy a -> num1; + copy b -> num2; + } + output { + mapSource { + String `value`; + } + mapTarget { + String sum; + } + copy `value` -> sum; + } +} +``` + +Only the reserved leaf name gets backticks -- non-reserved parent path +segments stay unescaped. + +## Semicolon placement (the #1 source of parser errors) + +- **Statements get a semicolon:** every `set`/`copy`/`drop`, every field + declaration (`String x;`), every property line inside a signature field's + `{ }` block or a `properties { }` block. +- **Step-level properties do NOT get a semicolon:** `comment:`, + `validateInput:`, `invoke-order:`, `switch:`, `inputArray:` etc. when they + appear as the first lines inside a flow step block (MAP, INVOKE, BRANCH, + LOOP, ...). `MAP { comment: "x" }` -- correct. `MAP { comment: "x"; }` -- + parser error. +- **Closing braces never get a semicolon**, for ANY block: MAP, INVOKE, + SEQUENCE, BRANCH, IF/ELSEIF/ELSE, LOOP, WHILE, REPEAT, DO/UNTIL, TRY/CATCH/ + FINALLY, EXIT, TRANSFORM. `SEQUENCE { ... };` is always wrong. +- `BREAK` and `CONTINUE` are standalone -- no trailing semicolon: + `IF (%y% >= 15) { BREAK }`, not `{ BREAK; }`. +- No single-line multi-statement blocks. One declaration/statement/brace per + line, nested structures indented -- this isn't just style, dense one-liners + are a common source of "extraneous input" parse errors. + +## Property ordering inside a step + +Inside any step block, properties must appear before nested steps, in this +order: general (`comment`, `scope`, `timeout`, `label`) first, then +block-specific (`exitOn` for SEQUENCE/TRY/CATCH/FINALLY, `switch`/ +`evaluateLabels` for BRANCH, `inputArray` for LOOP, `count`/`repeatInterval`/ +`repeatOn` for REPEAT), then child steps (MAP, INVOKE, IF, ...). Putting a +child step before a property causes an "extraneous input" error. + +## EXIT and TRY/CATCH (failure paths) + +`EXIT` immediately halts the flow with a signal. `exitFrom: "$flow"` + +`signal: "FAILURE"` is how a service deliberately fails with a message an +IS Unit Test suite can assert against (see the FSL example test-suite note +below): + +```fsl +IF (%amount% < 0) { + comment: "Business rule: amount must be non-negative" + EXIT { + exitFrom: "$flow" + signal: "FAILURE" + failureMessage: "Amount must be greater than or equal to zero" + } +} +``` + +A test case in an IS Unit Test suite that expects this EXIT to fire must use +`` in its +`webMethodsTestCase` -- not a `` IData comparison, which only applies +to normal successful output. + +`TRY`/`CATCH` are adjacent sibling blocks (not nested), matching putNode's +model: put the risky steps in `TRY { }`, recovery/rethrow logic in +`CATCH { }` immediately after. To propagate the failure out of the current +scope from inside CATCH, use `EXIT { exitFrom: "$parent" signal: "FAILURE" }`. + +```fsl +TRY { + INVOKE risky:operation {} +} +CATCH { + EXIT { + exitFrom: "$parent" + signal: "FAILURE" + failureMessage: "risky:operation failed" + } +} +``` + +## INVOKE vs MAP+TRANSFORM + +- Standalone service call, nothing else happening in that step -> `INVOKE + service:name { input { ... } output { ... } }` at the top level. +- Service call bundled with other pipeline work (extra `set`/`copy`/`drop` in + the same logical step) -> wrap it as `MAP { TRANSFORM service:name { ... } }`. + Inside an active `MAP` block, `INVOKE` is never valid -- only `TRANSFORM` is. +- A `MAP` block is either pure direct assignments (`mapSource`/`mapTarget` + + `set`/`copy` at the MAP's own root, no nested TRANSFORM) OR a pure + TRANSFORM wrapper (MAP has no root-level `mapSource`/`mapTarget`, all + mapping lives inside the child TRANSFORM's `input`/`output`). Never mix + both patterns in the same MAP. + +## System variables + +`$retries` (REPEAT), `$iterationCount` (DO/WHILE/LOOP), `$null`, `$flow`, +`$default` are implicitly available in their respective contexts. Never +declare them in `mapSource`/`mapTarget` -- just reference them directly, e.g. +`copy repeatVals[$retries] -> target;`. + +## Type preservation with catalog services + +When mapping into an `INVOKE`/`TRANSFORM` target, the CALLED SERVICE's +declared parameter type always wins over the pipeline source variable's +type -- both `mapTarget` and the calling service's own signature must match +it end-to-end, or the parameter silently arrives as null and the service +throws "Missing Parameter" at runtime. E.g. `pub.math:addInts` takes String +`num1`/`num2` even though it's adding numbers -- an `Integer` pipeline +variable must still be declared `String` in `mapTarget`. Only fall back to +matching the source variable's own type when the target service imposes no +type constraint. +"#; diff --git a/mcp-server-rs/src/scopes.rs b/mcp-server-rs/src/scopes.rs index a241e24..2f98a6e 100644 --- a/mcp-server-rs/src/scopes.rs +++ b/mcp-server-rs/src/scopes.rs @@ -32,8 +32,10 @@ pub fn tool_scope(name: &str) -> &'static [&'static str] { // requested on its own without pulling in SAP/flat-file/doc-type // generation/debugging/testing tools that "develop" also covers). "dsl_validate" | "fsl_deploy" | "fsl_extract" | "service_invoke" | "node_list" - | "node_get" | "node_delete" | "folder_create" | "package_create" | "package_list" - | "package_reload" | "package_info" => &["fsl-develop", "develop"], + | "node_get" | "node_delete" | "folder_create" => &["fsl-develop", "develop"], + "package_create" | "package_list" | "package_reload" | "package_info" => { + &["fsl-develop", "develop", "deploy"] + } // ── develop ───────────────────────────────────────────── "flow_service_create" | "put_node" | "document_type_create" | "mapset_value" => { @@ -121,6 +123,8 @@ fn is_readonly_tool(name: &str) -> bool { || name == "node_list" || name == "node_get" || name == "service_invoke" + || name == "dsl_validate" + || name == "fsl_extract" || name.ends_with("_categories") || name.ends_with("_registries") } diff --git a/npm/README.md b/npm/README.md index 91f8e5e..c378861 100644 --- a/npm/README.md +++ b/npm/README.md @@ -1,6 +1,6 @@ # wm-mcp-server -MCP server for [webMethods Integration Server](https://www.ibm.com/docs/en/webmethods-integration/wm-integration-server/11.1.0) — 336 tools replacing Designer for development and administration. +MCP server for [webMethods Integration Server](https://www.ibm.com/docs/en/webmethods-integration/wm-integration-server/11.1.0) — 339 tools replacing Designer for development and administration. ## Quick Start diff --git a/npm/package.json b/npm/package.json index 62059e1..0030f21 100644 --- a/npm/package.json +++ b/npm/package.json @@ -1,7 +1,7 @@ { "name": "@wm-mcp-server/cli", "version": "2.9.1", - "description": "MCP server for webMethods Integration Server — 336 tools replacing Designer for development and administration", + "description": "MCP server for webMethods Integration Server — 339 tools replacing Designer for development and administration", "license": "MIT", "repository": { "type": "git", From db006ea8bc33f6ec670a04979928cbe847c4db49 Mon Sep 17 00:00:00 2001 From: cpoder Date: Tue, 28 Jul 2026 14:18:42 +0200 Subject: [PATCH 3/3] Register fsl-develop as a documented scope, fix RAG resource count Follow-up to the merge of main, pushed by the maintainer so the PR can go green on its own. `every_scope_in_use_is_documented` failed on `fsl-develop`: the scope was already added to the README list and the AppConfig::scopes doc comment, but DOCUMENTED_SCOPES did not exist on this branch's base, so there was no way to know about the third place the test requires. The README also still advertised 5 RAG resources. It was already stale at 6 before this PR (fb8a730 added the on-prem provisioning resource without updating the count), and the new FSL language reference makes 7. Verified against a resources/list call on the built binary. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01QLxwTsE7P4RmNskk9LuV9L --- README.md | 4 ++-- mcp-server-rs/src/scopes.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 54b9376..7a468de 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Compatible with any MCP client: [IBM Bob](https://www.ibm.com/products/bob), [Cl | **IP access** | Global IP allow/deny rules | 4 | | **WebSocket** | Session management, endpoint creation, broadcast | 4 | -**339 tools + 9 interactive prompts + 5 RAG resources** in total. **184 end-to-end tests** validated against a live IS with real infrastructure (Mosquitto MQTT broker, ActiveMQ JMS, MySQL). +**339 tools + 9 interactive prompts + 7 RAG resources** in total. **184 end-to-end tests** validated against a live IS with real infrastructure (Mosquitto MQTT broker, ActiveMQ JMS, MySQL). ### Interactive setup wizards (prompts) @@ -197,7 +197,7 @@ AI Assistant ──MCP (stdio/HTTP)──> wm-mcp-server (Rust) ──HTTP/JSON All operations use IS built-in HTTP services. No filesystem access needed for most operations (marketplace install requires local access to the IS packages directory). -Flow services are created via `wm.server.ns/putNode` which accepts the full flow tree as JSON -- the same `FlowElement` / `Values` serialization used internally by the IS runtime. The server includes 5 embedded RAG resources with comprehensive flow language documentation, 15 working putNode examples (including TRY/CATCH, LOOP, BRANCH, MAPINVOKE, transactions), and adapter service configuration guides. +Flow services are created via `wm.server.ns/putNode` which accepts the full flow tree as JSON -- the same `FlowElement` / `Values` serialization used internally by the IS runtime. The server includes 7 embedded RAG resources: comprehensive flow language documentation, 15 working putNode examples (including TRY/CATCH, LOOP, BRANCH, MAPINVOKE, transactions), adapter service configuration guides, an FSL language reference, and on-prem provisioning / database setup notes. ### Transport modes diff --git a/mcp-server-rs/src/scopes.rs b/mcp-server-rs/src/scopes.rs index 9ab6efb..93b89f7 100644 --- a/mcp-server-rs/src/scopes.rs +++ b/mcp-server-rs/src/scopes.rs @@ -139,6 +139,7 @@ mod tests { const DOCUMENTED_SCOPES: &[&str] = &[ "admin", "develop", + "fsl-develop", "deploy", "adapters", "messaging",