Skip to content
AGNT
All guides
Ecosystem workflowadvanced

Build an MCP server that exposes AGNT wiki + graph

Ship a custom MCP server wrapping AGNT's wiki and knowledge graph endpoints.

AGNT's built-in MCP server at /mcp/sse surfaces venue search and memory. If you want to expose additional AGNT surfaces — the wiki vault, the graph API, custom metrics — you'll need a custom MCP server. This guide walks through building one in TypeScript with the official MCP SDK.

AGNT Developer Experience15 minverified 2026-04-10

Prerequisites

  • Node.js 20+.
  • Familiarity with the MCP spec (https://modelcontextprotocol.io).
  • An AGNT API key with `wiki.read` and `graph.read` scopes.
  • Comfort with TypeScript and async HTTP clients.

Why roll your own

AGNT ships a default MCP server that covers the high-frequency surfaces — venue search, memory, knowledge graph. If your workflow needs something more specific (a single wiki cluster, a filtered graph view, custom aggregations), you want a thin custom server rather than overloading the built-in one.

The MCP spec makes this cheap. A server is a process that speaks MCP over stdio or SSE, declares tools, and handles tool calls. With the official SDK, you can have a custom server in ~100 lines of TypeScript.

Step 1 — Scaffold the project

Create a new directory and install the MCP SDK:

mkdir agnt-wiki-mcp && cd agnt-wiki-mcp
npm init -y
npm install @modelcontextprotocol/sdk

The SDK provides the transport layer, the JSON-RPC handling, and the tool registration API. You're only writing business logic.

Step 2 — Define your tools

Decide which AGNT surfaces you want to expose. For this guide, we'll expose two tools: `wiki_search` (full-text search against the wiki) and `graph_neighbors` (return direct neighbors of an entity in the knowledge graph).

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server({ name: "agnt-wiki", version: "1.0.0" });

server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "wiki_search",
      description: "Full-text search the AGNT wiki vault",
      inputSchema: {
        type: "object",
        properties: { query: { type: "string" } },
        required: ["query"],
      },
    },
    {
      name: "graph_neighbors",
      description: "Return direct neighbors of an entity in the AGNT knowledge graph",
      inputSchema: {
        type: "object",
        properties: { entity: { type: "string" } },
        required: ["entity"],
      },
    },
  ],
}));

The `description` field is the single most important thing. LLMs route into tools based on description quality. Use the `/prompts/tool-description-tightener` discipline when writing these.

Step 3 — Implement the tool handlers

Each tool gets a handler that calls AGNT's REST API and returns a structured result:

server.setRequestHandler("tools/call", async (request) => {
  const { name, arguments: args } = request.params;
  const apiKey = process.env.AGNT_API_KEY;
  const base = "https://api.agntdot.com";

  if (name === "wiki_search") {
    const res = await fetch(`${base}/wiki/search?q=${encodeURIComponent(args.query)}`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    const data = await res.json();
    return { content: [{ type: "text", text: JSON.stringify(data) }] };
  }

  if (name === "graph_neighbors") {
    const res = await fetch(`${base}/graph/neighbors?entity=${encodeURIComponent(args.entity)}`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    const data = await res.json();
    return { content: [{ type: "text", text: JSON.stringify(data) }] };
  }

  throw new Error(`Unknown tool: ${name}`);
});

Notice the response shape: `{ content: [{ type: "text", text: ... }] }`. This is MCP's standard tool response format. You can return multiple content items (text, images, etc.) — stick with text for JSON payloads.

Step 4 — Start the server

Add the stdio transport and start:

const transport = new StdioServerTransport();
await server.connect(transport);

Compile with `npx tsc` (or `tsx` for dev). The server runs as a subprocess — MCP clients like Claude Code launch it, speak to it over stdio, and terminate it when the session ends.

Step 5 — Wire it into Claude Code

Add the server to your Claude Code MCP config:

{
  "mcpServers": {
    "agnt-wiki": {
      "command": "node",
      "args": ["/abs/path/to/agnt-wiki-mcp/dist/index.js"],
      "env": {
        "AGNT_API_KEY": "${AGNT_API_KEY}"
      }
    }
  }
}

Restart Claude Code. Ask: "what tools are available from agnt-wiki?" You should see `wiki_search` and `graph_neighbors`.

Tighten your tool descriptions

Before you ship, run the `tool-description-tightener` prompt against each tool description. LLM routing is extremely sensitive to description quality — a 10-character change in the description can flip whether a model routes into the tool or not. This is the single biggest lever for usability.

Rule of thumb: the first 10 words must contain the action verb and the primary object. "Full-text search the AGNT wiki vault" is good. "Helps you find things in the wiki" is bad.

Next steps