warekit-mcp
š warekit
The CLI for WareKit ā scaffold and manage NetSuite apps built with React.
A Masterpiece Will Always Require Effort.
npx warekit new restlet customers --methods get,post
npx warekit new user-event sync-customer --record CUSTOMERš Commands
| Scaffold a script. Interactive when arguments are missing. |
| Show the resolved project manifest. |
| How to start a new project. |
Options: --methods a,b, --record TYPE, --dry.
š§ Script types
Governance is the decision the type actually turns on. Every script gets a
usage-unit budget per execution, and exceeding it throws
SSS_USAGE_LIMIT_EXCEEDED mid-request.
Type | Units | Notes |
| 1,000 | Session-based, can serve HTML, can be login-free |
| 5,000 | JSON only, 5x the budget |
| 1,000 | Runs in the browser on a form. Record-bound. |
| 1,000 | Server-side, on record events. Record-bound. |
| 10,000 | Plus a fresh allowance per stage call. Task-invoked. |
| 10,000 | One budget for the whole run. Task-invoked. |
search.create().run() costs 10 units and record.load() costs 5, so a
Suitelet doing 100 record loads is already over budget while a RESTlet has
room. Reach for a RESTlet when an endpoint touches many records.
client and user-event are triggered by NetSuite on a record type, not
over a URL, so they need --record and are deliberately not added to the
endpoint registry.
map-reduce and scheduled are invoked by the scheduler or task.create(),
not by a request, so their deployments carry a <recurrence> and ship as
NOTSCHEDULED ā you pick the schedule in the UI after deploy. Map/Reduce gets
its 10,000 units per stage call, which is why a job too big for a Scheduled
script fits comfortably once you split it across map or reduce.
š What it writes
The SuiteScript file, in the folder your manifest declares
The SDF object, with a filename matching its
scriptidThe
deploy.xml<path>when the folder is newRuntime registration, for URL-addressed types only
Step 3 is the one that bites. Scripting/suitelets/* is usually already
globbed, but your first RESTlet lives in a folder deploy.xml has never heard
of, and SDF fails the entire deploy on it.
It also refuses names that would breach NetSuite's 40-character script-ID cap before writing anything, rather than at validation time where the error never mentions length.
āļø warekit.json
The CLI writes only where a project tells it to. Every project carries a manifest at its root:
{
"version": 1,
"kit": "netsuite",
"edition": "lite",
"identity": {
"publisherId": "com.amware",
"projectId": "myapplication",
"scriptPrefix": "amw"
},
"paths": {
"suiteapp": "apps/suiteapp/template",
"scripting": {
"suitelet": "Scripting/suitelets",
"restlet": "Scripting/restlets",
"client": "Scripting/client",
"user-event": "Scripting/user-event",
"map-reduce": "Scripting/map-reduce",
"scheduled": "Scripting/schedule"
},
"objects": "Objects/scripts",
"deployXml": "deploy.xml",
"endpointRegistry": "FileCabinet/SuiteApps/{suiteApp}/Scripting/suitelets/{prefix}_sl_urls.js"
}
}Found by walking up from the working directory, the way git finds .git. A
missing or malformed manifest is a hard error rather than a guess ā guessing
means scaffolding into the wrong folder and failing at deploy time, which is
far more expensive to diagnose.
{suiteApp} and {prefix} are substituted, so the manifest stays valid after
you change your project identity.
edition is lite or pro. The CLI reads it rather than sniffing the
directory, so a Pro-only command fails with a clear message instead of half
running against a Lite checkout. warekit info prints it.
š¦ Kits
Kit |
| Edition | What you get |
|
| Lite | The React-in-NetSuite architecture: SDF, both deploy modes, E2E, CI |
|
| Pro | Adds licensing, role mapping, typed data layer, schema generator, admin center |
warekit create clones the Lite kit. Pro is in development.
The framework is in the name because a Next.js kit is planned for hybrid SuiteApps: a frontend on Vercel that reaches NetSuite from its API routes, over OAuth 2 for user sign-in or token-based auth for server-to-server calls, rather than running inside a Suitelet on the session cookie.
Both kinds ship an SDF project and both are scaffolded by this CLI ā the
SuiteScript backend is the same work either way, and warekit new does not
care where the frontend is hosted. The kits differ only in their kit id, so
a kit-specific command can tell them apart without inspecting the tree.
š¤ MCP server
A second binary exposes the same generator over MCP, so agents and humans produce identical output.
{
"mcpServers": {
"warekit": { "command": "npx", "args": ["-y", "warekit-mcp"] }
}
}Tools: warekit_script_types, warekit_project_info, warekit_new_script.
Every tool takes an explicit cwd ā an MCP server's working directory is
whatever the host launched it in, which is rarely your project.
š Licence
MIT. The CLI is free and open. The kits it scaffolds are a separate, commercially licensed product.
šļø Project layout
src/
āāā index.ts CLI entry, registers commands
āāā mcp.ts MCP entry
āāā version.ts
āāā commands/
ā āāā new/new.command.ts
ā āāā info/info.command.ts
ā āāā create/create.command.ts
āāā utils/ the actions ā commands are thin wrappers
ā āāā generate-script.ts
ā āāā format-result.ts
ā āāā manifest.ts
ā āāā with-project.ts
ā āāā logger.ts
āāā templates/ NetSuite script templates + type registryThe rule that makes this work: commands parse, utils do. mcp.ts imports
from utils/, never from commands/, so the CLI and the MCP server run the
same code and cannot drift. A command file should be argument parsing,
prompting, and one call into a util.
Adding a command
src/commands/<name>/<name>.command.tsexporting a function that returns aCommand.Put the work in
src/utils/<verb>-<noun>.tsā not in the command ā so the MCP server can expose it too.Register it in
src/index.tswithprogram.addCommand(...).
Subcommands nest: a plugins add command would be
commands/plugins/plugins.command.ts plus commands/plugins/add/add.command.ts.
Adding a script type
One entry in SCRIPT_TYPES and one source function in src/templates/. No
command changes ā Map/Reduce, Scheduled, Portlet and Mass Update all fit the
existing shape.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/amwaredotdev/warekit-cli'
If you have feedback or need assistance with the MCP directory API, please join our Discord server