Skip to content
Merged
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
1,520 changes: 756 additions & 764 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@modesty/fluent-mcp",
"version": "0.0.16",
"version": "0.0.17",
"description": "MCP server for Fluent (ServiceNow SDK)",
"keywords": [
"Servicenow SDK",
Expand Down Expand Up @@ -49,32 +49,32 @@
}
},
"dependencies": {
"@modelcontextprotocol/sdk": "1.18.1",
"@servicenow/sdk": "4.0.1",
"@modelcontextprotocol/sdk": "1.19.1",
"@servicenow/sdk": "4.0.2",
"zod": "^3.25.76",
"zod-to-json-schema": "^3.24.6"
},
"devDependencies": {
"@eslint/js": "^9.36.0",
"@eslint/js": "^9.37.0",
"@rollup/plugin-commonjs": "^28.0.6",
"@rollup/plugin-eslint": "^9.0.5",
"@rollup/plugin-json": "^6.0.1",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-node-resolve": "^16.0.2",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.4",
"@types/jest": "^30.0.0",
"@types/node": "^24.5.2",
"@types/node": "^24.7.0",
"@typescript-eslint/eslint-plugin": "^8.44.0",
"@typescript-eslint/parser": "^8.44.0",
"eslint": "^9.36.0",
"jest": "^30.1.3",
"rollup": "^4.52.0",
"eslint": "^9.37.0",
"jest": "^30.2.0",
"rollup": "^4.52.4",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-sourcemaps": "^0.6.3",
"ts-jest": "^29.4.4",
"ts-node": "^10.9.2",
"tslib": "^2.8.1",
"typescript": "~5.9.2"
"typescript": "~5.9.3"
},
"publishConfig": {
"access": "public"
Expand Down
2 changes: 1 addition & 1 deletion res/instruct/fluent_instruct_acl.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Instructions for Fluent Acl (Access Control List) API
Always reference the Acl API specifications for more details.
1. when `type` is `record`, provide the `table` and `field` properties, `applies_to` is only applicable to `record` type ACL too but optional and `name` is not applicable.
1. when `type` is `record`, provide the `table` and `field` properties, `appliesTo` is only applicable to `record` type ACL too but optional and `name` is not applicable.
2. `roles` property is an array of Record<'sys_user_role'>, either sys_ids or Role objects. If using a new role, use the Role object. If using an existing role, use function like `get_sys_id('sys_user_role', 'name=ex_role')` - no `label` field for roles.
3. The `script` property is optional and should only be used for advanced ACLs where the condition cannot be expressed using just the `roles` and `condition` fields.
4. a `named ACL` can be created by providing a value for the `$id` , `type` and `name` properties.
Expand Down
10 changes: 5 additions & 5 deletions res/instruct/fluent_instruct_application-menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Follow the below instructions for top Application Menu
3. The `role` are defined by an array consisting of Role objects or role names that already exist on the platform.

Follow the below instructions for Application Submenu under top Application Menu. Application Submenu is also known as app module or application module at Servicenow platform menu navigator.
1. Identify the right value for `link_type` column from the below combination of it's label and value, as per the user prompts, instructions or devrequest.
1. Identify the right value for `linkType` column from the below combination of it's label and value, as per the user prompts, instructions or devrequest.
2. The below combinations format is "<column label> or <display value>"~"<actual value>". For example: "List of Records"~"LIST" - label is `List of Records` and value is `LIST`.
"None"~""
"Separator"~"SEPARATOR"
Expand All @@ -26,7 +26,7 @@ Follow the below instructions for Application Submenu under top Application Menu
"Map Page"~"MAP"
"Run a Report"~"REPORT"
"URL (from Arguments:)"~"DIRECT"
3. If `link_type` is not specified in user instructions or prompts, then completely skip the field from code generation.
4. `assessment` is link type assessment and is applicable and mandatory only when `link_type` is `ASSESSMENT`.
5. `name` is table associated to link type and is applicable and mandatory only when `link_type` is `FILTER` or `LIST` or `NEW` or `SEARCH` or `DETAIL`.
6. `query` is link type arguments and is mandatory only when `link_type` is `DOC_LINK` or `HTML` or `SCRIPT` or `DIRECT`.
3. If `linkType` is not specified in user instructions or prompts, then completely skip the field from code generation.
4. `assessment` is link type assessment and is applicable and mandatory only when `linkType` is `ASSESSMENT`.
5. `name` is table associated to link type and is applicable and mandatory only when `linkType` is `FILTER` or `LIST` or `NEW` or `SEARCH` or `DETAIL`.
6. `query` is link type arguments and is mandatory only when `linkType` is `DOC_LINK` or `HTML` or `SCRIPT` or `DIRECT`.
6 changes: 3 additions & 3 deletions res/instruct/fluent_instruct_atf.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ To generate ATF (Automated Test Framework) Test in Fluent, ALWAYS start respondi
// Fluent ATF Test
import { Test } from '@servicenow/sdk/core'
import '@servicenow/sdk-core/global'
Test({ // all properties are mandatory
Test({ // all properties are mandatory
$id: Now.ID[''], // fill in a valid GUID string or the name of the test
name: 'Fill in a name for the test', // string
description: 'Fill in a description of the test', // string
Expand Down Expand Up @@ -32,14 +32,14 @@ import '@servicenow/sdk-core/global'
// atf.form.openExistingRecord({
// $id: Now.ID['0004'], // id the test step in the test suite
// table: 'incident',
// recordId: outputOfSubmit.record_id, // use the declared variable to fill in value
// recordId: outputOfSubmit.recordId, // use the declared variable to fill in value
// formUI: 'service_operations_workspace',
// view: '',
// selectedTabIndex: 0,
// })
// atf.server.log({
// $id: Now.ID['0005'], // id the test step in the test suite
// log: `record opened: ${outputOfSubmit.record_id}` // explicitly use ${} for embedding function calls or variables in strings Template Literals
// log: `record opened: ${outputOfSubmit.recordId}` // explicitly use ${} for embedding function calls or variables in strings Template Literals
// })
// Additional steps...
})
Expand Down
4 changes: 2 additions & 2 deletions res/instruct/fluent_instruct_business-rule.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
Always reference the Business Rule API specifications for more details.
1. The `when` field is used to specify when the business rule should be executed. The only valid values for `when` are: before, after, async, display.
2. The `action` field is used to specify the CRUD operations that the business rule applies to. The only valid values for `action` are: insert, update, delete, query.
3. The `add_message` field indicates whether or not to display a message on the UI when the business rule runs. `add_message` === `true` means a message will be displayed.
4. The `condition` and `filter_condition` must be valid ServiceNow encoded query strings.
3. The `addMessage` field indicates whether or not to display a message on the UI when the business rule runs. `addMessage` === `true` means a message will be displayed.
4. The `condition` and `filterCondition` must be valid ServiceNow encoded query strings.
5. For Business Rule updates, do not modify the `script` property unless explicitly specified.
2 changes: 1 addition & 1 deletion res/instruct/fluent_instruct_cross-scope-privilege.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Instructions for Fluent Cross-Scope Privilege API
Always reference the Cross-Scope Privilege API specifications for more details.
1. If target is a table (`target_type` is `sys_db_object`), the supported operations are `create`, `read`, `write`, and `delete`. If target is a script or script include, the only supported operation is `execute`.
1. If target is a table (`targetType` is `sys_db_object`), the supported operations are `create`, `read`, `write`, and `delete`. If target is a script or script include, the only supported operation is `execute`.
2. The status `requested` occurs when an application attempts to access a resource set to Caller Restriction, and requires an admin user to manually change to `allowed` or `denied`.
4 changes: 2 additions & 2 deletions res/instruct/fluent_instruct_form.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Always reference the Form API specifications for more details.
2. To create a new Form view from scratch, you must utilize ALL of the following types of records: `sys_ui_form`, `sys_ui_section`, `sys_ui_form_section`, and `sys_ui_element`
- `sys_ui_form` is a container for multiple form sections
- `sys_ui_section` is a reusable container for form elements
- `sys_ui_form_section` tracks the m2m relationships between sections and forms. Each section in the form MUST have a corresponding `sys_ui_form_section` record
- `sys_ui_element` tracks the fields that will be displayed in a section
- `sys_ui_form_section` tracks the m2m relationships between sections and forms. Each section in the form MUST have a corresponding `sys_ui_form_section` record
- `sys_ui_element` tracks the fields that will be displayed in a section
3. Typically, the first section in a form has no `caption`, but the following sections do have a `caption` that serves as a section title
4. `sys_ui_element` records usually store ordinary fields. However, you can also add column breaks between fields by using `.split` and `.end_split`.
5. Exclude any scripts or duplicate code from your output unless explicitly instructed in the prompt.
Expand Down
3 changes: 2 additions & 1 deletion res/instruct/fluent_instruct_list.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Instructions for Fluent List API
Always reference the List API specifications for more details.
1. For the `view` field, you must either use `default_view` or create a custom view using the `Record` plugin.
- In order to use default_view, you must first import it from '@servicenow/sdk/core'.
- In order to use `default_view`, you must first import it from '@servicenow/sdk/core'.
- In order to use a custom view, you must import the `Record` plugin from '@servicenow/sdk/core' and create a record in the `sys_ui_view` table.
2. $id property is deprecated since v4.0.0.
8 changes: 4 additions & 4 deletions res/instruct/fluent_instruct_role.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Instructions on Fluent Role API
Always reference the Role API specification for more details.
1. `$id`is mandatory and should always be present, format should be `$id: Now.ID['<role name>']`, where '<role name>' is to be replaced with the role name as per user prompt or instructions.
2. `contains_roles` property is an array of Record<'sys_user_role'>, either sys_ids or Role objects. It is optional, it indicates other Role objects that this role contains. If using a new role, use the Role object. If using an existing role, use function like `get_sys_id('sys_user_role', 'name=ex_role')` - no `label` field for roles.
3. `elevated_privilege` is default to `false`, when it's `true`, it means user must manually accept the responsibility of using the role before you can access its features.
4. `can_delegate` is default to `true`, when it's `false`, it means the role cannot be delegated to other users.
1. `$id` is deprecated since v4.0.0.
2. `containsRoles` property is an array of Record<'sys_user_role'>, either sys_ids or Role objects. It is optional, it indicates other Role objects that this role contains. If using a new role, use the Role object. If using an existing role, use function like `get_sys_id('sys_user_role', 'name=ex_role')` - no `label` field for roles.
3. `elevatedPrivilege` is default to `false`. `true` means user must manually accept the responsibility of using the role before you can access its features.
4. `canDelegate` is default to `true`. `false` means the role cannot be delegated to other users.
14 changes: 7 additions & 7 deletions res/instruct/fluent_instruct_scheduled-script.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Instructions on Scheduled Script Execution API
Always reference the Record API specification for more details.
1. The second parameter of the get_sys_id function for `business_calendar` should always query for both `calendar_name` and `label` field, and the query value can only be one of the following: `Year`, `Quarter`, `Month`, `Week`. ex: `calendar_name=Month^ORlabel=Month`.
2. `run_period`, `run_start` and `run_time` should all follow the following date time format: `YYYY-MM-DD HH-MM-SS`.
3. `run_type` can take any 1 of these values: `daily` | `weekly` | `monthly` | `periodically` | `once` | `on_demand` | `business_calendar_start` | `business_calendar_end`.
4. `time_zone` can take any 1 of these values: `floating` | `US/Hawaii` | `Canada Pacific` | `US/Pacific` | `Canada/Mountain` | `US/Mountain` | `US/Arizona` | `Canada/Central` | `US/Central` | `Canada/Eastern` | `US/Eastern` | `Canada/Atlantic` | `Europe/Dublin` | `Europe/London` | `GMT` | `Europe/Amsterdam` | `Europe/Berlin` | `Europe/Brussels` | `Europe/Copenhagan` | `Europe/Madrid` | `Europe/Paris` | `Europe/Rome` | `Europe/Stockholm` | `Europe/Zurich` | `Hongkong`.
5. `run_dayofweek` can take any value between `1` and `7`. `1` is Monday, `2` is Tuesday, `3` is Wednesday, `4` is Thursday, `5` is Friday, `6` is Saturday, and `7` is Sunday.
6. `run_period` is calculated by the time difference between its value and January 1st 1970 at midnight. ex: a job that runs every 2 and a half days will have a `run_period` of `1970-01-03 12:00:00`.
Always reference the Record API specification for more details.
1. The second parameter of the get_sys_id function for `businessCalendar` should always query for both `calendar_name` and `label` field, and the query value can only be one of the following: `Year`, `Quarter`, `Month`, `Week`. ex: `calendar_name=Month^ORlabel=Month`.
2. `runPeriod`, `runStart` and `runTime` should all follow the following date time format: `YYYY-MM-DD HH-MM-SS`.
3. `runType` can take any 1 of these values: `daily` | `weekly` | `monthly` | `periodically` | `once` | `on_demand` | `business_calendar_start` | `business_calendar_end`.
4. `timeZone` can take any 1 of these values: `floating` | `US/Hawaii` | `Canada Pacific` | `US/Pacific` | `Canada/Mountain` | `US/Mountain` | `US/Arizona` | `Canada/Central` | `US/Central` | `Canada/Eastern` | `US/Eastern` | `Canada/Atlantic` | `Europe/Dublin` | `Europe/London` | `GMT` | `Europe/Amsterdam` | `Europe/Berlin` | `Europe/Brussels` | `Europe/Copenhagan` | `Europe/Madrid` | `Europe/Paris` | `Europe/Rome` | `Europe/Stockholm` | `Europe/Zurich` | `Hongkong`.
5. `runDayofweek` can take any value between `1` and `7`. `1` is Monday, `2` is Tuesday, `3` is Wednesday, `4` is Thursday, `5` is Friday, `6` is Saturday, and `7` is Sunday.
6. `runPeriod` is calculated by the time difference between its value and January 1st 1970 at midnight. ex: a job that runs every 2 and a half days will have a `runPeriod` of `1970-01-03 12:00:00`.
9 changes: 9 additions & 0 deletions res/instruct/fluent_instruct_script-action.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Instructions for Fluent Script Action API
Always reference the Script Action API specifications for more details.
1. Use the `ScriptAction` API to define a server-side script that executes when a specific event is triggered.
2. The `eventName` property must match the name of a registered event in the Event Registry (`sysevent_registry`).
3. The `script` property should be a function that contains the JavaScript code to be executed. This script has access to the `current` (the record that triggered the event) and `event` (the event object itself) variables. You can provide an inline arrow function or import a function from another module.
4. By default, Script Actions run asynchronously. This is a best practice to avoid performance impacts on user transactions.
5. Use the `event.parm1` and `event.parm2` properties to pass additional information from the triggering script to the Script Action.
6. The `conditionScript` is a string containing a server-side script that must evaluate to true for the action to execute (e.g., `"gs.hasRole('admin')"`).
7. Before creating a Script Action, ensure the event it responds to is registered in the ServiceNow Event Registry.
9 changes: 8 additions & 1 deletion res/instruct/fluent_instruct_script-include.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Instructions for Fluent Script Include API
Always reference the Script Include API specifications for more details.
1. `caller_access` property only applies when `access` is set to `public`

**Key Changes in v4:**
* Import the API as `import { ScriptInclude } from '@servicenow/sdk/core';`.
* The `script` property can now use the `Now.include()` helper to include a script from a file (e.g., `script: Now.include("./SampleClass.server.js")`).

**Best Practices:**
1. `callerAccess` property only applies when `accessibleFrom` is set to `package_private`.
2. Use `Now.include()` to keep your script logic in separate files for better organization and maintainability.
2 changes: 1 addition & 1 deletion res/instruct/fluent_instruct_scripted-rest.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Instructions for Fluent Scripted REST API
Always reference the Scripted REST API specifications for more details.
1. Each Scripted REST API can contain more than one Route, each route is corresponding to HTTP verb.
2. To not `enforce_acl` set this field to be an empty array, otherwise specify a list of ACL object ot sys_ids
2. To not `enforceAcl` set this field to be an empty array, otherwise specify a list of ACL object ot sys_ids
3. The `consumes` field contains a list of media types/resources that the API can consume, default values here are: application/json, application/xml, text/xml.
ACL objects from the fluent ACL spec.
4. The `produces` field contains a list of media types/resources that the API can produce, default values here are: application/json, application/xml, text/xml.
Expand Down
64 changes: 64 additions & 0 deletions res/instruct/fluent_instruct_service-portal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Instructions for Fluent Service Portal APIs

Always reference the Service Portal API specifications for more details.

## SpWidget API

1. **Templates and Controllers**:
- Use AngularJS data binding: `{{c.data.property}}` (controller accessible as `c` by default)
- Override controller alias with `controllerAs` property if needed
- Use `cssTemplate` for simple styles, `sassSrc` for complex SCSS with variables

2. **Scripts**:
- **Client script**: AngularJS controller function. Use `c.server.get()` or `c.server.update()` to communicate with server
- **Server script**: Runs before rendering. Access `input`, store data in `data`, use `options` for widget configuration
- **Link function**: Only for direct DOM manipulation. Avoid unless necessary

3. **Configuration**:
- Define `optionSchema` as JSON array for configurable widgets: `{name, label, type, default_value}`
- Use `field_list` to specify which fields from `dataTable` are available
- Set `controllable: true` to allow widget communication via events (`$scope.$on()`)

4. **Security**:
- Set `roles` property to restrict visibility
- Use `public: true` for unauthenticated access
- Always check `gs.hasRole()` in server script for sensitive operations

5. **Dependencies**:
- Use `scriptIncludes` array for server-side script includes
- Create SPWidgetDependency records for client-side libraries

## SPWidgetDependency API

1. **Loading**:
- Use `order` to control load sequence (lower numbers load first, default: 100)
- Separate multiple URLs with newlines in `jsIncludes` or `cssIncludes`

2. **Angular Modules**:
- Set `angularModuleName` when including Angular modules
- Module name must match the actual Angular module name

3. **Inline Code**:
- Include inline JavaScript or CSS directly for small utilities
- Use `version` property to track external library versions

## SpAngularProvider API

1. **Provider Types** (lowercase):
- **service**: Business logic, instantiated as singleton with `new`
- **factory**: Returns object/function, more flexible than service
- **directive**: Reusable UI components. Use `restrict: 'E'` for elements, `'A'` for attributes
- **filter**: Data transformation in templates. Keep pure functions
- **constant**: Immutable configuration values
- **value**: Simple values that can be overridden
- **provider**: Advanced configuration with `$get` method

2. **Best Practices**:
- Inject dependencies as function parameters: `$http`, `$q`, `$timeout`, `$sce`
- Set `restricted: true` and specify `roles` for role-based access
- Name services/factories in PascalCase, directives/filters in camelCase

3. **Common Issues**:
- Avoid heavy computations in filters (run on every digest cycle)
- Don't manipulate DOM in services/factories - use directives
- Always handle promise rejections with error callbacks
Loading