SuiteScript
NetSuite 2026.1
2026-07-23

MCP Apps: Build Interactive HTML UIs Inside AI Client Chat via Custom Tools

NetSuite now supports MCP Apps — Custom Tool scripts that declare a bundled HTML UI resource via _meta.ui.resourceUri, allowing AI clients connected through the NetSuite AI Connector to render sandboxed interactive interfaces directly in the chat experience.

Affects:SuiteScript 2.1Custom Tool Script TypeN/searchSDFNetSuite AI ConnectorFile Cabinet

What changed

The Custom Tool script framework (@NScriptType CustomTool) now supports MCP Apps — tools that serve a sandboxed, interactive HTML UI inside an MCP-enabled AI client. Previously, custom tools could only return text or structured JSON to the chat. MCP Apps extend this by letting a tool declare a UI resource that the AI client renders inline, enabling form inputs, confirmations, and multi-step workflows without leaving the chat.

New schema attribute: _meta.ui.resourceUri

A custom tool's JSON schema can now include a _meta block that tells the AI client where to load the UI:

  • Format: ui://SuiteApps/<SuiteAppId>/<folder>/mcp-app.html
  • Any tool in the toolset JSON schema that includes this attribute is treated as an MCP App tool; tools without it remain standard text-output tools.

Bundled HTML UI resource

The HTML file referenced by resourceUri must be self-contained — all CSS and JavaScript inlined into a single file. No dynamic dependency loading or external fetches at runtime. The @modelcontextprotocol/ext-apps SDK provides an App class for host communication (receiving tool results, requesting tool execution from the UI).

Deployment constraints

  • For SuiteApps, place the bundled HTML under /SuiteApps/<appId>/....
  • For ACPs (account customization projects), place it under the SuiteScripts folder at the referenced path.
  • Once deployed, the custom tool script, JSON schema, and HTML resource cannot be edited in the File Cabinet. All changes must go through SDF.

Security considerations

Two warnings that are easy to miss:

  • Files in the SuiteScripts folder can be exposed. Any file in your project can be referenced as a UI resource and served to the AI client if a tool's schema points to it.
  • Hidden is not a security boundary. Marking a file as hidden in the File Cabinet does not prevent it from being delivered to AI clients via the NetSuite AI Connector. Access control must be enforced through toolset permissions (the <permissions> block in the toolset XML) and careful schema exposure.

Recommended architecture pattern

Oracle recommends separating logic from UI into distinct tool methods within the same toolset:

  1. A logic tool (standard custom tool) that performs the business operation — e.g., running an N/search saved search.
  2. An MCP App tool that serves the interactive UI and calls the logic tool when user input is collected.

This lets AI clients run the action directly when no interaction is needed, and load the UI only when user input or confirmation is required.

Toolset XML

The toolset SDF object remains the same structure. Key attributes:

  • <scriptfile> — path to the .js custom tool script
  • <rpcschema> — path to the JSON schema (which now may include _meta.ui)
  • <exposetoaiconnector>T</exposetoaiconnector> — required to make tools visible to the AI Connector
  • <permissions> — permission keys and levels that control who can see/invoke the tool

Code structure overview

A minimal MCP App project contains four artifacts:

  1. Custom Tool Script (.js) — SuiteScript 2.1 with @NScriptType CustomTool, exporting async entry points for each tool method.
  2. JSON Schema — defines inputSchema, outputSchema, and annotations for each tool. The MCP App tool additionally includes _meta.ui.resourceUri.
  3. Toolset XML — SDF object binding the script and schema together, setting permissions.
  4. Bundled HTML file — the self-contained UI, built with @modelcontextprotocol/ext-apps.

What to do

  1. Evaluate the pattern. If you have workflows that require user confirmation, form input, or interactive selection before executing a NetSuite operation, MCP Apps let you build that UI without a separate Suitelet or external app.
  2. Review existing custom tools. Any existing @NScriptType CustomTool can be extended into an MCP App by adding _meta.ui.resourceUri to its JSON schema and bundling an HTML file. No script-type change is needed.
  3. Bundle your UI. Use a build tool (Webpack, Vite, esbuild, etc.) to inline all CSS and JS into a single HTML file. The source project does not need to ship in the SuiteCloud project — only the bundled output.
  4. Audit exposed files. Because any file in your SuiteCloud project can be served as a UI resource, review what ships in your SuiteScripts and SuiteApps folders. Do not embed secrets, API keys, or sensitive internal logic in any file that could be referenced by a tool schema. The Hidden flag on File Cabinet files is not enforced by the AI Connector.
  5. Use toolset permissions for access control. Define appropriate <permkey> and <permlevel> entries in your toolset XML. This is the only reliable mechanism to restrict who can invoke your MCP App tools.
  6. Plan for SDF-only editing. Once deployed, you cannot hotfix the script, schema, or HTML via the File Cabinet UI. All changes require an SDF deployment cycle.
  7. Reference the full working sample. Oracle provides a complete example (including the bundled HTML UI) in the MCP App Sample in the SuiteCloud Project Repository on Oracle Samples GitHub.

Open questions

The release notes do not clarify the following — verify in your target account:

  • Whether MCP App HTML files are subject to File Cabinet size limits or separate quotas.
  • Governance impact — the docs do not state whether MCP App tool invocations consume governance units differently from standard custom tool calls.
  • Whether the @modelcontextprotocol/ext-apps SDK version is pinned or auto-updated by Oracle.
  • The exact NetSuite release version introducing this feature is not stated in the source article. The feature is documented as generally available at time of writing but confirm availability in your account's release.