codemie-mcp-assistants 0.1000.7__tar.gz
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 codemie-mcp-assistants might be problematic. Click here for more details.
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: codemie-mcp-assistants
|
|
3
|
+
Version: 0.1000.7
|
|
4
|
+
Summary: MCP server for connecting to CodeMie Assistants API
|
|
5
|
+
Author: Nikita Levyankov
|
|
6
|
+
Author-email: nikita_levyankov@epam.com
|
|
7
|
+
Requires-Python: >=3.12,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Requires-Dist: certifi (>=2025.1.31,<2026.0.0)
|
|
11
|
+
Requires-Dist: codemie-sdk-python-az (==0.1000.7)
|
|
12
|
+
Requires-Dist: httpx (>=0.27.0,<0.28.0)
|
|
13
|
+
Requires-Dist: mcp (>=1.2.0,<2.0.0)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "codemie-mcp-assistants-az"
|
|
3
|
+
version = "0.1.2"
|
|
4
|
+
description = "MCP server for connecting to CodeMie Assistants API"
|
|
5
|
+
#readme = "README.md"
|
|
6
|
+
packages = [
|
|
7
|
+
{ include = "assistants_mcp", from = "src" }
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
[tool.poetry]
|
|
11
|
+
name = "codemie-mcp-assistants"
|
|
12
|
+
version = "0.1000.7"
|
|
13
|
+
description = "MCP server for connecting to CodeMie Assistants API"
|
|
14
|
+
authors = [
|
|
15
|
+
"Nikita Levyankov <nikita_levyankov@epam.com>",
|
|
16
|
+
]
|
|
17
|
+
#readme = "README.md"
|
|
18
|
+
packages = [
|
|
19
|
+
{ include = "assistants_mcp", from = "src" }
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[tool.poetry.dependencies]
|
|
23
|
+
python = "^3.12"
|
|
24
|
+
mcp = "^1.2.0"
|
|
25
|
+
httpx = "^0.27.0"
|
|
26
|
+
codemie-sdk-python-az = "0.1000.7"
|
|
27
|
+
certifi = "^2025.1.31"
|
|
28
|
+
|
|
29
|
+
[tool.poetry.group.dev.dependencies]
|
|
30
|
+
pytest = "^8.0.0"
|
|
31
|
+
black = "^24.1.0"
|
|
32
|
+
isort = "^5.13.2"
|
|
33
|
+
|
|
34
|
+
[build-system]
|
|
35
|
+
requires = ["poetry-core"]
|
|
36
|
+
build-backend = "poetry.core.masonry.api"
|
|
37
|
+
|
|
38
|
+
[tool.poetry.scripts]
|
|
39
|
+
codemie-mcp-assistant = "src.assistants_mcp:main"
|
|
File without changes
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import uuid
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from codemie_sdk import CodeMieClient
|
|
6
|
+
from codemie_sdk.models.assistant import (
|
|
7
|
+
AssistantChatRequest,
|
|
8
|
+
ChatMessage,
|
|
9
|
+
ChatRole,
|
|
10
|
+
)
|
|
11
|
+
from mcp.server.fastmcp import FastMCP
|
|
12
|
+
|
|
13
|
+
DEFAULT_AUTH_CLIENT_ID = "codemie-sdk"
|
|
14
|
+
DEFAULT_AUTH_REALM_NAME = "codemie-prod"
|
|
15
|
+
DEFAULT_AUTH_SERVER_URL = (
|
|
16
|
+
"https://keycloak.eks-core.aws.main.edp.projects.epam.com/auth"
|
|
17
|
+
)
|
|
18
|
+
DEFAULT_CODEMIE_API_DOMAIN = "https://codemie.lab.epam.com/code-assistant-api"
|
|
19
|
+
|
|
20
|
+
# Initialize FastMCP server
|
|
21
|
+
mcp = FastMCP("codemie-assistants")
|
|
22
|
+
|
|
23
|
+
# Client instance
|
|
24
|
+
_client: Optional[CodeMieClient] = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_client() -> CodeMieClient:
|
|
28
|
+
"""Gets authenticated CodeMie client instance."""
|
|
29
|
+
username = os.getenv("CODEMIE_USERNAME")
|
|
30
|
+
password = os.getenv("CODEMIE_PASSWORD")
|
|
31
|
+
auth_client_id = os.getenv("CODEMIE_AUTH_CLIENT_ID", DEFAULT_AUTH_CLIENT_ID)
|
|
32
|
+
auth_realm_name = os.getenv("CODEMIE_AUTH_REALM_NAME", DEFAULT_AUTH_REALM_NAME)
|
|
33
|
+
auth_server_url = os.getenv("CODEMIE_AUTH_SERVER_URL", DEFAULT_AUTH_SERVER_URL)
|
|
34
|
+
codemie_api_domain = os.getenv("CODEMIE_API_DOMAIN", DEFAULT_CODEMIE_API_DOMAIN)
|
|
35
|
+
|
|
36
|
+
if not username or not password:
|
|
37
|
+
raise ValueError(
|
|
38
|
+
"Username and password must be set via environment variables: CODEMIE_USERNAME, CODEMIE_PASSWORD"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return CodeMieClient(
|
|
42
|
+
username=username,
|
|
43
|
+
password=password,
|
|
44
|
+
verify_ssl=False,
|
|
45
|
+
auth_client_id=auth_client_id,
|
|
46
|
+
auth_realm_name=auth_realm_name,
|
|
47
|
+
auth_server_url=auth_server_url,
|
|
48
|
+
codemie_api_domain=codemie_api_domain,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@mcp.tool()
|
|
53
|
+
async def get_tools() -> List[Dict[str, Any]]:
|
|
54
|
+
"""Get available tools for assistants."""
|
|
55
|
+
try:
|
|
56
|
+
print("Getting tools")
|
|
57
|
+
client = get_client()
|
|
58
|
+
if client.token is None:
|
|
59
|
+
raise ValueError("Client not initialized")
|
|
60
|
+
toolkits = client.assistants.get_tools()
|
|
61
|
+
|
|
62
|
+
# Convert to dict format for better visualization
|
|
63
|
+
tools_list = []
|
|
64
|
+
for toolkit in toolkits:
|
|
65
|
+
tools_list.extend(
|
|
66
|
+
[
|
|
67
|
+
{
|
|
68
|
+
"toolkit": toolkit.toolkit,
|
|
69
|
+
"tool": tool.name,
|
|
70
|
+
"label": tool.label or tool.name,
|
|
71
|
+
"settings_required": tool.settings_config,
|
|
72
|
+
}
|
|
73
|
+
for tool in toolkit.tools
|
|
74
|
+
]
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return tools_list
|
|
78
|
+
except Exception as e:
|
|
79
|
+
print(f"Error getting tools: {str(e)}")
|
|
80
|
+
raise e
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@mcp.tool()
|
|
84
|
+
async def get_assistants(
|
|
85
|
+
minimal: bool = True, project: Optional[str] = None
|
|
86
|
+
) -> List[Dict[str, Any]]:
|
|
87
|
+
"""Get list of available assistants.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
minimal: Return minimal info (default: True)
|
|
91
|
+
project: Filter by project name
|
|
92
|
+
"""
|
|
93
|
+
client = get_client()
|
|
94
|
+
filters = {"project": project} if project else None
|
|
95
|
+
|
|
96
|
+
assistants = client.assistants.list(minimal_response=minimal, filters=filters)
|
|
97
|
+
|
|
98
|
+
# Convert to dict format
|
|
99
|
+
return [
|
|
100
|
+
{
|
|
101
|
+
"id": asst.id,
|
|
102
|
+
"name": asst.name,
|
|
103
|
+
"description": asst.description,
|
|
104
|
+
"project": getattr(asst, "project", None) if not minimal else None,
|
|
105
|
+
}
|
|
106
|
+
for asst in assistants
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@mcp.tool()
|
|
111
|
+
async def chat_with_assistant(
|
|
112
|
+
message: str,
|
|
113
|
+
assistant_id: str,
|
|
114
|
+
conversation_id: Optional[str] = None,
|
|
115
|
+
history: Optional[List[Dict[str, str]]] = None,
|
|
116
|
+
) -> str:
|
|
117
|
+
"""Chat with a specific assistant.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
message: User message
|
|
121
|
+
assistant_id: ID of the assistant to chat with
|
|
122
|
+
conversation_id: Optional conversation ID
|
|
123
|
+
history: Optional chat history as list of dicts with role and message
|
|
124
|
+
"""
|
|
125
|
+
client = get_client()
|
|
126
|
+
|
|
127
|
+
# Convert history to ChatMessage objects if provided
|
|
128
|
+
chat_history = []
|
|
129
|
+
if history:
|
|
130
|
+
for msg in history:
|
|
131
|
+
chat_history.append(
|
|
132
|
+
ChatMessage(role=ChatRole(msg["role"]), message=msg["message"])
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Create chat request
|
|
136
|
+
request = AssistantChatRequest(
|
|
137
|
+
text=message,
|
|
138
|
+
conversation_id=conversation_id if conversation_id else str(uuid.uuid4()),
|
|
139
|
+
history=chat_history,
|
|
140
|
+
stream=False, # For now using non-streaming responses
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Send chat request
|
|
144
|
+
response = client.assistants.chat(assistant_id=assistant_id, request=request)
|
|
145
|
+
|
|
146
|
+
return response.generated
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
# Initialize and run the server
|
|
151
|
+
mcp.run(transport="stdio")
|