Atlas / MCP servers / sema-lisp / Sema

SemaBLOCK

mcp/sema-lisp/sema-1

A Lisp with first-class LLM primitives, implemented in Rust

Verdict
BLOCK
Grade
F
Trust score
32 /100
Exposed tools
17 9r · 7w · 1d
Transport
stdio · streamable-http
License
MIT
Stars
50
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

A Lisp where LLM agents are language primitives, not an SDK — compiled to a fast bytecode VM, shipped as a single binary.

[](https://sema.run) [](https://sema-lang.com/docs/) [](https://github.com/sema-lisp/sema/releases/latest) [](https://codecov.io/gh/sema-lisp/sema) [](LICENSE)

**Docs** · **Playground** · **For Agents** · **Examples** · **Issues**

Stop rewriting the agent loop. Every LLM script grows the same scaffolding — retries, caching, cost caps, rate limits, tool dispatch, conversation state. Sema makes that scaffolding the runtime: your script stays the size of its idea, ships as a single binary, and your coding agent already speaks the language.

Sema is a Scheme-like Lisp where prompts are s-expressions, conversations are persistent data structures, and LLM calls are just another form of evaluation — with Clojure-style keywords (:foo), map literals ({:key val}), and vector literals ([1 2 3]).

What It Looks Like

A coding agent with file tools, safety checks, and budget tracking — in ~40 lines:

;; Define tools the LLM can call
(deftool read-file
"Read a file's contents"
{:path {:type :string :description "File path"}}
(lambda (path)
(if (file/exists? path) (file/read path) "File not found")))

(deftool edit-file
"Replace text in 
Read from source at commit 9f8c1a173cd8OBSERVED · 2026-10-08
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add sema-website --env ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} --env OPENAI_API_KEY=${OPENAI_API_KEY} -- npx -y sema-website
claude-desktop
{
  "mcpServers": {
    "sema-website": {
      "command": "npx",
      "args": [
        "-y",
        "sema-website"
      ],
      "env": {
        "ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}",
        "OPENAI_API_KEY": "${OPENAI_API_KEY}"
      }
    }
  }
}
03

Exposed tools (17)

9 read · 7 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
continue_debuggingreadContinue the paused Sema debugger and wait for the next breakpoint, finish, or error.
find_examplesreadFind bundled Sema examples by filename, category, or identifier. Returns identifiers accepted by load_example.
format_editorwriteFormat and replace the current Sema source in the editor. This does not run the code.
get_debug_statereadRead debugger status, active line, breakpoints, locals, and stack frames.
list_filesreadList the immediate children of one virtual filesystem directory. The listing is non-recursive.
load_examplereadReplace the editor with one bundled Sema example selected by identifier or filename. This does not run the code.
read_editorreadRead Sema source from the playground editor. Use this before editing or running unfamiliar code.
read_filereadRead a character range from a UTF-8 text file in the playground virtual filesystem.
read_outputreadRead the current playground output, including values, printed lines, errors, and timing.
run_editorwriteRun the current Sema source, using the worker runtime when available, and wait for evaluation to finish.
set_breakpointswriteReplace all debugger breakpoints with one-based lines, snapping requests to executable source lines.
start_debuggingwriteStart debugging the current Sema source and wait for a pause, finish, or error.
step_debuggerreadStep the paused Sema debugger into, over, or out, then wait for its next stable state.
stop_debuggingwriteStop the active Sema debugger and return the playground to its idle state.
stop_runwriteCancel the active worker-backed Sema evaluation when one is running.
write_editorwriteReplace the entire playground editor with Sema source. This does not run the code.
write_filedestructiveCreate or overwrite a UTF-8 virtual file, creating parent directories as needed. Content is limited to 1 MiB.
04

Trust audit

BLOCKgrade F · trust 32/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)WARN
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (8 observation(s))
Network
declared (14 observation(s))
Shell
declared (5 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

CRITICALHard-coded secrets · secret.github · CWE-798, CWE-321
crates/sema-stdlib/src/secret.rs:412
let gh = "ghp_0000000000000000000000000000000000000000";
CRITICALHard-coded secrets · secret.private_key · CWE-798, CWE-321
crates/sema-stdlib/src/secret.rs:416
let pk = "-----BEGIN RSA PRIVATE KEY-----";
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
crates/sema-core/src/args.rs:156
self.map_err(|e| SemaError::eval(format!("{what}: {e}")))
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
crates/sema-core/src/context.rs:228
Err(SemaError::eval(format!(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
crates/sema-core/src/context.rs:342
return Err(SemaError::eval(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
crates/sema-core/src/context.rs:536
.map_err(|error| SemaError::eval(format!("module load scope: {error}")))?;
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
crates/sema-core/src/context.rs:605
Err(SemaError::eval(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHNetwork egress · net.metadata_ip · CWE-200, CWE-319
crates/sema-llm/src/builtins/tests.rs:493
url_host("http://169.254.169.254/latest").as_deref(),
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
HIGHNetwork egress · net.metadata_ip · CWE-200, CWE-319
crates/sema-llm/src/builtins/tests.rs:494
Some("169.254.169.254")
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
HIGHNetwork egress · net.metadata_ip · CWE-200, CWE-319
crates/sema-llm/src/builtins/tests.rs:508
"169.254.169.254", // cloud metadata
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
HIGHNetwork egress · net.metadata_ip · CWE-200, CWE-319
crates/sema-llm/src/builtins/tests.rs:536
"0xA9FEA9FE", // 169.254.169.254 cloud metadata
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
crates/sema-llm/src/builtins/tests.rs:493
url_host("http://169.254.169.254/latest").as_deref(),
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
crates/sema-llm/src/builtins/tests.rs:561
Value::string("http://169.254.169.254/"),
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
crates/sema-mcp/src/builtins.rs:1325
"http://127.0.0.1:1/callback".to_string()
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
crates/sema-mcp/src/builtins.rs:1354
"http://127.0.0.1:1/callback".to_string()
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
crates/sema-mcp/src/builtins.rs:2862
assert!(driver.redirect_uri().starts_with("http://127.0.0.1"));
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
crates/sema-notebook/src/ui/vendor/sema-ui.js:6675
zwnj: "",
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
crates/sema-notebook/src/ui/vendor/sema-ui.js:6676
zwj: "",
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
crates/sema-notebook/src/ui/vendor/sema-ui.js:10688
`).map((t) => _`<span class="cl">${an(t === "" ? "" : t)}</span>`);
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
crates/sema-notebook/src/ui/vendor/sema-ui.js:11019
(r, o) => _`<div class="ln ${o + 1 === t ? "cur" : ""}" part="line">${an(r === "" ? "" : r)}</div>`
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
crates/sema-stdlib/src/secret.rs:426
let hit = "api_key = 'a8Fk3Lm9Zq2Wx7Bv1Nc4Pd6'";
MEDIUMPrompt injection · prompt.hidden_style · CWE-94, CWE-1427
docs/plans/archive/2026-02-23-github-linked-packages.md:1224
<p style="font-size:0.78rem; color:var(--text);">
MEDIUMPrompt injection · prompt.hidden_style · CWE-94, CWE-1427
docs/plans/archive/2026-02-23-github-linked-packages.md:1228
<a href="/auth/github?mode=connect&return_to=/account" class="btn btn-secondary" style="font-size:0.7rem; padding:0.4rem 0.8rem;">Reconnect</a>
MEDIUMPrompt injection · prompt.hidden_style · CWE-94, CWE-1427
docs/plans/archive/2026-02-23-github-linked-packages.md:1231
<p style="font-size:0.78rem; color:var(--text-dim); margin-bottom:0.75rem;">
MEDIUMPrompt injection · prompt.hidden_style · CWE-94, CWE-1427
docs/plans/archive/2026-02-23-github-linked-packages.md:1234
<a href="/auth/github?mode=connect&return_to=/account" class="btn btn-primary" style="font-size:0.7rem; padding:0.45rem 0.8rem;">Connect GitHub</a>

Gates applied: critical_finding, no_behavioural_pass.

Audited 2026-10-08 · audit v0.4.1 · source sha 9f8c1a173cd8full audit observations/trust-audit/mcp-server/sema-lisp__sema-1.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-089f8c1a173cd8BLOCKF32first audit
06

Questions

What is the Sema MCP server?

A Lisp with first-class LLM primitives, implemented in Rust

What tools does Sema expose?

17 in total: 9 read-only, 7 that write, and 1 that can delete or overwrite (write_file). Every one is listed on this page with its risk.

Is Sema safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (32/100) and found 11 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does Sema need?

It reads ANTHROPIC_API_KEY and OPENAI_API_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does Sema run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as sema-website.

How current is this page?

The grade is for one exact copy of the source (9f8c1a173cd8), read on 2026-10-08. The repository is watched and re-audited when it changes.

Advertisement