Step 6: Deploy it, and call it
A deployed tool answers MCP over Streamable HTTP at POST /api/mcp/<tool> and plain REST at POST /api/v1/tools/<tool>/search. Same data, same rules, same answer. Both authenticate with Authorization: Bearer <key>, and a key opens exactly one tool.
Over MCP your agent sees two tools: search_<tool> and get_<tool>. You never write a schema for them. It is generated from your contract, so the model picks allergen values from an enum of your list and literally cannot ask for a value you never defined.
POST /api/v1/tools/menu/search
Authorization: Bearer cc_live_...
Content-Type: application/json
{
"query": "something warm",
"exclude": { "allergens": ["peanut"] },
"limit": 5
}{
"results": [
{
"id": "9f1c...",
"fields": {
"name": "Tomato soup",
"description": "Slow-roasted tomatoes finished with a swirl of cream",
"price": 6.5,
"allergens": ["dairy"]
},
"origin": { "kind": "imported" },
"unknown_safety_fields": [],
"receipts": {
"allergens": {
"method": "rule",
"confidence": 1,
"contract_version": 3,
"decided_by": null
}
}
}
],
"next_cursor": null,
"meta": {
"release": 7,
"contract_versions": { "allergens": 3 },
"applied_exclusions": { "allergens": ["peanut"] },
"total": 1,
"ranking": "query",
"warnings": []
}
}Read meta before you read the results. applied_exclusions is the server telling you what it actually enforced, which is the caller's request merged with whatever the key pins. release and contract_versions are how a logged answer stays explainable months later.
- 1
query
Words, up to 200 characters. Ranked by meaning and by matching text together.
- 2
similar_to
The id of a result. Returns records like it, using the anchor and facet fields from the release.
- 3
filters
Ordinary narrowing: a value, a list, or a
{gte, lte}range on numbers and dates. - 4
exclude
Safety exclusions, enforced in the query. Offered only on safety fields. Read the next section.
- 5
sort
Up to three fields. Missing values always sort last, either direction.
- 6
limit and cursor
Page size, and the opaque cursor from
next_cursor. Send the same other parameters with it. - 7
include_receipts
On by default. Turn it off for a smaller payload once you trust the pipeline.
claude mcp add --transport http menu https://cloudcrane.in/api/mcp/menu \ --header "Authorization: Bearer cc_live_..."
{
"mcpServers": {
"menu": {
"url": "https://cloudcrane.in/api/mcp/menu",
"headers": { "Authorization": "Bearer cc_live_..." }
}
}
}- 1
Claude Desktop, Cursor, Windsurf
The JSON above. Some clients spell the block
serversrather thanmcpServers, and some want atypeofhttpalongside the url. - 2
n8n
MCP Client Tool node, transport HTTP Streamable, Bearer authentication. If it connects but lists no tools, check the transport really is Streamable: this endpoint offers no SSE stream, and a client that silently falls back to SSE finds nothing.
- 3
Docker MCP Gateway
Add it as a remote server with the url and an Authorization header, which the gateway passes through to the endpoint.
- 4
Dify and Flowise
Add the endpoint as an MCP server with a Bearer token.
- 5
LangChain
MultiServerMCPClientwith transportstreamable_httpand a headers dict. - 6
OpenAI Agents SDK
MCPServerStreamableHttpwith the url and headers.
Your own tool's snippet is in the app. Each of these appears on the tool's page once you deploy it, with your url and a real key already filled in, so none of it has to be copied off a web page and edited.