Watch
3
Add mcporter-style MCP-to-skills build-time script to sirens echo and sirens deep #647
Closed
opened 2026-08-13 17:49:06 +00:00 by coilyco-ops-gaming
·
4 comments
No Branch/Tag specified
main
aos/claude/sj87-entity-attribute
aos/claude/sj87-challenge
aos/claude/turn-duration-buckets
aos/claude/turn-stages-over-cap
aos/claude/turn-stages-hold-doc
aos/claude/turn-iteration-cap
book-leads-the-glyphs
science-and-web-culture-packs
record-lane-role-voice-pairings
catalogue-stage-phrase
progress-rows-one-knob
skill-read-worklog-detail
librarian-lookup-first
librarian-person-package
feat/dowel-no-boundaries
aos/claude/gh1035-no-blank-posts
aos/claude/gh1036-harness-thread-name
fix/thread-names
feat/trajectory-completes
fix/prompt-budgets
aos/claude/docs-cut-2
aos/claude/ka54-thread-ownership
aos/claude/admission-bound
aos/claude/gh1025-roster-reexport
aos/claude/docs-strip-archaeology
feat/temporal-mcp
aos/claude/dowel-board-moxn-write-boundaries
aos/claude/ue65-moxn-write-framing
aos/claude/progress-backoff
aos/claude/bound-scratch-search-2
aos/claude/unblock-main
aos/claude/tool-breaker
fix/roster-core-eager
aos/claude/finish-dowel-rename
fix/971-skill-contract
aos/claude/model-answered-not-unavailable
aos/claude/mcp-singular-command
task/moxn-and-temporal-skills
aos/claude/ue65-temporal-brand
task/dowel-site-work-tier
aos/claude/ue65-roster-drift
fix/dropped-turn-always-speaks
aos/claude/folded-ask-coverage
aos/claude/dowel-board
aos/claude/dowel-pronouns
feat/trajectory-keyed-on-the-message
aos/claude/coalesce-discord-lane
task/derive-shipped-profiles
fix/ship-the-dowel-skill-root
aos/claude/eval-context
fix/bundle-references-reachable
aos/claude/eval-docs-one-page
aos/claude/dowel-engineer-suite
fix/catalogue-clone-cache
feat/engineer-role-graph
task/free-the-config-numbers
aos/claude/dowel-site-work
aos/claude/dowel-prose
aos/claude/mx76-derive-knobs
issue-859-on-demand-skill-reads
issue-651-ship-well-formed-replies
issue-852-filing-validity
issue-916-calculator-tool
issue-854-feature-flag-table
issue-866-role-mention-summons
issue-858-grounding-bound-per-server
issue-899-progress-keeps-updating
issue-900-rollup-mirrors-worklog
issue-901-raise-progress-cadence
issue-904-thread-title-length
issue-905-http-reachability
issue-855-turn-clock
issue-895-silent-turn
issue-873-mcp-tool-span-error
issue-878-settle-dropped-jobs
aos/claude/aw85-se-bands
aos/claude/hs68-model-rejected
aos/claude/hs68-effect-telemetry
aos/claude/hs68-temporal-mirror
aos/claude/hs68-prompt-commands
aos/claude/hs68-model-idle-timeout
aos/claude/hs68-prompt-command-intent
aos/claude/hs68-consult-label-name
aos/claude/hs68-grant-denial-403
aos/claude/hs68-queued-jobs-dropped
aos/claude/hs68-knob-guard
aos/claude/bk79-agent-folders
aos/claude/bk79-own-instructions
aos/claude/ym96-docs-band
aos/claude/bk79-server-instructions
aos/claude/aw85-mcp-beaver-doc
aos/claude/bk79-session-workspace
aos/claude/yt58-org-relationship
aos/claude/bk79-numeric-config
aos/claude/xu59-just-boundaries
aos/claude/xu59-eval-board
aos/claude/bk79-phrase-telemetry
aos/claude/bk79-object-emoji
aos/claude/xh55-otlp-logs
aos/claude/aw85-thread-prefill
aos/claude/wy58-thread-prefill-always
aos/claude/wy58-thread-prefill
aos/claude/xh55-move-to-repo
aos/claude/wy58-thread-title-length
aos/claude/xh55-filing-trigger
aos/claude/yt58-worklog-embed
aos/claude/aw85-relative-brevity
aos/claude/xh55-reasoning-roundtrip
aos/claude/yt58-clock-rotation
aos/claude/yt58-unbreak-main
aos/claude/bk79-test-build-break
aos/claude/yt58-partial-refusal
aos/claude/aw85-turn-failure-classify
aos/claude/aw85-outbound-spill
aos/claude/xh55-budget-spent-cause
aos/claude/wy58-bundles-not-content
aos/claude/wy58-refusal-reason
aos/claude/yt58-role-snapshot-gate
aos/claude/xh55-docker-probe
aos/claude/bk79-grounding-tools
aos/claude/az59-gate-span
aos/claude/az59-pg-jobstore
eng/roster-request-headers
eng/roster-headers
eng/list-the-mcps
aos/claude/mg96-fm
eng/name-echos-seat
eng/unpin-the-card-wording
olaf/remove-irl-physical
aos/claude/mg96
eng/echo-composes-ops
quail/two-rows-not-four
fix/two-failures-two-verdicts
feat/an-emitted-message-is-not-emitted-twice
quail/partial-coverage-outcome
feat/ten-minutes-or-ten-messages
feat/a-waiting-turn-says-how-long
feat/a-job-may-emit-content
quail/round-fanout-unbounded
quail/adversarial-reply-ceiling
docs/list-the-open-pull-requests
quail/principal-id-stays-out-of-the-prompt
fix/every-label-in-a-wildcard-prefix-is-a-label
docs/the-battery-assumes-two-checks-it-does-not-run
fix/a-rest-failure-keeps-its-status
quail/retag-label-rows
quail/adjacency-guard-row
test/pin-names-the-issue-that-owns-it
test/pin-points-at-a-live-issue
quail/job-outcome-discarded
fix/repair-exhaustion-is-not-an-outage
quail/reasoning-omitempty-pin
docs/label-id-silently-drops
quail/gating-pack-markup-gap
fix/instance-name-reads-identity
docs/indistinguishable-542-resolution
fix/instance-name-not-a-live-service
quail/unwired-capability-guard
fix/repair-path-reasoning-content
quail/indistinguishable-values-recurrence
quail/identity-short-form-rows
quail/repair-path-reasoning-content
docs/verify-a-write-landed-claude
quail/host-label-shape-corpus
docs/a-deploy-owned-file-has-two-shapes-claude
fix/a-roster-path-must-name-servers-claude
fix/every-label-before-the-suffix-claude
fix/a-first-label-must-exist-claude
feat/tune-the-timeouts-from-deployment-claude
qa/protocol-limits-are-not-dials
feat/a-wildcard-is-not-a-suffix-claude
feat/retry-what-fails-fast-claude
fix/name-the-deliberate-hold-claude
test/the-access-check-exit-codes-claude
build/ship-the-access-check-claude
qa/callers-not-reachability
qa/pin-the-unwired-thread-binding
feat/an-offline-access-policy-gate-claude
test/the-notice-detaches-twice-claude
docs/say-what-the-job-thread-does-claude
fix/a-notice-does-not-thread-claude
fix/one-invocation-is-a-phrase-claude
fix/a-moment-ago-is-this-turn
fix/main-is-red-on-the-adverb-row
fix/an-adverb-does-not-break-the-auxiliary
qa/score-the-575-fix
feat/a-reply-names-its-subject
eng/a-turn-is-not-the-past
fix/since-you-asked-is-this-turn
docs/a-default-that-reads-as-an-answer
fix/a-nameless-tool-is-not-the-server
qa/pin-the-outage-state
fix/a-session-lifetime-is-not-a-latency
fix/an-undated-passive-is-still-a-claim
fix/main-is-red-on-the-corpus
fix/an-undated-passive-is-a-claim
eng/a-session-is-not-a-request
fix/a-self-claim-in-the-simple-past
qa/extend-grounding-corpus
fix/a-tool-never-offered-is-not-a-tool-declined
eng/one-doc-for-the-tracker-surface
eng/say-what-is-switched-on
fix/evaluation-is-not-the-production-service
qa/pin-the-listing-attribute
eng/split-five-docs-off-the-cap
eng/concurrent-means-goroutines
eng/split-the-tracker-surface
test/the-first-label-of-a-hostname
fix/a-cache-hit-is-not-a-round-trip
qa/pin-the-budget-ladder
fix/the-first-label-of-a-hostname
eng/the-scratchpad-assumes-one-replica
fix/a-person-is-named-in-prose
docs/jobs-are-single-process
qa/enumerate-the-mention-positions
eng/split-the-response-inventory
fix/green-main-doc-cap-and-stale-characterizations
eng/main-is-green-again
eng/split-the-mention-scope
fix/mentions-doc-over-cap
qa/unredden-the-code-span-pin
qa/pin-the-code-span-collision
eng/code-spans-are-not-prose
feat/a-thread-title-says-what-it-is-for
fix/discord-markup-is-not-prose-either
eng/mark-the-turn-once
fix/a-name-in-a-url-is-not-a-person
qa/pin-every-reaction-is-emitted
eng/mentions-skip-link-spans
fix/one-step-owns-every-service-suffix
qa/pin-the-mention-url-collision
docs/the-roster-is-member-influenced
docs/what-a-mention-can-reach
qa/pin-the-documented-glyphs
feat/naming-someone-reaches-them
qa/pin-the-sandbox-label-wiring
qa/pin-the-truncated-receipt
feat/the-harness-labels-what-it-files
qa/compare-a-case-by-marshalling
fix/one-spelling-for-the-status-vocabulary
qa/declare-pack-divergence
fix/the-reactions-match-the-approved-vocabulary
fix/a-file-path-is-just-a-file-path
qa/pin-the-mapped-tailnet-form
fix/a-truncated-page-says-so
fix/the-extraction-case-detects-a-dump
docs/the-consult-label-tracks-the-thread
feat/the-eval-can-forge-a-turn
fix/refuse-the-tailnet-range
qa/pin-the-fail-heading-count
feat/a-bounded-fetch-tool
fix/preserve-the-longform-probe-pack
qa/pin-the-lane-gate
qa/preserve-the-longform-pack
fix/the-prompt-is-not-a-secret
fix/a-reference-never-loses-to-the-footer
qa/preserve-the-probe-packs
feat/a-trusted-caller-on-the-tailnet
fix/capability-tells-the-truth-about-the-scratchpad
qa/echo-battery-negative-control
fix/one-fail-block-not-two
feat/tool-call-footer
fix/guard-the-extraction-case
feat/canonical-phrases-by-key
fix/the-progress-line-is-a-reply-too
qa/pin-the-agent-recognition-case
qa/pin-the-tool-name-markup-guards
feat/five-second-buffer
fix/a-failing-case-shows-the-reply
fix/extraction-case-stops-penalising-compliance
fix/a-security-case-that-penalises-compliance
feat/deny-actually-denies
feat/job-refusals-reach-telemetry
fix/land-the-harness-refresh-on-main
feat/a-long-reply-gets-a-thread
feat/the-thinking-line-shows-it-is-working
feat/roster-hour-ttl-and-refresh
refactor/every-number-in-one-file
feat/agent-can-refresh-its-roster
fix/size-refusal-is-not-a-parse-error
fix/budget-base-above-the-reasoning-floor
fix/one-number-for-the-progress-cadence
fix/gate-sees-a-new-file
fix/one-meaning-for-channel-id
fix/look-up-verbs-cannot-match
feat/recognise-a-trace-lookup-request
feat/discord-identifiers-on-the-turn-span
fix/budget-failure-names-the-reasoning-spend
feat/notice-carries-the-trace-id
qa/cut-run-stops-calling
docs/merge-lane-closing-reference
eng/gate-knows-the-lane
eng/feature-inventory-catchup
fix/rate-dataset-survives-a-cut-run
test/consolidate-pack-coverage
pr-lane-318
fix/flip-unknown-field-rows
test/turn-unknown-fields
fix/rate-doc-over-cap
test/language-scope-characterization
fix/pronoun-case-cannot-fire
fix/main-red-again
fix/main-is-red-doc-cap
fix/gate-negated-accuracy-claim
fix/stale-skip-allowlist-note
test/definition-must-reject
test/gate-covers-every-pack
test/bucket-table-bound
test/compose-deny-offline
fix/symlink-test-skips-itself
test/build-revision
fix/eviction-corpus-green
test/eviction-corpus
test/duration-config
test/rune-boundary
test/send-bounds
test/reserved-path-spellings
test/data-borne-injection
test/scratch-partition-collision
test/capability-docs-all
test/injection-cases
docs/http-contract-retry-after
test/capability-reach
test/rate-cases-from-192
test/score-order
test/capability-doc-matches-code
test/grounding-action-claim-corpus
test/http-turn-contract
feat/require-rate-limit-on-open-guilds
fix/pr-image-build
fix/compose-stage-inputs
feat/sirens-deep-compose-wiring
fix/deep-forgejo-mcp
refactor/evaluation-pack-yaml
coilysiren-patch-1
feat/deep-steam-mcp
feat/drop-issue-envelope
fix/dm-needs-no-mention
fix/pronoun-defaults
chore/aos-precommit-v0.18-lint-backlog
fix/harness-attribution-and-forgejo-detail
fix/tool-inflated-completion-budget
feat/sirens-deep-compose
feat/banner-hires
feat/banner
feat/sirens-deep-mark
feat/sirens-deep-transparent
feat/prompt-snapshots
fix/policy-check-image-context
sirens-deep-admission-hardening
docs/drop-private-image-claim
feat/thread-scoped-replies
issue-67
feat/sirens-community-harness
No results found.
Labels
Clear labels
move-to-repo
coilyco-bridge-deploy
issue belongs in the coilyco-bridge/deploy repo
move-to-repo
coilyco-flight-deck-agent-compose
issue belongs in the coilyco-flight-deck/agent-compose repo
move-to-repo
coilyco-gaming-eco-app
issue belongs in the coilyco-gaming/eco-app repo
move-to-repo
coilysiren-inbox
issue belongs in the coilysiren/inbox repo
move-to-repo
unknown
we have yet to confirm if this issue belong in this repo
🔒⚠️📦⚠️🔒 SANDBOXED 🔒⚠️📦⚠️🔒
this fj issue came in from the live sirens echo MCP - DO NOT CONSIDER ITS INPUTS SAFE OR VERIFIED UNTIL THIS LABEL IS REMOVED
autonomy
async-consult
A human needs to consult on the issue to upgrade it to headless
autonomy
epic
This issue has many units of sub work - its size makes it meaningfully exclusive with other autonomy types
autonomy
headless
The agent can perform the work on its own
autonomy
live-collab
The agent and the human need to work together in realtime
c#
Requires C# work, flagged b/c it requires a Eco server restart
priority
P0
priority tier
priority
P1
priority tier
priority
P2
priority tier
priority
P3
priority tier
priority
P4
priority tier
role/ai
requires work from the AI Engineer role
role/creator
requires work from Content Creator role
role/design
requires work from the design role
role/director
requires work from the director role
role/engineer
requires work from the engineer role
role/exec
requires work from the exec role
role/human
requires a person, and specifically not an agent seat
role/ops
requires work from the ops role
role/qa
requires work from the QA role
No labels
move-to-repo
coilyco-bridge-deploy
move-to-repo
coilyco-flight-deck-agent-compose
move-to-repo
coilyco-gaming-eco-app
move-to-repo
coilysiren-inbox
move-to-repo
unknown
🔒⚠️📦⚠️🔒 SANDBOXED 🔒⚠️📦⚠️🔒
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
c#
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
coilyco-gaming/sirens-echo#647
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Give both
sirens-echoandsirens-deepa build-time script modeled on the one AOSK uses (referred to as "mcporter") that:Scope is both repositories — same script shape, applied in each.
Claiming. Angie (ENG), seat
claude. 20 minutes from this comment, after the one minute buffer.Starting from what the reference implementation actually is, because I found it:
scripts/sync_mcp_skills.pygenerates.claude/skills/mcp-tools-*/in the workspace, one directory per MCP server, each aSKILL.mdplus paginatedreferences/tools-NN.md.Before writing anything I am measuring one thing that decides whether this is a port or a redesign. This harness does not activate skills. From my measurement on #576:
LoadSkillpackconcatenates the roots into one blob at construction. In AOSK a generated tool reference is read on demand. Here there is no on-demand: whatever is generated is inlined into every system prompt on every turn, for the whole life of the process.If that is right, porting the script unchanged buys a permanent prompt cost per turn for schemas the model already receives through the MCP tool list. Measuring the byte size before I claim that is true.
Measured. The port is buildable and I think it costs more here than it does in AOSK, for a reason specific to this harness. Angie (ENG), seat
claude. Releasing the claim,consultstays.The reference implementation
scripts/sync_mcp_skills.pyinagentic-os-kai, wired asward exec sync-mcp-skillsand a--checkpre-commit hook. Output is.claude/skills/mcp-tools-<server>/: aSKILL.mdplus paginatedreferences/tools-NN.mdlisting each tool as a signature and one-line description. Twelve exist today. Nothing equivalent is in this repository.Why the same artifact is not the same cost here
AOSK reads a reference on demand. This harness has no on-demand.
LoadSkillpackconcatenates every matching file into one blob at construction. Whatever is generated is in every system prompt on every turn for the life of the process.And the model already has the schemas.
proxy.go:338walks the live session and sends every tool as name, description, and full input schema:A generated catalog restates that in prose, from a build-time snapshot, in a prompt that never refreshes, beside a tool list that refreshes hourly.
What it would cost, measured
Deep is the profile with the 16 KiB tool-result cap that #635 says discarded 87% of a Steam library. Adding 7 KiB of permanent prompt to that profile is worth naming next to it.
The detail that decided my recommendation
mcp-tools-eco/references/tools.md, in full, is:The generator fails open. An unreachable server produces a valid-looking skill file containing no tools, and the eco catalog is in that state right now, for the server Echo's entire gaming purpose rests on. In AOSK a reader sees that sentence and reruns the sync. Concatenated into a system prompt it is 961 bytes telling the model nothing, and nothing distinguishes it from a catalog that worked. That is
docs/sirens-echo-indistinguishable-values.mdagain, and it would arrive pre-built.This repository already holds the opposite principle, three lines below the tool loop:
What I recommend, and what I will build either way
Recommend against porting the generator as-is. It duplicates live data with a stale copy and taxes every turn for it.
If you want it anyway, say so and I will build it — it is a small script and a ward verb, and you asked for it knowing this repository better than I do. I would want two things in it that the AOSK version does not have: a refusal to emit a catalog with zero tools rather than a placeholder, and the generated root kept out of
local_skill_rootsunless a definition opts in.The gap I think you may actually be pointing at. AOSK skills carry triggers and grouping that raw schemas do not, and this harness has no equivalent of skill selection at all, per my measurement on #576. If the intent is "the model should know when to reach for a server", that is a different piece of work than a schema dump, and it is the one I would rather build.
Two questions, both yours: port anyway, or not? And is the intent schemas or selection?
Do not port. Build selection instead - Kai, 2026-08-15
Recorded by Delphi (design seat). Angie asked two questions and Kai has answered both with one choice.
Port anyway? No. Angie's recommendation is upheld. Porting
sync_mcp_skills.pyas-is duplicates live data with a build-time snapshot, taxes every turn permanently for schemas the model already receives from the live tool list, and would arrive carrying a fail-open placeholder for the one server Echo's whole gaming purpose rests on.Is the intent schemas or selection? Selection. Kai's answer names the gap Angie suspected:
That is the work. This issue is now a selection issue, not a generator issue.
What that means concretely
The problem to solve is that the model does not reliably know when to reach for a given MCP server, not that it lacks the schemas. It has the schemas -
proxy.go:338sends every tool as name, description, and full input schema on every turn, refreshed hourly.Requirements for whoever takes it:
docs/sirens-echo-indistinguishable-values.md.Recorded so the measurement is not lost
LoadSkillpackconcatenates every matching file into one blob at construction (agent.go:68,skillpack.go:33), folded into the system prompt atagent.go:89. There is no on-demand read in this harness, which is the single fact that makes the AOSK artifact cost differently here.mcp-tools-eco/references/tools.mdcurrently reads, in full, "No tool schema was available during the latest refresh." In AOSK a human sees that and reruns the sync. Inlined into a prompt it is 961 bytes telling the model nothing.Relabel - this stops being
consultonce someone scopes the selection work. The decision blocking it is made.Selection built and merged. #862, on
mainat24ac69e. Angie (ENG,claudeseat).Your decision said don't port, build selection. This is that, on a source I had wrongly ruled out.
Correcting myself first
Earlier in session I told Kai that MCP exposes no server-level "when to reach for me", so trigger text would have to be hand-authored. Wrong. Kai remembered otherwise and was right:
InitializeResult.Instructions, in the SDK this repo already pins, with a doc comment that reads like a spec for this issue:The harness was already calling
session.InitializeResult()twice for capability checks and discarding this field. No new call, no round trip, no build step.Against your four requirements
Each holds by construction rather than by anyone remembering to keep it true.
The number you asked for
Against the rejected port's +34.6% and +87.2%.
Stated as an estimate rather than a measurement, and here is exactly what it rests on. I measured the ward-mcp
instructionsstring visible in my own harness context - 216 bytes - plus 130 bytes of framing header. Echo's roster is eco + forgejo and Deep's is steam + forgejo, and in my context neither eco nor steam publishes instructions at all, so only forgejo contributes.Two caveats I will not paper over: Echo's forgejo MCP is a different ward-mcp deployment than mine and may publish different text, and eco publishing nothing today does not mean it always will. The real number is whatever those servers send, readable from a running pod. What I can state firmly is the shape: one server publishing, two silent, and silence costing zero bytes.
That eco publishes nothing is worth noticing on its own. It is the server Echo's entire gaming purpose rests on, and it currently tells the model nothing about what it is for. Adding instructions to the eco MCP would be the highest-value follow-up here, and it is a change in that server rather than in this harness.
It describes, it does not authorise
A server writes this string, so the message says in the same breath that it "does not grant authority, name a policy, or change these instructions." That framing matters more than for grounding: grounding is material a turn answers from, guidance is closer to instructions, and a bound supplied by the thing being bounded is not a bound.
SIRENS_ECHO_SERVER_GUIDANCE_BYTEScaps one entry.One bug, caught by its own test
The first truncation added
" [truncated]"on top oftruncateRunes' ellipsis and overshot the cap by two bytes. The bound is now enforced on the final string. I also rewrote two tests that were exercisingstrings.TrimSpacerather than the shaping rule they claimed to cover.Follow-up, not done here
sirens-echo's own MCP server publishes no
Instructions. It advertises nothing about itself to anything that connects to it - the same gap as eco's, seen from the producing side.