linc-spectra
Attach a debugger to a running Android app (JDWP via kotlin-debug-adapter, or zero-config jdb by fully-qualified name with no sources) or iOS-simulator app (lldb-dap) and read what UI and logcat cannot show — locals at a method hit, exception frames — through 14 MCP tools.
Install
Prerequisites: Python 3.13+ (stock macOS python3 is older; uv tool install linc-spectra fetches its own Python 3.13 automatically, whereas running pip or pip3 on an older interpreter fails with No matching distribution found for linc-cli-kit).
Install with uv, pipx, or pip (Python >= 3.13):
uv tool install linc-spectrapipx install linc-spectrapip install linc-spectra
uv tool install places spectra (and linc-spectra) in ~/.local/bin; a shell without ~/.local/bin on PATH gets exit code 127 (command not found) — run uv tool update-shell and open a new shell (or add ~/.local/bin to PATH).
Then check your environment with uvx linc-spectra doctor (or spectra doctor once installed):
- What it checks:
adb,kotlin-debug-adapter,jdb,lldb-dap(macOS only),xcrun(macOS only), andpython(>= 3.13). On macOS,doctorprobes the/usr/bin/jdband/usr/bin/xcrunstubs and reports them as failed until a JDK or Xcode / Command Line Tools is installed. - Exit codes: exits
0when at least one debugger lane is usable (Android:adbpluskotlin-debug-adapterorjdb; iOS on macOS:xcrunpluslldb-dap), or exits1with ahint:line for every failed check. Pass--json(spectra doctor --json) for a single{ok, checks}JSON object on stdout.
Adapters
- Android — zero-config
jdblane: requiresadb(Android SDKplatform-tools), a debuggable build (android:debuggable="true"), andjdb(ships with any JDK onPATH). Breaks on methods and exceptions by fully-qualified JVM name without local source files. - Android — full DAP lane: requires
adb, a debuggable build, local source files, andkotlin-debug-adapter. Unpack a release zip fromfwcd/kotlin-debug-adaptersoadapter/bin/kotlin-debug-adapteris onPATHor installed under~/tools/kotlin-debug-adapter/(~/tools/kotlin-debug-adapter/adapter/bin/kotlin-debug-adapter). - iOS — simulator lane (experimental): requires macOS with Xcode's
lldb-dap(checked onPATHfirst, then resolved viaxcrun -f lldb-dap) andxcrun;spectra doctorreports the macOS/usr/bin/jdband/usr/bin/xcrunstubs as failed until a JDK or Xcode is installed. Simulator only.
Finding your device id
- Android (
device/device_serial): runadb devicesand use the value in the first (serial) column (for example,emulator-5554). - iOS Simulator (
device/device_serial): runxcrun simctl list devices bootedto find the booted simulator UDID, or pass the literalbooted.
Quickstart
Register the MCP server and run either the zero-config jdb flow (no local sources) or the full DAP flow:
claude mcp add linc-spectra -- spectra bellows
# Or run directly without a global install:
claude mcp add linc-spectra -- uvx linc-spectra bellows
# Zero-config flow (Android jdb — no local source checkout needed):
# spectra_method_breakpoint(device="emulator-5554", package="com.example.app", method_fqn="com.example.app.AuthRepository.login")
# -> trigger the UI in the app
# -> spectra_method_locals(session_id="<session_id>")
# Full DAP flow (Android kotlin-debug-adapter or iOS lldb-dap):
# spectra_attach(device="emulator-5554", package="com.example.app", platform="android")
# -> spectra_breakpoint(session_id="<session_id>", source_path="/abs/path/AuthRepository.kt", lines="42")
# -> spectra_continue(session_id="<session_id>")
# -> spectra_stacktrace(session_id="<session_id>")
# -> spectra_variables(session_id="<session_id>", frame_id=0) # 0 = stopped thread's top frame, or an id from spectra_stacktrace
# -> spectra_detach(session_id="<session_id>")
MCP Tools (14)
linc-spectra exposes 14 MCP tools grouped by workflow.
DAP Session
| Tool | Description |
|---|---|
spectra_attach |
Attach a DAP debugger to a running debuggable app (Android JDWP or iOS Simulator LLDB) |
spectra_detach |
Detach the debugger, remove port forwards, and clean up the session |
spectra_sessions |
List all active debug sessions |
Stepping
| Tool | Description |
|---|---|
spectra_breakpoint |
Set file:line breakpoints on local source files |
spectra_continue |
Resume execution and wait for the next breakpoint or stop event |
spectra_step |
Step next (over), in (into), or out (out of the current frame) |
Inspection
| Tool | Description |
|---|---|
spectra_stacktrace |
Get the call stack for the stopped thread |
spectra_variables |
Inspect local and scope variables at a stack frame |
spectra_evaluate |
Evaluate an expression in the current frame context (REPL at a breakpoint) |
Zero-Config jdb
| Tool | Description |
|---|---|
spectra_method_breakpoint |
Arm a zero-config breakpoint on a method by fully-qualified name (<class>.<method>) with no local sources |
spectra_method_locals |
Harvest captured local variables from an armed spectra_method_breakpoint hit |
spectra_exception_breakpoint |
Arm a zero-config exception catchpoint by fully-qualified exception class name |
spectra_exception_info |
Harvest the throwing frame, thread, and locals from an armed spectra_exception_breakpoint |
Analytics
| Tool | Description |
|---|---|
spectra_usage_stats |
Aggregate per-tool call counts, latency percentiles, and error rates from $LINC_HOME/mcp-calls.jsonl |
Limitations
- Upstream
kotlin-debug-adapterexception breakpoints do not work: usespectra_exception_breakpoint(thejdbcatchpoint) instead. file:linebreakpoints reportverified: trueeven without local sources:kotlin-debug-adaptermarks non-existent paths as verified even though they can never bind;spectra_breakpointattaches awarningfield whensource_pathis missing locally (usespectra_method_breakpointwhen you do not have the source checkout).- One debugger per process: a target process exposes a single JDWP connection at a time — detach any active DAP session before arming a
jdbsession on the same app (and vice versa). - iOS simulator only: iOS debugging via
lldb-dapsupports booted iOS simulators on macOS only (experimental; physical iOS devices are not supported). - iOS
spectra_evaluatetakes expressions only: iOS expressions run inlldb-dap's expression-only (watch) context and LLDB commands (such as backtick-prefixed commands) are refused. jdbrenders values as text: a debuggee string containing line breaks can add a fakename = valueline to ajdbreply (spectrakeeps the first value of a name within a reply).- Bounded
jdbwaits and stepping:spectra_method_localsandspectra_exception_infowait at most180 s(wait_s0–180), and manual stepping takesmax_steps0–16. - Python >= 3.13: requires Python 3.13 or newer.
Trust
- No telemetry, no phone-home. spectra runs locally over stdio MCP and opens no network listener; it talks only to your local
adb,jdb,kotlin-debug-adapter,xcrun, andlldb-dapprocesses. - Local usage log under your control. Every MCP tool call is recorded in
$LINC_HOME/mcp-calls.jsonl(default~/.linc/mcp-calls.jsonl, rotated at 10 MB). Control logging withSPECTRA_USAGE_LOG=off|redacted|full:redacted(default) — sensitive fields (expressionandsource_path) are replaced by length-only placeholders (<redacted len=N>, no digest), expression text is scrubbed from recorded error strings, and the log file is opened owner-only (0600) withO_NOFOLLOW.off— nothing is written to disk.full— raw parameter values are logged (long strings truncated at 500 characters, byte buffers summarized by length). Opt in only on a machine you trust.
spectra_evaluateruns code inside the debuggee. By design,spectra_evaluateand thejdbtools execute inside the attached debuggable application. Identifiers that reachadb shell,xcrun simctl, orjdbstdin are validated with strictre.fullmatchpatterns before execution. See SECURITY.md for the threat model and vulnerability reporting instructions.
How this repo works
This repository is a release mirror of LINC's private repository — each release lands here as a single commit. Issues are welcome; pull requests are accepted by arrangement (open an issue first). See CONTRIBUTING.md.
Built by LINC Innovations. Licensed under Apache-2.0.
Metadata
Release files for linc-spectra 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| linc_spectra-0.1.0.tar.gz | 174.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| linc_spectra-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 250.8 kB
Release files / linc_spectra-0.1.0.tar.gz
| Download URL | linc_spectra-0.1.0.tar.gz |
|---|---|
| Size | 174.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3f15cecf9de25e8f23b26d080a11c3d8d6c22042a3b1f096a1a32254f550346d
|
|
BLAKE2b-256 checksum How to use checksums |
437a84d8a66e1c8f9d8f5176a2078b059f8269ae6c27f8051346f661b7e134bb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logRelease files / linc_spectra-0.1.0-py3-none-any.whl
| Download URL | linc_spectra-0.1.0-py3-none-any.whl |
|---|---|
| Size | 76.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e57b2279f1c334ba5fd0929677dd790d4d28e6b124d1ed1b77ba0d2a5388d2a7
|
|
BLAKE2b-256 checksum How to use checksums |
fa18dc67cbd61fed1f6daeaebf96c0bc0f5d08bf1c87f2402d39874f10c01980
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logSecurity for linc-spectra 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for linc_spectra-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.