Skip to main content
Glama
mvagnon

opencode-mcp

by mvagnon

opencode-mcp

MCP server (stdio) exposing an ask_codebase tool: ask a natural-language question about a GitHub repository, get an answer grounded in the real code. READ-ONLY by design.

Built in TypeScript on the official MCP TypeScript SDK, and on opencode running headless as the analysis engine.

How it works

  1. The server fetches the repo itself — clone if absent, fetch + hard resync otherwise. Fully deterministic: a nonexistent repo fails in seconds with the git error relayed verbatim, zero LLM tokens spent.

  2. opencode runs headless with cwd = the repo directory. No opencode serve, no --attach. The repo's own AGENTS.md (if any) is loaded as project context. Sessions are opencode-native and scoped per project directory, so continue_session=true deterministically means "the latest session of this repo" — cross-repo cross-talk is impossible by construction.

Fetch policy

A clone/fetch runs only when:

  • the repo is not in the manifest, or

  • its checkout is missing on disk (periodic cleanup), or

  • an explicitly requested branch differs from the checked-out one, or

  • the last fetch is older than OPENCODE_REPO_TTL_DAYS (default 3).

Otherwise the existing checkout is used as-is, so the code stays stable across follow-up calls.

Manifest

Known checkouts are tracked in .opencode_mcp_manifest.json (atomic writes, one entry per owner/repo):

{
  "owner/repo": {
    "dir": "/abs/path",
    "branch": "main",
    "fetched_at": "2026-07-15T03:21:00Z"
  }
}

Read-only enforcement

Two layers:

  1. A read-only preamble injected into every prompt by this server.

  2. Your opencode agent config — define an "explore"-style agent with edit: deny and set OPENCODE_AGENT to force it on every run.

Do not put read-only rules in your global AGENTS.md: it would poison your normal interactive opencode sessions.

Long calls

The hard timeout defaults to 10 minutes and an MCP progress notification is emitted every 15 s (clone/fetch included). Per the MCP spec, clients that reset their request timeout on progress keep the call alive; when the client sends no progressToken, the heartbeat is a no-op. Align the client's own per-call timeout (timeout: in the mcp_servers entry) above the hard one.

Related MCP server: GitHub Repo Explainer MCP

Requirements

  • Node.js ≥ 20

  • git on the PATH

  • opencode CLI (absolute path recommended via OPENCODE_BIN)

Install

From npm:

npm install -g @mvagnon/opencode-mcp   # installs the `opencode-mcp` command

Or run it without installing:

npx -y @mvagnon/opencode-mcp

From source:

npm install
npm run build   # server binary: dist/index.js (stdio transport)

Configuration

Declare environment variables in the env: block of the client's mcp_servers entry. Hermes does not pass your full shell env to stdio servers — only PATH, HOME, USER, LANG, LC_ALL, TERM, SHELL, TMPDIR.

Variable

Default

Purpose

OPENCODE_BIN

opencode

opencode binary (absolute path recommended)

OPENCODE_AGENT

(none)

opencode agent forced on every run (e.g. explore)

OPENCODE_REPOS_DIR

~/codelab/repositories

Where checkouts live

OPENCODE_MANIFEST_DIR

~

Directory of .opencode_mcp_manifest.json

OPENCODE_REPO_TTL_DAYS

3

Re-fetch a repo after this many days

ASK_CODEBASE_TIMEOUT

600

Hard timeout for the opencode run, in seconds

Example client entry (Hermes):

mcp_servers:
  opencode:
    command: npx
    args: ["-y", "@mvagnon/opencode-mcp"]
    timeout: 660 # keep above ASK_CODEBASE_TIMEOUT
    env:
      OPENCODE_BIN: /usr/local/bin/opencode
      OPENCODE_AGENT: explore

For a from-source checkout, use command: node with args: ["/abs/path/to/opencode-mcp/dist/index.js"] instead.

The ask_codebase tool

Argument

Type

Description

question

string

The natural-language question (e.g. "where is API request auth validated?")

repo

string

Exact GitHub slug owner/repo — no nicknames, no URLs

branch

string?

Optional branch to pin; omit for the default branch

continue_session

boolean

Resume the latest discussion of this repo (default false)

Use it for architecture questions, where a feature lives, request flow, conventions, design rationale, etc.

Development

npm run lint        # eslint
npm run typecheck   # tsc --noEmit
npm run build       # emit dist/
npm test            # node:test unit tests (pure logic)
npm run dev         # tsc --watch

Source layout: see AGENTS.md.

Releasing

Releases are fully automated with release-please and npm trusted publishing (OIDC — no npm token stored in the repo):

  1. Land changes on main using Conventional Commits (feat:, fix:, feat!:…) — they drive the version bump and the changelog.

  2. release-please maintains a release PR that accumulates changes, bumps package.json, and updates CHANGELOG.md.

  3. Merging the release PR creates the GitHub release and tag; the publish job then publishes to npm via OIDC.

One-time setup (already done once the package exists):

  • npm cannot create a package via OIDC, so the first version must be published manually (npm login && npm publish).

  • Then on npmjs.com → package → Settings → Trusted Publisher: GitHub Actions, repository mvagnon/opencode-mcp, workflow release.yml.

Available Tools

1 tool
ask_codebaseAsk codebaseA
Read-only

Ask a natural-language question about a GitHub repository and get an answer grounded in the real code. READ-ONLY: never writes, edits, builds, or executes anything. The harness fetches the repo itself (clone or refresh, max every few days) — a nonexistent repo fails fast with the exact git error. Stateful PER REPOSITORY: continue_session=true resumes the latest discussion of that owner/repo (follow-up questions keep their context); false (default) starts a fresh one. Optional branch pins a specific branch. Use it for architecture questions, where a feature lives, request flow, conventions, design rationale, etc.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoYesREQUIRED exact GitHub slug "owner/repo" (e.g. "vercel/next.js"). Deterministic — no nicknames, no fuzzy descriptions, no URLs. The harness fetches it itself and fails fast with the exact git error if it does not exist or is unreachable.
branchNoOptional branch to pin (e.g. "canary"). Omit for the repo's default branch. An explicit branch different from the current checkout triggers a re-fetch.
questionYesThe natural-language question (e.g. "where is API request auth validated?").
continue_sessionNoIf true, resume the latest discussion of this repo (same context; the checkout is only refreshed by the TTL policy, so code usually stays stable). If false (default), start a fresh discussion.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds substantial behavioral context beyond the readOnlyHint and openWorldHint annotations: it explicitly states 'READ-ONLY: never writes, edits, builds, or executes anything', explains the harness's repo fetching and caching behavior, fails-fast with git errors, and details session statefulness with continue_session. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (four sentences) and front-loaded with the core purpose. Every sentence delivers unique value: purpose, safety, fetch behavior, statefulness, and usage examples. No fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description fully covers the tool's behavior, safety, statefulness, fetch mechanics, and use cases. The input schema thoroughly documents all four parameters, and the description complements it without needing an output schema. It is complete for an AI agent to decide when and how to invoke the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description enriches parameter understanding beyond the schema by explaining deterministic repo slugs, session semantics associated with continue_session, and branch behavior (e.g., re-fetch on explicit branch). This adds meaningful context rather than merely repeating schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description precisely states that the tool answers natural-language questions about a GitHub repository with answers grounded in real code. The verb 'Ask' and resource 'codebase' are specific and there are no sibling tools requiring differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly lists use cases: 'architecture questions, where a feature lives, request flow, conventions, design rationale, etc.' This gives clear context on when to use the tool, even though no alternatives exist to contrast.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 1 tool updatev1.0.0
    • First observedask_codebase

TDQS

A4.8/5.0
Disambiguation5/5

With only one tool, there is no possibility of confusion or overlap. The tool's purpose is clearly defined as read-only codebase Q&A.

Naming Consistency5/5

The single tool name 'ask_codebase' follows a clear verb_noun pattern, which is consistent and descriptive.

Tool Count3/5

One tool feels thin for a general-purpose MCP server, but it is appropriately focused for a specialized read-only Q&A assistant. The count is borderline but acceptable.

Completeness5/5

The tool covers the entire stated domain of asking questions about a codebase, with session state, branch selection, and error handling. No obvious gaps for its intended purpose.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mvagnon/opencode-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server