mcp-oauth-triage – skill Agent & Tự động hóa cho agent AI
Chẩn đoán vì sao một MCP connector trước đây xác thực được nay lại lỗi: phân loại lỗi thành envelope, expiry, rotation clobber, binding hoặc poisoned cache trước khi sửa code. Dùng khi token exchange thành công nhưng tool call trả 401, khi connector âm thầm suy giảm sau khi refresh, khi thiết lập đa tài khoản trả về an
Cài skill mcp-oauth-triage bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/mcp-oauth-triage-5d242.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /mcp-oauth-triage – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/mcp-oauth-triage-5d242.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $mcp-oauth-triage – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/mcp-oauth-triage-5d242.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /mcp-oauth-triage – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/mcp-oauth-triage-5d242.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /mcp-oauth-triage – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
MCP OAuth Triage
Tier: POWERFUL · Category: Engineering · Domain: AI / Auth / Connectors
Overview
An OAuth-backed MCP connector rarely fails at the exchange. It fails somewhere between storing what the
exchange returned and reading it back on the next call, so the visible symptom is a wall of 401s while
every dashboard says the connection is healthy.
The cost of guessing is high because five common faults share one symptom and need opposite fixes.
Rotating a client secret does nothing when the real fault is a writer and a reader disagreeing about
which key holds the token. Re-authenticating cures a poisoned auth cache for a day and hides the actual
defect. This skill exists to stop that guessing: collect three artifacts, run one classifier, fix the
class you actually have.
Use it before touching code, and again before declaring the fix done.
When to Use
- A connector that authenticated yesterday returns 401 or 403 today with no configuration change.
- The token endpoint returns 200, but the first tool call after a refresh fails.
- Re-authenticating fixes the symptom, and the failure returns within one token lifetime.
- A multi-account install returns data belonging to the wrong account.
- A "needs auth" state persists after a successful login.
- A refresh loop hammers the token endpoint (429s, rotation churn) while the connector stays down.
Do not use this skill for first-time setup that never worked. That is a scopes, redirect URI, or client
registration problem, and it belongs with mcp-server-builder. This skill assumes a working state
existed and was lost.
Features
One classifier covers five fault classes. Each row names the discriminator that separates it from its
neighbours, because the fixes are destructive to each other.
| Detector | Fires on | Confirmed by |
|---|---|---|
| Envelope check | token stored one level below where the reader looks | reader key list vs record key list |
| Expiry check | fractional TTL, zero sentinel, seconds/milliseconds confusion | failure gap equals token lifetime |
| Rotation check | more than one exchange per credential per window | stored refresh token vs last exchange result |
| Binding check | audience, issuer, or account-key mismatch | claims vs the surface's protected-resource metadata |
| Cache check | auth marker that survives a successful login | clearing the marker alone restores service |
The classifier also reports what it could not check, so a clean exit is read as "not proven broken"
rather than "proven working".
Usage
# Classify from a record and a log
python3 scripts/oauth_triage.py --token-file ./token.json --log ./connector.jsonl
# Machine-readable verdict for a ticket or CI
python3 scripts/oauth_triage.py --token-file ./token.json --log ./connector.jsonl --json
# Redact a record before it goes into a ticket or a chat
python3 scripts/oauth_triage.py --token-file ./token.json --redact
# Assert the reader's expectations explicitly
python3 scripts/oauth_triage.py --token-file ./token.json --expect-flat --expect-absolute-expiry| Exit | Meaning |
|---|---|
| 0 | No defect signals found in the supplied artifacts |
| 1 | Suspect findings only, worth a second probe |
| 2 | A defect class is confirmed by the artifacts |
Exit 0 is not a health check. If the symptom is live and the classifier is clean, the artifacts are
wrong, and Step 1 of the workflow is where to go back to.
Workflow
Step 1: Collect three artifacts
| Artifact | What it is | Why |
|---|---|---|
| Token record | the stored JSON the connector reads back, exactly as written | reveals envelope, field types, sentinels |
| Connector log | ordered events with timestamps: exchange, store, load, call, error | reveals order, races, which side failed |
| Timing | how long after a successful call the failure appears | separates expiry semantics from binding faults |
Redact secrets. The classifier needs key names, value types, and timestamps, never the token value.
Step 2: Run the classifier
python3 scripts/oauth_triage.py --token-file ./token.json --log ./connector.jsonl --jsonStep 3: Match the class to its fix
Each class has one cheap confirmation and one fix. Apply the confirmation before the fix, because the
fixes are destructive to each other: rotating credentials while the real fault is a shape mismatch
produces a second, harder incident.
Class A: Envelope mismatch
The exchange returns a nested payload and the reader expects flat keys, or the reverse. The token
exists, the reader cannot see it, and every health check that reads the file directly reports success.
Fix: normalise on write and keep one reader. Do not add fallbacks that probe two shapes, because they
turn a loud failure into a silent one that survives the next refactor.
Class B: Expiry semantics
A TTL is stored in a form the reader misinterprets: fractional expires_in, an expires_at of 0
read as "no expiry" when it means "expired at the epoch", or a relative duration read as an absolute
timestamp.
Fix: store one absolute expiry as an integer, compute it once from the provider response, and treat
zero and missing as expired. Never treat a falsy expiry as permanent.
Class C: Rotation clobber
Two refresh paths run concurrently. The provider rotates the refresh token and invalidates the old one.
The losing path writes its dead token over the winner's, and the next refresh fails permanently.
Fix: one refresher per credential, guarded by a lock, with the store write inside the same critical
section as the exchange. Every other caller waits on that result instead of exchanging again.
Class D: Binding fault
The token is valid, unexpired, correctly stored, and one surface still rejects it: audience or resource
mismatch, issuer mismatch between environments, wrong tenant, or a multi-account install keyed by a
human-readable identifier two accounts share.
Fix: request the audience the surface actually advertises, and key stored credentials on a stable
account identifier rather than an email address or display name.
Class E: Poisoned negative cache
A failed handshake writes a machine-wide or organization-wide "needs authentication" marker. The marker
outlives the failure, so a later successful login does not clear it and the connector stays disabled
while every credential is valid.
Fix: scope the marker to the credential it describes, and clear it on a successful exchange. A negative
cache must never outlive the condition that produced it.
Step 4: Verify with one full round trip
A fix is not verified by a successful login. It is verified by surviving a refresh. Report three facts:
the call succeeded before refresh, it succeeded after refresh, and it succeeded after a second refresh.
Two of three is not a fix.
Examples
Example: rotation clobber, the cheapest possible detection. A connector works, then fails once a
day at roughly the same hour, and re-authenticating fixes it until the next day.
$ python3 scripts/oauth_triage.py --token-file ./token.json --log ./connector.jsonl
primary_class: rotation_clobber
confidence: high
- [high] rotation_clobber: 2 exchange(s) within 60s of the previous one; concurrent refreshers rotate each other's token
- [high] rotation_clobber: stored refresh_token does not match the most recent exchange result (19 vs 18 chars)
- [medium] rotation_clobber: 1 store event(s) carry no refresh_token payload, so a clobbering writer cannot be distinguished from a correct one
next_probe: Count concurrent refreshers; add a single-flight lock around exchange plus store, then re-check the stored refresh token.
exit_code: 2The record was not corrupt and the credentials were not stale. Two components noticed the same expiry
at the same moment, one of them lost the rotation race, and its write decided which token survived.
Example: envelope mismatch that survived a dependency upgrade. A connector worked for months and
broke on a library upgrade that changed the serialiser. The stored file still held a valid token; the
only change was a wrapper key.
$ python3 scripts/oauth_triage.py --token-file ./token.json --expect-flat
primary_class: envelope_mismatch
confidence: high
- [high] envelope_mismatch: token sits under nested key 'tokens'; a flat reader sees no access_token
exit_code: 2Example: a clean record. Exit 0 means the artifacts support no defect. It does not mean the
connector is healthy, and the correct next move is to collect a log or a failing call, not to close the
ticket.
Architecture
The classifier is deliberately three stages, and each stage is testable in isolation.
record + log -> detectors (5) -> findings (class, severity, evidence)
|
v
verdict (primary class, confidence)
… (nội dung đầy đủ có trong gói tải về)
Skill liên quan
- crypto-bd-agent – Mẫu tham chiếu (từ báo cáo upstream, chưa được xác minh độc lập tại đây) để xây dựng AI…
- session-guard – Dùng khi làm tác vụ nhiều bước phức tạp, khi phiên làm việc kéo dài (40+ lần gọi tool)…
- mcp-server-builder – Thiết kế và triển khai MCP (Model Context Protocol) server sẵn sàng production từ hợp…
- cursor-delegate – Giao tác vụ lập trình cho Cursor Agent CLI (`cursor-agent`) chỉ khi người dùng yêu cầu…
- scrapling – Thu thập dữ liệu website với trình duyệt tàng hình và vượt Cloudflare.
- memory-engineering – Dùng khi thiết kế, rà soát hoặc chi trả cho hệ thống bộ nhớ của agent — thêm bộ nhớ cho…
- memory-review – Phân tích auto-memory để tìm ứng viên thăng cấp, mục cũ, cơ hội hợp nhất và chỉ số sức…
- memory-status – Bảng điều khiển sức khỏe bộ nhớ: số dòng, file chủ đề, dung lượng, mục cũ và khuyến…