Skip to main content
Glama
samson10504

netsuite-suiteanalytics-odbc-mcp

by samson10504

NetSuite SuiteAnalytics ODBC MCP

A local, read-only Model Context Protocol (MCP) server for querying a user's own NetSuite SuiteAnalytics Connect account through the user's locally installed ODBC driver.

This project is an independent community project. It is not affiliated with, sponsored by, or endorsed by Oracle or NetSuite. NetSuite and SuiteAnalytics Connect are trademarks or products of Oracle.

Use this software only with accounts, data, credentials, roles, services, and driver software that you are authorized and licensed to use. Configure a dedicated least-privilege NetSuite role. This project does not grant a NetSuite subscription, SuiteAnalytics Connect entitlement, driver license, or right to access any data.

What It Does

The server exposes exactly four MCP tools:

Tool

Purpose

netsuite_query

Execute one bounded, read-only SELECT or WITH query.

netsuite_tables

Search bounded ODBC table metadata visible to the configured role.

netsuite_describe

Describe columns for one exact table visible to the configured role.

netsuite_status

Return secret-safe status and optionally perform a live connection check.

The MCP client launches this package as a local child process and communicates over standard input/output. The Node.js process uses the system ODBC driver manager and the user's named local data source (DSN) to connect directly to NetSuite. There is no HTTP listener, remote transport, or hosted service.

The proprietary NetSuite ODBC driver and installer are never bundled, uploaded, downloaded, mirrored, or licensed by this package. Each user must obtain the driver independently from an authorized NetSuite account, accept the applicable terms, and install and configure it locally. Java, JDBC, and NQjc.jar are not required.

Requirements

  • Node.js 20 or later. NETSUITE_DRIVER_HOME self-replacement requires Node.js 22.15+ on POSIX systems.

  • A supported local environment for the native Node odbc addon. Native binaries are platform-, architecture-, Node ABI-, and driver-manager-specific; installation may require platform build tools.

  • A system ODBC driver manager: unixODBC on macOS/Linux, or the Windows ODBC Data Source Administrator on Windows.

  • SuiteAnalytics Connect enabled and licensed for the user's NetSuite account.

  • The latest ODBC driver available from the user's authorized account. Actual compatibility with the selected OS, architecture, Node runtime, driver manager, NetSuite release, and account must be tested locally.

  • A local system or user DSN whose name exactly matches NETSUITE_ODBC_DSN.

  • A dedicated least-privilege role with Connect access and only the record permissions needed for the intended use.

  • A TBA integration and access token assigned to the intended user and that exact role.

  • Outbound DNS and network access to the account-specific Connect service host on port 1708.

ODBC access does not expose every NetSuite record, field, feature, saved search, workbook, SuiteScript API, REST record, or SuiteQL surface. The NetSuite2.com Connect schema and the configured role determine what is available.

Quick Start

  1. In an authorized NetSuite account, go to Settings > Set Up SuiteAnalytics Connect.

  2. Choose the correct operating system, record the values under Your Configuration, accept the applicable terms, then download, extract, and install the ODBC driver locally.

  3. Configure a system or user DSN using the installed driver and the recorded NetSuite configuration. Set NETSUITE_ODBC_DSN to that DSN's exact name.

  4. Create a dedicated least-privilege role, TBA integration, and token as described in Token-based authentication.

  5. Run the exact public package version without a global installation:

npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 doctor

For development from a source checkout, use npm install followed by npm run build.

  1. Supply the required environment through the MCP launcher's protected configuration. These are placeholders, not working values:

NETSUITE_ACCOUNT_ID=YOUR_ACCOUNT_ID
NETSUITE_ROLE_ID=YOUR_NUMERIC_ROLE_ID
NETSUITE_SERVICE_HOST=YOUR_SERVICE_HOST_FROM_NETSUITE
NETSUITE_ODBC_DSN=YOUR_LOCALLY_CONFIGURED_NETSUITE_DSN
NETSUITE_CONSUMER_KEY=YOUR_CONSUMER_KEY
NETSUITE_CONSUMER_SECRET=YOUR_CONSUMER_SECRET
NETSUITE_TOKEN_ID=YOUR_TOKEN_ID
NETSUITE_TOKEN_SECRET=YOUR_TOKEN_SECRET
NETSUITE_DRIVER_HOME=/opt/netsuite/odbcclient
  1. Run local diagnostics, then deliberately run the live test when authorized:

node dist/cli.js doctor
node dist/cli.js test-connection

doctor is local-only with respect to NetSuite: it validates configuration, loads the native ODBC addon/driver manager, and performs a DNS lookup, but does not open the DSN, authenticate, or query NetSuite. test-connection is live: it opens the configured DSN with TBA and executes SELECT 1, which may create NetSuite audit or connection records.

  1. Configure the MCP client to launch the exact package version in stdio mode:

{
  "mcpServers": {
    "netsuite": {
      "command": "npx",
      "args": ["-y", "netsuite-suiteanalytics-odbc-mcp@1.0.2", "serve"],
      "env": {
        "NETSUITE_ACCOUNT_ID": "YOUR_ACCOUNT_ID",
        "NETSUITE_ROLE_ID": "YOUR_NUMERIC_ROLE_ID",
        "NETSUITE_SERVICE_HOST": "YOUR_SERVICE_HOST_FROM_NETSUITE",
        "NETSUITE_ODBC_DSN": "YOUR_LOCALLY_CONFIGURED_NETSUITE_DSN",
        "NETSUITE_CONSUMER_KEY": "YOUR_CONSUMER_KEY",
        "NETSUITE_CONSUMER_SECRET": "YOUR_CONSUMER_SECRET",
        "NETSUITE_TOKEN_ID": "YOUR_TOKEN_ID",
        "NETSUITE_TOKEN_SECRET": "YOUR_TOKEN_SECRET"
      }
    }
  }
}

Client configuration formats vary. Protect the child-process environment. Do not pass credentials as CLI arguments; the CLI rejects configuration arguments. A tool caller cannot choose a DSN, connection string, account, role, or credentials. All four tools use the single operator-configured NETSUITE_ODBC_DSN and environment.

LibreChat Setup

The package is published as netsuite-suiteanalytics-odbc-mcp. LibreChat runs the pinned 1.0.2 release as a local stdio MCP process.

The LibreChat backend must run in the same environment that has Node.js 20+, the ODBC driver manager, the authorized NetSuite ODBC driver, and the configured DSN. The simplified NETSUITE_DRIVER_HOME setup shown below requires Node.js 22.15+ on Linux/macOS. For Docker deployments, those dependencies and the DSN must exist inside the LibreChat backend container; installing them only on the Docker host is not enough. Do not put the proprietary driver or credentials in a public image.

Set these values in LibreChat's protected server-side environment, not directly in source-controlled librechat.yaml:

NETSUITE_ACCOUNT_ID=YOUR_ACCOUNT_ID
NETSUITE_ROLE_ID=YOUR_NUMERIC_ROLE_ID
NETSUITE_SERVICE_HOST=YOUR_SERVICE_HOST_FROM_NETSUITE
NETSUITE_ODBC_DSN=YOUR_LOCALLY_CONFIGURED_NETSUITE_DSN
NETSUITE_CONSUMER_KEY=YOUR_CONSUMER_KEY
NETSUITE_CONSUMER_SECRET=YOUR_CONSUMER_SECRET
NETSUITE_TOKEN_ID=YOUR_TOKEN_ID
NETSUITE_TOKEN_SECRET=YOUR_TOKEN_SECRET

Add this entry to librechat.yaml:

mcpServers:
  netsuite-suiteanalytics:
    title: NetSuite SuiteAnalytics
    description: Bounded read-only access to the configured SuiteAnalytics Connect role
    type: stdio
    command: npx
    args:
      - -y
      - netsuite-suiteanalytics-odbc-mcp@1.0.2
      - serve
    env:
      NETSUITE_ACCOUNT_ID: '${NETSUITE_ACCOUNT_ID}'
      NETSUITE_ROLE_ID: '${NETSUITE_ROLE_ID}'
      NETSUITE_SERVICE_HOST: '${NETSUITE_SERVICE_HOST}'
      NETSUITE_ODBC_DSN: '${NETSUITE_ODBC_DSN}'
      NETSUITE_CONSUMER_KEY: '${NETSUITE_CONSUMER_KEY}'
      NETSUITE_CONSUMER_SECRET: '${NETSUITE_CONSUMER_SECRET}'
      NETSUITE_TOKEN_ID: '${NETSUITE_TOKEN_ID}'
      NETSUITE_TOKEN_SECRET: '${NETSUITE_TOKEN_SECRET}'
      NETSUITE_DRIVER_HOME: /opt/netsuite/odbcclient
      ODBCINI: /etc/odbc.ini
      NETSUITE_SERVICE_PORT: '1708'
      NETSUITE_DATA_SOURCE: NetSuite2.com
      NETSUITE_TELEMETRY: 'off'
    initTimeout: 30000
    timeout: 130000
    stderr: inherit
    serverInstructions: true
    chatMenu: false

Before starting LibreChat, validate the setup from the same host or container and operating-system user that runs the LibreChat backend:

npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 doctor
npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 test-connection

test-connection makes a live TBA connection and executes SELECT 1. Restart LibreChat after changing librechat.yaml. In the Agent Builder, select Add MCP Server Tools, choose NetSuite SuiteAnalytics, and enable only the required tools. chatMenu: false keeps the tools agent-only; enable it only after reviewing access controls and data exposure.

This local MVP uses one process-level NetSuite credential set and does not provide per-user OAuth or tenant isolation. Do not expose one shared NetSuite account to unrelated LibreChat users. Query results can enter LibreChat history and model-provider requests, so review user access, retention, tracing, backups, sharing, and model-provider approval before enabling the server.

LibreChat Container Checklist

LibreChat stdio children receive only the environment explicitly configured for that MCP server. Variables present in an interactive shell or the parent container are not enough. Include every NETSUITE_* value above and NETSUITE_DRIVER_HOME in the MCP env block.

NETSUITE_DRIVER_HOME is the absolute directory containing the extracted odbcclient. It must not be writable by group or other users. The CLI replaces itself in place where supported and derives:

OASDK_ODBC_HOME=/opt/netsuite/odbcclient/lib64
LD_LIBRARY_PATH=/opt/netsuite/odbcclient/lib64:/opt/netsuite/odbcclient/lib:/opt/netsuite/odbcclient:...

Explicit OASDK_ODBC_HOME, ODBCINI, and loader-path values take precedence if the installed driver requires different paths. The self-replacement is necessary because Linux resolves LD_LIBRARY_PATH when the process starts.

When lib64/ivoa27.ini exists, OASDK_ODBC_HOME is derived as /opt/netsuite/odbcclient/lib64; otherwise it falls back to the extraction root. On Node.js 20, omit NETSUITE_DRIVER_HOME and place OASDK_ODBC_HOME=/opt/netsuite/odbcclient/lib64, ODBCINI, and LD_LIBRARY_PATH explicitly in LibreChat's MCP env block. Those values are then present when the process starts, so no self-replacement is needed.

For a container deployment, make all setup persistent rather than repairing a running container:

  1. Extract the authorized driver on the host into a git-ignored private directory such as ./netsuite-odbc/odbcclient. Do not commit or publish the zip or extracted driver.

  2. Bind-mount the extracted directory read-only at /opt/netsuite/odbcclient.

  3. Bind-mount reviewed odbc.ini and odbcinst.ini files read-only at /etc/odbc.ini and /etc/odbcinst.ini.

  4. Build a private LibreChat API image containing the required ODBC/runtime packages so container recreation does not erase them.

  5. Pin and optionally preinstall netsuite-suiteanalytics-odbc-mcp in that private image to avoid relying on a warm npx cache.

Copy the maintained templates from examples/librechat:

examples/librechat/Dockerfile.odbc
examples/librechat/docker-compose.override.example.yml

Place Dockerfile.odbc alongside LibreChat's Compose project, copy the override as docker-compose.override.yml, and set LIBRECHAT_API_IMAGE to the exact pinned upstream API image. Review the upstream runtime user before building.

The NetSuite Linux driver is glibc-linked. LibreChat Alpine images use musl, so a typical private image needs:

# Extend the exact LibreChat API image version used by your deployment.
FROM YOUR_LIBRECHAT_API_IMAGE
USER root
RUN apk add --no-cache \
    gcompat libc6-compat linux-pam libstdc++ \
    unixodbc unixodbc-dev
RUN npm install --global netsuite-suiteanalytics-odbc-mcp@1.0.2
USER node

Confirm node is the non-root user in the exact upstream image; restore its actual user if different. If the native npm odbc addon must compile instead of using a compatible prebuilt binary, the private image may also need python3, make, and g++. Never add the proprietary NetSuite driver to a public image.

When the package is preinstalled globally in the private image, avoid npx cache/network resolution by changing the LibreChat entry to:

command: netsuite-mcp
args:
  - serve

A compose override can provide only the private runtime files:

services:
  api:
    volumes:
      - ./netsuite-odbc/odbcclient:/opt/netsuite/odbcclient:ro
      - ./netsuite-odbc/odbc.ini:/etc/odbc.ini:ro
      - ./netsuite-odbc/odbcinst.ini:/etc/odbcinst.ini:ro

The DSN name must exactly match NETSUITE_ODBC_DSN. Its host, port 1708, NetSuite2.com source, driver library, and truststore must point to files visible inside the container. Any RoleID in odbc.ini or the driver's odbc64.ini must match NETSUITE_ROLE_ID; the access token must also belong to that exact role.

Self-Service Diagnosis

Run both commands inside the LibreChat API container, as the same user that launches the MCP child:

npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 doctor
npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 test-connection

doctor stays local-only. It checks the native addon/driver manager, unixODBC DSN registration, designated driver home, odbc64.ini role alignment, designated ODBCINI, registered driver library, declared truststore, DNS, and any host/port/data-source declarations present in the DSN. It does not authenticate. Omitted or vendor-specific DSN keys cannot always be inferred, so the live check remains required.

test-connection is explicit and live. It loads the registered NetSuite driver, generates a fresh TBA password, opens a connection, and executes SELECT 1. Safe error categories distinguish missing DSNs, driver initialization/runtime failures, authentication failures, network/port failures, TLS failures, and query/session failures without returning raw driver diagnostics.

Common recovery order:

  1. DRIVER_NOT_FOUND: verify the DSN is registered for the runtime user and its name exactly matches NETSUITE_ODBC_DSN.

  2. DRIVER_LOAD_FAILED: verify the mounted driver home, ivoa27.so registration, glibc/PAM/C++ runtime packages, library path, and ODBC configuration files.

  3. INVALID_TOKEN or INVALID_ROLE: align every local RoleID, NETSUITE_ROLE_ID, and the integration + user + role token assignment. Stop repeated attempts before lockout.

  4. DNS_FAILURE or PORT_BLOCKED: verify DNS and outbound TCP from the container to the exact account host on port 1708.

  5. TLS_FAILURE: verify the DSN truststore/certificate path is mounted and readable.

After changing LibreChat MCP configuration, use the Admin UI save path or restart LibreChat. Direct database edits can remain hidden behind application and failure caches. Renaming an MCP server can leave saved agent tool bindings pointing at the old server key; remove and re-add the MCP tools in Agent Builder.

Container recreation removes ad hoc apk packages, /etc/odbc*.ini, and npx cache contents. A custom private image plus read-only mounts avoids that fragility. A plain restart normally preserves the existing container filesystem. Live status and connection tests create real NetSuite connection/audit activity.

The package deliberately does not write odbc.ini, odbcinst.ini, alter the proprietary driver package, or install OS libraries: layouts and permitted installation procedures vary by driver release and platform, and those are privileged deployment operations. Use the current authorized NetSuite driver instructions, keep configuration in private deployment files, and use doctor to validate the result.

See the full LibreChat guide and setup guide for deployment details, limits, and security boundaries.

Safety Model

  • Only one SELECT statement or read-only WITH query is accepted.

  • SQL comments, semicolons, write/DDL/control keywords, and unsupported or ambiguous syntax are rejected locally.

  • Row count, serialized row bytes, timeout, pool size, concurrency, and physical connection lifetime are bounded. Native driver buffers may allocate beyond the serialized response cap.

  • Optional table allowlists and denylists narrow local access.

  • The configured NetSuite role is the authoritative access boundary. Local SQL checks are defense in depth, not a substitute for least privilege.

  • A fresh Connect token password is generated only when a new physical ODBC connection is created. Pooled operations reuse that connection until it expires or closes.

  • Three consecutive classified authentication failures open a local circuit breaker for a configurable cooldown.

  • Project telemetry is fixed to off. NetSuite, the ODBC driver, the MCP client, the selected model provider, the operating system, and dependencies may have their own logging or telemetry.

  • Errors are categorized and redacted before being returned, but logs, queries, results, and MCP transcripts must still be treated as potentially sensitive.

CLI

npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 serve
npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 doctor
npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 test-connection
npx -y netsuite-suiteanalytics-odbc-mcp@1.0.2 print-example-config

serve is the default. Pin an exact version rather than relying on the npm latest tag. With a source build, substitute node dist/cli.js for the npx command. Standard output carries MCP protocol messages while serving; do not wrap the process with software that writes banners or logs to stdout.

Scope

This release supports one local, single-user stdio process. It does not provide HTTP or another remote transport, a hosted service, multi-user tenancy, writes, DDL, SuiteScript, REST access, credential hosting, driver acquisition, driver redistribution, automatic NetSuite role provisioning, or arbitrary SQL compatibility.

Kiokii-originated queries may require changes for the SuiteAnalytics Connect ODBC SQL dialect, NetSuite2.com schema, identifier quoting, functions, joins, date handling, and pagination. Use netsuite_tables and netsuite_describe against the target account rather than assuming another connection method's schema or SQL is compatible. No Kiokii-specific schema, customization, adapter, or support guarantee is included.

Documentation

License

The original project code and documentation are licensed under Apache License 2.0. The NetSuite service, ODBC driver, and installer are separate proprietary products governed by their owners' terms. See LICENSE, NOTICE, and licensing guidance. This repository does not provide legal advice.