Skip to main content
Glama
jcdumlao14

FastMCP Documentation & Web Scraping Server

by jcdumlao14
main.py•2.81 kB
from fastmcp import FastMCP import requests import os import zipfile from minsearch import Index mcp = FastMCP("Demo 🚀") def fetch_markdown_impl(url: str) -> str: """Fetch a web page using Jina reader and return its markdown text. The Jina reader endpoint is `https://r.jina.ai/{original_url}`. The `url` argument may be a full URL (including scheme) or a hostname/path. """ if not url.startswith("http://") and not url.startswith("https://"): url = "https://" + url target = "https://r.jina.ai/" + url resp = requests.get(target, timeout=15) resp.raise_for_status() return resp.text @mcp.tool def fetch_markdown(url: str) -> str: """Return markdown content of a web page via Jina reader.""" return fetch_markdown_impl(url) @mcp.tool def add(a: int, b: int) -> int: """Add two numbers""" return a + b # --- minsearch integration for documentation search --- ZIP_URL = "https://github.com/jlowin/fastmcp/archive/refs/heads/main.zip" ZIP_NAME = "fastmcp-main.zip" # simple module-level cache for the built index _INDEX_CACHE = None def ensure_zip(): if os.path.exists(ZIP_NAME): return resp = requests.get(ZIP_URL, stream=True, timeout=60) resp.raise_for_status() with open(ZIP_NAME, "wb") as f: for chunk in resp.iter_content(1024 * 64): if chunk: f.write(chunk) def iter_md_files_from_zip(zip_path): with zipfile.ZipFile(zip_path, "r") as z: for name in z.namelist(): lower = name.lower() if lower.endswith(".md") or lower.endswith(".mdx"): data = z.read(name) text = data.decode("utf-8", errors="replace") if "/" in name: _, rest = name.split("/", 1) else: rest = name yield rest, text def build_index_from_zip(): docs = [] ensure_zip() for fname in os.listdir('.'): if fname.lower().endswith('.zip'): for filename, text in iter_md_files_from_zip(fname): docs.append({'content': text, 'filename': filename}) idx = Index(text_fields=["content"], keyword_fields=["filename"]) idx.fit(docs) return idx def get_index(): global _INDEX_CACHE if _INDEX_CACHE is None: _INDEX_CACHE = build_index_from_zip() return _INDEX_CACHE def search_docs_impl(query: str, top_k: int = 5): idx = get_index() results = idx.search(query, num_results=top_k) return results @mcp.tool def search_docs(query: str) -> list: """Search the documentation index and return top filenames for `query`.""" results = search_docs_impl(query, top_k=5) return [r.get('filename') for r in results] if __name__ == "__main__": mcp.run()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jcdumlao14/03-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server