greennode-agentbase-mcp

greennode-agentbase-mcp

MCP server that exposes GreenNode AgentBase REST APIs as three searchable meta-tools (list_servers, search_tools, execute), reducing tool-definition overhead by ~95%. Runs locally over stdio or remotely over streamable HTTP with any MCP client.

Category
Visit Server

README

greennode-agentbase-mcp

An MCP server that exposes the GreenNode AgentBase REST APIs as 3 searchable meta-tools — a search→execute gateway that cuts the MCP tool-definition tax ~95%+ versus flattening every operation into its own tool. Runs locally over stdio (default) or remotely over streamable HTTP, with any MCP-speaking client.

Table of contents

Quick start

Connect a local MCP client (Claude Code, Cursor, Windsurf, …) to the gateway over stdio in under a minute.

Prerequisites

  • Node.js ≥ 20 (see package.json engines)
  • A GreenNode AgentBase bearer token — one token is valid across all six services

1. Install

git clone https://github.com/GreenNodeHub/greennode-agentbase-mcp.git
cd greennode-agentbase-mcp
npm ci

2. Run (stdio is the default transport — no need to set TRANSPORT)

GREENNODE_MCP_TOKEN=<your-token> npm start

3. Wire up your client. Claude Code — .mcp.json:

{
  "mcpServers": {
    "agentbase": {
      "command": "npx",
      "args": ["tsx", "src/index.ts"],
      "env": { "GREENNODE_MCP_TOKEN": "<your-token>" }
    }
  }
}

For Cursor, Windsurf, Cline, Roo Code, Claude Desktop, and other clients, see docs/mcp-client-quickstart.html — same command + env, each client's own config key.

Optional — auto-rotating token (external). If you have the agentbase skill installed (it ships .claude/skills/agentbase/scripts/get_token.sh, which is not part of this repo) plus GREENNODE_CLIENT_ID / GREENNODE_CLIENT_SECRET (or a .greennode.json), point your client at scripts/mcp-launch.sh instead. It mints a fresh ~30-minute IAM JWT on every (re)start, so reconnecting rotates the token automatically — no manual re-export, no stale-token 401s.

First call flow: list_servers → search_tools → execute (see How it works).

How it works

Instead of exposing 100+ operations as individual MCP tools (a large manifest the model pays for every turn), the server exposes 3 meta-tools. The full operation set lives in a generated registry the model searches on demand.

┌───────────────────────────────────────────────────────────────┐
│  Generated layer  (from specs, committed, never hand-edited)  │
│    registry.generated.json                                    │
│      every operation: { id, service, method, path,            │
│                         summary, tags, inputSchema, … }       │
└───────────────────────────────────────────────────────────────┘
                          ▲ consumed by
┌───────────────────────────────────────────────────────────────┐
│  Meta layer  (hand-written TypeScript)                        │
│    • 3 meta-tools: list_servers, search_tools, execute        │
│    • BM25 search engine                                       │
│    • JMESPath field projection + response byte cap            │
│    • inbound auth + downstream token pass-through             │
│    • env resolver (base URLs, transport, limits)              │
└───────────────────────────────────────────────────────────────┘

Meta-tools

Tool Args Returns
list_servers — the services, each with its operation count + tags
search_tools query, server?, limit? BM25-ranked operations, each with its full inputSchema inline
execute id, args?, fields? the real HTTP response, projected by fields and byte-capped

Discovery is two steps: search_tools returns enough to call execute directly (the input schema is inline), so there's no separate describe step.

// 1) orient on the six services
list_servers()
// → [{ "name": "policy", "description": "policy service (… operations)", "operationCount": …, "tags": […] }, …]

// 2) search by intent — the id and full inputSchema come back together
search_tools({ query: "list policy groups" })
// → [{ "id": "policy.get_api_v1_policy_groups", "service": "policy",
//      "summary": "List policy groups", "inputSchema": { "type": "object",
//      "properties": { "page": {…}, "page_size": {…}, "name": {…} } } }, …]

// 3) execute; `fields` is an optional JMESPath projection to shrink the response
execute({ id: "policy.get_api_v1_policy_groups", args: { page: 1, page_size: 10 } })
// → the live response (omit `fields` to see the whole body; pass e.g. fields:"items[].name" to project it)

Operation ids look like service.<method>_<slugified-path> (e.g. policy.get_api_v1_policy_groups). Always take an id from search_tools — never type one by hand.

Why meta-tools: 3 tool definitions (~1–2K resident tokens) instead of one tool per operation. See benchmarks/report-2026-07-06.md for the token math — a 36.8× smaller manifest and 7–41% fewer input tokens end-to-end versus the flat (one-tool-per-op) variant.

Transports: stdio vs. streamable HTTP

stdio streamable HTTP
Use case local, any MCP client deployed runtime / remote clients
Default yes (TRANSPORT=stdio) opt-in (TRANSPORT=http)
Lifecycle one server for the process lifetime fresh server + transport per request (stateless)
Token source env var named by TOKEN_ENV (default GREENNODE_MCP_TOKEN) Authorization: Bearer header, per request
Endpoint stdin/stdout (JSON-RPC) POST /mcp
Health — GET /healthz, GET /health

stdio (default)

The server reads JSON-RPC from stdin and writes responses to stdout. stdout is the protocol — all diagnostics and the one-line startup banner go to stderr, so they never corrupt the stream.

GREENNODE_MCP_TOKEN=<your-token> npm start   # TRANSPORT=stdio is the default

The token is read once at startup from the env var named by TOKEN_ENV (default GREENNODE_MCP_TOKEN). The server runs for the process lifetime and exits when the client closes stdin. See Quick start for the client-wiring snippet.

Streamable HTTP

For a deployed runtime or remote clients. Each POST /mcp builds a fresh server + StreamableHTTPServerTransport for that request (stateless) and authenticates from the Authorization header. The token is not read from the environment in this mode.

TRANSPORT=http npm start   # listens on :8080 (PORT); pass the token per request, not via env

Smoke-test it:

curl http://localhost:8080/healthz          # → {"ok":true}

# a raw initialize request to /mcp (clients normally build this JSON-RPC envelope for you)
curl -X POST http://localhost:8080/mcp \
  -H "Authorization: Bearer <your-token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

Configuration

All config is via environment variables, read once at startup by loadEnvConfig (src/config/env.ts).

Var Default Notes
TRANSPORT stdio stdio or http. Any other value throws at boot — the process exits non-zero, nothing listens.
GREENNODE_MCP_TOKEN — Upstream bearer token, stdio only. Forwarded to all six services on execute.
TOKEN_ENV GREENNODE_MCP_TOKEN Name of the env var that holds the token, stdio only. Set this to read the token from a differently-named var.
PORT 8080 HTTP transport listen port.
MAX_RESPONSE_BYTES 25000 Hard cap on execute responses; over-cap responses are truncated with a notice.
SEARCH_LIMIT_DEFAULT 5 Default limit for search_tools when the caller omits it.

In streamable HTTP mode the token is not read from env at all — clients supply it per request via Authorization: Bearer. GREENNODE_MCP_TOKEN / TOKEN_ENV apply only to stdio.

Development & operations

Scripts (package.json):

Script What it does
npm start Run the server (tsx src/index.ts)
npm run dev Run with reload (tsx watch src/index.ts)
npm run build Typecheck only (tsc --noEmit). There is no compiled dist/ — the runnable form is tsx.
npm test / npm run test:watch Vitest
npm run fetch-specs Refresh specs/ from the AgentBase spec endpoints
npm run generate-registry Rebuild registry.generated.json from specs/

Regenerate the registry when the upstream specs change:

npm run fetch-specs && npm run generate-registry

Then commit both specs/ and registry.generated.json. Both are generated — never hand-edit them.

Docker:

docker build -t greennode-agentbase-mcp .
docker run -e TRANSPORT=http -p 8080:8080 greennode-agentbase-mcp

The bearer token is supplied per request via the Authorization header (same as HTTP mode) — not via env.

⚠️ TRANSPORT defaults to stdio. A deployed HTTP runtime — and the shipped Dockerfile (which sets PORT but not TRANSPORT) — must set TRANSPORT=http explicitly. Without it the process starts in stdio mode and listens on no port. The docker run command above passes -e TRANSPORT=http; for a production image, bake ENV TRANSPORT=http into the Dockerfile.

Further reading

License

See LICENSE.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured