API
The Newnadoon API is the runtime surface your frontend, internal tools, and services use to run agents and stream execution events.
This page explains:
- how to expose the API in a Next.js App Router app
- what each endpoint does
- request and response examples
- how to run a standalone production API server
Two ways to expose the API
Option 1: Next.js App Router integration
Use this when your frontend app and agent runtime live in the same Next.js project.
Create:
app/api/newnadoon/[...path]/route.ts
import { createNewnadoonApiRoute } from '@newnadoon/ai-framework/next/app-router'
export const runtime = 'nodejs'
export const { GET, POST } = createNewnadoonApiRoute()This gives you runtime endpoints under /api/newnadoon/*.
Option 2: Standalone production API server
Use this when you want a dedicated backend process.
$ npx newnadoon-apiOptional flags:
npx newnadoon-api --port 8080 --base-path /api --project-dir ./By default, this serves endpoints under /api/* and includes health + MCP routes.
Required project config
The API loads agents from newnadoon.json. If this file is missing or invalid, agent endpoints cannot run.
Minimal example:
{
"agents": {
"general-department-agent": {
"name": "General Department Agent",
"path": "./agent.ts"
}
}
}Core runtime endpoints
The same runtime concepts are used in both integration modes.
When using the Next.js helper, the base path is /api/newnadoon.
When using newnadoon-api, the default base path is /api.
POST /run
Starts an agent execution.
Next.js path:
/api/newnadoon/run
Standalone server path:
/api/run
Example request:
{
"agentId": "general-department-agent",
"initialState": {
"task": "Summarize today's shipping issues"
},
"checkpoint": true
}Example response:
{
"success": true,
"runId": "run-1742451111-abc123",
"workflowId": "workflow-1742451111-def456",
"message": "Agent execution started"
}GET /events (SSE)
Streams runtime events using Server-Sent Events (SSE).
Next.js path:
/api/newnadoon/events
Standalone server path:
/api/events
Optional query params:
runIdworkflowId
Example browser client:
const source = new EventSource('/api/newnadoon/events?runId=run-123')
source.onmessage = (event) => {
const data = JSON.parse(event.data)
console.log(data.type, data)
}You will receive events such as connection, token streaming, step/run updates, and final completion events.
GET /agents
Returns registered agents loaded from newnadoon.json.
Next.js path:
/api/newnadoon/agents
Standalone server path:
/api/agents
Example response:
{
"agents": [
{
"id": "general-department-agent",
"name": "General Department Agent",
"description": "",
"path": "./agent.ts"
}
],
"defaultAgent": "general-department-agent"
}GET /graph
Returns workflow/agent structure for visualization.
Next.js path:
/api/newnadoon/graph?agentId=general-department-agent
Standalone server path:
/api/graph?agentId=general-department-agent
Use this for topology views, step maps, and runtime UI graph rendering.
Additional standalone server endpoints
When running npx newnadoon-api, you also get:
GET /
Landing page for browsers (@newnadoon/[email protected]+). HTML GET / serves the project’s public/index.html when that file exists; otherwise the framework default page with MCP client snippets (Cursor, Claude Code, Codex, GitHub Copilot, Gemini CLI, Grok). Other files in public/ are served at / (for example public/favicon.ico). JSON Accept: application/json still returns the framework payload. This process is the API + MCP server, not a product UI. Any MCP client should use POST /api/mcp.
GET /health
Health status for readiness/liveness checks.
MCP endpoints
GET /api/mcp(SSE session setup; default--base-path /api)POST /api/mcp(Streamable HTTP JSON-RPC; Cursor, Claude Code, Codex, VS Code, Windsurf, and other MCP clients) — shipped in@newnadoon/[email protected]./api/healthis reliable in 1.0.23 (1.0.22 could 503 on a normal heap).POST /api/mcp/messages?sessionId=...(legacy SSE JSON-RPC messages)
The SSE endpoint event data is the message path as a raw string (/api/mcp/messages?sessionId=...), not JSON. Cursor and other MCP clients treat that string as a URL. A JSON payload such as {"messageEndpoint":"..."} is resolved as a relative path and returns Cannot POST /api/{...}.
These endpoints allow external MCP clients to discover and call registered agents as tools. tools/list also includes each agent’s exported agentTools / tools as {agentId}.{toolName} (for example kanban-workitem-agent.create_work_item). tools/call runs the agent when name is an agent id, or executes that tool directly when name is a dotted {agentId}.{toolName}.
Generic agents work with no headers. There is no KANBAN_ORGANIZATION_ID fallback. If a client sends Authorization: Bearer <org-api-key>, the server validates it against KANBAN_API_URL/api/integrations/api-keys/validate and injects that key’s organizationId. Client-supplied organizationId arguments are stripped. Without a valid key, Kanban tools fail rather than acting on a default org. Set MCP_REQUIRE_API_KEY=true when you want every tools/call (including generic agents) to require a key.
Connect an MCP client
The running API (GET /) shows the same snippets with the live MCP URL filled in. Replace ndk_... with an org API key when the agent talks to Kanban. Generic agents can omit the header. Stdio-only clients: npx -y mcp-remote http://localhost:8080/api/mcp.
Cursor — .cursor/mcp.json
{
"mcpServers": {
"newnadoon": {
"url": "http://localhost:8080/api/mcp",
"headers": {
"Authorization": "Bearer ndk_..."
}
}
}
}Claude Code — .mcp.json (type is required)
{
"mcpServers": {
"newnadoon": {
"type": "http",
"url": "http://localhost:8080/api/mcp",
"headers": {
"Authorization": "Bearer ndk_..."
}
}
}
}claude mcp add --transport http --scope project newnadoon http://localhost:8080/api/mcp --header "Authorization: Bearer ndk_..."Codex — ~/.codex/config.toml
[mcp_servers.newnadoon]
url = "http://localhost:8080/api/mcp"
bearer_token_env_var = "NEWNADOON_MCP_KEY"GitHub Copilot — .vscode/mcp.json (servers, not mcpServers)
{
"servers": {
"newnadoon": {
"type": "http",
"url": "http://localhost:8080/api/mcp",
"headers": {
"Authorization": "Bearer ndk_..."
}
}
}
}Gemini CLI — ~/.gemini/settings.json
{
"mcpServers": {
"newnadoon": {
"httpUrl": "http://localhost:8080/api/mcp",
"headers": {
"Authorization": "Bearer ndk_..."
}
}
}
}Grok — ~/.grok/config.toml
[mcp_servers.newnadoon]
url = "http://localhost:8080/api/mcp"
headers = { Authorization = "Bearer ${NEWNADOON_MCP_KEY}" }Start the server with npx newnadoon-api --port 8080. After connect, the client should list the agent plus each exported CRUD tool.
Validate without an IDE:
npx newnadoon-mcp --baseUrl http://localhost:8080 --tool kanban-workitem-agent --input {"task":"list work items"}Typical frontend flow
In a browser app using useNewnadoonAgent():
- call
/runto start execution - subscribe to
/eventsfor live updates - render streamed tokens while running
- read final state on completion
This is the same flow used by the prebuilt chat hooks and components.
Common errors
If API calls fail, check:
newnadoon.jsonexists and has a validagentsobjectagentIdin requests matches a registered agent key- route file is exactly at
app/api/newnadoon/[...path]/route.ts(for App Router mode) - Node runtime is enabled in the route (
export const runtime = 'nodejs') - your frontend
runUrlandeventsUrlmatch the deployed base path
Next step
Use the frontend integration guide to connect these endpoints to UI patterns: Bring agent to Frontend apps.