greennode-agentbase-mcp
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@greennode-agentbase-mcplist policy groups"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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
Related MCP server: daimonos
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.jsonengines)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 ci2. Run (stdio is the default transport — no need to set TRANSPORT)
GREENNODE_MCP_TOKEN=<your-token> npm start3. 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
agentbaseskill installed (it ships.claude/skills/agentbase/scripts/get_token.sh, which is not part of this repo) plusGREENNODE_CLIENT_ID/GREENNODE_CLIENT_SECRET(or a.greennode.json), point your client atscripts/mcp-launch.shinstead. 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 |
| — | the services, each with its operation count + tags |
|
| BM25-ranked operations, each with its full |
|
| the real HTTP response, projected by |
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 ( | opt-in ( |
Lifecycle | one server for the process lifetime | fresh server + transport per request (stateless) |
Token source | env var named by |
|
Endpoint | stdin/stdout (JSON-RPC) |
|
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 defaultThe 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 envSmoke-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 |
|
|
|
| — | Upstream bearer token, stdio only. Forwarded to all six services on |
|
| Name of the env var that holds the token, stdio only. Set this to read the token from a differently-named var. |
|
| HTTP transport listen port. |
|
| Hard cap on |
|
| Default |
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_ENVapply only to stdio.
Development & operations
Scripts (package.json):
Script | What it does |
| Run the server ( |
| Run with reload ( |
| Typecheck only ( |
| Vitest |
| Refresh |
| Rebuild |
Regenerate the registry when the upstream specs change:
npm run fetch-specs && npm run generate-registryThen 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-mcpThe bearer token is supplied per request via the Authorization header (same as HTTP mode) — not via env.
⚠️
TRANSPORTdefaults tostdio. A deployed HTTP runtime — and the shippedDockerfile(which setsPORTbut notTRANSPORT) — must setTRANSPORT=httpexplicitly. Without it the process starts in stdio mode and listens on no port. Thedocker runcommand above passes-e TRANSPORT=http; for a production image, bakeENV TRANSPORT=httpinto the Dockerfile.
Further reading
docs/mcp-client-quickstart.html— per-client wiring (Claude Desktop/Code, Cursor, Windsurf, Claude.ai, Cline, Roo Code, agent frameworks)benchmarks/report-2026-07-06.md— gateway vs. flat token mathspecs/README.md— spec sources and regenerate notesdocs/superpowers/specs/— design docs (gateway, stdio local server, flatten baseline)
License
See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
MCP Server for an Agent Task Marketplace
Search, vet & assemble MCP servers from your agent: verified tools, risk labels, and trust scores.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceA high-performance Go-based MCP server that provides a microservice architecture for orchestrating diverse tools through gRPC and HTTP/REST APIs. Enables seamless integration of language-agnostic tools including ML capabilities, web search, calculations, and human interaction for intelligent agent workflows.2-
- AlicenseBqualityAmaintenanceAgent-optimized MCP server that replaces built-in file, search, exec, and git tools with compact, structured JSON equivalents. Benchmarked 20–45% token savings for AI coding agents.202MIT
- AlicenseNot gradedqualityCmaintenanceConfigurable MCP server that lets you define LLM-powered tools via JSON, enabling easy integration of multiple models (GPT, Gemini, Claude, etc.) as MCP tools without writing Python code.6MIT
- FlicenseNot gradedqualityCmaintenanceA model-agnostic MCP server exposing example tools (add1, multiply2, greet) for learning purposes, working with any LLM through stdio transport.-