Tutorial 1: your first search
What you will have at the end. A running rypsok that answers a
web_search call, an answer you have read line by line, and a host entry
that lets your agent runtime start rypsok itself.
What you need. The rypsok binary and a shell. No key, no account:
this tutorial uses Wikipedia, which needs none.
1. Write the configuration
Save this as rypsok.toml:
# Tutorial 1: one keyless engine, nothing else to set up.
config_version = 1
[engines.wikipedia]
type = "wikipedia"
categories = ["general", "science"]
Check it:
rypsok check --config rypsok.toml
You should see configuration from --config rypsok.toml is valid, the
effective settings, and the line
engine wikipedia: type=wikipedia enabled=true ... no credential needed.
2. Talk to rypsok without a host
rypsok speaks the Model Context Protocol over standard input and output:
one JSON message per line. Two lines are enough for a first search. Save
them as first-search.jsonl:
{"jsonrpc": "2.0", "id": 1, "method": "server/discover", "params": {"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientInfo": {"name": "tutorial", "version": "1"}, "io.modelcontextprotocol/clientCapabilities": {}}}}
{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "web_search", "arguments": {"query": "rust programming language", "max_results": 5}, "_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientInfo": {"name": "tutorial", "version": "1"}, "io.modelcontextprotocol/clientCapabilities": {}}}}
The first line asks rypsok what it offers; the second calls web_search.
The _meta object names the protocol revision and your client; every
call carries it. Now pipe the file in:
rypsok serve --config rypsok.toml < first-search.jsonl 2>/dev/null
rypsok answers each line with one line, then stops because its input
ended. The 2>/dev/null hides the logs; drop it to see them.
3. Read the answer
The second answer looks like this (the search was answered by a fixed Wikipedia sample when this page was built; the titles you see come from Wikipedia today, the shape is the same):
{
"request": {
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "web_search",
"arguments": {
"query": "rust programming language",
"max_results": 5
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "tutorial",
"version": "1"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
},
"response": {
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "{\"notices\":[],\"outcome\":\"ok\",\"results\":[{\"date\":\"2026-09-01\",\"snippet\":\"Rust is a general-purpose programming language emphasizing performance, type safety, and concurrency. It enforces memory safety—meaning that all references\",\"title\":\"Rust (programming language)\",\"url\":\"https://en.wikipedia.org/wiki/Rust_(programming_language)\"},{\"date\":\"2026-07-19\",\"snippet\":\"Rust and Bone is a 2012 romantic drama film\",\"title\":\"Rust & Bone\",\"url\":\"https://en.wikipedia.org/wiki/Rust_&_Bone\"}]}"
}
],
"structuredContent": {
"notices": [],
"outcome": "ok",
"results": [
{
"date": "2026-09-01",
"snippet": "Rust is a general-purpose programming language emphasizing performance, type safety, and concurrency. It enforces memory safety—meaning that all references",
"title": "Rust (programming language)",
"url": "https://en.wikipedia.org/wiki/Rust_(programming_language)"
},
{
"date": "2026-07-19",
"snippet": "Rust and Bone is a 2012 romantic drama film",
"title": "Rust & Bone",
"url": "https://en.wikipedia.org/wiki/Rust_&_Bone"
}
]
},
"isError": false
}
}
}
Reading it from the top:
isError: false: the call succeeded andstructuredContentholds the answer. The same JSON is repeated as text incontent[0].textfor hosts that read text only.outcome: "ok": every engine asked answered. The other outcomes arepartial(results, but an engine failed) andempty(an engine answered, nothing remained).notices: []: nothing to tell you. When rypsok cut a snippet, skipped an engine or dropped a result, a notice says so, from a fixed list.results: at mostmax_results, deduplicated and ranked.title,urlandsnippetcome from the engine and are cleaned and bounded;dateis present when the engine supplied one.
Everything in title, snippet and url is text from another site.
rypsok never treats it as an instruction, and neither should your agent:
Reading a response says how to tell it.
4. Let your runtime start rypsok
A runtime that speaks MCP starts rypsok as a child process from an entry like this one (the key names vary by runtime; the command and arguments are what matters):
{
"mcpServers": {
"rypsok": {
"command": "rypsok",
"args": ["serve", "--config", "/etc/rypsok/rypsok.toml"]
}
}
}
Restart the runtime, list the tools, and you should see web_search,
web_fetch and engine_status.
If it did not work
checkreported a problem: it names the key. Fix the line it names.- No second line came back: look at the logs (drop
2>/dev/null). A line withengine_failednames the engine and the class of failure, for exampletimeoutwhen Wikipedia could not be reached. - The answer is
emptyfor a query that should match: Wikipedia’s search is literal; try fewer words. - The runtime does not list the tools: run the pipe of step 2 by hand first; if that works, the problem is the host entry’s path or arguments.
More in Troubleshooting. Next: Tutorial 2: a keyed engine.