GLM-5.2 Zread MCP: When Repository Context Goes Stale
Independent research — not an official Z.ai publication.Identity and provider disclosure
Original repository trust-boundary diagram. The sanitized evidence image below is rendered from the archived live result.
A coding agent can lose minutes opening GitHub pages, scanning a tree and copying files into context. Z.ai’s Zread MCP compresses those steps into repository search, tree inspection and file reading. That makes it adjacent to web retrieval, but not interchangeable with it: repository indexing has a branch and freshness problem that ordinary page reading does not solve for you.
The critical question is therefore not only “did the MCP connect?” It is “did it return the current file, did the requested operation succeed semantically, and what may the model do next?” We tested those boundaries with a digest-pinned, non-root Docker probe on July 29, 2026. The target was Z.ai’s own public GLM repository so its current README gave us release-specific controls rather than subjective answer grading.
Navigate the GLM-5.2 Zread test
Section titled “Navigate the GLM-5.2 Zread test”- Give Zread one job
- Inspect the ten-request run
- Copy an OpenCode configuration
- Prove the tool can run
- Read the live MCP contract
- Gate repository freshness
- Detect semantic failures
- Bound GLM-5.2 ingestion
- Separate quotas and billing
- Constrain the repository trust boundary
- Troubleshoot by failed contract
- Promote only with acceptance evidence
- Resolve operational questions
- Review data and sources
Give Zread one repository job
Section titled “Give Zread one repository job”Use Zread after the application knows a public GitHub owner/repo and wants repository-specific context. Keep the surrounding products separate:
| Product surface | Starting input | Current documented access | Endpoint | Model ID in this object? |
|---|---|---|---|---|
| Zread Remote MCP | Public owner/repo, query or relative file |
GLM Coding Plan | https://api.z.ai/api/mcp/zread/mcp |
No |
| Web Search | A web query | General API, Chat tool or Coding Plan MCP | Route-dependent | Only in Chat |
| Web Reader | A selected URL | General Reader API or Coding Plan MCP | Route-dependent | No |
| GLM-5.2 Chat | Validated text and instructions | Coding Plan or pay-as-you-go model route | Route-dependent | Yes: glm-5.2 |
The dedicated Z.ai Zread guide calls it an exclusive Coding Plan server and documents only public, supported repositories. It does not publish a pay-as-you-go Zread endpoint. A separate metered GLM-5.2 request can consume validated output, but that does not turn the MCP call into general API traffic.
Use GLM-5.2 Web Search when the agent does not know the source URL. Use the Web Reader test for a chosen documentation page. Use Zread when the unit of work is a repository tree, repository documentation or a specific file. For a custom function that your own application executes, follow the complete tool-calling loop instead.
Inspect the ten-request wire run
Section titled “Inspect the ten-request wire run”The final probe made one current-source GET, seven MCP exchanges and two GLM-5.2 Chat Completions. All ten observed statuses were 200:
| Observation | HTTP | Client time | Measured result |
|---|---|---|---|
| GitHub raw README control | 200 | 0.717 s | 11,776 characters; 104 lines; four of four current markers |
MCP initialize |
200 | 0.735 s | Protocol 2024-11-05; server zread-server |
| Initialized notification | 200 | 0.653 s | Session accepted |
MCP tools/list |
200 | 0.580 s | Three tool schemas |
get_repo_structure |
200 | 1.702 s | 577 characters; 23 lines |
read_file README.md |
200 | 2.131 s | 10,219 characters; 140 lines |
search_doc |
200 | 3.274 s | 5,813 characters; 186 lines |
| Missing-file control | 200 | 1.917 s | Business error 1015 in text; isError: false |
| GLM-5.2 over Zread text | 200 | 2.704 s | Valid JSON; 3,093 total tokens |
| GLM-5.2 over GitHub control | 200 | 2.264 s | Valid JSON; 3,600 total tokens |
Actual evidence view generated from the sanitized result archive. It is not a Z.ai dashboard and contains no credential, Authorization header, response ID, MCP session value, cookie or model reasoning.
This is not a latency benchmark. The rows perform different work, and each time is one client-side observation rather than a percentile, service-level objective or availability claim. The useful evidence is contractual: connection, schema discovery, all three tool shapes, returned content, one controlled failure and source-specific validation.
Connect OpenCode without committing the key
Section titled “Connect OpenCode without committing the key”OpenCode’s current Remote MCP documentation supports environment expansion inside headers. Put the Coding Plan key in the shell or your secret manager:
export ZHIPU_API_KEY="your-coding-plan-key"test -n "$ZHIPU_API_KEY" && echo "ZHIPU_API_KEY is set"Then merge this mcp block into the project’s opencode.json:
{ "$schema": "https://opencode.ai/config.json", "model": "zai-coding-plan/glm-5.2", "mcp": { "zread": { "type": "remote", "url": "https://api.z.ai/api/mcp/zread/mcp", "oauth": false, "headers": { "Authorization": "Bearer {env:ZHIPU_API_KEY}" }, "enabled": true, "timeout": 15000 } }}The MCP block has no model field. zai-coding-plan/glm-5.2 selects the agent model elsewhere in OpenCode; zread only adds repository tools. If the current provider IDs, endpoint or key source are unfamiliar, start with the separately tested GLM-5.2 OpenCode setup and then add this MCP block.
The 15-second tool-fetch timeout is an application choice, not a Z.ai guarantee. OpenCode currently documents a five-second default, while our tools/list observation took 0.580 seconds. A bounded increase gives transient setup work room without allowing an indefinite hang. Set a separate longer task timeout for large repository calls rather than using one unlimited timer for every phase.
Do not paste a real key into JSON, a screenshot, a shell history example or a bug report. A placeholder copied literally should fail; that is safer than a tutorial that normalizes committed credentials.
Verify a tool call, not just a config file
Section titled “Verify a tool call, not just a config file”First ask OpenCode to show MCP status:
opencode mcp listA green zread entry proves that the config parsed and tool discovery succeeded. It does not prove the intended repository can be read or that the returned file is current. Run an explicit, checkable task:
Use only the zread MCP.1. Call get_repo_structure for zai-org/GLM-5.2. Call read_file for README.md.3. Report the first Markdown heading and whether the exact strings GLM-5.2, IndexShare, 2.9, and 1M are present.Do not edit files or call a shell.Record the client version, selected model, repository, tool names, status, elapsed time, returned heading and marker result. Configuration screenshots are setup evidence; a completed tool response is integration evidence. A freshness comparison is stronger still.
Our archived test used a client-independent Streamable HTTP MCP sequence
inside Docker rather than treating OpenCode’s UI as the protocol oracle. It
requested MCP 2025-03-26; the server returned 2024-11-05. That negotiation
worked in this run. A future client that drops the older version could fail
even if the same JSON still looks correct.
Treat the live tool schema as a versioned contract
Section titled “Treat the live tool schema as a versioned contract”tools/list returned exactly these shapes:
search_doc(repo_name, query, language?)read_file(repo_name, file_path)get_repo_structure(repo_name, dir_path?)repo_name was required everywhere. query was required for search,
file_path for file reading, and dir_path was optional for structure. All
three schemas set additionalProperties: false. Send zai-org/GLM-5, not a
full GitHub URL, and send repository-relative paths rather than absolute
filesystem paths.
Each of our four tool results put one JSON-encoded string inside the MCP text
item. The probe decoded the outer MCP object, then unwrapped the value only
when a second JSON parse yielded a string. Without that step, a multiline
README appeared as one line full of escaped \n sequences. Do not blindly
parse arbitrary objects as text: accept the documented content type, cap the
body and make any compatibility unwrap narrowly typed and observable.
Schemas and response shapes can change independently of model weights. Keep a small canary that records server name, negotiated protocol, tool names, required fields and response shape. Fail closed if a formerly read-only tool becomes write-capable or the client introduces automatic execution you did not authorize.
Compare an indexed snapshot with the current origin
Section titled “Compare an indexed snapshot with the current origin”The public GLM repository was a useful
control because its current README began with GLM-5.2 & GLM-5.1 & GLM-5.
It named a solid 1M context and IndexShare reuse across every four sparse
attention layers, with a stated 2.9× per-token FLOPs reduction at that
context.
Zread’s read_file result began with GLM-5.1 & GLM-5 and linked to a
/blob/master/README.md source. The comparison was:
| Release marker | Current GitHub README | Zread read_file |
|---|---|---|
GLM-5.2 |
Present | Missing |
IndexShare |
Present | Missing |
2.9 |
Present | Missing |
1M |
Present | Missing |
Across unique nontrivial lines, 35 of the current source’s 64 lines matched exactly, giving 0.5469 source-line recall for this one file comparison. That is not semantic recall and not whole-repository coverage. The result shows one indexed snapshot lagging one current origin on one date; it does not prove every Zread repository is stale.
Turn freshness into a task-specific contract. For release notes, require the release name or commit. For an API migration, require the new endpoint and a version heading. For security work, use the exact advisory or commit as the source of truth. If the marker is absent, fetch the current origin through an approved path or stop for review. Do not ask GLM-5.2 to invent the missing delta.
Detect an application error inside HTTP 200
Section titled “Detect an application error inside HTTP 200”The deliberate read_file call for
__glm52_probe_missing__.md returned:
code: 1015, message: tool execute error,error: `__glm52_probe_missing__.md` does not existTransport status was 200 and MCP result.isError was false. A caller that
checks only those two fields can pass an error string downstream as repository
evidence.
A narrow validator can reject the observed shape while preserving telemetry:
def accept_zread_text(http_status, is_error, text, required_markers=()): if http_status != 200: raise RuntimeError(f"Zread transport failed: HTTP {http_status}") if is_error is True: raise RuntimeError("Zread MCP marked the tool result as an error") if text.startswith("code: 1015") or "tool execute error" in text: raise RuntimeError("Zread returned an application-level tool error") if not text.strip(): raise RuntimeError("Zread returned empty text") missing = [marker for marker in required_markers if marker not in text] if missing: raise RuntimeError(f"Repository freshness markers missing: {missing}") return textThe text match is a fixture for the error we observed, not a complete Z.ai error taxonomy. Preserve sanitized codes, inspect new shapes and prefer a documented structured error field if the server adds one.
Bound untrusted repository data before synthesis
Section titled “Bound untrusted repository data before synthesis”Public code and documentation are external data. They can contain stale instructions, malicious comments or prose that tells an agent to reveal secrets and run commands. The OWASP prompt-injection guidance recommends separating instructions from remote content, validating tool parameters and applying least privilege.
Our probe released at most 24,000 characters inside explicit untrusted-data
delimiters. The first request left thinking at its default and set
max_tokens: 300. It returned 200, consumed all 300 completion tokens and
did not yield parseable JSON. The corrected controls made output behavior
explicit:
{ "model": "glm-5.2", "thinking": { "type": "disabled" }, "max_tokens": 500, "response_format": { "type": "json_object" }}Both corrected calls produced valid JSON. Over the Zread snapshot, GLM-5.2
reported GLM-5, DeepSeek Sparse Attention and null for the current
IndexShare fields. Over the current GitHub control, it reported GLM-5.2,
IndexShare, four shared layers, 2.9 and 1M. The model followed the
supplied evidence; it did not recover facts absent from stale context.
That A/B test is the practical reason to validate retrieval before synthesis. If a reasoning-heavy task needs thinking, allocate a sufficient output budget and validate the final structured object. See the GLM-5.2 reasoning-effort map for the difference between selecting a reasoning path and merely capping generation.
Separate Coding Plan MCP quota from model tokens
Section titled “Separate Coding Plan MCP quota from model tokens”The current Coding Plan overview says Zread, Web Search and Web Reader share one monthly MCP pool:
| Plan | Combined Search + Reader + Zread calls |
|---|---|
| Lite | 100/month |
| Pro | 1,000/month |
| Max | 4,000/month |
Those calls are separate from the five-hour and weekly model prompt quotas.
The overview listed Coding Plan from $18/month when checked, while model
multipliers and promotions varied by time. Recheck the live terms rather than
embedding those numbers in an annual budget.
The Coding Plan FAQ says exhausted supported
plan quota does not spill into general API balance. The current public
pricing table listed GLM-5.2 at
$1.40/M input and $4.40/M output, but it did not publish a pay-as-you-go
Zread price. Our two final model extractions calculate to $0.0097662 in
model tokens; that figure excludes the subscription and MCP pool.
For the broader choice, compare Coding Plan, pay-as-you-go API and self-hosting and model token scenarios in the GLM-5.2 cost calculator. Do not use either page to fill in an unpublished Zread per-call price.
Keep read-only retrieval from becoming unbounded agency
Section titled “Keep read-only retrieval from becoming unbounded agency”The official MCP security practices stress server trust, explicit consent and least privilege. Zread’s three observed tools are read-oriented, but their content enters an agent that may also possess shell, file-write, browser or deployment tools. A malicious README can therefore influence a higher-privilege next action.
Use layered controls:
- allowlist repository owners or exact repositories after validating the
owner/reposyntax; - reject absolute paths, backslashes, nulls and
.or..traversal segments before a file request; - cap returned bytes, lines and tool calls per task;
- require a release marker, commit or direct-origin check when freshness affects the answer;
- wrap tool output as untrusted data and keep trusted instructions outside that boundary;
- require human approval before writes, credential access, package installation, publication or deployment;
- log sanitized tool name, arguments, timing, content hash and validation result—not keys, session values or full private context.
Our syntax fixture intentionally accepted localhost/repo as a valid string
shape but labelled it as still needing a policy allowlist. Syntax is not
authorization. Likewise, “public repository” does not mean “safe
instructions.”
Troubleshoot Zread by the contract that failed
Section titled “Troubleshoot Zread by the contract that failed”| Symptom | Check first | Avoid concluding |
|---|---|---|
| 401 or invalid token | Coding Plan key, activation, header format, entitlement and nonempty env expansion | The repository is unsupported |
| MCP appears but has no tools | tools/list, client timeout, negotiated protocol and current server URL |
The JSON file alone proves connectivity |
| Repository access fails | Exact owner/repo, public visibility and support on zread.ai |
Every public repository is indexed |
| File “succeeds” with error prose | HTTP, isError, returned business code and nonempty-content contract |
HTTP 200 means the file exists |
| Release details are old | Current default-branch file, commit/release marker and Zread result hash | GLM-5.2 will infer the missing update |
| Multiline content looks escaped | Whether the text item contains one JSON-encoded string layer | Backslash sequences are real source lines |
| Structured model output truncates | Thinking mode, output cap, finish reason and JSON parse | Raising context alone fixes output budgeting |
| Goose setup is unclear | Current Z.ai client section and linked issue | One contradictory documentation line settles support |
The last row matters because the dedicated Zread page currently lists Goose among supported clients and later says it is not supported. Treat that as a documentation conflict, check the linked issue and perform a live tool call before adopting it. Do not silently generalize our protocol test into a client-support guarantee.
If the failure occurs only in a large project, retry from an empty diagnostic directory with the minimal config and one public repository. OpenCode merges configuration sources; a project override can replace the header, timeout or MCP block you thought you were testing.
Promote Zread only after an acceptance sequence
Section titled “Promote Zread only after an acceptance sequence”Use a sequence that proves each boundary:
- Record the coding client version, selected
glm-5.2route and current first-party documentation date. - Confirm
opencode mcp listdiscovers exactly the expected read tools. - Call
get_repo_structurefor one allowlisted public repository. - Call
read_filefor a known file and reject empty, error-shaped or oversized output. - Compare a release marker, commit or hash with the current origin when the task needs current facts.
- Send only the bounded, validated content to GLM-5.2 as untrusted data.
- Validate the model’s schema and source claims before any consequential tool action.
- Monitor transport, MCP-envelope, application-error, freshness and quota failures as separate metrics.
The reader-facing JSON preserves the tool schemas, timings, hashes, marker comparison, missing-file result, model answers, token arithmetic and local guard fixtures. The repository bundle adds the standard-library probe, pinned container runner, first failed attempt, visual sources and limitations.
Answers to practical Zread questions
Section titled “Answers to practical Zread questions”Does Zread MCP use the glm-5.2 model ID?
Section titled “Does Zread MCP use the glm-5.2 model ID?”No model ID appears in the MCP server object. Zread exposes repository tools.
Select zai-coding-plan/glm-5.2 in OpenCode’s model configuration; the MCP
endpoint remains https://api.z.ai/api/mcp/zread/mcp.
Can a pay-as-you-go API key call Zread?
Section titled “Can a pay-as-you-go API key call Zread?”The current first-party page describes Zread as exclusive to GLM Coding Plan users and does not document a general metered Zread route. A pay-as-you-go key can fund a separate GLM-5.2 model request after your application validates content.
Does the stale README make Zread unusable?
Section titled “Does the stale README make Zread unusable?”No. Structure discovery and broad repository orientation can remain useful. The observation means release-sensitive facts need an origin freshness check. It is one repository, file, account and date—not a global defect rate.
Can Zread read private repositories?
Section titled “Can Zread read private repositories?”The current troubleshooting guide says to confirm that the repository is open source/public and supported. Do not send private repository identifiers or assume private access without a separate first-party product contract.
Why did a missing file return HTTP 200?
Section titled “Why did a missing file return HTTP 200?”The JSON-RPC exchange itself completed, while the returned text carried application error 1015. Validate transport, MCP envelope and the application-level result separately.
Is search_doc guaranteed to be current?
Section titled “Is search_doc guaranteed to be current?”No freshness SLA was found in the checked documentation. Our search result also omitted three current GLM-5.2 markers. Require a date, release, commit or direct-origin control when currency changes the decision.
Evidence ledger and checked sources
Section titled “Evidence ledger and checked sources”- Sanitized Zread MCP test data — live schemas, timing, hashes, marker comparison, semantic error, two model controls and local guards.
- Z.ai Zread MCP — product boundary, endpoint, three tools, client examples and repository troubleshooting.
- Z.ai Coding Plan overview — supported models, starting price, model quotas and shared Search/Reader/Zread MCP pools.
- Z.ai Coding Plan FAQ — quota non-spillover and current wording that lags the newer Zread-specific documentation.
- Z.ai GLM-5.2 pricing — dated model-token rates and the absence of a visible metered Zread line.
- OpenCode Remote MCP servers — remote configuration, environment-backed headers, OAuth opt-out, status command and timeout.
- Official GLM repository — current README control and release-specific markers.
- MCP security best practices — server trust, consent and least-privilege guidance.
- OWASP prompt-injection prevention — remote-content, tool-validation and output-control guidance.
- AI HOT: Gemini Managed Agents, Kimi Linear, and Perplexity Personal Computer — reviewed discovery leads for this operation; none supplied factual evidence for this Zread article.
Evidence date: July 29, 2026 (Asia/Hong_Kong). Recheck endpoint, client support, quotas, plan pricing, model multipliers and repository index state before production use.
