claude-mpm 5.0.9__py3-none-any.whl → 5.4.41__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +4 -0
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/{PM_INSTRUCTIONS_TEACH.md → CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md} +721 -41
- claude_mpm/agents/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +468 -468
- claude_mpm/agents/WORKFLOW.md +5 -254
- claude_mpm/agents/agent_loader.py +13 -44
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/frontmatter_validator.py +70 -2
- claude_mpm/agents/templates/circuit-breakers.md +431 -45
- claude_mpm/cli/__init__.py +0 -1
- claude_mpm/cli/__main__.py +4 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/agent_state_manager.py +18 -27
- claude_mpm/cli/commands/agents.py +175 -37
- claude_mpm/cli/commands/auto_configure.py +723 -236
- claude_mpm/cli/commands/config.py +88 -2
- claude_mpm/cli/commands/configure.py +1262 -157
- claude_mpm/cli/commands/configure_agent_display.py +25 -6
- claude_mpm/cli/commands/mpm_init/core.py +225 -46
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
- claude_mpm/cli/commands/postmortem.py +1 -1
- claude_mpm/cli/commands/profile.py +277 -0
- claude_mpm/cli/commands/skills.py +214 -189
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/executor.py +21 -3
- claude_mpm/cli/interactive/agent_wizard.py +85 -10
- claude_mpm/cli/parsers/agents_parser.py +54 -9
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
- claude_mpm/cli/parsers/base_parser.py +12 -0
- claude_mpm/cli/parsers/config_parser.py +153 -83
- claude_mpm/cli/parsers/profile_parser.py +148 -0
- claude_mpm/cli/parsers/skills_parser.py +3 -2
- claude_mpm/cli/startup.py +879 -149
- claude_mpm/commands/mpm-config.md +28 -0
- claude_mpm/commands/mpm-doctor.md +9 -22
- claude_mpm/commands/mpm-help.md +5 -287
- claude_mpm/commands/mpm-init.md +81 -507
- claude_mpm/commands/mpm-monitor.md +15 -402
- claude_mpm/commands/mpm-organize.md +120 -0
- claude_mpm/commands/mpm-postmortem.md +6 -108
- claude_mpm/commands/mpm-session-resume.md +12 -363
- claude_mpm/commands/mpm-status.md +5 -69
- claude_mpm/commands/mpm-ticket-view.md +52 -495
- claude_mpm/commands/mpm-version.md +5 -107
- claude_mpm/config/agent_sources.py +27 -0
- claude_mpm/core/config.py +2 -4
- claude_mpm/core/framework/formatters/content_formatter.py +3 -13
- claude_mpm/core/framework/loaders/agent_loader.py +8 -5
- claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
- claude_mpm/core/framework_loader.py +4 -2
- claude_mpm/core/logger.py +13 -0
- claude_mpm/core/optimized_startup.py +59 -0
- claude_mpm/core/output_style_manager.py +173 -43
- claude_mpm/core/shared/config_loader.py +1 -1
- claude_mpm/core/socketio_pool.py +3 -3
- claude_mpm/core/unified_agent_registry.py +134 -16
- claude_mpm/core/unified_config.py +22 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
- claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
- claude_mpm/hooks/claude_hooks/installer.py +33 -10
- claude_mpm/hooks/claude_hooks/memory_integration.py +28 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +30 -6
- claude_mpm/hooks/memory_integration_hook.py +46 -1
- claude_mpm/init.py +63 -19
- claude_mpm/models/agent_definition.py +7 -0
- claude_mpm/models/git_repository.py +3 -3
- claude_mpm/scripts/claude-hook-handler.sh +58 -18
- claude_mpm/scripts/launch_monitor.py +93 -13
- claude_mpm/scripts/start_activity_logging.py +0 -0
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/cache_git_manager.py +6 -6
- claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -5
- claude_mpm/services/agents/deployment/agent_template_builder.py +5 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +320 -29
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +546 -68
- claude_mpm/services/agents/git_source_manager.py +36 -2
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
- claude_mpm/services/agents/sources/git_source_sync_service.py +13 -6
- claude_mpm/services/agents/startup_sync.py +22 -2
- claude_mpm/services/agents/toolchain_detector.py +10 -6
- claude_mpm/services/analysis/__init__.py +11 -1
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/command_deployment_service.py +81 -10
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
- claude_mpm/services/event_bus/config.py +3 -1
- claude_mpm/services/git/git_operations_service.py +101 -16
- claude_mpm/services/monitor/daemon.py +9 -2
- claude_mpm/services/monitor/daemon_manager.py +39 -3
- claude_mpm/services/monitor/management/lifecycle.py +8 -1
- claude_mpm/services/monitor/server.py +698 -22
- claude_mpm/services/pm_skills_deployer.py +676 -0
- claude_mpm/services/profile_manager.py +331 -0
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/self_upgrade_service.py +120 -12
- claude_mpm/services/skills/__init__.py +3 -0
- claude_mpm/services/skills/git_skill_source_manager.py +130 -2
- claude_mpm/services/skills/selective_skill_deployer.py +704 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_deployer.py +126 -9
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +51 -6
- claude_mpm/services/socketio/server/core.py +386 -108
- claude_mpm/services/version_control/git_operations.py +103 -0
- claude_mpm/skills/skill_manager.py +92 -3
- claude_mpm/utils/agent_dependency_loader.py +14 -2
- claude_mpm/utils/agent_filters.py +17 -44
- claude_mpm/utils/gitignore.py +3 -0
- claude_mpm/utils/migration.py +4 -4
- claude_mpm/utils/robust_installer.py +47 -3
- {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/METADATA +57 -87
- {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/RECORD +160 -211
- claude_mpm-5.4.41.dist-info/entry_points.txt +5 -0
- claude_mpm-5.4.41.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.41.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
- claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
- claude_mpm/agents/BASE_OPS.md +0 -219
- claude_mpm/agents/BASE_PM.md +0 -480
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
- claude_mpm/agents/BASE_QA.md +0 -167
- claude_mpm/agents/BASE_RESEARCH.md +0 -53
- claude_mpm/agents/base_agent_loader.py +0 -601
- claude_mpm/cli/commands/agents_detect.py +0 -380
- claude_mpm/cli/commands/agents_recommend.py +0 -309
- claude_mpm/cli/ticket_cli.py +0 -35
- claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
- claude_mpm/commands/mpm-agents-detect.md +0 -177
- claude_mpm/commands/mpm-agents-list.md +0 -131
- claude_mpm/commands/mpm-agents-recommend.md +0 -223
- claude_mpm/commands/mpm-config-view.md +0 -150
- claude_mpm/commands/mpm-ticket-organize.md +0 -304
- claude_mpm/dashboard/analysis_runner.py +0 -455
- claude_mpm/dashboard/index.html +0 -13
- claude_mpm/dashboard/open_dashboard.py +0 -66
- claude_mpm/dashboard/static/css/activity.css +0 -1958
- claude_mpm/dashboard/static/css/connection-status.css +0 -370
- claude_mpm/dashboard/static/css/dashboard.css +0 -4701
- claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
- claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
- claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
- claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
- claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
- claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
- claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
- claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
- claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
- claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
- claude_mpm/dashboard/static/js/connection-manager.js +0 -536
- claude_mpm/dashboard/static/js/dashboard.js +0 -1914
- claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/js/socket-client.js +0 -1474
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/socket.io.min.js +0 -7
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
- claude_mpm/dashboard/templates/code_simple.html +0 -153
- claude_mpm/dashboard/templates/index.html +0 -606
- claude_mpm/dashboard/test_dashboard.html +0 -372
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm/scripts/mcp_server.py +0 -75
- claude_mpm/scripts/mcp_wrapper.py +0 -39
- claude_mpm/services/mcp_gateway/__init__.py +0 -159
- claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
- claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
- claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
- claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
- claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
- claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
- claude_mpm/services/mcp_gateway/core/base.py +0 -312
- claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
- claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
- claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
- claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
- claude_mpm/services/mcp_gateway/main.py +0 -589
- claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
- claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
- claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
- claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
- claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
- claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
- claude_mpm-5.0.9.dist-info/entry_points.txt +0 -10
- claude_mpm-5.0.9.dist-info/licenses/LICENSE +0 -21
- /claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +0 -0
- {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/WHEEL +0 -0
- {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/top_level.txt +0 -0
|
@@ -1,414 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
MCP Gateway Implementation
|
|
3
|
-
==========================
|
|
4
|
-
|
|
5
|
-
MCP protocol gateway using Anthropic's official MCP package.
|
|
6
|
-
Handles stdio-based communication, request routing, and tool invocation.
|
|
7
|
-
Acts as a bridge between Claude Code and internal tools.
|
|
8
|
-
|
|
9
|
-
NOTE: MCP is ONLY for Claude Code - NOT for Claude Code.
|
|
10
|
-
Claude Code uses a different system for agent deployment.
|
|
11
|
-
|
|
12
|
-
Part of ISS-0035: MCP Gateway Implementation - Core Gateway and Tool Registry
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
import asyncio
|
|
16
|
-
import contextlib
|
|
17
|
-
import json
|
|
18
|
-
import traceback
|
|
19
|
-
from datetime import datetime, timezone
|
|
20
|
-
from typing import Any, Callable, Dict, List, Optional, Union
|
|
21
|
-
|
|
22
|
-
# Import from the official MCP package
|
|
23
|
-
from mcp.server import Server
|
|
24
|
-
from mcp.types import EmbeddedResource, ImageContent, TextContent, Tool
|
|
25
|
-
|
|
26
|
-
from claude_mpm.services.mcp_gateway.core.base import BaseMCPService
|
|
27
|
-
from claude_mpm.services.mcp_gateway.core.interfaces import (
|
|
28
|
-
IMCPCommunication,
|
|
29
|
-
IMCPGateway,
|
|
30
|
-
IMCPToolRegistry,
|
|
31
|
-
MCPToolInvocation,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class MCPGateway(BaseMCPService, IMCPGateway):
|
|
36
|
-
"""
|
|
37
|
-
MCP Protocol Gateway implementation using Anthropic's official MCP package.
|
|
38
|
-
|
|
39
|
-
WHY: We use the official MCP package to ensure protocol compliance and
|
|
40
|
-
compatibility with Claude Code. The stdio-based communication model allows
|
|
41
|
-
seamless integration with Claude Code's MCP client as a protocol bridge.
|
|
42
|
-
|
|
43
|
-
DESIGN DECISIONS:
|
|
44
|
-
- Use asyncio for all I/O operations to handle concurrent requests efficiently
|
|
45
|
-
- Maintain request handlers in a dictionary for extensibility
|
|
46
|
-
- Implement comprehensive error handling to prevent gateway crashes
|
|
47
|
-
- Use structured logging for debugging and monitoring
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
def __init__(self, gateway_name: str = "claude-mpm-mcp", version: str = "1.0.0"):
|
|
51
|
-
"""
|
|
52
|
-
Initialize MCP Gateway.
|
|
53
|
-
|
|
54
|
-
Args:
|
|
55
|
-
gateway_name: Name of the MCP gateway
|
|
56
|
-
version: Gateway version
|
|
57
|
-
"""
|
|
58
|
-
super().__init__(f"MCPGateway-{gateway_name}")
|
|
59
|
-
|
|
60
|
-
# Gateway configuration
|
|
61
|
-
self.gateway_name = gateway_name
|
|
62
|
-
self.server_name = gateway_name # Keep for compatibility
|
|
63
|
-
self.version = version
|
|
64
|
-
|
|
65
|
-
# MCP Server instance from official package
|
|
66
|
-
self.mcp_server = Server(gateway_name)
|
|
67
|
-
|
|
68
|
-
# Dependencies (injected via setters)
|
|
69
|
-
self._tool_registry: Optional[IMCPToolRegistry] = None
|
|
70
|
-
self._communication: Optional[IMCPCommunication] = None
|
|
71
|
-
|
|
72
|
-
# Request handlers
|
|
73
|
-
self._handlers: Dict[str, Callable] = {}
|
|
74
|
-
|
|
75
|
-
# Server capabilities
|
|
76
|
-
self._capabilities = {
|
|
77
|
-
"tools": {},
|
|
78
|
-
"prompts": {},
|
|
79
|
-
"resources": {},
|
|
80
|
-
"experimental": {},
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
# Metrics
|
|
84
|
-
self._metrics = {
|
|
85
|
-
"requests_handled": 0,
|
|
86
|
-
"errors": 0,
|
|
87
|
-
"tool_invocations": 0,
|
|
88
|
-
"start_time": None,
|
|
89
|
-
"last_request_time": None,
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
# Running state
|
|
93
|
-
self._run_task: Optional[asyncio.Task] = None
|
|
94
|
-
self._shutdown_event = asyncio.Event()
|
|
95
|
-
|
|
96
|
-
# Setup default handlers
|
|
97
|
-
self._setup_default_handlers()
|
|
98
|
-
|
|
99
|
-
def _setup_default_handlers(self) -> None:
|
|
100
|
-
"""
|
|
101
|
-
Setup default MCP protocol handlers.
|
|
102
|
-
|
|
103
|
-
WHY: The MCP protocol requires specific handlers for initialization,
|
|
104
|
-
tool discovery, and tool invocation. We set these up to ensure
|
|
105
|
-
protocol compliance.
|
|
106
|
-
"""
|
|
107
|
-
|
|
108
|
-
# Initialize handler
|
|
109
|
-
@self.mcp_server.list_tools()
|
|
110
|
-
async def handle_list_tools() -> List[Tool]:
|
|
111
|
-
"""Handle tools/list request."""
|
|
112
|
-
self.log_info("Handling tools/list request")
|
|
113
|
-
|
|
114
|
-
if not self._tool_registry:
|
|
115
|
-
self.log_warning("No tool registry available")
|
|
116
|
-
return []
|
|
117
|
-
|
|
118
|
-
tools = []
|
|
119
|
-
for tool_def in self._tool_registry.list_tools():
|
|
120
|
-
tool = Tool(
|
|
121
|
-
name=tool_def.name,
|
|
122
|
-
description=tool_def.description,
|
|
123
|
-
inputSchema=tool_def.input_schema,
|
|
124
|
-
)
|
|
125
|
-
tools.append(tool)
|
|
126
|
-
|
|
127
|
-
self.log_info(f"Returning {len(tools)} tools")
|
|
128
|
-
return tools
|
|
129
|
-
|
|
130
|
-
@self.mcp_server.call_tool()
|
|
131
|
-
async def handle_call_tool(
|
|
132
|
-
name: str, arguments: Dict[str, Any]
|
|
133
|
-
) -> List[Union[TextContent, ImageContent, EmbeddedResource]]:
|
|
134
|
-
"""Handle tools/call request."""
|
|
135
|
-
self.log_info(f"Handling tools/call request for tool: {name}")
|
|
136
|
-
|
|
137
|
-
if not self._tool_registry:
|
|
138
|
-
error_msg = "No tool registry available"
|
|
139
|
-
self.log_error(error_msg)
|
|
140
|
-
return [TextContent(type="text", text=f"Error: {error_msg}")]
|
|
141
|
-
|
|
142
|
-
# Create invocation request
|
|
143
|
-
invocation = MCPToolInvocation(
|
|
144
|
-
tool_name=name,
|
|
145
|
-
parameters=arguments,
|
|
146
|
-
request_id=f"req_{datetime.now(timezone.utc).timestamp()}",
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
try:
|
|
150
|
-
# Invoke tool through registry
|
|
151
|
-
result = await self._tool_registry.invoke_tool(invocation)
|
|
152
|
-
|
|
153
|
-
# Update metrics
|
|
154
|
-
self._metrics["tool_invocations"] += 1
|
|
155
|
-
|
|
156
|
-
# Log invocation
|
|
157
|
-
self.log_tool_invocation(name, result.success, result.execution_time)
|
|
158
|
-
|
|
159
|
-
if result.success:
|
|
160
|
-
# Return successful result
|
|
161
|
-
if isinstance(result.data, str):
|
|
162
|
-
return [TextContent(type="text", text=result.data)]
|
|
163
|
-
return [
|
|
164
|
-
TextContent(type="text", text=json.dumps(result.data, indent=2))
|
|
165
|
-
]
|
|
166
|
-
# Return error
|
|
167
|
-
return [TextContent(type="text", text=f"Error: {result.error}")]
|
|
168
|
-
|
|
169
|
-
except Exception as e:
|
|
170
|
-
error_msg = f"Failed to invoke tool {name}: {e!s}"
|
|
171
|
-
self.log_error(error_msg)
|
|
172
|
-
self._metrics["errors"] += 1
|
|
173
|
-
return [TextContent(type="text", text=f"Error: {error_msg}")]
|
|
174
|
-
|
|
175
|
-
def set_tool_registry(self, registry: IMCPToolRegistry) -> None:
|
|
176
|
-
"""
|
|
177
|
-
Set the tool registry for the server.
|
|
178
|
-
|
|
179
|
-
Args:
|
|
180
|
-
registry: Tool registry to use
|
|
181
|
-
"""
|
|
182
|
-
self._tool_registry = registry
|
|
183
|
-
self.log_info("Tool registry set")
|
|
184
|
-
|
|
185
|
-
def set_communication(self, communication: IMCPCommunication) -> None:
|
|
186
|
-
"""
|
|
187
|
-
Set the communication handler.
|
|
188
|
-
|
|
189
|
-
Args:
|
|
190
|
-
communication: Communication handler to use
|
|
191
|
-
"""
|
|
192
|
-
self._communication = communication
|
|
193
|
-
self.log_info("Communication handler set")
|
|
194
|
-
|
|
195
|
-
async def _do_initialize(self) -> bool:
|
|
196
|
-
"""
|
|
197
|
-
Perform server initialization.
|
|
198
|
-
|
|
199
|
-
Returns:
|
|
200
|
-
True if initialization successful
|
|
201
|
-
"""
|
|
202
|
-
try:
|
|
203
|
-
self.log_info("Initializing MCP server components")
|
|
204
|
-
|
|
205
|
-
# Validate dependencies
|
|
206
|
-
if not self._tool_registry:
|
|
207
|
-
self.log_warning("No tool registry set - server will have no tools")
|
|
208
|
-
|
|
209
|
-
# Initialize metrics
|
|
210
|
-
self._metrics["start_time"] = datetime.now(timezone.utc).isoformat()
|
|
211
|
-
|
|
212
|
-
# Update capabilities based on registry
|
|
213
|
-
if self._tool_registry:
|
|
214
|
-
tools = self._tool_registry.list_tools()
|
|
215
|
-
self._capabilities["tools"]["available"] = len(tools)
|
|
216
|
-
self._capabilities["tools"]["names"] = [t.name for t in tools]
|
|
217
|
-
|
|
218
|
-
self.log_info("MCP server initialization complete")
|
|
219
|
-
return True
|
|
220
|
-
|
|
221
|
-
except Exception as e:
|
|
222
|
-
self.log_error(f"Failed to initialize MCP server: {e}")
|
|
223
|
-
return False
|
|
224
|
-
|
|
225
|
-
async def _do_start(self) -> bool:
|
|
226
|
-
"""
|
|
227
|
-
Start the MCP server.
|
|
228
|
-
|
|
229
|
-
Returns:
|
|
230
|
-
True if startup successful
|
|
231
|
-
"""
|
|
232
|
-
try:
|
|
233
|
-
self.log_info("Starting MCP server")
|
|
234
|
-
|
|
235
|
-
# Clear shutdown event
|
|
236
|
-
self._shutdown_event.clear()
|
|
237
|
-
|
|
238
|
-
# Start the run task
|
|
239
|
-
self._run_task = asyncio.create_task(self.run())
|
|
240
|
-
|
|
241
|
-
self.log_info("MCP server started successfully")
|
|
242
|
-
return True
|
|
243
|
-
|
|
244
|
-
except Exception as e:
|
|
245
|
-
self.log_error(f"Failed to start MCP server: {e}")
|
|
246
|
-
return False
|
|
247
|
-
|
|
248
|
-
async def _do_shutdown(self) -> None:
|
|
249
|
-
"""
|
|
250
|
-
Shutdown the MCP server gracefully.
|
|
251
|
-
"""
|
|
252
|
-
self.log_info("Shutting down MCP server")
|
|
253
|
-
|
|
254
|
-
# Signal shutdown
|
|
255
|
-
self._shutdown_event.set()
|
|
256
|
-
|
|
257
|
-
# Cancel run task if active
|
|
258
|
-
if self._run_task and not self._run_task.done():
|
|
259
|
-
self._run_task.cancel()
|
|
260
|
-
with contextlib.suppress(asyncio.CancelledError):
|
|
261
|
-
await self._run_task
|
|
262
|
-
|
|
263
|
-
# Clean up resources
|
|
264
|
-
if self._tool_registry:
|
|
265
|
-
self.log_info("Cleaning up tool registry")
|
|
266
|
-
# Tool registry cleanup if needed
|
|
267
|
-
|
|
268
|
-
self.log_info("MCP server shutdown complete")
|
|
269
|
-
|
|
270
|
-
async def handle_request(self, request: Dict[str, Any]) -> Dict[str, Any]:
|
|
271
|
-
"""
|
|
272
|
-
Handle an MCP request.
|
|
273
|
-
|
|
274
|
-
This method routes requests to appropriate handlers based on the method.
|
|
275
|
-
|
|
276
|
-
Args:
|
|
277
|
-
request: MCP request message
|
|
278
|
-
|
|
279
|
-
Returns:
|
|
280
|
-
Response message
|
|
281
|
-
"""
|
|
282
|
-
try:
|
|
283
|
-
# Update metrics
|
|
284
|
-
self._metrics["requests_handled"] += 1
|
|
285
|
-
self._metrics["last_request_time"] = datetime.now(timezone.utc).isoformat()
|
|
286
|
-
|
|
287
|
-
# Extract request details
|
|
288
|
-
method = request.get("method", "")
|
|
289
|
-
params = request.get("params", {})
|
|
290
|
-
request_id = request.get("id")
|
|
291
|
-
|
|
292
|
-
self.log_debug(f"Handling request: {method}")
|
|
293
|
-
|
|
294
|
-
# Check for custom handler
|
|
295
|
-
if method in self._handlers:
|
|
296
|
-
handler = self._handlers[method]
|
|
297
|
-
result = await handler(params)
|
|
298
|
-
|
|
299
|
-
# Build response
|
|
300
|
-
response = {"jsonrpc": "2.0", "id": request_id, "result": result}
|
|
301
|
-
else:
|
|
302
|
-
# Unknown method
|
|
303
|
-
self.log_warning(f"Unknown method: {method}")
|
|
304
|
-
response = {
|
|
305
|
-
"jsonrpc": "2.0",
|
|
306
|
-
"id": request_id,
|
|
307
|
-
"error": {"code": -32601, "message": f"Method not found: {method}"},
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return response
|
|
311
|
-
|
|
312
|
-
except Exception as e:
|
|
313
|
-
self.log_error(f"Error handling request: {e}")
|
|
314
|
-
self._metrics["errors"] += 1
|
|
315
|
-
|
|
316
|
-
return {
|
|
317
|
-
"jsonrpc": "2.0",
|
|
318
|
-
"id": request.get("id"),
|
|
319
|
-
"error": {"code": -32603, "message": f"Internal error: {e!s}"},
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
async def run(self) -> None:
|
|
323
|
-
"""
|
|
324
|
-
Run the MCP server main loop.
|
|
325
|
-
|
|
326
|
-
This method uses the official MCP Server's stdio-based communication
|
|
327
|
-
to handle incoming requests from Claude Code.
|
|
328
|
-
|
|
329
|
-
WHY: We use stdio (stdin/stdout) as it's the standard communication
|
|
330
|
-
method for MCP servers in Claude Code. This ensures compatibility
|
|
331
|
-
and allows the server to be launched as a subprocess.
|
|
332
|
-
"""
|
|
333
|
-
try:
|
|
334
|
-
self.log_info("Starting MCP server main loop")
|
|
335
|
-
|
|
336
|
-
# Import the stdio server function
|
|
337
|
-
from mcp.server.lowlevel import NotificationOptions
|
|
338
|
-
from mcp.server.models import InitializationOptions
|
|
339
|
-
from mcp.server.stdio import stdio_server
|
|
340
|
-
|
|
341
|
-
# Create initialization options
|
|
342
|
-
init_options = InitializationOptions(
|
|
343
|
-
server_name=self.server_name,
|
|
344
|
-
server_version=self.version,
|
|
345
|
-
capabilities=self.mcp_server.get_capabilities(
|
|
346
|
-
notification_options=NotificationOptions(),
|
|
347
|
-
experimental_capabilities={},
|
|
348
|
-
),
|
|
349
|
-
)
|
|
350
|
-
|
|
351
|
-
# Run the MCP server with stdio transport
|
|
352
|
-
async with stdio_server() as (read_stream, write_stream):
|
|
353
|
-
self.log_info("MCP server stdio connection established")
|
|
354
|
-
|
|
355
|
-
# Run the server
|
|
356
|
-
await self.mcp_server.run(read_stream, write_stream, init_options)
|
|
357
|
-
|
|
358
|
-
self.log_info("MCP server main loop ended")
|
|
359
|
-
|
|
360
|
-
except Exception as e:
|
|
361
|
-
self.log_error(f"Error in MCP server main loop: {e}")
|
|
362
|
-
self.log_error(f"Traceback: {traceback.format_exc()}")
|
|
363
|
-
self._metrics["errors"] += 1
|
|
364
|
-
raise
|
|
365
|
-
|
|
366
|
-
def register_handler(self, method: str, handler: Callable) -> None:
|
|
367
|
-
"""
|
|
368
|
-
Register a custom request handler.
|
|
369
|
-
|
|
370
|
-
Args:
|
|
371
|
-
method: Method name to handle
|
|
372
|
-
handler: Handler function
|
|
373
|
-
"""
|
|
374
|
-
self._handlers[method] = handler
|
|
375
|
-
self.log_info(f"Registered handler for method: {method}")
|
|
376
|
-
|
|
377
|
-
def get_capabilities(self) -> Dict[str, Any]:
|
|
378
|
-
"""
|
|
379
|
-
Get server capabilities.
|
|
380
|
-
|
|
381
|
-
Returns:
|
|
382
|
-
Dictionary of server capabilities formatted for MCP protocol
|
|
383
|
-
"""
|
|
384
|
-
capabilities = {}
|
|
385
|
-
|
|
386
|
-
# Add tool capabilities if registry is available
|
|
387
|
-
if self._tool_registry:
|
|
388
|
-
capabilities["tools"] = {}
|
|
389
|
-
|
|
390
|
-
# Add experimental features
|
|
391
|
-
capabilities["experimental"] = {}
|
|
392
|
-
|
|
393
|
-
return capabilities
|
|
394
|
-
|
|
395
|
-
def get_metrics(self) -> Dict[str, Any]:
|
|
396
|
-
"""
|
|
397
|
-
Get server metrics.
|
|
398
|
-
|
|
399
|
-
Returns:
|
|
400
|
-
Server metrics dictionary
|
|
401
|
-
"""
|
|
402
|
-
return self._metrics.copy()
|
|
403
|
-
|
|
404
|
-
async def stop(self) -> None:
|
|
405
|
-
"""
|
|
406
|
-
Stop the MCP service gracefully.
|
|
407
|
-
|
|
408
|
-
This implements the IMCPLifecycle interface method.
|
|
409
|
-
"""
|
|
410
|
-
await self.shutdown()
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
# Backward compatibility alias
|
|
414
|
-
MCPServer = MCPGateway
|