Skip to content

fix(mcp,harness): name the two MCP servers by role in both offline fallbacks [SAP-3179] - #814

Open
gwitwer wants to merge 4 commits into
mainfrom
fix/sap-3179-mcp-alias-role-names
Open

fix(mcp,harness): name the two MCP servers by role in both offline fallbacks [SAP-3179]#814
gwitwer wants to merge 4 commits into
mainfrom
fix/sap-3179-mcp-alias-role-names

Conversation

@gwitwer

@gwitwer gwitwer commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Primary change type

  • Bug fix
  • Documentation
  • Feature
  • Tests
  • Dependency update
  • Maintenance or refactor

Problem and motivation

The two offline fallbacks — AUTHORING_INSTRUCTIONS in @sapiom/mcp and DEFAULT_SYSTEM_PROMPT in @sapiom/harness — named the same two Sapiom MCP servers differently. The Studio prompt said sapiom (hosted) / sapiom-dev (local), which is what mcp-config.ts registers. The authoring primer said sapiom (local) / sapiom-direct (hosted), which is what a plain Claude Code user is told to register. A Studio session reads both, so "use the sapiom alias to author agents" pointed it at the remote server the prompt had just said not to call while authoring.

Summary and scope

Both bodies are now byte-identical copies of the backend's 2.9 authoring primer and 1.1 Agent Studio system prompt, which describe the servers by role ("the local authoring server", "the hosted capability server") and mention an alias only inside the unchanged claude mcp add commands. Both digest pins (instructions.test.ts, default.test.ts) move to the new bodies, and the alias assertions now check the role phrases.

Out of scope: claude-code-info.ts tells a user installing outside Studio to register the local server as sapiom-dev, while the primer's command says sapiom. That is a separate install flow, noted on the Sapiom ticket.

Related work

Related issue or discussion: SAP-3179 (https://linear.app/sapiom/issue/SAP-3179). Paired backend PR in sapiom/Sapiom — linked in the first comment. Land both together; the cross-repo digest tests redden either repo alone.

Validation

pnpm --filter @sapiom/mcp exec vitest run src/instructions.test.ts — 8 passed
pnpm --filter @sapiom/harness exec vitest run src/profiles/default.test.ts — 2 passed
pnpm exec prettier --check <changed files> — clean

Tests and documentation

Updated the two pin tests: new sha-256 digests, and role-phrase assertions replacing the alias-identity assertions. No user-facing docs in this repo change; the served text is the documentation.

Compatibility and release impact

  • Breaking or externally visible changes: None. The fallback text is served only when the startup fetch of the live copy fails.
  • Changeset: Added (@sapiom/mcp patch, @sapiom/harness patch).

Security

  • I have not included secrets, credentials, private data, or unsanitized logs.
  • This pull request does not publicly disclose a suspected vulnerability. I
    will follow the
    Security Policy for
    private reporting.

AI assistance

  • I did not use AI assistance for this change.
  • I used AI assistance and have described it below.

Claude Code authored the change. The bodies were copied programmatically from the backend constants and verified by the digest tests in both repos; the test edits and changeset were reviewed by reading the diff.

Checklist

  • I read CONTRIBUTING.md, and this contribution follows the direct-PR or issue-first policy.
  • This pull request addresses one focused problem and contains no unrelated cleanup.
  • I added or updated tests, or explained above why tests are not applicable.
  • I ran the relevant build, typecheck, lint, and test commands, or explained
    any N/A checks above.
  • I updated documentation for user-facing changes, or marked it N/A above.
  • I added a Changeset for a published-package change, or explained why it is not applicable.
  • I can explain and maintain every submitted change, including any AI-assisted work.

🤖 Generated with Claude Code

https://claude.ai/code/session_013XCxe63LD6M6aaWVT9E5zE

…llbacks

Byte-identical copies of the backend's 2.9 authoring primer and 1.1 Agent
Studio system prompt, with both digest pins moved to the new bodies.

The two texts disagreed about what the two servers are called: the Studio
prompt said `sapiom` (hosted) / `sapiom-dev` (local), which is what
mcp-config.ts registers; the authoring primer said `sapiom` (local) /
`sapiom-direct` (hosted), which is what a plain Claude Code user is told to
register. A Studio session reads both, so "use the `sapiom` alias to author
agents" pointed it at the remote server the prompt had just said not to call.
Both now describe the servers by role — "the local authoring server", "the
hosted capability server" — and mention an alias only inside the unchanged
`claude mcp add` commands.

Refs: SAP-3179

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013XCxe63LD6M6aaWVT9E5zE
@gwitwer

gwitwer commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator Author

Paired backend PR (content releases 2.9 / 1.1 + both digest pins): https://github.com/sapiom/Sapiom/pull/4884

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Review — PR #814 (round 1)

1. The one alias the primer still names is the one that collides (published copy)

packages/mcp/src/instructions.ts:23 still says:

register it with claude mcp add sapiom -- npx -y @sapiom/mcp

That registers the local authoring server under sapiom. Everywhere else in this repo,
sapiom is the hosted server and the local one is sapiom-dev:

  • packages/harness/src/core/inject/mcp-config.ts:60,95 — Studio wires sapiom = hosted,
    sapiom-dev = local.
  • docs/mcp-servers.md:7,10 — table headed Remote sapiom / Local sapiom-dev.
  • packages/mcp/README.md:24,46 — config examples key the local server as sapiom-dev
    (README:35 has the same contradictory claude mcp add sapiom line, so the README is
    internally inconsistent too).
  • packages/harness/src/core/adapters/{claude-code-info.ts:17,conductor.ts:21,codex-info.ts:17}
    all instruct sapiom-dev.

What breaks: a user who connected the hosted capability MCP as sapiom (per
docs/mcp-servers.md) and then follows the primer clobbers/shadows that entry with a stdio
launch of @sapiom/mcp; their claude mcp list then contradicts every other Sapiom
instruction they will read. And a Studio session reads this primer, where sapiom really
is the hosted server — so the exact misdirection the PR exists to remove ("the sapiom alias
is the local one") survives verbatim in the only surviving alias sentence.

I accept the PR's scoping of claude-code-info.ts, and the byte-identity pin means the primer
line can't be changed here alone — but that makes this a request on the paired backend PR,
not a thing to close out. Either make the primer's command sapiom-dev (matching every install
adapter and the docs table) or change the docs; do not ship SAP-3179 as "aliases resolved" while
the one remaining alias statement is the wrong one.

2. The harness pin test lost its only alias guard, asymmetrically

packages/harness/src/profiles/default.test.ts:41-43 replaced toContain("sapiom-dev") with
role-phrase assertions and added no negative assertion, while
packages/mcp/src/instructions.test.ts:60-66 kept three (not.toContain(...)). The digest is
not a substitute: its own doc comment (default.test.ts:24-29) says editing the prompt reddens
it and the author re-pins it, so any future prompt edit that reintroduces sapiom-dev passes
review with a re-pinned digest and nothing flags the regression this PR just paid to fix.

Add the mirror of the mcp test:

expect(DEFAULT_SYSTEM_PROMPT).not.toMatch(/sapiom-dev\b|sapiom-direct\b/);

(safe — the prompt's sapiom_dev_agents_* uses underscores, already asserted on line 43).

Nits

  • .changeset/mcp-alias-role-names.md: paragraph 2 ships internal maintenance detail into two
    public CHANGELOGs — backend copy version numbers ("2.9 authoring primer", "1.1 Agent Studio
    system prompt") and "Both digest pins move with the bodies" reference instructions.test.ts,
    which is explicitly not published. An npm consumer cannot act on any of it. The first
    paragraph is the whole consumer-relevant story; consider cutting the rest to one sentence.
  • I could not execute the two vitest runs in this environment, so the new digests
    (2af1edd6…, 55e0e1d6…) are unverified here — CI covers it, but confirm both repos' pins
    are the same values before landing either side.

Verdict

Patch level and changeset presence are right, no public API or dependency surface moves, and
the prose is clean on confidentiality (no third-party company names, business terms, or
internal hosts; SAP-#### in a changeset matches existing CHANGELOG precedent). Approve on
the mechanics — but finding 1 means the naming problem is not actually closed, and finding 2
leaves the fix unguarded.

Byte-identical to the revised 2.9 primer and 1.1 Studio prompt from review
round 1 on the backend PR: `sapiom_authenticate` / `sapiom_status` exist on
both servers, so both texts now tie the pair to the local server by the
tools alongside `sapiom_dev_agents_*`. Both digest pins move with the bodies.

Refs: SAP-3179

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013XCxe63LD6M6aaWVT9E5zE
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Review — PR #814 (round 2, delta since e9a4f88)

One new commit (f2b30de9) changed both bodies again (sign-in disambiguation) and re-pinned
both digests. It did not address either round-1 finding.

New

1. The changeset now mis-describes what ships. .changeset/mcp-alias-role-names.md was not
touched by f2b30de9, so the published CHANGELOG still asserts the bodies are the backend's
"2.9 authoring primer" and "1.1 Agent Studio system prompt" — while the bodies moved after that
claim was written. Either the backend re-released under the same numbers (then say so on the
paired PR) or the CHANGELOG ships a false identity claim to npm, permanently. The new
user-visible instruction (which server's sapiom_authenticate to call) is also absent from
the changeset body, which still says only aliases changed. Round-1's nit on paragraph 2
(internal copy-version numbers, reference to the unpublished instructions.test.ts) also
stands — rewriting that paragraph fixes both.

2. Unsourced claim about the hosted server. packages/harness/src/profiles/default.ts:23-25
("the hosted server offers same-named tools that only describe the auth flows and cache
nothing") and packages/mcp/src/instructions.ts:53-56 assert hosted-server behavior nothing in
this repo backs. docs/mcp-servers.md says the opposite by omission: it attributes the
unprefixed sapiom_authenticate / sapiom_status tools to the local server only and lists the
remote's surface as capability tools. If the collision is real, the disambiguation doc is the
one place a reader can act on it — update it here.

Round-1 findings not fixed

  • Alias collision (round-1 cleanup HTTP SDKs #1): instructions.ts:23 still says
    claude mcp add sapiom -- npx -y @sapiom/mcp; instructions.test.ts:66 now positively pins
    that string, so the one surviving alias sentence is still the wrong one.
  • Missing guard (round-1 update SDKs to use payment protocol data #2): default.test.ts still has no
    not.toMatch(/sapiom-dev\b|sapiom-direct\b/), asymmetric with the mcp test's three negatives.

Nothing in round 1 reads as wrong. Digests remain unverified locally (sandbox blocked vitest).

Verdict: delta does not close the round-1 findings and adds an inaccurate changeset — fix
the changeset before merge; the rest is for the paired backend PR.

…tus wording fix

Byte-identical to the backend's revised 1.1 prompt: the hosted `sapiom_status`
reports the hosted session's API-key auth rather than merely describing flows.
Digest pin moves with the body.

Refs: SAP-3179

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013XCxe63LD6M6aaWVT9E5zE
…h fallbacks

main rewrote DEFAULT_SYSTEM_PROMPT (Agent Map bullet, shorter first-reply
guidance) without a backend release, so the harness fallback had already
diverged from the served 1.0 text. The backend's 1.1 release now adopts main's
prompt as its body, with the two Sapiom server bullets named by role and the
Agent Map bullet gated to builds that ship it; this copy is byte-identical to
that and its pin moves accordingly. resolveKnownSystemPrompt keeps upgrading
the served 1.0 text to this body.

The authoring fallback moves to the backend's 2.11 body, which carries 2.10's
trigger-kinds section (SAP-3174) plus the role-based server names.

Refs: SAP-3179

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013XCxe63LD6M6aaWVT9E5zE
@gwitwer

gwitwer commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

Merged origin/main in c4a0c22 (no force-push). Two things changed underneath this PR:

  • Harness prompt. main rewrote DEFAULT_SYSTEM_PROMPT (Agent Map bullet, shorter first-reply guidance) with no backend release, so the fallback had already diverged from the served 1.0 text. Rather than re-diverge, the backend's 1.1 release (sapiom/Sapiom#4884, 1789920000000) now adopts main's body with the two Sapiom server bullets named by role; this copy is byte-identical to it and the pin moves to that digest. resolveKnownSystemPrompt keeps upgrading the served 1.0 text to this body. One addition to main's text: the Agent Map bullet is gated to builds that ship it, because the backend serves this text to older harnesses too.
  • Authoring primer. Moves to the backend's 2.11 body, which is 2.10 (SAP-3174 trigger kinds, already on backend main) plus the role-based server names. Overlaps with feat(mcp,agent-core): expose event and webhook trigger kinds from sapiom_dev_agents_schedule [SAP-3174] #817's instructions.ts change; see the note there.

Verified locally: default.test.ts, served-system-prompt.test.ts and instructions.test.ts pass (20 tests).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant