SkillAgentSearch skills...

hammer-mcp

MCP server for Source-engine map work: read and lint VMF, edit without reformatting, measure BSP against format limits, compile under Wine (stock or Hammer++)

Install / Use

claude mcp add ProjectSocietyStudio -- npx -y github:ProjectSocietyStudio/hammer-mcp

If the server publishes to npm under a different name, use that package instead โ€” check the repo README.

About this skill
๐Ÿ”Œ

MCP Server

Model Context Protocol server

Quality Score

75/100

Supported Platforms

Claude Code
Claude Desktop

Our assessment of hammer-mcp

hammer-mcp scores 75/100 on our quality scale, 3678th of 4,575 Development & Engineering skills we index.

Its MCP Server is 40 KB long, well organised into 23 sections with 7 code examples: long enough that it reads more like full documentation than a focused instruction file, which agents can find harder to follow.

It has 10 GitHub stars, so there is little community track record yet; judge it on its content.

Substance
21/30
Structure
20/20
Description
15/15
Adoption
4/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated about 2 months ago, so hammer-mcp is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 97/100, with no cautions. These come from repository metadata, not a code audit โ€” read the skill file before letting an agent act on it.

hammer-mcp compared with similar skills

All 4 of these similar skills score higher than hammer-mcp; compare them before choosing.

SkillScoreStarsUpdatedFormat
hammer-mcp (this skill)by ProjectSocietyStudio751053d agoMCP Server
Agent-Reachby Panniantong10093.6ktodayCLAUDE.md
headroomby headroomlabs-ai10074.6ktodayCLAUDE.md
CowAgentby zhayujie10047.3ktodayCLAUDE.md
ai-job-searchby MadsLorentzen10045.2k2d agoCLAUDE.md

Frequently asked questions

How do I install hammer-mcp?
Run claude mcp add ProjectSocietyStudio -- npx -y github:ProjectSocietyStudio/hammer-mcp. The install tabs above show the steps for each supported agent.
Which AI agents does hammer-mcp work with?
It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
Is hammer-mcp safe to use?
It is MIT-licensed and scores 97/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is hammer-mcp still maintained?
The repository was last updated about 2 months ago, so hammer-mcp is actively maintained.

hammer-mcp

CI License: MIT

An MCP server for Source-engine map work. It reads .vmf and .bsp files, lints a map against the game's own FGD, edits a .vmf without reformatting it, patches a compiled map's entities without recompiling, drives the compilers under Wine โ€” Hammer++ by default, stock on demand or as a fallback โ€” and measures a map against the limits of the format.

It never talks to a running engine. It reads and writes files and runs compilers, and nothing else. That is what lets it hold no lock and sit beside a live server without disturbing it.

> read_map_geometry rp_nycity_day.bsp

  a 1.13 GB map โ€” header and lump directory only, 1 ms

  MODELS       1218 /  1024   119%  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–  over
  TEXINFO     11841 / 12288    96%  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‹
  VERTEXES    62270 / 65536    95%  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–Œ
  BRUSHES      6913 /  8192    84%  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–

  4 lumps at or past 80% of their ceiling.

  MODELS is past it outright โ€” and this map loads every day. That is
  not a broken map: it is evidence that the compilers which built it
  raise that ceiling. The tool reports it in those terms, rather than
  an error it cannot substantiate.

Measured on 11/08/2026. The tool returns JSON; the bars are this README's rendering of it. Every number above is in that JSON, and docs/measuring.md says what corroborates each one.

What it does

flowchart LR
  VMF[".vmf"] --> LINT["read_vmf_lint<br/>against the game's FGD"]
  LINT --> EDIT["edit_vmf<br/>splice, never reserialise"]
  EDIT --> VMF
  LINT --> C["vbsp ยท vvis ยท vrad<br/>under Wine"]
  C --> BSP[".bsp"]
  BSP --> M["measure ยท pack ยท patch entities"]
  M -. never .-x ENG["a running engine"]
  style ENG stroke-dasharray: 4 4

| | | |---|---| | Measure | how full each lump is, world extents, prop inventory, packed assets, sightlines | | Judge | the same measurements against a budget profile, as a verdict per criterion โ€” so a caller knows when it is done, not just where it stands | | Read and lint | entities, outputs and brush counts of a .vmf; every finding checked against the FGD the game itself declares | | Edit | entities, keyvalues and outputs of a .vmf, by splicing byte ranges โ€” untouched bytes stay untouched | | Build | brushes from a shape description, wound and textured the way vbsp expects, refused unless they close | | Optimise | func_detail, hint brushes including diagonal ones, per-face lightmap scale โ€” the decisions a compiled map no longer contains | | Compile | vbsp/vvis/vrad under Wine, findings per stage, and a leak turned into a named entity | | Ship | resolve every asset a map references and find what will be missing, pack them into a .bsp โ€” by hand or derived from the map โ€” check a nav mesh still matches | | Open | a Workshop .gma: read its index, pull one map out of a gigabyte without unpacking the rest | | Patch without recompiling | rewrite a compiled map's entity list through a .lmp |

Knowing when you are done

Every reader above answers how much. None of them answers is that enough โ€” so anything driving this toolchain can measure a map forever without learning that it is finished. read_map_report closes that: it runs the readers and judges them against a budget profile.

> read_map_report rp_nycity_day.bsp --profile source-stock

  FAIL   19 pass ยท 3 warn ยท 3 fail ยท 1 skipped

  fail   MODELS            119%   past MAX_MAP_MODELS
  fail   LIGHTING          264%   42.29 MiB of a 16 MiB ceiling
  fail   edicts            174%   3555 entities against MAX_EDICTS (2048)
  skip   luxel-density      --    nothing calibrates a threshold for this

Measured on 11/08/2026. The LIGHTING line is the one that was not already known: this map carries 42.29 MiB of lightmap data against MAX_MAP_LIGHTING's 16 MiB, and it holds no HDR at all (lumps 53, 54 and 58 are empty), so that is LDR alone. It is a second stock ceiling exceeded, in a lump entirely independent of the first โ€” which corroborates the MODELS reading rather than repeating it.

Two things this design refuses to do:

  • It never restates a limit. Ceilings live once, in src/bsp/geometry.ts and in LIMITS, read from Valve's headers with a date. A profile carries thresholds โ€” policy โ€” and every one of them states its own provenance, including "we chose it".
  • It never invents a threshold to fill a row. luxel-density is measurable and uncalibrated, so it reports skipped and says so. A confident verdict about nothing is worse than an admitted gap, and the same goes for the overall verdict: a run that judged nothing comes back skipped, never pass.

Building brushes, and why that was refused until now

edit_vmf used to say it outright: creating a brush means choosing planes and texture axes, and a tool that does that without an oracle produces maps that compile and are wrong. The argument was right. What changed is that the oracles exist now, so the conclusion expired rather than the reasoning.

write_vmf_solid takes a shape โ€” box, wedge for a ramp, cylinder for an n-sided prism, or convex for a hull given face by face โ€” and two things it gets right by construction rather than by care:

  • Winding. Every face is wound against the solid's own centroid, so a normal that points inward is turned around before it is written. A new shape cannot introduce a winding bug.
  • Texture axes. Not invented: vbsp's own base-axis table. All six of its branches are reproduced exactly by gen_probe.py, which was written by hand and has been through a real compile and a real boot. So a ramp does not reach a seventh entry โ€” there is no seventh. What it exercises is the selection: picking the closest base for a normal that matches none of them exactly. That step is Valve's algorithm rather than an extrapolation, and it is the part still owed a compile.

Nothing is written until the result has been read back by read_vmf_solids and passed. The writer goes volume โ†’ planes and the checker goes planes โ†’ volume, so neither hides the other's sign error, and a solid that does not close is refused rather than reported.

And because two programs written on the same afternoon agreeing proves less than it looks: a six-brush room built entirely by this tool is compiled by vbsp for real, and seals. Remove one wall and it leaks. Without that second half, a writer that emitted nothing at all would pass the first test just as happily.

The checkerboard, before a player finds it

A missing asset is the only failure on this page a mapper never sees at home โ€” they have the files. read_map_dependencies resolves every asset a compiled map references and says where each will come from: packed inside the map, found in the game's own content, or missing.

The walk is recursive because a one-level walk gives a short, plausible, wrong answer. It follows VMT patch and include chains, $bottommaterial and $fallbackmaterial, a model's own material list, the skybox's six sides, and the detail sprite config.

On the production map โ€” 11/08/2026:

  10 520 assets resolved   (10 493 packed ยท 27 from the game)
       5 faults

  nodegraph-name-mismatch   maps/graphs/rp_nyc1ty_day.ain
  texture ร—4                referenced by model materials, present nowhere

That first line is a real defect in a map that has shipped and runs daily: the packed nodegraph is rp_nyc1ty_day.ain, with a digit 1 where an i belongs. The engine loads maps/graphs/<mapname>.ain, will never find it, and the NPCs navigate without it. Nothing warns about this at compile time, because nothing checks that a packed file's name matches the map it was packed into.

โš ๏ธ "Unreferenced" is not "safe to delete", and the tool refuses to blur the two. The same map packs 4261 files the engine references and no file names:

  • 3983 .vhv โ€” vrad's per-prop vertex lighting. Delete these and every static prop in the map goes flat.
  • the built cubemaps under materials/maps/<mapname>/.
  • everything the engine finds by naming convention rather than by reference: the skybox's six sides derived from skyname, the detail sprite material and its .vbsp config, maps/<mapname>.nav, maps/graphs/<mapname>.ain, the level sounds list.

That last group is the same mechanism that let the misspelled .ain ship: a file the engine locates by deriving its name is invisible to a dependency walk and to the compiler. Getting it right in both directions matters โ€” miss it and the tool reports a dozen essential files as dead weight.

Counted separately again: the 251 files under sound/, scripts/ and particles/, which this walk does not follow. A soundscape is named by a string defined in a manifest, and info_particle_system names an effect, not a file.

What is left โ€” 254 on that map โ€” is the only number that means anything, and it is still not a delete list.

And where in the game it was found matters as much as whether. An asset inside a VPK is base content: every player who owns that game has it. An asset sitting loose in the content tree usually is not โ€” it resolves at home because it is on that disk, and it is a checkerboard for everyone else.

run_pack with auto: true packs exactly those, deriving the list from the map and returning it so what was packed is visible rather than inferred. It never packs VPK content.

โš ๏ธ Loose is a candidate, not a certainty, and that is measured rather than assumed: Garry's Mod ships detail.vbsp loose in its own root. No rule separates a mapper's work from a game's loose files โ€” they live under the same install. The asymmetry is what makes erring toward inclusion right: packing a stock file wastes kilobytes, missing a custom one ships a broken map. exclude drops the ones you recognise.

Opening a Workshop archive

A .gma is how the Workshop ships everything, maps included, so until now a Workshop map had to be unpacked by hand before anything here could look at it โ€” which meant the corpus a mapper learns from was out of reach.

The format concatenates every file after an index with no padding, so one pass over the index gives random access to the whole archive. run_gma_extract pulls maps/rp_pinescity_v2b.bsp out of a 245 MB addon without reading the materials beside it.

Read across every archive on this machine, 11/08/2026: 56 archives, no failures โ€” the largest 1143 MB, the busiest 6521 entries, seven of them carrying a map. Header and index only.

Where the lighting budget goes

lightmapscale is units per luxel, so it reads backwards: smaller is finer and more expensive, and the cost is an area. The probe room, compiled at four scales โ€” 11/08/2026:

| scale | luxels | LIGHTING | |---|---|---| | 8 | 17 424 | 69 760 B | | 16 (Hammer's default) | 4 624 | 18 560 B | | 32 | 1 296 | 5 248 B | | 64 | 400 | 1 664 B |

Each doubling divides the bill by roughly four. That arithmetic is why the production map audited here carries 264% of MAX_MAP_LIGHTING โ€” nobody arrives there by choosing a fine lightmap once, but by never coarsening the surfaces that did not need one. A warehouse floor at 16 and the same floor at 32 are indistinguishable to a player and differ fourfold on disk.

set_lightmap_scale selects by solid, material, which way a face points, minimum area, or a combination, and projects the luxel count before writing. It refuses to touch every face in the map unless told all: true โ€” rescaling a whole map is legitimate and is never what someone meant by accident.

โš ๏ธ It also warns about the cost that does not look like one. A brush face may carry at most **32 luxels along either t

Truncated for display โ€” read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars10
CategoryDevelopment
Updated1mo ago
Forks2

Languages

TypeScript

Trust signals

97/100

From repository metadata: license, adoption, age and documentation. Not a code audit โ€” see the Safety scan above for what the skill file itself contains.

1 info
hammer-mcp โ€” MCP Server: Install & Safety Check | SkillAgent