Create your first HTTP function¶
In this lesson you will register a JavaScript handler, call it, and remove it. You need this management-layer checkout, Rust, Python 3, curl, and two terminals. See feature status for the exact baseline. All requests stay on loopback. This lesson uses an unauthenticated local server; use authentication for a shared deployment.
Start the server¶
From the repository root in terminal 1:
cargo build --locked -p server --bin server
export MCP_V8_HTTP_FUNCTIONS_DIR="$(mktemp -d)"
./target/debug/server --heap-store none --http-port 8080 --bind-host 127.0.0.1
Keep the server running. Its fresh registry directory belongs to this lesson.
Register a greeting¶
In terminal 2, write a definition to a temporary file:
cat > /tmp/mcp-greeting.json <<'JSON'
{
"version": 1,
"methods": ["GET"],
"export": "handler",
"source": "function handler(request) { return {status: 200, headers: {'content-type': 'text/plain'}, body: 'Hello from ' + request.path}; }",
"limits": {"timeout_seconds": 5, "heap_mb": 32}
}
JSON
curl --fail-with-body -i -X PUT http://127.0.0.1:8080/api/http-functions/v1/definitions/greeting -H 'Content-Type: application/json' -H 'If-None-Match: *' --data-binary @/tmp/mcp-greeting.json
You should receive a successful response with a quoted ETag. Registration
stores the definition; it does not execute the handler.
Call the handler¶
curl --fail-with-body http://127.0.0.1:8080/functions/v1/greeting
The response body is Hello from /functions/v1/greeting. The handler returns
its response object directly; console.log would produce execution logs instead.
A POST to this GET-only definition returns 405.
Invoke the same function through MCP¶
Keep the server running. In terminal 2, send a sessionless MCP call:
curl --fail-with-body http://127.0.0.1:8080/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2026-07-28' \
-H 'Mcp-Method: tools/call' \
-H 'Mcp-Name: http_function_invoke' \
--data-binary '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"http_function_invoke","arguments":{"name":"greeting","method":"GET"},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"management-lesson","version":"1"},"io.modelcontextprotocol/clientCapabilities":{}}}}'
The MCP result contains a JSON content block with status: 200, response headers,
and a base64 body. Decode body_base64 to see the same greeting returned by HTTP.
Both calls used the definition you registered above. MCP does not require a
second registration or a separate registry directory.
Inspect and remove it¶
curl --fail-with-body -i http://127.0.0.1:8080/api/http-functions/v1/definitions/greeting
Copy the quoted ETag into the next request, replacing REVISION and keeping the
quotes inside the header value:
curl --fail-with-body -i -X DELETE http://127.0.0.1:8080/api/http-functions/v1/definitions/greeting -H 'If-Match: "REVISION"'
curl -i http://127.0.0.1:8080/functions/v1/greeting
The final request returns 404. Stop terminal 1 with Ctrl-C. You have learned the registration, invocation, and conditional deletion cycle. Next, learn to update handlers safely or consult the request and response contract.