Skip to content

Commit a9e1b14

Browse files
authored
add allowed domains cli option (#11)
1 parent 71ddda1 commit a9e1b14

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

mcpdoc/cli.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class CustomFormatter(
4242
4343
# Using SSE transport with additional HTTP options
4444
mcpdoc --yaml sample_config.yaml --follow-redirects --timeout 15 --transport sse --host localhost --port 8080
45+
46+
# Allow fetching from additional domains. The domains hosting the llms.txt files are always allowed.
47+
mcpdoc --yaml sample_config.yaml --allowed-domains https://example.com/ https://another-example.com/
48+
49+
# Allow fetching from any domain
50+
mcpdoc --yaml sample_config.yaml --allowed-domains '*'
4551
"""
4652

4753

@@ -74,6 +80,12 @@ def parse_args() -> argparse.Namespace:
7480
action="store_true",
7581
help="Whether to follow HTTP redirects",
7682
)
83+
parser.add_argument(
84+
"--allowed-domains",
85+
type=str,
86+
nargs="*",
87+
help="Additional allowed domains to fetch documentation from. Use '*' to allow all domains",
88+
)
7789
parser.add_argument(
7890
"--timeout", type=float, default=10.0, help="HTTP request timeout in seconds"
7991
)
@@ -229,6 +241,7 @@ def main() -> None:
229241
follow_redirects=args.follow_redirects,
230242
timeout=args.timeout,
231243
settings=settings,
244+
allowed_domains=args.allowed_domains,
232245
)
233246

234247
if args.transport == "sse":

mcpdoc/main.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def create_server(
4040
follow_redirects: bool = False,
4141
timeout: float = 10,
4242
settings: dict | None = None,
43+
allowed_domains: list[str] | None = None,
4344
) -> FastMCP:
4445
"""Create the server and generate documentation retrieval tools.
4546
@@ -48,6 +49,10 @@ def create_server(
4849
follow_redirects: Whether to follow HTTP redirects when fetching docs
4950
timeout: HTTP request timeout in seconds
5051
settings: Additional settings to pass to FastMCP
52+
allowed_domains: Additional domains to allow fetching from.
53+
Use ['*'] to allow all domains
54+
The domain hosting the llms.txt file is always appended to the list
55+
of allowed domains.
5156
5257
Returns:
5358
A FastMCP server instance configured with documentation tools
@@ -81,7 +86,14 @@ def list_doc_sources() -> str:
8186
return content
8287

8388
# Parse the domain names in the llms.txt URLs
84-
allowed_domains = set(extract_domain(entry["llms_txt"]) for entry in doc_source)
89+
domains = set(extract_domain(entry["llms_txt"]) for entry in doc_source)
90+
91+
# Add additional allowed domains if specified
92+
if allowed_domains:
93+
if "*" in allowed_domains:
94+
domains = {"*"} # Special marker for allowing all domains
95+
else:
96+
domains.update(allowed_domains)
8597

8698
@server.tool()
8799
async def fetch_docs(url: str) -> str:
@@ -99,11 +111,11 @@ async def fetch_docs(url: str) -> str:
99111
The fetched documentation content converted to markdown, or an error message
100112
if the request fails or the URL is not from an allowed domain.
101113
"""
102-
nonlocal allowed_domains
103-
if not any(url.startswith(domain) for domain in allowed_domains):
114+
nonlocal domains
115+
if "*" not in domains and not any(url.startswith(domain) for domain in domains):
104116
return (
105117
"Error: URL not allowed. Must start with one of the following domains: "
106-
+ ", ".join(allowed_domains)
118+
+ ", ".join(domains)
107119
)
108120

109121
try:

0 commit comments

Comments
 (0)