-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
225 lines (181 loc) · 6.89 KB
/
Copy pathmain.py
File metadata and controls
225 lines (181 loc) · 6.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
"""
MCP Server for Markdown to Postman Collection converter.
"""
import os
from typing import Any
import aiofiles
from fastmcp import FastMCP
from md_to_postman.helpers import PROMPT
from md_to_postman.markdown_parser import MarkdownParser
from md_to_postman.postman_builder import PostmanCollectionBuilder
mcp = FastMCP("M-docs")
parser = MarkdownParser()
builder = PostmanCollectionBuilder()
@mcp.resource("file:///examples/example.md", mime_type="text/markdown")
async def m_docs_markdown_example():
"""
Read M-docs example markdown file content for more
context of syntax usage while trying to generate md file via llm
"""
try:
async with aiofiles.open("examples/example.md") as f:
content = await f.read()
return content
except FileNotFoundError:
return "Example file not found."
@mcp.resource("file:///examples/syntax.md", mime_type="text/markdown")
async def m_docs_markdown_syntax_guide():
"""
Read M-docs syntax markdown file content for more
context of syntax usage while trying to generate md file via llm
"""
try:
async with aiofiles.open("examples/syntax.md") as f:
content = await f.read()
return content
except FileNotFoundError:
return "Syntax file not found."
@mcp.prompt
async def create_mardown():
"""
Returns the system prompt string used to instruct the LLM for generating
M-docs compliant Markdown files.
This prompt includes strict formatting rules and metadata requirements for
Markdown->Postman conversion.
"""
# TOBO: Improve this to be more rich and less vague (this isnt enough but
# fn cook with this :))
return PROMPT
@mcp.tool
def convert_markdown_to_postman(
markdown_content: str,
collection_name: str = "Generated Collection",
collection_description: str = "Collection generated from Markdown",
output_file: str | None = None,
) -> dict[str, Any]:
"""
Convert structured Markdown with cURL requests to Postman Collection v2.1.
Args:
markdown_content: The markdown content containing structured cURL requests
collection_name: Name for the generated collection
collection_description: Description for the generated collection
output_file: Optional file path to save the collection JSON
Returns:
Dict containing the Postman collection JSON and metadata
"""
try:
requests = parser.parse(markdown_content)
if not requests:
return {
"success": False,
"error": "No valid requests found in markdown content",
"collection": None,
}
collection = builder.build_collection(
requests, collection_name, collection_description
)
result = {
"success": True,
"collection": collection,
"requests_count": len(requests),
"folders_count": len(set(req.folder for req in requests if req.folder)),
"variables_count": len(collection.get("variable", [])),
}
if output_file:
builder.save_collection(collection, output_file)
result["output_file"] = output_file
return result
except (OSError, ValueError, KeyError, AttributeError) as e:
return {"success": False, "error": str(e), "collection": None}
@mcp.tool
def convert_markdown_file_to_postman(
file_path: str,
collection_name: str | None = None,
collection_description: str = "Collection generated from Markdown",
output_file: str | None = None,
) -> dict[str, Any]:
"""
Convert a Markdown file with cURL requests to Postman Collection v2.1.
Args:
file_path: Path to the markdown file
collection_name: Name for the generated collection (defaults to filename)
collection_description: Description for the generated collection
output_file: Optional file path to save the collection JSON
Returns:
Dict containing the Postman collection JSON and metadata
"""
try:
if not os.path.exists(file_path):
return {
"success": False,
"error": f"File not found: {file_path}",
"collection": None,
}
with open(file_path, encoding="utf-8") as file:
markdown_content = file.read()
if collection_name is None:
collection_name = os.path.splitext(os.path.basename(file_path))[0]
return convert_markdown_to_postman(
markdown_content,
collection_name,
collection_description,
output_file,
)
except (OSError, ValueError, KeyError, AttributeError) as e:
return {"success": False, "error": str(e), "collection": None}
@mcp.tool
def validate_markdown_structure(markdown_content: str) -> dict[str, Any]:
"""
Validate the structure of a markdown file for conversion.
Args:
markdown_content: The markdown content to validate
Returns:
Dict containing validation results and suggestions
"""
try:
requests = parser.parse(markdown_content)
validation_result = {
"valid": True,
"requests_found": len(requests),
"issues": [],
"suggestions": [],
"requests": [],
}
for request in requests:
request_info = {
"name": request.name,
"folder": request.folder,
"has_description": bool(request.metadata.description),
"has_curl": bool(request.curl_command),
"variables_used": [],
"issues": [],
}
if not request.curl_command:
request_info["issues"].append("No cURL command found")
validation_result["issues"].append(
f"Request '{request.name}': No cURL command found"
)
if not request.metadata.description:
request_info["issues"].append("No description provided")
validation_result["suggestions"].append(
f"Request '{request.name}': Consider adding a description"
)
if request.curl_command:
variables = builder.extract_postman_variables(request.curl_command)
request_info["variables_used"] = variables
validation_result["requests"].append(request_info)
if not requests:
validation_result["valid"] = False
validation_result["issues"].append("No valid requests found in markdown")
return validation_result
except (OSError, ValueError, KeyError, AttributeError) as e:
return {
"valid": False,
"error": str(e),
"requests_found": 0,
"issues": [f"Parse error: {str(e)}"],
"suggestions": [],
"requests": [],
}
if __name__ == "__main__":
mcp.run()