sample-mcp
Click on "Install 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., "@sample-mcpadd 5 and 3"
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.
Sample MCP Server + AI Hook Web Service
A sample MCP (Model Context Protocol) server and an AI Hook Web Service built with Node.js and TypeScript.
MCP Server — exposes Tools, Resources, and Prompts to AI clients (Claude Desktop, Claude Code, etc.)
AI Hook Web Service — HTTP service for logging AI usage events from Claude, Claude Code, OpenAI/Codex, OpenCode, and any other provider. Logs are kept in memory and persisted to a JSON file (no database required), with automatic cost estimation and a live web dashboard.
Table of Contents
Related MCP server: Basic MCP Server
Project Structure
sample-mcp-and-hook/
├── src/
│ ├── main.ts # MCP server entry point
│ ├── tools.ts # MCP Tools (greet, add)
│ ├── resources.ts # MCP Resources (config, user-profile)
│ ├── prompts.ts # MCP Prompts (explain-code, review-code)
│ └── web-server.ts # AI Hook Web Service entry point
├── public/
│ └── index.html # Static web dashboard (AI Hook Monitor)
├── scripts/
│ └── ai-hook.sh # Enriches Claude Code Stop hooks with token usage
├── .claude/
│ └── settings.json # Claude Code hooks + AI_HOOK_URL
├── .mcp.json # MCP server registration for Claude Code
├── logs/ # Persisted hook logs (ai-hooks.json, git-ignored)
├── dist/ # Compiled JavaScript (after build)
├── package.json
├── tsconfig.json
└── README.mdSetup
Prerequisites: Node.js 18+ (and jq + curl for the Claude Code hooks)
# Install dependencies
pnpm install
# Build TypeScript
pnpm buildMCP Server
Running the MCP Server
# Production
pnpm start:mcp
# Development (auto-rebuild on change)
pnpm devMCP Core Primitives
Primitive | Purpose | Direction | Example Use Case |
Tools | Execute actions | AI → Server | Calculations, API calls |
Resources | Provide data | Server → AI | Config, documents, user data |
Prompts | Template messages | Server → AI | Standardized instructions |
Tools (src/tools.ts)
greet— greets a user by nameadd— adds two numbers together
Resources (src/resources.ts)
config://app— static application configurationusers://{userId}/profile— dynamic user profile by ID
Prompts (src/prompts.ts)
explain-code— prompt template for explaining codereview-code— parameterized code review (language, focus area)
Connect to Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"sample-mcp": {
"command": "node",
"args": ["/absolute/path/to/sample-mcp-and-hook/dist/main.js"]
}
}
}For Claude Code, the server is already registered in .mcp.json (relative path) and enabled in .claude/settings.local.json — no manual setup needed once you've run pnpm build.
AI Hook Web Service
A lightweight HTTP service that receives AI usage events, logs them to the console, and persists them to logs/ai-hooks.json. Logs survive server restarts — the file is loaded automatically on startup. Cost is estimated automatically from token counts, and a live dashboard is served at the root URL. No database needed.
Running the Web Service
# Production (build first)
pnpm build
pnpm start:hook
# Development (watches compiled output)
pnpm dev # terminal 1 — recompile on change
pnpm dev:hook # terminal 2 — restart server on changeDefault port: 3000. Override with the PORT environment variable:
PORT=4000 pnpm start:hookLog file:
logs/ai-hooks.json(auto-created, already in.gitignore). Logs persist across restarts — the file is loaded on startup and rewritten after every hook received. Up to 1000 most-recent entries are retained in memory.
Web Dashboard
Once the service is running, open the dashboard in your browser:
http://localhost:3000/The static dashboard (public/index.html) visualizes logged events and aggregate stats per provider and model — color-coded by provider (Claude, Claude Code, OpenAI, OpenCode) and event type.
Logging Claude Code Usage
This repo is preconfigured to log its own Claude Code usage to the web service.
Step 1 — Start the web service (keep it running in a separate terminal):
pnpm build
pnpm start:hook
# AI Hook Web Service running on http://localhost:3000Step 2 — No model config needed. The hooks auto-detect your model at runtime:
On Stop events,
scripts/ai-hook.shreads the session transcript and extracts the exact model plus real token usage (input, output, cache read/write).On SessionStart / UserPromptSubmit events (no token data available), an inline hook resolves the model from
.claude/settings.json→~/.claude/settings.json→ falls back to"claude-code".
Whatever model you have configured in Claude Code is tracked automatically — no manual configuration required.
The hooks and endpoint are already wired up in .claude/settings.json:
{
"env": {
"AI_HOOK_URL": "http://localhost:3000/api/hook/claudecode"
},
"hooks": {
"SessionStart": [ /* inline curl — logs session_start */ ],
"UserPromptSubmit": [ /* inline curl — logs prompt_submit */ ],
"Stop": [ { "command": "bash scripts/ai-hook.sh" } ]
}
}Step 3 — Open Claude Code in this project directory as usual:
claudeEvery session start, user prompt, and Claude response is logged automatically (asynchronously, so Claude Code is never blocked).
Step 4 — View the logs in the dashboard or via the API:
# All events from Claude Code
curl "http://localhost:3000/api/logs?provider=claudecode"
# Aggregated stats
curl http://localhost:3000/api/statsNote: The web service must be running on the configured port before Claude Code starts. If the service is down, hooks fail silently (Claude Code is not affected).
Endpoints
Method | Path | Description |
|
| Static web dashboard |
|
| Receive a hook (provider auto-detected from body) |
|
| Receive a hook with explicit provider name |
|
| List logs (newest first) |
|
| Aggregate stats grouped by provider + model |
|
| Clear all logs |
|
| Health check (log count, log file path, uptime) |
Sending Hooks
The service auto-detects the provider from the request body. You can also send hooks to /api/hook/:provider to set the provider explicitly.
Claude
curl -X POST http://localhost:3000/api/hook \
-H "Content-Type: application/json" \
-d '{
"provider": "claude",
"model": "claude-sonnet-4-6",
"type": "message",
"id": "msg_01abc",
"session_id": "sess_xyz",
"usage": {
"input_tokens": 1200,
"output_tokens": 350,
"cache_read_input_tokens": 800
}
}'Console output (cost is auto-estimated from tokens):
[HOOK] 2026-07-02T06:00:00.000Z | claude | claude-sonnet-4-6 | in=1200 out=350 total=1550 cost=$0.008850 session=sess_xyzOpenAI / Codex
curl -X POST http://localhost:3000/api/hook \
-H "Content-Type: application/json" \
-d '{
"provider": "openai",
"model": "gpt-4o",
"object": "chat.completion",
"id": "chatcmpl-abc",
"cost_usd": 0.00014,
"usage": {
"prompt_tokens": 500,
"completion_tokens": 200,
"total_tokens": 700
}
}'OpenCode
# Using explicit provider path
curl -X POST http://localhost:3000/api/hook/opencode \
-H "Content-Type: application/json" \
-d '{
"model": "claude-3-5-sonnet",
"event": "completion",
"input_tokens": 900,
"output_tokens": 420,
"total_tokens": 1320,
"cost": 0.00031,
"duration_ms": 1850,
"session_id": "oc_sess_999"
}'Generic / Custom Provider
Any JSON body with a provider field works:
curl -X POST http://localhost:3000/api/hook \
-H "Content-Type: application/json" \
-d '{
"provider": "my-custom-llm",
"model": "my-model-v1",
"event": "inference",
"input_tokens": 300,
"output_tokens": 150,
"cost_usd": 0.00005,
"user_id": "user_42",
"metadata": { "region": "ap-southeast-1" }
}'Cost Estimation
When a hook does not include an explicit cost_usd (or cost), the service estimates it from token counts using built-in per-model pricing (input, output, cache-read, and cache-write rates per million tokens). Pricing is matched by substring against the model name, covering the Claude Opus/Sonnet/Haiku families (v3, v3.5, and v4).
If an explicit cost is provided in the payload, it is used as-is.
If no matching model pricing is found, cost is left unset.
Estimated cost appears in the console output, the
cost_usdlog field, and the aggregated stats.
Adjust the MODEL_PRICING table in src/web-server.ts to add models or update rates.
Query Logs
# All logs (newest first, default limit 50, max 500)
curl http://localhost:3000/api/logs
# Filter by provider (exact match)
curl "http://localhost:3000/api/logs?provider=claude"
# Filter by model name (partial match)
curl "http://localhost:3000/api/logs?model=sonnet"
# Combine filters and set limit
curl "http://localhost:3000/api/logs?provider=openai&limit=10"
# Clear all logs
curl -X DELETE http://localhost:3000/api/logsResponse shape:
{
"total": 42,
"returned": 10,
"logs": [
{
"id": "log_1782972333250_96p2e",
"received_at": "2026-07-02T06:05:33.250Z",
"provider": "claude",
"model": "claude-sonnet-4-6",
"event": "message",
"session_id": "sess_xyz",
"tokens": {
"input": 1200,
"output": 350,
"cache_read": 800,
"total": 1550
},
"cost_usd": 0.00885,
"request_id": "msg_01abc",
"raw": { "...": "original payload" }
}
]
}View Stats
curl http://localhost:3000/api/statsStats are grouped by provider + model and sorted by call count (descending).
Response shape:
{
"providers": ["claude", "openai", "opencode"],
"stats": [
{
"provider": "claude",
"model": "claude-sonnet-4-6",
"calls": 15,
"total_input_tokens": 18000,
"total_output_tokens": 5250,
"total_tokens": 23250,
"total_cache_read_tokens": 9600,
"total_cache_write_tokens": 0,
"total_cost_usd": 0.1328,
"total_duration_ms": 0
},
{
"provider": "openai",
"model": "gpt-4o",
"calls": 8,
"total_input_tokens": 4000,
"total_output_tokens": 1600,
"total_tokens": 5600,
"total_cache_read_tokens": 0,
"total_cache_write_tokens": 0,
"total_cost_usd": 0.00112,
"total_duration_ms": 0
}
]
}Dependencies
Package | Purpose |
| Official MCP SDK |
| HTTP server for the AI Hook Web Service |
| Schema validation for MCP tool inputs |
Learn More
License
ISC
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Thammasok/sample-mcp-and-hook'
If you have feedback or need assistance with the MCP directory API, please join our Discord server