Deno-powered JavaScript Runtime MCP server and CLI for agents
SubJS is a Deno-powered MCP server and CLI program to run persistent JavaScript sessions.
As an MCP server, SubJS lets your agent create and run JavaScript session with full access to library registries such as NPM and JSR on-demand.
As a CLI, SubJS lets you execute JavaScript like this:
$ subjs session new my-session
$ subjs run -s my-session 'import * as z from "npm:zod"'
$ subjs run -s my-session 'const schema = z.object({ age: z.number(), cool: z.boolean() })'
$ subjs run -s my-session 'schema.parse({ a: 20, cool: true })'
[object Object]
$ subjs run -s my-session 'const bad = "bad"; schema.parse({ a: bad, cool: false })'
Error: ZodError: [
{
"expected": "number",
"code": "invalid_type",
"path": [
"age"
],
"message": "Invalid input: expected number, received string"
}
]
at <anonymous>:1:29
$ subjs session terminate my-sessionLLMs are great at writing code, especially JavaScript. Not only do they know JavaScript very well but they also have a huge amount of books, repositories, documentation, specifications, etc. compressed in them to know how to use the JavaScript ecosystem very well.
By giving agents a tool to run JavaScript as they see fit in Deno (a Node.js-compatible runtime), they are now capable of transforming all that knowledge into actions.
For cases where the LLM on its own is not enough, we can fill the gaps by using agent skills. In this way, multiple MCP servers can be replaced by SubJS and some markdown files.
You can install SubJS and its requirements through npm or by executing a shell script:
deno i -A -g npm:@emi0x7d1/subjs
# or...
npm i -g @emi0x7d1/subjs
# or...
bun i -g @emi0x7d1/subjs
# or...
# Install under ~/.local/bin/
curl -fsSL https://subjs.emi0x7d1.dev/install.sh | sh
# or...
# Install under /usr/local/bin/ (runs with sudo)
curl -fsSL https://subjs.emi0x7d1.dev/install.sh | sudo shThen setup the MCP server with your AI client. For example:
OpenCode
Add to ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"subjs": {
"type": "local",
"command": [
"subjs",
"mcp"
],
"enabled": true
}
}
}Claude Code
Add to ~/.claude.json:
{
"mcpServers": {
"subjs": {
"command": "subjs",
"args": ["mcp"]
}
}
}Codex
Add to ~/.codex/config.toml:
[mcp_servers.subjs]
command = "subjs"
args = ["mcp"]Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"subjs": {
"command": "subjs",
"args": ["mcp"]
}
}
}SubJS is best utilized when paired with agent skills. Skills let your agent best decide when to use SubJS. You can also replace many MCP servers with this combo.
Example
You may use SubJS as a universal MCP server for databases with a skill like the following:
---
name: universal-database-driver
description: Connects to any database using a JS runtime
---
When the user or a task requires information from the database, connect to it
using subjs.
If the database is:
- Postgres, use `npm:postgres`.
- Sqlite, use `npm:better-sqlite3`
- Mysql, use `npm:mysql2`
- ...
The connection string is in .env.localWith this minimal skill, your agent is now capable of connecting to the specified databases. You may repeat this pattern for any capability you want your agent to have.
-
Replace your MCP servers with official SDKs and JS libraries.
MCP might be limiting your and your agent's possibilities. Let your agent use its full coding capabilities.
Instead using an MCP server to connect to services such as Supabase, a Postgres DB, Playwright, Cloudflare, etc, you can ask SubJS to do it and it will figure out how to do it by leveraging the JS ecosystem.
-
Give your agent access to the massive JS ecosystem.
The JS ecosystem is full of libraries for every algorithm, data structure, file format, protocol, etc. Your agent can take advantage of this to gain capabilities on demand to work with almost anything.
Use-case examples
All of these prompts do not require external dependencies for your agent to perform these tasks. It will fetch the required dependencies on-demand.
-
Work with arbitrary file formats.
Prompt: Use subjs to convert @cover.jpg to png, jpg, webp, avif and keep the smallest one.
Prompt: Use subjs to read the excel file in https://example.com/dl/archive.tar.xz and save it as a table in archive.md
-
Experiment quickly
Prompt: Use subjs to generate an index.html page with a summary of user with email user10@example.com. Fetch the data from postgres. My creds are in .env.local
-
Talk to anything
Prompt: Use subjs to send { message: "status" } to /tmp/service.sock encoded as msgpack
Prompt: Use subjs to read the protobuf stream dump in /tmp/proto.dump and print a human readable summary
-
-
For JS developers:
Having a portable JS runtime makes it easier for your agent to complete tasks that require interaction with the same things the software you are developing interacts with.
You can SubJS to use the same libraries you are using in your project or you can use JS libraries to help you augment your development.
Some examples for using SubJS in your JS project:
-
Make your AI run custom static analysis in your project
Prompt: Use subjs with a typescript parser that reads the files src/ and gets the exported types that are not documented and have inferred types. Save the results in a file.
-
Ask SubJS to reuse a library
Prompt: Use subjs with TRPC to call
user.get({ id: 13 })on http://localhost:3000/trpc
-
I've decided to take the time to polish the software in hopes of getting attention on a personal issue.
I would appreciate it if you took the time to read:
A few weeks ago my girlfriend started having serious health issues and we are struggling to pay the medical bills. I am making less than 1000 USD per month as a contractor for an American company and we have to pay ~1500 USD in a few days so you might imagine how desperate we are feeling right now as I am our only source of income
I am a 24 year old self-taught programmer from Mexico who has been programming since the age of 10 and I am looking for a job as a software engineer. I went to college two years but had to dropout to work and haven't been able to get a stable foothold since.
Please, see my resume here if you are interested
I am willing to work as a contractor or normal job.
The nature of the project might make some people think I quickly vibecoded this project specifically for this section so here is some evidence of me not being a vibecoder:
- 17-year-old me developing a game in a minimal vim install, no lsp, no autocomplete, no syntax highlighting (2019)
- Spanish programming language I wrote when I was 17
- Wrote about advanced Rust
- Released well-received Rust tool
I know they're not impressive but their purpose is to show a bit of credibility in an internet written by LLMs.