@formio/uag 1.13.0 → 1.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/UAGProjectInterface.js +5 -1
- package/lib/tools/agentProvideData.js +2 -0
- package/lib/tools/annotations.d.ts +34 -0
- package/lib/tools/annotations.js +56 -0
- package/lib/tools/collectData.js +2 -0
- package/lib/tools/confirmSubmission.js +2 -0
- package/lib/tools/fetchExternalData.js +2 -0
- package/lib/tools/findSubmission.js +2 -0
- package/lib/tools/getFieldInfo.js +2 -0
- package/lib/tools/getFormFields.js +2 -0
- package/lib/tools/getForms.js +2 -0
- package/lib/tools/index.d.ts +1 -0
- package/lib/tools/index.js +1 -0
- package/lib/tools/submissionUpdate.js +2 -0
- package/lib/tools/submitForm.js +2 -0
- package/lib/tools/utils.d.ts +2 -0
- package/package.json +6 -6
|
@@ -38,7 +38,11 @@ class UAGProjectInterface extends appserver_1.ProjectInterface {
|
|
|
38
38
|
server.registerTool(tool.name, {
|
|
39
39
|
title: tool.title,
|
|
40
40
|
description: tool.description,
|
|
41
|
-
inputSchema: tool.inputSchema
|
|
41
|
+
inputSchema: tool.inputSchema,
|
|
42
|
+
// Carries readOnly/destructive/idempotent/openWorld through to the
|
|
43
|
+
// client. Tools from config.tools may omit them, so this stays
|
|
44
|
+
// conditional rather than sending `annotations: undefined`.
|
|
45
|
+
...(tool.annotations && { annotations: tool.annotations })
|
|
42
46
|
}, tool.execute);
|
|
43
47
|
}
|
|
44
48
|
}
|
|
@@ -4,11 +4,13 @@ exports.agentProvideData = void 0;
|
|
|
4
4
|
const template_1 = require("../template");
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
7
|
+
const annotations_1 = require("./annotations");
|
|
7
8
|
const agentProvideData = async (project) => {
|
|
8
9
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.agent_provide_data || {}, {
|
|
9
10
|
name: 'agent_provide_data',
|
|
10
11
|
title: 'Agent Provide Data',
|
|
11
12
|
description: 'Provides a mechanism for agents to process existing submission data, understand it, and then to provide additional data values provided a criteria and form context.',
|
|
13
|
+
annotations: (0, annotations_1.reads)('Process submission data'),
|
|
12
14
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
13
15
|
.form_name()
|
|
14
16
|
.submission_id()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool annotations, as presets rather than per-tool literals.
|
|
3
|
+
*
|
|
4
|
+
* Annotations are how a client knows whether a call is safe to make speculatively,
|
|
5
|
+
* safe to retry, and whether it can change data — the difference between an agent
|
|
6
|
+
* that asks before overwriting someone's submission and one that just does it.
|
|
7
|
+
* Spelling the four hints out in ten tool files would guarantee drift, so each tool
|
|
8
|
+
* picks the preset matching its verb and supplies only a human-readable title.
|
|
9
|
+
*
|
|
10
|
+
* `openWorldHint` is true throughout: every tool here resolves forms or submissions
|
|
11
|
+
* against a Form.io deployment, so results depend on a system outside this process.
|
|
12
|
+
*/
|
|
13
|
+
export interface ToolAnnotations {
|
|
14
|
+
title: string;
|
|
15
|
+
readOnlyHint: boolean;
|
|
16
|
+
destructiveHint: boolean;
|
|
17
|
+
idempotentHint: boolean;
|
|
18
|
+
openWorldHint: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Reads, or shapes data in the response without persisting it. Repeatable, and
|
|
22
|
+
* nothing on the server changes — which covers the conversational tools too:
|
|
23
|
+
* `collect_field_data` and `confirm_form_submission` validate and echo back the
|
|
24
|
+
* caller's `form_data`, they do not save it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function reads(title: string): ToolAnnotations;
|
|
27
|
+
/** Creates a record. Calling it twice creates two, so not idempotent. */
|
|
28
|
+
export declare function creates(title: string): ToolAnnotations;
|
|
29
|
+
/**
|
|
30
|
+
* Overwrites an existing record. Destructive because the previous values are gone
|
|
31
|
+
* once it returns; idempotent because applying the same updates again lands the
|
|
32
|
+
* same result.
|
|
33
|
+
*/
|
|
34
|
+
export declare function overwrites(title: string): ToolAnnotations;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP tool annotations, as presets rather than per-tool literals.
|
|
4
|
+
*
|
|
5
|
+
* Annotations are how a client knows whether a call is safe to make speculatively,
|
|
6
|
+
* safe to retry, and whether it can change data — the difference between an agent
|
|
7
|
+
* that asks before overwriting someone's submission and one that just does it.
|
|
8
|
+
* Spelling the four hints out in ten tool files would guarantee drift, so each tool
|
|
9
|
+
* picks the preset matching its verb and supplies only a human-readable title.
|
|
10
|
+
*
|
|
11
|
+
* `openWorldHint` is true throughout: every tool here resolves forms or submissions
|
|
12
|
+
* against a Form.io deployment, so results depend on a system outside this process.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.reads = reads;
|
|
16
|
+
exports.creates = creates;
|
|
17
|
+
exports.overwrites = overwrites;
|
|
18
|
+
/**
|
|
19
|
+
* Reads, or shapes data in the response without persisting it. Repeatable, and
|
|
20
|
+
* nothing on the server changes — which covers the conversational tools too:
|
|
21
|
+
* `collect_field_data` and `confirm_form_submission` validate and echo back the
|
|
22
|
+
* caller's `form_data`, they do not save it.
|
|
23
|
+
*/
|
|
24
|
+
function reads(title) {
|
|
25
|
+
return {
|
|
26
|
+
title,
|
|
27
|
+
readOnlyHint: true,
|
|
28
|
+
destructiveHint: false,
|
|
29
|
+
idempotentHint: true,
|
|
30
|
+
openWorldHint: true,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** Creates a record. Calling it twice creates two, so not idempotent. */
|
|
34
|
+
function creates(title) {
|
|
35
|
+
return {
|
|
36
|
+
title,
|
|
37
|
+
readOnlyHint: false,
|
|
38
|
+
destructiveHint: false,
|
|
39
|
+
idempotentHint: false,
|
|
40
|
+
openWorldHint: true,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Overwrites an existing record. Destructive because the previous values are gone
|
|
45
|
+
* once it returns; idempotent because applying the same updates again lands the
|
|
46
|
+
* same result.
|
|
47
|
+
*/
|
|
48
|
+
function overwrites(title) {
|
|
49
|
+
return {
|
|
50
|
+
title,
|
|
51
|
+
readOnlyHint: false,
|
|
52
|
+
destructiveHint: true,
|
|
53
|
+
idempotentHint: true,
|
|
54
|
+
openWorldHint: true,
|
|
55
|
+
};
|
|
56
|
+
}
|
package/lib/tools/collectData.js
CHANGED
|
@@ -4,11 +4,13 @@ exports.collectData = void 0;
|
|
|
4
4
|
const template_1 = require("../template");
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
7
|
+
const annotations_1 = require("./annotations");
|
|
7
8
|
const collectData = async (project) => {
|
|
8
9
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.collect_field_data || {}, {
|
|
9
10
|
name: 'collect_field_data',
|
|
10
11
|
title: 'Collect Field Data',
|
|
11
12
|
description: 'Collect data for a form, or a specific field with nested components. Identify the component by its path, validate the provided value, and update the form_data object. After updating, determine the next required field to collect or indicate if all required fields are complete. PREREQUISITE: This tool should only be called after the `get_form_fields` tool AND subsequentially the `get_field_info` tool have been called to understand the structure and validation rules of the fields.',
|
|
13
|
+
annotations: (0, annotations_1.reads)('Collect field data'),
|
|
12
14
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
13
15
|
.form_name()
|
|
14
16
|
.form_data()
|
|
@@ -4,11 +4,13 @@ exports.confirmSubmission = void 0;
|
|
|
4
4
|
const template_1 = require("../template");
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
7
|
+
const annotations_1 = require("./annotations");
|
|
7
8
|
const confirmSubmission = async (project) => {
|
|
8
9
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.confirm_form_submission || {}, {
|
|
9
10
|
name: 'confirm_form_submission',
|
|
10
11
|
title: 'Confirm Form Submission',
|
|
11
12
|
description: 'Show a summary of the collected form data if the user wishes to see a summary of the collected data',
|
|
13
|
+
annotations: (0, annotations_1.reads)('Summarise before submitting'),
|
|
12
14
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
13
15
|
.form_name()
|
|
14
16
|
.form_data().schema,
|
|
@@ -6,6 +6,7 @@ const utils_1 = require("./utils");
|
|
|
6
6
|
const core_1 = require("@formio/core");
|
|
7
7
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
8
8
|
const lodash_1 = require("lodash");
|
|
9
|
+
const annotations_1 = require("./annotations");
|
|
9
10
|
const error = require('debug')('formio:uag:fetchExternalData:error');
|
|
10
11
|
/**
|
|
11
12
|
* Strip HTML tags from a string.
|
|
@@ -74,6 +75,7 @@ const fetchExternalData = async (project) => {
|
|
|
74
75
|
name: 'fetch_external_data',
|
|
75
76
|
title: 'Fetch External Data',
|
|
76
77
|
description: 'Fetch external data for a component that loads data from an external URL, a Form.io Resource, or a DataSource. Use this tool when `get_form_fields` indicates that a field requires calling `fetch_external_data` to retrieve its data. For select components, this returns the available options. For datasource components, this returns the fetched data. You can optionally provide a `search_value` to filter results server-side. If the component\'s URL or headers contain interpolation tokens (e.g. `{{ data.someField }}`), you MUST provide `form_data` with the current collected data so the tokens can be resolved.',
|
|
78
|
+
annotations: (0, annotations_1.reads)('Fetch external field data'),
|
|
77
79
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
78
80
|
.form_name()
|
|
79
81
|
.data_path()
|
|
@@ -5,12 +5,14 @@ const template_1 = require("../template");
|
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
const lodash_1 = require("lodash");
|
|
7
7
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
8
|
+
const annotations_1 = require("./annotations");
|
|
8
9
|
const error = require('debug')('formio:uag:findSubmission:error');
|
|
9
10
|
const findSubmission = async (project) => {
|
|
10
11
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.find_submissions || {}, {
|
|
11
12
|
name: 'find_submissions',
|
|
12
13
|
title: 'Find submissions within a form',
|
|
13
14
|
description: 'Find existing form submissions based on field values (search query). Use this to search for people, records, or data by name, email, phone, position, company, or other field values. Examples: find a contact by name, find someone who works at a company, find records with specific criteria. To retrieve the total count of records within a form, use this tool without providing a `search_query`.',
|
|
15
|
+
annotations: (0, annotations_1.reads)('Find submissions'),
|
|
14
16
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
15
17
|
.form_name()
|
|
16
18
|
.search_query()
|
|
@@ -4,12 +4,14 @@ exports.getFieldInfo = void 0;
|
|
|
4
4
|
const template_1 = require("../template");
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
7
|
+
const annotations_1 = require("./annotations");
|
|
7
8
|
const error = require('debug')('formio:uag:getFieldInfo:error');
|
|
8
9
|
const getFieldInfo = async (project) => {
|
|
9
10
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.get_field_info || {}, {
|
|
10
11
|
name: 'get_field_info',
|
|
11
12
|
title: 'Get Field(s) Info',
|
|
12
13
|
description: 'Get detailed information about a specific field(s) that have been provided from the user. It is used to understand the properties, validation rules, and options of the specific field(s) the user has provided values for. This purpose of this tool is to provide detailed information for any field(s) (provided using the `field_paths` parameter) to help understand the structure and requirements of a form. PREREQUISITE: This tool should be called after the `get_form_fields` tool has been called AND once the user has provided some values for the provided fields.',
|
|
14
|
+
annotations: (0, annotations_1.reads)('Get field details'),
|
|
13
15
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
14
16
|
.form_name()
|
|
15
17
|
.field_paths()
|
|
@@ -4,12 +4,14 @@ exports.getFormFields = void 0;
|
|
|
4
4
|
const template_1 = require("../template");
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
7
|
+
const annotations_1 = require("./annotations");
|
|
7
8
|
const error = require('debug')('formio:uag:getFormFields:error');
|
|
8
9
|
const getFormFields = async (project) => {
|
|
9
10
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.get_form_fields || {}, {
|
|
10
11
|
name: 'get_form_fields',
|
|
11
12
|
title: 'Get Form Fields',
|
|
12
13
|
description: 'Get high level overview of the fields that are present in a form, and to understand the "rules" on how the data for each field type should be collected. The purpose of this tool is to determine what fields the user is requesting (and to understand how to format that values for that data), and use that to create a list of field data_path\'s that the user is providing context for. This list can then be provided to the `get_field_info` tool to determine the specific field level information for those fields (validation, required, collection rules, etc). PREREQUISITE: You must call the `get_forms` tool first to understand what forms are available to submit and the permissions associated with those forms.',
|
|
14
|
+
annotations: (0, annotations_1.reads)('Get form fields'),
|
|
13
15
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
14
16
|
.form_name()
|
|
15
17
|
.criteria()
|
package/lib/tools/getForms.js
CHANGED
|
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getForms = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
const template_1 = require("../template");
|
|
6
|
+
const annotations_1 = require("./annotations");
|
|
6
7
|
const getForms = async (project) => {
|
|
7
8
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.get_forms || {}, {
|
|
8
9
|
name: 'get_forms',
|
|
9
10
|
title: 'Get Available Forms',
|
|
10
11
|
description: 'Get a list of all available forms with their descriptions. Use this tool when a user expresses intent to add, create, submit, fill out, register for something (e.g., "I want to add a new Contact", "I need to submit a User Registration", "I met a contact who was the CMO", "What was the email of the contact"). This tool can also be used when they ask what forms are available.',
|
|
12
|
+
annotations: (0, annotations_1.reads)('Get available forms'),
|
|
11
13
|
inputSchema: {},
|
|
12
14
|
execute: async ({}, extra) => {
|
|
13
15
|
const forms = Object.values(project.forms).filter(form => form.uag);
|
package/lib/tools/index.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ import { ToolInfo } from "./utils";
|
|
|
10
10
|
import { UAGProjectInterface } from "../UAGProjectInterface";
|
|
11
11
|
import { fetchExternalData } from "./fetchExternalData";
|
|
12
12
|
export * from './utils';
|
|
13
|
+
export * from './annotations';
|
|
13
14
|
export { getForms, getFormFields, getFieldInfo, collectData, confirmSubmission, submitCompletedForm, findSubmission, submissionUpdate, fetchExternalData };
|
|
14
15
|
export declare const getTools: (project: UAGProjectInterface) => Promise<ToolInfo[]>;
|
package/lib/tools/index.js
CHANGED
|
@@ -35,6 +35,7 @@ const agentProvideData_1 = require("./agentProvideData");
|
|
|
35
35
|
const fetchExternalData_1 = require("./fetchExternalData");
|
|
36
36
|
Object.defineProperty(exports, "fetchExternalData", { enumerable: true, get: function () { return fetchExternalData_1.fetchExternalData; } });
|
|
37
37
|
__exportStar(require("./utils"), exports);
|
|
38
|
+
__exportStar(require("./annotations"), exports);
|
|
38
39
|
const getTools = async (project) => {
|
|
39
40
|
return [
|
|
40
41
|
await (0, getForms_1.getForms)(project),
|
|
@@ -4,12 +4,14 @@ exports.submissionUpdate = void 0;
|
|
|
4
4
|
const template_1 = require("../template");
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
7
|
+
const annotations_1 = require("./annotations");
|
|
7
8
|
const error = require('debug')('formio:uag:submissionUpdate:error');
|
|
8
9
|
const submissionUpdate = async (project) => {
|
|
9
10
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.submission_update || {}, {
|
|
10
11
|
name: 'submission_update',
|
|
11
12
|
title: 'Submission Update',
|
|
12
13
|
description: 'Apply multiple planned field updates to a selected submission after the user confirmed they wish to update the record.',
|
|
14
|
+
annotations: (0, annotations_1.overwrites)('Update a submission'),
|
|
13
15
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
14
16
|
.form_name()
|
|
15
17
|
.submission_id()
|
package/lib/tools/submitForm.js
CHANGED
|
@@ -4,12 +4,14 @@ exports.submitCompletedForm = void 0;
|
|
|
4
4
|
const template_1 = require("../template");
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const SchemaBuilder_1 = require("./SchemaBuilder");
|
|
7
|
+
const annotations_1 = require("./annotations");
|
|
7
8
|
const debug = require('debug')('formio:uag:submitForm');
|
|
8
9
|
const submitCompletedForm = async (project) => {
|
|
9
10
|
return (0, lodash_1.defaultsDeep)(project.config?.toolOverrides?.submit_completed_form || {}, {
|
|
10
11
|
name: 'submit_completed_form',
|
|
11
12
|
title: 'Submit Completed Form',
|
|
12
13
|
description: 'Submit the completed form data. Should only be used once all the required fields have been collected, and the user has explicitly confirmed submission (e.g. has said "submit", "send", "done", etc)',
|
|
14
|
+
annotations: (0, annotations_1.creates)('Submit a completed form'),
|
|
13
15
|
inputSchema: (new SchemaBuilder_1.SchemaBuilder(project))
|
|
14
16
|
.form_name()
|
|
15
17
|
.form_data().schema,
|
package/lib/tools/utils.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ZodRawShape } from "zod";
|
|
2
|
+
import { ToolAnnotations } from "./annotations";
|
|
2
3
|
/**
|
|
3
4
|
* Escape a literal value so it can be carried in a `__regex` query parameter.
|
|
4
5
|
*
|
|
@@ -24,6 +25,7 @@ export type ToolInfo = {
|
|
|
24
25
|
title?: string;
|
|
25
26
|
description?: string;
|
|
26
27
|
inputSchema?: ZodRawShape | undefined;
|
|
28
|
+
annotations?: ToolAnnotations;
|
|
27
29
|
execute?: any;
|
|
28
30
|
};
|
|
29
31
|
export type ParentInfo = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formio/uag",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.2",
|
|
4
4
|
"mcpName": "io.form/formio-uag",
|
|
5
5
|
"description": "The Form.io Universal Agent Gateway (UAG).",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"author": "Form.io Developers",
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@formio/appserver": "^2.14.
|
|
33
|
+
"@formio/appserver": "^2.14.1",
|
|
34
34
|
"@formio/core": "2.8.0",
|
|
35
35
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
36
36
|
"cors": "^2.8.6",
|
|
@@ -59,15 +59,15 @@
|
|
|
59
59
|
"@types/dotenv": "^8.2.3",
|
|
60
60
|
"@types/express": "^5.0.6",
|
|
61
61
|
"@types/jsonwebtoken": "^9.0.10",
|
|
62
|
-
"@types/lodash": "^4.17.
|
|
62
|
+
"@types/lodash": "^4.17.25",
|
|
63
63
|
"@types/mocha": "^10.0.10",
|
|
64
64
|
"@types/node": "^26.1.2",
|
|
65
65
|
"@types/supertest": "^7.2.1",
|
|
66
66
|
"chai": "^6.2.2",
|
|
67
|
-
"mocha": "^11.
|
|
67
|
+
"mocha": "^11.8.0",
|
|
68
68
|
"supertest": "^7.2.2",
|
|
69
|
-
"terser": "^5.49.
|
|
70
|
-
"tsx": "^4.23.
|
|
69
|
+
"terser": "^5.49.1",
|
|
70
|
+
"tsx": "^4.23.5",
|
|
71
71
|
"typescript": "^7.0.2"
|
|
72
72
|
},
|
|
73
73
|
"packageManager": "yarn@4.17.1",
|