hoi4-agent-tools 0.0.0-bootstrap.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/LICENSE +201 -0
- package/README.md +140 -2
- package/SECURITY.md +17 -0
- package/dist/bin/http.d.ts +3 -0
- package/dist/bin/http.d.ts.map +1 -0
- package/dist/bin/http.js +27 -0
- package/dist/bin/http.js.map +1 -0
- package/dist/bin/setup.d.ts +3 -0
- package/dist/bin/setup.d.ts.map +1 -0
- package/dist/bin/setup.js +188 -0
- package/dist/bin/setup.js.map +1 -0
- package/dist/bin/stdio.d.ts +3 -0
- package/dist/bin/stdio.d.ts.map +1 -0
- package/dist/bin/stdio.js +36 -0
- package/dist/bin/stdio.js.map +1 -0
- package/dist/hoi4_agent_tools/core/artifacts.d.ts +117 -0
- package/dist/hoi4_agent_tools/core/artifacts.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/artifacts.js +1047 -0
- package/dist/hoi4_agent_tools/core/artifacts.js.map +1 -0
- package/dist/hoi4_agent_tools/core/canonical.d.ts +13 -0
- package/dist/hoi4_agent_tools/core/canonical.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/canonical.js +41 -0
- package/dist/hoi4_agent_tools/core/canonical.js.map +1 -0
- package/dist/hoi4_agent_tools/core/configuration.d.ts +137 -0
- package/dist/hoi4_agent_tools/core/configuration.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/configuration.js +383 -0
- package/dist/hoi4_agent_tools/core/configuration.js.map +1 -0
- package/dist/hoi4_agent_tools/core/diagnostic-collector.d.ts +18 -0
- package/dist/hoi4_agent_tools/core/diagnostic-collector.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/diagnostic-collector.js +45 -0
- package/dist/hoi4_agent_tools/core/diagnostic-collector.js.map +1 -0
- package/dist/hoi4_agent_tools/core/diagnostics.d.ts +26 -0
- package/dist/hoi4_agent_tools/core/diagnostics.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/diagnostics.js +25 -0
- package/dist/hoi4_agent_tools/core/diagnostics.js.map +1 -0
- package/dist/hoi4_agent_tools/core/diff.d.ts +22 -0
- package/dist/hoi4_agent_tools/core/diff.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/diff.js +93 -0
- package/dist/hoi4_agent_tools/core/diff.js.map +1 -0
- package/dist/hoi4_agent_tools/core/engine.d.ts +56 -0
- package/dist/hoi4_agent_tools/core/engine.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/engine.js +319 -0
- package/dist/hoi4_agent_tools/core/engine.js.map +1 -0
- package/dist/hoi4_agent_tools/core/image-diff.d.ts +14 -0
- package/dist/hoi4_agent_tools/core/image-diff.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/image-diff.js +121 -0
- package/dist/hoi4_agent_tools/core/image-diff.js.map +1 -0
- package/dist/hoi4_agent_tools/core/index.d.ts +64 -0
- package/dist/hoi4_agent_tools/core/index.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/index.js +963 -0
- package/dist/hoi4_agent_tools/core/index.js.map +1 -0
- package/dist/hoi4_agent_tools/core/index.public.d.ts +16 -0
- package/dist/hoi4_agent_tools/core/index.public.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/index.public.js +16 -0
- package/dist/hoi4_agent_tools/core/index.public.js.map +1 -0
- package/dist/hoi4_agent_tools/core/render-budget.d.ts +51 -0
- package/dist/hoi4_agent_tools/core/render-budget.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/render-budget.js +109 -0
- package/dist/hoi4_agent_tools/core/render-budget.js.map +1 -0
- package/dist/hoi4_agent_tools/core/result.d.ts +45 -0
- package/dist/hoi4_agent_tools/core/result.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/result.js +26 -0
- package/dist/hoi4_agent_tools/core/result.js.map +1 -0
- package/dist/hoi4_agent_tools/core/scanner.d.ts +28 -0
- package/dist/hoi4_agent_tools/core/scanner.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/scanner.js +136 -0
- package/dist/hoi4_agent_tools/core/scanner.js.map +1 -0
- package/dist/hoi4_agent_tools/core/server-state.d.ts +31 -0
- package/dist/hoi4_agent_tools/core/server-state.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/server-state.js +413 -0
- package/dist/hoi4_agent_tools/core/server-state.js.map +1 -0
- package/dist/hoi4_agent_tools/core/source/encoding.d.ts +10 -0
- package/dist/hoi4_agent_tools/core/source/encoding.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/source/encoding.js +54 -0
- package/dist/hoi4_agent_tools/core/source/encoding.js.map +1 -0
- package/dist/hoi4_agent_tools/core/source/index.d.ts +7 -0
- package/dist/hoi4_agent_tools/core/source/index.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/source/index.js +7 -0
- package/dist/hoi4_agent_tools/core/source/index.js.map +1 -0
- package/dist/hoi4_agent_tools/core/source/lexer.d.ts +30 -0
- package/dist/hoi4_agent_tools/core/source/lexer.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/source/lexer.js +266 -0
- package/dist/hoi4_agent_tools/core/source/lexer.js.map +1 -0
- package/dist/hoi4_agent_tools/core/source/limits.d.ts +21 -0
- package/dist/hoi4_agent_tools/core/source/limits.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/source/limits.js +49 -0
- package/dist/hoi4_agent_tools/core/source/limits.js.map +1 -0
- package/dist/hoi4_agent_tools/core/source/localisation.d.ts +20 -0
- package/dist/hoi4_agent_tools/core/source/localisation.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/source/localisation.js +163 -0
- package/dist/hoi4_agent_tools/core/source/localisation.js.map +1 -0
- package/dist/hoi4_agent_tools/core/source/parser.d.ts +44 -0
- package/dist/hoi4_agent_tools/core/source/parser.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/source/parser.js +334 -0
- package/dist/hoi4_agent_tools/core/source/parser.js.map +1 -0
- package/dist/hoi4_agent_tools/core/source/rewrite.d.ts +10 -0
- package/dist/hoi4_agent_tools/core/source/rewrite.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/source/rewrite.js +28 -0
- package/dist/hoi4_agent_tools/core/source/rewrite.js.map +1 -0
- package/dist/hoi4_agent_tools/core/svg-text.d.ts +34 -0
- package/dist/hoi4_agent_tools/core/svg-text.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/svg-text.js +127 -0
- package/dist/hoi4_agent_tools/core/svg-text.js.map +1 -0
- package/dist/hoi4_agent_tools/core/transaction-limits.d.ts +9 -0
- package/dist/hoi4_agent_tools/core/transaction-limits.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/transaction-limits.js +9 -0
- package/dist/hoi4_agent_tools/core/transaction-limits.js.map +1 -0
- package/dist/hoi4_agent_tools/core/transactions.d.ts +162 -0
- package/dist/hoi4_agent_tools/core/transactions.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/transactions.js +1181 -0
- package/dist/hoi4_agent_tools/core/transactions.js.map +1 -0
- package/dist/hoi4_agent_tools/core/workspace.d.ts +68 -0
- package/dist/hoi4_agent_tools/core/workspace.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/core/workspace.js +794 -0
- package/dist/hoi4_agent_tools/core/workspace.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/compiler.d.ts +9 -0
- package/dist/hoi4_agent_tools/focus/compiler.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/compiler.js +273 -0
- package/dist/hoi4_agent_tools/focus/compiler.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/continuous-render.d.ts +32 -0
- package/dist/hoi4_agent_tools/focus/continuous-render.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/continuous-render.js +179 -0
- package/dist/hoi4_agent_tools/focus/continuous-render.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/drift.d.ts +22 -0
- package/dist/hoi4_agent_tools/focus/drift.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/drift.js +124 -0
- package/dist/hoi4_agent_tools/focus/drift.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/geometry.d.ts +17 -0
- package/dist/hoi4_agent_tools/focus/geometry.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/geometry.js +35 -0
- package/dist/hoi4_agent_tools/focus/geometry.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/importer.d.ts +9 -0
- package/dist/hoi4_agent_tools/focus/importer.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/importer.js +732 -0
- package/dist/hoi4_agent_tools/focus/importer.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/index.d.ts +14 -0
- package/dist/hoi4_agent_tools/focus/index.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/index.js +14 -0
- package/dist/hoi4_agent_tools/focus/index.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/layout.d.ts +5 -0
- package/dist/hoi4_agent_tools/focus/layout.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/layout.js +653 -0
- package/dist/hoi4_agent_tools/focus/layout.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/limits.d.ts +9 -0
- package/dist/hoi4_agent_tools/focus/limits.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/limits.js +9 -0
- package/dist/hoi4_agent_tools/focus/limits.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/lint.d.ts +14 -0
- package/dist/hoi4_agent_tools/focus/lint.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/lint.js +839 -0
- package/dist/hoi4_agent_tools/focus/lint.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/model.d.ts +303 -0
- package/dist/hoi4_agent_tools/focus/model.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/model.js +20 -0
- package/dist/hoi4_agent_tools/focus/model.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/native-effects.d.ts +9 -0
- package/dist/hoi4_agent_tools/focus/native-effects.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/native-effects.js +563 -0
- package/dist/hoi4_agent_tools/focus/native-effects.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/planning.d.ts +15 -0
- package/dist/hoi4_agent_tools/focus/planning.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/planning.js +241 -0
- package/dist/hoi4_agent_tools/focus/planning.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/presentation.d.ts +24 -0
- package/dist/hoi4_agent_tools/focus/presentation.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/presentation.js +204 -0
- package/dist/hoi4_agent_tools/focus/presentation.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/render.d.ts +35 -0
- package/dist/hoi4_agent_tools/focus/render.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/render.js +491 -0
- package/dist/hoi4_agent_tools/focus/render.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/service.d.ts +82 -0
- package/dist/hoi4_agent_tools/focus/service.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/service.js +492 -0
- package/dist/hoi4_agent_tools/focus/service.js.map +1 -0
- package/dist/hoi4_agent_tools/focus/source-update.d.ts +6 -0
- package/dist/hoi4_agent_tools/focus/source-update.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/focus/source-update.js +328 -0
- package/dist/hoi4_agent_tools/focus/source-update.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/animation-manifest.d.ts +37 -0
- package/dist/hoi4_agent_tools/gui/animation-manifest.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/animation-manifest.js +66 -0
- package/dist/hoi4_agent_tools/gui/animation-manifest.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/assets.d.ts +71 -0
- package/dist/hoi4_agent_tools/gui/assets.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/assets.js +629 -0
- package/dist/hoi4_agent_tools/gui/assets.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/dds.d.ts +17 -0
- package/dist/hoi4_agent_tools/gui/dds.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/dds.js +245 -0
- package/dist/hoi4_agent_tools/gui/dds.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/helpers.d.ts +101 -0
- package/dist/hoi4_agent_tools/gui/helpers.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/helpers.js +1072 -0
- package/dist/hoi4_agent_tools/gui/helpers.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/index.d.ts +15 -0
- package/dist/hoi4_agent_tools/gui/index.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/index.js +15 -0
- package/dist/hoi4_agent_tools/gui/index.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/layout.d.ts +6 -0
- package/dist/hoi4_agent_tools/gui/layout.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/layout.js +753 -0
- package/dist/hoi4_agent_tools/gui/layout.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/limits.d.ts +25 -0
- package/dist/hoi4_agent_tools/gui/limits.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/limits.js +27 -0
- package/dist/hoi4_agent_tools/gui/limits.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/renderer.d.ts +18 -0
- package/dist/hoi4_agent_tools/gui/renderer.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/renderer.js +388 -0
- package/dist/hoi4_agent_tools/gui/renderer.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/scenario.d.ts +66 -0
- package/dist/hoi4_agent_tools/gui/scenario.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/scenario.js +191 -0
- package/dist/hoi4_agent_tools/gui/scenario.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/source-graph.d.ts +7 -0
- package/dist/hoi4_agent_tools/gui/source-graph.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/source-graph.js +1074 -0
- package/dist/hoi4_agent_tools/gui/source-graph.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/source-patch.d.ts +13 -0
- package/dist/hoi4_agent_tools/gui/source-patch.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/source-patch.js +90 -0
- package/dist/hoi4_agent_tools/gui/source-patch.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/studio.d.ts +86 -0
- package/dist/hoi4_agent_tools/gui/studio.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/studio.js +830 -0
- package/dist/hoi4_agent_tools/gui/studio.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/tga.d.ts +16 -0
- package/dist/hoi4_agent_tools/gui/tga.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/tga.js +157 -0
- package/dist/hoi4_agent_tools/gui/tga.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/types.d.ts +322 -0
- package/dist/hoi4_agent_tools/gui/types.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/types.js +19 -0
- package/dist/hoi4_agent_tools/gui/types.js.map +1 -0
- package/dist/hoi4_agent_tools/gui/validators.d.ts +8 -0
- package/dist/hoi4_agent_tools/gui/validators.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/gui/validators.js +951 -0
- package/dist/hoi4_agent_tools/gui/validators.js.map +1 -0
- package/dist/hoi4_agent_tools/map/bmp.d.ts +62 -0
- package/dist/hoi4_agent_tools/map/bmp.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/bmp.js +363 -0
- package/dist/hoi4_agent_tools/map/bmp.js.map +1 -0
- package/dist/hoi4_agent_tools/map/diagnostic-limit.d.ts +5 -0
- package/dist/hoi4_agent_tools/map/diagnostic-limit.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/diagnostic-limit.js +21 -0
- package/dist/hoi4_agent_tools/map/diagnostic-limit.js.map +1 -0
- package/dist/hoi4_agent_tools/map/index.d.ts +8 -0
- package/dist/hoi4_agent_tools/map/index.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/index.js +8 -0
- package/dist/hoi4_agent_tools/map/index.js.map +1 -0
- package/dist/hoi4_agent_tools/map/limits.d.ts +13 -0
- package/dist/hoi4_agent_tools/map/limits.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/limits.js +13 -0
- package/dist/hoi4_agent_tools/map/limits.js.map +1 -0
- package/dist/hoi4_agent_tools/map/model.d.ts +269 -0
- package/dist/hoi4_agent_tools/map/model.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/model.js +1114 -0
- package/dist/hoi4_agent_tools/map/model.js.map +1 -0
- package/dist/hoi4_agent_tools/map/operations.d.ts +401 -0
- package/dist/hoi4_agent_tools/map/operations.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/operations.js +2717 -0
- package/dist/hoi4_agent_tools/map/operations.js.map +1 -0
- package/dist/hoi4_agent_tools/map/render.d.ts +90 -0
- package/dist/hoi4_agent_tools/map/render.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/render.js +759 -0
- package/dist/hoi4_agent_tools/map/render.js.map +1 -0
- package/dist/hoi4_agent_tools/map/service.d.ts +81 -0
- package/dist/hoi4_agent_tools/map/service.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/service.js +695 -0
- package/dist/hoi4_agent_tools/map/service.js.map +1 -0
- package/dist/hoi4_agent_tools/map/validation.d.ts +23 -0
- package/dist/hoi4_agent_tools/map/validation.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/map/validation.js +1177 -0
- package/dist/hoi4_agent_tools/map/validation.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/prompts/register.d.ts +3 -0
- package/dist/hoi4_agent_tools/mcp/prompts/register.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/prompts/register.js +50 -0
- package/dist/hoi4_agent_tools/mcp/prompts/register.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/registry/metadata.d.ts +9 -0
- package/dist/hoi4_agent_tools/mcp/registry/metadata.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/registry/metadata.js +10 -0
- package/dist/hoi4_agent_tools/mcp/registry/metadata.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/resources/register.d.ts +5 -0
- package/dist/hoi4_agent_tools/mcp/resources/register.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/resources/register.js +278 -0
- package/dist/hoi4_agent_tools/mcp/resources/register.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/security/auth.d.ts +24 -0
- package/dist/hoi4_agent_tools/mcp/security/auth.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/security/auth.js +234 -0
- package/dist/hoi4_agent_tools/mcp/security/auth.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/base-tools.d.ts +35 -0
- package/dist/hoi4_agent_tools/mcp/server/base-tools.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/base-tools.js +835 -0
- package/dist/hoi4_agent_tools/mcp/server/base-tools.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/create.d.ts +5 -0
- package/dist/hoi4_agent_tools/mcp/server/create.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/create.js +26 -0
- package/dist/hoi4_agent_tools/mcp/server/create.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/output-schemas.d.ts +133 -0
- package/dist/hoi4_agent_tools/mcp/server/output-schemas.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/output-schemas.js +127 -0
- package/dist/hoi4_agent_tools/mcp/server/output-schemas.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/progress.d.ts +8 -0
- package/dist/hoi4_agent_tools/mcp/server/progress.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/progress.js +21 -0
- package/dist/hoi4_agent_tools/mcp/server/progress.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/result.d.ts +232 -0
- package/dist/hoi4_agent_tools/mcp/server/result.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/server/result.js +353 -0
- package/dist/hoi4_agent_tools/mcp/server/result.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/tools/focus.d.ts +5 -0
- package/dist/hoi4_agent_tools/mcp/tools/focus.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/tools/focus.js +1059 -0
- package/dist/hoi4_agent_tools/mcp/tools/focus.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/tools/gui.d.ts +111 -0
- package/dist/hoi4_agent_tools/mcp/tools/gui.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/tools/gui.js +598 -0
- package/dist/hoi4_agent_tools/mcp/tools/gui.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/tools/map.d.ts +5 -0
- package/dist/hoi4_agent_tools/mcp/tools/map.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/tools/map.js +685 -0
- package/dist/hoi4_agent_tools/mcp/tools/map.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.d.ts +58 -0
- package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.js +181 -0
- package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/transports/event-store.d.ts +26 -0
- package/dist/hoi4_agent_tools/mcp/transports/event-store.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/transports/event-store.js +86 -0
- package/dist/hoi4_agent_tools/mcp/transports/event-store.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/transports/http.d.ts +28 -0
- package/dist/hoi4_agent_tools/mcp/transports/http.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/transports/http.js +744 -0
- package/dist/hoi4_agent_tools/mcp/transports/http.js.map +1 -0
- package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.d.ts +15 -0
- package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.js +51 -0
- package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.js.map +1 -0
- package/dist/hoi4_agent_tools/runtime.d.ts +4 -0
- package/dist/hoi4_agent_tools/runtime.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/runtime.js +27 -0
- package/dist/hoi4_agent_tools/runtime.js.map +1 -0
- package/dist/hoi4_agent_tools/schemas/common.d.ts +74 -0
- package/dist/hoi4_agent_tools/schemas/common.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/schemas/common.js +51 -0
- package/dist/hoi4_agent_tools/schemas/common.js.map +1 -0
- package/dist/hoi4_agent_tools/schemas/focus.d.ts +784 -0
- package/dist/hoi4_agent_tools/schemas/focus.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/schemas/focus.js +330 -0
- package/dist/hoi4_agent_tools/schemas/focus.js.map +1 -0
- package/dist/hoi4_agent_tools/schemas/index.d.ts +5 -0
- package/dist/hoi4_agent_tools/schemas/index.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/schemas/index.js +5 -0
- package/dist/hoi4_agent_tools/schemas/index.js.map +1 -0
- package/dist/hoi4_agent_tools/schemas/map.d.ts +654 -0
- package/dist/hoi4_agent_tools/schemas/map.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/schemas/map.js +570 -0
- package/dist/hoi4_agent_tools/schemas/map.js.map +1 -0
- package/dist/hoi4_agent_tools/schemas/transaction.d.ts +259 -0
- package/dist/hoi4_agent_tools/schemas/transaction.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/schemas/transaction.js +104 -0
- package/dist/hoi4_agent_tools/schemas/transaction.js.map +1 -0
- package/dist/hoi4_agent_tools/version.d.ts +6 -0
- package/dist/hoi4_agent_tools/version.d.ts.map +1 -0
- package/dist/hoi4_agent_tools/version.js +7 -0
- package/dist/hoi4_agent_tools/version.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/docs/README.md +22 -0
- package/docs/adr/0001-runtime-and-language.md +16 -0
- package/docs/adr/0002-lossless-source-model.md +18 -0
- package/docs/adr/0003-image-and-font-codecs.md +18 -0
- package/docs/adr/0004-focus-layout.md +16 -0
- package/docs/adr/0005-offline-rendering.md +18 -0
- package/docs/adr/0006-mcp-sdk-and-protocol.md +16 -0
- package/docs/adr/0007-storage-and-transactions.md +24 -0
- package/docs/adr/0008-test-strategy.md +18 -0
- package/docs/adr/0009-packaging-and-registry.md +16 -0
- package/docs/adr/0010-unsupported-and-refusal-policy.md +18 -0
- package/docs/adr/0011-http-security.md +16 -0
- package/docs/adr/README.md +13 -0
- package/docs/architecture.md +60 -0
- package/docs/artifacts.md +133 -0
- package/docs/compatibility.md +33 -0
- package/docs/completion-report.md +60 -0
- package/docs/configuration.md +285 -0
- package/docs/focus-workflow.md +68 -0
- package/docs/gui-workflow.md +121 -0
- package/docs/limitations.md +30 -0
- package/docs/map-workflow.md +89 -0
- package/docs/performance.md +117 -0
- package/docs/release.md +181 -0
- package/docs/research/mcp-2026-07-10.md +46 -0
- package/docs/research/source-ledger.md +68 -0
- package/docs/security.md +139 -0
- package/docs/self-hosting.md +168 -0
- package/docs/testing.md +43 -0
- package/docs/third-party-notices.md +11 -0
- package/docs/transactions.md +162 -0
- package/docs/troubleshooting.md +46 -0
- package/package.json +98 -5
- package/schemas/configuration.schema.json +794 -0
- package/schemas/continuous-focus-palette.schema.json +325 -0
- package/schemas/focus-plan.schema.json +902 -0
- package/schemas/focus-planning-sidecar.schema.json +364 -0
- package/schemas/gui-animation-source.schema.json +176 -0
- package/schemas/gui-helper.schema.json +301 -0
- package/schemas/gui-scenario.schema.json +298 -0
- package/schemas/map-operation.schema.json +2284 -0
- package/schemas/operation-result.schema.json +344 -0
- package/schemas/transaction-manifest.schema.json +685 -0
- package/server.json +32 -0
package/docs/release.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Release and MCP Registry publication
|
|
2
|
+
|
|
3
|
+
Releases use strict stable Semantic Versioning and an immutable Git tag. Every public writer
|
|
4
|
+
re-queries both the direct tag and its optional annotated-tag peel immediately before the write.
|
|
5
|
+
The peeled commit must equal `GITHUB_SHA` and the commit recorded in the release artifact.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- a clean tested commit on `main`;
|
|
10
|
+
- package, server, source, schema, documentation, lockfile, and changelog versions synchronized;
|
|
11
|
+
- the public GitHub repository owned by the canonical `klimPaskov` account;
|
|
12
|
+
- GitHub release immutability enabled in repository settings before the first stable release;
|
|
13
|
+
- a public, pre-bootstrapped `ghcr.io/klimpaskov/hoi4-agent-tools` package;
|
|
14
|
+
- the npm namespace bootstrap completed and the trusted publisher configured;
|
|
15
|
+
- GitHub Actions OIDC available for ordinary npm and MCP Registry publication.
|
|
16
|
+
|
|
17
|
+
The release workflow uses the npm 11.16.0 CLI bundled with the pinned Node 24.18.0 LTS distribution.
|
|
18
|
+
No release job upgrades npm globally. The ordinary npm OIDC publisher does not check out source,
|
|
19
|
+
run `npm ci`, execute dependency lifecycle scripts, or install any package. It downloads the one
|
|
20
|
+
artifact made by `validate_pack`, checks its recorded commit and SHA-256/SHA-512 digests, rechecks
|
|
21
|
+
the public npm state and peeled Git tag, resolves the validated basename to a contained absolute
|
|
22
|
+
artifact path, and publishes that exact tarball with `--ignore-scripts` and provenance. The
|
|
23
|
+
absolute path is required because npm can parse a slash-containing relative path as a GitHub
|
|
24
|
+
repository shorthand. If either the legacy `NPM_TOKEN` or one-use `NPM_BOOTSTRAP_TOKEN` repository secret exists, the ordinary release fails
|
|
25
|
+
before requesting or using trusted-publisher credentials.
|
|
26
|
+
|
|
27
|
+
## One-time npm namespace bootstrap
|
|
28
|
+
|
|
29
|
+
An unclaimed package cannot have a trusted publisher configured. The one-time manual
|
|
30
|
+
`Bootstrap npm trusted publishing` workflow claims the namespace with the non-executable
|
|
31
|
+
prerelease `0.0.0-bootstrap.1`; it never publishes a stable release. The `.1` suffix preserves
|
|
32
|
+
the immutable audit trail of an earlier `.0` tag whose run stopped before npm accepted any
|
|
33
|
+
publication.
|
|
34
|
+
|
|
35
|
+
1. Create the immutable tag `npm-bootstrap-v0.0.0-bootstrap.1` on the reviewed `main` commit.
|
|
36
|
+
2. Create a short-lived npm granular access token with read/write access to **All Packages** and
|
|
37
|
+
bypass-2FA enabled. This broad initial scope is an npm limitation for an unclaimed namespace.
|
|
38
|
+
Give it the shortest practical expiry and store it only as `NPM_BOOTSTRAP_TOKEN`.
|
|
39
|
+
3. Dispatch `bootstrap-npm.yml` from that exact tag. The workflow has no `id-token` permission,
|
|
40
|
+
accepts only the hard-coded package/version/dist-tag, runs `npm audit signatures` before the
|
|
41
|
+
write, publishes a two-file non-executable tarball under the `bootstrap` dist-tag, and verifies
|
|
42
|
+
the public bytes and npm registry signature without the token.
|
|
43
|
+
4. Revoke the granular token immediately and delete `NPM_BOOTSTRAP_TOKEN`.
|
|
44
|
+
5. Configure npm trusted publishing for GitHub owner `klimPaskov`, repository
|
|
45
|
+
`hoi4-agent-tools`, and workflow `release.yml`; explicitly select the required allowed action `npm publish`.
|
|
46
|
+
npm requires an allowed action for configurations created after May 20, 2026.
|
|
47
|
+
|
|
48
|
+
The ordinary release workflow never supports token fallback. Do not create an `NPM_TOKEN`
|
|
49
|
+
secret, and delete `NPM_BOOTSTRAP_TOKEN` immediately after the namespace claim; either secret's
|
|
50
|
+
presence deliberately blocks the OIDC publisher.
|
|
51
|
+
|
|
52
|
+
On an entirely new npm package, the registry can additionally assign the sole bootstrap version
|
|
53
|
+
to `latest` even when the publish command explicitly selects `bootstrap`. The first stable release
|
|
54
|
+
accepts only the exact observed recovery state: versions contains only `0.0.0-bootstrap.1`, and
|
|
55
|
+
the only dist-tags are `bootstrap` and `latest`, both naming that version. Any extra version, tag,
|
|
56
|
+
different prerelease, missing bootstrap tag, or malformed state stops publication. Once the first
|
|
57
|
+
stable package is published, the normal strict stable-version monotonic and exact-rerun rules apply.
|
|
58
|
+
|
|
59
|
+
## Required pre-tag immutability check
|
|
60
|
+
|
|
61
|
+
GitHub's immutable-release settings endpoint requires repository `Administration:read`, which
|
|
62
|
+
the short-lived repository `GITHUB_TOKEN` cannot request. Do not add a long-lived administration
|
|
63
|
+
token to Actions for this check. Instead, the repository owner must run the authenticated check
|
|
64
|
+
below immediately before pushing each stable release tag:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
test "$(gh api \
|
|
68
|
+
--header 'X-GitHub-Api-Version: 2026-03-10' \
|
|
69
|
+
repos/klimPaskov/hoi4-agent-tools/immutable-releases \
|
|
70
|
+
--jq '.enabled')" = 'true'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This owner check is a release prerequisite and must pass before the first public writer starts.
|
|
74
|
+
The workflow also requires the completed release to report `immutable: true` before MCP Registry
|
|
75
|
+
publication and final verification. That post-publication gate detects a skipped prerequisite,
|
|
76
|
+
but it cannot undo a mutable release; an administrator changing the setting between the owner
|
|
77
|
+
check and release publication is an external GitHub settings race that the release API offers no
|
|
78
|
+
conditional publish operation to close.
|
|
79
|
+
|
|
80
|
+
## One-time GHCR visibility bootstrap
|
|
81
|
+
|
|
82
|
+
GitHub creates the first personal-account container package as private. Run the pinned manual
|
|
83
|
+
`Bootstrap GHCR` workflow from public `main`, then change package visibility to **Public** in the
|
|
84
|
+
package settings. The bootstrap uses only the repository-scoped `GITHUB_TOKEN`, publishes only
|
|
85
|
+
the `bootstrap` tag, and verifies the authenticated index contains exact `linux/amd64` and
|
|
86
|
+
`linux/arm64` runtime manifests. GitHub exposes no supported API for changing a personal GHCR
|
|
87
|
+
package's visibility, so the bootstrap cannot prove anonymous access until an administrator makes
|
|
88
|
+
that newly created package public in the package settings.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
gh workflow run bootstrap-ghcr.yml --repo klimPaskov/hoi4-agent-tools --ref main
|
|
92
|
+
gh run watch --repo klimPaskov/hoi4-agent-tools
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
After changing visibility to **Public**, prove anonymous visibility and both runtime manifests with
|
|
96
|
+
a Docker configuration that contains no credentials:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
ANONYMOUS_DOCKER_CONFIG="$(mktemp -d)"
|
|
100
|
+
MANIFEST="$(DOCKER_CONFIG="$ANONYMOUS_DOCKER_CONFIG" \
|
|
101
|
+
docker buildx imagetools inspect --raw \
|
|
102
|
+
ghcr.io/klimpaskov/hoi4-agent-tools:bootstrap)"
|
|
103
|
+
RUNTIME_PLATFORMS="$(jq --raw-output \
|
|
104
|
+
'[.manifests[] | select(.platform.os == "linux") | "\(.platform.os)/\(.platform.architecture)"] | unique | sort | join(",")' \
|
|
105
|
+
<<<"$MANIFEST")"
|
|
106
|
+
rm -rf "$ANONYMOUS_DOCKER_CONFIG"
|
|
107
|
+
test "$RUNTIME_PLATFORMS" = 'linux/amd64,linux/arm64'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Local release audit
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm ci --ignore-scripts
|
|
114
|
+
npm audit --audit-level=high
|
|
115
|
+
npm audit signatures --ignore-scripts
|
|
116
|
+
npm run check
|
|
117
|
+
npm run test:coverage
|
|
118
|
+
npm run inspector
|
|
119
|
+
REGISTRY_LIVE_VALIDATION=1 npm run registry:validate
|
|
120
|
+
npm pack --dry-run --ignore-scripts --json
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The workflow repeats `npm audit signatures` as a mandatory gate before any public writer can
|
|
124
|
+
start. It verifies the package-manager inputs used by the build and later verifies the newly
|
|
125
|
+
published package with `npm audit signatures --json --include-attestations`.
|
|
126
|
+
|
|
127
|
+
## Enforced publication chain
|
|
128
|
+
|
|
129
|
+
1. `validate_pack` verifies the remote peeled tag, `main` ancestry, canonical identity, npm
|
|
130
|
+
release order, repository/GHCR visibility, all checks, dependency signatures, and coverage. It
|
|
131
|
+
creates one tarball, `npm-pack.json`, and `release-identity.json` bound to the tarball digests
|
|
132
|
+
and source commit. This job has no OIDC permission.
|
|
133
|
+
2. `publish_npm` is the minimal OIDC job. It rejects both npm bearer-token secrets, downloads and validates the
|
|
134
|
+
exact artifact, rechecks npm ordering and the remote peeled tag, resolves the tarball to a
|
|
135
|
+
contained absolute file path, then publishes only when the version is absent. It performs no
|
|
136
|
+
checkout or dependency installation.
|
|
137
|
+
3. `verify_npm` has no OIDC permission. It downloads the public tarball byte-for-byte, runs the
|
|
138
|
+
official npm signature verifier, and passes the exact returned Sigstore bundle to npm's bundled
|
|
139
|
+
official Sigstore verifier with the expected Fulcio issuer and workflow certificate identity.
|
|
140
|
+
Verification requires one signed DSSE envelope, Rekor inclusion, the exact npm PURL and
|
|
141
|
+
SHA-512 subject, GitHub-hosted runner builder, release workflow/tag, and release commit. A
|
|
142
|
+
replayed bundle that differs from the current registry response is rejected.
|
|
143
|
+
4. `publish_image` first checks the anonymous exact SemVer tag and GitHub release as one state
|
|
144
|
+
matrix. A completed identical rerun is accepted only when the tag digest equals the immutable
|
|
145
|
+
`container-image.json` release asset. If the tag exists but the later GitHub release does not,
|
|
146
|
+
the workflow reconstructs `container-image.json` from the exact anonymous digest and permits
|
|
147
|
+
recovery only after the normal anonymous verifier proves the index digest, two runtime
|
|
148
|
+
platforms, image source/revision/version labels, SBOM subjects, provenance subjects, source
|
|
149
|
+
tag, and source SHA against `GITHUB_SHA`. A release without its image tag, any mismatched
|
|
150
|
+
release asset, or any failed provenance check stops the chain. A first publication builds from
|
|
151
|
+
the action's default Git context, pushes by digest without a tag, rechecks the Git tag, then
|
|
152
|
+
creates the exact SemVer tag once. No mutable major/minor tag is published.
|
|
153
|
+
5. `github_release` uses the authenticated, fully paginated List releases endpoint because
|
|
154
|
+
GitHub's by-tag endpoint exposes published releases but not drafts. It requires zero or one
|
|
155
|
+
exact tag match, cross-checks the published endpoint, and classifies the state as absent, a
|
|
156
|
+
mutable draft, or an already-complete immutable release. Drafts and publications must be owned
|
|
157
|
+
by the canonical GitHub Actions bot, use the exact tag-derived title and checked-in changelog
|
|
158
|
+
body, and expose no asset-label override. An existing draft may contain only a byte-for-byte
|
|
159
|
+
verified subset of the four expected uploaded assets from that same bot; unexpected,
|
|
160
|
+
duplicate, differently uploaded, non-uploaded, or differing assets stop the workflow without
|
|
161
|
+
deletion or replacement. The pinned release action stages missing assets with overwrite
|
|
162
|
+
disabled, canonicalizes the title and body, and leaves the release as a draft. Its numeric
|
|
163
|
+
release ID must match the unique authenticated listing. The workflow then requires the exact
|
|
164
|
+
npm tarball, both npm manifests, and `container-image.json`, repeats the unique-ID, metadata,
|
|
165
|
+
and byte checks, rechecks the peeled tag, and publishes that verified draft once.
|
|
166
|
+
Repository-level release immutability protects the assets and Git tag after publication. An
|
|
167
|
+
exact uploaded subset is resumable; a failed GitHub upload left in `starter` state or a draft
|
|
168
|
+
with noncanonical authorship or labels is a manual draft-cleanup blocker rather than permission
|
|
169
|
+
to overwrite or delete assets automatically. A completed rerun must match the one listed/public
|
|
170
|
+
release ID, canonical metadata, and all four immutable assets exactly.
|
|
171
|
+
6. `publish_registry` validates a checksum-pinned official publisher, uses GitHub OIDC, rechecks
|
|
172
|
+
the peeled tag after login, and publishes the exact `server.json` only when absent.
|
|
173
|
+
7. `verify_public` re-queries the peeled tag and verifies npm, immutable GitHub release assets,
|
|
174
|
+
anonymous GHCR digest/SBOM/provenance, and complete MCP Registry metadata. It also performs a
|
|
175
|
+
clean public install and registry-signature audit.
|
|
176
|
+
|
|
177
|
+
The global non-cancelling `release` concurrency group serializes releases. npm, GitHub release,
|
|
178
|
+
the exact container tag, and MCP Registry version are treated as immutable: existing matching
|
|
179
|
+
objects may make a completed rerun idempotent, while absent records, moved tags, ambiguous state,
|
|
180
|
+
or differing bytes/digests stop the chain. The Registry hosts metadata, not package bytes; local
|
|
181
|
+
validation alone is never treated as publication evidence.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# MCP protocol, SDK, security, and Registry review
|
|
2
|
+
|
|
3
|
+
Verified 2026-07-10 against official sources.
|
|
4
|
+
|
|
5
|
+
## Selected production baseline
|
|
6
|
+
|
|
7
|
+
- Final protocol: [`2025-11-25`](https://modelcontextprotocol.io/specification/2025-11-25).
|
|
8
|
+
- Production TypeScript SDK: [`@modelcontextprotocol/sdk` 1.29.0](https://www.npmjs.com/package/%40modelcontextprotocol/sdk?activeTab=versions), using the [`v1.x` server guide](https://github.com/modelcontextprotocol/typescript-sdk/blob/v1.x/docs/server.md).
|
|
9
|
+
- Inspector: [`@modelcontextprotocol/inspector` 0.22.0](https://www.npmjs.com/package/%40modelcontextprotocol/inspector).
|
|
10
|
+
- Registry schema: [`2025-12-11/server.schema.json`](https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json).
|
|
11
|
+
- Registry publisher pinned by release workflow: `v1.7.9`; the workflow verifies the published checksum manifest and archive before extraction.
|
|
12
|
+
|
|
13
|
+
The breaking `2026-07-28` protocol and SDK v2 split packages were release candidates on the review date. They are not used for the production package. This decision must be revisited after the final release.
|
|
14
|
+
|
|
15
|
+
## Transport and capability requirements applied
|
|
16
|
+
|
|
17
|
+
- Stdio uses newline-delimited UTF-8 JSON-RPC, protocol-only stdout, and stderr logging.
|
|
18
|
+
- Streamable HTTP uses one `/mcp` POST/GET endpoint plus DELETE for session termination. It is stateful to support progress, cancellation, server notifications, SSE resumption, and secure random sessions.
|
|
19
|
+
- Sessions are bound to authenticated principals and expire; they are never authentication credentials.
|
|
20
|
+
- Tools use strict schemas and explicit read-only/destructive/idempotent/open-world annotations. Hints do not replace enforcement.
|
|
21
|
+
- Long work observes `AbortSignal` and sends monotonic progress only when the client supplies a progress token.
|
|
22
|
+
- Large results are content-addressed resources. Binary reads are bounded/chunkable because resource links defer retrieval but are not a byte-stream transport.
|
|
23
|
+
- Prompts describe safe workflows but grant no permission.
|
|
24
|
+
|
|
25
|
+
## Remote security requirements applied
|
|
26
|
+
|
|
27
|
+
- Loopback is the default bind address.
|
|
28
|
+
- Present origins and Host are validated; request body, concurrency, rate, session, and expiry limits are enforced.
|
|
29
|
+
- Every HTTP method authenticates. Static environment bearer tokens are loopback-only.
|
|
30
|
+
- Non-loopback operation requires HTTPS and OAuth/OIDC resource-server JWT verification: issuer, JWKS, audience, algorithms, expiry, subject, and required scopes.
|
|
31
|
+
- Protected Resource Metadata is exposed when OAuth is configured.
|
|
32
|
+
- Principal-to-workspace grants are server-side; token passthrough, query-string tokens, cross-principal sessions, and cross-workspace transactions are rejected.
|
|
33
|
+
|
|
34
|
+
Primary references: [transport specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports), [authorization](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization), [security guidance](https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices), [tools](https://modelcontextprotocol.io/specification/2025-11-25/server/tools), [resources](https://modelcontextprotocol.io/specification/2025-11-25/server/resources), [prompts](https://modelcontextprotocol.io/specification/2025-11-25/server/prompts), [progress](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/progress), and [cancellation](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/cancellation).
|
|
35
|
+
|
|
36
|
+
## Registry requirements applied
|
|
37
|
+
|
|
38
|
+
- `package.json.mcpName` exactly matches `server.json.name`.
|
|
39
|
+
- The public npm package version, server version, and Registry version are exact and synchronized.
|
|
40
|
+
- Registry versions are immutable; release metadata is validated before publishing.
|
|
41
|
+
- npm is published first because the Registry stores discovery metadata rather than package bytes.
|
|
42
|
+
- The release workflow uses GitHub OIDC for `mcp-publisher` and npm provenance.
|
|
43
|
+
- npm trusted publishers created after May 20, 2026 require an explicit allowed action; this package selects `npm publish`, uses a GitHub-hosted runner with `id-token: write`, and does not restore a package-manager cache in release jobs.
|
|
44
|
+
- The pinned official publisher's live `validate` operation accepts this release's `server.json` before publication.
|
|
45
|
+
|
|
46
|
+
References: [Registry quickstart](https://modelcontextprotocol.io/registry/quickstart), [package types](https://modelcontextprotocol.io/registry/package-types), [versioning](https://modelcontextprotocol.io/registry/versioning), and [GitHub Actions publishing](https://modelcontextprotocol.io/registry/github-actions).
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# HOI4 source research ledger
|
|
2
|
+
|
|
3
|
+
Reviewed 2026-07-10. These sources informed format support and tests; no installed-game or third-party-mod content is included in this repository.
|
|
4
|
+
|
|
5
|
+
## Offline wiki snapshot
|
|
6
|
+
|
|
7
|
+
The supplied offline Hearts of Iron IV wiki snapshot was consulted for:
|
|
8
|
+
|
|
9
|
+
- `Data structures - Hearts of Iron 4 Wiki.md`: ordered blocks, variables/tokens, event targets, and generic script structure.
|
|
10
|
+
- `National focus modding - Hearts of Iron 4 Wiki.md`: tree assignment, prerequisite grouping, relative positions, exclusions, continuous focuses, icons, AI, filters, and localisation.
|
|
11
|
+
- `Interface modding - Hearts of Iron 4 Wiki.md`: containers, element types, scrolling, positions, orientation, and fonts.
|
|
12
|
+
- `Scripted GUI modding - Hearts of Iron 4 Wiki.md`: contexts, parents, visibility, effects/triggers, dynamic lists, properties, AI, templates, and scripted localisation.
|
|
13
|
+
- `Graphical asset modding - Hearts of Iron 4 Wiki.md`: sprite, frame animation, progress, and bitmap-font declarations.
|
|
14
|
+
- `Map modding - Hearts of Iron 4 Wiki.md`: BMP headers/palettes, coordinates, definitions, terrain, buildings, unit positions, adjacency, and supply.
|
|
15
|
+
- `State modding - Hearts of Iron 4 Wiki.md`: state/history/province/building/resource/victory-point structure and strategic-region constraints.
|
|
16
|
+
- `Localisation - Hearts of Iron 4 Wiki.md`: UTF-8 BOM, language headers, key grammar, versions, escaping, and scripted localisation.
|
|
17
|
+
- `Triggers`, `Effects`, and `Scopes`: ordered raw trigger/effect preservation and source-reference indexing.
|
|
18
|
+
|
|
19
|
+
The wiki remains useful background, but current official files and installed examples take precedence when they differ.
|
|
20
|
+
|
|
21
|
+
## Installed official documentation
|
|
22
|
+
|
|
23
|
+
Under `<HOI4_ROOT>/documentation`:
|
|
24
|
+
|
|
25
|
+
- `script_concept_documentation.md`: collections, contextual/formatted localisation, math expressions, and script constants.
|
|
26
|
+
- `triggers_documentation.md`: current trigger names/scopes, state/province/focus/railway references, and dynamic argument support.
|
|
27
|
+
- `effects_documentation.md`: current effect names/scopes and state/province/focus references. Its
|
|
28
|
+
553 documented effect identifiers form the bundled Focus Workbench native-effect catalog;
|
|
29
|
+
headings only were retained, not proprietary documentation prose.
|
|
30
|
+
- `loc_objects_documentation.md` and `loc_formatter_documentation.md`: current province/state objects and font/layout-relevant localisation behavior.
|
|
31
|
+
- `dynamic_variables_documentation.md`, `modifiers_documentation.md`, collection input/operator documentation: tokens and raw constructs the CST must retain.
|
|
32
|
+
|
|
33
|
+
Official documentation found outside that folder was also consulted, especially:
|
|
34
|
+
|
|
35
|
+
- `common/scripted_guis/_documentation.md`: authoritative current contexts, parent attachment, dynamic lists, properties, dirty variables, effects/triggers, and AI fields.
|
|
36
|
+
- `common/focus_inlay_windows/documentation.md`: current inlay fields, including scripted buttons and progress bars absent from older summaries.
|
|
37
|
+
|
|
38
|
+
## Vanilla precedents
|
|
39
|
+
|
|
40
|
+
Representative read-only examples:
|
|
41
|
+
|
|
42
|
+
- `common/national_focus/generic.txt` and large country trees for repeated prerequisite blocks, OR groups, exclusions, relative positions, raw rewards, `continuous_focus_position`, route AI, uppercase `IF`/`ELSE_IF`/`ELSE`, weighted `random_list`, direct scripted-effect calls, scoped country/state/character blocks, decision/formable links, and cosmetic-tag effects.
|
|
43
|
+
- `common/continuous_focus/generic.txt` for the current `continuous_focus_palette = { ... focus = { ... } }` model, palette selection/position, and continuous-focus availability, enablement, modifier, cost, and AI fields.
|
|
44
|
+
- `interface/achievements.gui`, `interface/abilitylist.gui`, scripted-GUI interface files, and paired `.gfx` files for nested containers, lists, click regions, sprite states, and ordering.
|
|
45
|
+
- `common/scripted_guis/*.txt` for decision-category contexts, button effect/trigger naming, AI, dynamic lists, and parent/window connections.
|
|
46
|
+
- `interface/*.gfx`, `gfx/interface/**`, and `gfx/fonts/**` for horizontal frame strips, fractional animation rates, DDS/TGA/PNG textures, vector and bitmap font sources.
|
|
47
|
+
- `map/default.map`, `map/provinces.bmp`, `map/definition.csv`, `map/adjacencies.csv`, `map/supply_nodes.txt`, `map/railways.txt`, `map/buildings.txt`, `map/unitstacks.txt`, and `map/weatherpositions.txt` for current map formats.
|
|
48
|
+
- `history/states/*.txt` and `map/strategicregions/*.txt` for state/region membership and ordered history payloads.
|
|
49
|
+
|
|
50
|
+
## Current format conclusions
|
|
51
|
+
|
|
52
|
+
- The inspected installed build was HOI4 1.19.2 content dated 2026-06-12.
|
|
53
|
+
- `provinces.bmp` is a 5632×2048, uncompressed, bottom-up 24-bit BMP with a 40-byte DIB header.
|
|
54
|
+
- Other current map BMPs include indexed 8-bit DIB40 and DIB124 files; the codec must honor pixel offsets, row padding, palette size, orientation, and untouched bytes.
|
|
55
|
+
- Map CSV/text examples use UTF-8 without BOM and LF; localisation examples use UTF-8 BOM. The source model detects and preserves each file rather than normalizing it.
|
|
56
|
+
- Active placement data is in building/unit/weather files; `positions.txt` may exist but be empty. Model-local `.asset` locator blocks are a separate source family.
|
|
57
|
+
- `weatherpositions.txt` uses `small` and `big` tokens in the inspected build.
|
|
58
|
+
- Sprite textures include PNG, TGA, uncompressed DDS, DXT1/3/5, DX10 RGBA/BGRA, and RXGB variants. Frame counts divide a horizontal strip; animation rates may be fractional.
|
|
59
|
+
- Bitmap fonts use `.fnt` metrics/kerning and texture atlases. Locale overrides and additional script font files must remain connected in the source graph.
|
|
60
|
+
- Definition rows and state IDs are contiguous in the inspected build. Province ID allocation therefore records current contiguity and must not treat arbitrary gaps as universally safe.
|
|
61
|
+
- Only land provinces are required to belong to a state; sea provinces and some lakes legitimately do not. Every nonzero province is expected in one strategic region.
|
|
62
|
+
- State source does not expose a generic `capital` field. Map operations distinguish a country's capital-state reference from a state's chief victory-point/capital province and never guess between them.
|
|
63
|
+
- Clausewitz quoted strings decode only escaped quote and backslash. Literal newlines are invalid. Token expressions such as `variable?100` are scalar atoms; only `?=` is an operator.
|
|
64
|
+
- Focus completion rewards call scripted effects directly by identifier; there is no native
|
|
65
|
+
`scripted_effect = helper_id` wrapper. `set_cosmetic_tag` targets cosmetic identity and is not a
|
|
66
|
+
formable-decision reference. Formables are decision targets, and
|
|
67
|
+
`unlock_decision_category_tooltip` targets a top-level decision category.
|
|
68
|
+
- File replacement, duplicate keys, and ordering are database-specific. Same relative indexed filename shadows lower load-order sources; directly indexed files in a `replace_path` directory are removed without treating every descendant asset as removed.
|
package/docs/security.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Security and threat model
|
|
2
|
+
|
|
3
|
+
## Protected assets
|
|
4
|
+
|
|
5
|
+
- external mod source and binary map data;
|
|
6
|
+
- installed game and dependency references;
|
|
7
|
+
- transaction approval intent and rollback blobs;
|
|
8
|
+
- generated artifacts that may reveal source details;
|
|
9
|
+
- HTTP credentials and principal/workspace grants.
|
|
10
|
+
|
|
11
|
+
## Trust boundaries
|
|
12
|
+
|
|
13
|
+
MCP input, file paths, manifest content, client annotations, session IDs, Origin/Host headers, and remote access tokens are untrusted. Tool annotations are descriptive hints. Prompts are guidance. Server-side policy is authoritative.
|
|
14
|
+
|
|
15
|
+
## Filesystem controls
|
|
16
|
+
|
|
17
|
+
- Only registered roots are visible.
|
|
18
|
+
- Public paths are relative and canonicalized.
|
|
19
|
+
- Traversal, absolute paths, UNC/device paths, NULs, alternate data streams, ambiguous trailing characters, and device names are rejected.
|
|
20
|
+
- Existing symlinks and junctions are resolved; an escape outside the root is rejected.
|
|
21
|
+
- Artifact shards, transaction journals, blobs, and lock descendants are re-canonicalized before access. A symlink or junction observed in artifact/journal enumeration is rejected.
|
|
22
|
+
- Transaction mode requires an absolute `serverStateRoot` whose existing components are non-linked
|
|
23
|
+
and whose canonical target does not overlap any source, registration capability,
|
|
24
|
+
generated-storage root, or runtime-nominated root. Harmless native path-spelling aliases are
|
|
25
|
+
normalized only after the link check. Its random journal key and protected revision heads are
|
|
26
|
+
never returned through MCP.
|
|
27
|
+
- Writes target the canonical mod root only. Game, dependency, fixture, and unrelated user files are never writable.
|
|
28
|
+
- Runtime mod registration requires a separate, default-empty `writableRegistrationRoots`
|
|
29
|
+
capability. A caller cannot relabel a game/dependency path from the read-only
|
|
30
|
+
`registrationRoots` allowlist as a mod.
|
|
31
|
+
- Artifact URIs are opaque and authorization-checked; filesystem paths are not placed in MCP responses.
|
|
32
|
+
|
|
33
|
+
These are application checks, not a kernel-enforced filesystem sandbox. The operator must prevent
|
|
34
|
+
hostile operating-system principals from concurrently replacing directories, symlinks, junctions,
|
|
35
|
+
mounts, or files inside registered and generated roots between validation and I/O. Such an actor
|
|
36
|
+
already has direct filesystem authority and is outside the application security boundary. The
|
|
37
|
+
server detects normal stale-source changes and observed link escapes, but does not claim
|
|
38
|
+
race-proof `openat`-style containment or operating-system transaction atomicity against hostile
|
|
39
|
+
concurrent mutation.
|
|
40
|
+
|
|
41
|
+
## Write controls
|
|
42
|
+
|
|
43
|
+
Read-only is the default. A write requires global and workspace enablement, a validated dry run, a persisted transaction, exact plan hash, separate apply call, unexpired principal/workspace binding, unchanged source hashes, and a workspace lock. There is no command execution field. Stale apply and rollback operations fail closed.
|
|
44
|
+
|
|
45
|
+
Runtime registration definitions and raw paths are not persisted. The canonical artifact root does
|
|
46
|
+
retain an atomically created ownership claim containing only domain-separated SHA-256 workspace and
|
|
47
|
+
owner bindings. Re-registration restores that binding only for the same canonical workspace and
|
|
48
|
+
runtime principal; malformed, linked, raced, aliased, cross-principal, and cross-workspace claims
|
|
49
|
+
fail closed. A failed journal recovery removes only the in-memory registration, never its persistent
|
|
50
|
+
claim or existing generated data. Statically configured workspaces do not use runtime claims and
|
|
51
|
+
remain shared according to their operator-reviewed principal grants.
|
|
52
|
+
|
|
53
|
+
Every artifact provenance manifest includes the resolved workspace identity and its configured or
|
|
54
|
+
runtime owner identity in the immutable provenance hash. List, describe, and resource-read paths
|
|
55
|
+
verify both values before returning metadata or bytes. Reusing a physical artifact store through a
|
|
56
|
+
different workspace or owner therefore cannot expose prior evidence; unbound legacy or malformed
|
|
57
|
+
manifests are rejected rather than migrated or deleted implicitly.
|
|
58
|
+
|
|
59
|
+
Transaction manifests are authenticated with HMAC-SHA-256 over the complete canonical manifest,
|
|
60
|
+
excluding only the authentication tag. The 256-bit random key lives beneath `serverStateRoot`, not
|
|
61
|
+
in a workspace or public configuration value. Protected revision heads prevent replay of an older
|
|
62
|
+
valid manifest. A cache-first crash may reconcile only an authenticated exact next revision; a
|
|
63
|
+
missing head, revision gap, altered expiry/state/failure/rollback field, or recomputed public hash
|
|
64
|
+
fails closed. No HMAC key is derived from public workspace data.
|
|
65
|
+
|
|
66
|
+
Read-only transaction operations never repair protected state. Cache-first successor promotion is
|
|
67
|
+
confined to startup recovery and authorized write paths. Artifact manifests are capped at 1 MiB and
|
|
68
|
+
transaction manifests at 16 MiB before parsing; transaction resource ranges use a bounded verified
|
|
69
|
+
byte cache instead of repeatedly rebuilding the authenticated object.
|
|
70
|
+
|
|
71
|
+
## HTTP controls
|
|
72
|
+
|
|
73
|
+
- Every POST, GET, and DELETE request to `/mcp` is authenticated; only standards-required OAuth discovery metadata is public.
|
|
74
|
+
- Present Origin and Host are checked before MCP dispatch. Security-sensitive singleton fields are counted from the raw HTTP header list before Node normalization, so duplicate Host, Authorization, Origin, content metadata, forwarding identity, or MCP session/protocol fields fail closed. Absolute-form request targets must use an allowlisted authority identical to Host.
|
|
75
|
+
- Session IDs are secure random routing identifiers bound to the authenticated principal, an explicit OAuth client when present, the exact bearer credential's SHA-256 identifier, and the non-downgraded scope set; they are not credentials. A token without `client_id` or `azp` is credential-bound rather than being aliased to the subject.
|
|
76
|
+
- Missing, expired, cross-principal, or unknown sessions fail.
|
|
77
|
+
- Connection count, requests per socket, header/request/keep-alive time, JSON body size, admitted concurrency, request rate, session count, event streams, event history, and session lifetime are bounded.
|
|
78
|
+
- Admitted request concurrency is fixed at no more than two; configured body bytes multiplied by
|
|
79
|
+
concurrency cannot exceed 16 MiB.
|
|
80
|
+
- Static bearer tokens are loopback-only. A non-loopback listener or a non-loopback canonical `publicUrl` (including a loopback listener behind a public reverse proxy) requires HTTPS and OAuth/OIDC JWT signature, issuer, audience, algorithm, expiry, subject, and scope verification.
|
|
81
|
+
- Tokens are accepted only in the Authorization header and are never logged, forwarded, copied into a session, or exposed to MCP handlers. Only a one-way SHA-256 credential identifier is retained for session binding.
|
|
82
|
+
- Protected Resource Metadata is published for OAuth deployments and linked from OAuth `WWW-Authenticate` challenges.
|
|
83
|
+
- Initial 401 challenges identify the baseline scope. A write-scoped tool call made with a read token receives an HTTP 403 `insufficient_scope` challenge naming the baseline plus `hoi4:write`, before JSON-RPC dispatch.
|
|
84
|
+
- Streamable HTTP reserves concurrency before JSON parsing or token verification and applies a socket-address rate bucket before authentication, followed by an independent per-principal bucket after authentication. Host and any present Origin are rejected even earlier. Every `/mcp` POST must advertise unparameterized, positively weighted `application/json` and `text/event-stream` response media types, use the exact `application/json` request media type with an absent or `utf-8` charset, and use no content coding other than identity. GET requires an unparameterized, positively weighted `text/event-stream` range. Bodies are fatal-decoded as UTF-8 and parsed under the raw-wire `maxBodyBytes` ceiling; suffix types, malformed or ambiguous media parameters, encoded entities, replacement-decoded UTF-8, and parameter-only media-type mentions are rejected before SDK dispatch.
|
|
85
|
+
- `trustedProxyAddresses` contains exact IP addresses only and affects only derivation of the pre-auth rate-limit key; it does not enable general forwarded-header trust. `X-Forwarded-For` is ignored unless the direct socket peer exactly matches a configured address (IPv4-mapped IPv6 is normalized). For a trusted peer, a missing or invalid header is rejected and only the first comma-separated address is used.
|
|
86
|
+
- A reverse proxy must be the only network path to a proxied server, terminate TLS, overwrite client-supplied forwarding headers with a validated client IP, preserve Authorization/Origin/Host, and enforce edge connection, header, body, timeout, and rate limits. CIDR ranges, hostnames, and an unverified proxy chain are not inferred by the application.
|
|
87
|
+
- Every session request is reauthenticated and must present the exact credential that initialized the session; another token cannot take over merely because its subject or client claims match. OAuth refresh and scope step-up therefore initialize a new MCP session. Scope authority within a session remains monotonic, and handler-level write-scope checks remain in place as defense in depth.
|
|
88
|
+
|
|
89
|
+
Session admission counts both active sessions and initializations in progress, globally and per
|
|
90
|
+
principal. Static-token sessions use the configured sliding inactivity lifetime. OAuth session
|
|
91
|
+
expiry is the earlier of that lifetime and the access token's `exp`; an expired token cannot create
|
|
92
|
+
a session. Expiration timers remove sessions at that bound, with access checks, pre-admission
|
|
93
|
+
pruning, and periodic cleanup as fail-closed backstops.
|
|
94
|
+
Resumable GET streams have separate global/per-principal ceilings; once accepted, a long-lived
|
|
95
|
+
stream releases the ordinary short-request concurrency reservation and remains charged to the
|
|
96
|
+
stream ceilings.
|
|
97
|
+
|
|
98
|
+
Replay history is also bounded: at most 1,000 events per session, the configured per-session byte
|
|
99
|
+
budget, the configured process-wide event-store byte budget, and the session TTL. Per-session
|
|
100
|
+
overflow evicts the oldest history first. If one event cannot fit the per-session or shared byte
|
|
101
|
+
budget, it is not retained for replay; the store does not evict another session's history to make
|
|
102
|
+
room. Closing or expiring a session releases its shared budget.
|
|
103
|
+
|
|
104
|
+
## Stdio controls
|
|
105
|
+
|
|
106
|
+
Stdio accepts newline-delimited JSON-RPC frames of at most 16,777,216 bytes, excluding the line-feed
|
|
107
|
+
delimiter. The ceiling is fixed and matches the largest configurable Streamable HTTP JSON body.
|
|
108
|
+
Input is retained in a geometrically grown bounded byte buffer, keeping cumulative copy work
|
|
109
|
+
linear without per-chunk metadata growth. Completed frames use fatal UTF-8 decoding; malformed byte
|
|
110
|
+
sequences are never replaced with U+FFFD or dispatched as JSON-RPC. A malformed UTF-8 frame or a
|
|
111
|
+
frame that crosses the ceiling is refused immediately (for size, including when no newline or
|
|
112
|
+
end-of-input has arrived): the server writes a structured `STDIO_INVALID_UTF8` or
|
|
113
|
+
`STDIO_FRAME_TOO_LARGE` event to stderr, closes that transport, and exits unsuccessfully. The
|
|
114
|
+
rejected payload is never echoed. Protocol responses remain exclusively on stdout; transport and
|
|
115
|
+
startup diagnostics remain exclusively on stderr.
|
|
116
|
+
|
|
117
|
+
Well-formed UTF-8 frames that fail JSON or JSON-RPC schema validation are not dispatched. Their
|
|
118
|
+
stderr diagnostic has the fixed `STDIO_INVALID_MESSAGE` code and a generic message; it never
|
|
119
|
+
interpolates caller-controlled frame content. A later valid frame may continue on the local
|
|
120
|
+
connection.
|
|
121
|
+
|
|
122
|
+
## Source and artifact privacy
|
|
123
|
+
|
|
124
|
+
Stdio inherits the local process user's access but still applies the configured roots. A remote deployment can access only paths mounted and registered on the server; it cannot reach a client computer. Do not mount a home directory or an entire game library when one read-only game root and selected workspaces suffice.
|
|
125
|
+
|
|
126
|
+
On POSIX, the server enforces mode `0700` on the state root and `0600` on the journal key. Node does
|
|
127
|
+
not provide a portable Windows DACL authoring API, so Windows operators must provision the state
|
|
128
|
+
root ACL for the dedicated server account; the server still rejects a linked/non-regular key and
|
|
129
|
+
inherits that operator ACL. A hostile operating-system principal that can read the key or replace
|
|
130
|
+
state-root entries remains outside the documented filesystem trust boundary.
|
|
131
|
+
|
|
132
|
+
Raw installed-game or dependency sprite, font, and bitmap files are never registered as downloadable resources. Structured JSON evidence strips embedded raster and glyph payloads, retaining only source-linked hashes, paths, frame and dimension metadata. Composite SVG/PNG reviews may contain processed frames or glyphs required to inspect the requested render, but remain generated, authorization-checked workspace evidence rather than raw asset-file resources. Transaction evidence may contain authorized mod-source before/proposed text and diffs; every artifact remains bound to the workspace principal.
|
|
133
|
+
|
|
134
|
+
The runtime sends no telemetry or analytics. Its only outbound network request is OAuth JWT-key retrieval from the administrator-configured JWKS endpoint; stdio and static-token loopback deployments require no runtime network access.
|
|
135
|
+
|
|
136
|
+
The product never launches, automates, controls, or captures Hearts of Iron IV. Every preview is
|
|
137
|
+
an offline tool-generated render, not a game screenshot or evidence of in-engine behavior.
|
|
138
|
+
|
|
139
|
+
Vulnerabilities should be reported through GitHub private vulnerability reporting as described in the root [security policy](../SECURITY.md).
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Self-hosting Streamable HTTP
|
|
2
|
+
|
|
3
|
+
The server exposes one stateful MCP endpoint at `/mcp` for POST and GET, plus DELETE session termination. It does not provide legacy SSE-only transport.
|
|
4
|
+
|
|
5
|
+
## Loopback
|
|
6
|
+
|
|
7
|
+
Set a random token of at least 32 characters in the environment named by config:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
export HOI4_AGENT_HTTP_TOKEN='replace-with-a-random-secret'
|
|
11
|
+
HOI4_AGENT_CONFIG=/srv/hoi4/config.json hoi4-agent-tools-http
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Keep `host` as `127.0.0.1`. The client sends `Authorization: Bearer ...`. Present origins still need to match `allowedOrigins`.
|
|
15
|
+
|
|
16
|
+
The HTTP process refuses to start if a configured token environment variable is missing, shorter
|
|
17
|
+
than 32 characters, or has the same secret value as another configured token. Static tokens and
|
|
18
|
+
OAuth are mutually exclusive deployment modes.
|
|
19
|
+
|
|
20
|
+
## Public/team deployment
|
|
21
|
+
|
|
22
|
+
Public mode—either a non-loopback listener or a non-loopback `publicUrl` in front of a loopback/private listener—refuses to start unless:
|
|
23
|
+
|
|
24
|
+
- `publicUrl` is an HTTPS origin or exact `/mcp` endpoint and contains no credentials, path prefix, query, or fragment;
|
|
25
|
+
- OAuth/OIDC JWT validation is configured;
|
|
26
|
+
- the OAuth issuer, JWKS, and every authorization-server URL use HTTPS;
|
|
27
|
+
- at least one origin is allowlisted;
|
|
28
|
+
- principal/workspace grants are configured.
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"http": {
|
|
33
|
+
"host": "0.0.0.0",
|
|
34
|
+
"port": 3210,
|
|
35
|
+
"publicUrl": "https://mcp.example.test",
|
|
36
|
+
"allowedOrigins": ["https://agent.example.test"],
|
|
37
|
+
"trustedProxyAddresses": ["10.20.0.5"],
|
|
38
|
+
"tokens": [],
|
|
39
|
+
"principals": [
|
|
40
|
+
{ "principal": "user-subject", "workspaceIds": ["example"], "allowRegistration": false }
|
|
41
|
+
],
|
|
42
|
+
"oauth": {
|
|
43
|
+
"issuer": "https://issuer.example.test/",
|
|
44
|
+
"jwksUri": "https://issuer.example.test/.well-known/jwks.json",
|
|
45
|
+
"audience": "https://mcp.example.test/mcp",
|
|
46
|
+
"authorizationServers": ["https://issuer.example.test/"],
|
|
47
|
+
"requiredScopes": ["hoi4:read"],
|
|
48
|
+
"algorithms": ["RS256"]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The server is an OAuth resource server, not an authorization server. Protected Resource Metadata is served at the standard well-known paths and its endpoint-specific URL is included in 401 and insufficient-scope 403 challenges. Baseline access uses the configured `requiredScopes`; transaction planning, registration, apply, and rollback additionally require `hoi4:write`. Each MCP session is bound to the exact bearer credential that initialized it, not only to mutable subject/client claims. A refreshed or step-up token must initialize a new MCP session; the previous session remains bound to its original credential and expires no later than that credential's `exp`. The server retains only a SHA-256 credential identifier, never the raw token. Static-token sessions keep the configured sliding inactivity lifetime. Terminate TLS at a trusted reverse proxy, preserve Authorization/Origin/Host headers, and do not make a session ID a bearer credential.
|
|
55
|
+
|
|
56
|
+
### Reverse-proxy boundary
|
|
57
|
+
|
|
58
|
+
`trustedProxyAddresses` is not a general proxy switch; it affects only the pre-auth rate-limit
|
|
59
|
+
address and does not trust forwarded host or protocol metadata. Each entry is one exact IPv4 or
|
|
60
|
+
IPv6 address as it appears for the direct socket peer; CIDR ranges and hostnames are rejected. An
|
|
61
|
+
IPv4-mapped IPv6 peer is normalized to IPv4 for matching. When the peer is not an exact match, the
|
|
62
|
+
application ignores `X-Forwarded-For` and rate-limits the socket address. When it is a match, the
|
|
63
|
+
application requires a valid `X-Forwarded-For` value and uses its first comma-separated IP.
|
|
64
|
+
|
|
65
|
+
The edge proxy must therefore:
|
|
66
|
+
|
|
67
|
+
- be the only network path to the server port, enforced by a private bind/network and firewall;
|
|
68
|
+
- terminate TLS for the HTTPS `publicUrl`;
|
|
69
|
+
- remove any client-supplied forwarding chain and set the first `X-Forwarded-For` value to a
|
|
70
|
+
validated originating client IP;
|
|
71
|
+
- preserve the bearer `Authorization` header, the original `Origin`, and a `Host` accepted by the
|
|
72
|
+
configured bind host or `publicUrl`;
|
|
73
|
+
- enforce its own connection, header-size, body-size, header/request/idle timeout, and pre-auth
|
|
74
|
+
rate ceilings before forwarding.
|
|
75
|
+
|
|
76
|
+
Do not configure a load-balancer subnet and expect range matching, and do not allow clients to
|
|
77
|
+
bypass the named proxy. For multiple proxy hops, use an edge-controlled normalization point that
|
|
78
|
+
delivers one trustworthy first address to the directly connected trusted peer.
|
|
79
|
+
|
|
80
|
+
### Admission, sessions, and streams
|
|
81
|
+
|
|
82
|
+
Before authentication, the application enforces Node connection/request timeouts and socket
|
|
83
|
+
ceilings, then reserves one `maxConcurrentRequests` slot and applies a fixed-minute
|
|
84
|
+
`requestsPerMinute` bucket to the resolved client address. Every POST must advertise exact,
|
|
85
|
+
unparameterized positive-quality `application/json` and `text/event-stream` response ranges, use exact
|
|
86
|
+
`application/json` request media with an absent or `utf-8` charset, and use identity content
|
|
87
|
+
encoding. GET must advertise exact positive-quality `text/event-stream`. JSON is fatal-decoded as
|
|
88
|
+
UTF-8 and parsed under the raw-wire `maxBodyBytes` ceiling before SDK dispatch. Suffix types,
|
|
89
|
+
duplicate/malformed parameters, encoded entities, invalid UTF-8, and parameter-only media mentions
|
|
90
|
+
are rejected.
|
|
91
|
+
|
|
92
|
+
Before those checks, the server counts security-sensitive fields in the raw header list rather
|
|
93
|
+
than trusting Node's first-value normalization. Duplicate Host, Authorization, Origin,
|
|
94
|
+
Content-Type, Content-Encoding, forwarding identity, or MCP session/protocol fields are rejected.
|
|
95
|
+
For an absolute-form request target, its allowlisted authority must exactly match Host; an allowed
|
|
96
|
+
Host cannot conceal an untrusted request-target authority.
|
|
97
|
+
After authentication, a separate fixed-minute bucket is applied to the principal. Host and any
|
|
98
|
+
present Origin are checked before admission. These in-process controls complement, rather than
|
|
99
|
+
replace, the edge limits above.
|
|
100
|
+
|
|
101
|
+
`maxConcurrentRequests` cannot exceed two, and its product with `maxBodyBytes` cannot exceed
|
|
102
|
+
16 MiB. The fixed concurrency ceiling also bounds simultaneous offline render allocations; raise
|
|
103
|
+
edge capacity by running isolated server instances, not by removing the per-process safety bound.
|
|
104
|
+
|
|
105
|
+
Session initialization is refused when either the global `maxSessions` or
|
|
106
|
+
`maxSessionsPerPrincipal` count (including initializations in progress) is full. Resumable GET
|
|
107
|
+
streams use `maxEventStreams` and `maxEventStreamsPerPrincipal`; an accepted long-lived stream
|
|
108
|
+
releases the ordinary request-concurrency slot. Each session retains at most 1,000 replay events,
|
|
109
|
+
`maxSessionEventBytes`, and the shared `maxEventStoreBytes`, for no longer than
|
|
110
|
+
`sessionTtlSeconds`. Old per-session history is evicted first. A new event that cannot fit the
|
|
111
|
+
shared budget is not retained for replay and does not evict another session's history.
|
|
112
|
+
|
|
113
|
+
Principal grants isolate tool, resource, session, and transaction access within one deployment. Run separate least-privilege server instances or containers for mutually distrustful teams or operating-system trust domains; do not treat application-level grants as an OS sandbox.
|
|
114
|
+
|
|
115
|
+
Runtime registration has two operator capabilities. `registrationRoots` permits read-only source
|
|
116
|
+
selection. A caller-declared mod root additionally must be under the default-empty
|
|
117
|
+
`writableRegistrationRoots` list, even when source apply is disabled, because mod registration
|
|
118
|
+
creates generated storage. Never place a game or dependency directory under a writable
|
|
119
|
+
registration root. Granting `allowRegistration` exposes every otherwise-unclaimed source beneath
|
|
120
|
+
these capability roots to that principal; prefer static registrations or separate instances for
|
|
121
|
+
mutually distrustful users.
|
|
122
|
+
|
|
123
|
+
Runtime artifact storage must support same-volume hard links so the server can create persistent
|
|
124
|
+
owner claims without replacement races. Transaction deployments additionally require an isolated,
|
|
125
|
+
persistent `serverStateRoot` on a filesystem with hard-link and atomic-replacement support. Do not
|
|
126
|
+
place it beneath any source, capability, artifact, cache, fixture, or `storageRoots` directory.
|
|
127
|
+
|
|
128
|
+
## Container
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
docker build -t hoi4-agent-tools:0.1.2 .
|
|
132
|
+
docker run --read-only --rm -p 127.0.0.1:3210:3210 \
|
|
133
|
+
-e HOI4_AGENT_CONFIG=/config/config.json \
|
|
134
|
+
-v /srv/hoi4/config:/config:ro \
|
|
135
|
+
-v /srv/hoi4/game:/srv/hoi4/game:ro \
|
|
136
|
+
-v /srv/hoi4/workspaces:/srv/hoi4/workspaces \
|
|
137
|
+
-v /var/lib/hoi4-agent-tools:/var/lib/hoi4-agent-tools \
|
|
138
|
+
-v /var/lib/hoi4-agent-tools-state:/var/lib/hoi4-agent-tools-state \
|
|
139
|
+
hoi4-agent-tools:0.1.2
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Port publishing reaches the container through a non-loopback interface. The mounted configuration
|
|
143
|
+
for this form must therefore use the public/team OAuth policy above: bind `0.0.0.0`, declare the
|
|
144
|
+
canonical HTTPS `publicUrl`, allowlist the coding-agent origin, and validate OAuth access tokens.
|
|
145
|
+
Terminate TLS at the configured reverse proxy. Mapping the host port only to `127.0.0.1` limits host
|
|
146
|
+
exposure but does not turn the container-side listener into loopback, so it does not permit static
|
|
147
|
+
bearer tokens.
|
|
148
|
+
|
|
149
|
+
When writes are enabled, set `serverStateRoot` to `/var/lib/hoi4-agent-tools-state` in this example.
|
|
150
|
+
Keep that mount persistent across restarts and protect it for the dedicated server account. It is a
|
|
151
|
+
separate mount because a state root may not overlap `/var/lib/hoi4-agent-tools` when that path is a
|
|
152
|
+
configured generated-storage capability.
|
|
153
|
+
|
|
154
|
+
On Linux, a local-only static-token deployment may instead use `--network host` with the configured
|
|
155
|
+
listener kept at `127.0.0.1`; do not combine that mode with `-p`. Host networking changes the
|
|
156
|
+
container isolation boundary and is not portable to every Docker host, so review it explicitly
|
|
157
|
+
before use.
|
|
158
|
+
|
|
159
|
+
Do not mount a developer's home directory. A remote server sees only server-side mounts; the MCP client does not tunnel local files.
|
|
160
|
+
|
|
161
|
+
If a configured workspace has `kind: "game"` or `kind: "dependency"`, mount a separate writable
|
|
162
|
+
operator-owned generated-data directory, list its parent in `storageRoots`, and set both
|
|
163
|
+
`artifactRoot` and `cacheRoot` beneath it. Never make the installed-game or dependency source
|
|
164
|
+
mount writable merely to hold generated state. Mod workspaces may instead use their confined
|
|
165
|
+
`<mod>/.hoi4-agent/artifacts` and `<mod>/.hoi4-agent/cache` defaults.
|
|
166
|
+
|
|
167
|
+
The server does not launch or capture Hearts of Iron IV. A self-hosted deployment needs filesystem
|
|
168
|
+
access only; it does not need a desktop session, Steam automation, or game-process permissions.
|