pingpong

pingpong

Pingpong is an MCP server for oh-my-pi that gives your AI agent a local code reviewer using a local LLM (llama.cpp) for automated code reviews after task completion.

Category
访问服务器

README

⚠️ DEPRECATED: Moved to brainrouter

Note: This project is now part of brainrouter. All new development, features, and bug fixes are happening there.

Pingpong is an MCP server for oh-my-pi that gives your AI agent a local code reviewer. After completing work, the agent calls request_review. Pingpong sends the git diff, PRD, and task context to a local LLM (llama.cpp) which reviews the work and returns structured feedback — all within the same tool call. The agent revises and retries inside one premium cloud request. A browser-based escalation UI handles the cases the local LLM cannot resolve.

Optionally, a model router selects the cheapest sufficient model for each task, routing through a LiteLLM proxy.


Quick Start

oh-my-pi (recommended)

curl -sSL https://raw.githubusercontent.com/ajaxdude/pingpong/master/install.sh | bash

The installer:

  • Clones this repo into ~/.omp/skills/pingpong/
  • Builds the TypeScript
  • Installs node_modules into the skill folder
  • Writes ~/.omp/agent/mcp.json pointing at ~/.omp/skills/pingpong/dist/mcp.js
  • Injects templates/APPEND_SYSTEM.md and templates/LLAMACPP.md into your agent config

After installing, create pingpong.config.json in each project where you want reviews (see Configuration).

Manual

git clone https://github.com/ajaxdude/pingpong.git
cd pingpong
npm install && npm run build

Add to your MCP config:

{
  "mcpServers": {
    "pingpong": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/pingpong/dist/mcp.js"]
    }
  }
}

How It Works

  1. Your agent completes a task and calls request_review.
  2. Pingpong creates a session and blocks until the review resolves.
  3. Pingpong reads the local pingpong.config.json, collects the git diff, PRD, and any AGENTS.md.
  4. The local LLM (llama.cpp) reviews the context and responds with a JSON verdict: { "status": "approved" | "needs_revision" | "escalated", "feedback": "..." }
  5. On needs_revision: feedback is added to session history and the loop continues (up to maxIterations).
  6. On approved: request_review returns the verdict to the agent immediately.
  7. On escalated or LLM failure: the browser UI opens at http://localhost:3458/review-requests for human review.

The agent receives the final resolved status from request_review — never a pending response that requires polling.


MCP Tools

request_review

Submit completed work for automated review. Blocks until the review reaches a terminal state.

Input:

Field Type Required Description
taskId string Yes Format: [type]-[date]-[seq], e.g. feature-20260314-001
summary string Yes 2–3 sentences: what changed, why, assumptions
details string No Additional context, edge cases, security notes
conversationHistory string[] No Prior conversation turns for context

Return:

{
  "status": "approved",
  "feedback": "Looks good. Error handling is solid.",
  "sessionId": "abc123",
  "iterationCount": 2,
  "reviewerType": "llm"
}

status is always terminal: approved, needs_revision, or escalated. The agent should treat needs_revision as a directive to fix and re-submit.

What gets reviewed:

  • Git diff (git diff HEAD)
  • Project PRD (auto-detected from ./docs/PRD.md, ./PRD.md, or ./README.md)
  • AGENTS.md if present
  • Built-in criteria: correctness, security, performance, maintainability, test coverage, documentation

get_session_list

Returns all sessions (for debugging or the dashboard).

{
  "sessions": [
    { "id": "abc123", "taskId": "feature-20260314-001", "status": "approved", "summary": "..." }
  ]
}

get_session_details

Returns full detail for a session.

Input: sessionId (string, required)

Return includes: status, llmFeedback, humanFeedback, escalationReason, iterationCount, reviewerType


resolve_session

Manually resolve a session. Used by the web UI and for testing.

Input: sessionId (string), feedback (string)


Model Routing (optional)

The select_model tool picks the cheapest sufficient model before significant LLM calls.

select_model

Input: prompt (string, required), context (string, optional)

Return:

{ "model": "claude-sonnet-4", "cached": false, "latencyMs": 42 }

How routing works:

  1. First 500 chars of the prompt are hashed for cache lookup (200-entry LRU).
  2. On cache miss: the classifier (your local llama.cpp) picks from the live model list fetched from LiteLLM.
  3. Selection tiers: local/small → fast cloud → frontier → reasoning models.
  4. Any routing failure falls back silently to router.fallbackModel.

Requires a running LiteLLM proxy (router.litellmBaseUrl). Disable with router.enabled: false.


Configuration

Create pingpong.config.json in your project root (not the pingpong install directory). Pingpong reads it from process.cwd() at startup — one config per project.

{
  "llm": {
    "endpoint": "http://127.0.0.1:8080/v1/chat/completions",
    "model": "default",
    "temperature": 0.2,
    "maxTokens": 4096,
    "timeout": 1800
  },
  "prd": {
    "autoDetect": true,
    "paths": ["./docs/PRD.md", "./PRD.md", "./README.md"],
    "fallbackPath": null
  },
  "review": {
    "maxIterations": 5,
    "retryOnLlmError": true
  },
  "escalation": {
    "enabled": true,
    "port": 3458,
    "autoOpenBrowser": true
  },
  "gitDiff": {
    "enabled": true,
    "maxSizeBytes": 102400
  },
  "router": {
    "enabled": false,
    "litellmBaseUrl": "http://localhost:4000",
    "litellmApiKey": "sk-1234",
    "classifierUrl": "http://127.0.0.1:8080/v1/chat/completions",
    "fallbackModel": "best",
    "modelListRefreshSeconds": 60,
    "cacheMaxEntries": 200
  }
}

Copy pingpong.config.example.json as a starting point.

Key options

Option Default Description
llm.endpoint http://127.0.0.1:8080/v1/chat/completions llama.cpp endpoint for reviews
llm.timeout 1800 Seconds before LLM call times out
review.maxIterations 5 Max LLM passes before human escalation
escalation.enabled true Whether to start the web UI server
escalation.port 3458 Port for the web UI and HTTP API
router.enabled false Enable model routing (requires LiteLLM)

Environment variable overrides

PINGPONG_LLM_ENDPOINT          # Override llm.endpoint
PINGPONG_LLM_MODEL             # Override llm.model
PINGPONG_LLM_TIMEOUT           # Override llm.timeout (integer seconds)
PINGPONG_PRD_PATH              # Set prd.fallbackPath
PINGPONG_ESCALATION_PORT       # Override escalation.port
PINGPONG_ROUTER_ENABLED        # "true" or "false"
PINGPONG_ROUTER_FALLBACK_MODEL # Override router.fallbackModel

Web UI & HTTP API

The escalation server starts automatically when escalation.enabled is true. If port 3458 is already in use (e.g. a prior instance), Pingpong logs a warning and continues without the web UI — stdio tool calls still work.

Pages

URL Description
http://localhost:3458/review-requests All review sessions — status, feedback, iteration count
http://localhost:3458/ Model routing dashboard (if router enabled)

HTTP API

GET  /api/health                    Health check
GET  /api/sessions                  All sessions with full fields
POST /api/sessions/:id/feedback     Submit human review feedback
DELETE /api/sessions/:id            Delete a session
GET  /api/routing-events            Recent routing decisions

Submit feedback:

curl -X POST http://localhost:3458/api/sessions/<sessionId>/feedback \
  -H 'Content-Type: application/json' \
  -d '{"feedback": "Approved — looks good."}'

ok, lgtm, approved, looks good, or ship it (case-insensitive) resolve the session as approved.


Session Storage

Sessions persist to .pingpong/sessions/ in your project root (the directory where the agent runs, not the pingpong install). Each session is a JSON file named by its nanoid. Sessions older than 24 hours are purged by an hourly cleanup cron.

Add .pingpong/ to your project's .gitignore.


Agent Contract

Two template files govern agent behavior after install:

~/.omp/agent/APPEND_SYSTEM.md — injected into the agent system prompt:

  • Agent must call request_review after completing any task
  • Agent must never claim work is done without an approved review
  • needs_revision feedback is a directive to fix and re-submit in the same session

~/.omp/agent/LLAMACPP.md — context for the local LLM reviewer:

  • Six evaluation categories and their criteria
  • Required JSON response format
  • Edit to adjust review strictness or add project-specific rules

Development

Build and deploy

npm run build              # Compile TypeScript to dist/
npm test                   # Run all tests
npm run test:unit          # Unit tests only
npm run test:integration   # Integration tests only

# Deploy to local OMP skill installation
./scripts/sync-to-skill.sh

sync-to-skill.sh builds, then rsyncs dist/ and templates/ to ~/.omp/skills/pingpong/. Restart OMP after running it.

Project layout

src/
├── mcp.ts                 # MCP entry point — tool handlers, stdio transport
├── config.ts              # Config loader, env overrides, validation
├── types.ts               # All TypeScript types
├── review-loop.ts         # Review iteration orchestrator
├── llm-client.ts          # LLM HTTP client and response parser
├── llm-prompt.ts          # Prompt assembler
├── context-gatherer.ts    # PRD, git diff, AGENTS.md loading
├── session-manager.ts     # Session CRUD, file persistence, cleanup cron
├── escalation-server.ts   # Express HTTP server, all routes
├── router.ts              # ModelRouter, LiteLLM integration, route events
└── tools/
    └── mcp_pingpong_select_model.ts

templates/
├── APPEND_SYSTEM.md       # Agent system prompt additions
├── LLAMACPP.md            # Local LLM reviewer instructions
├── escalation.html        # Human review session page
├── review-requests.html   # Session dashboard
├── routing-dashboard.html # Routing events dashboard
└── setup.html             # llama.cpp setup guide

scripts/
└── sync-to-skill.sh       # Build + deploy to ~/.omp/skills/pingpong/

Troubleshooting

Sessions stay pending in the dashboard The MCP tool blocks and returns the final status — if you see pending it means an old session from a prior (broken) version. Delete stale sessions via the dashboard or DELETE /api/sessions/:id.

llama.cpp not connecting

curl http://127.0.0.1:8080/v1/models   # verify it is running
llama-server -p 8080 -m /path/to/model.gguf

Port 3458 already in use A prior Pingpong process is still running. Kill it, or set a different escalation.port in config. Pingpong will log a warning and run without the web UI if the port is occupied.

PRD not detected Ensure a file exists at ./docs/PRD.md, ./PRD.md, or ./README.md in your project root, or set prd.fallbackPath in pingpong.config.json.

Router always falls back LiteLLM is not running at router.litellmBaseUrl, or router.enabled is false. Check router.litellmBaseUrl in config.

MCP not appearing in tool list after restart Verify ~/.omp/agent/mcp.json points at ~/.omp/skills/pingpong/dist/mcp.js and that file exists.


License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选