Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

fix(mcp): resolve third-round Claude/OpenAI directory readiness findings

merged#2834CedarCopilot

CedarCopilot wants to merge 1 commit into staging from fix/mcp-directory-round3

Live on prod, 0 of 8 surfaces working, 1 day leftTimeline and evidence
  1. Opened
    Sep 19, 2026, 9:27 PM
  2. Sep 19, 2026, 9:32 PM
  3. Merged
    Sep 19, 2026, 10:27 PM
  4. Live on prod
    Sep 19, 2026, 10:27 PM
  5. Observed 9 hours, 8 surfaces, 0 requests
    Sep 19, 2026, 10:27 PM
  6. Watching

    Live on prod, 0 of 8 surfaces working, 1 day left

    Sep 19, 2026, 10:27 PM
  7. Pipelines steady after this deploy
    Sep 19, 2026, 10:27 PM

Behaviors Libra is checking

Autonomous document deletion through external MCP, cron, automations, or bots continues to apply the tombstone immediately because there is no live approver to receive an in-app card.Not checked
prod
Interactive in-app document deletion proposes an approval card and defers the delete until the user confirms it.Not checked
prod
The external document-write delete operation advertises itself as destructive so Claude, OpenAI, and other MCP hosts can apply their own tool-approval UI.Not checked
prod
External MCP clients no longer see or can request the config-read get-credentials action, its parameters, or its credential-related description.Not checked
prod
External MCP server registration fails loudly if a configured capability redaction no longer matches the tool schema or description instead of silently re-advertising a forbidden capability.Not checked
prod
External MCP clients can manage MCP connections by URL but are no longer offered stored credential management or static authorization-header inputs.Not checked
prod

Libra found 8 production surfaces on prod but could not judge any of them yet. 8 surfaces had no requests at all. Libra checks hourly for 3 days after each deploy.

Summary

Fourth round of fixes against Manufact's Claude/OpenAI app-directory readiness checklist for the public MCP server (apps/server/src/mastra/mcp/external/server.ts), following PR #2831's earlier round.

Fix #1 , server instructions push tool use too broadly

buildSessionInstructions's purposeSentence told the model to "use these tools whenever a request touches" a long list of subjects , flagged under "descriptions must not recommend overly broad triggering beyond the explicit user intent." Reworded to state what Cedar is and gate on the user's own request actually needing a tool, with an explicit disclaimer against reaching for Cedar merely because a request is adjacent or another tool could help. server.test.ts updated to assert the old phrasing is gone and the new scoped wording is present (mirrors the existing configLoadNote test in the same file). Verified the assembled instructions stay well under the 2KB Claude Code truncation budget (1429 of 2048 bytes for the four fixed notes).

Fix #2 , raw credentials advertised in tool schema/description

config-read.get-credentials and systems-write's manage_credential_entry/authorizationHeader were already scope-gated to in-app (never reachable at runtime over external MCP), but the schema and description advertised to a client at tools/list time still solicited them , the actual evidence Manufact's review cited.

Built a new, generic, throw-on-mismatch redaction helper , apps/server/src/mastra/mcp/external/external-capability-redaction.ts , the subtractive counterpart to the (now-removed, see Fix #3) injectIntentFields. It can drop enum values, whole param objects, or specific fields/variants out of a nested discriminated union, plus trim matching prose from the description, and it throws if a removal target no longer exists (so a redaction can't silently rot into a no-op).

Applied it to:

  • config-read: drops get-credentials from the action enum and the whole getCredentials params object.
  • systems-write: drops the entire manage_credential_entry change type (storing a named credential is the secret bag , no non-secret sub-path exists) and trims authorizationHeader off manage_mcp_connection (which does have a legitimate non-secret sub-path: adding a server by URL alone , the "headless account setup over external MCP" case scope-map.ts's own history calls out). update_mcp_connection_settings is untouched (never carried a secret).

Important structural finding caught during self-review: the redaction must NOT be applied to the shared FAMILY_TOOLS array in server.ts, because that array is also iterated directly by two genuinely-internal call sites , workflows/chat/harness/mcp-server.ts (the in-app Chat Agent SDK harness) and tools/master-surface.ts (the Master agent family surface) , where get-credentials/manage_credential_entry are legitimate, needed capabilities. The fix is a new pure function, externalFamilyTools(), that applies the redaction only for the external registration path; FAMILY_TOOLS itself is untouched. A regression test locks this in (external-capability-redaction.test.ts's "FAMILY_TOOLS itself... stays un-redacted" suite).

As defense-in-depth, scope-map.ts's systems-write entry moved from a fixed playbook:write scope to an action/type-override family (mirroring config-read): both secret-bearing change.type variants now also require the never-externally-grantable in-app scope, so a stale/cached client that never re-reads the trimmed schema still can't get the call through.

EXTERNAL_TOOL_METADATA titles/comments updated (systems-write's title is now "Manage MCP server connections", reflecting that credential management is gone from this surface).

Fix #3 , universal intent-capture fields are pure telemetry solicitation

user_request_summary/is_new_request were injected as REQUIRED fields into every external-MCP tool's schema, and their own `.describe()

Show production surfaces and changed-file mapping

Production surfaces

SurfaceRequestsErrorsp95UsersVerdict
/api/trpc/admin.documents.writeGuarded0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
execute_tool write-document0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
execute_tool read-document0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
execute_tool list-documents0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
/api/trpc/documents.lastEditors0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
POST /api/trpc/documents.lastEditors0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
/api/trpc/documents.getDoc0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
POST /api/trpc/documents.getDoc0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.

Changed files → surfaces

  • apps/server/src/mastra/tools/document/documentTool.ts/api/trpc/admin.documents.writeGuardedexecute_tool write-documentexecute_tool read-documentexecute_tool list-documents/api/trpc/documents.lastEditorsPOST /api/trpc/documents.lastEditors+2
  • apps/server/docs/design/reversible-writes-and-approval.mdno production surface mapped
  • apps/server/docs/wiki/document-deletion-lifecycle.mdno production surface mapped
  • apps/server/src/mastra/mcp/external/__tests__/external-capability-redaction.test.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/__tests__/flat-args.test.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/__tests__/mutating-actions-are-administrable.test.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/__tests__/no-bare-user-id-inputs.test.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/__tests__/scope-map.test.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/__tests__/server.test.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/__tests__/tool-call-observability.test.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/__tests__/tool-inputschema-size.test.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/deprecated-record-shims.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/external-capability-redaction.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/flat-args.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/scope-map.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/server.tsno production surface mapped
  • apps/server/src/mastra/mcp/external/tool-call-observability.tsno production surface mapped
  • apps/server/src/mastra/tools/document/__tests__/documentTool.delete.integration.test.tsno production surface mapped
  • apps/server/src/mastra/utils/__tests__/approval.test.tsno production surface mapped
  • apps/server/src/mastra/utils/__tests__/chat-message-persistence.test.tsno production surface mapped
  • apps/server/src/mastra/utils/approval-policy.tsno production surface mapped
  • apps/server/src/mastra/utils/chat-message-persistence.tsno production surface mapped
  • apps/server/src/mastra/utils/redact-secrets.tsno production surface mapped
  • apps/server/src/routes/__tests__/external-mcp.e2e.test.tsno production surface mapped
  • apps/server/src/services/documents/index.tsno production surface mapped
  • docs/design/mcp-observability-and-plugin.mdno production surface mapped