lap - measure & improve the token-efficiency of agent-facing APIs (OpenAPI & MCP): scorer, linter, the LAP profile, and a token benchmark
Project description
lap — token-efficiency scorer for agent-facing APIs
lap is the open, neutral, standalone toolkit (no pet-zoo dependency) that measures
how many tokens an API's definitions cost an LLM. It answers: is my agent-API
menu efficient, and by how much could it shrink? — an open, reproducible number to set
beside the fast-growing MCP/OpenAPI tooling (see ../docs/LANDSCAPE.md
for the neighbors LAP builds on and credits).
Install
pip install -e . # from the repo root (or: pip install lap-score once published)
pip install -e ".[mcp]" # + real-MCP baseline (fastmcp)
pip install -e ".[faithful]" # + faithful Anthropic count_tokens
Core deps are just httpx + tiktoken + pyyaml; fastmcp and anthropic are optional extras.
Robust to real specs: allOf/oneOf/anyOf, $ref in params/requestBodies/responses,
path-item-level parameters, OpenAPI 3.1 type lists, external $refs (left intact), YAML input,
Swagger/OpenAPI 2.0 (response schema, in: body params, type-on-parameter, #/definitions),
and non-JSON media types (*+json, form, XML). Verified crash-free + non-degenerate across 175+
real APIs.guru specs — re-run with ../experiments/fuzz_corpus.py.
Quickstart
lap score https://petstore3.swagger.io/api/v3/openapi.json # menu (bucket A) token cost
lap lint https://petstore3.swagger.io/api/v3/openapi.json # flag LAP rule violations
lap score --mcp-url http://localhost:8080/mcp # score a live MCP server's tools
lap score lap/examples/bookstore.openapi.json
# no install needed, from the repo root:
python -m lap.score lap/examples/bookstore.openapi.json
Example output:
LAP menu score - Bookstore API
operations: 6 referenced component schemas: 2
variant A tokens saved vs full form
openapi_full 418 +0% 6 tool(s)
compact_sig 205 +51% manifest text
numbered 168 +60% manifest text
Menu efficiency: compact signatures are +51% vs naive OpenAPI->tools (418 -> 205 tokens).
When fastmcp is installed, the score also includes a real-MCP baseline
(FastMCP.from_openapi) — what an actual MCP generator emits — plus its
output-schema-inclusive figure (--no-mcp to skip). On a real public API
(Swagger Petstore, 19 ops) the real MCP server costs 2226 menu tokens
(3844 with output schemas) vs 415 for compact signatures — an ~81%
reduction. The toy finding holds in the wild: a real MCP generator is heavier
than the naive baseline.
The score also includes a lazy tool_search form (the Anthropic Tool Search /
Cloudflare Code Mode pattern: a fixed 2-tool menu + a name index, schemas loaded on
demand). Because it doesn't preload schemas, its bucket A is ~flat in the number of
operations — on a 120-operation API it collapses the menu ~83% vs full schemas,
beating even compact signatures at scale (Petstore: 1740 → 207, −88%).
- Faithful counts: set
ANTHROPIC_API_KEY(uses the free Anthropiccount_tokensendpoint; tool defs counted via the realtools=parameter). Without it, a GPT-styletiktokenapproximation — absolute numbers approximate, relative ordering robust.
CI gate
--json makes both commands machine-readable; thresholds set the exit code so LAP can fail a build:
lap score openapi.json --gate-form compact_sig --max-menu-tokens 800 # exit 1 if the menu is too heavy
lap lint openapi.json --fail-on warn # exit 1 on any warning
lap lint openapi.json --ignore R2,A1 # suppress rules (or a ./.lapignore file)
GitHub Actions:
- run: pip install lap-score # or: pip install -e .
- run: lap score api/openapi.json --gate-form compact_sig --max-menu-tokens 800
- run: lap lint api/openapi.json --fail-on warn
…or the bundled composite Action (one step, no manual install):
- uses: lCrazyblindl/lap@v0.3.0
with:
spec: api/openapi.json
max-menu-tokens: "800" # gate the compact_sig menu (omit = report only)
fail-on: warn # fail on any lint warning (omit = report only)
Already lint OpenAPI with Spectral? The same LAP rules ship as a ruleset —
see ../spectral/.
What it measures (and what it doesn't)
It measures bucket A (the definitions/menu the model carries in context) and estimates
C (result size, from each response schema + an assumed --page-size — a structural lower
bound that captures keys/nesting/types). B (the call) still depends on per-API tasks; for a
full measured A/B/C run see
../experiments/token-bench. The conventions
behind the compact form are the LAP profile.
Files
| file | role |
|---|---|
openapi_ir.py |
load any OpenAPI (file/URL) → normalized operations + inline_refs |
menu.py |
render the menu forms (openapi_full / compact_sig / numbered) from the IR |
mcp_form.py |
real-MCP baseline via FastMCP.from_openapi (optional; --no-mcp to skip) |
mcp_client.py |
scores a live MCP server's advertised tools (lap score --mcp-url) |
estimate.py |
estimates bucket C (result size) from response schemas (--page-size) |
tokens.py |
token counting (Anthropic endpoint, or tiktoken approx) |
score.py |
the lap score CLI |
lint.py |
the lap lint CLI — checks a spec against the LAP profile rules (D3/R1/R2/R3/W1/E1/A1) |
examples/ |
sample specs: a Bookstore API, a gnarly OpenAPI 3.1 (allOf / $ref-params / nullable / external-ref), and a Swagger 2.0 spec (swagger2.json) |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lap_score-0.3.0.tar.gz.
File metadata
- Download URL: lap_score-0.3.0.tar.gz
- Upload date:
- Size: 33.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97e7aef65bcf42fd692c50eecaebe94022a35772b8cf1e042934940ef80eb839
|
|
| MD5 |
87a89c6d86aaa1d1494d00a5f83c96d9
|
|
| BLAKE2b-256 |
60eeb8d849e168da916f7a5c53733db3eeee11bc9f5b56beca9c8f8ece46be8b
|
File details
Details for the file lap_score-0.3.0-py3-none-any.whl.
File metadata
- Download URL: lap_score-0.3.0-py3-none-any.whl
- Upload date:
- Size: 28.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
914235e16060ba63bb7972d27b2a63e001c0490b52fa427aaa5bd4390a1ca201
|
|
| MD5 |
64d2fbed9fcf262eeff3bc23972f43bc
|
|
| BLAKE2b-256 |
d905be77fd3bdd531263ecf2e9f04e17c88c7676990f955f661c90dff0a50bb6
|