AI for Work

Advanced: Share a Claude Code MCP Definition Without Sharing Sign-In

Summary

Cihan's view: Share a Claude Code server definition through the project's .mcp.json file, then check each teammate's effective scope before onboarding. A private local definition can override the shared entry. Keep credentials out of the repository, require individual sign-in, and record unresolved approvals and provider permissions before any live read.

Choose another work task →

Two teammates can clone the same .mcp.json and still use different server definitions. A private local entry takes precedence over the shared project entry. Your handoff should catch that before either person reads a work record.

You will prepare a team configuration handoff: the shared definition, each person’s effective scope, approval and sign-in requirements, and a decision about whether onboarding can continue.

This is a documentation-based Claude Code CLI lesson with a fictional offline fixture and editor-written desired output. The endpoint is intentionally invalid and non-runnable. No server was connected, no sign-in occurred, and no tool was called. The official documentation was checked on 29 October 2026; that is not a provider review date.

Before you start

This builder lesson assumes a terminal, Claude Code installed and authenticated to Claude, a trusted test project, and permission to review its configuration. Access to Claude does not authenticate you to a ticket provider. Check Claude Code’s setup prerequisites for your account; this guide promises no plan entitlement.

For the offline exercise, use only the supplied text. Do not run the CLI examples or substitute a real URL. A future live attempt needs the provider’s official endpoint, transport, authentication and tool documentation, an owner-approved test account, and evidence of its actual permissions. None is supplied by this fictional provider.

1. Choose what the team should share

Claude Code’s installation scopes distinguish configuration sharing from data access:

Scope Loads in Definition location Shared?
local, the default Current project ~/.claude.json, under that project’s path No
project Current project .mcp.json in the project root Through version control
user All your projects ~/.claude.json, top-level mcpServers No

For duplicate server names, local takes precedence over project, then user. Claude Code uses the complete winning entry; it does not merge fields. These are CLI rules. Desktop Code-tab behavior and managed policies can differ, so this handoff does not cover those surfaces. A setting in .claude/settings.local.json is also different from an MCP local-scope definition.

Use project scope when the team needs a common definition. Keep a personal experiment local. Sharing the definition does not share an authenticated provider account or establish read-only permissions.

2. Review the shared definition

A command shape, for reference only, is:

# Fictional endpoint. Do not execute this example.
claude mcp add --transport http --scope project approved-tickets https://tickets.example.invalid/mcp

The quickstart documents this HTTP JSON shape. Treat the following block as the complete fictional .mcp.json:

Shared definition

{
  "mcpServers": {
    "approved-tickets": {
      "type": "http",
      "url": "https://tickets.example.invalid/mcp"
    }
  }
}

There is no executable package to install and no credential in this file. Review the exact HTTPS host and path, the explicit type, the diff, and any competing definitions before sharing a real replacement. Do not commit this fictional endpoint as working configuration.

The fixture below supplies both the private override and the approved-data target in full. These names and permission requirements are invented for the exercise; they are not provider approvals.

Team source fixture

{
  "fixture_id": "team-handoff-v1",
  "project": "demo-workspace",
  "server": "approved-tickets",
  "provider": "Example Tickets, fictional",
  "provider_documentation": null,
  "provider_review_date": null,
  "provider_approval": "UNKNOWN",
  "transport": "http",
  "endpoint": "https://tickets.example.invalid/mcp",
  "auth_design": "OAuth browser sign-in, hypothetical provider support",
  "required_oauth_scopes": ["tickets:read"],
  "required_data_boundary": {"project": "DEMO", "ticket_id": "DEMO-17", "actions": ["read"]},
  "members": [
    {"name": "Mina", "local_definition": null, "user_definition": null, "workspace_trust": "UNKNOWN", "project_approval": "UNKNOWN", "provider_account": "UNKNOWN", "granted_oauth_scopes": "UNKNOWN", "provider_data_boundary": "UNKNOWN"},
    {"name": "Leo", "local_definition": {"type": "http", "url": "https://old-tickets.example.invalid/mcp"}, "user_definition": null, "workspace_trust": "UNKNOWN", "project_approval": "UNKNOWN", "provider_account": "UNKNOWN", "granted_oauth_scopes": "UNKNOWN", "provider_data_boundary": "UNKNOWN"}
  ],
  "ticket_source": {
    "source_id": "ticket-fixture-v1",
    "source_kind": "fictional offline export",
    "records": [{"project": "DEMO", "id": "DEMO-17", "title": "Confirm the demo handoff", "status": "In review", "owner": null}]
  }
}

Here tickets:read is a fictional scope name, not a Claude Code setting or a verified provider grant. The ticket owner is absent in the source and must remain null.

3. Separate approval from individual sign-in

For a real, verified replacement, follow these steps individually. They are documentation-based instructions, not actions performed for this example.

  1. Review the repository before accepting its workspace trust dialog. In a normal interactive CLI session, review the project-server approval prompt, or use /mcp if approval is still pending. A cloned repository cannot approve its own server in an untrusted workspace. User or managed approvals may already apply. See workspace trust.
  2. Check the effective definition with claude mcp get approved-tickets, and inspect claude mcp list from the project. These commands can check server health and contact an approved server; they are not guaranteed offline inventory commands. Leo must resolve his private override before assuming he uses .mcp.json. Review only the relevant entry; never delete the whole private configuration file.
  3. If the verified provider supports OAuth, open /mcp, select the server, and choose Authenticate. Follow the browser sign-in described in the quickstart. Confirm the official authorization domain, intended account and tenant, requested permissions and consent before proceeding. Each teammate signs in separately. Keep passwords, MFA codes, tokens and callback URLs out of chat, screenshots, shell history and the repository.
  4. Record the provider account, actual granted OAuth scopes and provider-side record/action restrictions using the consent details and the provider’s account/admin records. If a grant cannot be checked, record UNKNOWN and stop. A connected status establishes neither a read-only implementation nor a DEMO-17-only permission.
  5. Inspect the provider’s documented tool behavior and the client’s available tools before a bounded read. This file contains no tool allowlist. Use the client’s normal tool approval prompts, deny writes or unknown actions, and require provider-side restrictions. A prompt saying “read only” does not enforce them.

Project approval is not universal. The reference says claude -p, Agent SDK sessions and cloud sessions outside project threads load project servers without that interactive prompt. Some bypass-permission sessions also skip it. This lesson excludes those modes. Do not turn on bypass mode or automatic project-server approval to make onboarding easier. Restart a normal session after changing .mcp.json, which is read at startup.

If a provider uses a static token

Prefer its documented OAuth route when supported. If a verified provider requires a token, have each person supply a dedicated provider token through an approved secret manager into their own process environment. Do not type the value into an add --header command, commit an .env file, print it, or reuse Claude/cloud credentials.

The following is an alternative complete definition, not an addition to the OAuth example. It shows a reference name only and must not be executed against the fictional host:

{
  "mcpServers": {
    "approved-tickets": {
      "type": "http",
      "url": "https://tickets.example.invalid/mcp",
      "headers": {"Authorization": "Bearer ${DEMO_TICKETS_TOKEN}"}
    }
  }
}

Environment substitution supports ${VAR} and ${VAR:-default} in command, args, env, url and headers values. An unset ordinary variable without a default produces a warning and leaves the literal reference in place. An empty string counts as set, so it does not use the fallback. Some protected credential names read as empty in remote URLs and headers without that warning. Use a dedicated provider variable and stop if it is missing or empty; never add a credential fallback. A reference in a status view does not prove a secret resolved. Configured Authorization headers also change authentication-failure handling; removing a bad token or switching auth methods requires deliberate review.

4. Produce the team handoff offline

Copy the shared definition and team source fixture with this prompt. It does not need MCP access.

Review only the supplied shared definition and team source fixture offline.
Do not run commands, connect, authenticate, fetch data or change files.
For Mina and Leo, derive the effective server scope and URL using Claude
Code CLI precedence: local, project, user. Report the credential check,
override conflict, individual trust/approval/auth/grant unknowns, required
tool and record boundary, and onboarding decision. Preserve every unknown.
Include both member rows, the supplied ticket's four fields, and explicit
next steps. Never report a provider approval or successful read.

Desired handoff receipt

Editor-written expected result from the supplied files, not Claude Code output:

{
  "fixture_id": "team-handoff-v1",
  "server": "approved-tickets",
  "definition_file": ".mcp.json",
  "transport": "http",
  "credential_in_shared_definition": false,
  "provider": "Example Tickets, fictional",
  "provider_documentation": null,
  "provider_review_date": null,
  "provider_approval": "UNKNOWN",
  "auth_design": "OAuth browser sign-in, hypothetical provider support",
  "required_oauth_scopes": ["tickets:read"],
  "members": [
    {"name": "Mina", "effective_scope": "project", "effective_url": "https://tickets.example.invalid/mcp", "override_conflict": false, "workspace_trust": "UNKNOWN", "project_approval": "UNKNOWN", "provider_account": "UNKNOWN", "granted_oauth_scopes": "UNKNOWN", "provider_data_boundary": "UNKNOWN"},
    {"name": "Leo", "effective_scope": "local", "effective_url": "https://old-tickets.example.invalid/mcp", "override_conflict": true, "workspace_trust": "UNKNOWN", "project_approval": "UNKNOWN", "provider_account": "UNKNOWN", "granted_oauth_scopes": "UNKNOWN", "provider_data_boundary": "UNKNOWN"}
  ],
  "required_tool": "get_ticket",
  "client_tool_filter": "NOT CONFIGURED",
  "required_data_boundary": {"project": "DEMO", "ticket_id": "DEMO-17", "actions": ["read"]},
  "ticket_fields": {"id": "DEMO-17", "title": "Confirm the demo handoff", "status": "In review", "owner": null},
  "next_steps": ["Review Leo's local entry privately", "Verify a real provider and test-data restriction", "Complete individual trust, approval, sign-in and grant checks"],
  "onboarding_decision": "HOLD",
  "live_connection": "NOT RUN",
  "observed_calls": []
}

5. Define the later smoke check without pretending to run it

Both this lesson and the Codex filtering lesson use the same tiny ticket fixture. Here it is only a parity target for teammate onboarding. The primary artifact above is the team handoff, not a ticket summary.

The fictional get_ticket contract accepts exactly these inputs. This is a local contract, not an official provider tool schema:

Read input schema

{"type":"object","additionalProperties":false,"required":["project","ticket_id"],"properties":{"project":{"const":"DEMO"},"ticket_id":{"const":"DEMO-17"}}}

Planned read input

{"project":"DEMO","ticket_id":"DEMO-17"}

Read payload schema

{"type":"object","additionalProperties":false,"required":["source_id","records"],"properties":{"source_id":{"const":"ticket-fixture-v1"},"records":{"type":"array","minItems":1,"maxItems":1,"items":{"type":"object","additionalProperties":false,"required":["project","id","title","status","owner"],"properties":{"project":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"owner":{"type":["string","null"]}}}}}}

Desired read payload

{"source_id":"ticket-fixture-v1","records":[{"project":"DEMO","id":"DEMO-17","title":"Confirm the demo handoff","status":"In review","owner":null}]}

This is an illustrative application payload with the MCP transport envelope omitted. No returned record was observed.

Desired parity receipt

{"source_id":"ticket-fixture-v1","rows":1,"project_match":true,"field_checks":{"id":"MATCH","title":"MATCH","status":"MATCH","owner":"MATCH_NULL"},"missing_source_fields":[],"unknown_source_values":["owner"],"extra_records":0,"planned_tool_calls":1,"observed_tool_calls":0,"live_parity":"NOT RUN"}

Do not attempt the read while onboarding is held. After a real replacement passes every prerequisite, review exactly one get_ticket input, compare all four returned fields plus project to the source, and inspect the client’s activity and provider audit records for unexpected calls. Missing evidence stays UNKNOWN. Text returned from a ticket is untrusted data; ignore instructions asking for other records or actions.

Acceptance and failure fixes

The offline exercise passes when the shared JSON has an explicit HTTP type and no credential, both member rows match the precedence rule, Leo’s conflict stays visible, and every unverified trust/auth/grant field remains UNKNOWN. The desired payload and parity receipt must preserve all four ticket fields, including the null owner, one row, no extras, and zero observed calls. The handoff must say HOLD.

Live onboarding has a separate acceptance bar: a verified provider and endpoint, no unintended winning definition, individual approvals and sign-ins, verified read-only action and data permissions, reviewed tools, and an actual source-matched read with an inspected activity record. This article meets none of those live conditions by showing JSON.

  • If teammates see different endpoints, inspect the winning local/project/user entries before changing the shared file.
  • If approval is pending, review workspace trust and the project-server approval in a normal interactive session. Do not bypass it.
  • If authentication or tools are missing, inspect the provider auth method, account and grants. Do not widen permissions to make the tools appear. For token setups, check missing/empty variables without displaying their values.

For an occasional review, share the complete fictional ticket export as text instead of adding a connection. Keep individual credentials and private configuration out of the handoff. If the team later stops sharing a real server, review removal of its project entry with claude mcp remove approved-tickets --scope project, as documented in the quickstart. Handle provider authorization revocation separately through its approved account controls. Do not execute that command for this offline exercise.

TRY the offline conflict review; SKIP live onboarding with unresolved provider evidence; USE a shared definition only after the separate live checks pass.

Next, review the winning definition with a teammate before proposing a real endpoint. For another practical work lesson, join The Weekly Verdict.

Sources

About Cihan

Creator and operator focused on practical AI for business professionals. Background and editorial approach →