mseep-dify-mcp-server 0.1.3__py3-none-any.whl → 0.1.4__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.
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.4
2
+ Name: mseep-dify-mcp-server
3
+ Version: 0.1.4
4
+ Summary: Add your description here
5
+ Home-page:
6
+ Author: mseep
7
+ Author-email: support@skydeck.ai
8
+ Maintainer: mseep
9
+ Maintainer-email: support@skydeck.ai
10
+ Keywords: mseep
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.6
15
+ Description-Content-Type: text/plain
16
+ Requires-Dist: httpx>=0.28.1
17
+ Requires-Dist: mcp>=1.1.2
18
+ Requires-Dist: omegaconf>=2.3.0
19
+ Requires-Dist: pip>=24.3.1
20
+ Requires-Dist: python-dotenv>=1.0.1
21
+ Requires-Dist: requests
22
+ Dynamic: author
23
+ Dynamic: author-email
24
+ Dynamic: classifier
25
+ Dynamic: description
26
+ Dynamic: description-content-type
27
+ Dynamic: keywords
28
+ Dynamic: maintainer
29
+ Dynamic: maintainer-email
30
+ Dynamic: requires-dist
31
+ Dynamic: requires-python
32
+ Dynamic: summary
33
+
34
+ Package managed by MseeP.ai
@@ -0,0 +1,4 @@
1
+ mseep_dify_mcp_server-0.1.4.dist-info/METADATA,sha256=DVsH-aOy8AuLNuYWu7RXeGyrPWxqKR5HkwlQvtedPAU,881
2
+ mseep_dify_mcp_server-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
3
+ mseep_dify_mcp_server-0.1.4.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
4
+ mseep_dify_mcp_server-0.1.4.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -1,9 +0,0 @@
1
- from . import server
2
- import asyncio
3
-
4
- def main():
5
- """Main entry point for the package."""
6
- asyncio.run(server.main())
7
-
8
- # Optionally expose other important items at package level
9
- __all__ = ['main', 'server']
dify_mcp_server/server.py DELETED
@@ -1,281 +0,0 @@
1
- import asyncio
2
- import json
3
- import os
4
- from abc import ABC
5
-
6
- import mcp.server.stdio
7
- import mcp.types as types
8
- import requests
9
- from mcp.server import NotificationOptions, Server
10
- from mcp.server.models import InitializationOptions
11
- from omegaconf import OmegaConf
12
-
13
-
14
- def get_app_info():
15
- config_path = os.getenv("CONFIG_PATH")
16
- base_url = os.getenv("DIFY_BASE_URL")
17
- dify_app_sks = os.getenv("DIFY_APP_SKS")
18
- if config_path is not None:
19
- print(f"Loading config from {config_path}")
20
- config = OmegaConf.load(config_path)
21
- dify_base_url = config.get('dify_base_url', "https://api.dify.ai/v1")
22
- dify_app_sks = config.get('dify_app_sks', [])
23
- return dify_base_url, dify_app_sks
24
- elif base_url is not None and dify_app_sks is not None:
25
- print(f"Loading config from env variables")
26
- dify_base_url = base_url
27
- dify_app_sks = dify_app_sks.split(",")
28
- return dify_base_url, dify_app_sks
29
-
30
- class DifyAPI(ABC):
31
- def __init__(self,
32
- base_url: str,
33
- dify_app_sks: list,
34
- user="default_user"):
35
- # dify configs
36
- self.dify_base_url = base_url
37
- self.dify_app_sks = dify_app_sks
38
- self.user = user
39
-
40
- # dify app infos
41
- dify_app_infos = []
42
- dify_app_params = []
43
- dify_app_metas = []
44
- for key in self.dify_app_sks:
45
- dify_app_infos.append(self.get_app_info(key))
46
- dify_app_params.append(self.get_app_parameters(key))
47
- dify_app_metas.append(self.get_app_meta(key))
48
- self.dify_app_infos = dify_app_infos
49
- self.dify_app_params = dify_app_params
50
- self.dify_app_metas = dify_app_metas
51
- self.dify_app_names = [x['name'] for x in dify_app_infos]
52
-
53
- def chat_message(
54
- self,
55
- api_key,
56
- inputs={},
57
- response_mode="streaming",
58
- conversation_id=None,
59
- user="default_user",
60
- files=None,):
61
- url = f"{self.dify_base_url}/workflows/run"
62
- headers = {
63
- "Authorization": f"Bearer {api_key}",
64
- "Content-Type": "application/json"
65
- }
66
- data = {
67
- "inputs": inputs,
68
- "response_mode": response_mode,
69
- "user": user,
70
- }
71
- if conversation_id:
72
- data["conversation_id"] = conversation_id
73
- if files:
74
- files_data = []
75
- for file_info in files:
76
- file_path = file_info.get('path')
77
- transfer_method = file_info.get('transfer_method')
78
- if transfer_method == 'local_file':
79
- files_data.append(('file', open(file_path, 'rb')))
80
- elif transfer_method == 'remote_url':
81
- pass
82
- response = requests.post(
83
- url, headers=headers, data=data, files=files_data, stream=response_mode == "streaming")
84
- else:
85
- response = requests.post(
86
- url, headers=headers, json=data, stream=response_mode == "streaming")
87
- response.raise_for_status()
88
- if response_mode == "streaming":
89
- for line in response.iter_lines():
90
- if line:
91
- if line.startswith(b'data:'):
92
- try:
93
- json_data = json.loads(line[5:].decode('utf-8'))
94
- yield json_data
95
- except json.JSONDecodeError:
96
- print(f"Error decoding JSON: {line}")
97
- else:
98
- return response.json()
99
-
100
- def upload_file(
101
- self,
102
- api_key,
103
- file_path,
104
- user="default_user"):
105
-
106
- url = f"{self.dify_base_url}/files/upload"
107
- headers = {
108
- "Authorization": f"Bearer {api_key}"
109
- }
110
- files = {
111
- "file": open(file_path, "rb")
112
- }
113
- data = {
114
- "user": user
115
- }
116
- response = requests.post(url, headers=headers, files=files, data=data)
117
- response.raise_for_status()
118
- return response.json()
119
-
120
- def stop_response(
121
- self,
122
- api_key,
123
- task_id,
124
- user="default_user"):
125
-
126
- url = f"{self.dify_base_url}/chat-messages/{task_id}/stop"
127
- headers = {
128
- "Authorization": f"Bearer {api_key}",
129
- "Content-Type": "application/json"
130
- }
131
- data = {
132
- "user": user
133
- }
134
- response = requests.post(url, headers=headers, json=data)
135
- response.raise_for_status()
136
- return response.json()
137
-
138
- def get_app_info(
139
- self,
140
- api_key,
141
- user="default_user"):
142
-
143
- url = f"{self.dify_base_url}/info"
144
- headers = {
145
- "Authorization": f"Bearer {api_key}"
146
- }
147
- params = {
148
- "user": user
149
- }
150
- response = requests.get(url, headers=headers, params=params)
151
- response.raise_for_status()
152
- return response.json()
153
-
154
- def get_app_parameters(
155
- self,
156
- api_key,
157
- user="default_user"):
158
- url = f"{self.dify_base_url}/parameters"
159
- headers = {
160
- "Authorization": f"Bearer {api_key}"
161
- }
162
- params = {
163
- "user": user
164
- }
165
- response = requests.get(url, headers=headers, params=params)
166
- response.raise_for_status()
167
- return response.json()
168
-
169
- def get_app_meta(
170
- self,
171
- api_key,
172
- user="default_user"):
173
- url = f"{self.dify_base_url}/meta"
174
- headers = {
175
- "Authorization": f"Bearer {api_key}"
176
- }
177
- params = {
178
- "user": user
179
- }
180
- response = requests.get(url, headers=headers, params=params)
181
- response.raise_for_status()
182
- return response.json()
183
-
184
-
185
- base_url, dify_app_sks = get_app_info()
186
- server = Server("dify_mcp_server")
187
- dify_api = DifyAPI(base_url, dify_app_sks)
188
-
189
-
190
- @server.list_tools()
191
- async def handle_list_tools() -> list[types.Tool]:
192
- """
193
- List available tools.
194
- Each tool specifies its arguments using JSON Schema validation.
195
- """
196
- tools = []
197
- tool_names = dify_api.dify_app_names
198
- tool_infos = dify_api.dify_app_infos
199
- tool_params = dify_api.dify_app_params
200
- tool_num = len(tool_names)
201
- for i in range(tool_num):
202
- # 0. load app info for each tool
203
- app_info = tool_infos[i]
204
- # 1. load app param for each tool
205
- inputSchema = dict(
206
- type="object",
207
- properties={},
208
- required=[],
209
- )
210
- app_param = tool_params[i]
211
- property_num = len(app_param['user_input_form'])
212
- if property_num > 0:
213
- for j in range(property_num):
214
- param = app_param['user_input_form'][j]
215
- # TODO: Add readme about strange dify user input param format
216
- param_type = list(param.keys())[0]
217
- param_info = param[param_type]
218
- property_name = param_info['variable']
219
- inputSchema["properties"][property_name] = dict(
220
- type=param_type,
221
- description=param_info['label'],
222
- )
223
- if param_info['required']:
224
- inputSchema['required'].append(property_name)
225
-
226
- tools.append(
227
- types.Tool(
228
- name=app_info['name'],
229
- description=app_info['description'],
230
- inputSchema=inputSchema,
231
- )
232
- )
233
- return tools
234
-
235
-
236
- @server.call_tool()
237
- async def handle_call_tool(
238
- name: str, arguments: dict | None
239
- ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
240
- tool_names = dify_api.dify_app_names
241
- if name in tool_names:
242
- tool_idx = tool_names.index(name)
243
- tool_sk = dify_api.dify_app_sks[tool_idx]
244
- responses = dify_api.chat_message(
245
- tool_sk,
246
- arguments,
247
- )
248
- for res in responses:
249
- if res['event'] == 'workflow_finished':
250
- outputs = res['data']['outputs']
251
- mcp_out = []
252
- for _, v in outputs.items():
253
- mcp_out.append(
254
- types.TextContent(
255
- type='text',
256
- text=v
257
- )
258
- )
259
- return mcp_out
260
- else:
261
- raise ValueError(f"Unknown tool: {name}")
262
-
263
-
264
- async def main():
265
- # Run the server using stdin/stdout streams
266
- async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
267
- await server.run(
268
- read_stream,
269
- write_stream,
270
- InitializationOptions(
271
- server_name="dify_mcp_server",
272
- server_version="0.1.0",
273
- capabilities=server.get_capabilities(
274
- notification_options=NotificationOptions(),
275
- experimental_capabilities={},
276
- ),
277
- ),
278
- )
279
-
280
- if __name__ == "__main__":
281
- asyncio.run(main())
@@ -1,16 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: mseep-dify-mcp-server
3
- Version: 0.1.3
4
- Summary: Add your description here
5
- Author-email: mseep <support@skydeck.ai>
6
- Maintainer-email: mseep <support@skydeck.ai>
7
- Requires-Python: >=3.10
8
- Requires-Dist: httpx>=0.28.1
9
- Requires-Dist: mcp>=1.1.2
10
- Requires-Dist: omegaconf>=2.3.0
11
- Requires-Dist: pip>=24.3.1
12
- Requires-Dist: python-dotenv>=1.0.1
13
- Requires-Dist: requests
14
- Description-Content-Type: text/markdown
15
-
16
- # Package managed by MseeP.ai
@@ -1,6 +0,0 @@
1
- dify_mcp_server/__init__.py,sha256=kTuRDcmoAa4al59WMbwXx_TjJhMqmpzCMFCZ981BL1M,213
2
- dify_mcp_server/server.py,sha256=pTdMPTmvK1uO6Ki062bVSp-VQ9cBbFO2WtMSfowGgzU,8966
3
- mseep_dify_mcp_server-0.1.3.dist-info/METADATA,sha256=mGZ2wE7Neze3UthGzTUs_ffYJ4we4NzUPhGD1ntBHBY,455
4
- mseep_dify_mcp_server-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
- mseep_dify_mcp_server-0.1.3.dist-info/entry_points.txt,sha256=YughlZESvmM9v4WMtY4GAUzFWY-udx_CBKQUa3WXxeU,57
6
- mseep_dify_mcp_server-0.1.3.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- dify_mcp_server = dify_mcp_server:main