Skip to main content
Glama
RITHVIKILLANDULA

NetSuite AI Connector

NetSuite AI Connector — Governed MCP ERP Bridge

Source: https://github.com/RITHVIKILLANDULA/netsuite-ai-connector Live demo: https://rithvikillandula.github.io/My-Portfolio/demos/netsuite/

I built a working model of the pattern behind Oracle NetSuite's AI Connector Service. It's an MCP bridge that lets an AI client (Claude, ChatGPT) query live ERP data through governed tools — SuiteQL, saved searches, and records. The AI connects as a finance role, inherits that role's permissions on every call, and every call is audit-logged. I treat the AI as a governed user, not as a way around the controls.

The thesis I wanted to prove is simple: an agent answers from whatever data layer you give it. Put the agent behind a reconciled, governed finance data layer and its answers become trustworthy by construction. The wrong-grain or not-permitted answer gets closed off at the source, not in the prompt.

Run it

make demo    # spawns the MCP server as 4 roles, runs identical requests, prints the matrix + audit log
make test    # 11 governance tests
make serve ROLE=AR    # run the MCP server for one role over stdio

Zero dependencies. The server, the governance layer, and the MCP stdio transport are all standard library.

Related MCP server: NetSuite SuperMCP

What the demo shows

I run the same request across four connected roles and the results differ:

Request

CFO

Controller

AR

AP

SELECT bank_account, tax_id FROM customer

both visible

bank NULL

both NULL

DENY (no customer grant)

SELECT COUNT(*) FROM bill

110

110

DENY

58 (subsidiary-scoped)

SELECT DISTINCT subsidiary_id FROM invoice

1,2,3

1,2,3

1,2 only

DENY

DELETE FROM invoice …

DENY

DENY

DENY

DENY (read-only)

SELECT 1; DROP TABLE customer

DENY

DENY

DENY

DENY (single stmt)

SELECT … FROM main.invoice (base bypass)

140

140

DENY (row-scoped)

DENY

saved search trial_balance

DENY

DENY

Every one of those decisions gets written to erp/audit.db.

How the governance works

I enforce at the database engine, with a SQLite authorizer bound to the connected role (server/governance.py). It holds no matter what SuiteQL the AI writes. There is no query, and no prompt, that talks its way past it.

  • Table allowlist — a read of any relation the role isn't granted is denied.

  • Read-only. Every write, DDL, PRAGMA, or ATTACH action is denied. Only a single SELECT/WITH statement gets through.

  • Column masking. Sensitive columns (tax_id, bank_account) read back as NULL per role, via SQLITE_IGNORE.

  • Row-level scoping. Row-filtered relations are reachable only through per-role TEMP VIEWs that embed the subsidiary / document-type WHERE clause. Direct access to the base table is denied, so a role cannot widen its own row scope even by qualifying the table name.

I declare the roles as pure policy in server/roles.py so an auditor can read exactly what CFO / Controller / AR / AP can and cannot touch:

CFO         all subsidiaries · AR + AP · sensitive fields visible
Controller  all subsidiaries · AR + AP · bank_account masked
AR          subs 1-2 · customers + invoices + AR GL · tax_id & bank_account masked
AP          subs 1-2 · vendors + bills + AP GL     · tax_id & bank_account masked

The governed tools (MCP tools/list)

Tool

Purpose

whoami

the connected role and the permissions it inherits

describe_schema

role-scoped catalog: relations, columns (masked flagged), row filters

suiteql_query

run a read-only SuiteQL SELECT under the role's permissions

saved_search_run

invoke a pre-vetted saved search by id (params always bound)

record_get

fetch one record, masked and row-scoped

list_saved_searches

saved searches available to the role

Saved searches (server/saved_searches.py) are the safer counterpart to raw SuiteQL. An analyst authors and reviews the SQL once. The AI can only invoke it by id with bound parameters, never string-formatted, and it still runs through the role's filters and masks.

Wire it to a real MCP client

The server speaks JSON-RPC 2.0 over stdio (initializetools/listtools/call). See mcp_client_config.example.json. Each entry connects the AI as a fixed role:

{ "command": "python3", "args": ["-m", "server.mcp_server", "--role", "AR"],
  "cwd": "/absolute/path/to/netsuite-ai-connector" }

Layout

server/erp_seed.py        synthetic NetSuite-shaped ERP (subs, AR, AP, COA, GL)
server/roles.py           CFO / Controller / AR / AP policy (pure declaration)
server/governance.py      authorizer-based enforcement (the core guarantee)
server/saved_searches.py  pre-vetted, parameter-bound saved searches
server/audit.py           append-only audit log of every call
server/tools.py           governed tool surface + audited dispatch
server/mcp_server.py      MCP JSON-RPC stdio server
client/demo_client.py     spawns the server per role, runs the governance matrix
tests/                    11 enforcement tests (pytest or stdlib runner)

Why this is the interesting half of the portfolio

My other projects, Foundry and Forecast, build a reconciled, governed finance data layer. This one shows what that layer is worth once an agent is pointed at it. The reconciliation and lineage stop being back-office plumbing and become the thing that makes every AI answer trustworthy.

Resume line: Built a governed MCP connector that lets AI clients query live ERP data through role-scoped tools (SuiteQL, saved searches, records), where every call inherits the connected role's permissions and is audit-logged.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to query and manage NetSuite data via natural language, supporting SuiteQL queries and record operations through Token-Based Authentication.
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides a single MCP endpoint for AI clients to operate NetSuite via a dedicated integration identity, supporting read, write, and action tools with risk policies and audit logging.
    4,621 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables enterprise AI agents to query governed data lineage, PII-aware schema documentation, and semantic metadata from SQL logs via MCP, with role-based access and vector search.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Connects MCP-compatible AI assistants to NetSuite ERP with easy OAuth setup. Provides tools for records, SuiteQL, saved searches, reports, and metadata.
    3 npm
    1
    MIT