Suite Utils
Open source
FreeClaude Code onlyUPL-1.0v0.5.1

NetSuite Claude harness

Caches NetSuite metadata, keeps big results out of context and checks SuiteQL before Claude runs it.

Runs in Claude Code only: the CLI, the Code tab in the Claude desktop app, or an IDE extension. Cowork and claude.ai don't run plugin hooks, so none of the checks happen there.

Not affiliated with Oracle or Anthropic.

A Claude Code session running through the su-ns-harness plugin: a top bar links a Claude Code label, a su-ns-harness box and a NetSuite AI Connector label. A card titled Top 20 customers by open AR, labelled Claude writes SuiteQL, shows the query as a diff: SELECT entity, currency, SUM(foreignamountunpaid) AS open_ar FROM transaction WHERE type = 'CustInvc' AND ROWNUM <= 20 GROUP BY entity, currency. The AND ROWNUM <= 20 condition is struck through in red, and two lines are added: ORDER BY SUM(foreignamountunpaid) DESC and FETCH FIRST 20 ROWS ONLY. A red row reads Blocked before the call: ROWNUM caps rows before GROUP BY: wrong totals. The next row shows ns_runCustomSuiteQL returning 20 rows, summed over every open invoice, and the row after it reads Claude gets the real top 20, per currency. The last line shows the same check from a terminal: nsx sql lint on a query ending ROWNUM <= 20 GROUP BY entity, with Exit 1.

Two commands inside Claude Code

A Claude Code plugin for Oracle's NetSuite AI Connector. Its hooks run before and after every connector call. Catalogs are cached on your machine, large results are saved to a file and summarised, and SuiteQL that would return wrong totals is blocked with a suggested fix. Creates and updates stay off until you turn them on.

  • Claude Code (the CLI, the Code tab in the Claude desktop app, or an IDE extension)
  • Node.js 18 or newer on your PATH
  • The NetSuite AI Connector, with the MCP Standard Tools SuiteApp installed
  • A NetSuite role with the MCP Server Connection permission
  1. /plugin marketplace add suiteutils/suiteutils-netsuite-claude-harness
  2. /plugin install su-ns-harness@suiteutils

Then run /reload-plugins or start a new session. Set up the NetSuite AI Connector first: Oracle's getting started guide covers the NetSuite side, and our install guide covers connecting it to Claude.

Hooks around every connector call

Metadata cached on your machine

Report lists, saved searches, subsidiaries, periods, record types and field metadata are cached locally, each section with its own expiry. Claude looks them up with the bundled nsx CLI instead of calling the connector again.

Big results go to a file

A result over 6,000 characters is saved locally. Claude gets the row count, column stats, the first rows and a result id. For a 3,000-row result that's under 1,500 characters. Claude then totals, filters or pivots the file instead of querying NetSuite again.

SuiteQL checked before it runs

ROWNUM next to GROUP BY or ORDER BY caps rows before aggregating, so the query is blocked and a FETCH FIRST version comes back with the error. OFFSET, LIMIT, WITH, unsupported functions and swapped type values are blocked too.

Errors come back with a next step

On a rate limit, Claude waits about 5, 10 and then 20 seconds between retries, one call at a time. Auth errors say to reconnect via /mcp. A bad field marks that table's field cache stale.

Writes off until you turn them on

Creates and updates are blocked by default. With writes on, each one needs a preview, a call with the same input and your approval. Every NetSuite call, writes included, goes in a local audit log.

No dependencies, no network calls

The code is one bundled file that imports only Node's built-in modules. Installing it fetches no npm packages, so there's no upstream package that could be swapped for malicious code. It makes no network calls and doesn't touch the connector's OAuth.

Why a plugin, not a skill

Oracle publishes a skill for the connector, netsuite-ai-connector-instructions. The NetSuite team wrote it, and it's a good set of instructions. This plugin's skill is derived from it.

A skill is text Claude reads and then decides whether to follow. Nothing checks the query before it reaches NetSuite. Nothing changes what comes back. This plugin keeps the skill and adds hooks: code Claude Code runs on every connector call, which the model can't skip.

Before the call

The SuiteQL is parsed and checked. A query that would return wrong totals is denied with the rule and a fix, so it never reaches NetSuite. Writes are denied, or sent to your approval prompt when you've turned them on.

After the call

Catalog results are cached. A result over 6,000 characters (the default limit) goes to a local file, and Claude gets a summary and a result id instead of the raw rows. Every call lands in an audit log.

Same verdict every time

The same query gets the same verdict every time, because the checker is code. If a hook itself breaks, reads go through unchanged and writes are blocked.

Oracle's skillNetSuite Claude harness
Report lists, saved searches, field metadataFetched from NetSuite whenever Claude needs them.Cached locally and searched with nsx. Refreshed when a section goes stale.
A 3,000-row query resultAll of it lands in Claude's context.Saved to a local file. Claude gets a summary and a result id, then works on the file.
Row caps (ROWNUM)Templates put ROWNUM next to GROUP BY and ORDER BY, which caps rows before aggregating or sorting. Wrong totals, wrong top-N.The query is blocked and a FETCH FIRST version is suggested. An outer ROWNUM is blocked too, because NetSuite applies it before the inner GROUP BY.
type vs recordtype valuesMixed up in places.Swapped values are blocked, with the right value.
approvalstatus filtersApplied broadly.Allowed only on types where your account uses approvals. Elsewhere the field is empty and the filter returns zero rows.
Account facts (currency, fiscal year, subsidiaries, open periods)Looked up again in each new session.A short profile is loaded at the start of every session.
Rate limits, auth and field errorsGeneral advice in the text. Claude decides what to do.Classified, with a recovery step. Spaced retries one call at a time, "reconnect via /mcp", stale field cache refreshed.
Creates and updatesA request in the text to confirm first.Blocked by default. When enabled, a preview, a call with the same input, your approval prompt and an audit log.

Claude still picks the tables, writes the query and reads the result. Why a plugin, not a skill covers what runs as code and what stays with Claude.

Install guide, settings and reference

Open the docs

Getting started

Using it

Reference

Questions

Where does it run?

Only in Claude Code: the CLI, the Code tab in the Claude desktop app, or an IDE extension. The plugin works through Claude Code hooks, and Cowork and claude.ai don't run plugin hooks yet. You can install it there, but you'd get only the skill's guidance: no caching, no SuiteQL checks and no write protection. If you use those apps, control writes through the connector role's permissions in NetSuite.

Is it free?

Yes. It's open source under the Universal Permissive License 1.0. The netsuite skill inside it is derived from Oracle's own connector skill, which uses the same license.

Does it send my NetSuite data anywhere?

No. The plugin makes no network calls of its own. The NetSuite AI Connector is still the only thing that talks to NetSuite. The cache, saved results and audit log stay in the plugin's data folder under ~/.claude/plugins/data/. Nothing goes into your project unless you export it.

Do I need Oracle's netsuite-ai-connector-instructions skill?

No, and you should remove it if you added it. This plugin's netsuite skill is derived from it and fixes its templates. With both installed, Claude gets conflicting instructions, including the ROWNUM pattern this plugin blocks.

Can it create or update records?

Only after you turn writes on yourself, from your own terminal. The settings command refuses that change when Claude runs it. After that, each create or update needs a preview, a call with exactly the previewed input and your approval in Claude Code's permission prompt. Creates also need an externalId, so a retry can't make a duplicate record.

Which NetSuite accounts does it work with?

Any account where the AI Connector works, OneWorld or not. If the connector role can't see the subsidiary table, the plugin infers the base currency from transactions and asks you to confirm it. Tables the role can't see are skipped.

How is it different from the NetSuite AI Connector?

The connector is Oracle's MCP server. It runs SuiteQL, reports, saved searches and record calls against your account. This plugin doesn't replace it. Its hooks check each query before it goes out and shape each result before Claude sees it.

Built on Oracle's work

The NetSuite team at Oracle built the NetSuite AI Connector Service and the MCP Standard Tools SuiteApp. This plugin wraps their tools. It doesn't replace them.

They also wrote the netsuite-ai-connector-instructions skill and published it under the Universal Permissive License 1.0. Its tool order, currency handling and SuiteQL checklist are the base of this plugin's skill. The NOTICE file credits it and lists what we changed. Oracle documents the skill in Using Skills with Claude, ChatGPT, and Other MCP Clients.

Install it, then ask Claude a NetSuite question

If it blocks a correct query or lets a wrong one through, open an issue on GitHub.

  1. /plugin marketplace add suiteutils/suiteutils-netsuite-claude-harness
  2. /plugin install su-ns-harness@suiteutils

NetSuite is a trademark of Oracle. Claude is a trademark of Anthropic. Suite Utils is not affiliated with either.

Short on time. Long on NetSuite headaches.

Practical fixes, script patterns, and new utility alerts from the people who build them. No fluff, no sales pitch. Just the stuff that actually helps.

We respect your privacy. No spam, just pure utility.