HexForge Gateway
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| HEXFORGE_URL | No | The base URL of the HexForge Gateway (must already be running). Defaults to http://localhost:8080. | http://localhost:8080 |
| HEXFORGE_API_KEY | No | API key required only if the Gateway has AUTH_ENABLED=true. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_workspacesA | List every workspace on the Gateway. Only reads, takes no arguments. Returns an array of { id, name, targetLabel, status, createdAt, updatedAt } where status is one of created, analyzing, ready, error and the timestamps are ISO 8601. Use it to see what already exists before choosing a workspace name; use get_or_create_workspace to make a new one. |
| get_or_create_workspaceA | Get a workspace by name, creating it first if it doesn't exist - idempotent, so safe to call every time you start work on something (calling it again never makes a duplicate or changes an existing workspace). Returns the workspace as { id, name, targetLabel, status, createdAt, updatedAt }; a new one starts with status "created". Most other tools create their workspace implicitly, so you only need this to set a targetLabel or to get the id. |
| list_knowledgeA | List a workspace's knowledge base entries, newest first: reports (auto-generated when a workflow finishes), notes (including APKs claimed from the inbox), summaries, and chat history. Only reads, apart from creating the workspace if it doesn't exist. Returns an array of { id, workspaceId, type, title, content, source, createdAt, updatedAt, relatedEntryIds }. Without the type filter all four types are returned, chat turns included, which can be long - filter to "report" or "note" for findings. To ask a question about the findings rather than read them, use chat_with_workspace. |
| get_inbox_apksA | List the .apk files that were dropped into the server's inbox folder (APK_INBOX_DIR) and automatically claimed into this workspace, newest first - use it to get a real apkPath for decompile_apk, decode_apk, identify_packer or adb_install without the user typing or pasting a path. Only reads. Returns an array of { fileName, path, sizeBytes, detectedAt }, where path is absolute. An empty array means nothing has been dropped for this workspace, or the inbox isn't enabled on the server. A dropped file lands in the workspace named after its filename ("MyApp-v2.apk" becomes workspace "myapp-v2"), so pass that name as workspace. |
| chat_with_workspaceA | Send a message in a workspace's ongoing chat and get the assistant's reply as plain text. It's a real multi-turn conversation: earlier turns (up to 20, trimmed to roughly 12,000 characters) are sent along, and your message and the reply are both saved to the workspace's knowledge base as chat entries. The assistant sees only that chat history - not the workspace's reports, notes, job results, or files - so put the facts a question depends on in the message itself. The message and history go to the Gateway's configured AI provider (a remote API or a local model); errors if none is configured. For a one-off summary of some text use summarize_text; to read stored entries use list_knowledge. |
| list_capabilitiesA | List what this Gateway can do: each capability (for example java.decompile, android.rebuild or instrument.trace) with the agents that provide it and the operations they offer for it, plus every agent's descriptor (backend tools, permissions, payload keys, declared outputs). Only reads, and needs no workspace. Use it to discover what is available, for example when a plugin might provide something the other tools don't. |
| list_artifactsA | List the artifacts recorded in a workspace: directories and files that finished tasks produced (decompiled sources, a decoded APK project, a rebuilt APK, secret-scan and Frida trace results), newest first. Returns an array of { id, kind, path, pathType, source: { taskId, agent, operation, capability }, tools?, createdAt, updatedAt }; tools lists the backend tool versions behind it. Artifact ids are what create_finding evidence cites. Only reads, apart from creating the workspace if it doesn't exist. |
| list_graph_entitiesA | List the typed entities in a workspace's knowledge graph, sorted by name: packages and classes indexed automatically from a jadx decompile, plus anything added through the Gateway API. Returns an array of { id, type, name, attributes, artifactIds, createdAt, updatedAt }; class entities keep their source file in attributes.file. Use get_graph_entity for one entity's relationships, and an entity id as entityId in a finding's evidence. Only reads, apart from creating the workspace if it doesn't exist. |
| get_graph_entityA | Get one knowledge-graph entity together with every edge touching it (a package containing a class, calls, invokes, accesses and so on), by entity id from list_graph_entities. Returns { entity, edges: [{ id, from, to, relation, createdAt }] }, where from and to are entity ids. Only reads. Errors if the entity doesn't exist. |
| list_findingsA | List a workspace's findings - claims about the target with their status, confidence and evidence - newest first. Returns an array of { id, claim, status, confidence?, reasoning?, evidence: [{ artifactId, entityId?, location?, note? }], source, createdAt, updatedAt }. Check it before create_finding so you don't record the same claim twice. Only reads, apart from creating the workspace if it doesn't exist. |
| create_findingA | Record a claim about the target together with the evidence behind it. The Gateway checks the evidence: an artifact or entity that doesn't exist in this workspace is rejected with an explanation, and a finding can't be confirmed without at least one piece of evidence - so cite artifacts from list_artifacts, and say where (for example "com/acme/Api.java:12"). It is saved as unverified unless you set a status, and with source "ai". Returns the created finding; change it later with update_finding. Creates the workspace if it doesn't exist. |
| update_findingA | Change a finding: its status (confirm it once the evidence supports it, or mark it contradicted), confidence, reasoning or evidence. Evidence given here replaces the finding's existing evidence rather than adding to it, and is checked the same way as in create_finding; a finding can't be confirmed without evidence. Provide at least one field besides findingId. Returns the updated finding. Errors if the finding doesn't exist or the change is rejected, in which case it is left as it was. |
| verify_findingA | Check a finding's evidence against the files it cites. For each evidence item with a location such as "com/acme/Api.java:12" it confirms the file exists in the artifact and the line (or range) is within it; items without a location, or in a single-file artifact, are reported as unverified. Returns { findingId, checkedAt, summary: verified | partial | unverified | failed, items: [{ index, artifactId, entityId?, location?, status, reason }] }. "verified" means the cited place exists - it does not prove the claim is true, so still read the code. It never changes the finding's status; use update_finding for that. Only reads. Errors if the finding doesn't exist. |
| decompile_apkA | Decompile an APK (also .dex, .jar, .aar, .zip) to readable Java-like source with jadx, for reading and searching. The output is reference code that cannot be rebuilt into an APK - use decode_apk if you need to edit and rebuild. Writes into the workspace's jadx directory (a re-run writes into the same one) and returns { outputDir, fileCount, files, stdoutTail, stderrTail? }; files holds at most 200 relative paths, so use list_files or search_code to explore the rest. Waits up to 2 minutes for jadx; on a very large APK the call can time out with an error while the decompile keeps running in the Gateway. Requires jadx on PATH. |
| decode_apkA | Decode an APK's resources to editable XML and disassemble its code to smali with apktool, so the result can be edited and rebuilt with build_apk (unlike decompile_apk's read-only Java). Always writes to the workspace's single apktool/decode directory and replaces whatever was there, including any edits you made to a previous decode - copy it elsewhere first if you need to keep it. Returns { outputDir, fileCount, files, stdoutTail, stderrTail? }; files holds at most 200 relative paths. Requires apktool on PATH. |
| build_apkA | Rebuild an APK from an apktool-decoded (and possibly edited) project directory. The result is unsigned, so it won't install until you sign it separately. Writes to the workspace's apktool/build directory (overwriting a previous build of the same name) and returns { outputPath, signed: false, stdoutTail, stderrTail? }. Fails if inputDir has no apktool.yml, i.e. isn't a decode_apk output. Requires apktool on PATH. |
| identify_packerA | Fingerprint the compiler, packer, obfuscator, and anti-debug/anti-VM techniques an APK uses, via APKiD's YARA rules - a good first look before deciding how to approach an APK. Only reads the file. Returns APKiD's own JSON report (for each scanned file, its matches grouped by category - compiler, obfuscator, packer, anti_vm and so on); if APKiD's output isn't valid JSON it returns { raw } instead. Requires apkid on PATH (pip install apkid). |
| scan_secretsA | Recursively scan a directory (typically decompile_apk or decode_apk output) for likely hardcoded secrets: AWS access keys, Google API keys, private key headers, Slack/GitHub/Stripe tokens, JWTs, and Firebase Cloud Messaging keys. A curated high-precision starting set, not exhaustive, and not a replacement for a maintained secret scanner. Only reads files; skips files over 2 MB. Returns { dirPath, filesScanned, matchCount, matches: [{ file, line, text, name }], truncated } where name is the secret type, file is relative to dirPath, line is 1-based, and text is the trimmed line (max 300 chars). For your own patterns use search_code. The full result is also saved as a JSON file in the workspace and its path returned as outputPath, so it can be cited as evidence. |
| search_codeA | Search a directory tree for a regular expression, line by line - e.g. a permission string or URL in decompiled output. Only reads files; skips files over 2 MB, and has a 10-second limit so a pathological regex errors instead of hanging. Returns { dirPath, filesScanned, matchCount, matches: [{ file, line, text, name }], truncated } where file is relative to dirPath, line is 1-based, text is the trimmed matching line (max 300 chars), and name is always "match". To look specifically for hardcoded credentials use scan_secrets instead. |
| read_fileA | Read one file's contents by absolute path - e.g. a decompiled source file or an AndroidManifest.xml from decode_apk's output. Only reads. Content over 512 KB is cut off at 512 KB, signalled by truncated: true. Returns { filePath, size, truncated, encoding, content } where size is the full file size in bytes. Errors if the path doesn't exist or is a directory (use list_files to see what's in a directory first). |
| list_filesA | List a directory's immediate children, or every file beneath it with recursive - e.g. to see what decompile_apk or decode_apk produced before reading individual files. Only reads. Returns { dirPath, count, entries: [{ path, isDirectory, size }], truncated } where path is relative to dirPath and size is in bytes (0 for directories); truncated is true if the limit cut the listing short. Errors if dirPath doesn't exist. To find files by content rather than name use search_code. |
| adb_devicesA | List Android devices and emulators visible to adb. Only reads, and the workspace parameter has no effect on the result - the listing is the same for any workspace. Call this first to confirm a device is connected and to get serials for the deviceSerial parameter of the other adb_* and frida_* tools. Returns { devices: [{ serial, state, extra }] } where state is e.g. "device", "unauthorized" or "offline" and extra is adb's remaining -l detail (model, transport). An empty list means nothing is connected. Requires adb on PATH. |
| adb_shellA | Run one shell command on a connected Android device via |
| adb_installA | Install an APK from this machine onto a connected device via |
| adb_logcatA | Dump the device's current logcat buffer and return its most recent lines - a snapshot, not a live stream, and it doesn't clear the buffer. Only reads. Returns { lineCount, truncatedFrom, lines } where lines is an array of raw log lines, lineCount is how many are returned, and truncatedFrom is the total lines in the dump before trimming. Use filter to cut noise (e.g. one app's tag) before raising lines. Requires adb on PATH and an authorized device. |
| frida_list_processesA | List running processes on a device via Frida, or with includeApps the installed apps too. Only reads. Use it to find the package name or PID to pass to frida_trace. Returns { processes: [...] } where each entry is { pid, name } or, with includeApps, { pid, name, identifier } - identifier is the package name, and an installed app that isn't running has no real PID. Requires frida-tools on PATH and a frida-server on the device whose version matches. |
| frida_traceA | Spawn or attach to a process on a device, inject a Frida script, and capture whatever it prints within a fixed time window - not an interactive Frida session: it runs the script, waits timeoutSeconds, then kills the session. Hitting the timeout is the normal way a trace ends (timedOut: true), not a failure. The script runs inside the target app and can modify its behavior and state, and spawn mode launches the app. Returns { target, mode, scriptPath, timedOut, stdout, stderr } where stdout is whatever the script printed (e.g. console.log output) and scriptPath is where the script was saved in the workspace. The full result is also saved as a JSON file in the workspace and its path returned as outputPath, so it can be cited as evidence. Find targets with frida_list_processes. Requires frida-tools and a matching frida-server on the device. |
| summarize_textA | Summarize text - e.g. long tool output - using the Gateway's configured AI provider, returning { summary } (up to about 512 tokens). The text and instructions are sent to that provider, which may be a remote API (Anthropic, OpenAI, Gemini, etc.) or a local model (Ollama), so don't pass anything you wouldn't send there. Errors if no provider is configured on the Gateway. Doesn't save anything to the knowledge base; to ask questions about a workspace's accumulated findings use chat_with_workspace instead. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 28 tools
Tools cover distinct operations: decompile vs decode are explicitly contrasted, search_code vs scan_secrets are clearly differentiated, and the workspace/finding/graph/adb/frida groups have clear boundaries. Minor potential confusion between list_files/read_file/search_code, but descriptions explicitly cross-reference each other to disambiguate.
Predominantly consistent verb_noun snake_case (list_capabilities, create_finding, decompile_apk, adb_install). A few compound/agent-prefixed names (frida_list_processes, get_or_create_workspace) deviate slightly from the simple verb_noun pattern but remain readable and predictable.
28 tools exceeds the typical well-scoped range and is heavy for what is essentially a multi-domain gateway. While each tool maps to a real capability, the volume approaches the 25+ threshold where discovery and selection become burdensome.
Covers the full APK analysis lifecycle: discovery, decompile/decode, build, secrets/packer scanning, findings with evidence, knowledge graph, device interaction, and AI summarization. Minor gaps include no signing tool (build_apk output is unsigned and must be signed externally) and no dedicated update/delete for findings besides update_finding.