The complete implementation guide: building the ADK agent, handling tool calls, and what happens when an LLM meets real ERP complexity.
In Part 1 of this series, we tackled the hardest part of enterprise AI integrations: authentication.
We went through the research journey that led to mcp-remote as the solution to OAuth complexity, debugged NetSuite's non-standard token format (returning expires_in as a string instead of a number), patched the MCP SDK, and established a clean architecture that isolates all authentication complexity away from the agent code.
By the end of Part 1, we had a working authentication layer. But we didn't have an actual AI agent yet. We had the foundation, but not the house.
In this article, we build the complete agent on top of that foundation — and discover what happens when an LLM tries to talk to a real ERP system.
The full source code is available on GitHub. Let's walk through the key pieces.
I used uv for project structure and dependency management — fast, clean, and it handles Python virtual environments well:
adk-netsuite-demo/
├── .env # Environment variables
├── .node/
│ └── mcp-remote/ # Patched mcp-remote package
├── main.py # Entry point
├── netsuite_agent/
│ ├── agent.py # Agent definition
│ └── tools/
│ └── netsuite.py # MCP toolset configuration
├── pyproject.toml # Dependencies
└── uv.lock
We use gemini-2.5-flash for speed and cost-effectiveness, with a standard Google API key from Google AI Studio. The .env file holds the Google API key alongside the NetSuite credentials (Account ID, Client ID, Client Secret) configured via the NetSuite Integration setup.
This is where we configure the connection to NetSuite using our patched mcp-remote from Part 1:
# netsuite_agent/tools/netsuite.py
mcp_tool = McpToolset(
connection_params=StdioConnectionParams(
server_params=StdioServerParameters(
command="npx",
args=[
"-y",
".node/mcp-remote",
# Local patched version
f"https://{os.environ['NETSUITE_ACCOUNT_ID']}.suitetalk.api.netsuite.com/services/mcp/v1/all",
"--static-oauth-client-info",
json.dumps({
"client_id": os.environ['NETSUITE_CLIENT_ID'],
"client_secret": os.environ['NETSUITE_CLIENT_SECRET'],
}),
"--static-oauth-client-metadata",
json.dumps({"scope": "mcp"}),
],
),
timeout=120,
),
)
The connection runs mcp-remote as a child process, passes NetSuite's MCP endpoint URL with OAuth credentials, and exposes everything via stdio so ADK treats it like a local tool.
I kept the agent deliberately minimal — the whole point of this POC was to validate whether Gemini can effectively use the tools exposed by NetSuite's MCP Server:
# netsuite_agent/agent.py
root_agent = Agent(
model='gemini-2.5-flash',
name='root_agent',
description="A helpful assistant for questions about business information in NetSuite.",
instruction="""
You are a helpful agent who can retrieve information from the user's NetSuite account.
Use the provided tools to answer the user's questions.
When querying NetSuite:
- Be specific about what data you're requesting
- Format responses in a clear, readable way
- If you're unsure about available data, ask the user for clarification
""",
tools=[netsuite.mcp_tool],
)
With this in place, you can fire up the agent with ADK's built-in tools — adk web for a browser interface or adk run netsuite_agent from the terminal.
The first time you run it, a browser window pops up asking you to authenticate with NetSuite. Once authorised, all session and refresh tokens are stored in your ~/.mcp-auth/ directory.
Let's start simple: "Hi! What's the total turnover for 2024? My fiscal year starts on January 1st."
After the OAuth handshake completes, the agent connects, tool calls start flowing, and…
It works. The response was correct. The LLM successfully used NetSuite's MCP tools to query transaction data and return the right answer.
This is where the dream of "talk to your ERP in natural language" becomes very real. But it's also where things get interesting — because the agent isn't always this smooth.
Using adk run is useful but doesn't show the full picture. Asking for a simple turnover figure required several tool calls behind the scenes. Let's look at how the LLM figures out what to do — and where it struggles.
The LLM's first approach to the turnover question:
Result: wrong answer, and a lot of wasted calls to NetSuite.
Starting fresh, the LLM took a different path:
Result: right answer. The LLM was already learning what works.
When I asked for sales rep performance data, things got harder:
Result: fail. The minimal prompt I was using wasn't enough for complex queries. The LLM needs more context about NetSuite's data model to do its job properly.
While NetSuite's own demos show the AI Connector working smoothly with Claude and ChatGPT, my experience with Google's ADK revealed that there are still many immature pieces in this puzzle. That said, everything is moving so fast that experimenting is a must.
Here's what I found:
Smaller models don't work yet. I tested with the instruct versions of Qwen3 14B, DeepSeek R1, GPT-OSS 120B, and Mistral 7B. None could reliably use the NetSuite MCP tools. For now, you need the reasoning power of a frontier model.
Tools do their job, but ERP processes are complex. Chatting directly with an ERP is impressive as a demo but fundamentally limited for real work. You need an agentic system that properly splits and coordinates activities among different, specialised agents — one for financial queries, one for inventory, one for customer data, each with domain-specific context.
The full tech stack is still maturing. As of this writing, trying to do something beyond the standard Claude/ChatGPT demos with tools like Google's ADK introduces a series of small technical hiccups. Even N8N has open pull requests for proper OAuth2 authorisation management with MCP servers.
We're still early in the "AI agents for enterprise" era. The frameworks exist. The protocols exist. But the integration patterns are still being discovered.
Projects like this — where you hit real problems and share real solutions — move the ecosystem forward. NetSuite's non-standard OAuth isn't a secret anymore. The mcp-remote approach is documented. The authentication trade-offs are clearer.
Agentic AI implies a lot of experimentation to get agents working properly. Sharing is essential: that's how we mature this space. Not by pretending integration is trivial, but by honestly sharing what works, what doesn't, and why.
And sometimes, the entire solution is just one word: coerce.
Code:
Documentation:
Previous article:
Originally published on Medium.
This is the kind of enterprise AI integration work we do at RAAS Impact every day — connecting AI to the systems that actually run your business. If you're exploring AI agents for NetSuite or other ERP platforms, let's talk about what a proof of concept looks like for your setup.