Skip to main content
Glama
tatsuro-sys

outcome-router

by tatsuro-sys

Outcome Router

Article extraction fallback for agents. MCP · HTTP API · CLI.

Give your agent a public URL or HTML and an acceptance contract. Outcome Router tries eligible extractors, checks the result, falls back when necessary, and uses independent local observations to rank future requests.

Public developer beta · free · runs on your machine. This release supports static article HTML using three real open-source extractors. It does not render JavaScript, bypass access controls, invoke arbitrary MCP servers, or offer a hosted endpoint. Quality checks are explicit heuristics, not a guarantee of semantic completeness.

Try it

Install uv first. No API key is needed for the demo or local extractors.

uvx --from git+https://github.com/tatsuro-sys/outcome-router@v0.1.0b1 outcome demo

The demo uses a synthetic article and a temporary database. It does not contact the network after installation or train your real routing history.

For repeated use, install the release:

uv tool install git+https://github.com/tatsuro-sys/outcome-router@v0.1.0b1
outcome extract https://example.com --min-chars 30 --require "Example Domain"

The extract command explicitly requests a public URL fetch. JSON API/MCP calls require allow_network: true. Extracted page text is untrusted data; agents must not execute instructions embedded in it.

Related MCP server: foundrynet-scrape

Connect your agent with MCP

Add this server configuration to a host that supports MCP stdio:

{
  "mcpServers": {
    "outcome-router": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/tatsuro-sys/outcome-router@v0.1.0b1", "outcome", "mcp"]
    }
  }
}

If the host cannot find uvx, use its absolute executable path. The first launch needs network access to install the package and dependencies. Runtime URL fetching is a separate, explicit permission.

Tools:

  • search_capability(request) — inspect eligible providers and ranking; does not fetch or execute.

  • run_capability(request) — extract, check, fall back, and save the outcome locally.

  • get_outcome(run_id) — retrieve a local run.

  • report_outcome(run_id, report) — record consumer feedback separately from trusted routing evidence.

Example run_capability arguments:

{
  "request": {
    "need": {"capability": "web.article_text"},
    "source": {"url": "https://example.com"},
    "contract": {"min_chars": 30, "required_terms": ["Example Domain"]},
    "constraints": {"allow_network": true, "max_provider_cost_usd": 0, "deadline_ms": 10000}
  }
}

The parent agent maps the user's request to web.article_text. The router does not pretend to understand arbitrary tasks. Unsupported capabilities and unknown constraints are rejected.

Use the local HTTP API

export OUTCOME_API_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
outcome serve --port 8787

In a second terminal, set the same token, then:

curl http://127.0.0.1:8787/v1/runs \
  -H "Authorization: Bearer $OUTCOME_API_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"need":{"capability":"web.article_text"},"source":{"url":"https://example.com"},"contract":{"min_chars":30},"constraints":{"allow_network":true}}'

Open http://127.0.0.1:8787/docs for interactive API documentation. serve binds to localhost and requires a token of at least 24 characters. This is a single-owner service; do not expose it directly to the public internet.

Endpoint

Purpose

POST /v1/resolve

Rank eligible extractors

POST /v1/runs

Execute with checks and fallback

GET /v1/runs/{run_id}

Retrieve a saved result

POST /v1/runs/{run_id}/outcome

Save first consumer report for a run

GET /v1/providers

Inspect installed provider manifests

Completed executions return HTTP 200 with status: succeeded or status: failed. A failed result may include partial text: always check status. CLI executions return exit code 2 on contract failure. Invalid inputs return 422 in HTTP; auth errors 401, unknown runs 404, idempotency conflicts 409, oversized bodies 413.

What is measured

The engine checks minimum length, required/forbidden phrases, grounding in the original visible source, and navigation/footer contamination. Each attempt records provider version, outcome, checks, elapsed time and allocated time. It stops work at the deadline using killable extractor and evaluator processes.

Three curated providers: Trafilatura fast/no-fallback, readability-lxml, and BeautifulSoup article/main extraction. Independent observations update a versioned, time-decayed posterior. Repeated identical inputs cannot inflate observation counts. Timeout attempts starved by an earlier stage do not penalize a provider's learned ranking. Consumer reports do not directly train the router.

Do not assume this beats a single extractor. The included synthetic benchmark also has single-provider baselines with the same evaluator. Some baselines match the router. Real workload advantage remains to be demonstrated. See benchmark notes.

Data and cost

  • Runtime history stays in a local SQLite database. No analytics are sent to us.

  • Raw HTML, URL and free-form need descriptions are not stored in that database. Extracted output is stored for retrieval and idempotent replay.

  • Default storage uses your OS's application-data directory. Set OUTCOME_DB or --db PATH to choose another location. API and MCP use the same default.

  • outcome purge --days 7 deletes old runs, outputs and observations when invoked. No background scheduler is installed. Backup copies are outside its scope.

  • Provider charges are zero for the included local software. Infrastructure cost is reported as unknown, not free. No billing, paid provider calls or subscription is enabled.

  • Public URLs are fetched directly with public-IP validation, redirect checks, no ambient proxy/cookies and a 1 MB HTML limit.

Develop and reproduce

git clone https://github.com/tatsuro-sys/outcome-router.git
cd outcome-router
uv sync --frozen
uv run pytest -q
uv run ruff check src tests examples benchmarks
uv run python benchmarks/run.py
uv build

Python 3.11+. See the CI workflow for the tested OS/Python matrix. Examples: JSON, Python, MCP client. Interfaces: OpenAPI, request, result, MCP tools, manifests.

Help shape the next release

Have a public page your existing extractor gets wrong? Submit an extraction failure, including the expected result and your current baseline. Only submit pages and content you have permission to share publicly. Do not post tokens, personal data or private pages.

The next capability should follow real failures: rendering, a paid BYOK provider, or stronger evaluation. This beta makes no promise of a general software marketplace or automatic improvement on every workload.

Architecture · Security · Privacy · Changelog · Contributing

MIT licensed. Third-party components retain their own licenses; see THIRD_PARTY.md.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables AI agents to read web pages reliably, returning clean markdown content, hyperlinks, and metadata without navigation or ad noise.
    3
    6 npm
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to perform web searches, extract webpage content, and conduct end-to-end search-and-extract operations using multiple search providers and content extraction methods.
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI agents to extract clean, structured web content (articles, tables, links, visual layouts) optimized for LLM token efficiency, with fast response times and optional JavaScript support.
    5
    29 npm
    MIT