Tank Fight MCP

Tank Fight MCP

Serves the canonical Tank Fight specification, enabling clients to query game parameters, maze layouts, and rules via MCP tools.

Category
访问服务器

README

Tank Fight MCP — the game spec as a service

An MCP server that serves the canonical specification for Tank Fight: field and window size, tank and bullet stats, spawn rules, scoring, controls, menu behaviour, AI strategies, the difficulty ramp, and a destructible maze per level.

It runs as a local service on a port. Any MCP client can connect, ask what tools it offers, and query the specification — while building the game in Java, in TypeScript, or in anything else.

What it's for

Two jobs, and the second matters more than it first looks.

1. Keep independent implementations in agreement. Two builds of the same game, written separately, drift the moment they need a number nobody wrote down. Both asking the same service how big a tank is removes the guesswork.

2. Stop the model inventing requirements. Every detail a spec leaves out is a place where an AI coding assistant quietly picks something plausible and moves on — do bullets stop at walls? can allies shoot each other? what happens when a player is destroyed mid-round? It rarely mentions that it decided. Each of those is answered here, so the question becomes a lookup instead of a guess, and open_questions names what genuinely isn't decided, so the honest answer is "ask a human" rather than a confident invention.

Run it

Requires uv.

uv sync
uv run server.py

That serves the specification at http://127.0.0.1:8082/mcp. Use --port to listen elsewhere, --host to bind another interface, and --stdio for clients that only speak stdio.

Connect a client

Any MCP client, any number of them at once. For Claude Code:

claude mcp add --transport http tank-spec http://localhost:8082/mcp

Add --scope project to record it in the repository you're building in, so everyone working on that build gets the same specification. Then /mcp to confirm the connection, and the client can ask the server what tools exist and how to call them — nothing here needs configuring per client.

Tools

Tool Answers
list_sections() What's in the spec, one line each — start here
get_spec(section) One section, or a dotted path like entities.bullet.damage
search_spec(query) "Does X happen?" — finds the rule that decides it
resolve_level(level) What level N means: total enemies, max concurrent, spawn interval, which maze
get_maze(level) That level's brick layout, expanded into tiles, with an ASCII picture
open_questions() What the spec deliberately hasn't decided

What this server deliberately does not do

It has no idea who is connected or what they are building, and that is on purpose. It knows about the specification; clients know about the server. Nothing points the other way.

So checking whether an implementation still matches the spec is the client's job. A client can read the values out of its own code and compare them against what these tools return — it is sitting in that repository and the server is not. A server that reached into a checkout to inspect it would have to know the language, the file layout and the path, and would need updating every time another implementation appeared.

The same reasoning is why the spec is served rather than shipped as a file:

  • It's outside every implementation. A session working in one repository can't read another's files, but it can call a service.
  • It's queried, not dumped. search_spec("friendly fire") returns one rule. Loading the whole specification into a model's context to answer one question is exactly the waste this avoids.
  • Some answers are computed, not stored. Levels are generated from a ramp formula — level 6 exists in no file. resolve_level is the only correct way to ask, and its integer truncation is load-bearing: a floating-point version disagrees at four of the eight levels.

Destructible brick and per-level mazes

Everything inside the border is brick, and brick can be shot away — by both sides, since sides matter for tanks and never for walls. A tile is 20x20 and takes 40 damage, so two standard bullets open a hole that tanks then drive through. The border itself is immune.

Each level has its own maze, so the level number is the only difficulty knob: it sets how many enemies arrive, how fast, and the terrain they arrive into. Level 1 is nearly open; level 8 is dense enough that shooting a path is usually faster than finding one.

get_maze(level) returns the rectangles, the expanded tile list, and a picture:

########################################
#EE................EE................EE#
#EE................EE................EE#
#......................................#
#......BBBBBBBBBBB....BBBBBBBBBBB......#
...
#.............AA...AA...AA.............#
########################################

Use the expanded tiles rather than expanding the rectangles yourself — that step, and the rule for which tile a bullet damages when it straddles two, are where two builds most easily end up digging different holes from the same shots.

Adding a maze is just adding rectangles under mazes.levels in the YAML. The test suite then holds it to the invariants that make a level playable: tile-aligned, inside the area, non-overlapping, spawn and ally boxes clear, and every entry point reachable on foot without destroying anything — digging is a shortcut, never a requirement.

Editing the spec

spec/game-spec.yaml is the whole thing, and it's meant to be edited by hand — that's the point. The server re-reads it on every call, so a change takes effect immediately without restarting anything.

The specification was seeded from a working implementation and is independent of it from that point on. It leads: change a value here first, then make the implementations follow.

Tests

uv run pytest

tests/test_spec.py pins the spec's values and holds every maze to the playability invariants. tests/test_server.py drives the server through an MCP client — discover the tools, read their descriptions, call them. tests/test_http.py starts the real process on a port and connects to it over HTTP, the way a client does.

Layout

spec/game-spec.yaml   the specification — the actual source of truth
server.py             MCP server: tool definitions, their descriptions, and the transport
tank_spec/spec.py     loading, searching, level maths, maze expansion
tests/                spec and maze invariants, MCP integration, HTTP transport

推荐服务器

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 模型以安全和受控的方式获取实时的网络信息。

官方
精选