agentstatus-mcpjobgraph
Stop paying for out-of-order MCP tool calls.
Agents ignore "call X first" in your tool descriptions. They still hit get_package / fetch / get_deal with garbage IDs. You still eat the traffic, the error noise, and the bad demos.
agentstatus-mcpjobgraph is a thin author-side gate: illegal order never reaches your tools. Legal order still runs, and binds can fill downstream args from earlier steps.
Measured on public MCPs (2026-09-01): 7/7 eligible servers — bare MCP got the illegal call; middleware blocked it with upstream never hit. See results/friction_top9_2026-09-01.md.
Install
pip install agentstatus-mcpjobgraph
# optional adapters
pip install "agentstatus-mcpjobgraph[fastmcp]"
pip install "agentstatus-mcpjobgraph[mcp]"
Python 3.10+. Core has zero required dependencies.
From AgentStatus / Carmel Labs (agentstatus.dev).
60-second FastMCP drop-in
Hand-author the job. Do not ship inferred graphs without reading them.
from fastmcp import FastMCP
from agentstatus_mcpjobgraph import Workflow, install
mcp = FastMCP("packages")
@mcp.tool
def search_packages(query: str) -> dict:
return {"package_id": "abc123", "name": query}
@mcp.tool
def get_package(package_id: str) -> dict:
return {"package_id": package_id, "ok": True}
install(
mcp,
[
Workflow(
id="search_then_get",
steps=["search_packages", "get_package"],
binds={"package_id": "search_packages.package_id"},
)
],
)
if __name__ == "__main__":
mcp.run()
Calling get_package first → blocked with a repair hint. Never hits your function.
Official MCP Python SDK
from mcp.server import Server
from agentstatus_mcpjobgraph import Workflow, make_enforcer, jobgraph_middleware
server = Server("packages")
enforcer = make_enforcer([
Workflow(id="search_then_get", steps=["search_packages", "get_package"],
binds={"package_id": "search_packages.package_id"}),
])
server.middleware.append(jobgraph_middleware(enforcer))
Or wrap a classic handler:
from agentstatus_mcpjobgraph import make_enforcer, Workflow, wrap_call_tool
enforcer = make_enforcer([Workflow(id="x", steps=["a", "b"])])
async def handle(name: str, arguments: dict):
...
handle = wrap_call_tool(enforcer, handle)
In-process decorator (@with_jobs)
from agentstatus_mcpjobgraph import Workflow, make_enforcer, with_jobs
enforcer = make_enforcer([Workflow(id="x", steps=["a", "b"])])
@with_jobs(enforcer, session_id="default")
def call_tool(name: str, arguments: dict):
return dispatch(name, arguments)
Hand-authored workflows (preferred)
from agentstatus_mcpjobgraph import Workflow, load_workflows
workflows = [
Workflow(
id="search_then_get",
steps=["search_packages", "get_package"],
binds={"package_id": "search_packages.package_id"},
)
]
# or
workflows = load_workflows("workflows.json")
workflows.json:
{
"workflows": [
{
"id": "search_then_get",
"steps": ["search_packages", "get_package"],
"binds": {"package_id": "search_packages.package_id"}
}
]
}
Bootstrap only (then edit)
Infer candidates from a live catalog, then rewrite by hand:
from agentstatus_mcpjobgraph import bootstrap_workflows_from_tools
sketches = bootstrap_workflows_from_tools(tools, instructions)
# review / edit sketches → ship as Workflow(...)
Inference is a sketch. Enforcement should run on jobs you own.
HTTP proxy (no code change on the origin)
python -m agentstatus_mcpjobgraph proxy --url https://your-mcp.example/mcp --port 8765
Point clients at http://127.0.0.1:8765/mcp.
Prove friction removal
python -m agentstatus_mcpjobgraph friction --url https://chat.gitsim.com/api/mcp
Expect friction_removed=True: illegal order hits upstream without the gate; blocked with upstream_hit=false with the gate.
What this is / is not
| Is | Is not |
|---|---|
| Author-side enforcement | A Cursor/Claude host patch |
| Order + bind gate | Auth, rate limits, or billing |
| Pip-installable OSS sketch → product | A hosted Carmel service |
Emit-only _meta.workflows without a gate does not remove friction. Hosts ignore it. This package is the gate.
Package layout
agentstatus_mcpjobgraph/
workflow.py # hand-authored Workflow (preferred)
middleware.py # JobEnforcer core
with_jobs.py # @with_jobs + install()
fastmcp_ext.py # FastMCP middleware
mcp_sdk.py # official MCP Python SDK middleware
bootstrap.py # infer once, then edit (not the default)
License
MIT
Metadata
Release files for agentstatus-mcpjobgraph 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| agentstatus_mcpjobgraph-0.2.0.tar.gz | 25.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agentstatus_mcpjobgraph-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 56.5 kB
Release files / agentstatus_mcpjobgraph-0.2.0.tar.gz
| Download URL | agentstatus_mcpjobgraph-0.2.0.tar.gz |
|---|---|
| Size | 25.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
21b511403f5d1166e892fd8d1a7e238b5c25d9e20400477f5cae9b5113b8a9d0
|
|
BLAKE2b-256 checksum How to use checksums |
f8d0da8fd10d3b60399bae0d22f291ca70d5fe7b1d1c4eb8e686761232f2f5b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / agentstatus_mcpjobgraph-0.2.0-py3-none-any.whl
| Download URL | agentstatus_mcpjobgraph-0.2.0-py3-none-any.whl |
|---|---|
| Size | 30.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7c128cf1859365c2805251ee5cdcf75549eca59523978106b0756837a457cc45
|
|
BLAKE2b-256 checksum How to use checksums |
421be799c10c90a8ccd6fbacdad5140a8cf72413cb7c68f353fbe77ffffe161a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Security for agentstatus-mcpjobgraph 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.