{
  "markdown": "# helldivers2-mcp\n\nA stateless [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that exposes live **Helldivers 2** galactic war data to LLMs.\n\nData is sourced from the community API at [api.helldivers2.dev](https://api.helldivers2.dev).\n\n---\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| `get_war_status` | Galaxy-wide war statistics (kills by faction, missions won/lost, accuracy, deaths, impact multiplier) and active planets with owner, player count, active events, attack vectors, and region health |\n| `get_assignments` | Active Major Orders with title, briefing, decoded task list (faction, difficulty, target planet), current progress numbers, reward type and amount, and time until expiry |\n| `get_all_planets` | Full planet list with IDs, names, and sectors |\n| `get_planet_details` | Detailed per-planet info: biome, hazards, initial/current owner, health, waypoints, active events, full combat statistics, attacking planets, and regions (up to 5 planets per call) |\n| `get_dispatches` | In-game dispatch feed — High Command broadcasts with published date (relative time) and message text; optional `limit` parameter (default 20, max 50) |\n| `get_steam_news` | Steam news for Helldivers 2 with title, URL, publish date (relative time), and full article content; optional `limit` parameter (default 10, max 30) |\n| `get_space_station_details` | DSS details: current host planet (full planet info), time until next election, and active tactical actions with name, description, status, planet effects, and resource costs |\n\n---\n\n## Quickstart\n\n### Prerequisites\n\n- Node.js 22+ or Docker\n- A contact email for the `X-Super-Contact` header (required by the upstream API)\n\n### Local dev\n\n```bash\ncp .env.example .env   # set X_SUPER_CONTACT=your@email.com\nnpm install\nnpm run dev               # hot-reload via tsx watch on :3000\n```\n\n### Production build\n\n```bash\nnpm run build   # tsc → dist/\nnpm run start\n```\n\n### Docker\n\nImage is available on [Docker Hub](https://hub.docker.com/r/xerno42/helldivers2-mcp).\n\n```bash\ndocker pull xerno42/helldivers2-mcp # pull from Docker Hub\n# or\ndocker build -t helldivers2-mcp . # build locally\n\n#then run with:\ndocker run -p 3000:3000 -e X_SUPER_CONTACT=your@email.com helldivers2-mcp\n```\n\n---\n\n## Configuration\n\nAll configuration is via environment variables.\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `X_SUPER_CONTACT` | *(required)* | Forwarded as `X-Super-Contact` to the upstream API per their usage guidelines |\n| `PORT` | `3000` | HTTP port to listen on |\n| `BIND_HOST` | `127.0.0.1` | Interface to bind (`0.0.0.0` for Docker/containers) |\n| `MCP_ALLOWED_ORIGINS` | *(unset)* | Comma-separated list of allowed browser `Origin` headers. Unset means browser-originated requests are blocked; server-to-server calls (no `Origin` header) are always allowed |\n| `MCP_RATE_LIMIT_PER_MIN` | `60` | Sustained request rate limit (requests per minute) |\n| `MCP_RATE_LIMIT_BURST` | `= MCP_RATE_LIMIT_PER_MIN` | Burst capacity for the token-bucket rate limiter |\n\n---\n\n## Endpoints\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `POST` | `/mcp` | MCP Streamable HTTP transport endpoint |\n| `GET` | `/health` | Liveness check — returns `{ \"ok\": true }` |\n\nThe server uses the **stateless** Streamable HTTP transport. Each `POST /mcp` request creates a fresh `McpServer` + transport pair, handles the request, then tears them down. There is no session state.\n\n---\n\n## Usage in Code\n\nCall the MCP server directly over HTTP using the Streamable HTTP transport. Each request is a JSON-RPC `tools/call` message sent to `POST /mcp`.\n\n### JavaScript / TypeScript\n\nUsing the official [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk):\n\n```typescript\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\nconst client = new Client({ name: \"my-app\", version: \"1.0.0\" });\n\nconst transport = new StreamableHTTPClientTransport(\n  new URL(\"https://mcp.avengersofsuperearth.com/mcp\")\n);\n\nawait client.connect(transport);\n\n// List available tools\nconst { tools } = await client.listTools();\nconsole.log(tools.map((t) => t.name));\n\n// Get current war status\nconst warStatus = await client.callTool({\n  name: \"get_war_status\",\n  arguments: {},\n});\nconsole.log(warStatus.content[0].text);\n\n// Get details for specific planets by index (up to 5)\nconst planets = await client.callTool({\n  name: \"get_planet_details\",\n  arguments: { planetindices: [57, 153] },\n});\nconsole.log(planets.content[0].text);\n\nawait client.close();\n```\n\nWithout the SDK — raw JSON-RPC over `fetch`:\n\n```typescript\nasync function callTool(name: string, args: Record<string, unknown> = {}) {\n  const res = await fetch(\"https://mcp.avengersofsuperearth.com/mcp\", {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      \"Accept\": \"application/json, text/event-stream\",\n    },\n    body: JSON.stringify({\n      jsonrpc: \"2.0\",\n      id: 1,\n      method: \"tools/call\",\n      params: { name, arguments: args },\n    }),\n  });\n  const text = await res.text();\n  // The response is an SSE frame (\"event: message\\ndata: {json}\\n\\n\");\n  // concatenate its data line(s) to recover the JSON-RPC payload.\n  const json = text\n    .split(\"\\n\")\n    .filter((line) => line.startsWith(\"data:\"))\n    .map((line) => line.slice(5).trim())\n    .join(\"\");\n  const data = JSON.parse(json);\n  return data.result.content[0].text;\n}\n\nconst status = await callTool(\"get_war_status\");\nconst assignments = await callTool(\"get_assignments\");\nconst dispatches = await callTool(\"get_dispatches\", { limit: 5 });\nconst planets = await callTool(\"get_planet_details\", { planetindices: [57, 153] });\n```\n\n### Python\n\nUsing the official [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk):\n\n```python\nimport asyncio\nfrom mcp import ClientSession\nfrom mcp.client.streamable_http import streamablehttp_client\n\nasync def main():\n    async with streamablehttp_client(\"https://mcp.avengersofsuperearth.com/mcp\") as (read, write, _):\n        async with ClientSession(read, write) as session:\n            await session.initialize()\n\n            # List available tools\n            tools = await session.list_tools()\n            print([t.name for t in tools.tools])\n\n            # Get current war status\n            result = await session.call_tool(\"get_war_status\", {})\n            print(result.content[0].text)\n\n            # Get details for specific planets by index (up to 5)\n            result = await session.call_tool(\n                \"get_planet_details\",\n                {\"planetindices\": [57, 153]},\n            )\n            print(result.content[0].text)\n\nasyncio.run(main())\n```\n\nWithout the SDK — raw JSON-RPC over `httpx`:\n\n```python\nimport httpx\n\nMCP_URL = \"https://mcp.avengersofsuperearth.com/mcp\"\n\ndef call_tool(name: str, arguments: dict = {}) -> str:\n    payload = {\n        \"jsonrpc\": \"2.0\",\n        \"id\": 1,\n        \"method\": \"tools/call\",\n        \"params\": {\"name\": name, \"arguments\": arguments},\n    }\n    headers = {\n        \"Content-Type\": \"application/json\",\n        \"Accept\": \"application/json, text/event-stream\",\n    }\n    response = httpx.post(MCP_URL, json=payload, headers=headers)\n    response.raise_for_status()\n    import json\n    # The response is an SSE frame (\"event: message\\ndata: {json}\\n\\n\");\n    # concatenate its data line(s) to recover the JSON-RPC payload.\n    text = \"\".join(\n        line[5:].strip()\n        for line in response.text.splitlines()\n        if line.startswith(\"data:\")\n    )\n    return json.loads(text)[\"result\"][\"content\"][0][\"text\"]\n\nstatus = call_tool(\"get_war_status\")\nassignments = call_tool(\"get_assignments\")\nplanets = call_tool(\"get_planet_details\", {\"planetindices\": [57, 153]})\n```\n\n---\n\n## Connecting to Claude Desktop\n\n### Hosted server (easiest)\n\nA public instance is available at `https://mcp.avengersofsuperearth.com/mcp`. No setup required — just add it to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"helldivers2\": {\n      \"url\": \"https://mcp.avengersofsuperearth.com/mcp\"\n    }\n  }\n}\n```\n\n### Self-hosted (local binary)\n\n```json\n{\n  \"mcpServers\": {\n    \"helldivers2\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/to/helldivers2-mcp/dist/index.js\"],\n      \"env\": {\n        \"X_SUPER_CONTACT\": \"your@email.com\"\n      }\n    }\n  }\n}\n```\n\n### Self-hosted (HTTP server)\n\n```json\n{\n  \"mcpServers\": {\n    \"helldivers2\": {\n      \"url\": \"http://localhost:3000/mcp\"\n    }\n  }\n}\n```\n\n---\n\n## Development\n\n```bash\nnpm run test              # Jest (ESM mode)\nnpm run test:watch\nnpm run test:coverage\nnpm run lint              # ESLint\n```\n\nRun a single test file:\n\n```bash\nnpm run test src/__tests__/tools.war.test.ts\n```\n\n### Adding a tool\n\n1. Create `src/tools/your-tool.ts` and export a `Tool` object with `.definition` and `.handler`.\n2. Import it and add it to the `TOOLS` array in [src/index.ts](src/index.ts).\n3. Return `textResponse(...)` on success or `errorResponse(...)` on failure — never throw from a handler.\n4. All upstream calls must go through `hd2Fetch` (in-memory 2-minute cache + rate-limit-aware queue).\n\n---\n\n## License\n\n[MIT](LICENSE)\n",
  "bytes": 9272,
  "sha": "c78a2c05dbbeaa6e512bf57f5c474f1ffde8e3d948ecd0783e4e606294c7f7c5",
  "repo_slug": "xerno42/helldivers2-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_xerno42_helldivers2_mcp_e5803496/readme"
}