research-mcp exposes muckwire over the Model Context Protocol using stdio.
It is built on mcp.server.lowlevel.Server so lifecycle tools and connector
tools share one dynamic tool list.
pip install -e .
research-mcpThe server writes telemetry to data/mcp_events/<pid>.jsonl. Each line names
the tool, process id, success flag, error text when present, timestamp, and
schema version.
start_research_job- wrapsresearch_agent.start_job; acceptsgoal, optionalbudget_usd,time_cap,local, andfresh_reset; returnsjob_idanddaemon_pid.get_job_status- wrapsget_job_status; returns status, spend, elapsed time, current iteration, and latest event summary.list_jobs- wrapslist_jobs; returnsjobs.stop_job- wrapsstop_job; returnsstopped.resume_job- wrapsresume_job; returnsresumedanddaemon_pid.get_report- wrapsget_report; returnsreport_mdandsources.get_findings- wrapsget_findings; returnsfindings.search_findings- wrapssearch_findings; returnsresults.export_job- wrapsexport_job; returns outputpathand byte count.
Lifecycle calls use the same programmatic API as the CLI. A
start_research_job request respects the job's budget_usd; once the daemon
is running, normal LLM calls continue through that job's BudgetTracker.
{
"mcpServers": {
"muckwire": {
"command": "research-mcp",
"args": []
}
}
}{
"mcp_servers": {
"muckwire": {
"type": "stdio",
"command": "research-mcp",
"args": []
}
}
}{
"servers": {
"muckwire": {
"transport": "stdio",
"command": "research-mcp"
}
}
}The tool-level connector surface is registered from
research_agent.tools._registry.iter_kinds(). Adding a connector kind to the
registry exposes a matching MCP tool without editing mcp/server.py.
Tool-level calls are one-shot connector lookups and do not have an active job
context, so they do not use BudgetTracker and do not enforce a per-job
budget. Cost-bearing connector tools refuse to dispatch unless their required
credential is configured; the MCP consumer is responsible for any additional
budget gate at the agent layer.
Connector tool output is structured as an MCP object with a results field;
results is serialized as list[SearchResult] from research_agent.tools.models.
The object wrapper is intentional because the Python MCP SDK only validates
object-valued structuredContent.