Launcher API¶
Package¶
doc_processing_std_tools
¶
doc-processing-std-tools — Standard MCP tool servers for doc-processing-toolkit agents.
Each server is a FastMCP instance that can be passed directly to
Agent(tools=[...]) in doc-processing-toolkit.
Example::
from doc_processing_std_tools import file_system_server, memory_server
from doc_processing_toolkit import Agent
agent = Agent(
model="claude-sonnet-5",
tools=[file_system_server, memory_server],
)
For consumers that want all 8 servers exposed through a single MCP endpoint,
run python -m doc_processing_std_tools (see __main__.py).
Server attributes are imported lazily (PEP 562 __getattr__): importing
this package, or one server, never force-imports the others. So a minimal
install (e.g. only the docs extra) can from doc_processing_std_tools
import document_processing_server without the absence of an unrelated
server's optional dependency breaking the import.
__getattr__(name)
¶
Import the owning module on first access (PEP 562).
Composed Launcher¶
doc_processing_std_tools.__main__
¶
Multi-server launcher for doc-processing-std-tools.
Running python -m doc_processing_std_tools composes all 8 sub-servers
into a single FastMCP service and runs it over stdio (default) or HTTP.
The browser server is added only when DPTTOOLS_ENABLE_BROWSER=true
and the computer (desktop) server only when DPTTOOLS_ENABLE_COMPUTER=true:
a server that drives a browser or a desktop should not appear just because
the package is installed.
Composition model¶
The bundled mcp SDK does not expose a high-level composition API
(no import_server / mount / compose on FastMCP). We
therefore compose by manually re-registering each sub-server's tools
on a single parent FastMCP instance via parent.add_tool().
Each tool's underlying function, name, description, annotations, icons
and metadata are copied over verbatim — there are no behavioural
differences between calling a tool through the composed parent and
calling it through its original sub-server.
Tool-name namespacing (no prefix)¶
We do not prefix tool names. The 8 sub-servers ship with 56
globally-unique names today (verified at composition time). If a
future addition introduces a collision, this module raises
RuntimeError at startup with the colliding tool name and the two
owning sub-servers — fail fast rather than silently shadow.
If you ever need to add prefixing (e.g. because two sub-servers
genuinely need to expose tools with the same short name), add a
prefix parameter to compose_servers() and apply it inside the
add_tool loop. Keep the no-prefix default for backward compatibility
with consumers that import the individual sub-servers.
Configuration¶
All DPTTOOLS_* environment variables are honoured exactly as when
running individual sub-servers. Each is read through _config the first
time it is needed and cached for the life of the process, and main()
validates them at start-up so a bad value stops the launcher at once.
Optional servers¶
enabled_sub_servers() returns the always-on eight plus the browser
server when DPTTOOLS_ENABLE_BROWSER is true and the computer server
when DPTTOOLS_ENABLE_COMPUTER is true. Their settings
(DPTTOOLS_BROWSER_*, DPTTOOLS_COMPUTER_*) are validated at start-up
only in that case, so a bad setting for an optional server cannot stop the
others.
Blocking tools run on worker threads¶
FastMCP calls a synchronous tool function directly on its event loop, so
one slow call (an OCR job, a LibreOffice conversion, a long command)
would freeze every other request and the transport itself. The parent
therefore registers each synchronous tool as an async wrapper that
runs it on a worker thread (anyio.to_thread.run_sync). The wrapper
uses functools.wraps, so the tool's name, description and JSON schema
are unchanged. Tools that are already async are registered as-is.
Individual sub-servers and in-process use are not affected.
CLI¶
::
python -m doc_processing_std_tools # stdio (default)
python -m doc_processing_std_tools --transport http --port 8000
HTTP transport security¶
The HTTP transport binds to 127.0.0.1 by default (loopback only). The
composed server performs no authentication of its own, so do not bind it
to a public interface (--host 0.0.0.0) unless it sits behind an
authenticating reverse proxy / network policy. This is a network posture
note (separate from the filesystem container model).
compose_servers(sub_servers=None, name=PARENT_SERVER_NAME)
¶
Compose the given sub-servers into a single parent FastMCP server.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sub_servers
|
list[tuple[str, FastMCP]] | None
|
Optional list of |
None
|
name
|
str
|
Parent server name. |
PARENT_SERVER_NAME
|
Returns:
| Type | Description |
|---|---|
FastMCP
|
A new |
FastMCP
|
on it. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If two sub-servers register a tool with the same name — fail fast rather than silently shadow. |
enabled_sub_servers()
¶
The always-on sub-servers plus any optional server switched on by env.
Raises:
| Type | Description |
|---|---|
ConfigError
|
|