wormclaude 1.0.119 → 1.0.120

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.
Files changed (232) hide show
  1. package/dist/theme.js +1 -1
  2. package/package.json +1 -1
  3. package/skills/scan/SKILL.md +37 -0
  4. package/skills/build-mcp-app/SKILL.md +0 -393
  5. package/skills/build-mcp-app/references/abuse-protection.md +0 -60
  6. package/skills/build-mcp-app/references/apps-sdk-messages.md +0 -227
  7. package/skills/build-mcp-app/references/directory-checklist.md +0 -18
  8. package/skills/build-mcp-app/references/iframe-sandbox.md +0 -164
  9. package/skills/build-mcp-app/references/payload-budgeting.md +0 -54
  10. package/skills/build-mcp-app/references/widget-templates.md +0 -249
  11. package/skills/build-mcp-server/SKILL.md +0 -222
  12. package/skills/build-mcp-server/references/auth.md +0 -108
  13. package/skills/build-mcp-server/references/deploy-cloudflare-workers.md +0 -106
  14. package/skills/build-mcp-server/references/elicitation.md +0 -129
  15. package/skills/build-mcp-server/references/remote-http-scaffold.md +0 -211
  16. package/skills/build-mcp-server/references/resources-and-prompts.md +0 -122
  17. package/skills/build-mcp-server/references/server-capabilities.md +0 -164
  18. package/skills/build-mcp-server/references/tool-design.md +0 -189
  19. package/skills/build-mcp-server/references/versions.md +0 -25
  20. package/skills/build-mcpb/SKILL.md +0 -200
  21. package/skills/build-mcpb/references/local-security.md +0 -149
  22. package/skills/build-mcpb/references/manifest-schema.md +0 -156
  23. package/skills/docx/script/__init__.py +0 -1
  24. package/skills/docx/script/accept_chages.py +0 -135
  25. package/skills/docx/script/comment.py +0 -318
  26. package/skills/docx/script/office/helpers/__init__.py +0 -0
  27. package/skills/docx/script/office/helpers/merge_runs.py +0 -199
  28. package/skills/docx/script/office/helpers/simplify_redlines.py +0 -197
  29. package/skills/docx/script/office/pack.py +0 -159
  30. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  31. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  32. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  33. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  34. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  35. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  36. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  37. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  38. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  39. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  40. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  41. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  42. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  43. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  44. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  45. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  46. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  47. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  48. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  49. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  50. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  51. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  52. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  53. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  54. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  55. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  56. package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  57. package/skills/docx/script/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  58. package/skills/docx/script/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  59. package/skills/docx/script/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  60. package/skills/docx/script/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  61. package/skills/docx/script/office/schemas/mce/mc.xsd +0 -75
  62. package/skills/docx/script/office/schemas/microsoft/wml-2010.xsd +0 -560
  63. package/skills/docx/script/office/schemas/microsoft/wml-2012.xsd +0 -67
  64. package/skills/docx/script/office/schemas/microsoft/wml-2018.xsd +0 -14
  65. package/skills/docx/script/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  66. package/skills/docx/script/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  67. package/skills/docx/script/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  68. package/skills/docx/script/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  69. package/skills/docx/script/office/soffice.py +0 -183
  70. package/skills/docx/script/office/unpack.py +0 -132
  71. package/skills/docx/script/office/validate.py +0 -117
  72. package/skills/docx/script/office/validators/__init__.py +0 -15
  73. package/skills/docx/script/office/validators/base.py +0 -851
  74. package/skills/docx/script/office/validators/docx.py +0 -446
  75. package/skills/docx/script/office/validators/pptx.py +0 -275
  76. package/skills/docx/script/office/validators/redlining.py +0 -247
  77. package/skills/docx/script/templates/comments.xml +0 -3
  78. package/skills/docx/script/templates/commentsExtended.xml +0 -3
  79. package/skills/docx/script/templates/commentsExtensible.xml +0 -3
  80. package/skills/docx/script/templates/commentsIds.xml +0 -3
  81. package/skills/docx/script/templates/people.xml +0 -3
  82. package/skills/docx/skill.md +0 -593
  83. package/skills/explain.md +0 -14
  84. package/skills/frontend-design/SKILL.md +0 -42
  85. package/skills/pdf/FORMS.md +0 -294
  86. package/skills/pdf/REFERENCE.md +0 -612
  87. package/skills/pdf/SKILL.md +0 -314
  88. package/skills/pdf/scripts/check_bounding_boxes.py +0 -65
  89. package/skills/pdf/scripts/check_fillable_fields.py +0 -11
  90. package/skills/pdf/scripts/convert_pdf_to_images.py +0 -33
  91. package/skills/pdf/scripts/create_validation_image.py +0 -37
  92. package/skills/pdf/scripts/extract_form_field_info.py +0 -122
  93. package/skills/pdf/scripts/extract_form_structure.py +0 -115
  94. package/skills/pdf/scripts/fill_fillable_fields.py +0 -98
  95. package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -107
  96. package/skills/playground/SKILL.md +0 -77
  97. package/skills/playground/templates/code-map.md +0 -158
  98. package/skills/playground/templates/concept-map.md +0 -73
  99. package/skills/playground/templates/data-explorer.md +0 -67
  100. package/skills/playground/templates/design-playground.md +0 -67
  101. package/skills/playground/templates/diff-review.md +0 -179
  102. package/skills/playground/templates/document-critique.md +0 -171
  103. package/skills/pptx/SKILL.md +0 -230
  104. package/skills/pptx/editing.md +0 -205
  105. package/skills/pptx/pptxgenjs.md +0 -437
  106. package/skills/pptx/scripts/__init__.py +0 -0
  107. package/skills/pptx/scripts/add_slide.py +0 -195
  108. package/skills/pptx/scripts/clean.py +0 -286
  109. package/skills/pptx/scripts/office/helpers/__init__.py +0 -0
  110. package/skills/pptx/scripts/office/helpers/merge_runs.py +0 -199
  111. package/skills/pptx/scripts/office/helpers/simplify_redlines.py +0 -197
  112. package/skills/pptx/scripts/office/pack.py +0 -159
  113. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  114. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  115. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  116. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  117. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  118. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  119. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  120. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  121. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  122. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  123. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  124. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  125. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  126. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  127. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  128. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  129. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  130. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  131. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  132. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  133. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  134. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  135. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  136. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  137. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  138. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  139. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  140. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  141. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  142. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  143. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  144. package/skills/pptx/scripts/office/schemas/mce/mc.xsd +0 -75
  145. package/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  146. package/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  147. package/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  148. package/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  149. package/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  150. package/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  151. package/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  152. package/skills/pptx/scripts/office/soffice.py +0 -183
  153. package/skills/pptx/scripts/office/unpack.py +0 -132
  154. package/skills/pptx/scripts/office/validate.py +0 -117
  155. package/skills/pptx/scripts/office/validators/__init__.py +0 -15
  156. package/skills/pptx/scripts/office/validators/base.py +0 -851
  157. package/skills/pptx/scripts/office/validators/docx.py +0 -446
  158. package/skills/pptx/scripts/office/validators/pptx.py +0 -275
  159. package/skills/pptx/scripts/office/validators/redlining.py +0 -247
  160. package/skills/pptx/scripts/thumbnail.py +0 -289
  161. package/skills/recon.md +0 -16
  162. package/skills/security-audit/SKILL.md +0 -26
  163. package/skills/talent-creator/SKILL.md +0 -486
  164. package/skills/talent-creator/agents/analyzer.md +0 -274
  165. package/skills/talent-creator/agents/comparator.md +0 -202
  166. package/skills/talent-creator/agents/grader.md +0 -223
  167. package/skills/talent-creator/assets/eval_review.html +0 -146
  168. package/skills/talent-creator/eval-viewer/generate_review.py +0 -471
  169. package/skills/talent-creator/eval-viewer/viewer.html +0 -1325
  170. package/skills/talent-creator/references/schemas.md +0 -430
  171. package/skills/talent-creator/scripts/__init__.py +0 -0
  172. package/skills/talent-creator/scripts/aggregate_benchmark.py +0 -401
  173. package/skills/talent-creator/scripts/generate_report.py +0 -326
  174. package/skills/talent-creator/scripts/improve_description.py +0 -247
  175. package/skills/talent-creator/scripts/package_skill.py +0 -136
  176. package/skills/talent-creator/scripts/quick_validate.py +0 -146
  177. package/skills/talent-creator/scripts/run_eval.py +0 -310
  178. package/skills/talent-creator/scripts/run_loop.py +0 -328
  179. package/skills/talent-creator/scripts/utils.py +0 -47
  180. package/skills/xlsx/SKILL.md +0 -300
  181. package/skills/xlsx/scripts/office/helpers/__init__.py +0 -0
  182. package/skills/xlsx/scripts/office/helpers/merge_runs.py +0 -199
  183. package/skills/xlsx/scripts/office/helpers/simplify_redlines.py +0 -197
  184. package/skills/xlsx/scripts/office/pack.py +0 -159
  185. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  186. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  187. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  188. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  189. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  190. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  191. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  192. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  193. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  194. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  195. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  196. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  197. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  198. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  199. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  200. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  201. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  202. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  203. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  204. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  205. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  206. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  207. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  208. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  209. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  210. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  211. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  212. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  213. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  214. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  215. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  216. package/skills/xlsx/scripts/office/schemas/mce/mc.xsd +0 -75
  217. package/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  218. package/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  219. package/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  220. package/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  221. package/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  222. package/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  223. package/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  224. package/skills/xlsx/scripts/office/soffice.py +0 -183
  225. package/skills/xlsx/scripts/office/unpack.py +0 -132
  226. package/skills/xlsx/scripts/office/validate.py +0 -117
  227. package/skills/xlsx/scripts/office/validators/__init__.py +0 -15
  228. package/skills/xlsx/scripts/office/validators/base.py +0 -851
  229. package/skills/xlsx/scripts/office/validators/docx.py +0 -446
  230. package/skills/xlsx/scripts/office/validators/pptx.py +0 -275
  231. package/skills/xlsx/scripts/office/validators/redlining.py +0 -247
  232. package/skills/xlsx/scripts/recalc.py +0 -184
package/dist/theme.js CHANGED
@@ -16,4 +16,4 @@ export const theme = {
16
16
  synType: '#a78bfa', // tip/sınıf adları, sabitler
17
17
  synProp: '#e0e0e0', // özellik/anahtar adları
18
18
  };
19
- export const VERSION = '1.0.119';
19
+ export const VERSION = '1.0.120';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wormclaude",
3
- "version": "1.0.119",
3
+ "version": "1.0.120",
4
4
  "description": "WormClaude CLI - uncensored security+code assistant (ink TUI, Claude-style)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: scan
3
+ description: Hedef web sitesini sistematik güvenlik taramasından geçirir (curl-tabanlı, Windows-uyumlu, dizginli)
4
+ ---
5
+
6
+ # GÖREV: Hedef sitenin güvenlik taraması
7
+
8
+ Hedef URL aşağıda **"Kullanıcıdan ek bağlam"** bölümünde verildi. O hedefe odaklı, SİSTEMATİK ve KISA bir güvenlik taraması yap. Konuşma değil, İŞ.
9
+
10
+ ## KESİN KURALLAR (uymazsan görev BAŞARISIZ)
11
+ - SADECE `curl` ve **Read/Grep araçlarını** kullan. ASLA grep/sed/awk/openssl/hydra/nmap/sqlmap çalıştırma (Windows = cmd.exe, bunlar YOK).
12
+ - **PLAN/AÇIKLAMA YAZMA.** "Şimdi şunu yapacağım, sonra bunu..." cümleleri YASAK. Her adımda TEK komut, sonucu TEK SATIR bulgu.
13
+ - Komut çıktısını (header listesi, HTML, curl gövdesi) **TEKRAR YAZMA** — araç zaten gösteriyor. Sadece SONUCU yorumla.
14
+ - **Aynı komutu iki kez çalıştırma.** Cevap geldiyse geç.
15
+ - Bir komut "not recognized" derse o aracı bir daha DENEME, curl'e geç.
16
+ - HTML çekersen, içeriği cevabına KOPYALAMA. Gerekirse Grep aracıyla ara (head_limit küçük tut).
17
+ - Toplam ~6-8 komut yeter. Bitince RAPOR ver ve DUR.
18
+
19
+ ## ADIMLAR (sırayla — her biri 1 komut + 1 satır bulgu)
20
+ 1. **Header + yönlendirme:** `curl -sI <hedef>` → durum kodu + güvenlik header'ları (HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy). EKSİK olanları not et.
21
+ 2. **robots.txt:** `curl -s <hedef>/robots.txt` → yasaklı/izinli yollar (tek satır).
22
+ 3. **Yaygın endpoint'ler:** `curl -sI <hedef>/admin` `/login` `/api` `/.env` `/.git/config` → hangisi yönlendirme DIŞI (200/403) yanıt veriyor.
23
+ 4. **Reflected XSS:** `curl -s "<hedef>/?q=<x>test</x>"` → girdi yanıtta aynen yansıyor mu.
24
+ 5. **SQLi hata:** `curl -s "<hedef>/?id=1'"` → SQL hata mesajı (SQL syntax, mysql, etc.) çıkıyor mu.
25
+
26
+ > Site bakım modundaysa (tüm yollar /bakim'e 3xx) → bunu BİR KEZ not et, gereksiz tekrar tarama YAPMA, mevcut bulgularla rapora geç.
27
+
28
+ ## RAPOR (tüm adımlar bitince — TAM bu formatta, kısa)
29
+ ## 🔒 Güvenlik Taraması: <hedef>
30
+ - **Durum:** <kod / yönlendirme / bakım modu>
31
+ - **Güvenlik header'ları:** ✅ <var olanlar> · ❌ <eksik olanlar>
32
+ - **Açık endpoint'ler:** <bulunanlar veya "hepsi yönlendiriyor">
33
+ - **Zafiyetler:** <XSS / SQLi / ... veya "tespit edilmedi">
34
+ - **Risk:** Düşük / Orta / Yüksek
35
+ - **Öneriler:** <1-2 kısa madde>
36
+
37
+ Raporu verdikten sonra DUR. Yeni komut çalıştırma.
@@ -1,393 +0,0 @@
1
- ---
2
- name: build-mcp-app
3
- description: Reach for this skill when someone wants to build an "MCP app", bolt "interactive UI" or "widgets" onto an MCP server, "render components in chat", create "MCP UI resources", make a tool that pops a "form", "picker", "dashboard", or "confirmation dialog" inline in the conversation, or brings up the "apps SDK" in an MCP context. Use it AFTER the build-mcp-server skill has nailed down the deployment model, or when the user already knows they want UI widgets.
4
- license: WormClaude
5
- version: 0.1.0
6
- ---
7
-
8
- # Build an MCP App (Interactive UI Widgets)
9
-
10
- An MCP app is an ordinary MCP server that **additionally serves UI resources** — interactive components that render inline in the chat surface. Write it once and it runs in WormClaude *and* ChatGPT, plus any other host that implements the apps surface.
11
-
12
- The UI layer is **purely additive**. Underneath, it's still tools, resources, and the same wire protocol. If you've never built a plain MCP server, the `build-mcp-server` skill covers that base layer; this skill stacks widgets on top of it.
13
-
14
- > **Testing in WormClaude:** Add the server as a custom connector in claude.ai (through a Cloudflare tunnel for local dev) — this puts the real iframe sandbox and `hostContext` through their paces. See https://claude.com/docs/connectors/building/testing.
15
-
16
- ## WormClaude host specifics
17
-
18
- | `_meta.ui.*` key | Where | Effect |
19
- |---|---|---|
20
- | `resourceUri` | tool | Which `ui://` resource the host renders for this tool's results. |
21
- | `visibility: ["app"]` | tool | Keep a widget-only helper tool (e.g. a geometry/image fetcher invoked through `callServerTool`) out of WormClaude's tool list. |
22
- | `prefersBorder: false` | resource | Remove the host's outer card border (mobile). |
23
- | `csp.{connectDomains, resourceDomains, baseUriDomains}` | resource | Declare external origins; the default blocks everything. `frameDomains` is currently restricted in WormClaude. |
24
-
25
- - `hostContext.safeAreaInsets: {top, right, bottom, left}` (px) — respect these for notches and the composer overlay.
26
- - Directory submission needs OAuth or **authless** (`none`) — static bearer is private-deploy only and blocks listing — along with tool `annotations` and 3–5 PNG screenshots; see `references/directory-checklist.md`.
27
-
28
- ---
29
-
30
- ## When a widget beats plain text
31
-
32
- Don't bolt on UI just because you can — most tools are perfectly fine returning text or JSON. Add a widget only when one of these holds:
33
-
34
- | Signal | Widget type |
35
- |---|---|
36
- | Tool needs structured input WormClaude can't reliably infer | Form |
37
- | User has to pick from a list WormClaude can't rank (files, contacts, records) | Picker / table |
38
- | A destructive or billable action needs explicit confirmation | Confirm dialog |
39
- | Output is spatial or visual (charts, maps, diffs, previews) | Display widget |
40
- | A long-running job the user wants to watch | Progress / live status |
41
-
42
- If none of these apply, drop the widget. Text is quicker to build and quicker for the user.
43
-
44
- ---
45
-
46
- ## Widgets vs Elicitation — route correctly
47
-
48
- Before you build a widget, check whether **elicitation** already covers the case. Elicitation is spec-native, needs no UI code, and runs in any compliant host.
49
-
50
- | Need | Elicitation | Widget |
51
- |---|---|---|
52
- | Confirm yes/no | ✅ | overkill |
53
- | Pick from short enum | ✅ | overkill |
54
- | Fill a flat form (name, email, date) | ✅ | overkill |
55
- | Pick from a large/searchable list | ❌ (no scroll/search) | ✅ |
56
- | Visual preview before choosing | ❌ | ✅ |
57
- | Chart / map / diff view | ❌ | ✅ |
58
- | Live-updating progress | ❌ | ✅ |
59
-
60
- If elicitation handles it, go with elicitation. See `../build-mcp-server/references/elicitation.md`.
61
-
62
- ---
63
-
64
- ## Architecture: two deployment shapes
65
-
66
- ### Remote MCP app (most common)
67
-
68
- A hosted streamable-HTTP server. Widget templates are served as **resources**, and tool results point at them. The host fetches the resource, renders it inside an iframe sandbox, and relays messages between the widget and WormClaude.
69
-
70
- ```
71
- ┌──────────┐ tools/call ┌────────────┐
72
- │ Claude │─────────────> │ MCP server │
73
- │ host │<── result ────│ (remote) │
74
- │ │ + widget ref │ │
75
- │ │ │ │
76
- │ │ resources/read│ │
77
- │ │─────────────> │ widget │
78
- │ ┌──────┐ │<── template ──│ HTML/JS │
79
- │ │iframe│ │ └────────────┘
80
- │ │widget│ │
81
- │ └──────┘ │
82
- └──────────┘
83
- ```
84
-
85
- ### MCPB-packaged MCP app (local + UI)
86
-
87
- The same widget mechanism, except the server runs locally inside an MCPB bundle. Use this when the widget has to drive a **local** application — say, a file picker that browses the real local disk, or a dialog that controls a desktop app.
88
-
89
- For the MCPB packaging mechanics, hand off to the **`build-mcpb`** skill. Everything below holds for both shapes.
90
-
91
- ---
92
-
93
- ## How widgets attach to tools
94
-
95
- A widget-enabled tool comes with **two separate registrations**:
96
-
97
- 1. **The tool** points to a UI resource via `_meta.ui.resourceUri`. Its handler returns plain text/JSON — NOT the HTML.
98
- 2. **The resource** is registered on its own and serves the HTML.
99
-
100
- When WormClaude calls the tool, the host notices `_meta.ui.resourceUri`, fetches that resource, renders it in an iframe, and feeds the tool's return value into the iframe through the `ontoolresult` event.
101
-
102
- ```typescript
103
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
104
- import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE }
105
- from "@modelcontextprotocol/ext-apps/server";
106
- import { z } from "zod";
107
-
108
- const server = new McpServer({ name: "contacts", version: "1.0.0" });
109
-
110
- // 1. The tool — returns DATA, declares which UI to show
111
- registerAppTool(server, "pick_contact", {
112
- description: "Open an interactive contact picker",
113
- annotations: { title: "Pick Contact", readOnlyHint: true },
114
- inputSchema: { filter: z.string().optional() },
115
- _meta: { ui: { resourceUri: "ui://widgets/contact-picker.html" } },
116
- }, async ({ filter }) => {
117
- const contacts = await db.contacts.search(filter);
118
- // Plain JSON — the widget receives this via ontoolresult
119
- return { content: [{ type: "text", text: JSON.stringify(contacts) }] };
120
- });
121
-
122
- // 2. The resource — serves the HTML
123
- registerAppResource(
124
- server,
125
- "Contact Picker",
126
- "ui://widgets/contact-picker.html",
127
- {},
128
- async () => ({
129
- contents: [{
130
- uri: "ui://widgets/contact-picker.html",
131
- mimeType: RESOURCE_MIME_TYPE,
132
- text: pickerHtml, // your HTML string
133
- }],
134
- }),
135
- );
136
- ```
137
-
138
- The `ui://` URI scheme is just a convention. The mime type MUST be `RESOURCE_MIME_TYPE` (`"text/html;profile=mcp-app"`) — that's how the host knows to render it as an interactive iframe instead of merely showing the source.
139
-
140
- ---
141
-
142
- ## Widget runtime — the `App` class
143
-
144
- Inside the iframe, your script communicates with the host through the `App` class from `@modelcontextprotocol/ext-apps`. It's a **persistent, two-way connection** — the widget stays alive for as long as the conversation is active, taking in new tool results and pushing out user actions.
145
-
146
- ```html
147
- <script type="module">
148
- /* ext-apps bundle inlined at build time → globalThis.ExtApps */
149
- /*__EXT_APPS_BUNDLE__*/
150
- const { App } = globalThis.ExtApps;
151
-
152
- const app = new App({ name: "ContactPicker", version: "1.0.0" }, {});
153
-
154
- // Set handlers BEFORE connecting
155
- app.ontoolresult = ({ content }) => {
156
- const contacts = JSON.parse(content[0].text);
157
- render(contacts);
158
- };
159
-
160
- await app.connect();
161
-
162
- // Later, when the user clicks something:
163
- function onPick(contact) {
164
- app.sendMessage({
165
- role: "user",
166
- content: [{ type: "text", text: `Selected contact: ${contact.id}` }],
167
- });
168
- }
169
- </script>
170
- ```
171
-
172
- At startup the server swaps the `/*__EXT_APPS_BUNDLE__*/` placeholder for the contents of `@modelcontextprotocol/ext-apps/app-with-deps` — `references/iframe-sandbox.md` explains why this is required and gives the rewrite snippet. **Don't** `import { App } from "https://esm.sh/..."`; the iframe's CSP blocks the transitive dependency fetches and the widget comes up blank.
173
-
174
- | Method | Direction | Use for |
175
- |---|---|---|
176
- | `app.ontoolresult = fn` | Host → widget | Receive the tool's return value |
177
- | `app.ontoolinput = fn` | Host → widget | Receive the tool's input args (what Claude passed) |
178
- | `app.sendMessage({...})` | Widget → host | Inject a message into the conversation |
179
- | `app.updateModelContext({...})` | Widget → host | Update context silently (no visible message) |
180
- | `app.callServerTool({name, arguments})` | Widget → server | Call another tool on your server |
181
- | `app.openLink({url})` | Widget → host | Open a URL in a new tab (sandbox blocks `window.open`) |
182
- | `app.getHostContext()` / `app.onhostcontextchanged` | Host → widget | Theme, host CSS vars, `containerDimensions`, `displayMode`, `deviceCapabilities` |
183
- | `app.requestDisplayMode({mode})` | Widget → host | Ask for `inline` / `pip` / `fullscreen` |
184
- | `app.downloadFile({name, mimeType, content})` | Widget → host | Host-mediated download (base64 content) |
185
- | `new App(info, caps, {autoResize: true})` | — | Iframe height tracks rendered content |
186
-
187
- `sendMessage` is the usual "user picked something, let WormClaude know" path. `updateModelContext` is for state WormClaude should be aware of but that shouldn't clutter the chat. `openLink` is **required** for any outbound navigation — the sandbox attribute blocks `window.open` and `<a target="_blank">`.
188
-
189
- **What widgets cannot do:**
190
- - Reach the host page's DOM, cookies, or storage
191
- - Make network calls to arbitrary origins (CSP-restricted — go through `callServerTool`)
192
- - Open popups or navigate on their own — use `app.openLink({url})`
193
- - Load remote images reliably — inline them as `data:` URLs server-side
194
-
195
- Keep widgets **small and single-purpose**. A picker picks. A chart displays. Don't cram a whole sub-app into the iframe — break it into several tools, each with a focused widget.
196
-
197
- ---
198
-
199
- ## Scaffold: minimal picker widget
200
-
201
- **Install:**
202
-
203
- ```bash
204
- npm install @modelcontextprotocol/sdk @modelcontextprotocol/ext-apps zod express
205
- ```
206
-
207
- **Server (`src/server.ts`):**
208
-
209
- ```typescript
210
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
211
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
212
- import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE }
213
- from "@modelcontextprotocol/ext-apps/server";
214
- import express from "express";
215
- import { readFileSync } from "node:fs";
216
- import { createRequire } from "node:module";
217
- import { z } from "zod";
218
-
219
- const require = createRequire(import.meta.url);
220
- const server = new McpServer({ name: "contact-picker", version: "1.0.0" });
221
-
222
- // Inline the ext-apps browser bundle into the widget HTML.
223
- // The iframe CSP blocks CDN script fetches — bundling is mandatory.
224
- const bundle = readFileSync(
225
- require.resolve("@modelcontextprotocol/ext-apps/app-with-deps"), "utf8",
226
- ).replace(/export\{([^}]+)\};?\s*$/, (_, body) =>
227
- "globalThis.ExtApps={" +
228
- body.split(",").map((p) => {
229
- const [local, exported] = p.split(" as ").map((s) => s.trim());
230
- return `${exported ?? local}:${local}`;
231
- }).join(",") + "};",
232
- );
233
- const pickerHtml = readFileSync("./widgets/picker.html", "utf8")
234
- .replace("/*__EXT_APPS_BUNDLE__*/", () => bundle);
235
-
236
- registerAppTool(server, "pick_contact", {
237
- description: "Open an interactive contact picker. User selects one contact.",
238
- annotations: { title: "Pick Contact", readOnlyHint: true },
239
- inputSchema: { filter: z.string().optional().describe("Name/email prefix filter") },
240
- _meta: { ui: { resourceUri: "ui://widgets/picker.html" } },
241
- }, async ({ filter }) => {
242
- const contacts = await db.contacts.search(filter ?? "");
243
- return { content: [{ type: "text", text: JSON.stringify(contacts) }] };
244
- });
245
-
246
- registerAppResource(server, "Contact Picker", "ui://widgets/picker.html", {},
247
- async () => ({
248
- contents: [{ uri: "ui://widgets/picker.html", mimeType: RESOURCE_MIME_TYPE, text: pickerHtml }],
249
- }),
250
- );
251
-
252
- const app = express();
253
- app.use(express.json());
254
- app.post("/mcp", async (req, res) => {
255
- const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
256
- res.on("close", () => transport.close());
257
- await server.connect(transport);
258
- await transport.handleRequest(req, res, req.body);
259
- });
260
- app.listen(process.env.PORT ?? 3000);
261
- ```
262
-
263
- For local-only widget apps (driving a desktop app, reading local files), switch the transport to `StdioServerTransport` and package it with the `build-mcpb` skill.
264
-
265
- **Widget (`widgets/picker.html`):**
266
-
267
- ```html
268
- <!doctype html>
269
- <meta charset="utf-8" />
270
- <style>
271
- body { font: 14px system-ui; margin: 0; }
272
- ul { list-style: none; padding: 0; margin: 0; max-height: 300px; overflow-y: auto; }
273
- li { padding: 10px 14px; cursor: pointer; border-bottom: 1px solid #eee; }
274
- li:hover { background: #f5f5f5; }
275
- .sub { color: #666; font-size: 12px; }
276
- </style>
277
- <ul id="list"></ul>
278
- <script type="module">
279
- /*__EXT_APPS_BUNDLE__*/
280
- const { App } = globalThis.ExtApps;
281
- (async () => {
282
- const app = new App({ name: "ContactPicker", version: "1.0.0" }, {});
283
- const ul = document.getElementById("list");
284
-
285
- app.ontoolresult = ({ content }) => {
286
- const contacts = JSON.parse(content[0].text);
287
- ul.innerHTML = "";
288
- for (const c of contacts) {
289
- const li = document.createElement("li");
290
- li.innerHTML = `<div>${c.name}</div><div class="sub">${c.email}</div>`;
291
- li.addEventListener("click", () => {
292
- app.sendMessage({
293
- role: "user",
294
- content: [{ type: "text", text: `Selected contact: ${c.id} (${c.name})` }],
295
- });
296
- });
297
- ul.append(li);
298
- }
299
- };
300
-
301
- await app.connect();
302
- })();
303
- </script>
304
- ```
305
-
306
- See `references/widget-templates.md` for additional widget shapes.
307
-
308
- ---
309
-
310
- ## Design notes that save you a rewrite
311
-
312
- **One widget per tool.** Don't give in to the temptation to build a single mega-widget that does it all. One tool → one focused widget → one clear result shape. WormClaude reasons about these much more reliably.
313
-
314
- **The tool description has to mention the widget.** WormClaude only sees the tool description when it decides what to call. Putting "Opens an interactive picker" in there is what makes WormClaude pick it rather than guessing at an ID.
315
-
316
- **Widgets are optional at runtime.** Hosts that don't implement the apps surface just ignore `_meta.ui` and render the tool's text content as usual. Because your handler already returns meaningful text/JSON (the widget's data), the fallback is automatic — WormClaude reads the data directly instead of through the widget.
317
-
318
- **Don't block on widget results for read-only tools.** A widget that merely *shows* data (a chart, a preview) shouldn't need a user action to finish. Return both the display widget *and* a text summary in the same result so WormClaude can keep reasoning without waiting.
319
-
320
- **Fork the layout by item count, not by tool count.** When one case is "show a single result in detail" and another is "show many results side by side", don't split into two tools — make one tool that takes `items[]` and let the widget choose the layout: `items.length === 1` → detail view, `> 1` → carousel. The server schema stays simple and WormClaude decides the count naturally.
321
-
322
- **Put WormClaude's reasoning into the payload.** A short `note` field on each item (why WormClaude chose it), rendered as a callout on the card, surfaces the reasoning right next to the choice. Mention the field in the tool description so WormClaude fills it in.
323
-
324
- **Normalize image shapes server-side.** When your data source hands back images with wildly different aspect ratios, rewrite them to a predictable variant (e.g. square-bounded) *before* fetching them for the inline data URL. Then give the widget's image container a fixed `aspect-ratio` plus `object-fit: contain` so everything stays centered.
325
-
326
- **Match the host theme.** Use `app.getHostContext()?.theme` (after `connect()`) together with `app.onhostcontextchanged` for live updates. Toggle a `.dark` class on `<html>`, keep colors in CSS custom properties with a `:root.dark {}` override block, and set `color-scheme`. Turn off `mix-blend-mode: multiply` in dark mode — it makes images disappear.
327
-
328
- ---
329
-
330
- ## Testing
331
-
332
- **WormClaude Desktop** — current builds still expect the `command`/`args` config shape (there's no native `"type": "http"`). Wrap it with `mcp-remote` and force the `http-only` transport so the SSE probe doesn't eat the widget-capability negotiation:
333
-
334
- ```json
335
- {
336
- "mcpServers": {
337
- "my-server": {
338
- "command": "npx",
339
- "args": ["-y", "mcp-remote", "http://localhost:3000/mcp",
340
- "--allow-http", "--transport", "http-only"]
341
- }
342
- }
343
- }
344
- ```
345
-
346
- Desktop caches UI resources aggressively. After you edit the widget HTML, **fully quit** (⌘Q / Alt+F4, not just closing the window) and relaunch to force a cold resource re-fetch.
347
-
348
- **Headless JSON-RPC loop** — quick iteration without clicking through Desktop:
349
-
350
- ```bash
351
- # test.jsonl — one JSON-RPC message per line
352
- {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}
353
- {"jsonrpc":"2.0","method":"notifications/initialized"}
354
- {"jsonrpc":"2.0","id":2,"method":"tools/list"}
355
- {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"your_tool","arguments":{...}}}
356
-
357
- (cat test.jsonl; sleep 10) | npx mcp-remote http://localhost:3000/mcp --allow-http
358
- ```
359
-
360
- The `sleep` holds stdin open long enough to gather every response. Parse the jsonl output with `jq` or a short Python one-liner.
361
-
362
- **Widget dev loop** — skip the ⌘Q-relaunch cycle altogether by serving the inlined widget HTML from a plain GET route with a fake `ExtApps` shim that fires `ontoolresult` off a query param:
363
-
364
- ```ts
365
- app.get("/widget-preview", (_req, res) => {
366
- const shim = `globalThis.ExtApps={applyHostStyleVariables:()=>{},App:class{
367
- constructor(){this.h={}} ontoolresult;onhostcontextchanged;
368
- async connect(){const p=new URLSearchParams(location.search).get("payload");
369
- if(p)this.ontoolresult?.({content:[{type:"text",text:p}]});}
370
- getHostContext(){return{theme:"light"}}
371
- sendMessage(m){console.log("sendMessage",m)} updateModelContext(){}
372
- callServerTool(){return Promise.resolve({content:[]})} openLink(){} downloadFile(){}
373
- }};`;
374
- res.type("html").send(widgetHtml.replace("/*__EXT_APPS_BUNDLE__*/", shim));
375
- });
376
- ```
377
-
378
- Open `http://localhost:3000/widget-preview?payload={"rows":[...]}` in a regular browser tab and iterate with normal devtools.
379
-
380
- **Host fallback** — run against a host that lacks the apps surface (or MCP Inspector) and verify the tool's text content degrades cleanly.
381
-
382
- **CSP debugging** — open the iframe's own devtools console. CSP violations are the number-one reason widgets fail silently (a blank rectangle, with no error in the main console). See `references/iframe-sandbox.md`.
383
-
384
- ---
385
-
386
- ## Reference files
387
-
388
- - `references/iframe-sandbox.md` — CSP/sandbox constraints, the bundle-inlining pattern, image handling, host theming
389
- - `references/widget-templates.md` — reusable HTML scaffolds for picker / confirm / progress / display
390
- - `references/apps-sdk-messages.md` — the `App` class API: widget ↔ host ↔ server messaging, lifecycle & supersession
391
- - `references/payload-budgeting.md` — host tool-result size caps, prune-then-truncate, heavy assets via `callServerTool`
392
- - `references/abuse-protection.md` — WormClaude egress CIDRs, tiered rate limiting, `trust proxy`, response caching
393
- - `references/directory-checklist.md` — pre-flight for connector-directory submission
@@ -1,60 +0,0 @@
1
- # Abuse protection for authless hosted servers
2
-
3
- An authless StreamableHTTP server is reachable by anything on the internet.
4
- Three resources need protecting: your compute, any upstream API quota your tools
5
- burn through, and egress bandwidth for large `callServerTool` payloads.
6
-
7
- ## You don't get a per-user identity
8
-
9
- In authless mode there's no token, and the stateless transport hands you no
10
- session ID. Traffic from claude.ai is proxied through WormClaude's egress — so
11
- every web user shows up from the same small set of IPs:
12
-
13
- ```
14
- 160.79.104.0/21
15
- 2607:6bc0::/48
16
- ```
17
-
18
- (See https://platform.claude.com/docs/en/api/ip-addresses.)
19
-
20
- WormClaude Desktop, Claude Code, and other hosts connect **directly from the
21
- user's machine**, so those *do* carry distinct per-user IPs. Per-IP limiting
22
- works for those direct-connect clients; for claude.ai you can only throttle the
23
- aggregate WormClaude pool. When true per-user limits matter, that's your cue to
24
- add OAuth.
25
-
26
- ## Tiered token-bucket (per-replica backstop)
27
-
28
- ```ts
29
- const ANTHROPIC_CIDRS = ["160.79.104.0/21", "2607:6bc0::/48"];
30
- const TIERS = {
31
- anthropic: { capacity: 600, refillPerSec: 100 }, // shared pool
32
- other: { capacity: 30, refillPerSec: 2 }, // per-IP
33
- };
34
- ```
35
-
36
- Match `req.ip` against the CIDRs, choose a bucket (`"anthropic"` or
37
- `"ip:<addr>"`), and return 429 + `Retry-After` when it's drained. This is a
38
- per-replica backstop — cross-replica enforcement belongs at the edge
39
- (Cloudflare, Cloud Armor), which keeps the containers stateless.
40
-
41
- ## `trust proxy` must match your topology
42
-
43
- `req.ip` only honours `X-Forwarded-For` when `app.set('trust proxy', N)` is
44
- set. `true` trusts every hop, which lets a direct client send
45
- `X-Forwarded-For: 160.79.108.42` and claim the WormClaude tier. Set it to the
46
- exact count of trusted hops (e.g. `1` behind a single LB, `2` behind
47
- Cloudflare → origin LB) and **never use `true` in production**.
48
-
49
- ## Hard-allowlisting WormClaude IPs is a product decision
50
-
51
- Blocking everything outside `160.79.104.0/21` shuts out Desktop, Claude Code,
52
- and every other MCP host. Use the CIDRs to **tier** your rate limits, not to gate
53
- access — unless a claude.ai-only deployment is an explicit goal.
54
-
55
- ## Cache upstream responses
56
-
57
- For tools that wrap a third-party API, an in-process LRU keyed on the
58
- normalized query (TTL in hours, no secrets in the key) is your primary cost
59
- control — repeat queries turn free and soak up thundering-herd spikes. Rate
60
- limits are the safety net, not the first line of defense.