Skip to main content

bowmark-mcp — Bowmark MCP over stdio

Bowmark turns the interaction-gated web into a callable function library. An agent reads the library (get_library), writes a short JavaScript script against it, and sends it to run — Bowmark executes it on the live sites in a sandbox and hands back the result. The canonical server is hosted, streamable HTTP, no auth required: https://api.bowmark.ai/mcp.

This package is a thin stdio bridge to that hosted server, for MCP hosts whose client only speaks stdio (for example browser-use's MCPClient). Tool schemas, descriptions, and results pass through verbatim — the hosted server stays the single source of truth; nothing is reimplemented here. (Node-flavored environments: the same bridge exists on npm as bowmark-mcp — npx @bowmark/mcp, packages/bowmark-mcp/node/ in the monorepo. The npm name is scoped and this one is not, deliberately: PyPI cannot be scoped and has no rename mechanism, so bowmark-mcp here is already what PEP 752 blesses.)

mcp-name: ai.bowmark/bowmark

Use

uvx bowmark-mcp        # or: pipx run bowmark-mcp / python -m bowmark_mcp

Example — browser-use:

from browser_use.mcp.client import MCPClient

bowmark = MCPClient(server_name="bowmark", command="uvx", args=["bowmark-mcp"])

Example — any MCP host config:

{ "mcpServers": { "bowmark": { "command": "uvx", "args": ["bowmark-mcp"] } } }

If your host speaks streamable HTTP, skip this bridge and connect directly to https://api.bowmark.ai/mcp.

Environment

Var Meaning
BOWMARK_MCP_URL Target MCP URL. Default https://api.bowmark.ai/mcp/pypi (the /pypi destination attributes the install to this bridge). Point at http://localhost:3001/mcp for a local Bowmark API.
BOWMARK_API_KEY Optional. Forwarded as X-Bowmark-Key; a free key (bowmark.ai dashboard) lifts the anonymous per-IP daily cap to your plan budget.

Design notes (repo-internal)

  • One remote session per request, retried once. streamablehttp_client is an anyio-scoped context manager; holding one session across handler tasks trips "exit cancel scope in a different task". The hosted MCP is stateless, so a fresh session per request is semantically identical and costs one initialize round-trip — noise next to a run that drives real browsers.
  • The real host's name is relayed upstream. The api tailors its operating guidance per host and detects the host from clientInfo on the handshake — but through a bridge that names the BRIDGE, so every install here would read the platform-neutral text. So the host's own clientInfo.name (from OUR stdio handshake) is forwarded as X-Bowmark-Client on every proxied request, and the api ranks that above its own handshake. Best-effort: an unknown or missing name simply falls back to the neutral text, never an error.
  • Pass-through only. No tool logic lives here; the agent-surfaces sync rule in the root CLAUDE.md is unaffected because descriptions/schemas ride through from apps/api/src/routes/mcp.ts.
  • The /pypi destination is registered in apps/api/src/mcp-destinations.ts + mcp-registry/sources.json (PyPI stdio bridge channel). It carries the channel and deliberately pins NO platform, because the relayed X-Bowmark-Client above is a better answer than any pin. The old ?s=p query form still resolves for installs already in the wild. Adding a destination: .claude/rules/mcp-destinations.md.
  • The mcp-name: ai.bowmark/bowmark line above is load-bearing: the official MCP Registry validates PyPI package ownership by finding that marker in the package README. Don't remove it.
  • Versioning is manual (this is a thin bridge, not the api): bump pyproject.toml when it changes. Not wired into release-please.

Tests

cd packages/bowmark-mcp/python
uv run --with pytest --with-editable . pytest -q

Network-free (the remote hop is monkeypatched). A live smoke against prod:

uv run --with-editable . python - <<'EOF'
import asyncio, bowmark_mcp
async def main():
    tools = await bowmark_mcp.list_tools_impl()
    print([t.name for t in tools])
asyncio.run(main())
EOF

Publishing to PyPI

Live since 2026-07-03, published + cold-verified via uvx bowmark-mcp against prod. To ship a new version: bump version in pyproject.toml and merge. The actual publish does NOT run in this monorepo's CI — this repo is private, and PyPI Trusted Publishing (OIDC) validates against pyproject.toml's Repository URL, which (correctly) points at the public mirror github.com/bowmark-ai/mcp, not Metroxe/bowmark. So merging here only lands the version bump; release-bowmark-mcp.yml mirror-syncs it to bowmark-ai/mcp, and THAT repo's own .github/workflows/publish.yml (source-controlled at packages/bowmark-mcp/.github/workflows/publish.yml in this monorepo, mirrored in like any other file) does the real uv publish. Auth is PyPI Trusted Publishing (OIDC) — no token, configured on pypi.org (project → Publishing → GitHub publisher for bowmark-ai/mcp / publish.yml). Publishing from the public mirror also auto-generates provenance attestations. Not release-please; the bump IS the release action. If the registry surface changed, also bump packages[0].version in mcp-registry/server.json (rides the next api-release republish — the registry validates ownership via the mcp-name marker above).

Manual fallback (creds: 1Password item "PyPI", vault Christopher-Macbook-CLI, token in the Christopher_Bowmark_API_Key field; service-account op read requires the vault in the path): cd packages/bowmark-mcp/python && rm -rf dist && uv build && UV_PUBLISH_TOKEN="$(op read 'op://Christopher-Macbook-CLI/PyPI/Christopher_Bowmark_API_Key')" uv publish

Metadata

Release files for bowmark-mcp 2.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bowmark-mcp 2.1.0
File Size Uploaded
bowmark_mcp-2.1.0.tar.gz 63.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bowmark-mcp 2.1.0
File Interpreter ABI Platform
bowmark_mcp-2.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 71.0 kB

Release files / bowmark_mcp-2.1.0.tar.gz

Download URL bowmark_mcp-2.1.0.tar.gz
Size 63.2 kB
Tags Source
SHA-256 checksum
How to use checksums
ce5fc1575d28b8ba2c4789796a2bca67fdadae27bb184d910fee68f05d7f87c5
BLAKE2b-256 checksum
How to use checksums
bcbec3baa6e511d48f4e7da0f78d29c51ba4ddc95c6e964d25ad22319e1a5d55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / bowmark_mcp-2.1.0-py3-none-any.whl

Download URL bowmark_mcp-2.1.0-py3-none-any.whl
Size 7.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
297fa0e5876d6e8efa000d85c14a1ff93df5ae464e53f8f528aed57c329b9cb0
BLAKE2b-256 checksum
How to use checksums
836d7151ad82fed345f812502dae398ae3a1abeb2a7885353f10605b83422228
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

2.1.0 This release

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page