@fprad0/skill-master-mcp 0.0.12 → 1.0.0

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 (331) hide show
  1. package/CHANGELOG.md +96 -90
  2. package/README.md +472 -472
  3. package/VERSION.md +9 -9
  4. package/bin/lib/bootstrap-global-core.mjs +34 -0
  5. package/bin/lib/client-config.mjs +293 -293
  6. package/bin/lib/doctor-core.mjs +202 -0
  7. package/bin/lib/menu-core.mjs +1629 -1522
  8. package/bin/lib/operation-result.mjs +59 -0
  9. package/bin/lib/register-clients-core.mjs +247 -0
  10. package/bin/lib/skill-installation.mjs +215 -215
  11. package/bin/lib/update-cli-core.mjs +117 -0
  12. package/bin/skill-master-activation.mjs +163 -163
  13. package/bin/skill-master-bootstrap-global.mjs +61 -49
  14. package/bin/skill-master-configure-private-registry.mjs +3 -3
  15. package/bin/skill-master-doctor.mjs +239 -228
  16. package/bin/skill-master-eval-activation.mjs +32 -32
  17. package/bin/skill-master-install-global-skills.mjs +59 -59
  18. package/bin/skill-master-install-project-skills.mjs +97 -97
  19. package/bin/skill-master-menu.mjs +406 -405
  20. package/bin/skill-master-register-clients.mjs +232 -153
  21. package/bin/skill-master-success-skills.mjs +307 -307
  22. package/bin/skill-master-update.mjs +121 -72
  23. package/bin/skill-master.mjs +3 -3
  24. package/dist/activation.d.ts.map +1 -1
  25. package/dist/activation.js +12 -0
  26. package/dist/activation.js.map +1 -1
  27. package/dist/prompt-router.d.ts.map +1 -1
  28. package/dist/prompt-router.js +19 -0
  29. package/dist/prompt-router.js.map +1 -1
  30. package/dist/recommender.d.ts.map +1 -1
  31. package/dist/recommender.js +4 -1
  32. package/dist/recommender.js.map +1 -1
  33. package/docs/architecture/APRENDIZADO_DE_IMPLEMENTACOES_BEM_SUCEDIDAS.md +125 -125
  34. package/docs/architecture/ARQUITETURA_AUTO_UPDATE.md +9 -9
  35. package/docs/architecture/PLANO_MASTER_ACIONAMENTO_AUTOMATICO_E_APRENDIZADO.md +341 -341
  36. package/docs/architecture/REDE_SEGURA_DE_SKILLS.md +148 -148
  37. package/docs/operations/GUIA_MULTI_COMPUTADOR.md +262 -262
  38. package/docs/operations/GUIA_NPM_PRIVADO.md +294 -294
  39. package/docs/operations/GUIA_NPM_PUBLICO.md +147 -147
  40. package/docs/operations/MENU_VISUAL_EVIDENCE_2026-06-28.md +66 -66
  41. package/docs/operations/assets/menu-frame-compact.html +75 -75
  42. package/docs/operations/assets/menu-frame-large.html +83 -83
  43. package/docs/operations/assets/menu-frame-running.html +79 -79
  44. package/docs/operations/cross-platform-auth-transfer/ANALISE_COMPATIBILIDADE_MCP_2026-06-28.md +140 -140
  45. package/docs/operations/cross-platform-auth-transfer/README_TRANSFERENCIA.md +85 -85
  46. package/docs/operations/reborn-menu-cyberpunk-transfer/ANALISE_MENU_REBORN_CYBERPUNK_2026-06-28.md +174 -174
  47. package/docs/operations/reborn-menu-cyberpunk-transfer/HANDOFF_IMPLEMENTACAO_REBORN_CYBERPUNK_2026-06-28.md +119 -119
  48. package/docs/operations/reborn-menu-cyberpunk-transfer/ORDEM_DE_EXECUCAO_MENU_REBORN_CYBERPUNK.md +134 -134
  49. package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA.md +84 -84
  50. package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA_REBORN_PACKAGE.md +56 -56
  51. package/docs/operations/token-economy-transfer/ANALISE_AVANCADA_ECONOMIA_TOKENS_2026-06-30.md +141 -0
  52. package/docs/operations/token-economy-transfer/PLANO_DEV_SENIOR_MASTER_TOKEN_ECONOMY_2026-06-30.md +171 -0
  53. package/docs/operations/token-economy-transfer/README_TRANSFERENCIA_TOKEN_ECONOMY.md +31 -0
  54. package/docs/planning/MENU_RUNTIME_CORRECTION_PLAN_2026-06-30.md +551 -0
  55. package/docs/planning/V0_0_9_APROVACAO_CRITICA_MENSAGENS_DE_VENDA.md +85 -85
  56. package/docs/planning/V0_0_9_FONTES_E_CRITERIOS_DE_AUTORIDADE.md +139 -139
  57. package/docs/planning/V0_0_9_MATRIZ_SKILLS_MULTIDISCIPLINARES.md +105 -105
  58. package/docs/planning/V0_0_9_POLITICA_MORAL_CATOLICA_PARA_IA.md +181 -181
  59. package/docs/planning/V0_0_9_PROMPTS_EXECUCAO.md +59 -59
  60. package/docs/planning/V0_0_9_ROADMAP_DISCERNIMENTO_E_CONHECIMENTO_AMPLO.md +181 -181
  61. package/docs/prompt-tasks/PROMPT_TASK_001_BOOTSTRAP_SKILL_MASTER_MCP.md +6 -6
  62. package/docs/prompt-tasks/PROMPT_TASK_002_AUTO_UPDATE_LAUNCHER.md +6 -6
  63. package/docs/prompt-tasks/PROMPT_TASK_003_REMOTE_MANIFEST_AND_RELEASES.md +6 -6
  64. package/docs/prompt-tasks/PROMPT_TASK_004_MULTI_USER_DISTRIBUTION.md +6 -6
  65. package/docs/prompt-tasks/PROMPT_TASK_005_SECURITY_AND_QUALITY_GATE.md +6 -6
  66. package/docs/prompt-tasks/PROMPT_TASK_006_MASTER_ACIONAMENTO_APRENDIZADO.md +83 -83
  67. package/docs/prompt-tasks/PROMPT_TASK_007_PERSONA_ORQUESTRADORA.md +88 -88
  68. package/docs/prompt-tasks/PROMPT_TASK_008_PROMPT_ROUTER_MODOS_ATIVACAO.md +156 -156
  69. package/docs/prompt-tasks/PROMPT_TASK_009_PIPELINE_APRENDIZADO_SUCESSO.md +105 -105
  70. package/docs/prompt-tasks/PROMPT_TASK_010_EVALS_GOVERNANCA_ATIVACAO.md +119 -119
  71. package/docs/prompt-tasks/PROMPT_TASK_011_MENU_NOTIFICACOES_NOTION.md +120 -120
  72. package/docs/prompt-tasks/PROMPT_TASK_012_MENU_CYBERPUNK_PIXEL_FRAME.md +123 -123
  73. package/docs/prompt-tasks/PROMPT_TASK_013_MENU_FLUID_DNA_ANIMATION.md +114 -114
  74. package/docs/prompt-tasks/PROMPT_TASK_014_MENU_FUNCTIONAL_PARITY_QA.md +157 -157
  75. package/docs/prompt-tasks/PROMPT_TASK_015_TRANSFER_RELEASE_HANDOFF.md +127 -127
  76. package/docs/prompt-tasks/PROMPT_TASK_016_CROSS_PLATFORM_MCP_AUTH_REGISTRATION.md +107 -107
  77. package/docs/prompt-tasks/PROMPT_TASK_018_NPM_PUBLISH_2FA_SETUP.md +80 -80
  78. package/docs/prompt-tasks/PROMPT_TASK_019_TOKEN_ECONOMY_GLOBAL_SKILLS.md +56 -0
  79. package/docs/prompt-tasks/PROMPT_TASK_MASTER_EXECUTOR.md +6 -6
  80. package/docs/skill-candidates/v0.0.10/cli-creator/LICENSE.txt +201 -201
  81. package/docs/skill-candidates/v0.0.10/cli-creator/SKILL.md +160 -160
  82. package/docs/skill-candidates/v0.0.10/cli-creator/agents/openai.yaml +4 -4
  83. package/docs/skill-candidates/v0.0.10/cli-creator/references/agent-cli-patterns.md +154 -154
  84. package/docs/skill-candidates/v0.0.10/developer-workstation-ops/SKILL.md +32 -32
  85. package/docs/skill-candidates/v0.0.10/figma/LICENSE.txt +1 -1
  86. package/docs/skill-candidates/v0.0.10/figma/SKILL.md +42 -42
  87. package/docs/skill-candidates/v0.0.10/figma/agents/openai.yaml +14 -14
  88. package/docs/skill-candidates/v0.0.10/figma/assets/figma-small.svg +3 -3
  89. package/docs/skill-candidates/v0.0.10/figma/assets/icon.svg +28 -28
  90. package/docs/skill-candidates/v0.0.10/figma/references/figma-mcp-config.md +35 -35
  91. package/docs/skill-candidates/v0.0.10/figma/references/figma-tools-and-prompts.md +34 -34
  92. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/LICENSE.TXT +1 -1
  93. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/SKILL.md +349 -349
  94. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/agents/openai.yaml +14 -14
  95. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/figma-small.svg +3 -3
  96. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/icon.svg +28 -28
  97. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/references/mapping-checklist.md +7 -7
  98. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/scripts/normalize_node_id.py +25 -25
  99. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/LICENSE.TXT +1 -1
  100. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/SKILL.md +537 -537
  101. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/agents/openai.yaml +14 -14
  102. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/figma-small.svg +3 -3
  103. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/icon.svg +28 -28
  104. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/references/rule-template.md +15 -15
  105. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/scripts/check_agents_md.sh +9 -9
  106. package/docs/skill-candidates/v0.0.10/figma-generate-design/LICENSE.TXT +1 -1
  107. package/docs/skill-candidates/v0.0.10/figma-generate-design/SKILL.md +341 -341
  108. package/docs/skill-candidates/v0.0.10/figma-generate-design/agents/openai.yaml +14 -14
  109. package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/figma-small.svg +3 -3
  110. package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/icon.svg +28 -28
  111. package/docs/skill-candidates/v0.0.10/figma-generate-design/maintainers.yml +1 -1
  112. package/docs/skill-candidates/v0.0.10/figma-generate-library/LICENSE.TXT +1 -1
  113. package/docs/skill-candidates/v0.0.10/figma-generate-library/SKILL.md +314 -314
  114. package/docs/skill-candidates/v0.0.10/figma-generate-library/agents/openai.yaml +14 -14
  115. package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/figma-small.svg +3 -3
  116. package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/icon.svg +28 -28
  117. package/docs/skill-candidates/v0.0.10/figma-generate-library/maintainers.yml +3 -3
  118. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/code-connect-setup.md +260 -260
  119. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/component-creation.md +1014 -1014
  120. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/discovery-phase.md +518 -518
  121. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/documentation-creation.md +834 -834
  122. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/error-recovery.md +540 -540
  123. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/naming-conventions.md +527 -527
  124. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/token-creation.md +962 -962
  125. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/bindVariablesToComponent.js +110 -110
  126. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/cleanupOrphans.js +127 -127
  127. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createComponentWithVariants.js +148 -148
  128. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createDocumentationPage.js +139 -139
  129. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createSemanticTokens.js +108 -108
  130. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createVariableCollection.js +49 -49
  131. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/inspectFileStructure.js +121 -121
  132. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/rehydrateState.js +92 -92
  133. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/validateCreation.js +83 -83
  134. package/docs/skill-candidates/v0.0.10/figma-implement-design/LICENSE.txt +1 -1
  135. package/docs/skill-candidates/v0.0.10/figma-implement-design/SKILL.md +258 -258
  136. package/docs/skill-candidates/v0.0.10/figma-implement-design/agents/openai.yaml +14 -14
  137. package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/figma-small.svg +3 -3
  138. package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/icon.svg +28 -28
  139. package/docs/skill-candidates/v0.0.10/figma-use/LICENSE.TXT +1 -1
  140. package/docs/skill-candidates/v0.0.10/figma-use/SKILL.md +233 -233
  141. package/docs/skill-candidates/v0.0.10/figma-use/agents/openai.yaml +14 -14
  142. package/docs/skill-candidates/v0.0.10/figma-use/assets/figma-small.svg +3 -3
  143. package/docs/skill-candidates/v0.0.10/figma-use/assets/icon.svg +28 -28
  144. package/docs/skill-candidates/v0.0.10/figma-use/maintainers.yml +1 -1
  145. package/docs/skill-candidates/v0.0.10/figma-use/references/api-reference.md +301 -301
  146. package/docs/skill-candidates/v0.0.10/figma-use/references/common-patterns.md +512 -512
  147. package/docs/skill-candidates/v0.0.10/figma-use/references/component-patterns.md +488 -488
  148. package/docs/skill-candidates/v0.0.10/figma-use/references/effect-style-patterns.md +123 -123
  149. package/docs/skill-candidates/v0.0.10/figma-use/references/gotchas.md +599 -599
  150. package/docs/skill-candidates/v0.0.10/figma-use/references/maintainers.yml +12 -12
  151. package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-patterns.md +513 -513
  152. package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-standalone.d.ts +11293 -11293
  153. package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-standalone.index.md +441 -441
  154. package/docs/skill-candidates/v0.0.10/figma-use/references/text-style-patterns.md +203 -203
  155. package/docs/skill-candidates/v0.0.10/figma-use/references/validation-and-recovery.md +109 -109
  156. package/docs/skill-candidates/v0.0.10/figma-use/references/variable-patterns.md +354 -354
  157. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/maintainers.yml +9 -9
  158. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components--creating.md +17 -17
  159. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components--using.md +17 -17
  160. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components.md +50 -50
  161. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-effect-styles.md +52 -52
  162. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-text-styles.md +90 -90
  163. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables--creating.md +13 -13
  164. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables--using.md +13 -13
  165. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables.md +64 -64
  166. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds.md +41 -41
  167. package/docs/skill-candidates/v0.0.10/frontend-design/LICENSE.txt +177 -177
  168. package/docs/skill-candidates/v0.0.10/frontend-design/SKILL.md +55 -55
  169. package/docs/skill-candidates/v0.0.10/frontend-ui-ux-systems/SKILL.md +32 -32
  170. package/docs/skill-candidates/v0.0.10/github/SKILL.md +74 -74
  171. package/docs/skill-candidates/v0.0.10/github/agents/openai.yaml +6 -6
  172. package/docs/skill-candidates/v0.0.10/github/assets/github-small.svg +3 -3
  173. package/docs/skill-candidates/v0.0.10/image-graphic-design-rendering/SKILL.md +28 -28
  174. package/docs/skill-candidates/v0.0.10/language-quality-pt-en-fr-it-ru/SKILL.md +28 -28
  175. package/docs/skill-candidates/v0.0.10/math-physics-reasoning/SKILL.md +28 -28
  176. package/docs/skill-candidates/v0.0.10/mcp-builder/LICENSE.txt +201 -201
  177. package/docs/skill-candidates/v0.0.10/mcp-builder/SKILL.md +236 -236
  178. package/docs/skill-candidates/v0.0.10/mcp-builder/reference/evaluation.md +601 -601
  179. package/docs/skill-candidates/v0.0.10/mcp-builder/reference/mcp_best_practices.md +249 -249
  180. package/docs/skill-candidates/v0.0.10/mcp-builder/reference/node_mcp_server.md +969 -969
  181. package/docs/skill-candidates/v0.0.10/mcp-builder/reference/python_mcp_server.md +718 -718
  182. package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/connections.py +151 -151
  183. package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/evaluation.py +373 -373
  184. package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/example_evaluation.xml +22 -22
  185. package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/requirements.txt +2 -2
  186. package/docs/skill-candidates/v0.0.10/mcp-client-readiness/SKILL.md +31 -31
  187. package/docs/skill-candidates/v0.0.10/openai-docs/LICENSE.txt +201 -201
  188. package/docs/skill-candidates/v0.0.10/openai-docs/SKILL.md +161 -161
  189. package/docs/skill-candidates/v0.0.10/openai-docs/agents/openai.yaml +14 -14
  190. package/docs/skill-candidates/v0.0.10/openai-docs/assets/openai-small.svg +3 -3
  191. package/docs/skill-candidates/v0.0.10/openai-docs/references/latest-model.md +37 -37
  192. package/docs/skill-candidates/v0.0.10/openai-docs/references/prompting-guide.md +244 -244
  193. package/docs/skill-candidates/v0.0.10/openai-docs/references/upgrade-guide.md +181 -181
  194. package/docs/skill-candidates/v0.0.10/openai-docs/scripts/fetch-codex-manual.mjs +598 -598
  195. package/docs/skill-candidates/v0.0.10/openai-docs/scripts/resolve-latest-model-info.js +147 -147
  196. package/docs/skill-candidates/v0.0.10/playwright/NOTICE.txt +14 -14
  197. package/docs/skill-candidates/v0.0.10/playwright/SKILL.md +147 -147
  198. package/docs/skill-candidates/v0.0.10/playwright/agents/openai.yaml +6 -6
  199. package/docs/skill-candidates/v0.0.10/playwright/assets/playwright-small.svg +3 -3
  200. package/docs/skill-candidates/v0.0.10/playwright/references/cli.md +116 -116
  201. package/docs/skill-candidates/v0.0.10/playwright/references/workflows.md +95 -95
  202. package/docs/skill-candidates/v0.0.10/playwright/scripts/playwright_cli.sh +25 -25
  203. package/docs/skill-candidates/v0.0.10/polyglot-backend-engineering/SKILL.md +32 -32
  204. package/docs/skill-candidates/v0.0.10/screenshot/LICENSE.txt +201 -201
  205. package/docs/skill-candidates/v0.0.10/screenshot/SKILL.md +267 -267
  206. package/docs/skill-candidates/v0.0.10/screenshot/agents/openai.yaml +6 -6
  207. package/docs/skill-candidates/v0.0.10/screenshot/assets/screenshot-small.svg +5 -5
  208. package/docs/skill-candidates/v0.0.10/screenshot/scripts/ensure_macos_permissions.sh +54 -54
  209. package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_display_info.swift +22 -22
  210. package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_permissions.swift +40 -40
  211. package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_window_info.swift +126 -126
  212. package/docs/skill-candidates/v0.0.10/screenshot/scripts/take_screenshot.ps1 +163 -163
  213. package/docs/skill-candidates/v0.0.10/screenshot/scripts/take_screenshot.py +585 -585
  214. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/SKILL.md +62 -62
  215. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/agents/openai.yaml +4 -4
  216. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/activation-policy.md +77 -77
  217. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/human-approval-policy.md +83 -83
  218. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/persona-dev-senior-master.md +46 -46
  219. package/docs/skill-candidates/v0.0.10/terminal-menu-operations/SKILL.md +30 -30
  220. package/docs/skill-candidates/v0.0.10/terminal-pixel-art-tui/SKILL.md +43 -43
  221. package/docs/skill-candidates/v0.0.10/webapp-testing/LICENSE.txt +201 -201
  222. package/docs/skill-candidates/v0.0.10/webapp-testing/SKILL.md +95 -95
  223. package/docs/skill-candidates/v0.0.10/webapp-testing/examples/console_logging.py +34 -34
  224. package/docs/skill-candidates/v0.0.10/webapp-testing/examples/element_discovery.py +39 -39
  225. package/docs/skill-candidates/v0.0.10/webapp-testing/examples/static_html_automation.py +32 -32
  226. package/docs/skill-candidates/v0.0.10/webapp-testing/scripts/with_server.py +105 -105
  227. package/docs/skill-candidates/v0.0.10/winui-app/LICENSE.txt +201 -201
  228. package/docs/skill-candidates/v0.0.10/winui-app/SKILL.md +94 -94
  229. package/docs/skill-candidates/v0.0.10/winui-app/agents/openai.yaml +5 -5
  230. package/docs/skill-candidates/v0.0.10/winui-app/config.yaml +50 -50
  231. package/docs/skill-candidates/v0.0.10/winui-app/references/_sections.md +96 -96
  232. package/docs/skill-candidates/v0.0.10/winui-app/references/accessibility-input-and-localization.md +51 -51
  233. package/docs/skill-candidates/v0.0.10/winui-app/references/build-run-and-launch-verification.md +72 -72
  234. package/docs/skill-candidates/v0.0.10/winui-app/references/community-toolkit-controls-and-helpers.md +57 -57
  235. package/docs/skill-candidates/v0.0.10/winui-app/references/controls-layout-and-adaptive-ui.md +84 -84
  236. package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-environment-audit-and-remediation.md +82 -82
  237. package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-setup-and-project-selection.md +67 -67
  238. package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-template-first-recovery.md +62 -62
  239. package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-winui-app-structure.md +62 -62
  240. package/docs/skill-candidates/v0.0.10/winui-app/references/motion-animations-and-polish.md +45 -45
  241. package/docs/skill-candidates/v0.0.10/winui-app/references/performance-diagnostics-and-responsiveness.md +46 -46
  242. package/docs/skill-candidates/v0.0.10/winui-app/references/sample-source-map.md +37 -37
  243. package/docs/skill-candidates/v0.0.10/winui-app/references/shell-navigation-and-windowing.md +67 -67
  244. package/docs/skill-candidates/v0.0.10/winui-app/references/styling-theming-materials-and-icons.md +71 -71
  245. package/docs/skill-candidates/v0.0.10/winui-app/references/testing-debugging-and-review-checklists.md +77 -77
  246. package/docs/skill-candidates/v0.0.10/winui-app/references/windows-app-sdk-lifecycle-notifications-and-deployment.md +52 -52
  247. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/SKILL.md +398 -398
  248. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/common-patterns.md +330 -330
  249. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/complete-examples.md +871 -871
  250. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/component-patterns.md +501 -501
  251. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/data-fetching.md +766 -766
  252. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/file-organization.md +501 -501
  253. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/loading-and-error-states.md +500 -500
  254. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/performance.md +405 -405
  255. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/routing-guide.md +363 -363
  256. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/styling-guide.md +427 -427
  257. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/typescript-standards.md +417 -417
  258. package/docs/skill-candidates/v0.0.11/git-version-control-ops/SKILL.md +34 -34
  259. package/docs/skill-candidates/v0.0.11/go-engineering/SKILL.md +34 -34
  260. package/docs/skill-candidates/v0.0.11/java-engineering/SKILL.md +34 -34
  261. package/docs/skill-candidates/v0.0.11/javascript-engineering/SKILL.md +34 -34
  262. package/docs/skill-candidates/v0.0.11/json-contract-design/SKILL.md +34 -34
  263. package/docs/skill-candidates/v0.0.11/multi-client-mcp-ops/SKILL.md +36 -36
  264. package/docs/skill-candidates/v0.0.11/nextjs/SKILL.md +745 -745
  265. package/docs/skill-candidates/v0.0.11/nextjs/agents/openai.yaml +3 -3
  266. package/docs/skill-candidates/v0.0.11/nextjs/references/app-router-files.md +94 -94
  267. package/docs/skill-candidates/v0.0.11/python-engineering/SKILL.md +34 -34
  268. package/docs/skill-candidates/v0.0.11/ruby-engineering/SKILL.md +34 -34
  269. package/docs/skill-candidates/v0.0.11/senior-fullstack/SKILL.md +209 -209
  270. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/architecture_patterns.md +103 -103
  271. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/development_workflows.md +103 -103
  272. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/tech_stack_guide.md +103 -103
  273. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/code_quality_analyzer.py +114 -114
  274. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/fullstack_scaffolder.py +114 -114
  275. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/project_scaffolder.py +114 -114
  276. package/docs/skill-candidates/v0.0.11/shadcn/SKILL.md +573 -573
  277. package/docs/skill-candidates/v0.0.11/shadcn/agents/openai.yaml +3 -3
  278. package/docs/skill-candidates/v0.0.11/sql-postgresql-engineering/SKILL.md +34 -34
  279. package/docs/skill-candidates/v0.0.11/terminal-shell-ops/SKILL.md +34 -34
  280. package/docs/skill-candidates/v0.0.11/typescript-expert/SKILL.md +429 -429
  281. package/docs/skill-candidates/v0.0.11/typescript-expert/references/tsconfig-strict.json +91 -91
  282. package/docs/skill-candidates/v0.0.11/typescript-expert/references/typescript-cheatsheet.md +383 -383
  283. package/docs/skill-candidates/v0.0.11/typescript-expert/references/utility-types.ts +335 -335
  284. package/docs/skill-candidates/v0.0.11/typescript-expert/scripts/ts_diagnostic.py +203 -203
  285. package/docs/skill-candidates/v0.0.11/ui-component-primitives/SKILL.md +34 -34
  286. package/docs/skill-candidates/v0.0.11/web-mobile-design-systems/SKILL.md +34 -34
  287. package/docs/skill-candidates/v0.0.11/windows-linux-platform-ops/SKILL.md +34 -34
  288. package/docs/skill-candidates/v0.0.12/context-compression-handoff/SKILL.md +47 -0
  289. package/docs/skill-candidates/v0.0.12/csharp-senior-master-engineering/SKILL.md +32 -32
  290. package/docs/skill-candidates/v0.0.12/css-senior-master-engineering/SKILL.md +32 -32
  291. package/docs/skill-candidates/v0.0.12/go-senior-master-engineering/SKILL.md +32 -32
  292. package/docs/skill-candidates/v0.0.12/html-senior-master-engineering/SKILL.md +32 -32
  293. package/docs/skill-candidates/v0.0.12/javascript-senior-master-engineering/SKILL.md +32 -32
  294. package/docs/skill-candidates/v0.0.12/json-senior-master-engineering/SKILL.md +32 -32
  295. package/docs/skill-candidates/v0.0.12/prompt-budget-gate/SKILL.md +46 -0
  296. package/docs/skill-candidates/v0.0.12/python-senior-master-engineering/SKILL.md +32 -32
  297. package/docs/skill-candidates/v0.0.12/react-senior-master-engineering/SKILL.md +32 -32
  298. package/docs/skill-candidates/v0.0.12/ruby-senior-master-engineering/SKILL.md +32 -32
  299. package/docs/skill-candidates/v0.0.12/senior-master-code-optimizer/SKILL.md +48 -48
  300. package/docs/skill-candidates/v0.0.12/sql-senior-master-engineering/SKILL.md +31 -31
  301. package/docs/skill-candidates/v0.0.12/token-economy-orchestrator/SKILL.md +38 -0
  302. package/docs/skill-candidates/v0.0.12/typescript-senior-master-engineering/SKILL.md +35 -35
  303. package/docs/skill-candidates/v0.0.9/ai-ethics-human-dignity/SKILL.md +32 -32
  304. package/docs/skill-candidates/v0.0.9/broad-domain-router/SKILL.md +41 -41
  305. package/docs/skill-candidates/v0.0.9/catholic-moral-discernment/SKILL.md +31 -31
  306. package/docs/skill-candidates/v0.0.9/engineering-systems-master/SKILL.md +31 -31
  307. package/docs/skill-candidates/v0.0.9/language-quality-pt-en-fr/SKILL.md +28 -28
  308. package/docs/skill-candidates/v0.0.9/math-science-reasoning/SKILL.md +29 -29
  309. package/docs/skill-candidates/v0.0.9/philosophy-sociology-discernment/SKILL.md +28 -28
  310. package/docs/skill-candidates/v0.0.9/professional-boundary-triage/SKILL.md +40 -40
  311. package/docs/skill-candidates/v0.0.9/release-ethics-gate/SKILL.md +32 -32
  312. package/docs/skill-candidates/v0.0.9/source-authority-reviewer/SKILL.md +31 -31
  313. package/examples/client-configs/claude-code.commands.md +21 -21
  314. package/examples/client-configs/claude-code.project.mcp.json +18 -18
  315. package/examples/client-configs/claude-desktop.macos.json +18 -18
  316. package/examples/client-configs/claude-desktop.windows.json +20 -20
  317. package/examples/client-configs/codex.windows.toml +11 -11
  318. package/examples/client-configs/gemini-code-assist.intellij.mcp.json +18 -18
  319. package/examples/client-configs/gemini.linux.settings.json +21 -21
  320. package/examples/client-configs/gemini.windows.settings.json +23 -23
  321. package/examples/client-configs/generic-stdio.json +16 -16
  322. package/manifests/channels/beta.json +26 -26
  323. package/manifests/channels/stable.json +27 -27
  324. package/network/approved-skills.json +54 -54
  325. package/network/unapproved-skill-candidates.json +110 -110
  326. package/package.json +87 -86
  327. package/scripts/configure-private-registry.mjs +208 -208
  328. package/scripts/lib/private-registry.mjs +97 -97
  329. package/scripts/render-menu-evidence.mjs +130 -130
  330. package/scripts/verify-menu-actions.mjs +117 -117
  331. package/sources.json +11 -11
@@ -1,373 +1,373 @@
1
- """MCP Server Evaluation Harness
2
-
3
- This script evaluates MCP servers by running test questions against them using Claude.
4
- """
5
-
6
- import argparse
7
- import asyncio
8
- import json
9
- import re
10
- import sys
11
- import time
12
- import traceback
13
- import xml.etree.ElementTree as ET
14
- from pathlib import Path
15
- from typing import Any
16
-
17
- from anthropic import Anthropic
18
-
19
- from connections import create_connection
20
-
21
- EVALUATION_PROMPT = """You are an AI assistant with access to tools.
22
-
23
- When given a task, you MUST:
24
- 1. Use the available tools to complete the task
25
- 2. Provide summary of each step in your approach, wrapped in <summary> tags
26
- 3. Provide feedback on the tools provided, wrapped in <feedback> tags
27
- 4. Provide your final response, wrapped in <response> tags
28
-
29
- Summary Requirements:
30
- - In your <summary> tags, you must explain:
31
- - The steps you took to complete the task
32
- - Which tools you used, in what order, and why
33
- - The inputs you provided to each tool
34
- - The outputs you received from each tool
35
- - A summary for how you arrived at the response
36
-
37
- Feedback Requirements:
38
- - In your <feedback> tags, provide constructive feedback on the tools:
39
- - Comment on tool names: Are they clear and descriptive?
40
- - Comment on input parameters: Are they well-documented? Are required vs optional parameters clear?
41
- - Comment on descriptions: Do they accurately describe what the tool does?
42
- - Comment on any errors encountered during tool usage: Did the tool fail to execute? Did the tool return too many tokens?
43
- - Identify specific areas for improvement and explain WHY they would help
44
- - Be specific and actionable in your suggestions
45
-
46
- Response Requirements:
47
- - Your response should be concise and directly address what was asked
48
- - Always wrap your final response in <response> tags
49
- - If you cannot solve the task return <response>NOT_FOUND</response>
50
- - For numeric responses, provide just the number
51
- - For IDs, provide just the ID
52
- - For names or text, provide the exact text requested
53
- - Your response should go last"""
54
-
55
-
56
- def parse_evaluation_file(file_path: Path) -> list[dict[str, Any]]:
57
- """Parse XML evaluation file with qa_pair elements."""
58
- try:
59
- tree = ET.parse(file_path)
60
- root = tree.getroot()
61
- evaluations = []
62
-
63
- for qa_pair in root.findall(".//qa_pair"):
64
- question_elem = qa_pair.find("question")
65
- answer_elem = qa_pair.find("answer")
66
-
67
- if question_elem is not None and answer_elem is not None:
68
- evaluations.append({
69
- "question": (question_elem.text or "").strip(),
70
- "answer": (answer_elem.text or "").strip(),
71
- })
72
-
73
- return evaluations
74
- except Exception as e:
75
- print(f"Error parsing evaluation file {file_path}: {e}")
76
- return []
77
-
78
-
79
- def extract_xml_content(text: str, tag: str) -> str | None:
80
- """Extract content from XML tags."""
81
- pattern = rf"<{tag}>(.*?)</{tag}>"
82
- matches = re.findall(pattern, text, re.DOTALL)
83
- return matches[-1].strip() if matches else None
84
-
85
-
86
- async def agent_loop(
87
- client: Anthropic,
88
- model: str,
89
- question: str,
90
- tools: list[dict[str, Any]],
91
- connection: Any,
92
- ) -> tuple[str, dict[str, Any]]:
93
- """Run the agent loop with MCP tools."""
94
- messages = [{"role": "user", "content": question}]
95
-
96
- response = await asyncio.to_thread(
97
- client.messages.create,
98
- model=model,
99
- max_tokens=4096,
100
- system=EVALUATION_PROMPT,
101
- messages=messages,
102
- tools=tools,
103
- )
104
-
105
- messages.append({"role": "assistant", "content": response.content})
106
-
107
- tool_metrics = {}
108
-
109
- while response.stop_reason == "tool_use":
110
- tool_use = next(block for block in response.content if block.type == "tool_use")
111
- tool_name = tool_use.name
112
- tool_input = tool_use.input
113
-
114
- tool_start_ts = time.time()
115
- try:
116
- tool_result = await connection.call_tool(tool_name, tool_input)
117
- tool_response = json.dumps(tool_result) if isinstance(tool_result, (dict, list)) else str(tool_result)
118
- except Exception as e:
119
- tool_response = f"Error executing tool {tool_name}: {str(e)}\n"
120
- tool_response += traceback.format_exc()
121
- tool_duration = time.time() - tool_start_ts
122
-
123
- if tool_name not in tool_metrics:
124
- tool_metrics[tool_name] = {"count": 0, "durations": []}
125
- tool_metrics[tool_name]["count"] += 1
126
- tool_metrics[tool_name]["durations"].append(tool_duration)
127
-
128
- messages.append({
129
- "role": "user",
130
- "content": [{
131
- "type": "tool_result",
132
- "tool_use_id": tool_use.id,
133
- "content": tool_response,
134
- }]
135
- })
136
-
137
- response = await asyncio.to_thread(
138
- client.messages.create,
139
- model=model,
140
- max_tokens=4096,
141
- system=EVALUATION_PROMPT,
142
- messages=messages,
143
- tools=tools,
144
- )
145
- messages.append({"role": "assistant", "content": response.content})
146
-
147
- response_text = next(
148
- (block.text for block in response.content if hasattr(block, "text")),
149
- None,
150
- )
151
- return response_text, tool_metrics
152
-
153
-
154
- async def evaluate_single_task(
155
- client: Anthropic,
156
- model: str,
157
- qa_pair: dict[str, Any],
158
- tools: list[dict[str, Any]],
159
- connection: Any,
160
- task_index: int,
161
- ) -> dict[str, Any]:
162
- """Evaluate a single QA pair with the given tools."""
163
- start_time = time.time()
164
-
165
- print(f"Task {task_index + 1}: Running task with question: {qa_pair['question']}")
166
- response, tool_metrics = await agent_loop(client, model, qa_pair["question"], tools, connection)
167
-
168
- response_value = extract_xml_content(response, "response")
169
- summary = extract_xml_content(response, "summary")
170
- feedback = extract_xml_content(response, "feedback")
171
-
172
- duration_seconds = time.time() - start_time
173
-
174
- return {
175
- "question": qa_pair["question"],
176
- "expected": qa_pair["answer"],
177
- "actual": response_value,
178
- "score": int(response_value == qa_pair["answer"]) if response_value else 0,
179
- "total_duration": duration_seconds,
180
- "tool_calls": tool_metrics,
181
- "num_tool_calls": sum(len(metrics["durations"]) for metrics in tool_metrics.values()),
182
- "summary": summary,
183
- "feedback": feedback,
184
- }
185
-
186
-
187
- REPORT_HEADER = """
188
- # Evaluation Report
189
-
190
- ## Summary
191
-
192
- - **Accuracy**: {correct}/{total} ({accuracy:.1f}%)
193
- - **Average Task Duration**: {average_duration_s:.2f}s
194
- - **Average Tool Calls per Task**: {average_tool_calls:.2f}
195
- - **Total Tool Calls**: {total_tool_calls}
196
-
197
- ---
198
- """
199
-
200
- TASK_TEMPLATE = """
201
- ### Task {task_num}
202
-
203
- **Question**: {question}
204
- **Ground Truth Answer**: `{expected_answer}`
205
- **Actual Answer**: `{actual_answer}`
206
- **Correct**: {correct_indicator}
207
- **Duration**: {total_duration:.2f}s
208
- **Tool Calls**: {tool_calls}
209
-
210
- **Summary**
211
- {summary}
212
-
213
- **Feedback**
214
- {feedback}
215
-
216
- ---
217
- """
218
-
219
-
220
- async def run_evaluation(
221
- eval_path: Path,
222
- connection: Any,
223
- model: str = "claude-3-7-sonnet-20250219",
224
- ) -> str:
225
- """Run evaluation with MCP server tools."""
226
- print("šŸš€ Starting Evaluation")
227
-
228
- client = Anthropic()
229
-
230
- tools = await connection.list_tools()
231
- print(f"šŸ“‹ Loaded {len(tools)} tools from MCP server")
232
-
233
- qa_pairs = parse_evaluation_file(eval_path)
234
- print(f"šŸ“‹ Loaded {len(qa_pairs)} evaluation tasks")
235
-
236
- results = []
237
- for i, qa_pair in enumerate(qa_pairs):
238
- print(f"Processing task {i + 1}/{len(qa_pairs)}")
239
- result = await evaluate_single_task(client, model, qa_pair, tools, connection, i)
240
- results.append(result)
241
-
242
- correct = sum(r["score"] for r in results)
243
- accuracy = (correct / len(results)) * 100 if results else 0
244
- average_duration_s = sum(r["total_duration"] for r in results) / len(results) if results else 0
245
- average_tool_calls = sum(r["num_tool_calls"] for r in results) / len(results) if results else 0
246
- total_tool_calls = sum(r["num_tool_calls"] for r in results)
247
-
248
- report = REPORT_HEADER.format(
249
- correct=correct,
250
- total=len(results),
251
- accuracy=accuracy,
252
- average_duration_s=average_duration_s,
253
- average_tool_calls=average_tool_calls,
254
- total_tool_calls=total_tool_calls,
255
- )
256
-
257
- report += "".join([
258
- TASK_TEMPLATE.format(
259
- task_num=i + 1,
260
- question=qa_pair["question"],
261
- expected_answer=qa_pair["answer"],
262
- actual_answer=result["actual"] or "N/A",
263
- correct_indicator="āœ…" if result["score"] else "āŒ",
264
- total_duration=result["total_duration"],
265
- tool_calls=json.dumps(result["tool_calls"], indent=2),
266
- summary=result["summary"] or "N/A",
267
- feedback=result["feedback"] or "N/A",
268
- )
269
- for i, (qa_pair, result) in enumerate(zip(qa_pairs, results))
270
- ])
271
-
272
- return report
273
-
274
-
275
- def parse_headers(header_list: list[str]) -> dict[str, str]:
276
- """Parse header strings in format 'Key: Value' into a dictionary."""
277
- headers = {}
278
- if not header_list:
279
- return headers
280
-
281
- for header in header_list:
282
- if ":" in header:
283
- key, value = header.split(":", 1)
284
- headers[key.strip()] = value.strip()
285
- else:
286
- print(f"Warning: Ignoring malformed header: {header}")
287
- return headers
288
-
289
-
290
- def parse_env_vars(env_list: list[str]) -> dict[str, str]:
291
- """Parse environment variable strings in format 'KEY=VALUE' into a dictionary."""
292
- env = {}
293
- if not env_list:
294
- return env
295
-
296
- for env_var in env_list:
297
- if "=" in env_var:
298
- key, value = env_var.split("=", 1)
299
- env[key.strip()] = value.strip()
300
- else:
301
- print(f"Warning: Ignoring malformed environment variable: {env_var}")
302
- return env
303
-
304
-
305
- async def main():
306
- parser = argparse.ArgumentParser(
307
- description="Evaluate MCP servers using test questions",
308
- formatter_class=argparse.RawDescriptionHelpFormatter,
309
- epilog="""
310
- Examples:
311
- # Evaluate a local stdio MCP server
312
- python evaluation.py -t stdio -c python -a my_server.py eval.xml
313
-
314
- # Evaluate an SSE MCP server
315
- python evaluation.py -t sse -u https://example.com/mcp -H "Authorization: Bearer token" eval.xml
316
-
317
- # Evaluate an HTTP MCP server with custom model
318
- python evaluation.py -t http -u https://example.com/mcp -m claude-3-5-sonnet-20241022 eval.xml
319
- """,
320
- )
321
-
322
- parser.add_argument("eval_file", type=Path, help="Path to evaluation XML file")
323
- parser.add_argument("-t", "--transport", choices=["stdio", "sse", "http"], default="stdio", help="Transport type (default: stdio)")
324
- parser.add_argument("-m", "--model", default="claude-3-7-sonnet-20250219", help="Claude model to use (default: claude-3-7-sonnet-20250219)")
325
-
326
- stdio_group = parser.add_argument_group("stdio options")
327
- stdio_group.add_argument("-c", "--command", help="Command to run MCP server (stdio only)")
328
- stdio_group.add_argument("-a", "--args", nargs="+", help="Arguments for the command (stdio only)")
329
- stdio_group.add_argument("-e", "--env", nargs="+", help="Environment variables in KEY=VALUE format (stdio only)")
330
-
331
- remote_group = parser.add_argument_group("sse/http options")
332
- remote_group.add_argument("-u", "--url", help="MCP server URL (sse/http only)")
333
- remote_group.add_argument("-H", "--header", nargs="+", dest="headers", help="HTTP headers in 'Key: Value' format (sse/http only)")
334
-
335
- parser.add_argument("-o", "--output", type=Path, help="Output file for evaluation report (default: stdout)")
336
-
337
- args = parser.parse_args()
338
-
339
- if not args.eval_file.exists():
340
- print(f"Error: Evaluation file not found: {args.eval_file}")
341
- sys.exit(1)
342
-
343
- headers = parse_headers(args.headers) if args.headers else None
344
- env_vars = parse_env_vars(args.env) if args.env else None
345
-
346
- try:
347
- connection = create_connection(
348
- transport=args.transport,
349
- command=args.command,
350
- args=args.args,
351
- env=env_vars,
352
- url=args.url,
353
- headers=headers,
354
- )
355
- except ValueError as e:
356
- print(f"Error: {e}")
357
- sys.exit(1)
358
-
359
- print(f"šŸ”— Connecting to MCP server via {args.transport}...")
360
-
361
- async with connection:
362
- print("āœ… Connected successfully")
363
- report = await run_evaluation(args.eval_file, connection, args.model)
364
-
365
- if args.output:
366
- args.output.write_text(report)
367
- print(f"\nāœ… Report saved to {args.output}")
368
- else:
369
- print("\n" + report)
370
-
371
-
372
- if __name__ == "__main__":
373
- asyncio.run(main())
1
+ """MCP Server Evaluation Harness
2
+
3
+ This script evaluates MCP servers by running test questions against them using Claude.
4
+ """
5
+
6
+ import argparse
7
+ import asyncio
8
+ import json
9
+ import re
10
+ import sys
11
+ import time
12
+ import traceback
13
+ import xml.etree.ElementTree as ET
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+ from anthropic import Anthropic
18
+
19
+ from connections import create_connection
20
+
21
+ EVALUATION_PROMPT = """You are an AI assistant with access to tools.
22
+
23
+ When given a task, you MUST:
24
+ 1. Use the available tools to complete the task
25
+ 2. Provide summary of each step in your approach, wrapped in <summary> tags
26
+ 3. Provide feedback on the tools provided, wrapped in <feedback> tags
27
+ 4. Provide your final response, wrapped in <response> tags
28
+
29
+ Summary Requirements:
30
+ - In your <summary> tags, you must explain:
31
+ - The steps you took to complete the task
32
+ - Which tools you used, in what order, and why
33
+ - The inputs you provided to each tool
34
+ - The outputs you received from each tool
35
+ - A summary for how you arrived at the response
36
+
37
+ Feedback Requirements:
38
+ - In your <feedback> tags, provide constructive feedback on the tools:
39
+ - Comment on tool names: Are they clear and descriptive?
40
+ - Comment on input parameters: Are they well-documented? Are required vs optional parameters clear?
41
+ - Comment on descriptions: Do they accurately describe what the tool does?
42
+ - Comment on any errors encountered during tool usage: Did the tool fail to execute? Did the tool return too many tokens?
43
+ - Identify specific areas for improvement and explain WHY they would help
44
+ - Be specific and actionable in your suggestions
45
+
46
+ Response Requirements:
47
+ - Your response should be concise and directly address what was asked
48
+ - Always wrap your final response in <response> tags
49
+ - If you cannot solve the task return <response>NOT_FOUND</response>
50
+ - For numeric responses, provide just the number
51
+ - For IDs, provide just the ID
52
+ - For names or text, provide the exact text requested
53
+ - Your response should go last"""
54
+
55
+
56
+ def parse_evaluation_file(file_path: Path) -> list[dict[str, Any]]:
57
+ """Parse XML evaluation file with qa_pair elements."""
58
+ try:
59
+ tree = ET.parse(file_path)
60
+ root = tree.getroot()
61
+ evaluations = []
62
+
63
+ for qa_pair in root.findall(".//qa_pair"):
64
+ question_elem = qa_pair.find("question")
65
+ answer_elem = qa_pair.find("answer")
66
+
67
+ if question_elem is not None and answer_elem is not None:
68
+ evaluations.append({
69
+ "question": (question_elem.text or "").strip(),
70
+ "answer": (answer_elem.text or "").strip(),
71
+ })
72
+
73
+ return evaluations
74
+ except Exception as e:
75
+ print(f"Error parsing evaluation file {file_path}: {e}")
76
+ return []
77
+
78
+
79
+ def extract_xml_content(text: str, tag: str) -> str | None:
80
+ """Extract content from XML tags."""
81
+ pattern = rf"<{tag}>(.*?)</{tag}>"
82
+ matches = re.findall(pattern, text, re.DOTALL)
83
+ return matches[-1].strip() if matches else None
84
+
85
+
86
+ async def agent_loop(
87
+ client: Anthropic,
88
+ model: str,
89
+ question: str,
90
+ tools: list[dict[str, Any]],
91
+ connection: Any,
92
+ ) -> tuple[str, dict[str, Any]]:
93
+ """Run the agent loop with MCP tools."""
94
+ messages = [{"role": "user", "content": question}]
95
+
96
+ response = await asyncio.to_thread(
97
+ client.messages.create,
98
+ model=model,
99
+ max_tokens=4096,
100
+ system=EVALUATION_PROMPT,
101
+ messages=messages,
102
+ tools=tools,
103
+ )
104
+
105
+ messages.append({"role": "assistant", "content": response.content})
106
+
107
+ tool_metrics = {}
108
+
109
+ while response.stop_reason == "tool_use":
110
+ tool_use = next(block for block in response.content if block.type == "tool_use")
111
+ tool_name = tool_use.name
112
+ tool_input = tool_use.input
113
+
114
+ tool_start_ts = time.time()
115
+ try:
116
+ tool_result = await connection.call_tool(tool_name, tool_input)
117
+ tool_response = json.dumps(tool_result) if isinstance(tool_result, (dict, list)) else str(tool_result)
118
+ except Exception as e:
119
+ tool_response = f"Error executing tool {tool_name}: {str(e)}\n"
120
+ tool_response += traceback.format_exc()
121
+ tool_duration = time.time() - tool_start_ts
122
+
123
+ if tool_name not in tool_metrics:
124
+ tool_metrics[tool_name] = {"count": 0, "durations": []}
125
+ tool_metrics[tool_name]["count"] += 1
126
+ tool_metrics[tool_name]["durations"].append(tool_duration)
127
+
128
+ messages.append({
129
+ "role": "user",
130
+ "content": [{
131
+ "type": "tool_result",
132
+ "tool_use_id": tool_use.id,
133
+ "content": tool_response,
134
+ }]
135
+ })
136
+
137
+ response = await asyncio.to_thread(
138
+ client.messages.create,
139
+ model=model,
140
+ max_tokens=4096,
141
+ system=EVALUATION_PROMPT,
142
+ messages=messages,
143
+ tools=tools,
144
+ )
145
+ messages.append({"role": "assistant", "content": response.content})
146
+
147
+ response_text = next(
148
+ (block.text for block in response.content if hasattr(block, "text")),
149
+ None,
150
+ )
151
+ return response_text, tool_metrics
152
+
153
+
154
+ async def evaluate_single_task(
155
+ client: Anthropic,
156
+ model: str,
157
+ qa_pair: dict[str, Any],
158
+ tools: list[dict[str, Any]],
159
+ connection: Any,
160
+ task_index: int,
161
+ ) -> dict[str, Any]:
162
+ """Evaluate a single QA pair with the given tools."""
163
+ start_time = time.time()
164
+
165
+ print(f"Task {task_index + 1}: Running task with question: {qa_pair['question']}")
166
+ response, tool_metrics = await agent_loop(client, model, qa_pair["question"], tools, connection)
167
+
168
+ response_value = extract_xml_content(response, "response")
169
+ summary = extract_xml_content(response, "summary")
170
+ feedback = extract_xml_content(response, "feedback")
171
+
172
+ duration_seconds = time.time() - start_time
173
+
174
+ return {
175
+ "question": qa_pair["question"],
176
+ "expected": qa_pair["answer"],
177
+ "actual": response_value,
178
+ "score": int(response_value == qa_pair["answer"]) if response_value else 0,
179
+ "total_duration": duration_seconds,
180
+ "tool_calls": tool_metrics,
181
+ "num_tool_calls": sum(len(metrics["durations"]) for metrics in tool_metrics.values()),
182
+ "summary": summary,
183
+ "feedback": feedback,
184
+ }
185
+
186
+
187
+ REPORT_HEADER = """
188
+ # Evaluation Report
189
+
190
+ ## Summary
191
+
192
+ - **Accuracy**: {correct}/{total} ({accuracy:.1f}%)
193
+ - **Average Task Duration**: {average_duration_s:.2f}s
194
+ - **Average Tool Calls per Task**: {average_tool_calls:.2f}
195
+ - **Total Tool Calls**: {total_tool_calls}
196
+
197
+ ---
198
+ """
199
+
200
+ TASK_TEMPLATE = """
201
+ ### Task {task_num}
202
+
203
+ **Question**: {question}
204
+ **Ground Truth Answer**: `{expected_answer}`
205
+ **Actual Answer**: `{actual_answer}`
206
+ **Correct**: {correct_indicator}
207
+ **Duration**: {total_duration:.2f}s
208
+ **Tool Calls**: {tool_calls}
209
+
210
+ **Summary**
211
+ {summary}
212
+
213
+ **Feedback**
214
+ {feedback}
215
+
216
+ ---
217
+ """
218
+
219
+
220
+ async def run_evaluation(
221
+ eval_path: Path,
222
+ connection: Any,
223
+ model: str = "claude-3-7-sonnet-20250219",
224
+ ) -> str:
225
+ """Run evaluation with MCP server tools."""
226
+ print("šŸš€ Starting Evaluation")
227
+
228
+ client = Anthropic()
229
+
230
+ tools = await connection.list_tools()
231
+ print(f"šŸ“‹ Loaded {len(tools)} tools from MCP server")
232
+
233
+ qa_pairs = parse_evaluation_file(eval_path)
234
+ print(f"šŸ“‹ Loaded {len(qa_pairs)} evaluation tasks")
235
+
236
+ results = []
237
+ for i, qa_pair in enumerate(qa_pairs):
238
+ print(f"Processing task {i + 1}/{len(qa_pairs)}")
239
+ result = await evaluate_single_task(client, model, qa_pair, tools, connection, i)
240
+ results.append(result)
241
+
242
+ correct = sum(r["score"] for r in results)
243
+ accuracy = (correct / len(results)) * 100 if results else 0
244
+ average_duration_s = sum(r["total_duration"] for r in results) / len(results) if results else 0
245
+ average_tool_calls = sum(r["num_tool_calls"] for r in results) / len(results) if results else 0
246
+ total_tool_calls = sum(r["num_tool_calls"] for r in results)
247
+
248
+ report = REPORT_HEADER.format(
249
+ correct=correct,
250
+ total=len(results),
251
+ accuracy=accuracy,
252
+ average_duration_s=average_duration_s,
253
+ average_tool_calls=average_tool_calls,
254
+ total_tool_calls=total_tool_calls,
255
+ )
256
+
257
+ report += "".join([
258
+ TASK_TEMPLATE.format(
259
+ task_num=i + 1,
260
+ question=qa_pair["question"],
261
+ expected_answer=qa_pair["answer"],
262
+ actual_answer=result["actual"] or "N/A",
263
+ correct_indicator="āœ…" if result["score"] else "āŒ",
264
+ total_duration=result["total_duration"],
265
+ tool_calls=json.dumps(result["tool_calls"], indent=2),
266
+ summary=result["summary"] or "N/A",
267
+ feedback=result["feedback"] or "N/A",
268
+ )
269
+ for i, (qa_pair, result) in enumerate(zip(qa_pairs, results))
270
+ ])
271
+
272
+ return report
273
+
274
+
275
+ def parse_headers(header_list: list[str]) -> dict[str, str]:
276
+ """Parse header strings in format 'Key: Value' into a dictionary."""
277
+ headers = {}
278
+ if not header_list:
279
+ return headers
280
+
281
+ for header in header_list:
282
+ if ":" in header:
283
+ key, value = header.split(":", 1)
284
+ headers[key.strip()] = value.strip()
285
+ else:
286
+ print(f"Warning: Ignoring malformed header: {header}")
287
+ return headers
288
+
289
+
290
+ def parse_env_vars(env_list: list[str]) -> dict[str, str]:
291
+ """Parse environment variable strings in format 'KEY=VALUE' into a dictionary."""
292
+ env = {}
293
+ if not env_list:
294
+ return env
295
+
296
+ for env_var in env_list:
297
+ if "=" in env_var:
298
+ key, value = env_var.split("=", 1)
299
+ env[key.strip()] = value.strip()
300
+ else:
301
+ print(f"Warning: Ignoring malformed environment variable: {env_var}")
302
+ return env
303
+
304
+
305
+ async def main():
306
+ parser = argparse.ArgumentParser(
307
+ description="Evaluate MCP servers using test questions",
308
+ formatter_class=argparse.RawDescriptionHelpFormatter,
309
+ epilog="""
310
+ Examples:
311
+ # Evaluate a local stdio MCP server
312
+ python evaluation.py -t stdio -c python -a my_server.py eval.xml
313
+
314
+ # Evaluate an SSE MCP server
315
+ python evaluation.py -t sse -u https://example.com/mcp -H "Authorization: Bearer token" eval.xml
316
+
317
+ # Evaluate an HTTP MCP server with custom model
318
+ python evaluation.py -t http -u https://example.com/mcp -m claude-3-5-sonnet-20241022 eval.xml
319
+ """,
320
+ )
321
+
322
+ parser.add_argument("eval_file", type=Path, help="Path to evaluation XML file")
323
+ parser.add_argument("-t", "--transport", choices=["stdio", "sse", "http"], default="stdio", help="Transport type (default: stdio)")
324
+ parser.add_argument("-m", "--model", default="claude-3-7-sonnet-20250219", help="Claude model to use (default: claude-3-7-sonnet-20250219)")
325
+
326
+ stdio_group = parser.add_argument_group("stdio options")
327
+ stdio_group.add_argument("-c", "--command", help="Command to run MCP server (stdio only)")
328
+ stdio_group.add_argument("-a", "--args", nargs="+", help="Arguments for the command (stdio only)")
329
+ stdio_group.add_argument("-e", "--env", nargs="+", help="Environment variables in KEY=VALUE format (stdio only)")
330
+
331
+ remote_group = parser.add_argument_group("sse/http options")
332
+ remote_group.add_argument("-u", "--url", help="MCP server URL (sse/http only)")
333
+ remote_group.add_argument("-H", "--header", nargs="+", dest="headers", help="HTTP headers in 'Key: Value' format (sse/http only)")
334
+
335
+ parser.add_argument("-o", "--output", type=Path, help="Output file for evaluation report (default: stdout)")
336
+
337
+ args = parser.parse_args()
338
+
339
+ if not args.eval_file.exists():
340
+ print(f"Error: Evaluation file not found: {args.eval_file}")
341
+ sys.exit(1)
342
+
343
+ headers = parse_headers(args.headers) if args.headers else None
344
+ env_vars = parse_env_vars(args.env) if args.env else None
345
+
346
+ try:
347
+ connection = create_connection(
348
+ transport=args.transport,
349
+ command=args.command,
350
+ args=args.args,
351
+ env=env_vars,
352
+ url=args.url,
353
+ headers=headers,
354
+ )
355
+ except ValueError as e:
356
+ print(f"Error: {e}")
357
+ sys.exit(1)
358
+
359
+ print(f"šŸ”— Connecting to MCP server via {args.transport}...")
360
+
361
+ async with connection:
362
+ print("āœ… Connected successfully")
363
+ report = await run_evaluation(args.eval_file, connection, args.model)
364
+
365
+ if args.output:
366
+ args.output.write_text(report)
367
+ print(f"\nāœ… Report saved to {args.output}")
368
+ else:
369
+ print("\n" + report)
370
+
371
+
372
+ if __name__ == "__main__":
373
+ asyncio.run(main())