How to use the OSYRA OME MCP server
This how-to documents the OSYRA OME MCP server
(@osyra/mcp-osymem, service allocation AP00015): the configuration and tool
contract an MCP client such as Claude Desktop, Cursor, or Continue.dev will use
to interact with OME memory claims, export and verify bundle manifests, and run
policy pre-flight checks once each path's release gate is satisfied.
What it is
The OSYRA OME MCP server is an
Anthropic Model Context Protocol (MCP)
server intended to front the OSYRA ome service (AP00011). MCP clients invoke
osymem.* tools over stdio JSON-RPC; AP00015 translates those calls into
Connect-RPC requests to the ome backend once the release topology is
activated.
┌──────────────────┐ stdio JSON-RPC ┌──────────────────────┐ Connect-RPC ┌─────────────┐
│ Claude Desktop / │ ───────────────► │ @osyra/mcp-osymem │ ───────────► │ ome service │
│ Cursor / IDE │ ◄─────────────── │ (this package) │ ◄─────────── │ (AP00011) │
└──────────────────┘ └──────────────────────┘ └─────────────┘Design points worth knowing:
- The workspace is fixed at startup via
OME_WORKSPACE. Tool callers cannot override it — cross-workspace access is a hard server-side invariant. - No OME claim/bundle crypto runs in this server. All signing and
bundle-verify operations route through the
@osyra/omeSDK. The only local crypto surface is capability-token (JWT) validation. osymem.memory.putnever sees plaintext. Callers hash content themselves and submit only SHA-256 digests.
Naming note. The
osymem.*prefix andosymem://URI scheme are grandfathered for MCP tool names only (Anthropic registry convention; PM-DECISION 2026-05-26). In every other context the canonical OSYRA vocabulary is ome /@osyra/ome.
Package name. The one and only canonical npm name for this server is
@osyra/mcp-osymem— always scoped under@osyra. There is no unscopedmcp-osymempackage, and no alternate scope, separator, or spelling is published by OSYRA. Any package that resembles this name but is unscoped or differently spelled is not an OSYRA artifact; do not install it.
Availability. The source contract is
v1.0.0, but the package is not yet published. Publication remains gated on/osyra-securityreview, the ADR-066 threat-model merge, and the/osyra-pmGA gate. Remote use additionally requires the live acceptance and credential-separation gates described above.
Prerequisites
You need:
- An MCP client (Claude Desktop, Cursor, or Continue.dev).
- A capability token issued by the OSYRA IAM / OME admin flow
(
OME_MCP_TOKEN). - Your IAM workspace UUID (
OME_WORKSPACE). Existing workspaces may use UUIDv4. UUIDv7 is required for OME claim handles, not for the workspace. - The issuer DID and non-exporting AWS KMS key reference that AP00011 is authorized to use for this workspace.
- A local capability-token trust source: a pinned Ed25519 public key, an HTTPS JWKS URL, or both. Brokered request-capability deployments require JWKS.
Step 1 — Install the runtime SDK dependency
The MCP server has a runtime dependency on @osyra/ome (the TypeScript SDK,
AP00014). After its release gate clears, authenticated internal consumers
install it from OSYRA's private CodeArtifact registry:
npm install @osyra/ome \
--registry=https://osyra-273863930653.d.codeartifact.us-east-1.amazonaws.com/npm/osyra-npm/The registry requires a valid CodeArtifact authorization token. There is no anonymous or public install path for the pre-release package.
Step 2 — Run the server
Once both packages are published and the remote release gates pass, the server
is run via npx. Always pass --prefer-online so npx re-resolves from the
registry rather than trusting a possibly-poisoned local _npx cache:
npx --prefer-online @osyra/mcp-osymemFor CI or any non-interactive use, pin an exact version so npx can only run
that release:
npx --prefer-online @osyra/mcp-osymem@1.0.0Every published release carries a Sigstore-signed npm build-provenance attestation. After install you can verify the artifact's provenance:
npm audit signaturesIn practice you do not launch this yourself — your MCP client starts it for you
using the config blocks in Step 4. The npx command above is the exact
command/args pair those clients invoke.
Step 3 — Configure environment variables
The server reads its configuration from environment variables. MCP clients pass
these through a per-server env block.
Core client configuration (OME_* / OME_MCP_*)
| Variable | Required | Default | Purpose |
|---|---|---|---|
| OME_MCP_TOKEN | yes | — | Capability token issued by OSYRA IAM / OME admin flow |
| OME_WORKSPACE | yes | — | IAM workspace UUID the server is scoped to (UUIDv4 or UUIDv7, according to the existing IAM record) |
| OME_MCP_SIGNER_DID | yes | — | Issuer DID bound to the AP00011 non-exporting signer |
| OME_MCP_SIGNER_KMS_KEY_ID | yes | — | AWS KMS key ARN or alias; private key bytes are never accepted |
| OME_ENDPOINT | no | https://edge.osyra.ai | OME service endpoint |
| OME_NO_LOCAL_VERIFY | no | 0 | Set 1 to disable defense-in-depth local Ed25519 re-verify (logged at audit-WARN) |
| OME_MCP_QUIET | no | 0 | Set 1 to silence audit-INFO lines on stderr (audit-ERROR always emits) |
Operator tuning + token validation (OSYRA_OME_*)
| Variable | Required | Default | Purpose |
|---|---|---|---|
| OSYRA_OME_IAM_PUBKEY | one or both¹ | — | Ed25519 public key (base64 raw-32-byte or PEM-SPKI) used to locally verify direct-session AP00015 capability JWTs |
| OSYRA_OME_IAM_JWKS_URL | one or both¹ | — | HTTPS JWKS endpoint for AP00015 Ed25519 capability-token keys; mandatory for brokered request capabilities |
| OSYRA_OME_TOKEN_ISSUER | no | https://auth.osyra.ai | Expected token iss |
| OSYRA_OME_TOKEN_AUDIENCE | no | urn:osyra:mcp:osymem:v1 | Expected token aud (the server spec-id) |
| OSYRA_OME_SPEC_ID | no | urn:osyra:ome:v1 | Expected OME backend spec-id (osyra.spec_id) |
| OSYRA_OME_REQUIRE_TOKEN_VALIDATION | no | 1 | Default-on. 0 is honored only with an exact loopback OME_ENDPOINT for explicit local development; remote endpoints still fail closed |
| OSYRA_OME_RATE_LIMIT_RPM | no | 60 | Per-token requests-per-minute cap (1..10000) |
| OSYRA_OME_CALL_TIMEOUT_MS | no | 30000 | Per-tool-call deadline in ms (1000..300000) |
| OSYRA_OME_REGION | no | — | Operator-pinned data-residency region (e.g. us-east-1). When set, startup binds against the backend's advertised region and every token's osyra.region claim must match (cross-region caps refused). Absent/blank = region binding off (Enterprise SKU; ADR-297). |
The two prefixes are intentional and stable:
OME_*/OME_MCP_*is core client config;OSYRA_OME_*is operator tuning plus capability-token validation.
Exfil-detector thresholds (OSYRA_OME_EXFIL_*)
These optional, content-blind thresholds tune the per-token exfiltration detector (MCP-C-30 / ADR-295). When unset, conservative built-in defaults apply. A garbage value falls back to that field's default — it never silently disables the control.
| Variable | Purpose |
|---|---|
| OSYRA_OME_EXFIL_VOLUME_MAX_BYTES | Bytes returned within the window before tripping |
| OSYRA_OME_EXFIL_RATE_MAX_PER_MIN | Distinct handles/min (scraping signal) before tripping |
| OSYRA_OME_EXFIL_RATE_SOFT_PER_MIN | Read-rate floor that gates the enumeration signal |
| OSYRA_OME_EXFIL_WINDOW_MS | Sliding window (ms) for volume + rate accounting |
| OSYRA_OME_EXFIL_COOLDOWN_MS | Circuit-break cool-down (ms) after a trip |
Token validation behavior
Every non-loopback deployment validates the JWT locally using
OSYRA_OME_IAM_PUBKEY, OSYRA_OME_IAM_JWKS_URL, or both: EdDSA-only
signature, the standard
iss/aud/exp/nbf/iat/jti/nonce claims, osyra.workspace equal to
OME_WORKSPACE, the tool's required scope in osyra.scopes, osyra.spec_id,
and a jti replay cache. Failures return a uniform UNAUTHORIZED with no
indication of which check failed. A remote startup without a usable local trust
source fails closed.
spec-id startup binding
At startup the server reads the OME backend's advertised spec-id and validates
it against OSYRA_OME_SPEC_ID. A mismatch aborts startup with a non-zero exit —
the server refuses to serve a single tool call against a backend serving a
different spec. A backend that does not yet advertise a spec-id degrades to a
carried posture (the in-token osyra.spec_id validation still applies) and logs
an audit-WARN; it never silently allows.
Step 4 — Wire it into your MCP client
These templates show the minimum non-loopback configuration contract. Replace
every angle-bracketed value with an operator-issued value; none is a test
credential. The --prefer-online arg defeats a poisoned-cache shadow and is
the exact value the OSYRA install hardening recommends.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json on macOS
(or %APPDATA%/Claude/claude_desktop_config.json on Windows):
{
"mcpServers": {
"osymem": {
"command": "npx",
"args": ["--prefer-online", "@osyra/mcp-osymem"],
"env": {
"OME_MCP_TOKEN": "<your-capability-token>",
"OME_WORKSPACE": "<your-iam-workspace-uuid>",
"OME_MCP_SIGNER_DID": "<your-authorized-signer-did>",
"OME_MCP_SIGNER_KMS_KEY_ID": "<your-kms-key-arn-or-alias>",
"OSYRA_OME_IAM_JWKS_URL": "<your-capability-jwks-url>"
}
}
}
}Then quit and relaunch Claude Desktop completely (Cmd-Q on macOS). Verify the connection from the menu: hamburger → "Connected MCP servers".
Cursor
Edit ~/.cursor/mcp.json:
{
"mcpServers": {
"osymem": {
"command": "npx",
"args": ["--prefer-online", "@osyra/mcp-osymem"],
"env": {
"OME_MCP_TOKEN": "<your-capability-token>",
"OME_WORKSPACE": "<your-iam-workspace-uuid>",
"OME_MCP_SIGNER_DID": "<your-authorized-signer-did>",
"OME_MCP_SIGNER_KMS_KEY_ID": "<your-kms-key-arn-or-alias>",
"OSYRA_OME_IAM_JWKS_URL": "<your-capability-jwks-url>"
}
}
}
}Continue.dev
Edit ~/.continue/config.json:
{
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"type": "stdio",
"command": "npx",
"args": ["--prefer-online", "@osyra/mcp-osymem"]
},
"env": {
"OME_MCP_TOKEN": "<your-capability-token>",
"OME_WORKSPACE": "<your-iam-workspace-uuid>",
"OME_MCP_SIGNER_DID": "<your-authorized-signer-did>",
"OME_MCP_SIGNER_KMS_KEY_ID": "<your-kms-key-arn-or-alias>",
"OSYRA_OME_IAM_JWKS_URL": "<your-capability-jwks-url>"
}
}
]
}
}The tools
The v1.0.0 source contract exposes six base osymem.* tools. Each tool's
current input and output schema is shown below. A seventh, default-off tool
(osymem.memory.tombstone) is described separately under
Optional: GDPR erasure tool.
osymem.memory.list
List memory claim handles in the server's scoped OME workspace.
// Input
{
limit?: number, // 1..200; default 50
cursor?: string // opaque pagination cursor; <= 256 UTF-8 bytes
}
// Output
{
handles: string[], // UUIDv7
nextCursor?: string,
count: number, // handles in this page
totalCount: number // server-authoritative total matching count
}kind is deliberately not accepted because AP00011 does not yet expose the
indexed filter needed to implement it truthfully.
osymem.memory.get
Fetch unsigned body bytes and their SHA-256 commitment by UUIDv7 handle.
AP00014 recomputes SHA-256(body) and rejects a mismatch, so this proves
body/hash consistency only. The backing GetClaimBody RPC returns no Ed25519
signature, signer DID, certificate, or trust anchor; this response therefore
does not establish signer authenticity or claim provenance. AP00015 does not
fabricate those missing fields.
// Input
{
handle: string // UUIDv7 from memory.list or an existing AP00011 claim
}
// Output
{
handle: string,
bodyBase64: string,
contentHashBase64: string // SHA-256 commitment, 32 bytes encoded as base64
}osymem.memory.put
This tool is registered and its input schema is implemented, but its current
write path is fail-closed and not usable end to end. The handler constructs
the SDK claim with id: ""; AP00011's persistence boundary requires a valid
16-byte UUIDv7 claim id. Consequently the call cannot persist a claim or return
the declared success projection today.
The handler still never sees the underlying body — callers hash content themselves and submit only SHA-256 digests. The schema below documents what it accepts, not a promise of a successful AP00011 write. AP00015 must generate or accept a valid UUIDv7 (or AP00011 must deliberately change the contract) before this tool can be described as operational.
// Input
{
kind: "IngestClaim" | "DerivationClaim" | "AttestationClaim",
contentHashBase64: string, // SHA-256 of body (44 chars)
embeddingHashBase64?: string, // optional SHA-256 of embedding
parents: string[], // UUIDv7 DAG parents; max 64; [] for root
timestampMs?: number, // Unix-ms; default server-now; bound +/- 5 min
idempotencyKey?: string // 1..128 UTF-8 bytes; OME de-duplicates retries
}
// Declared success projection; currently unreachable against AP00011
{
handle: string, // valid persisted UUIDv7 after the blocker is fixed
kind: string,
workspaceId: string // always == OME_WORKSPACE
}osymem.bundle.sign
Export the server-scoped workspace and return AP00011's signed whole-workspace
bundle manifest. ExportBundle does not support a caller-selected handle
subset. The MCP server never holds signing keys.
// Input
{} // strict empty object; any handle selector is rejected
// Output
{
version: 2,
contentType: "application/vnd.osyra.ome.bundle.v1+zip",
rootHex: string, // 64 lowercase hex chars
claimCount: number,
tombstoneCount: number,
createdMs: number,
issuerPubKeysBase64: string[], // in-band candidates; NOT trust anchors
epoch: number,
coseSign1Base64: string,
preimageBase64: string, // separate 5-element Form-B preimage
bundleBytes: number, // bytes drained from ExportBundle
scope: "whole-workspace"
}osymem.bundle.verify
Verify the bundle manifest's signature leg. The declared root is bound by the
signed Form-B manifest/preimage, but this tool does not reopen the .ome
archive or re-derive its JMT root. It routes through the @osyra/ome
verify-subset (no kernel-copy, no signing).
// Input
{
coseSign1Base64: string, // <= 16 MiB after decode
preimageBase64: string, // <= 16 MiB after decode
trustAnchorsBase64: string[] // required; one or more external 32-byte Ed25519 keys
}
// Output
{
ok: boolean,
coseSign1Bytes: number,
preimageBytes: number,
trustAnchorCount: number
}The issuer keys carried by the bundle are candidates, not trust anchors. The relying party must resolve and supply at least one trusted key out of band.
osymem.policy.check
Policy pre-flight. Asks the OME enforcer for the would-be admission verdict for
an action (optionally on a resource, with bounded non-PII context)
without performing it. The enforcer evaluates the workspace's already-loaded,
AP00019-signed policy cascade — the MCP server adds no policy logic and never
decides. There is no policy_id selection: the workspace's active cascade is
authoritative (the workspace is server-pinned). Requires the dedicated
osymem.policy capability scope.
// Input
{
action: string, // non-empty decision verb; <= 256 UTF-8 bytes
resource?: string, // optional target ORN/handle; <= 512 UTF-8 bytes
context?: Record<string, string> // <= 32 entries; key <= 128 chars, value <= 512
}
// Output
{
decision: "ALLOW" | "DENY" | "IMPLICIT_DENY",
policy_version: string, // the executed cascade's combined digest (replayable)
decision_id: string, // server-minted decision correlation id
violations: string[] // responsible cascade layer / fail-reason
}Fail-closed. If the enforcer is unreachable, the eval is indeterminate, or
the per-call deadline trips, the tool returns decision = "IMPLICIT_DENY" (with
empty policy_version / decision_id) — never an ALLOW, and never a transport
error read as allow. A deny is a normal result, not an error; only a genuine
non-transport failure surfaces as a tool error.
Optional: GDPR erasure tool
The server can also register a seventh, destructive and irreversible tool —
osymem.memory.tombstone (GDPR Art-17 crypto-shred). It is outside the six-tool
base manifest and is off by default:
- It is registered only when
OME_MCP_ENABLE_TOMBSTONEis set to a truthy value (1/true/yes/on) and a local token-validator is active (OSYRA_OME_IAM_PUBKEYorOSYRA_OME_IAM_JWKS_URL). When the gate is off the tool is absent fromtools/listentirely — a prompt-injected model cannot even see it. - It requires the dedicated
osymem.tombstonecapability scope (notosymem.write). - It uses a two-step protocol: call without
confirmation_tokento PREPARE (erases nothing; returns a single-use token plus an irreversible-flagged preview), then call again with that exact token to EXECUTE.
The AP00014 erasure SDK leg is implemented and wired. The EXECUTE path is still
fail-closed refused, however, because token-revocation enforcement is not
live and no distinct-trust-domain human confirmation channel is wired into this
subprocess. It returns a typed PRECONDITION_FAILED rather than fabricating a
receipt. Do not rely on this tool for production erasure.
// Input
{
reason_code: "GDPR_ART17_DSAR" | "LEGAL_HOLD_EXPIRY" | "CUSTOMER_OFFBOARDING"
| "OPERATOR_REDACTION" | "REGULATORY_OTHER",
handle: string, // UUIDv7 claim handle to crypto-shred
reason_detail: string, // free-text audit context, <= 256 chars
confirmation_token?: string // STEP-2 EXECUTE only: the token from a prior PREPARE
}Error model
All tools return MCP-compliant tool-error envelopes (isError: true) on
failure. The error text always begins with a stable bracketed error code:
| Code | Meaning |
|---|---|
| INVALID_INPUT | Zod schema validation failed |
| NOT_IMPLEMENTED | SDK call is reserved for a later release |
| UNAUTHORIZED | Local capability validation or OME authorization rejected the call |
| WORKSPACE_MISMATCH | OME reports the workspace doesn't exist or you lack scope |
| TRANSPORT_ERROR | Network failure reaching OME |
| SERVER_ERROR | OME service-side failure (policy, quota, etc.) |
| VERIFY_FAILED | OME or the SDK returned a malformed or unverifiable result |
| NOT_FOUND | Resource (claim, bundle) not found |
| INTERNAL_ERROR | Catch-all (the audit log retains redacted, non-secret diagnostics) |
The optional tombstone tool additionally uses CONFIRMATION_REQUIRED (the
confirmation token is missing, expired, already used, or mis-bound) and
PRECONDITION_FAILED (an erasure precondition is not yet met — a deliberate
safety gate).
Capability tokens are redacted on every egress: client-facing errors, the structured audit log, and direct stderr writes. The token itself never stays in the audit log. Client errors omit stack traces and absolute paths; the stderr audit stream retains only redacted, non-secret diagnostics such as stable event class, tool/source, severity, correlation fields, and sanitized failure detail.
Troubleshooting
"Failed to load runtime SDK module '@osyra/ome'"
The server can't find the @osyra/ome package. Install it from the private
CodeArtifact registry, then restart:
npm install @osyra/ome \
--registry=https://osyra-273863930653.d.codeartifact.us-east-1.amazonaws.com/npm/osyra-npm/If npx --prefer-online @osyra/mcp-osymem is what's invoking, you may need a
global install so the global prefix is searched:
npm install -g @osyra/ome"OME_MCP_TOKEN appears to be a placeholder value"
Replace <your-capability-token> (or REPLACE_ME, TODO) with the real token
from the OSYRA IAM / OME admin flow.
"OME_WORKSPACE must be a canonical workspace UUID"
Use the IAM-owned workspace UUID shown by the OSYRA Console. Workspace IDs are
distinct from memory claim handles: current IAM workspaces may be UUIDv4, while
existing AP00011 claim handles listed by osymem.memory.list remain UUIDv7.
The current memory.put blocker described above means it does not return a new
handle today.
Connection hangs / no tools appear
Check the audit log:
- macOS:
~/Library/Logs/Claude/mcp-osymem.log - Windows:
%APPDATA%/Claude/logs/mcp-osymem.log
Any line with "level":"error" indicates the failure. Common causes are an
unreachable OME_ENDPOINT (firewall, DNS) and a token-scope mismatch (token
issued for a different workspace).
"I see Acme Corp / Default Workspace in a tool response"
This is a P0 bug. The MCP server does not generate placeholder data; if you see fake business data in a tool response, file a Linear issue referencing ENG-851 immediately.
Related
- Sibling TypeScript SDK: AP00014-osyra-ome-sdk-typescript
- Sibling Python SDK: AP00013-osyra-ome-sdk-python
- Model Context Protocol specification