alpacon-mcp: Instructions file for Codex

AGENTS.md

alpacon-mcp AGENTS.md is an instructions file for Codex, OpenCode from alpacax/alpacon-mcp. It costs 3,649 tokens per session, scanned A, original, MIT.

Repository instructions for an MCP server that gives AI assistants access to Alpacon's zero-trust infrastructure over HTTP. They define allowed access methods, identifiers and human approval rules.

In plain words
What is it for?
Use them when developing or operating this Alpacon integration, especially for server lookup, failed requests and pending approvals.
Why use it?
They prevent the agent from using forbidden shell or SSH fallbacks, sending the wrong server identifier or bypassing human approval.

Instructions file for CodexOpenCode

Written for Codex and OpenCode: the file is AGENTS.md. Also seen: mentions AGENTS.md.

This is alpacax/alpacon-mcp's own configuration. It tells Codex and OpenCode how to work on alpacon-mcp itself, so it is not a mod to install elsewhere. Copy it as a starting point and replace the rules that are about this project. Everything alpacon-mcp configures →

Reuse

Borrowing it

Nothing to install: this file belongs to alpacax/alpacon-mcp. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.

Copy the file
curl -O https://raw.githubusercontent.com/alpacax/alpacon-mcp/main/AGENTS.md
Clone the repo
git clone --depth 1 https://github.com/alpacax/alpacon-mcp

Made for: Codex, OpenCode.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for alpacon-mcp AGENTS.md

README.md
[![agentmods](https://agentmods.dev/badge/instructions/alpacax/alpacon-mcp/agents-md/github.svg)](https://agentmods.dev/instructions/alpacax/alpacon-mcp/agents-md)
Your own site
<a href="https://agentmods.dev/instructions/alpacax/alpacon-mcp/agents-md"><img src="https://agentmods.dev/badge/instructions/alpacax/alpacon-mcp/agents-md/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for alpacon-mcp AGENTS.md

Your own site · 80×15
<a href="https://agentmods.dev/instructions/alpacax/alpacon-mcp/agents-md"><img src="https://agentmods.dev/badge/instructions/alpacax/alpacon-mcp/agents-md.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 3,649 This file is loaded in full into every session.
When invoked 3,649 The same file — it is already loaded in full.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.03649 $0.03649
Opus 5.5 $0.01460 $0.01460
Sonnet 5.5 $0.00730 $0.00730
Haiku 4.5 $0.00365 $0.00365

Measured 2d ago against content hash 78c8ecf99eeb, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

alpacon-mcp AGENTS.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

AGENTS.md · 229 lines

How it starts

The opening of the file, as written. The whole thing — 229 lines — stays where its author put it; the contents beside it link to each section on GitHub.

AGENTS.md

Alpacon MCP Server: an MCP server that bridges Alpacon's zero-trust infrastructure access to AI assistants over plain HTTP. No alpacon CLI, no subprocess, no external binaries in the runtime path, except that a local stdio server raises desktop notifications through the platform tool, best effort.

Red lines

  • Reach Alpacon only through mcp__alpacon__* tools. Never the alpacon CLI, never ssh, never a shell fallback when an MCP call fails. On failure: report the exact error, propose another MCP route, ask for the missing auth/config. This constrains how you talk to Alpacon—it does not restrict ordinary local work in this repo (pytest, git, uv).
  • server_id is always a UUID, never a server name. list_servers maps a name to its UUID. A name fails at the input validator, before the API call.
  • Approve/reject is human-only. No approve_request tool exists and the server answers agent/token channels with 403. When a tool returns status="pending_approval", surface it to a human who decides out-of-band in the web console or Slack, then retry.

Development commands

Python 3.12 or higher and uv >=0.13,<0.14 are required (pyproject.toml).

uv venv && source .venv/bin/activate
uv sync --extra dev         # runtime + dev dependencies

python main.py              # stdio transport (default MCP mode)
python main_http.py         # streamable-http; needs AUTH0_ALPACON_* configured

pytest                      # test suite
ruff check .                # lint
ruff format --check .       # formatting check
mypy .                      # type check
python -c "from server import mcp; print('ok')"   # import smoke check

Non-obvious invariants

The legacy Auth0 environment variable names still work as fallbacks and will be removed in a later release; see docs/configuration.md for the mapping.

Things the code will not tell you at a glance:

  • Regions are ap1 and us1 only (the internal dev is not a served region), except where ALPACON_MCP_ENV is staging or dev: there the JWT names dev, so tool schemas accept it too. The setting is read when the tools are decorated, at import. An omitted region is resolved from the JWT in remote mode and from token.json in local mode, then validated; resolution fails when no unique region can be determined.
  • Toolset selection crosses module boundaries. --toolsets / ALPACON_MCP_TOOLSETS gates imports, and registration is an import-time side effect. alpacon://servers/.../overview is backed by system_info_tools, so --toolsets servers alone silently drops it. Remote mode is gated on ALPACON_MCP_AUTH_ENABLED=true, not on the transport name, and ignores the setting entirely.
  • @mcp_tool_handler owns validation, token injection, error shape, and logging. Never write a try/except around an HTTP call in a tool. region, workspace, server_id, server_ids, servers, session_id, limit, and page_size are validated before the local API token lookup; remote mode reads the JWT after workspace validation and before region resolution and the remaining field checks. Other explicitly declared *_id arguments are checked as single path segments, except work_session_id, whose padding is stripped separately. File paths are not checked—call validate_file_path() inline in any tool taking a path. requires_workspace=False is for a tool that answers before a workspace is known: it drops the workspace checks, the workspace-keyed region resolution, the JWT workspace authorization, and the stdio token injection. list_workspaces is the only tool using it. Whatever a tool declares, the decorator publishes region as ap1, us1 or null (plus dev on a staging or dev deployment), so the SDK refuses anything else, '' included. The decorator also rewrites the published signature, dropping the **kwargs it injects the token into: the SDK reads that catch-all as an ordinary required field and would publish it to clients. Two rules follow: a tool must declare **kwargs or decoration raises, and no tool may forward its own **kwargs on to another tool, because by then it holds the resolved credential. with_logging binds the published signature strictly, so a forwarded catch-all raises a TypeError—but only while INFO is enabled, since the bind sits inside that guard. TestCatchAllForwarding pins the direct form—a call handing its own **kwargs straight to another tool—at any log level; an indirect forward, such as **{**kwargs} or a single token=kwargs.get('token'), is still caught by the bind alone and so only at INFO. health_check sits outside the decorator entirely because it must answer before any JWT exists, and borrows @with_error_handling alone for the error shape.
  • AlpaconHTTPClient never caches a response, deliberately. Every read worth caching—the server list, process info, IAM users and groups—comes back filtered by the calling token's permissions, and nothing in this process sees a grant revoked in the web console, in Slack, or by another MCP process. Do not reintroduce a response cache in the shared client: a hit would answer with access the caller has lost. The auth-path caches stay: the JWKS keys in utils/auth.py and the renamed-slug lookup in utils/workspace_resolver.py are not permission-filtered tool data.
  • AlpaconHTTPClient never resends a POST or PATCH that may have reached the server (#392). Only the errors in _NEVER_SENT_ERRORS, raised before the request goes out, and the 5xx codes in _REJECTED_BEFORE_VIEW_CODES retry them; a read timeout, a broken connection or any other 5xx returns at once with outcome_unknown: true, and such an error gets no recovery hints. The upstream API takes no idempotency key, so a resent /api/events/commands/ POST runs the command twice.
  • The WorkSession gate applies to OAuth/browser callers only. Static API and service tokens bypass it, so a flow that works in stdio mode can be blocked in remote mode. ALPACON_WORK_SESSION supplies a default session id; an explicit work_session_id argument wins.
  • API token tools reject static API tokens. List/get receive an upstream 403 for source='api' tokens. Create/update/delete/duplicate/rotate use @require_jwt_auth and return a local error for non-JWT tokens before any HTTP call. The scopes and presets catalogs are exempt.
  • MFA re-authentication exists only in remote/streamable-http mode, with a 60-second cooldown against re-auth loops.
  • A remote auth_mfa_required answers in the tool result, not as a 403. _handle_upstream_401 records the step-up in utils/mfa_step_up.py's per-call holder and raises MfaStepUpRequired, never writing to request_signal (any entry there replaces the response with a re-auth challenge). The outermost with_error_handling returns status="mfa_required" with Alpacon's mfa_url, even when a fan-out tool swallowed the exception; a tool that is not read-only and returned normally keeps its result as partial_result (it may hold no successful part), and the message asks for a retry of the refused parts only. A tool whose refusal propagated after a POST or PATCH of the same call succeeded lists those requests in already_sent and never asks for the whole call again; one with no such request does. A read-only tool always asks for the whole call again. Once recorded, every later AlpaconHTTPClient.request the tool makes raises before sending (the mfa_url fetch runs after the holder is released), so a refusal is not followed by more side effects. There is no MFA pre-check: Alpacon decides. auth_token_mfa_missing keeps the 403 re-login.
  • A 2026-07-28 request declaring elicitation.url gets the whole-retry mfa_required as an InputRequiredResult (#427). The outermost with_error_handling builds it, so a tool calling a tool still gets the link. The retry's requestState and inputResponses reach it through utils/client_surfaces.py's bind_tool_call_round, and it answers with a freshly fetched link, without calling the tool, until Alpacon's completion poll stops saying MFA is not done; the link's ticket redeems once, so a sealed one is never reused. The requestState is sealed under a grant-secret key so any replica opens it, or per process when no grant or client secret is set.
  • A client that renders MCP Apps is pointed at show_mfa (tools/mfa_tools.py, remote mode only, #427). Its mfa_required message names the tool and still carries mfa_url; show_mfa puts its own fresh link only in result _meta, never in the text the model reads; a client of unknown support gets it in both, since its host may render the panel. Apps support means the io.modelcontextprotocol/ui extension lists text/html;profile=mcp-app, and hide_ui_tools (utils/ui_tools.py) drops every _meta.ui tool from tools/list for a client that declares capabilities without it.
  • The code and refresh token a remote client holds are sealed by this server, carrying the device id minted for that grant. Rotating ALPACON_MCP_GRANT_SECRET (or AUTH0_ALPACON_LOGIN_CLIENT_SECRET, which it is derived from by default) logs every remote session out.
  • A remote access token may not be an Auth0 JWT. With ALPACON_MCP_REMOTE_LEDGER=true, /oauth/token wraps a command pre-approval ledger token into an encrypted amcpl1. value (utils/ledger_grant.py), and Auth0TokenVerifier unwraps it before verifying, so AccessToken.token is always the bare JWT. That credential is the only place a remote ledger token lives; never cache one in the process.
  • Desktop notifications fire only inside server.run()'s stdio run. utils/local_signal.py runs the OS notifier on the MCP server's own host, so streamable-http and the hosted mcp.alpacon.io (including through mcp-remote or the alpacon plugin) never notify. A stdio server in a container or launched over SSH attempts delivery on that host, not on the user's desktop. Never enable stdio_transport() outside that run; a remote equivalent belongs in a client-side hook.
  • Transport settings live at the entry point, not on the constructor. SDK 2.x takes host, json_response and stateless_http on mcp.streamable_http_app(), so create_streamable_http_app(host=...) carries them. host decides DNS rebinding protection—the SDK enables it for loopback addresses only—and must be the address uvicorn actually binds, or a deployment on 0.0.0.0 rejects its own public Host header with a 421.
  • server.run() refuses streamable-http. It serves stdio only; main_http.py composes that transport itself, wrapping create_streamable_http_app() in UpstreamAuthErrorMiddleware. An app built through any other path is unguarded—no 401 is ever turned into a re-auth challenge.
  • The re-auth signal is a per-request mutable object in a ContextVar. The middleware plants an empty dict (utils/request_signal.py) and the tool handler mutates it; the handler runs in a task the transport spawned, so rebinding the ContextVar there never reaches the middleware. Only a JWT-carrying request ever signals, and UpstreamAuthError does not cross the ASGI boundary: the SDK turns a handler exception into a wire response.
  • The agent's clientInfo travels the other way, so a plain ContextVar works. utils/declared_agent.py binds it in an SDK ServerMiddleware, which wraps the handler call, and http_client forwards it as two X-Alpacon-Declared-Agent-* headers. It is self-reported, and the server composes and sanitizes it. A stateless streamable-http server never sees a pre-2026 client's handshake at tool time, so nothing is sent there (#317). Over stdio only (prepare() turns it on), a request whose clientInfo names no agent is declared from the CLI's environment markers instead (utils/agent_environment.py).

Read the full file on GitHub · 229 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 2d ago Changed · +8 lines · +143 tokens per session 78c8ecf99eeb
  2. 3d ago Changed · +1 lines · +146 tokens per session cc97afc0294a
  3. 5d ago First seen · 220 lines · 3,360 tokens per session scan A 217b6259977e

Subscribe to this mod's changes

alpacon-mcp AGENTS.md is an instructions file published in the GitHub repository alpacax/alpacon-mcp (1 stars, last pushed yesterday), licensed MIT. It adds 3,649 tokens to every session, about $0.0146 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-11-03.

Related

alpacon-mcp AGENTS.md compared with instructions from other repositories

alpacon-mcp AGENTS.md next to 6 instructions from other repositories
ModTypeStarsLast pushLicenceScanTokensWorks with
alpacon-mcp AGENTS.mdalpacax/alpacon-mcpInstructions file1yesterdayMITA3,649Codex, OpenCode
vibe-coding-prompt-template backend.instructions.mdKhazP/vibe-coding-prompt-templateInstructions file3.2k1mo agoMITA139GitHub Copilot
plan-forge naming.instructions.mdsrnichols/plan-forgeInstructions file63d agoMITA1,453GitHub Copilot
vscode buildNext.instructions.mdmicrosoft/vscodeInstructions file195ktodayMITA9,719GitHub Copilot
vscode oss-third-party-notices.instructions.mdmicrosoft/vscodeInstructions file195ktodayMITA5,516GitHub Copilot
next.js AGENTS.mdvercel/next.jsInstructions file143kyesterdayMITA7,461Codex, OpenCode
langchain AGENTS.mdlangchain-ai/langchainInstructions file149ktodayMITA4,680Codex, OpenCode