Skip to main content

Hidden Moves MCP adapter

An optional adapter around explicitly selected capability catalogs. The MCP SDK dependency belongs to this distribution; the core registry remains independent.

python -m pip install hidden-moves-mcp==0.1.0
hidden-moves-mcp --help

The experimental 0.1.x adapter depends on hidden-moves>=0.1,<0.2 and Python 3.11 or newer. Published GitHub releases use v0.1.0-mcp for this package in the shared repository. .github/workflows/release.yaml builds only its distribution, checks installed-wheel transports, and publishes in environment pypi-mcp.

Local installation

From the repository root:

uv venv /tmp/hidden-moves-mcp-env
uv pip install --python /tmp/hidden-moves-mcp-env/bin/python \
  . ./examples/text-plugin ./packages/hidden-moves-mcp
/tmp/hidden-moves-mcp-env/bin/python -m unittest discover \
  -s packages/hidden-moves-mcp/tests -v

The adapter uses the official Python SDK, mcp>=2.3.0,<3. The local proof was verified with SDK 2.3.0 and protocol 2026-07-28; legacy clients can negotiate the SDK's supported 2025-11-25 handshake. See the official protocol-version documentation.

Configure a local stdio host

A host starts the installed executable and owns the subprocess:

{
  "command": "/tmp/hidden-moves-mcp-env/bin/hidden-moves-mcp",
  "args": [
    "--plugin", "example-text",
    "--move", "example.text.repeat"
  ]
}

The --move option is required and repeatable. Only those names are listed and callable. Providers must be explicitly enabled with --plugin; installing one does not activate it. The executable begins with an empty registry and supplies no target binding. Configure a Python host for target-bound providers. It waits for protocol input on stdin and exits when its host closes the connection. Output on stdout is the protocol stream; application logging belongs on stderr.

This is an executable local proof, without a public service or configured account. The temporary environment is suitable for testing; install into a durable location before configuring a host for regular use.

Python setup and binding

import asyncio

from hidden_moves import Moves
from hidden_moves.adapters import CapabilityCatalog
from hidden_moves_example_text import repeat_text
from hidden_moves_mcp import MCPAdapter, serve_stdio

moves = Moves()
moves.learn(repeat_text, name="repeat", namespace="example.text")
catalog = CapabilityCatalog(moves, ["example.text.repeat"])
server = MCPAdapter(catalog).server()

if __name__ == "__main__":
    asyncio.run(serve_stdio(server))

Applications can configure clients or targets before building the catalog. The adapter consumes those bound callables and does not infer credentials or context. The stdio adapter defaults to invoking synchronous functions in the request handler and awaiting awaitable results there. MCPAdapter also accepts explicit offload_sync=True and a finite call_timeout for hosts that need them. Client resource setup and shutdown belong to the application.

Local Streamable HTTP

from hidden_moves_mcp import create_http_app, serve_http

async def authorize(request):
    # Check the application's local request grant without consuming the body.
    return await local_access_policy(request.headers)

app = create_http_app(catalog, authorize=authorize)
asyncio.run(serve_http(app, port=8000))

The application supplies an async authorizer that returns exactly True for each allowed request. Missing grants, rejected grants and authorizer exceptions return 401 before protocol dispatch. It chooses credentials, request identity and the selected catalog; no installed provider or account is activated implicitly.

serve_http binds only 127.0.0.1. The SDK's ASGI app handles Streamable HTTP, initialization, protocol negotiation and lifespan cleanup at /mcp, with its default localhost Host/Origin protection. Responses are JSON and HTTP is stateless. The same adapter supplies schemas, annotations and structuredContent: {"result": value} over HTTP and stdio. Unselected names remain protocol errors. Mounting the returned app inside another application requires the host to run its lifespan, as described in the SDK guide.

Defaults are a 10-second call deadline, 30-second request deadline, 16 concurrent requests and a 1 MiB request body. Limits must be finite; excess concurrency returns 503, an expired request returns 504, and the SDK rejects oversized bodies with 413. Timed-out tools return sanitized tool errors. Access logging is disabled by the local serving helper, and forwarded identity headers are not trusted.

HTTP offloads synchronous capabilities by default so blocking I/O does not stop other requests. Async capabilities execute on the event loop. Configure the underlying clients with their own finite I/O timeouts: cancellation cannot stop a running Python worker thread, and a timed-out write may still complete. Inspect its outcome before submitting another write. Thread-affine resources need an application-owned execution strategy; offload_sync=False is available for fast event-loop-safe callables, whose deadlines depend on cooperative yielding. The host owns resource cleanup and concurrency safety.

examples/mcp_http.py serves only example.text.repeat using an explicitly configured HIDDEN_MOVES_LOCAL_HTTP_TOKEN of 32–512 printable ASCII characters. It demonstrates a local request grant; hosted OAuth, delegated GitHub credentials and per-user catalog isolation require their separate authentication work.

Installed-wheel tests run real loopback initialize/list/call clients in modern and legacy modes, compare Python/HTTP DTOs, check authorization and request limits, exercise cancellation and worker offloading, then shut down the SDK lifespan and listener. The existing real stdio subprocess checks still run in the same suite.

Export contract

MCP names retain qualified capability names when they satisfy the protocol's ASCII name rules. Explicit tool_names={qualified_name: alias} mappings handle other names; invalid or colliding aliases fail before server creation. Exported schemas are independent copies of neutral definitions.

All successful results use structuredContent: {"result": value} with the matching object output schema and an equivalent JSON text block. This includes object, scalar, list, and null results. The catalog validates and serializes the underlying value before wrapping it. Ordinary Python results remain unchanged outside this adapter.

Behavioral hints map explicitly to MCP annotations, with unknown hints omitted. They do not authorize calls. The host/application chooses exposure and approval policy. Invalid arguments and invalid results are tool errors. Capability failures are tool errors reporting the exception type, without exposing arbitrary exception contents. Unknown/unexposed tool names are protocol errors. Cancellation propagates.

The low-level SDK server handles protocol discovery, legacy negotiation, wire types, and connection lifetime; the adapter owns its list/call handlers and uses the catalog for validation.

Metadata

Release files for hidden-moves-mcp 0.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 hidden-moves-mcp 0.1.0
File Size Uploaded
hidden_moves_mcp-0.1.0.tar.gz 9.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hidden-moves-mcp 0.1.0
File Interpreter ABI Platform
hidden_moves_mcp-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 20.6 kB

Release files / hidden_moves_mcp-0.1.0.tar.gz

Download URL hidden_moves_mcp-0.1.0.tar.gz
Size 9.0 kB
Tags Source
SHA-256 checksum
How to use checksums
b7dfdab836c009f0d3f2e3897fa5487c1b67e4a0539cbfbcb30a7a96816a54f7
BLAKE2b-256 checksum
How to use checksums
b25d8b73012476150bb9c36fdd0304dbdd9cd7dae2552da564c8c2f2c3ab6173
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / hidden_moves_mcp-0.1.0-py3-none-any.whl

Download URL hidden_moves_mcp-0.1.0-py3-none-any.whl
Size 11.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1fa3c50783c6ed4c1f16a3132c6285caf72f2910f63cdedcb613d79d555feff8
BLAKE2b-256 checksum
How to use checksums
0d32b68916e850c4286e1f56945c222dbc7d140cf209ed8e117b419563a9e18d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

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