Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
제작자가 쓴 설명(영어 원문)
MCP server demo — tickets, schema discovery, auth, and PII gating. stdio + HTTP.
이 세 가지는 절대 하나의 점수로 합치지 않아요. 의견, 측정, 인기는 서로 다른 것이니까요.
이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.
쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.
MCP_API_KEY, AUTH_MODE, MCP_USERS, RATE_LIMIT비밀로 표시된 값은 내 계정의 열쇠예요. 절대 다른 사람과 공유하거나 채팅에 붙여 넣지 마세요.
필요한 것
어떤 앱을 쓰세요?
위에서 앱을 고르세요. 기억해 두었다가 다음부터는 버튼에 “…에 설치”라고 표시해요.
Claude Desktop → Settings → Developer → Edit Config를 열고 claude_desktop_config.json에 이 내용을 붙여 넣으세요
{
"mcpServers": {
"ticket-demo": {
"command": "npx",
"args": [
"-y",
"mcp-ticket-demo"
],
"env": {
"MCP_API_KEY": "your-value",
"AUTH_MODE": "your-value",
"MCP_USERS": "your-value",
"RATE_LIMIT": "your-value"
}
}
}
}터미널에서 이 명령어를 실행하세요
claude mcp add ticket-demo --env MCP_API_KEY=your-value --env AUTH_MODE=your-value --env MCP_USERS=your-value --env RATE_LIMIT=your-value -- npx -y mcp-ticket-demo실행하기 전에 빈 값을 채워 주세요.
프로젝트의 .cursor/mcp.json 또는 ~/.cursor/mcp.json에 붙여 넣으세요
{
"mcpServers": {
"ticket-demo": {
"command": "npx",
"args": [
"-y",
"mcp-ticket-demo"
],
"env": {
"MCP_API_KEY": "your-value",
"AUTH_MODE": "your-value",
"MCP_USERS": "your-value",
"RATE_LIMIT": "your-value"
}
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
프로젝트의 .vscode/mcp.json에 붙여 넣으세요
{
"servers": {
"ticket-demo": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"mcp-ticket-demo"
],
"env": {
"MCP_API_KEY": "your-value",
"AUTH_MODE": "your-value",
"MCP_USERS": "your-value",
"RATE_LIMIT": "your-value"
}
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
이 서버는 내 컴퓨터에서 실행되는데, ChatGPT는 인터넷에 있는 서버에만 연결할 수 있어요. 다른 앱을 고르세요.
선택한 앱은 이 기기의 쿠키에만 저장돼요. 계정은 필요 없어요.
AUTH_MODE envRATE_LIMIT env이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.
내 컴퓨터에서 실행돼요. 설치하면 AI 앱에 도구 목록이 나타나요.
누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 8일 점검
레지스트리 이름이 GitHub 계정 markusvankempen 기준으로 확인되었고, 이 계정이 저장소를 소유하고 있어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
내 컴퓨터에서 실행되는 서버라 인터넷 엔드포인트가 없어요
내 컴퓨터에서 실행되며, 대신 로컬 설정을 사용해요
내 컴퓨터에서 실행돼요. 도구 목록은 인터넷 엔드포인트가 있는 서버에서만 읽을 수 있어요
레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.
해당하는 기본 점검 1개 중 1개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.
입력해야 할 값: MCP_API_KEY, MCP_USERS
내 컴퓨터에서 실행돼요. AI 앱이 필요할 때 실행하고, 데이터는 제작자의 서버를 거치지 않아요(서버 자체가 온라인 서비스를 호출하는 경우는 제외).
GitHub 저장소는 마지막으로 – 변경됐고, 최신 버전(1.9.0)은 지난달 레지스트리에 올라왔어요.
Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. 내 컴퓨터에 Node.js도 있어야 해요.
같은 카테고리에는: Spec Driven Development, Remote Desktop Commander, DECIDE: Migration Discovery Risk Review
같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.
카드 보는 법:↓ 주간 다운로드i★ GitHub 스타i세 기둥: 리뷰 · 점검 · 사용 정도i업데이트 = 최신 버전을 레지스트리에 공개한 날i
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Run after each discovery iteration to see what's still uncertain, who to ask next, and what changed.
제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.
A production-shaped MCP server you can run in under five minutes. Ships with 19 tools, 3 resources, 5 prompts, three auth modes, API key management, per-tool gates, rate limiting, a live observability dashboard, and a VS Code / Bob / Cursor / Windsurf control-plane extension.
Use it to learn MCP, test IDE integrations, run live demos, or as a reference implementation when building your own server.
Companion to MCP as a Platform: What I Learned Building a Portfolio of MCP Servers · MCP Dev Summit Toronto · 5 October 2026 · Talk slides →
| MCP server (3.0.1) | npm install mcp-ticket-demo |
| VS Code extension (1.16.0) | VS Code Marketplace · Open VSX |
| Talk slides | markusvankempen.github.io/linuxfoundation-mcp-dev-summit |
Personal open-source project.
Most MCP examples stop at "here is a tool that returns a string." This one goes further:
| Feature | What you learn |
|---|---|
| 19 tools with intent-named descriptions | Nouns live in a schema, verbs stay as tools — not request(path, method) |
3 resources (ticket://, tickets://open, schema://) | resources/list enumerates instances; reads use the same gate() as the matching tool |
| 5 MCP prompts | User-facing prompts vs agent-facing tools |
Tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint: false) | Client confirm/retry UX |
| Server instructions | The README the model actually reads |
| `isError: true` on every failure | Clients don't need to parse ok: false |
Attribution scar — create_ticket without requester_email | 201 is not done. The bot owns the ticket. |
Schema discovery — get_schema → run_query | One query tool beats a pile of query_* names |
| 0 tools discovered — hand a laptop path to a cloud runner | The silent failure with no error and no warning |
| stdio + SSE + Streamable HTTP from one codebase | Three transports, same 19 tools |
Auth modes (off / write / all) + per-tool gate + per-tool auth lock | Security is an operator concern |
| `tools/list_changed` broadcast when admin flips a gate | SSE and Streamable HTTP sessions refresh; one-shot curl does not |
Rate limiting with retry_after_seconds in the error | Stop the model retrying in a loop |
PII redaction on run_query schema=customers | Same tool, same endpoint; the phone field is REDACTED without the pii scope |
| `/health` vs `/test` | Alive ≠ works. Public /test is read-only; cwd stays off public /health |
Live observability — /log page with counters, error log, call trace | See what the model is actually doing |
Operate it over MCP — settings (one update_settings patch), users, API keys and settings import are tools, settings export is run_query schema=settings, and most need the admin scope even when auth is off | The control plane is part of the server, not a side door |
Three ways to operate one server — /admin Remote config, the extension's Remote config tab, and the mcp-ticket-demo command line | Same steps, same Demo setup, checked against each other |
# Run directly from npm — no clone needed
npx mcp-ticket-demo # stdio (IDE spawns this) MCP_MODE=http npx mcp-ticket-demo # HTTP — opens /health /test /admin /mcp
git clone https://github.com/markusvankempen/mcp-ticket-demo cd mcp-ticket-demo/server && npm install && npm run http
Then open in a browser:
| URL | What it shows |
|---|---|
| http://127.0.0.1:8787/health | Is the process alive? (cwd only on localhost) |
| http://127.0.0.1:8787/test | Read-only smoke: seed tickets, schemas, and run_query |
| http://127.0.0.1:8787/admin | Auth mode, API keys, tool gates, observability |
| http://127.0.0.1:8787/log | Call counters, error log, full call trace |
| http://127.0.0.1:8787/tools | Tool inventory with scope and auth status |
The same mcp-ticket-demo command is also a client for a running server, local or deployed. With no arguments it is still the MCP server, so the IDE configs below keep working.
npx mcp-ticket-demo status # http://127.0.0.1:8787/mcp by default
npx mcp-ticket-demo call run_query schema=tickets 'filter={"status":"open"}' limit=5 # any tool, values typed from its schema npx mcp-ticket-demo demo apply --user demo --password demo # users, keys, auth write, 30 calls / 60 s npx mcp-ticket-demo demo check --user demo --password demo # acts as each role and as nobody npx mcp-ticket-demo status --url https://my-host.example.com # a deployed server
--json prints one document for scripts, and exit codes are 0 done · 1 refused · 2 usage · 3 unreachable. Commands that delete or reconfigure ask first. Every command, option and example is in server/README.md, and a copy-paste page is at /clients/cli.html on a running desk. demo apply changes real settings, so use it on a server you own.
Laptop login: demo / demo. On a public bind (HOST=0.0.0.0, container, Code Engine) set ADMIN_PASSWORD — the default is disabled. Write smoke is /test?write=1 after admin sign-in.
VS Code / GitHub Copilot — .vscode/mcp.json:
{
"servers": { "mcp-ticket-demo": { "type": "stdio", "command": "npx", "args": ["mcp-ticket-demo"], "env": { "MCP_MODE": "stdio" } } } }
Bob / Cursor / Windsurf — .bob/mcp.json / .cursor/mcp.json / .windsurf/mcp.json:
{
"mcpServers": { "mcp-ticket-demo": { "command": "npx", "args": ["mcp-ticket-demo"], "env": { "MCP_MODE": "stdio" } } } }
Or install the extension and click Register server with all IDEs — it writes all four configs at once: VS Code Marketplace · Open VSX
The server has 19 tools. Six are the ticket desk, below. Eight operate the server itself: update_settings (every setting is one patch: auth mode, rate limit, call trace, desk sign-in, transports, events, gates, locks and scopes), set_mqtt, users, API keys, import_settings and sample traffic. Most of those need the admin scope even while auth is off; server/README.md lists the scope of each. Three are timers, start_timer, stop_timer and push_timer, with no get_timer (push_timer also streams the timer as events; see Events): you read a timer through the schema, run_query with schema=timers (server/README.md). push_log sends a log line as an event, and watch_system publishes the machine as system.info, including a container's cgroup limit. Plain lists are not tools of their own: run_query reads settings (the saved settings, importable as they are), system (the machine), events (the events already sent), and, with an admin credential, users, api_keys, trace, errors and counters. The page at /clients/dashboard.html draws them. Each of these tools is declared once and everything else is generated from that definition.
| Tool | Scope | When to use | Lesson |
|---|---|---|---|
describe_server | read | First call, and after any denial | Discovery beats guessing |
create_ticket | write | Open a ticket — always pass `requester_email` | Omit it → 201 + bot owns the ticket |
add_comment | write | Comment on a known ticket | Write tool; gated |
close_ticket | write | Resolve a ticket, optionally add resolution note | destructiveHint: true, idempotentHint: true |
get_schema | read | Before any query | No name lists every name with its kind (data, query, tool); a name gives that shape or those arguments |
run_query | read | The one query tool: schema=tickets (find by status / requester_email / query, or one ticket by id with body and comments), schema=customers (phone is REDACTED without the pii scope), plus assets, timers, system, settings, events (and, for an admin, users, api_keys, trace, errors, counters) | Nouns in a schema, verbs as tools. Replaces query_tickets / query_assets / … |
Resources are addressable and pinnable — clients can subscribe and refresh. Tools are for agent loops.
| URI | What it returns | Same gate as |
|---|---|---|
ticket://TCK-1001 | One ticket by id | run_query |
tickets://open | Live open ticket list (top 25) | run_query |
schema://tickets | Query schema shape (also customers, assets) | get_schema |
Call resources/list to browse — you do not need to know a URI ahead of time. A denied read is a JSON-RPC error (not a fake ticket document you can pin).
User-facing prompts — the user picks these, the model executes them.
| Prompt | Lesson it teaches |
|---|---|
search-open-tickets | Find service-account scars in the live data |
| attribution-scar | Create without requester_email → explain
앞부분만 보여 드려요. 나머지는 저장소에서 읽어 보세요