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-mcpnpx bowmark-mcp, packages/bowmark-mcp/node/ in the monorepo.)

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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bowmark_mcp-2.0.1.tar.gz (63.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bowmark_mcp-2.0.1-py3-none-any.whl (7.7 kB view details)

Uploaded Python 3

File details

Details for the file bowmark_mcp-2.0.1.tar.gz.

File metadata

  • Download URL: bowmark_mcp-2.0.1.tar.gz
  • Upload date:
  • Size: 63.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","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}

File hashes

Hashes for bowmark_mcp-2.0.1.tar.gz
Algorithm Hash digest
SHA256 d9df8f8cc0d52c3463aceafe4e0dbf8b0c7f71a4e72b83b6b5ef5d47b8b40269
MD5 1fbe96e31b5e8d4b064b13b0ac457537
BLAKE2b-256 35afe45d7bceb9862848e29505e40e3a22ce98d114b221756673c03fb987c187

See more details on using hashes here.

File details

Details for the file bowmark_mcp-2.0.1-py3-none-any.whl.

File metadata

  • Download URL: bowmark_mcp-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 7.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","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}

File hashes

Hashes for bowmark_mcp-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 edee96ad0df00e1e50bb4f43b59d10023b1fed5a01a6d1c4dcf3fb2021b31dc7
MD5 f71ef4c587246fb4a11ba32461a73761
BLAKE2b-256 abfd8d6f8afa1c081b43352009433a61eda1ca7a27915a9df2d53bf61fa4cec7

See more details on using hashes here.

Release history Release notifications | RSS feed

2.1.0

2 files

This release

2.0.1 This release

2 files

2.0.0

2 files

1.0.1

2 files

1.0.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page