Vercel AI SDK — Node.js Scripts
Step-by-step agent examples using the Vercel AI SDK with Neo4j.
Scripts
| File | Description |
|---|---|
|
Direct Neo4j query — sanity check, no AI |
|
MCP agent — connects to a Neo4j MCP server via |
|
MCP + custom Cypher tools merged in one agent |
|
Memory with the low-level |
|
Memory with |
|
Shared MCP connection + auth helper (mirrors the demo’s |
|
Shared system prompts (mirrors the demo’s |
|
Shared LLM provider config (OpenAI / Gemini / Anthropic / Mistral) |
Setup
cd notebook
cp .env.example .env # fill in OPENAI_API_KEY, NEO4J_*, MCP_*, and MEMORY_API_KEY
npm install
These scripts run AI SDK v7 (ai@^7, @ai-sdk/mcp@^2, @ai-sdk/openai@^4)
with @neo4j-labs/nams-ai-provider@^0.2, the same set the
vercel_Nams_demo/ app pins — both resolve to identical
versions.
Running
node 0-direct-query.mjs # verify Neo4j connection
node 1-mcp-agent.mjs # requires MCP_URL/MCP_PORT + MCP auth
node 2-custom-tools-agent.mjs
node 3-memory-agent.mjs # requires MEMORY_API_KEY
node 4-nams-provider-agent.mjs # NAMS_MODE=provider (default)
NAMS_MODE=tools node 4-nams-provider-agent.mjs # model-driven memory tools
NAMS_MODE=middleware node 4-nams-provider-agent.mjs # transparent memory on a model instance
Environment Variables
| Variable | Required | Description |
|---|---|---|
|
✅ |
LLM API key (or the key matching |
|
optional |
|
|
optional |
Overrides the provider default ( |
|
for scripts 0 & 2 |
Direct driver connection |
|
for scripts 1–4 |
Hosted MCP endpoint (or use |
|
optional |
Local |
|
one of these |
MCP auth via |
|
one of these |
MCP auth via |
|
for scripts 3 & 4 |
NAMS key from memory.neo4jlabs.com |
|
optional |
Pin to a specific NAMS workspace; blank uses the key’s default |
|
optional |
Override the NAMS endpoint |
|
optional |
Memory scope — memories persist per user id across runs |
|
optional |
|
MCP Authentication
mcp.mjs picks the scheme from the env vars, exactly like the demo’s
lib/neo4j-mcp.ts:
| Server | Set |
|---|---|
Hosted Aura / NeoCompanion (OAuth 2.1) |
|
Self-hosted |
|
On a 401 the scripts re-probe the endpoint and report its WWW-Authenticate
challenge, so a Basic/Bearer mismatch says so instead of surfacing a bare
MCP HTTP Transport Error.
NAMS Integration Modes (script 4)
NAMS_MODE |
API | Behaviour |
|---|---|---|
|
|
Memory retrieved and injected before each call, turn persisted after. No memory tools exposed to the model. |
|
|
Same transparent memory, applied to an already-resolved model instance. |
|
|
|
LLM Providers
All scripts import from providers.mjs — getModel() for a model instance,
getProvider() for the provider factory that NAMS provider mode needs. Switch
providers via AI_PROVIDER:
| Provider | AI_PROVIDER |
API Key Variable |
|---|---|---|
OpenAI (default) |
|
|
Google Gemini |
|
|
Anthropic Claude |
|
|
Mistral |
|
|
Notes
-
AI SDK v6 replaced
maxStepswithstopWhen: stepCountIs(N)— all scripts use the new API. v7 renames it toisStepCountbut keepsstepCountIsas a literal alias (same function object), so no change was needed -
On AI SDK v7,
tool()takes three type parameters (tool<INPUT, OUTPUT, CONTEXT>). These scripts are plain JS and pass no explicit generics, so inference frominputSchemastill works. In TypeScript, an explicit two-argumenttool<In, Out>now binds to thetool<INPUT, CONTEXT>overload and infersOUTPUT = never— it surfaces asnot assignable to type 'undefined'onexecute, not as an arity error. Add the third parameter or drop the generics -
MCP uses
createMCPClientfrom@ai-sdk/mcp(stable API, replacesexperimental_createMCPClient) -
workspaceIdbelongs on theMemoryClientconfig (sent asX-Workspace-Id), not oncreateConversation(), which only accepts{ userId, metadata } -
Script 4 records each agent step via
client.reasoning.recordStep, so past reasoning is recallable in later sessions — the same trace the demo’s reasoning panel renders