Python Library
DocuLayer ships as a first-class async Python library — use it inline in any application without running a separate MCP server.
Install
pip install doculayer
Quick Start
import asyncio
from doculayer import search, fetch
# Search live docs — returns verbatim sections with source attribution
results = asyncio.run(search("dependency injection", "fastapi"))
for r in results:
print(r.score, r.section.title)
print(r.section.source_url) # "https://fastapi.tiangolo.com/tutorial/..."
print(r.section.content) # verbatim Markdown from the real docs
print(r.section.cited_content) # content with attribution header prepended
# Fetch a specific section
content = asyncio.run(fetch("httpx", section="AsyncClient"))
print(content)
# > **Source**: https://www.python-httpx.org/...
# > **Fetched**: 2s ago
#
# ## AsyncClient
# ...verbatim text...
API Reference
search(query, source, max_results=5)
async def search(
query: str,
source: str,
max_results: int = 5,
) -> list[SearchResult]:
Searches live documentation for query within source. Returns a ranked list of SearchResult objects.
Parameters
| Name | Type | Description |
|---|---|---|
query | str | Keyword query — e.g. "field validators" |
source | str | Package or URL identifier |
max_results | int | Maximum sections to return |
Returns — list[SearchResult]
Each SearchResult has:
result.score # float — BM25 relevance score
result.section.title # str — section heading
result.section.source_url # str — canonical URL
result.section.content # str — verbatim Markdown text
result.section.cited_content # str — content with attribution prepended
result.section.trimmed(n) # str — content trimmed to n words
fetch(identifier, section=None)
async def fetch(
identifier: str,
section: str | None = None,
) -> str:
Fetches documentation for identifier. Returns verbatim text with citation header.
Parameters
| Name | Type | Description |
|---|---|---|
identifier | str | Package or URL — same formats as search |
section | str | None | Heading to extract; None returns the full page |
Returns — str — verbatim Markdown with > **Source**: … header
Async Usage in Frameworks
FastAPI / asyncio native
from doculayer import search
@app.get("/docs-search")
async def docs_search(query: str, source: str):
results = await search(query, source, max_results=3)
return [
{"title": r.section.title, "url": r.section.source_url, "score": r.score}
for r in results
]
Jupyter / IPython
import asyncio
from doculayer import fetch
# Jupyter already runs an event loop — use await directly
content = await fetch("pydantic", section="Field")
print(content)
Synchronous wrapper
import asyncio
from doculayer import search
results = asyncio.run(search("streaming", "httpx"))
Core Types
DocSection
@dataclass
class DocSection:
title: str # heading text
content: str # verbatim Markdown body
source_url: str # canonical page URL
depth: int # heading level (1 = h1, 2 = h2, …)
@property
def cited_content(self) -> str: ... # content with attribution header
def trimmed(self, max_words: int) -> str: ... # word-capped content
SearchResult
@dataclass
class SearchResult:
section: DocSection
score: float
FetchResult
@dataclass
class FetchResult:
url: str
sections: list[DocSection]
fetched_at: float # unix timestamp