Skip to main content

Prerequisites

  • Node.js 18.17+ (Node 20+ recommended)
  • A running MCP server using @modelcontextprotocol/sdk (or compatible: Skybridge, @vercel/mcp-handler)
  • A WaniWani account at app.waniwani.ai
If you do not have an MCP server yet, scaffold one from the Alpic Apps SDK template and come back here.
1

Install the SDK

bun add @waniwani/sdk
2

Get an API key

  1. Open app.waniwani.ai and sign in.
  2. Create an MCP environment (one per deployment target, for example my-app-prod).
  3. Copy the API key from the environment settings. Keys start with wwk_ and are shown in full only once.
  4. Expose it to your server process:
.env
WANIWANI_API_KEY=wwk_...
The SDK reads WANIWANI_API_KEY from the environment by default.
3

Wrap your MCP server

Call withWaniwani(server) once, after creating the server and before connecting the transport. It intercepts registerTool and emits a tool.called event for every invocation.
server/src/index.ts
import express from "express";
import { withWaniwani } from "@waniwani/sdk/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import "dotenv/config";

const server = new McpServer({ name: "my-mcp-app", version: "0.0.1" });

// Register tools as usual
server.registerTool(/* ... */);

// Enable automatic tracking
withWaniwani(server);

// Connect the Streamable HTTP transport
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);

const app = express();
app.use(express.json());
app.post("/mcp", (req, res) => transport.handleRequest(req, res, req.body));
app.listen(3000);
With no arguments, withWaniwani creates a client from WANIWANI_API_KEY. Tools registered before or after the wrap call are both instrumented.
4

Verify it works

Restart the server, trigger any tool call from your MCP client (Claude Desktop, ChatGPT, inspector, etc.), then open the WaniWani dashboard. The tool.called event should appear within a few seconds.If nothing shows up, check that WANIWANI_API_KEY is set in the process running the server and look for [waniwani] lines in your server logs.

Track a custom event

For anything beyond tool.called (a completed purchase, a successful quote, a custom funnel step), call client.track() from inside a tool handler. Pass meta: extra._meta so the event is linked to the current MCP session.
import { waniwani } from "@waniwani/sdk";

const wani = waniwani();

server.registerTool(
  "get_quote",
  { /* tool config */ },
  async ({ amount, currency }, extra) => {
    await wani.track({
      event: "quote.succeeded",
      properties: { amount, currency },
      meta: extra._meta,
    });

    return { content: [{ type: "text", text: `Quoted ${amount} ${currency}` }] };
  },
);

What’s next

Client configuration

Requirements, options, and graceful shutdown.

API keys

Per-environment keys, rotation, and troubleshooting.

withWaniwani reference

All options for the server wrapper.

Build a flow

Multi-turn, stateful MCP tools.