The self-test tool
orgrelay-connector-check connects to your connector the way OrgRelay does and checks everything the spec requires: auth, manifest, schemas, errors, timeouts, idempotency, tenant isolation and information leaks. Pass it before anyone binds your connector.
It is one file, bin/orgrelay-connector-check.mjs, in the developer kit. No dependencies, Node.js 18 or later, MIT licensed. Get the kit from the templates page.
Usage
orgrelay-connector-check <url> [options]
--mode mcp|rest transport, default mcp
--token <T> bearer token (tenant A)
--api-key-header <H> send the token in an API key header instead, e.g. X-API-Key
--client-id/--client-secret/--token-url OAuth 2.1 client credentials
--token-b <T> a second tenant's token, to check tenant isolation
--write test write tools and idempotency (test environments only!)
--sample tool='{json}' test arguments for a tool, repeatable
--timeout <ms> per-call timeout, default 20000 (OrgRelay's default)
--json print a JSON report
--lang en English output
sign-event --secret S --file event.json print an event signature headerTypical runs:
node bin/orgrelay-connector-check.mjs https://erp.example/mcp \
--token <tenant-a> --token-b <tenant-b> --lang ennode bin/orgrelay-connector-check.mjs https://erp.example/orgrelay --mode rest \
--token <tenant-a> --token-b <tenant-b> --lang ennode bin/orgrelay-connector-check.mjs https://erp.example/mcp \
--client-id <id> --client-secret <secret> --token-url https://erp.example/oauth/token --lang ennode bin/orgrelay-connector-check.mjs "$CONNECTOR_URL" --token "$TOKEN_A" --token-b "$TOKEN_B" --json > connector-report.jsonWhat it checks
The groups below are in the order the tool prints them. A sample run against the Node.js template is on the quickstart.
| Group | Checks | Spec reference |
|---|---|---|
| Auth | No token gives 401. Wrong token gives 401. Valid token connects | Authentication |
| Manifest | Readable. spec is orgrelay-connector/1. Has a name (four languages recommended) and a version. 1–100 tools. Names are domain.action and unique. Every tool has access. Manifest and tools/list agree. readOnlyHint consistent |
Connector spec |
| Tool schemas | Each inputSchema is a valid object schema |
Connector spec |
| Read calls | Each read tool answers with sample or --sample arguments |
Standard tools |
| Timeouts | Every call within --timeout; warns above 5 s |
Timeouts |
| Errors | Unknown tool gives a proper error. Wrong argument types give invalid_arguments |
Error codes |
| Security | Error messages do not leak internals | Security |
| Idempotency | With --write: the same key twice returns the first result |
Approvals and writes |
| Tenant isolation | With --token-b: tenant B sees none of tenant A's data |
Security |
The run ends with a line such as Result: PASSED · PASS 28 · FAIL 0 · WARN 0 · SKIP 0. The exit code is 1 if anything failed.
Giving it real arguments
The tool generates arguments from each schema's examples and types. For real systems, pass known-good values so read calls return data:
node bin/orgrelay-connector-check.mjs https://erp.example/mcp --token <t> \
--sample 'orders.get={"order_no":"SO-24017"}' \
--sample 'inventory.list={"sku":"HX-330"}'Adding examples to your inputSchema properties has the same effect and also helps the AI.
Fixing common failures
| Failure | Usual cause | Fix |
|---|---|---|
no token → 401 fails with 200 |
Auth middleware skipped on /mcp or on initialize |
Authenticate every request, including the first |
wrong token → 401 gives 302 |
A proxy redirects to a login page | Return 401 from the API path; OrgRelay does not follow redirects |
readOnlyHint consistent |
access: write but no annotation, or the reverse |
Set annotations.readOnlyHint from access in one place |
wrong argument types → invalid_arguments |
No validation, so the call fails deeper and returns 500 | Validate against inputSchema first |
errors do not leak internals |
Exception text passed through | Map exceptions to codes; log details, return a plain message |
| Tenant isolation | Lookup by id ignores tenant, or a shared cache | Filter by tenant first; key caches by tenant |
| Idempotency | Key ignored, or stored per process only | Store keys with the change, in the same transaction |
Before delivery
Run it once more against production without --write, add --json, and hand the report to the customer. Owners can keep it with the connection record. For the sandbox step that follows, see the quickstart.
Signing helper
sign-event prints the X-OrgRelay-Signature header for an event file, so you can compare it with what your code produces. The format is on events.
Common questions
Does it change data? Only with --write.
CI? Yes: exit code 1 on failure, --json for reports.
Dependencies? None beyond Node.js 18.
Next
- Implementation help: MCP transport, REST compatible mode.
- Vendor servers you did not build can still be inspected with an MCP client; see third-party MCP.
- When the connector is live, staff can reach it from Claude Code or Codex through OrgRelay.
- For the business owner you deliver to, the orgrelay.com security page explains what the report means for them.
- Read the rules being checked in context: connector spec, approvals and write tools, authentication.
- The platform connectors in the connector directory follow the same rules this tool checks.
- Agents that will call your tools are configured as in enterprise MCP patterns.
Related pages
- Human-in-the-loop: why approvals live outside the AI client.
- OpenAPI import: turn an OpenAPI or Swagger file into tools.
- Claude Code: one command with a personal token.