Connect an agent
nox has an MCP server, so your agent can write scripts for you, test them, read the logs, fix what fails and schedule them, all from a chat. You approve the connection once, in nox, and can disconnect it whenever you like.
Your MCP server address
https://pernox.dev/mcp
Add nox to your agent
- In your agent's settings, add a remote MCP server (sometimes called a connector), name it nox, and paste the address above. It uses the HTTP transport.
- Leave any OAuth client ID and secret fields empty; nox registers the agent itself.
- Connect. nox opens, asks you to log in, and shows what the agent will be able to do. Choose Allow.
- Turn nox on in your agent's tools, then ask for what you need.
An agent that runs in the cloud connects from its provider's servers, so this nox has to be reachable on the public internet over HTTPS. An agent running on your own machine can connect to a local nox too.
Things to ask
- "Write a script that fetches the Bank of England base rate every weekday at 07:00 London time and prints it. Test it first."
- "My FX rates script failed last night. Look at the run and fix it."
- "Pull yesterday's closing prices for these tickers and post a summary to my Google Sheet. I'll give you the API key."
- "Which of my scripts haven't succeeded this week?"
- "Move all my morning scripts to 06:30."
Your agent creates scripts paused, runs them to check the output, and only turns a schedule on when you say so.
Tools
What the nox MCP server lets your agent do. Most clients ask before each action.
-
list_scriptsread-onlyList the user's scripts with their schedules, next run times and the status of their last run.
-
get_scriptread-onlyGet a script's code, packages and settings, the names of its keys (never their values), its next runs and its most recent runs.
script_idinteger, required- The script's id, from list_scripts or create_script.
-
create_scriptCreate a Python script. It's created paused unless enabled is true; test it with run_script before turning the schedule on.
namestring, required- A short name the user will recognise, e.g. "Gilt curve to sheet".
codestring, required- The Python source. Print results to stdout; read secrets from os.environ.
requirementsstring- Packages to install, one per line in requirements.txt format, e.g. "requests\npandas==2.2.3".
schedulestring- Five-field cron expression in the script's timezone. Defaults to "0 7 * * 1-5" (07:00 on weekdays).
timezonestring- IANA timezone for the schedule and the script's TZ, e.g. "Europe/London". Defaults to UTC.
timeout_secondsinteger- Kill the run after this many seconds (1-3600). Defaults to 300.
enabledboolean- Run on the schedule. Defaults to false; only set true once the user agrees.
-
update_scriptChange any of a script's code, packages, name, schedule, timezone, timeout or whether it runs on schedule. Only the fields given are changed.
script_idinteger, required- The script's id, from list_scripts or create_script.
namestring- New name.
codestring- New Python source, replacing the old.
requirementsstring- New packages, replacing the old list. An empty string removes them all.
schedulestring- New five-field cron expression.
timezonestring- New IANA timezone.
timeout_secondsinteger- New timeout in seconds (1-3600).
enabledboolean- true to run on schedule, false to pause.
-
run_scriptRun a script immediately and wait for it to finish, returning its status, exit code and logs. Waits up to wait_seconds (default 30, max 50); if it's still running, call get_run with the run_id. If the script is already running, waits on that run instead of starting another.
script_idinteger, required- The script's id, from list_scripts or create_script.
wait_secondsinteger- How long to wait for the run to finish (0-50). 0 returns straight away.
-
get_runread-onlyGet a run's status, exit code, timings and logs, optionally waiting for it to finish.
run_idinteger, required- The run's id, from run_script or list_runs.
wait_secondsinteger- Wait up to this long for the run to finish (0-50). Defaults to 0.
-
list_runsread-onlyList a script's recent runs, newest first, with status, trigger and duration. Use get_run for a run's logs.
script_idinteger, required- The script's id, from list_scripts or create_script.
limitinteger- How many runs to return (1-50). Defaults to 10.
-
set_keySet an environment variable for a script, such as an API key or database URL. Values can't be read back. Only use values the user has given you for this purpose.
script_idinteger, required- The script's id, from list_scripts or create_script.
namestring, required- Variable name, e.g. DB_PASSWORD. Letters, numbers and underscores.
valuestring, required- The value.
-
delete_keydestructiveRemove one of a script's environment variables.
script_idinteger, required- The script's id, from list_scripts or create_script.
namestring, required- The variable to remove.
-
delete_scriptdestructivePermanently delete a script with its keys and run history. Confirm with the user first.
script_idinteger, required- The script's id, from list_scripts or create_script.
How scripts run
- Language
- Python, one file. Packages go in requirements.txt format, one per line.
- Output
- Anything printed to stdout or stderr is the run's log, up to 1 MB.
- Success
- Exit code 0 succeeds. A non-zero exit or an uncaught exception fails the run.
- Keys
- Environment variables, read with
os.environ["NAME"]. Values are never shown again, to you or to your agent. - Time
TZis set to the script's timezone, sodatetime.now()is local time.- Schedules
- Five-field cron, e.g.
0 7 * * 1-5is 07:00 on weekdays. At most once every 1m0s. - Timeout
- Up to 3600 seconds, then the run is stopped.
- Files
- The working directory is temporary and wiped after each run. Send results somewhere: an API, a database, a sheet.
- Overlaps
- A script never runs twice at once. A slot that comes up while it's still running is skipped.