Connect your LangChain agents to Agent Bazaar's metered MCP tool marketplace. Every tool call is priced, metered, and receipted — your agent pays only for what it uses.
pip install langchain langchain-openai
Bazaar runs each provider's MCP server for you behind one HTTPS proxy, so your agent needs no MCP client library. Swap langchain-openai for any LangChain chat model package.
export NOUI_API_KEY="bz_your_key_here" export OPENAI_API_KEY="sk-..." # or any LLM provider
Save this as bazaar_client.py. It lists tools from GET /api/bazaar/catalog and runs them through POST /api/bazaar/proxy:
# bazaar_client.py — no dependencies beyond the standard library
import json
import os
import re
import urllib.error
import urllib.request
BAZAAR_URL = "https://noui.bot/api/bazaar"
API_KEY = os.environ["NOUI_API_KEY"]
def list_bazaar_tools() -> list[dict]:
"""Every active tool in the public catalog, following pagination."""
tools: list[dict] = []
while True:
url = f"{BAZAAR_URL}/catalog?limit=100&offset={len(tools)}"
with urllib.request.urlopen(url, timeout=30) as resp:
page = json.load(resp)
tools += page["tools"]
if not page["tools"] or len(tools) >= page["total"]:
return tools
def tool_function_name(tool: dict) -> str:
"""LLM function names allow only letters, digits, _ and - (max 64)."""
return re.sub(r"[^A-Za-z0-9_-]", "_", tool["tool_name"])[:64]
def tool_description(tool: dict) -> str:
summary = tool["description"] or tool["display_name"]
return (
f"{summary} (price: {tool['pricing']['price']}). "
"Pass the tool's parameters as a JSON object in 'arguments'."
)
def call_bazaar_tool(tool_id: str, arguments: dict | None) -> str:
"""Run one tool through the metered proxy.
Failures (402 balance, 429 rate limit, provider errors) come back as text
so the agent can read them instead of crashing the run.
"""
request = urllib.request.Request(
f"{BAZAAR_URL}/proxy",
data=json.dumps({"tool_id": tool_id, "input": arguments or {}}).encode(),
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
method="POST",
)
try:
with urllib.request.urlopen(request, timeout=30) as resp:
body = json.load(resp)
except urllib.error.HTTPError as err:
try:
error = json.load(err)
except ValueError:
error = {}
return f"Bazaar error {err.code} {error.get('code', '')}: {error.get('message', err.reason)}"
return json.dumps(body["result"])Save this as agent.py next to the client and run it:
from langchain.agents import create_agent
from langchain_core.tools import StructuredTool
from langchain_openai import ChatOpenAI
from bazaar_client import (
call_bazaar_tool,
list_bazaar_tools,
tool_description,
tool_function_name,
)
def make_langchain_tool(tool: dict) -> StructuredTool:
tool_id = tool["id"]
def run(arguments: dict) -> str:
return call_bazaar_tool(tool_id, arguments)
return StructuredTool.from_function(
func=run,
name=tool_function_name(tool),
description=tool_description(tool),
)
tools = [make_langchain_tool(t) for t in list_bazaar_tools()]
print(f"Loaded {len(tools)} Bazaar tools")
agent = create_agent(
model=ChatOpenAI(model="gpt-4o", temperature=0),
tools=tools,
system_prompt="Use Bazaar tools when they help. Every call is billed to your balance.",
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What is the weather in Paris?"}]}
)
print(result["messages"][-1].content)The catalog does not publish parameter schemas yet, so each tool takes one arguments object and the model reads the expected fields from the tool description. To limit spend, filter list_bazaar_tools() by tool_name or pricing.price_cents before building tools.
Every tool call through Bazaar is metered transparently:
What happens on each tool call:
# Check your balance anytime curl https://noui.bot/api/v1/bazaar/balance \ -H "Authorization: Bearer bz_your_key" # View usage and spend curl https://noui.bot/api/v1/bazaar/usage/summary \ -H "Authorization: Bearer bz_your_key"
Build the tool list once at startup and reuse it across agent runs. Each proxy call is a single stateless HTTPS request, so there is no session to keep open.
The client turns insufficient balance (402), rate limits (429) and provider failures (502/504) into text the agent can read, so one failed call never crashes the run. Failed calls are never billed.
Check your balance before and after agent runs. Each tool's price is in its catalog entry and in the description the model sees.