Atlas / MCP servers / tangle-network / @tangle-network/agent-app

@tangle-network/agent-appBLOCK

mcp/tangle-network/agent-app

A feature-full starting point for production agent applications on Tangle.

Verdict
BLOCK
Grade
F
Trust score
36 /100
Exposed tools
74 40r · 30w · 4d
Transport
stdio · streamable-http
License
MIT
Stars
0
01

Overview

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

[](https://www.npmjs.com/package/@tangle-network/agent-app) [](https://www.npmjs.com/package/@tangle-network/agent-app#provenance) [](./LICENSE)

The application-shell layer for building agent products on the Tangle stack.

The substrate packages — @tangle-network/agent-runtime, agent-eval, agent-integrations, tcloud, sandbox — are the engine. This package is the shell: the chat tool-loop, the structured agent→app side channel, the integration-hub client, per-workspace billing, field crypto, and the web boundary utilities that every agent app otherwise rewrites by hand. You supply your domain through typed seams; the package supplies the mechanism and imports none of your code.

Who it's for: engineers building an agent product on the Tangle sandbox — a chat app, a copilot, an autonomous worker — who want the shell (chat routes, streaming, durability, approvals, billing, the tool side channel) as composable pieces instead of a per-app rewrite. It is not an agent framework or a model SDK: the reasoning lives in the sandbox agent; agent-app is everything around it — the turn plumbing, durability, and money.

Highlights

  • Structured tool side channel — submit_proposal (approval-gated), schedule_followup, render_ui, add_citation, exposed as validated tool calls over three surfaces (HTTP route, per-turn MCP server, agent-runtime executor). No fenced-text parsing.
  • Bounded tool loop — runAppToolLoop / streamAppToolLoop: stream a turn → collect tool calls → dispatch → fold results back → re-run, capped. These are 1:1 aliases of runToolLoop / streamToolLoop from @tangle-network/agent-runtime/tool-loop (the engine owns the loop; this package adds no logic on that path). Substrate-free be
Read from source at commit 9fe6534505b1OBSERVED · 2026-10-12
Advertisement
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 fixture-vendored-tarball --env JOURNEY_TEST_PASSWORD=${JOURNEY_TEST_PASSWORD} --env LIVE_EDGE_502_MAX_TOKENS=${LIVE_EDGE_502_MAX_TOKENS} --env SANDBOX_API_KEY=${SANDBOX_API_KEY} --env TANGLE_API_KEY=${TANGLE_API_KEY} -- npx -y fixture-vendored-tarball
claude-desktop
{
  "mcpServers": {
    "fixture-vendored-tarball": {
      "command": "npx",
      "args": [
        "-y",
        "fixture-vendored-tarball"
      ],
      "env": {
        "JOURNEY_TEST_PASSWORD": "${JOURNEY_TEST_PASSWORD}",
        "LIVE_EDGE_502_MAX_TOKENS": "${LIVE_EDGE_502_MAX_TOKENS}",
        "SANDBOX_API_KEY": "${SANDBOX_API_KEY}",
        "TANGLE_API_KEY": "${TANGLE_API_KEY}"
      }
    }
  }
}
03

Exposed tools (74)

40 read · 30 write · 4 destructive. Blast radius: 4 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
E-Filingreadpaid
GeneralreadGeneral work
ResearchreadFinds and cites sources
ReviewerreadReview the work
WriterreadDrafts posts
add_captionwriteAdd one caption clip. Omit start_seconds and duration_seconds to auto-place roughly 3 seconds of caption near the playhead without overlapping existing captions. language is a BCP-47 tag like
add_captionswriteAdd many caption clips in one call — use this for transcription output instead of repeated add_caption. Each item needs text, start_seconds, duration_seconds. One shared language applies to every caption. Max ${MAX_CAPTION_BATCH} per call.
add_imagewritePlace an image element on a page. src must be an http(s) URL or a rooted /api/ path — never a data: blob. The element id is minted server-side and returned.
add_pagewriteAdd a new blank page to the document. Returns the new page\
add_shapewritePlace a geometric shape on a page. kind must be
add_textwritePlace a text element on a page. The element id is minted server-side and returned. x/y are the top-left in page coordinates (px). width sets the wrap column; height derives from content at render time.
add_videowritePlace a video element on a page. Video renders and exports as its poster frame — motion belongs to the sequences surface. src must be an http(s) URL or /api/ path.
apply_datawriteFill template slots with data. bindings is a {slot_name: value} map. Text slots accept any string; image/video slots accept http(s) URLs or /api/ paths; unknown slot names throw. Partial application is allowed.
bind_slotreadBind or unbind a template slot name to an element. Slot names are unique document-wide. Text elements accept string data; image/video elements accept src URLs. Pass null for slot to unbind.
booking-guidereadAnswer booking questions from the declared reference files.
cleardestructiveClear the conversation
compactreadSummarize and compact the context
create_exportwriteQueue a document export. For
create_trackwriteAdd a track to the sequence. kind is one of: ${SEQUENCE_TRACK_KINDS.join(
delete_clipdestructiveRemove a clip from the timeline permanently. Prefer set_clip_disabled to audition a cut without losing the clip.
delete_elementdestructivePermanently delete an element (and all its children if it is a group) from a page.
delete_pagedestructiveDelete a page. Fails if the document has only one page.
describe_pagereadRead one page in detail: name, dimensions, background, bleed, guides, and every element with geometry, attributes, and slot bindings. Use this when you need attribute values (fill, font, src) the compact get_scene_state summary omits.
duplicate_pagereadDuplicate an existing page including all its elements. Element ids are re-minted server-side to avoid conflicts. Returns the new page\
extend_sequencewriteSet the sequence\
filesystemwriteRead and write local files.
flag_exceptionreadFlag problems with the current work product (missing documents, inconsistent sources, ...). An unresolved blocking exception parks the work product until it is resolved; re-emit the same id with resolved:true to release it. Address by scopeKey.
get_clipreadRead one clip by id, including its position (seconds + timecode), source in/out points, text, and media/provider status.
get_frame_at_timereadWhat is on screen and audible at one moment. seconds is sequence time (e.g. 12.5). Returns the active clips, visible caption text, and a one-line human-readable summary.
get_scene_statereadRead the full scene document: title, settings, all pages with dimensions and background, and every element with its axis-aligned bounding box (so you can reason about layout and overlap without rendering). Call this before editing to get real page and element ids.
get_timeline_statereadRead the full timeline: sequence settings (fps, duration), playhead, all tracks, and all clips with positions in seconds and m:ss.ff timecodes plus media URLs and provider status. Call this before editing to get real clip and track ids.
graph.editwriteEdit the system map.
group_elementsreadGroup 2+ sibling elements into a new group. Elements must share the same owner (page root or the same parent group). The group\
humanizerreadRewrite AI text.\nKeep the meaning.
insecurereadAn HTTP-only server.
instantiate_templatereadClone this document\
knowledge_readreadRead a published page by its exact citation id.
knowledge_searchreadSearch published consultation knowledge.
list_decisionsreadList recent agent decisions recorded against this document. Useful to audit what the agent has already done this session.
list_invoicesreadList invoices
modelreadSwitch the model for this session
move_clipwriteMove a clip so it starts at start_seconds, optionally onto another track via track_id. Duration and source in/out points are unchanged.
move_elementwriteMove an element to a new (x, y) position in page coordinates. Sugar for set_attrs({x, y}).
no_pathreadd
poster-copyreadWrites launch-poster captions in the house tone
pr-reviewerreadReviews PRs
profile.readreadRead the active agent profile text and revision. Saved text applies on the next message.
profile.rememberwriteSave one durable fact or standing instruction an owner or manager tells you to keep
profile.updatewriteSave a requested owner or manager text change with the revision from profile.read. Applies on the next message.
property-datareadRead property availability and reservations.
queue_exportreadQueue an export of the sequence. format is one of: ${SEQUENCE_EXPORT_FORMATS.join(
readreadRead.
record_invoicereadRecord an invoice
renamewriteRename this session
reorder_elementreadChange an element\
researchreadResearch a question from primary sources.
resize_elementreadResize an element by setting its width and height. Sugar for set_attrs({width, height}). Not valid on lines (use set_attrs with points instead).
rooms.readyreadCount ready rooms.
rotate_elementwriteSet an element\
savewriteSave a finding.
searchreadSearch docs
set_attrswriteSet one or more attributes on an existing element. Only provide the attrs you want to change — omitted attributes are unchanged. Attempting to change kind or id is an error. For convenience transforms (x/y/width/height/rotation) prefer move_element, resize_element, or rotate_element.
set_clip_disabledwriteDisable (true) or re-enable (false) a clip without deleting it. Disabled clips do not render or sound.
set_clip_textwriteReplace a caption clip\
set_configwriteUpdate workspace settings.
set_page_guideswriteSet ruler guides on a page. Replaces ALL existing guides for that axis — pass the full updated arrays.
set_page_propswriteUpdate a page\
split_clipreadCut a clip into two at at_seconds (sequence time, strictly inside the clip). The original clip id keeps the left half; the returned clip is the new right half with its source in-point re-anchored at the cut.
staff.task.createwriteCreate a task.
submit_proposalwritex
submit_work_productwriteSubmit the finished work product for professional review — the terminal call after evidence and exceptions are recorded. Refused while a blocking exception is unresolved, or when a material target lacks evidence. Include your own quality checks in
ungroup_elementreadDissolve a group, promoting its children to the group\
unpinned-skillwriteA skill without a pinned commit.
xreadx
04

Trust audit

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

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

What the source does

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

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
src/sandbox/binary-read.ts:20
exec(
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
src/sandbox/index.ts:1051
/\b(408|409|425|429|500|502|503|504)\b|rate.?limit|too many requests|\bfetch failed\b|network error|connection reset|socket hang up|timed? out|service unavailable|bad gateway|gateway timeout|internal
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
src/store/index.ts:60
exec(command: SqliteTransactionCommand): unknown | Promise<unknown>
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHFilesystem / path · fs.credential_store · CWE-22, CWE-59
src/workspace-export/secrets.ts:235
/(^|\/)\.git-credentials$/,
Why it matters. touches a credential store
HIGHFilesystem / path · fs.credential_store · CWE-22, CWE-59
src/workspace-export/secrets.ts:236
/(^|\/)\.netrc$/,
Why it matters. touches a credential store
HIGHHard-coded secrets · secret.db_uri · CWE-798, CWE-321
customer-db-gateway/src/server.ts:3
//   DATABASE_URL=postgres://tangle_agent:...@db:5432/app \
MEDIUMInventory / provenance · inv.binary · CWE-1104
artifacts/api-access/api-access-workflow.webm
api-access-workflow.webm
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
artifacts/api-access/dependency-workflow.webm
dependency-workflow.webm
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
artifacts/skill-menu-height-20261002/after-1280-agent-dark.webm
after-1280-agent-dark.webm
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
artifacts/skill-menu-height-20261002/after-1280-agent-light.webm
after-1280-agent-light.webm
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
src/copy-quality/index.ts:87
'delve', 'tapestry', 'testament to', 'realm', 'embark', 'beacon', 'multifaceted',
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
artifacts/skill-selection-20261002/check.mjs:11
await page.goto('http://127.0.0.1:6011/iframe.html?id=chatcontrols-chatcomposerslash--skills-with-file-mentions&viewMode=story', { waitUntil: 'networkidle' })
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
create-agent-app/proof/workspace-browser.mjs:25
const origin = `http://127.0.0.1:${port}`
MEDIUMObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
src/email/mark.generated.ts:4
'iVBORw0KGgoAAAANSUhEUgAAAFQAAABUCAYAAAAcaxDBAAAQAElEQVR4nOxcDZBV1X3//8+9971dVvkwEhR1GuvEatIY09hmOklTCU2bMQYnH3ZMTAmRZRdpqIAYgV3Iy35CgAUEBBGcBNskliSmTZqPjtox6dhJaGY61NFGpfEDSBRBgbjsvnfv+fd/P86959x73+5
MEDIUMObfuscation / stealth · obf.homoglyph · CWE-506, CWE-94
src/signoff/surface-ladder-cli.ts:26
'  --tolerance <L>          minimum |ΔL| (OKLCH L x100) for a card or field (default 3)',
MEDIUMObfuscation / stealth · obf.homoglyph · CWE-506, CWE-94
src/signoff/surface-ladder.ts:141
reason: `${box.kind} is ΔL ${signed(delta)} against ${box.parentLabel} (needs |ΔL| ≥ ${minDeltaL})` })
MEDIUMObfuscation / stealth · obf.homoglyph · CWE-506, CWE-94
src/signoff/surface-ladder.ts:423
'  route | width | theme | cards flat/total (min |ΔL|) | fields flat/total (min |ΔL|) | weak borders | long copy/blocks (max words) | median card words',
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
playground/src/routes/ShellRoute.tsx:109
base('emoji', '🚀 Launch 🚀 team 👩🏽💻', { updatedAt: null }),
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
customer-db-gateway/README.md:38
-e DATABASE_URL='postgres://tangle_agent:...@db:5432/app' \
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/assistant/useAssistantChat.test.tsx:429
const SECRET = "sk-tan-live-THE-SECRET-VALUE";
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/object-store/index.test.ts:104
const SECRET = 'test-signing-secret-0123456789'
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/runtime/protected-model.test.ts:17
port: createRouterProtectedModelPort({ apiKey: 'parent-secret-must-stay-server-side', maxCostUsd: 0.1, signal: options.signal, onSettlement: options.onSettlement }),
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/sandbox/index.test.ts:417
apiKey: 'sk-sandbox-provisioned',
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
src/sandbox/index.test.ts:428
apiKey: 'sk-sandbox-provisioned',
MEDIUMHard-coded secrets · secret.stripe · CWE-798, CWE-321
src/interactions/sidecar-session.test.ts:95
const fetchImpl = vi.fn().mockRejectedValue(new Error('failed with Bearer sk_live_abcdefgh12345678'))

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha 9fe6534505b1full audit observations/trust-audit/mcp-server/tangle-network__agent-app.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-129fe6534505b1BLOCKF36first audit
06

Questions

What is the @tangle-network/agent-app MCP server?

A feature-full starting point for production agent applications on Tangle.

What tools does @tangle-network/agent-app expose?

74 in total: 40 read-only, 30 that write, and 4 that can delete or overwrite (clear, delete_clip, delete_element, delete_page). Every one is listed on this page with its risk.

Is @tangle-network/agent-app safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (36/100) and found 6 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: 4 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does @tangle-network/agent-app need?

It reads JOURNEY_TEST_PASSWORD, LIVE_EDGE_502_MAX_TOKENS, SANDBOX_API_KEY, TANGLE_API_KEY, TANGLE_OIDC_CLIENT_SECRET, TANGLE_ROUTER_API_KEY and TANGLE_SANDBOX_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 @tangle-network/agent-app run?

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

How current is this page?

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

Advertisement