Network access with fetch¶
Recipes for enabling outbound HTTP, restricting which URLs are reachable, and injecting authentication headers server-side.
Enable fetch with a domain allowlist¶
fetch() is available in JS only when the server is started with a
--policies-json configuration that includes a fetch section. Without it,
any fetch() call throws an error.
Create a policy that allows only specific domains (fetch.rego):
package mcp.fetch
default allow = false
allow if {
input.method == "GET"
input.url_parsed.host == "api.example.com"
}
Create the policies configuration (policies.json):
{
"fetch": {
"policies": [
{ "url": "file:///path/to/fetch.rego" }
]
}
}
Start the server:
mcp-v8 --http-port=8080 --policies-json=/path/to/policies.json
Any fetch() call where the policy returns false raises a JS error:
fetch denied by policy: GET https://other.example.com/ is not allowed.
For the full policy input shape, see the Reference page.
Enable fetch with no per-request restrictions¶
To allow every outbound request (useful in trusted environments), configure a
fetch section with an empty policies list:
{
"fetch": {
"policies": []
}
}
An empty chain always allows. You can also pass inline JSON directly to the flag:
mcp-v8 --http-port=8080 --policies-json='{"fetch":{"policies":[]}}'
Inject a static auth header¶
Use --fetch-header to attach a fixed header value to every request targeting
a specific host. The header is injected by the server before the policy
evaluates, so JS code never sees or supplies the credential.
mcp-v8 --http-port=8080 \
--policies-json=/path/to/policies.json \
--fetch-header "host=api.example.com,header=Authorization,value=Bearer my-token"
Restrict injection to specific HTTP methods with methods= (semicolon-separated):
--fetch-header "host=api.example.com,methods=GET;POST,header=X-Api-Key,value=abc123"
If JS code already sets the same header, the JS-provided value takes precedence and the injected value is skipped.
The flag is repeatable; each --fetch-header adds one rule. Rules are
evaluated in declaration order and the first matching rule wins per header.
Inject OAuth client-credentials tokens¶
For services that require a bearer token from an OAuth token endpoint, use the
OAuth form of --fetch-header:
mcp-v8 --http-port=8080 \
--policies-json=/path/to/policies.json \
--fetch-header "host=api.example.com,header=Authorization,token_url=https://auth.example.com/token,client_id=my-client,client_secret=my-secret,scope=read:all"
The server acquires a token via the client_credentials grant, caches it in
memory, and refreshes it automatically before expiry. The default refresh
buffer is 30 seconds (token is considered expired 30 s before its stated
expiry). Override with refresh_buffer_secs=:
--fetch-header "host=api.example.com,header=Authorization,token_url=https://auth.example.com/token,client_id=my-client,client_secret=my-secret,scope=read:all,refresh_buffer_secs=60"
The injected header value has the form <token_type> <access_token>, where
token_type comes from the token endpoint response (defaults to Bearer).
If the token endpoint also returns a refresh_token, the server uses the
refresh-token grant on subsequent refreshes and falls back to
client_credentials if the refresh fails.
You cannot mix value= and OAuth keys (token_url, client_id,
client_secret) in the same --fetch-header entry.
Use a --fetch-header-config JSON file¶
For many rules or for secrets that should not appear on the command line, put rules in a JSON file:
mcp-v8 --http-port=8080 \
--policies-json=/path/to/policies.json \
--fetch-header-config=/path/to/header-rules.json
The file must be a JSON array of rule objects. Each rule has:
host(string, required) — exact hostname or*.suffixwildcard.methods(array of strings, optional) — restrict to these HTTP methods; omit or use[]to match all methods.- Exactly one of:
headers— object mapping header names to static values.auth— OAuth client-credentials configuration object.
Static example:
[
{
"host": "api.example.com",
"methods": ["GET", "POST"],
"headers": {
"Authorization": "Bearer my-token",
"X-Tenant-Id": "acme"
}
}
]
OAuth example:
[
{
"host": "api.example.com",
"auth": {
"type": "oauth_client_credentials",
"header": "Authorization",
"token_url": "https://auth.example.com/token",
"client_id": "my-client",
"client_secret": "my-secret",
"scope": "read:all",
"refresh_buffer_secs": 30
}
}
]
headers and auth are mutually exclusive per rule. The only supported
auth.type value is "oauth_client_credentials". Unknown JSON fields cause a
startup error.
--fetch-header (CLI) and --fetch-header-config (file) can be used
together; CLI rules are appended first.
Use a wildcard host pattern¶
Both --fetch-header and the JSON config support a *. prefix to match a
hostname and all its subdomains:
--fetch-header "host=*.github.com,header=Authorization,value=Bearer ghp_token"
*.github.com matches api.github.com, raw.github.com, and github.com
itself. Matching is case-insensitive.