You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Generate a copy-pasteable connection guide per instance, exposed via MCP tool and console UI #772
PROBLEM — There is no way today to get a ready-made briefing for how to connect to and work with one specific agent instance over MCP. A caller starting a fresh Claude or Codex session against a known instance has to rediscover, by trial and error, which tools that instance exposes, the exact tool and field names (list_instance_tools then call_instance_tool), and any instance-specific conventions. This session hit exactly that: repeated guessed tool names and guessed field names before landing on the right call shape.
CHECKED AND CONFIRMED MISSING — get_instance_instructions exists but returned an empty string for this instance (a185b1db-c560-456d-9522-f7792bd95cca) — it appears to hold a free-form custom instructions field, not a generated guide, and it is unset here. get_instance_operator_manual exists but the call did not complete. Neither is confirmed to already deliver the capability described below; if either turns out to already be intended for this, the fix may be to populate/generate it rather than add something new — please check the existing intent of both before building new plumbing.
PROPOSAL — A generated, per-instance connection guide containing: the instance id, its agent type, its registered repo (if any), the tools it actually exposes (from list_instance_tools), the exact call_instance_tool shape with real examples using its real tool names and field names, and any instance-specific operating notes. This should be:
Available as an MCP tool a caller can invoke to fetch that instance's guide as plain text, suitable for pasting directly into another assistant's system instructions.
Surfaced in the console UI on the instance's own page, with a copy button, so a human can grab it without going through MCP at all.
GOAL — Eliminate the discover-by-guessing loop for a caller who already knows which instance they are targeting, by giving them the exact contract up front instead of deriving it through failed calls.
RELATED — Distinct from #771 (direct per-agent-type tool exposure, which removes the discovery hop programmatically). This issue is about producing a human/assistant-readable reference for the existing discovery contract, useful even if #771 is never built.
Implemented in commit 6da7c9a1 (push to main, auto-deploy).
What shipped
GET /v1/instances/:instanceId/connection-guide (workers/api/src/routes/instances-guide.ts) — returns { guide }, Markdown, owner-scoped via requireOwnedInstance. The renderer is workers/api/src/lib/connection-guide.ts, a pure function over inputs the route has already fetched.
MCP tool get_instance_connection_guide (read scope, always-on) in a new workers/mcp/src/instance-tools/guide.ts. Returns plain text rather than JSON — the whole deliverable is a document meant to be pasted, and a JSON-wrapped one arrives with escaped newlines.
Console panel (store/console/src/components/ConnectionGuide.tsx) on the instance Settings tab, with Refresh and Copy.
The guide contains all six things the issue asked for: instance id, agent type, registered repos, the tools it actually exposes, a worked call_instance_tool example using real tool and field names, and the owner's operating notes. It also reports whether the agent needs a local runner — telling a caller to run pags up for a cloud-only agent is a wrong instruction that costs a debugging session.
On "check the existing intent of both before building new plumbing"
Checked, and the answer is that neither already delivers this — but the second one is closer than the issue could tell.
get_instance_instructions returns config.specialInstructions: the agent's standing orders, injected imperatively on four surfaces. Wrong audience by construction (that asymmetry is what An instance has one instructions box and it is wired to "obey", so guidance for the CALLER driving it has nowhere to live #739 was filed about), and correctly empty on an instance nobody set rules for. The guide echoes it in a section explicitly labelled as instructions to the agent, not to the caller — so a refusal reads as a rule rather than a malfunction.
The manual is included in the guide as "Operating notes from the owner", so the hand-written and the generated halves arrive in one document without being merged into one field.
Four decisions
One source of truth for the tool list. The guide reads instanceToolPolicy + projectToolListing — the same pair GET /v1/instances/:id/tools calls. Enumerating the registry instead would be a second answer to "what may this instance run", and the second answer is the one that drifts (routes/tools.ts:66 records the same finding from the other direction).
Allowed rows only, split by invocableBy.base.ts:52-98 measured the full listing at 61,796–66,189 B against a 64 KiB host limit, 38% of it prose about tools the reader cannot run. Callable-vs-chat-only is separated because a caller told to invoke a chat-only tool gets an error every time. A CONNECTION_GUIDE_MAX_CHARS = 24000 cap truncates with a visible notice rather than letting a host drop the response.
Placeholders are angle-bracketed inside quotes ("repo": "<repo>") — valid JSON a caller can paste, and visibly not a real value. Inventing "owner/name" would be the platform fabricating an argument. A test asserts the rendered block parses.
Two things the guards caught
The route reaches the Durable Object, which I did not expect. instanceToolPolicy calls emailPermitted (lib/instance-tool-policy.ts:402) for the find_confirmation_link permission gate, and that is a /state read. do-seam.contract.test.ts found it; I traced it before recording it, and the table entry says why.
routes/instances.ts size pin raised 1027 → 1031. Any new route module mounted there costs an import and a registrar call, so it was not avoidable by writing less. The work itself went into instances-guide.ts and lib/connection-guide.ts, which is what the pin asks for.
Surface bookkeeping
MCP_SERVER_VERSION 0.1.20 → 0.1.21 · MCP_TOOL_COUNT 149 → 150 · MCP_TOOL_ALWAYS_ON 126 → 127 (MCP_TOOL_GATED unchanged at 23 — ungated on purpose: the discovery problem belongs to every agent type) · TOOL_RISK read entry · MCP_RISK_COUNTS.read 74 → 75 · appended SURFACE_LOCK["0.1.21"]. Version restated in server.json, the served /.well-known manifest and platform-docs/mcp.md; tool-count prose fixed in nine files including all three SKILL.md copies. New OpenAPI operation. The response type is named on both sides (ConnectionGuideResponse) with an Extra<> assertion in types.test.ts, so check-console-types' anonymous-shape count did not grow.
Gates
22 new unit tests. Full suite 10886/10886; pnpm -r typecheck; CI's scoped biome check --error-on-warnings; docs:drift ("No drift"); size:check; mcp:parity; check-surface-lock --require-history; and check-console-types, check-design-tokens, check-migrations, check-bare-catch, check-typecheck-coverage, check-test-isolation, check-doc-citations, check-agents-allowlist, check-qa-config — all green.
Unchanged and still separate. #771 removes the discovery hop programmatically; this renders the existing discovery contract for a human or an assistant to read. Neither depends on the other.
Activity
serge-ivo commentedon Sep 8, 2026
Implemented in commit
6da7c9a1(push to main, auto-deploy).What shipped
GET /v1/instances/:instanceId/connection-guide(workers/api/src/routes/instances-guide.ts) — returns{ guide }, Markdown, owner-scoped viarequireOwnedInstance. The renderer isworkers/api/src/lib/connection-guide.ts, a pure function over inputs the route has already fetched.MCP tool
get_instance_connection_guide(read scope, always-on) in a newworkers/mcp/src/instance-tools/guide.ts. Returns plain text rather than JSON — the whole deliverable is a document meant to be pasted, and a JSON-wrapped one arrives with escaped newlines.Console panel (
store/console/src/components/ConnectionGuide.tsx) on the instance Settings tab, with Refresh and Copy.The guide contains all six things the issue asked for: instance id, agent type, registered repos, the tools it actually exposes, a worked
call_instance_toolexample using real tool and field names, and the owner's operating notes. It also reports whether the agent needs a local runner — telling a caller to runpags upfor a cloud-only agent is a wrong instruction that costs a debugging session.On "check the existing intent of both before building new plumbing"
Checked, and the answer is that neither already delivers this — but the second one is closer than the issue could tell.
get_instance_instructionsreturnsconfig.specialInstructions: the agent's standing orders, injected imperatively on four surfaces. Wrong audience by construction (that asymmetry is what An instance has one instructions box and it is wired to "obey", so guidance for the CALLER driving it has nowhere to live #739 was filed about), and correctly empty on an instance nobody set rules for. The guide echoes it in a section explicitly labelled as instructions to the agent, not to the caller — so a refusal reads as a rule rather than a malfunction.get_instance_operator_manualis a human-authored document. An instance has one instructions box and it is wired to "obey", so guidance for the CALLER driving it has nowhere to live #739 Decision 3 forbids the agent writing it and its body states "Explicitly not built: a generator". So it is not the generated guide this issue wants — but itscontextfield is the same live-facts material, and that half (An instance has one instructions box and it is wired to "obey", so guidance for the CALLER driving it has nowhere to live #739 Slice 3) is still unbuilt:routes/instances-apply.ts:493returns a hardcodedcontext: "". That is the likely reason the call looked incomplete ona185b1db-c560-456d-9522-f7792bd95cca, though I did not reproduce it live and am not claiming it as the cause. Filing a follow-up is worthwhile: the renderer now exists for it.The manual is included in the guide as "Operating notes from the owner", so the hand-written and the generated halves arrive in one document without being merged into one field.
Four decisions
instanceToolPolicy+projectToolListing— the same pairGET /v1/instances/:id/toolscalls. Enumerating the registry instead would be a second answer to "what may this instance run", and the second answer is the one that drifts (routes/tools.ts:66records the same finding from the other direction).invocableBy.base.ts:52-98measured the full listing at 61,796–66,189 B against a 64 KiB host limit, 38% of it prose about tools the reader cannot run. Callable-vs-chat-only is separated because a caller told to invoke a chat-only tool gets an error every time. ACONNECTION_GUIDE_MAX_CHARS = 24000cap truncates with a visible notice rather than letting a host drop the response."repo": "<repo>") — valid JSON a caller can paste, and visibly not a real value. Inventing"owner/name"would be the platform fabricating an argument. A test asserts the rendered block parses.Two things the guards caught
instanceToolPolicycallsemailPermitted(lib/instance-tool-policy.ts:402) for thefind_confirmation_linkpermission gate, and that is a/stateread.do-seam.contract.test.tsfound it; I traced it before recording it, and the table entry says why.routes/instances.tssize pin raised 1027 → 1031. Any new route module mounted there costs an import and a registrar call, so it was not avoidable by writing less. The work itself went intoinstances-guide.tsandlib/connection-guide.ts, which is what the pin asks for.Surface bookkeeping
MCP_SERVER_VERSION0.1.20 → 0.1.21 ·MCP_TOOL_COUNT149 → 150 ·MCP_TOOL_ALWAYS_ON126 → 127 (MCP_TOOL_GATEDunchanged at 23 — ungated on purpose: the discovery problem belongs to every agent type) ·TOOL_RISKread entry ·MCP_RISK_COUNTS.read74 → 75 · appendedSURFACE_LOCK["0.1.21"]. Version restated inserver.json, the served/.well-knownmanifest andplatform-docs/mcp.md; tool-count prose fixed in nine files including all threeSKILL.mdcopies. New OpenAPI operation. The response type is named on both sides (ConnectionGuideResponse) with anExtra<>assertion intypes.test.ts, socheck-console-types' anonymous-shape count did not grow.Gates
22 new unit tests. Full suite 10886/10886;
pnpm -r typecheck; CI's scopedbiome check --error-on-warnings;docs:drift("No drift");size:check;mcp:parity;check-surface-lock --require-history; andcheck-console-types,check-design-tokens,check-migrations,check-bare-catch,check-typecheck-coverage,check-test-isolation,check-doc-citations,check-agents-allowlist,check-qa-config— all green.Relationship to #771
Unchanged and still separate. #771 removes the discovery hop programmatically; this renders the existing discovery contract for a human or an assistant to read. Neither depends on the other.
feat(mcp): a session pinned to one instance at /mcp/i/<id>, publishin…
feat(console): a home-screen shortcut to one instance, and notificati…
feat(instances): the operator manual documents every tool the instanc…