Skip to content

Support explicitly allowed tools from local MCP servers #55

Closed

Description

@vicgupta

Summary

Add opt-in access to explicitly allowed tools from local Model Context Protocol (MCP) servers. Developers could give tinyagent a typed interface to an existing documentation index, issue tracker, or project service without adding a service-specific tool to the binary or teaching the model a shell wrapper.

Scope this first feature to stdio transport, a fixed per-run tool catalog, and text/JSON results. Keep the default nine-tool workflow unchanged. This is an evidence-backed integration opportunity, not a claim that tinyagent users have requested MCP or that maintainers have approved this direction.

Problem and opportunity

Today all native tools are compiled into internal/tools/tools.go: Specs() returns a fixed list and the executor dispatches through a switch with a fixed argument structure. The model can use shell commands for external integrations, but tinyagent cannot discover and expose a third-party service's tool schemas directly. Supporting another native integration requires changing the agent itself.

The intended beneficiaries are developers who already operate trusted local MCP servers and want those tools available during a coding task. A concrete workflow would combine repository inspection with a query against a team's local documentation service, then use the returned information in a code change. This is a proposed use case; no tinyagent adoption or productivity measurements were found.

Why now: merged background-process support provides relevant lifecycle patterns, and the existing provider abstraction already accepts tool names and schemas. A standard extension boundary could keep service integrations outside this minimal core. This inference needs maintainer evaluation; MCP compatibility brings real dependency and security costs.

Research and evidence

Verified repository facts — inspected local commit 7021942 and rechecked the subsequent main change 059bf16 through GitHub on 2026-10-24:

  • The README describes a static Go binary, nine tools, five provider choices, YAML configuration, bounded runs, and saved trajectories. It explicitly warns that bash is not sandboxed and file-path checks are lexical.
  • tools.go has no external-tool registry. provider.go defines Model.Query, ToolSpec, JSON argument strings, and text tool results: useful extension seams, not proof that arbitrary MCP schemas work with every provider.
  • Issue #41 and merged PR #51 establish bounded child-process output and cleanup at run end. MCP processes require separate protocol streams; these are lifecycle precedents, not an MCP implementation.
  • Merged PR #27 rejects unknown configuration keys. New server settings should retain that property.
  • During research, resume PR #54 merged at 2026-10-24 22:12:34 UTC. Its resume validator fingerprints the built-in tool definitions and checks saved tool names before provider setup. External tool identity must not bypass that contract.
  • No MCP request or maintainer endorsement was found. The inspected tree contains no issue template, CONTRIBUTING, AGENTS.md, roadmap, RFC, or ADR; discussions are disabled. Latest release v0.3.0 was published 2026-10-24; main includes subsequent merged work.

External findings — checked 2026-10-24:

  • MCP tools specification, revision 2026-07-28 defines schema-based discovery, paginated listing, invocation, and distinct tool-execution errors. It also calls for timeouts and auditability and treats tool annotations as untrusted hints. These inform interoperability and defensive behavior, rather than establish tinyagent demand.
  • MCP stdio binding, revision 2026-07-28 specifies subprocess communication, separate protocol stdout and diagnostic stderr, cancellation, shutdown, and compatibility with older initialization-based servers.
  • Gemini CLI's official MCP documentation demonstrates this integration pattern, including tool filtering, namespacing, schema compatibility handling, and server trust configuration. Its broader transports/resources/UI are deliberately outside this proposal.
  • Gemini CLI issue #28355, opened 2026-07-11 and still open when checked, reports a mismatched response ID causing silent discovery blocking. This is one firsthand failure report in another project, not a reproduced tinyagent defect or evidence of prevalence. It motivates bounded discovery and visible diagnostics.
  • The official Go SDK supplies client support. Its v1.8.0 release, published 2026-09-14, retains the 2026-07-28 protocol and legacy compatibility. Evaluate a pinned SDK rather than assuming older handshake examples describe the current protocol. No SDK dependency is mandated here.

Users and use cases

  • A developer with an existing trusted documentation server enables only its search/retrieval tools, then asks tinyagent to implement a change using that documentation.
  • A developer exposes selected project-specific query tools through an independently maintained server and reuses them across tinyagent's supported model providers.
  • A headless caller needs deterministic configuration failures and bounded execution rather than an interactive setup or approval flow.

Goals

  • Discover and invoke explicitly authorized external tools alongside the built-ins.
  • Preserve tool identity, arguments, results, and error visibility across providers and trajectories.
  • Bound discovery, invocation, output, and process lifetime.
  • Preserve current behavior when no server is configured.

Non-goals

Remote HTTP/SSE transports or OAuth; a server marketplace or installer; MCP resources/prompts; image/audio handling; sampling, elicitation, or other interactive callbacks; live catalog refresh; automatic server restart or call replay; a general plugin language; a new sandbox or comprehensive permissions system. Resuming MCP-enabled runs is excluded from this first feature; preserve resume for ordinary built-in-only runs.

Proposed behavior

  1. Accept server definitions through the existing user configuration or explicitly selected --config file. Each definition supplies a stable alias, executable plus argument array, an explicit nonempty tool-name allowlist, environment-variable names to forward, and finite discovery/call timeouts. Validate before launching anything. Do not discover executable configuration from repository files or model output. Launch directly without implicit shell interpolation, with --cwd as the working directory and a documented minimal environment plus explicitly forwarded variables.
  2. Connect using documented supported protocol revisions, discover tools across all listing pages within bounded limits, and retain only allowed tools. Fail before the first model request if an explicitly requested server/tool is unavailable, has an unsupported schema, or cannot be represented without changing its meaning. An empty allowed selection is an actionable configuration failure. Clean up already-started servers on partial startup failure.
  3. Expose stable provider-compatible names mapped unambiguously to the configured alias and original tool name. Built-in names remain reserved. Detect collisions rather than overwrite. Keep the allowed catalog fixed for this run; changed server catalogs require a new run.
  4. Route calls through this registry while preserving arbitrary JSON argument keys and types. Deny unknown or unlisted external calls at dispatch, even when a model fabricates one. Tool descriptions, server instructions, and returned text cannot grant additional access or replace project/system instructions.
  5. Return text content and serialized structured JSON, with a deterministic documented representation. Preserve tool-execution error status in the model-visible result. Mark omitted unsupported content explicitly; never download resource links or pretend image-only output was successfully understood. Bound transport messages before full buffering and truncate model-visible results with a marker. Do not resolve remote schema references over the network.
  6. A timeout, server exit, malformed response, permission failure, or unsupported interaction yields an identifiable error and matching tool result. Stop using a failed connection; subsequent calls fail visibly. Never automatically replay an invocation whose side effects may already have occurred. The model may choose its next action normally.
  7. Keep protocol messages and server diagnostics out of normal stdout. Report enabled tool identities and connection failures on stderr; retain call/result pairing and the effective catalog identity in -o trajectories. Mark MCP-enabled trajectories as ineligible for resume, and reject both resuming such a trajectory and adding MCP configuration to an ordinary resume before launching servers or contacting a provider. Close streams, reap servers, and apply platform-appropriate forced termination after a bounded shutdown grace period on every exit path. Existing Unix/Windows descendant-cleanup differences must be documented rather than hidden.

Acceptance criteria

  • With no MCP settings, no MCP subprocess starts and built-in schemas, default CLI output, exit behavior, and existing configuration handling are unchanged.
  • A local fixture server exposes an allowed tool on a later discovery page; a fake model invokes it and receives its text/JSON result in the next request. The saved trajectory retains the call ID, external identity, arguments, and result.
  • Nested objects, arrays, booleans, numbers, and argument names absent from the built-in args structure survive dispatch. Two servers with the same original tool name route independently; built-in names cannot be replaced. Invalid/colliding definitions fail explicitly.
  • An unlisted tool is neither advertised nor invoked when requested directly by a fake model. Newly advertised tools and misleading annotations/instructions cannot widen the configured allowlist during a run.
  • Missing executables, missing forwarded variables, unknown config keys, unsupported protocol versions/schemas, missing selected tools, empty selections, pagination loops, and discovery timeout fail before a model request and clean up started servers. Diagnostics identify the server and cause without dumping configuration secrets.
  • Fixture tests cover successful text and structured results, tool errors, mixed/unsupported content, malformed messages, wrong response IDs, oversized frames/results, call timeout, and server exit. Each case returns or terminates within its configured bound and preserves valid call/result pairing where a model call occurred.
  • A side-effecting fixture records one invocation before disconnecting; tinyagent does not automatically invoke it again. Unsupported callbacks/interactions fail without hanging or launching extra actions.
  • Completion, provider error, startup failure, Ctrl-C, and step/cost/time limits clean up server processes within the shutdown bound. The wall-clock deadline includes discovery and cleanup has a separate bounded grace period. Unix descendant termination and Windows behavior are tested/documented accurately.
  • Provider-wire tests cover OpenAI-compatible routing (including OpenRouter/Ollama), Anthropic, and Codex with supported schemas and streamed/nonstreamed model responses. Compaction preserves external call/result pairing and never changes authorization.
  • Built-in-only resume retains its current behavior. Attempting to resume an MCP-enabled trajectory, or to add MCP configuration to a built-in-only resume, fails with a specific explanation before any server launch or provider request; historical calls/configuration are never executed.
  • Credentials forwarded only to the child environment are absent from generated configuration diagnostics, startup summaries, and trajectory metadata. README warns that arguments/results/server stderr can themselves contain sensitive data; no blanket redaction guarantee is claimed.
  • README documents configuration, explicit trust, supported versions/schema subset, limits, result conversion, failure behavior, cross-platform prerequisites, and disabling the feature. Existing CI build/vet/tests and six-platform static builds continue to pass.

Technical context and constraints

Facts: cmd/tinyagent/main.go loads config, creates the executor, installs the signal context, and saves trajectories. internal/agent/loop.go obtains tools.Specs() and invokes the executor serially; its wall-time deadline currently begins inside Run. Discovery must participate in that deadline rather than occur unbounded before it. internal/agent/compact.go maintains a separate model view. internal/trajectory/trajectory.go records original messages and now includes versioned tool metadata; internal/agent/resume.go and internal/trajectory/resume.go validate resume compatibility. An MCP audit trajectory must not falsely advertise built-in-only resumability. The provider adapters translate the shared ToolSpec and messages. internal/tools/process.go manages background commands; its output buffer combines command output and is not a substitute for a protocol transport.

go.mod declares Go 1.27.1 and currently only one direct dependency, gopkg.in/yaml.v3. The Makefile targets Linux/macOS/Windows on amd64/arm64 with CGO disabled. CI runs formatting, build, vet, and uncached tests on Ubuntu; existing tests use fake models, HTTP fixtures, temporary directories, and process fixtures. There is no public extension API: relevant packages are under internal/.

Proposed choices for review: a bounded per-run registry, explicit per-tool preauthorization suitable for the existing noninteractive CLI, and an SDK-backed transport are reasonable approaches. The SDK version, registry placement, configuration names, schema subset, and concrete finite limits require engineering review. They are not existing repository constraints. Do not silently rewrite schemas to appease a provider; document/reject unsupported cases.

Alternatives considered

Candidate Evidence and value Fit, risk, and decision
Local MCP tool integration Verified fixed registry; standardized interoperable tool interface; comparable CLI implementation and official Go client Highest new capability: integrations stay outside core. Higher protocol/security maintenance than prompt features, constrained here to trusted stdio tools. Selected on opportunity evidence, not proven user demand.
Reusable Agent Skills discovery/loading Official integration guide describes catalog-first, on-demand instructions Plausible lower-dependency extension. Existing AGENTS.md, custom prompts, and file reads already offer partial workflows; adds instruction distribution rather than typed service access. Trust, path access, and compaction retention still need design. Deferred.
Structured final task results for automation Existing -t -, exit statuses, and trajectory output; aider scripting docs show comparable headless workflows Useful, coherent feature, but no specific unmet tinyagent output consumer or schema need was found; trajectory already supplies machine-readable data. Lower evidence for additional product surface. Deferred.
Durable checkpoint resume Strong direct task-continuation value Already proposed in #42, implemented by merged PR #54. Excluded as duplicate; persistent external connections must not later be mistaken for resumable handles.
Enforced read-only analysis Directly addresses the documented tool trust boundary Already covered by #49. Excluded as duplicate; external annotations alone cannot establish read-only safety.

Implementation alternative: keep using shell-based CLIs/wrappers. That has no new protocol dependency and remains useful, but does not offer native discovery/typed tools. A general executable-plugin protocol would also work, at the cost of inventing a new integration contract instead of reusing MCP.

Cross-cutting considerations

  • Security/privacy: this is explicit authorization to run local executables and allowed tools, not isolation. MCP servers can access the host/network with their own privileges. Default off, no automatic package installation, no repository-config auto-execution, minimal credential forwarding, dispatch enforcement, and no remote schema fetching limit accidental exposure. Preauthorization is a proposed compromise for headless use; sensitive integrations should remain disabled unless the operator accepts it. MCP's recommendation for human review of sensitive calls is not fully satisfied by per-run preauthorization.
  • Performance/scalability: cap server count, catalog/schema bytes, discovery pages, frames, results, and diagnostic buffering with documented finite defaults. An allowlist limits model context growth but does not eliminate schema token overhead. No speedup or token savings are promised.
  • Reliability/observability: bounded stderr diagnostics, stable identities, ordinary trajectory call/results, visible failure, and no implicit replay support troubleshooting without adding a telemetry backend. Cancellation cannot undo remote side effects.
  • Compatibility/rollout: additive opt-in configuration; no existing data migration. Preserve the newly merged built-in resume contract and do not depend on the unimplemented read-only proposal. If Add enforced read-only mode for repository analysis and code review #49 lands first, disable external tools in read-only mode unless a separately reviewed enforceable policy exists. Removing server configuration rolls back the feature; externally performed actions are not rolled back.
  • Accessibility/maintenance: retain text-only CLI operation and actionable stderr diagnostics without color-only status or interactive prompts. External server runtimes remain operator-managed; document version support and assign no new maintainer/owner through this issue. SDK upgrades need protocol and cross-platform regression checks.

Test and verification expectations

Use an offline fixture executable to exercise discovery, pagination, protocol versions, argument fidelity, invocation, stderr separation, and lifecycle failures. Use fake-provider HTTP tests to verify schemas and tool-result wire formats, plus agent tests through compaction and run limits. Test credential non-disclosure with harmless sentinel values. Keep external services, real credentials, and package downloads out of required tests. Run the existing CI checks and cross-build matrix; do not infer runtime portability from cross-compilation alone. No feature implementation or tests have been performed for this proposal.

Documentation and rollout considerations

Ship disabled by default with one complete local text-tool example and instructions for supplying an already-installed server. Explain the authorization boundary before enabling it, the supported protocol/schema matrix, result truncation/unsupported-content behavior, finite limits, troubleshooting, Windows lifecycle limitations, and sensitive trajectory handling. A separate feature flag is unnecessary if absence of server configuration disables all startup and dispatch. No migration or hosted monitoring service is required.

Dependencies and related work

Repository: #41 / #51 (process lifecycle precedent), #27 (strict config), #42 / #54 (newly merged resume compatibility contract), #49 (separate read-only proposal), and #24 / merged PR #28 (compaction invariants). External specifications, comparable implementation, failure report, and optional Go SDK are linked above; they are not runtime service requirements.

Duplicate review covered all then-listed open/closed issue and PR titles/bodies, available comments, releases, and the repository tree, plus MCP / Model Context Protocol / custom tools / plugin / extension searches. No equivalent proposal or prior rejection was found. Discussions are disabled and no roadmap entry exists in the inspected tree. Recheck the issue list before implementation because work is moving quickly.

Open questions

  • Which supported schema subset and provider-name encoding should be the initial compatibility contract? Preserve meaning and reject unsupported cases; avoid promising arbitrary schema support.
  • Should the first release use the official Go SDK or a smaller client dependency? Compare protocol compatibility, static cross-builds, bounded I/O support, and long-term update cost before choosing.
  • What finite default limits and shutdown grace period suit tinyagent's minimal CLI? Select documented bounds with fixture tests; no workload measurements justify numeric defaults in this proposal.

Activity

  1. added
    enhancementNew feature or request
    amf:readyReady for amf to turn into a pull request
    amf:doneamf opened a pull request for this issue
    and removed
    amf:readyReady for amf to turn into a pull request
    on Oct 24, 2026
  2. vicgupta commented on Oct 24, 2026

    @vicgupta
    OwnerAuthor

    amf opened #58 for this issue.

  3. added a commit that references this issue on Oct 24, 2026
    079e9ce
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    amf:doneamf opened a pull request for this issueenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions