claude-mpm 5.4.41__py3-none-any.whl → 5.6.72__py3-none-any.whl

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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (490) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
  3. claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +161 -298
  6. claude_mpm/agents/WORKFLOW.md +2 -0
  7. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  8. claude_mpm/auth/__init__.py +35 -0
  9. claude_mpm/auth/callback_server.py +328 -0
  10. claude_mpm/auth/models.py +104 -0
  11. claude_mpm/auth/oauth_manager.py +266 -0
  12. claude_mpm/auth/providers/__init__.py +12 -0
  13. claude_mpm/auth/providers/base.py +165 -0
  14. claude_mpm/auth/providers/google.py +261 -0
  15. claude_mpm/auth/token_storage.py +252 -0
  16. claude_mpm/cli/__init__.py +5 -1
  17. claude_mpm/cli/commands/agents.py +2 -4
  18. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  19. claude_mpm/cli/commands/autotodos.py +566 -0
  20. claude_mpm/cli/commands/commander.py +216 -0
  21. claude_mpm/cli/commands/configure.py +620 -21
  22. claude_mpm/cli/commands/configure_agent_display.py +3 -1
  23. claude_mpm/cli/commands/hook_errors.py +60 -60
  24. claude_mpm/cli/commands/mcp.py +29 -17
  25. claude_mpm/cli/commands/mcp_command_router.py +39 -0
  26. claude_mpm/cli/commands/mcp_service_commands.py +304 -0
  27. claude_mpm/cli/commands/monitor.py +2 -2
  28. claude_mpm/cli/commands/mpm_init/core.py +15 -8
  29. claude_mpm/cli/commands/oauth.py +481 -0
  30. claude_mpm/cli/commands/profile.py +9 -10
  31. claude_mpm/cli/commands/run.py +35 -3
  32. claude_mpm/cli/commands/skill_source.py +51 -2
  33. claude_mpm/cli/commands/skills.py +182 -32
  34. claude_mpm/cli/executor.py +129 -16
  35. claude_mpm/cli/helpers.py +1 -1
  36. claude_mpm/cli/interactive/__init__.py +10 -0
  37. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  38. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  39. claude_mpm/cli/interactive/skill_selector.py +481 -0
  40. claude_mpm/cli/parsers/base_parser.py +89 -1
  41. claude_mpm/cli/parsers/commander_parser.py +116 -0
  42. claude_mpm/cli/parsers/mcp_parser.py +79 -0
  43. claude_mpm/cli/parsers/oauth_parser.py +165 -0
  44. claude_mpm/cli/parsers/profile_parser.py +0 -1
  45. claude_mpm/cli/parsers/run_parser.py +10 -0
  46. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  47. claude_mpm/cli/parsers/skills_parser.py +2 -3
  48. claude_mpm/cli/startup.py +662 -524
  49. claude_mpm/cli/startup_display.py +76 -7
  50. claude_mpm/cli/startup_logging.py +2 -2
  51. claude_mpm/cli/utils.py +7 -3
  52. claude_mpm/commander/__init__.py +78 -0
  53. claude_mpm/commander/adapters/__init__.py +60 -0
  54. claude_mpm/commander/adapters/auggie.py +260 -0
  55. claude_mpm/commander/adapters/base.py +288 -0
  56. claude_mpm/commander/adapters/claude_code.py +392 -0
  57. claude_mpm/commander/adapters/codex.py +237 -0
  58. claude_mpm/commander/adapters/communication.py +366 -0
  59. claude_mpm/commander/adapters/example_usage.py +310 -0
  60. claude_mpm/commander/adapters/mpm.py +389 -0
  61. claude_mpm/commander/adapters/registry.py +204 -0
  62. claude_mpm/commander/api/__init__.py +16 -0
  63. claude_mpm/commander/api/app.py +121 -0
  64. claude_mpm/commander/api/errors.py +133 -0
  65. claude_mpm/commander/api/routes/__init__.py +8 -0
  66. claude_mpm/commander/api/routes/events.py +184 -0
  67. claude_mpm/commander/api/routes/inbox.py +171 -0
  68. claude_mpm/commander/api/routes/messages.py +148 -0
  69. claude_mpm/commander/api/routes/projects.py +271 -0
  70. claude_mpm/commander/api/routes/sessions.py +226 -0
  71. claude_mpm/commander/api/routes/work.py +296 -0
  72. claude_mpm/commander/api/schemas.py +186 -0
  73. claude_mpm/commander/chat/__init__.py +7 -0
  74. claude_mpm/commander/chat/cli.py +149 -0
  75. claude_mpm/commander/chat/commands.py +122 -0
  76. claude_mpm/commander/chat/repl.py +1821 -0
  77. claude_mpm/commander/config.py +51 -0
  78. claude_mpm/commander/config_loader.py +115 -0
  79. claude_mpm/commander/core/__init__.py +10 -0
  80. claude_mpm/commander/core/block_manager.py +325 -0
  81. claude_mpm/commander/core/response_manager.py +323 -0
  82. claude_mpm/commander/daemon.py +603 -0
  83. claude_mpm/commander/env_loader.py +59 -0
  84. claude_mpm/commander/events/__init__.py +26 -0
  85. claude_mpm/commander/events/manager.py +392 -0
  86. claude_mpm/commander/frameworks/__init__.py +12 -0
  87. claude_mpm/commander/frameworks/base.py +233 -0
  88. claude_mpm/commander/frameworks/claude_code.py +58 -0
  89. claude_mpm/commander/frameworks/mpm.py +57 -0
  90. claude_mpm/commander/git/__init__.py +5 -0
  91. claude_mpm/commander/git/worktree_manager.py +212 -0
  92. claude_mpm/commander/inbox/__init__.py +16 -0
  93. claude_mpm/commander/inbox/dedup.py +128 -0
  94. claude_mpm/commander/inbox/inbox.py +224 -0
  95. claude_mpm/commander/inbox/models.py +70 -0
  96. claude_mpm/commander/instance_manager.py +865 -0
  97. claude_mpm/commander/llm/__init__.py +6 -0
  98. claude_mpm/commander/llm/openrouter_client.py +167 -0
  99. claude_mpm/commander/llm/summarizer.py +70 -0
  100. claude_mpm/commander/memory/__init__.py +45 -0
  101. claude_mpm/commander/memory/compression.py +347 -0
  102. claude_mpm/commander/memory/embeddings.py +230 -0
  103. claude_mpm/commander/memory/entities.py +310 -0
  104. claude_mpm/commander/memory/example_usage.py +290 -0
  105. claude_mpm/commander/memory/integration.py +325 -0
  106. claude_mpm/commander/memory/search.py +381 -0
  107. claude_mpm/commander/memory/store.py +657 -0
  108. claude_mpm/commander/models/__init__.py +18 -0
  109. claude_mpm/commander/models/events.py +127 -0
  110. claude_mpm/commander/models/project.py +162 -0
  111. claude_mpm/commander/models/work.py +214 -0
  112. claude_mpm/commander/parsing/__init__.py +20 -0
  113. claude_mpm/commander/parsing/extractor.py +132 -0
  114. claude_mpm/commander/parsing/output_parser.py +270 -0
  115. claude_mpm/commander/parsing/patterns.py +100 -0
  116. claude_mpm/commander/persistence/__init__.py +11 -0
  117. claude_mpm/commander/persistence/event_store.py +274 -0
  118. claude_mpm/commander/persistence/state_store.py +403 -0
  119. claude_mpm/commander/persistence/work_store.py +164 -0
  120. claude_mpm/commander/polling/__init__.py +13 -0
  121. claude_mpm/commander/polling/event_detector.py +104 -0
  122. claude_mpm/commander/polling/output_buffer.py +49 -0
  123. claude_mpm/commander/polling/output_poller.py +153 -0
  124. claude_mpm/commander/project_session.py +268 -0
  125. claude_mpm/commander/proxy/__init__.py +12 -0
  126. claude_mpm/commander/proxy/formatter.py +89 -0
  127. claude_mpm/commander/proxy/output_handler.py +191 -0
  128. claude_mpm/commander/proxy/relay.py +155 -0
  129. claude_mpm/commander/registry.py +410 -0
  130. claude_mpm/commander/runtime/__init__.py +10 -0
  131. claude_mpm/commander/runtime/executor.py +191 -0
  132. claude_mpm/commander/runtime/monitor.py +346 -0
  133. claude_mpm/commander/session/__init__.py +6 -0
  134. claude_mpm/commander/session/context.py +81 -0
  135. claude_mpm/commander/session/manager.py +59 -0
  136. claude_mpm/commander/tmux_orchestrator.py +362 -0
  137. claude_mpm/commander/web/__init__.py +1 -0
  138. claude_mpm/commander/work/__init__.py +30 -0
  139. claude_mpm/commander/work/executor.py +207 -0
  140. claude_mpm/commander/work/queue.py +405 -0
  141. claude_mpm/commander/workflow/__init__.py +27 -0
  142. claude_mpm/commander/workflow/event_handler.py +241 -0
  143. claude_mpm/commander/workflow/notifier.py +146 -0
  144. claude_mpm/commands/mpm-config.md +8 -0
  145. claude_mpm/commands/mpm-doctor.md +8 -0
  146. claude_mpm/commands/mpm-help.md +8 -0
  147. claude_mpm/commands/mpm-init.md +8 -0
  148. claude_mpm/commands/mpm-monitor.md +8 -0
  149. claude_mpm/commands/mpm-organize.md +8 -0
  150. claude_mpm/commands/mpm-postmortem.md +8 -0
  151. claude_mpm/commands/mpm-session-resume.md +9 -1
  152. claude_mpm/commands/mpm-status.md +8 -0
  153. claude_mpm/commands/mpm-ticket-view.md +8 -0
  154. claude_mpm/commands/mpm-version.md +8 -0
  155. claude_mpm/commands/mpm.md +8 -0
  156. claude_mpm/config/agent_presets.py +8 -7
  157. claude_mpm/config/skill_sources.py +16 -0
  158. claude_mpm/constants.py +6 -0
  159. claude_mpm/core/claude_runner.py +154 -2
  160. claude_mpm/core/config.py +35 -22
  161. claude_mpm/core/config_constants.py +74 -9
  162. claude_mpm/core/constants.py +56 -12
  163. claude_mpm/core/hook_manager.py +53 -4
  164. claude_mpm/core/interactive_session.py +12 -11
  165. claude_mpm/core/logger.py +26 -9
  166. claude_mpm/core/logging_utils.py +39 -13
  167. claude_mpm/core/network_config.py +148 -0
  168. claude_mpm/core/oneshot_session.py +7 -6
  169. claude_mpm/core/optimized_startup.py +3 -1
  170. claude_mpm/core/output_style_manager.py +66 -18
  171. claude_mpm/core/shared/config_loader.py +3 -1
  172. claude_mpm/core/socketio_pool.py +47 -15
  173. claude_mpm/core/unified_config.py +54 -8
  174. claude_mpm/core/unified_paths.py +95 -90
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
  188. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
  189. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
  190. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
  191. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
  192. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  193. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  194. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
  195. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
  196. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
  197. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
  198. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
  199. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
  200. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
  201. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
  202. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  203. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
  204. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
  205. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
  206. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  207. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
  208. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  209. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
  210. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
  211. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
  212. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
  213. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
  214. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
  215. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
  216. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  217. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
  218. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
  219. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
  220. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
  221. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
  222. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
  223. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  224. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
  225. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  226. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
  227. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
  228. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
  229. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
  230. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  231. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
  232. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
  233. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
  234. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
  235. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  236. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
  237. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
  238. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  239. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  240. claude_mpm/dashboard/static/svelte-build/index.html +11 -11
  241. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  242. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  243. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  244. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  245. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  246. claude_mpm/experimental/cli_enhancements.py +2 -1
  247. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  248. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  249. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  250. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  251. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  252. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  253. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  254. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
  255. claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
  256. claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
  257. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  258. claude_mpm/hooks/claude_hooks/installer.py +291 -59
  259. claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
  260. claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
  261. claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
  262. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  263. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  264. claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
  265. claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
  266. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  267. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  268. claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
  269. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
  270. claude_mpm/hooks/claude_hooks/services/container.py +326 -0
  271. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  272. claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
  273. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
  274. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  275. claude_mpm/hooks/session_resume_hook.py +89 -1
  276. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  277. claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
  278. claude_mpm/init.py +224 -4
  279. claude_mpm/mcp/__init__.py +9 -0
  280. claude_mpm/mcp/google_workspace_server.py +610 -0
  281. claude_mpm/scripts/claude-hook-handler.sh +46 -19
  282. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  283. claude_mpm/services/agents/agent_selection_service.py +2 -2
  284. claude_mpm/services/agents/cache_git_manager.py +1 -1
  285. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
  286. claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
  287. claude_mpm/services/agents/deployment/agent_template_builder.py +37 -17
  288. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  289. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  290. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  291. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +36 -8
  292. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +50 -26
  293. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  294. claude_mpm/services/agents/git_source_manager.py +21 -2
  295. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  296. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  297. claude_mpm/services/agents/sources/git_source_sync_service.py +116 -5
  298. claude_mpm/services/agents/startup_sync.py +5 -2
  299. claude_mpm/services/cli/__init__.py +3 -0
  300. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  301. claude_mpm/services/cli/session_resume_helper.py +10 -2
  302. claude_mpm/services/command_deployment_service.py +44 -26
  303. claude_mpm/services/delegation_detector.py +175 -0
  304. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  305. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  306. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  307. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  308. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  309. claude_mpm/services/diagnostics/models.py +14 -1
  310. claude_mpm/services/event_log.py +325 -0
  311. claude_mpm/services/hook_installer_service.py +77 -8
  312. claude_mpm/services/infrastructure/__init__.py +4 -0
  313. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  314. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  315. claude_mpm/services/mcp_config_manager.py +99 -19
  316. claude_mpm/services/mcp_service_registry.py +294 -0
  317. claude_mpm/services/monitor/daemon_manager.py +15 -4
  318. claude_mpm/services/monitor/management/lifecycle.py +8 -3
  319. claude_mpm/services/monitor/server.py +111 -16
  320. claude_mpm/services/pm_skills_deployer.py +302 -94
  321. claude_mpm/services/profile_manager.py +10 -4
  322. claude_mpm/services/skills/git_skill_source_manager.py +192 -29
  323. claude_mpm/services/skills/selective_skill_deployer.py +211 -46
  324. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  325. claude_mpm/services/skills_deployer.py +192 -70
  326. claude_mpm/services/socketio/handlers/hook.py +14 -7
  327. claude_mpm/services/socketio/server/main.py +12 -4
  328. claude_mpm/skills/__init__.py +2 -1
  329. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  330. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  331. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  332. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  333. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  334. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  335. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  336. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  337. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  338. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  339. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  340. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  341. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  342. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  343. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  344. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  345. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  346. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  347. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  348. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  349. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  350. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  351. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  352. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  353. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  354. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  355. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  356. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  357. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  358. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  359. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  360. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  361. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  362. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  363. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  364. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  365. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  366. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  367. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  368. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  369. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  370. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  371. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  372. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  373. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  374. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  375. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  376. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  377. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  378. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  379. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  380. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  381. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  382. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  383. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  384. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  385. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  386. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  387. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  388. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  389. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  390. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  391. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  392. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  393. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  394. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  395. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  396. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  397. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  398. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  399. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  400. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  401. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  402. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  403. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  404. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  405. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  406. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  407. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  408. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  409. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  410. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  411. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  412. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  413. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  414. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  415. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  416. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  417. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  418. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  419. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  420. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  421. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  422. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  423. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  424. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  425. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  426. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  427. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  428. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  429. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  430. claude_mpm/skills/bundled/security-scanning.md +112 -0
  431. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  432. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  433. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  434. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  435. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  436. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  437. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  438. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  439. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  440. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  441. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  442. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  443. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  444. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  445. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  446. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  447. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  448. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  449. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  450. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  451. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  452. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  453. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  454. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  455. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  456. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  457. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  458. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  459. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  460. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  461. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  462. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  463. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  464. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  465. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  466. claude_mpm/skills/registry.py +295 -90
  467. claude_mpm/skills/skill_manager.py +29 -23
  468. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  469. claude_mpm/utils/agent_dependency_loader.py +103 -4
  470. claude_mpm/utils/robust_installer.py +45 -24
  471. claude_mpm-5.6.72.dist-info/METADATA +416 -0
  472. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/RECORD +477 -159
  473. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/WHEEL +1 -1
  474. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/entry_points.txt +2 -0
  475. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
  476. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
  477. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
  478. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
  479. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
  480. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
  481. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
  482. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
  483. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
  484. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
  485. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  486. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  487. claude_mpm-5.4.41.dist-info/METADATA +0 -998
  488. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE +0 -0
  489. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  490. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/top_level.txt +0 -0
@@ -523,23 +523,25 @@ PM: Task(agent="qa", task="Verify bug fix with regression test")
523
523
 
524
524
  ### KEY PRINCIPLE
525
525
 
526
- PM delegates implementation work, then MAY verify results.
526
+ PM delegates ALL work - implementation AND verification.
527
527
 
528
528
  **Workflow:**
529
- 1. **DELEGATE** to agent (using Task tool)
529
+ 1. **DELEGATE** implementation to appropriate agent (using Task tool)
530
530
  2. **WAIT** for agent to complete work
531
- 3. **VERIFY** results (using Bash verification commands OR delegating verification)
532
- 4. **REPORT** verified results with evidence
531
+ 3. **DELEGATE** verification to appropriate agent (local-ops, QA, web-qa)
532
+ 4. **REPORT** verified results with evidence from verification agent
533
533
 
534
- ### Allowed Verification Commands (AFTER Delegation)
534
+ ### PM NEVER Uses Verification Commands
535
535
 
536
- These commands are ALLOWED for quality assurance AFTER delegating implementation:
536
+ **FORBIDDEN for PM** (must delegate to local-ops or QA):
537
537
 
538
- - `curl`, `wget` - HTTP endpoint testing
539
- - `lsof`, `netstat`, `ss` - Port and network checks
540
- - `ps`, `pgrep` - Process status checks
541
- - `pm2 status`, `docker ps` - Service status
542
- - Health check endpoints
538
+ - `curl`, `wget` - HTTP endpoint testing → Delegate to api-qa or local-ops
539
+ - `lsof`, `netstat`, `ss` - Port and network checks → Delegate to local-ops
540
+ - `ps`, `pgrep` - Process status checks → Delegate to local-ops
541
+ - `pm2 status`, `docker ps` - Service status → Delegate to local-ops
542
+ - Health check endpoints → Delegate to api-qa or web-qa
543
+
544
+ **Why PM doesn't verify**: Verification is technical work requiring domain expertise. local-ops and QA agents have the tools, context, and expertise to verify correctly.
543
545
 
544
546
  ### Examples
545
547
 
@@ -550,23 +552,29 @@ These commands are ALLOWED for quality assurance AFTER delegating implementation
550
552
  PM: Bash("npm start") # VIOLATION - implementing
551
553
  PM: "App running on localhost:3000" # VIOLATION - no delegation
552
554
 
555
+ # Wrong: PM using verification commands
556
+ PM: Bash("lsof -i :3000") # VIOLATION - should delegate to local-ops
557
+ PM: Bash("curl http://localhost:3000") # VIOLATION - should delegate to api-qa
558
+
553
559
  # Wrong: PM testing before delegating implementation
554
560
  PM: Bash("npm test") # VIOLATION - testing without implementation
555
561
 
556
562
  # Wrong: "Let me" thinking
557
563
  PM: "Let me check the code..." # VIOLATION - should delegate
558
564
  PM: "Let me fix this bug..." # VIOLATION - should delegate
565
+ PM: "Let me verify the deployment..." # VIOLATION - should delegate to local-ops
559
566
  ```
560
567
 
561
568
  #### ✅ CORRECT Examples
562
569
 
563
570
  ```
564
- # Correct: Delegate first, then verify
565
- PM: Task(agent="local-ops-agent", task="Start app on localhost:3000 using npm")
566
- [Agent starts app]
567
- PM: Bash("lsof -i :3000 | grep LISTEN") # ALLOWED - verifying after delegation
568
- PM: Bash("curl http://localhost:3000") # ALLOWED - confirming deployment
569
- PM: "App verified: Port 3000 listening, HTTP 200 response"
571
+ # Correct: Delegate implementation, then delegate verification
572
+ PM: Task(agent="local-ops", task="Start app on localhost:3000 using npm")
573
+ [local-ops starts app]
574
+ PM: Task(agent="local-ops", task="Verify app is running on port 3000")
575
+ [local-ops uses lsof and curl to verify]
576
+ [local-ops returns: "Port 3000 listening, HTTP 200 response"]
577
+ PM: "App verified by local-ops: Port 3000 listening, HTTP 200 response"
570
578
 
571
579
  # Correct: Delegate implementation, then delegate testing
572
580
  PM: Task(agent="engineer", task="Fix authentication bug")
@@ -578,6 +586,7 @@ PM: "Bug fix verified by QA: All tests passed"
578
586
  # Correct: Thinking in delegation terms
579
587
  PM: "I'll have Research check the code..."
580
588
  PM: "I'll delegate this fix to Engineer..."
589
+ PM: "I'll have local-ops verify the deployment..."
581
590
  ```
582
591
 
583
592
  ---
@@ -0,0 +1,35 @@
1
+ """OAuth authentication module for MCP services.
2
+
3
+ This module provides secure OAuth token management and callback handling
4
+ for authenticating with MCP services that require OAuth2 flows.
5
+
6
+ Core Components:
7
+ - OAuthToken: Token data model with expiration handling
8
+ - TokenStorage: Secure encrypted token persistence
9
+ - OAuthCallbackServer: Local HTTP server for OAuth callbacks
10
+ - OAuthProvider: Abstract base class for OAuth providers
11
+ - GoogleOAuthProvider: Google OAuth2 implementation
12
+ """
13
+
14
+ from claude_mpm.auth.callback_server import OAuthCallbackServer
15
+ from claude_mpm.auth.models import (
16
+ OAuthToken,
17
+ StoredToken,
18
+ TokenMetadata,
19
+ TokenStatus,
20
+ )
21
+ from claude_mpm.auth.oauth_manager import OAuthManager
22
+ from claude_mpm.auth.providers import GoogleOAuthProvider, OAuthProvider
23
+ from claude_mpm.auth.token_storage import TokenStorage
24
+
25
+ __all__ = [
26
+ "GoogleOAuthProvider",
27
+ "OAuthCallbackServer",
28
+ "OAuthManager",
29
+ "OAuthProvider",
30
+ "OAuthToken",
31
+ "StoredToken",
32
+ "TokenMetadata",
33
+ "TokenStatus",
34
+ "TokenStorage",
35
+ ]
@@ -0,0 +1,328 @@
1
+ """OAuth callback server for handling authorization redirects.
2
+
3
+ This module provides a local HTTP server that handles OAuth2 callback
4
+ redirects, capturing authorization codes and tokens from OAuth providers.
5
+
6
+ Security Features:
7
+ - Binds only to localhost (127.0.0.1)
8
+ - CSRF protection via state parameter validation
9
+ - Automatic server shutdown after callback received
10
+ - Configurable timeout for callback wait
11
+ """
12
+
13
+ import asyncio
14
+ import secrets
15
+ from dataclasses import dataclass, field
16
+ from typing import Optional
17
+
18
+ from aiohttp import web
19
+
20
+ # Default port for OAuth callback server
21
+ DEFAULT_PORT = 8789
22
+
23
+ # HTML response templates
24
+ SUCCESS_HTML = """
25
+ <!DOCTYPE html>
26
+ <html>
27
+ <head>
28
+ <title>Authorization Successful</title>
29
+ <style>
30
+ body {
31
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
32
+ display: flex;
33
+ justify-content: center;
34
+ align-items: center;
35
+ height: 100vh;
36
+ margin: 0;
37
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
38
+ }
39
+ .container {
40
+ background: white;
41
+ padding: 40px 60px;
42
+ border-radius: 12px;
43
+ box-shadow: 0 10px 40px rgba(0,0,0,0.2);
44
+ text-align: center;
45
+ }
46
+ .success-icon {
47
+ font-size: 64px;
48
+ margin-bottom: 20px;
49
+ }
50
+ h1 { color: #22c55e; margin: 0 0 10px 0; }
51
+ p { color: #666; margin: 0; }
52
+ </style>
53
+ </head>
54
+ <body>
55
+ <div class="container">
56
+ <div class="success-icon">&#10004;</div>
57
+ <h1>Authorization Successful</h1>
58
+ <p>You can close this window and return to Claude.</p>
59
+ </div>
60
+ </body>
61
+ </html>
62
+ """
63
+
64
+ ERROR_HTML = """
65
+ <!DOCTYPE html>
66
+ <html>
67
+ <head>
68
+ <title>Authorization Failed</title>
69
+ <style>
70
+ body {
71
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
72
+ display: flex;
73
+ justify-content: center;
74
+ align-items: center;
75
+ height: 100vh;
76
+ margin: 0;
77
+ background: linear-gradient(135deg, #f87171 0%, #dc2626 100%);
78
+ }
79
+ .container {
80
+ background: white;
81
+ padding: 40px 60px;
82
+ border-radius: 12px;
83
+ box-shadow: 0 10px 40px rgba(0,0,0,0.2);
84
+ text-align: center;
85
+ }
86
+ .error-icon {
87
+ font-size: 64px;
88
+ margin-bottom: 20px;
89
+ }
90
+ h1 { color: #dc2626; margin: 0 0 10px 0; }
91
+ p { color: #666; margin: 0; }
92
+ .error-detail {
93
+ color: #999;
94
+ font-size: 14px;
95
+ margin-top: 15px;
96
+ padding: 10px;
97
+ background: #f5f5f5;
98
+ border-radius: 6px;
99
+ }
100
+ </style>
101
+ </head>
102
+ <body>
103
+ <div class="container">
104
+ <div class="error-icon">&#10006;</div>
105
+ <h1>Authorization Failed</h1>
106
+ <p>An error occurred during authorization.</p>
107
+ <div class="error-detail">{error}</div>
108
+ </div>
109
+ </body>
110
+ </html>
111
+ """
112
+
113
+
114
+ @dataclass
115
+ class CallbackResult:
116
+ """Result from an OAuth callback.
117
+
118
+ Attributes:
119
+ success: Whether the callback was successful.
120
+ code: Authorization code if successful.
121
+ state: State parameter from the callback.
122
+ error: Error message if unsuccessful.
123
+ error_description: Detailed error description from provider.
124
+ """
125
+
126
+ success: bool
127
+ code: Optional[str] = None
128
+ state: Optional[str] = None
129
+ error: Optional[str] = None
130
+ error_description: Optional[str] = None
131
+
132
+
133
+ @dataclass
134
+ class OAuthCallbackServer:
135
+ """Local HTTP server for OAuth2 callback handling.
136
+
137
+ This server listens on localhost for OAuth redirect callbacks,
138
+ captures the authorization code or token, and provides it to
139
+ the calling code.
140
+
141
+ The server implements CSRF protection by generating a unique
142
+ state parameter that must be validated in the callback.
143
+
144
+ Attributes:
145
+ port: Port to listen on, defaults to 8789.
146
+ host: Host to bind to, always 127.0.0.1 for security.
147
+
148
+ Example:
149
+ ```python
150
+ server = OAuthCallbackServer()
151
+ state = server.generate_state()
152
+
153
+ # Use server.callback_url and state in OAuth authorization URL
154
+ auth_url = f"https://provider.com/oauth/authorize?redirect_uri={server.callback_url}&state={state}"
155
+
156
+ # Wait for callback (user completes auth in browser)
157
+ result = await server.wait_for_callback(expected_state=state, timeout=300)
158
+
159
+ if result.success:
160
+ print(f"Got authorization code: {result.code}")
161
+ else:
162
+ print(f"Error: {result.error}")
163
+ ```
164
+ """
165
+
166
+ port: int = DEFAULT_PORT
167
+ host: str = field(default="127.0.0.1", init=False)
168
+ _state: Optional[str] = field(default=None, init=False, repr=False)
169
+ _result: Optional[CallbackResult] = field(default=None, init=False, repr=False)
170
+ _callback_received: asyncio.Event = field(
171
+ default_factory=asyncio.Event, init=False, repr=False
172
+ )
173
+
174
+ @property
175
+ def callback_url(self) -> str:
176
+ """Get the callback URL for OAuth configuration.
177
+
178
+ Returns:
179
+ The full callback URL including host and port.
180
+ """
181
+ return f"http://{self.host}:{self.port}/callback"
182
+
183
+ def generate_state(self) -> str:
184
+ """Generate a cryptographically secure state parameter.
185
+
186
+ The state parameter is used for CSRF protection in the OAuth flow.
187
+ It should be included in the authorization request and validated
188
+ when the callback is received.
189
+
190
+ Returns:
191
+ A 32-character URL-safe random string.
192
+ """
193
+ self._state = secrets.token_urlsafe(24)
194
+ return self._state
195
+
196
+ async def _handle_callback(self, request: web.Request) -> web.Response:
197
+ """Handle the OAuth callback request.
198
+
199
+ Args:
200
+ request: The incoming HTTP request.
201
+
202
+ Returns:
203
+ HTML response indicating success or failure.
204
+ """
205
+ # Extract query parameters
206
+ code = request.query.get("code")
207
+ state = request.query.get("state")
208
+ error = request.query.get("error")
209
+ error_description = request.query.get("error_description", "")
210
+
211
+ # Check for error from provider
212
+ if error:
213
+ self._result = CallbackResult(
214
+ success=False,
215
+ state=state,
216
+ error=error,
217
+ error_description=error_description,
218
+ )
219
+ self._callback_received.set()
220
+ return web.Response(
221
+ text=ERROR_HTML.format(error=f"{error}: {error_description}"),
222
+ content_type="text/html",
223
+ )
224
+
225
+ # Validate state parameter (CSRF protection)
226
+ if self._state and state != self._state:
227
+ self._result = CallbackResult(
228
+ success=False,
229
+ state=state,
230
+ error="state_mismatch",
231
+ error_description="State parameter does not match. Possible CSRF attack.",
232
+ )
233
+ self._callback_received.set()
234
+ return web.Response(
235
+ text=ERROR_HTML.format(error="State mismatch - possible CSRF attack"),
236
+ content_type="text/html",
237
+ )
238
+
239
+ # Check for authorization code
240
+ if not code:
241
+ self._result = CallbackResult(
242
+ success=False,
243
+ state=state,
244
+ error="missing_code",
245
+ error_description="No authorization code received.",
246
+ )
247
+ self._callback_received.set()
248
+ return web.Response(
249
+ text=ERROR_HTML.format(error="No authorization code received"),
250
+ content_type="text/html",
251
+ )
252
+
253
+ # Success
254
+ self._result = CallbackResult(
255
+ success=True,
256
+ code=code,
257
+ state=state,
258
+ )
259
+ self._callback_received.set()
260
+ return web.Response(text=SUCCESS_HTML, content_type="text/html")
261
+
262
+ async def wait_for_callback(
263
+ self,
264
+ expected_state: Optional[str] = None,
265
+ timeout: float = 300.0,
266
+ ) -> CallbackResult:
267
+ """Start the server and wait for an OAuth callback.
268
+
269
+ This method starts the HTTP server, waits for a callback request,
270
+ validates the state parameter, and returns the result.
271
+
272
+ Args:
273
+ expected_state: State parameter to validate against.
274
+ If not provided, uses the last generated state.
275
+ timeout: Maximum time to wait for callback in seconds.
276
+ Defaults to 300 seconds (5 minutes).
277
+
278
+ Returns:
279
+ CallbackResult containing the authorization code or error.
280
+
281
+ Raises:
282
+ asyncio.TimeoutError: If no callback received within timeout.
283
+ """
284
+ # Set expected state
285
+ if expected_state:
286
+ self._state = expected_state
287
+
288
+ # Reset state for new wait
289
+ self._result = None
290
+ self._callback_received.clear()
291
+
292
+ # Create aiohttp app and routes
293
+ app = web.Application()
294
+ app.router.add_get("/callback", self._handle_callback)
295
+
296
+ # Create and start runner
297
+ runner = web.AppRunner(app)
298
+ await runner.setup()
299
+
300
+ site = web.TCPSite(runner, self.host, self.port)
301
+ await site.start()
302
+
303
+ try:
304
+ # Wait for callback with timeout
305
+ await asyncio.wait_for(
306
+ self._callback_received.wait(),
307
+ timeout=timeout,
308
+ )
309
+
310
+ if self._result is None:
311
+ return CallbackResult(
312
+ success=False,
313
+ error="unknown_error",
314
+ error_description="Callback received but no result set.",
315
+ )
316
+
317
+ return self._result
318
+
319
+ except asyncio.TimeoutError:
320
+ return CallbackResult(
321
+ success=False,
322
+ error="timeout",
323
+ error_description=f"No callback received within {timeout} seconds.",
324
+ )
325
+
326
+ finally:
327
+ # Clean up server
328
+ await runner.cleanup()
@@ -0,0 +1,104 @@
1
+ """OAuth data models for token management.
2
+
3
+ This module defines Pydantic models for OAuth tokens and their metadata,
4
+ providing type-safe token handling with automatic validation.
5
+ """
6
+
7
+ from datetime import datetime, timezone
8
+ from enum import Enum
9
+ from typing import Optional
10
+
11
+ from pydantic import BaseModel, Field
12
+
13
+
14
+ class TokenStatus(str, Enum):
15
+ """Status of an OAuth token."""
16
+
17
+ VALID = "valid"
18
+ EXPIRED = "expired"
19
+ MISSING = "missing"
20
+ INVALID = "invalid"
21
+
22
+
23
+ class OAuthToken(BaseModel):
24
+ """OAuth2 token data.
25
+
26
+ Represents the token response from an OAuth provider with
27
+ expiration tracking and scope management.
28
+
29
+ Attributes:
30
+ access_token: The access token string for API authentication.
31
+ refresh_token: Optional refresh token for token renewal.
32
+ expires_at: UTC timestamp when the access token expires.
33
+ scopes: List of granted OAuth scopes.
34
+ token_type: Token type, typically "Bearer".
35
+ """
36
+
37
+ access_token: str = Field(..., description="OAuth access token")
38
+ refresh_token: Optional[str] = Field(
39
+ default=None, description="OAuth refresh token for renewal"
40
+ )
41
+ expires_at: datetime = Field(..., description="Token expiration timestamp (UTC)")
42
+ scopes: list[str] = Field(default_factory=list, description="Granted OAuth scopes")
43
+ token_type: str = Field(default="Bearer", description="Token type")
44
+
45
+ def is_expired(self, buffer_seconds: int = 60) -> bool:
46
+ """Check if the token is expired or about to expire.
47
+
48
+ Args:
49
+ buffer_seconds: Number of seconds before actual expiration
50
+ to consider the token expired. Defaults to 60 seconds
51
+ to allow time for token refresh.
52
+
53
+ Returns:
54
+ True if the token is expired or will expire within the buffer period.
55
+ """
56
+ now = datetime.now(timezone.utc)
57
+ # Ensure expires_at is timezone-aware
58
+ expires_at = self.expires_at
59
+ if expires_at.tzinfo is None:
60
+ expires_at = expires_at.replace(tzinfo=timezone.utc)
61
+
62
+ from datetime import timedelta
63
+
64
+ return now >= (expires_at - timedelta(seconds=buffer_seconds))
65
+
66
+
67
+ class TokenMetadata(BaseModel):
68
+ """Metadata about a stored OAuth token.
69
+
70
+ Tracks service information and timestamps for token lifecycle management.
71
+
72
+ Attributes:
73
+ service_name: Name of the MCP service this token authenticates.
74
+ provider: OAuth provider identifier (e.g., "github", "google").
75
+ created_at: When the token was first stored.
76
+ last_refreshed: When the token was last refreshed, if applicable.
77
+ """
78
+
79
+ service_name: str = Field(..., description="MCP service name")
80
+ provider: str = Field(..., description="OAuth provider identifier")
81
+ created_at: datetime = Field(
82
+ default_factory=lambda: datetime.now(timezone.utc),
83
+ description="Token creation timestamp",
84
+ )
85
+ last_refreshed: Optional[datetime] = Field(
86
+ default=None, description="Last token refresh timestamp"
87
+ )
88
+
89
+
90
+ class StoredToken(BaseModel):
91
+ """Complete stored token with metadata and versioning.
92
+
93
+ This is the top-level structure persisted to storage, containing
94
+ both the token data and metadata needed for management.
95
+
96
+ Attributes:
97
+ version: Schema version for future migration support.
98
+ metadata: Token metadata including service and provider info.
99
+ token: The actual OAuth token data.
100
+ """
101
+
102
+ version: int = Field(default=1, description="Schema version for migrations")
103
+ metadata: TokenMetadata = Field(..., description="Token metadata")
104
+ token: OAuthToken = Field(..., description="OAuth token data")