Skip to content

Add an MCP server: marketplace as native tool calls for MCP-client agents - #22

Merged
alipishbin77 merged 1 commit into
mainfrom
mcp-server
Sep 30, 2026
Merged

alipishbin77 merged 1 commit into
mainfrom
mcp-server

Conversation

@alipishbin77

Copy link
Copy Markdown
Owner

Exposes Aether's service catalogue as 6 MCP tools (list_services, get_service, register_agent, get_funding_instructions, get_balance, invoke_service) — a stateless proxy over the existing REST API, no new money-handling logic, no secrets held by this layer (every call authenticated with whatever credential the caller supplies). Mounted at /mcp, dispatched via an in-process ASGI transport rather than a network hop. Verified against a real MCP client, not just import-checked. 185 tests pass, ruff clean. Next: publish to the official MCP registry once this is live.

…lient agent

New app/mcp_server.py exposes 6 tools (list_services, get_service,
register_agent, get_funding_instructions, get_balance, invoke_service) as a
thin, stateless proxy over the existing REST API — every call is authenticated
with whatever credential the caller supplies, exactly like a direct REST call.
This process holds no agent secrets and makes no money-handling decisions; all
escrow/settlement logic stays in the already-tested REST layer.

Mounted at /mcp in app/main.py, dispatched in-process via an ASGI transport
(bind_app()), not a real TCP hop to a hardcoded port — caught during manual
testing: an earlier hardcoded 'http://127.0.0.1:8000' meant a local smoke test
silently hit the live production instance on the same box instead of the
isolated test instance actually being exercised. ASGI transport makes that
class of bug structurally impossible.

The MCP SDK's session manager has its own anyio task group that must be
cancelled from the same task it started in; a shared AsyncExitStack entered
through this file's own lifespan function broke across a session-scoped test
fixture's setup/teardown ('Attempted to exit cancel scope in a different task
than it was entered in'). Fixed by running the session manager as its own
asyncio task, cancelled the same way the existing settlement-worker and
maintenance-loop tasks already are.

Transport security (DNS-rebinding guard) needs its allowed_hosts/allowed_origins
set explicitly — the default is reject-everything, not disabled; derived from
settings.public_base_url.

Verified against a real MCP client (streamable_http_client + ClientSession),
not just import-checked: tool discovery, list_services, register_agent,
get_balance, and rejection of a bad api_key all round-trip correctly, first
against a live isolated instance, then as 4 new tests in the suite (185 total
pass, ruff clean).
@alipishbin77
alipishbin77 merged commit 1a2d583 into main Sep 30, 2026
4 checks passed
@alipishbin77
alipishbin77 deleted the mcp-server branch September 30, 2026 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant