sondahub

sondahub / MCP test server

MCP test server

A free, public Model Context Protocol server with real data behind it: tools over seven populated APIs, domain tools with real rules, resources, prompts and completions — and tools made to put an MCP client through its paces. With an OAuth-protected twin for the authorization flow.

Streamable HTTP at https://api.sondahub.com/mcp. No keys, no accounts. 26 tools, 47 resources (paged 20 at a time) and 2 templates, 4 prompts.

Connect

Address
https://api.sondahub.com/mcp
Transport
Streamable HTTP, stateless
Protocol
2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05
Auth
none — or OAuth 2.1 at /mcp/secure

Any MCP client that speaks Streamable HTTP connects with the address alone. A few common ones:

Claude Code
claude mcp add --transport http sondahub https://api.sondahub.com/mcp
Cursor — .cursor/mcp.json
{
  "mcpServers": {
    "sondahub": {
      "url": "https://api.sondahub.com/mcp"
    }
  }
}
VS Code — .vscode/mcp.json
{
  "servers": {
    "sondahub": {
      "type": "http",
      "url": "https://api.sondahub.com/mcp"
    }
  }
}
MCP Inspector
npx @modelcontextprotocol/inspector
# Transport: Streamable HTTP · URL: https://api.sondahub.com/mcp

How it behaves

Every request is answered on its own: no session, no server-to-client stream (a GET for one answers 405), nothing remembered between requests. That is the only kind of MCP server a site that stores nothing can be — and a valid one under the specification.

Reads are real. The write tools — create_record, update_record, delete_record, bank_transfer, flights_book, fleet_send_command, helpdesk_reply — validate, run the real rules and answer as a real server would. The server keeps nothing: the HTTP answer carries the change in an X-Sondahub-Session token, and a client that sends it back sees its writes. Their results carry _note in the structured content and "sondahub/write" in _meta. Calls in one JSON-RPC batch share the session, so a batch can create and then read.

Answers are JSON, except when the client accepts text/event-stream and calls a tool that streams (slow_operation): then progress notifications (when the request carries a progressToken) and log messages arrive first, the result last. Wrong arguments come back as a tool result with isError: true naming each problem, so a model can correct itself; an unknown tool or method is a JSON-RPC error.

Data

describe_api Describe an API · read-only

The collections of one sondahub API with their record counts, fields (types, required, read-only, allowed values) and relations. Start here to learn what list_records and the other data tools can ask for.

ArgumentTypeNotes
apirequiredstring: store | fleet | bank | social | helpdesk | flights | identityWhich API: store, fleet, bank, social, helpdesk, flights, identity.

list_records List records · read-only · structured output

A page of records from any collection, with filters, search, sorting, field selection and embedded relations. Filters are an object whose keys are field names, optionally with a suffix: _ne, _gt, _gte, _lt, _lte, _like (contains, case-insensitive), _in (a list), _null (true/false); a dotted key reaches into a JSON field (address.country). Example: {"price_lt": 20, "in_stock": true, "category_id_in": [1, 6]}.

ArgumentTypeNotes
apirequiredstring: store | fleet | bank | social | helpdesk | flights | identityWhich API: store, fleet, bank, social, helpdesk, flights, identity.
collectionrequiredstringA collection of that API, e.g. products, orders, accounts, transactions, devices, flights, tickets, posts. describe_api lists them.
filtersobjectField conditions, all of which must hold.
qstringSearch across the text fields.
sortstringComma-separated fields; prefix one with - for descending. Example: "-price,name".
pageinteger (≥ 1)Default 1.
limitinteger (≥ 1, ≤ 100)Default 10.
fieldsarrayOnly these fields back (id is always included).
expandarrayRelations to embed, e.g. ["customer", "items"] on orders.

get_record Get a record · read-only

One record by id, optionally with relations embedded.

ArgumentTypeNotes
apirequiredstring: store | fleet | bank | social | helpdesk | flights | identityWhich API: store, fleet, bank, social, helpdesk, flights, identity.
collectionrequiredstringA collection of that API, e.g. products, orders, accounts, transactions, devices, flights, tickets, posts. describe_api lists them.
idrequiredinteger (≥ 1)The record id.
expandarray

create_record Create a record · writes · simulated

Create a record in any collection. Validated and answered exactly as the REST API answers a POST — ids, computed fields, related records — but simulated: nothing is stored. describe_api lists the fields.

ArgumentTypeNotes
apirequiredstring: store | fleet | bank | social | helpdesk | flights | identityWhich API: store, fleet, bank, social, helpdesk, flights, identity.
collectionrequiredstringA collection of that API, e.g. products, orders, accounts, transactions, devices, flights, tickets, posts. describe_api lists them.
recordrequiredobjectThe fields of the new record.

update_record Update a record · writes · simulated

Change fields of a record (or replace it whole with replace: true). Validated and answered as the REST API answers a PATCH or PUT, including status rules such as a ticket’s allowed moves — simulated, nothing is stored.

ArgumentTypeNotes
apirequiredstring: store | fleet | bank | social | helpdesk | flights | identityWhich API: store, fleet, bank, social, helpdesk, flights, identity.
collectionrequiredstringA collection of that API, e.g. products, orders, accounts, transactions, devices, flights, tickets, posts. describe_api lists them.
idrequiredinteger (≥ 1)The record id.
changesrequiredobjectThe fields to change.
replacebooleantrue: the record becomes exactly these fields (PUT). Default false.

delete_record Delete a record · destructive · simulated

Delete a record — simulated: the answer is what would have been removed; the record is still there afterwards.

ArgumentTypeNotes
apirequiredstring: store | fleet | bank | social | helpdesk | flights | identityWhich API: store, fleet, bank, social, helpdesk, flights, identity.
collectionrequiredstringA collection of that API, e.g. products, orders, accounts, transactions, devices, flights, tickets, posts. describe_api lists them.
idrequiredinteger (≥ 1)The record id.

Store

store_search_products Search products · read-only · structured output

Search the store’s active products by words, category, price and stock.

ArgumentTypeNotes
querystringWords to look for in the name, brand and description.
categorystring: audio | computers | home | outdoors | fitness | books | toys | garden
min_pricenumber (≥ 0)
max_pricenumber (≥ 0)
in_stockboolean
sortstring: price | -price | rating | -rating | nameDefault "-rating".
limitinteger (≥ 1, ≤ 50)Default 10.

store_order_status Order status · read-only · structured output

Where an order is: status, dates, tracking, the customer and the lines, by order number (SH-100042).

ArgumentTypeNotes
order_numberrequiredstring (matches ^SH-\d{6}$)Like SH-100042.

Bank

bank_account_summary Account summary · read-only

An account with its holder, cards and latest transactions.

ArgumentTypeNotes
account_idrequiredinteger (≥ 1)The record id.
transactionsinteger (≥ 1, ≤ 50)Default 5.

bank_transfer Transfer money · writes · simulated

Move money between two accounts of the same currency. Checks both accounts and the funds, then answers with the transfer and both transactions. The balances move for whoever carries the session token.

ArgumentTypeNotes
from_account_idrequiredinteger (≥ 1)The record id.
to_account_idrequiredinteger (≥ 1)The record id.
amountrequirednumber (≥ 0.01)
descriptionstring

bank_convert_currency Convert currency · read-only · structured output

Convert an amount with the bank’s FX table, directly or across USD.

ArgumentTypeNotes
amountrequirednumber
fromrequiredstring: USD | EUR | GBP | ARS | BRL | MXN | JPY | CAD | AUD | CHF
torequiredstring: USD | EUR | GBP | ARS | BRL | MXN | JPY | CAD | AUD | CHF

Fleet

fleet_device_status Device status · read-only

A device by serial: its site, latest readings and open alerts.

ArgumentTypeNotes
serialrequiredstringLike TH200-7K2M4Q; list_records on fleet/devices shows them.
readingsinteger (≥ 1, ≤ 50)Default 5.

fleet_send_command Send a device command · writes · simulated

Send a command to a device; an online device acknowledges it in the answer, an offline one queues it — simulated.

ArgumentTypeNotes
serialrequiredstring
actionrequiredstring: reboot | set_config | report_now | update_firmware | identify
paramsobjectFor set_config: {"report_interval_s": 30}; for update_firmware: {"version": "3.0.0"}.

Flights

flights_book Book a seat · writes · simulated

Book a seat on a flight: refuses cancelled, departed and full flights, picks a free seat in the cabin, prices the fare and mints a record locator — simulated.

ArgumentTypeNotes
flight_idrequiredinteger (≥ 1)The record id.
first_namerequiredstring
last_namerequiredstring
emailstring
cabinstring: economy | premium | business | firstDefault "economy".

Helpdesk

helpdesk_ticket Read a ticket · read-only

A ticket by number (HD-10042) with its customer, assignee and whole message thread.

ArgumentTypeNotes
ticket_numberrequiredstring (matches ^HD-\d+$)

helpdesk_reply Reply to a ticket · writes · simulated

Add a message to a ticket as the agent or the customer; a customer reply reopens a pending ticket — simulated.

ArgumentTypeNotes
ticket_numberrequiredstring (matches ^HD-\d+$)
bodyrequiredstring
asstring: agent | customerDefault "agent".
internalbooleanDefault false.

Social

social_profile User profile · read-only

A user by username with their counters and latest posts.

ArgumentTypeNotes
usernamerequiredstring
postsinteger (≥ 1, ≤ 50)Default 5.

Testing a client

echo Echo · read-only

Answers with the message you send, optionally repeated.

ArgumentTypeNotes
messagerequiredstring
repeatinteger (≥ 1, ≤ 10)Default 1.

whoami Who am I · read-only

On the OAuth-protected endpoint (/mcp/secure): the identity and scopes in your access token. On the open endpoint: says there is none.

No arguments.

add Add two numbers · read-only · structured output

a + b, as text and as structured content checked by an output schema.

ArgumentTypeNotes
arequirednumber
brequirednumber

slow_operation Slow operation with progress · read-only · streams progress

Takes its time, in steps. When the client sends a progressToken and accepts text/event-stream, each step arrives as a progress notification and a log message before the result.

ArgumentTypeNotes
secondsnumber (≥ 0.5, ≤ 10)Default 3.
stepsinteger (≥ 1, ≤ 20)Default 5.

fail Fail on purpose · read-only

Fails, to see how a client shows it: tool_error answers a result with isError: true (the model sees it), protocol_error answers a JSON-RPC error (the client sees it).

ArgumentTypeNotes
modestring: tool_error | protocol_errorDefault "tool_error".

generate_image Draw an image · read-only

A PNG of the size and colour you ask for, as image content.

ArgumentTypeNotes
widthinteger (≥ 1, ≤ 512)Default 160.
heightinteger (≥ 1, ≤ 512)Default 100.
colorstring (matches ^[0-9a-fA-F]{6}$)Hex, no #. Default "f1772c".

mixed_content Every content type · read-only

One result carrying every content type — text for the user and for the model (annotations), an image, a sound, a resource link and an embedded resource — to see how a client renders each.

No arguments.

large_text A large answer · read-only

A text result of the size you ask for, to see how a client copes with a big answer.

ArgumentTypeNotes
kilobytesinteger (≥ 1, ≤ 512)Default 64.

Resources

Every collection is a resource — sondahub://{api}/{collection}, 37 of them — holding its first 25 records, the total and the fields, with later pages at …/page/{n}. Besides those:

URITypeWhat
sondahub://guidetext/markdownWhat the tools, resources and prompts here are, and the rule that writes are simulated.
sondahub://apisapplication/jsonThe seven APIs with their collections and record counts.
sondahub://store/openapi.jsonapplication/jsonThe OpenAPI 3 description of the Store REST API.
sondahub://fleet/openapi.jsonapplication/jsonThe OpenAPI 3 description of the Fleet REST API.
sondahub://bank/openapi.jsonapplication/jsonThe OpenAPI 3 description of the Bank REST API.
sondahub://social/openapi.jsonapplication/jsonThe OpenAPI 3 description of the Social REST API.
sondahub://helpdesk/openapi.jsonapplication/jsonThe OpenAPI 3 description of the Helpdesk REST API.
sondahub://flights/openapi.jsonapplication/jsonThe OpenAPI 3 description of the Flights REST API.
sondahub://identity/openapi.jsonapplication/jsonThe OpenAPI 3 description of the Identity REST API.
sondahub://utils/sample.pngimage/pngA binary resource (a PNG), returned as a blob.

Templates

URI templateWhat
sondahub://{api}/{collection}/{id}One record of any collection by id, e.g. sondahub://store/orders/7.
sondahub://{api}/{collection}/page/{page}25 records per page, e.g. sondahub://bank/transactions/page/3.

Completion works on the template arguments: api, collection (given the api), id and page.

Prompts

PromptArgumentsWhat
explore_apiapirequiredGet to know one of the APIs: what it holds, how the collections relate, and three good first questions to ask it.
investigate_orderorder_numberrequiredLook into a store order: what was bought, where it is, and anything odd about it.
fleet_health_reportsite_codeA health report of the IoT fleet, or of one site.
support_replyticket_numberrequired
tone
Draft the next agent reply on a helpdesk ticket from its whole thread.

Each prompt embeds the data it is about as a resource in its messages. Completion offers API names, order numbers, ticket numbers, site codes and tones as you type.

Over plain HTTP

MCP over Streamable HTTP is JSON-RPC in a POST, so curl — or a request in Sonda — speaks it too:

Initialize
curl https://api.sondahub.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
Call a tool
curl https://api.sondahub.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"store_order_status","arguments":{"order_number":"SH-100007"}}}'
Progress over SSE
curl -N https://api.sondahub.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"slow_operation","arguments":{"seconds":3,"steps":3},"_meta":{"progressToken":"p1"}}}'

Questions

Is there a public MCP server I can test my client against?

This one: https://api.sondahub.com/mcp, Streamable HTTP, no auth, no signup. It has real data behind its tools, every content type a tool result can carry, a tool that streams progress, one that fails on purpose, and argument checking that answers like a strict server.

Does it keep a session or push notifications?

No. It is stateless: no Mcp-Session-Id, a GET for a server-to-client stream answers 405, and nothing is remembered between requests — a valid shape under the specification. Progress and log notifications arrive on the response stream of the call that streams (slow_operation).

Which MCP protocol versions does it speak?

2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05. It answers initialize with the version the client asked for when it knows it, and the newest otherwise.

Can an agent change the data?

Yes, for itself. The write tools validate, run the real rules and answer as a real server would; the HTTP answer carries an X-Sondahub-Session token with the change, and a client that sends it back sees its writes on the next call. A client that does not gets the seed again — the results say which in _note and _meta, so a test can tell.

Is there an MCP server with OAuth to test the authorization flow?

Yes: https://api.sondahub.com/mcp/secure is this server behind OAuth 2.1 as the MCP specification describes it — a 401 pointing at protected-resource metadata, authorization-server metadata, dynamic client registration, PKCE, resource indicators and scopes. The flow, step by step.