create-mcp-json
Create an mcp.json client configuration from a server.json. Use when the user wants to generate a ready-to-use MCP client config for connecting to an MCP server.
Best use case
create-mcp-json is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Create an mcp.json client configuration from a server.json. Use when the user wants to generate a ready-to-use MCP client config for connecting to an MCP server.
Teams using create-mcp-json should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/create-mcp-json/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How create-mcp-json Compares
| Feature / Agent | create-mcp-json | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Create an mcp.json client configuration from a server.json. Use when the user wants to generate a ready-to-use MCP client config for connecting to an MCP server.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# create-mcp-json
## Sequencing Checklist
- [ ] Confirm a `server.json` is already in context (if not, ask user or suggest `/create-server-json`)
- [ ] Read the `server.json` and identify all `packages` and `remotes` entries
- [ ] Apply any user constraints from `$ARGUMENTS`
- [ ] Generate one mcp.json entry per `packages` item and one per `remotes` item
- [ ] Write descriptions that explain **when to reach for this server** (not just copy server.json)
- [ ] Pin all packages to specific versions (never `@latest`)
- [ ] Present the result and ask the user which output format they want
- [ ] Validate the generated file against `docs/mcp.schema.json` using `ajv`
- [ ] Fix any validation errors and re-validate until it passes
Generate a ready-to-use `mcp.json` client configuration from an MCP server's `server.json`.
The user provided this context about the configuration they want:
```
$ARGUMENTS
```
## Prerequisites
A `server.json` for the target server MUST already be in context before running this skill. If one is not present:
1. Ask the user to provide the `server.json`, OR
2. Suggest running `/create-server-json` first to generate one
Do NOT attempt to create an mcp.json without a server.json to derive it from.
## What is mcp.json?
An `mcp.json` is a **client-side configuration** that tells an MCP client (Claude Code, Claude Desktop, VS Code, Cursor, etc.) exactly how to connect to and run MCP servers. It is the fully-resolved, concrete form of what a `server.json` describes abstractly.
Think of it this way:
- `server.json` = "Here's how this server *can* be configured"
- `mcp.json` = "Here's exactly how this client *will* connect to its servers"
Reference the full mcp.json specification at: `docs/MCP_JSON.md` in this repository.
## Instructions
1. Read the `server.json` already in context
2. If `$ARGUMENTS` includes constraints (e.g., "read only tools", "no write access", "minimal env vars"), factor those into the configuration — for example by selecting specific `packageArguments` or omitting optional environment variables
3. Generate one mcp.json entry per `packages` item AND one per `remotes` item in the server.json
4. Present the result and ask the user which output format they want (see [Output Formats](#output-formats))
## Transformation Rules
### From `packages[]` (stdio servers)
| server.json field | mcp.json field | Notes |
|---|---|---|
| `title` | `title` | Direct copy |
| `description` | `description` | See [Writing descriptions](#writing-descriptions) |
| `packages[N].transport.type` | `type` | Usually `"stdio"` |
| `packages[N].registryType` / `runtimeHint` | `command` | See command mapping below |
| `packages[N].identifier` + `packageArguments` | `args` | See args construction below |
| `packages[N].environmentVariables` | `env` | Include ALL env vars as `${ENV_VAR_NAME}` templated variables — see [Environment variable handling](#environment-variable-handling) |
#### Command mapping
| `registryType` | `runtimeHint` | `command` |
|---|---|---|
| `npm` | `npx` (default) | `"npx"` |
| `pypi` | `uvx` (default) | `"uvx"` |
| `oci` | — | `"docker"` |
#### Version pinning
**ALWAYS** pin to a specific version — never use `@latest`, `@^1.0.0`, or leave the version off. This avoids supply chain attacks where a compromised latest version gets pulled automatically on every launch.
- **npm**: `@modelcontextprotocol/server-github@0.6.2` not `@modelcontextprotocol/server-github` or `@modelcontextprotocol/server-github@latest`
- **pypi**: `weather-mcp-server==0.5.0` not `weather-mcp-server` or `weather-mcp-server@latest`
- **oci**: `docker.io/mcp/server:1.0.2` not `docker.io/mcp/server:latest`
If the server.json has no `version` field, look it up on the package registry (PyPI, npm, etc.) to find the latest version and pin to that. Note the version you chose in the output.
#### Args construction
- **npm**: `["-y", "<identifier>@<version>", ...packageArguments]`
- **pypi**: `["<identifier>==<version>", ...packageArguments]`
- **oci**: `["run", "-i", "--rm", ...runtimeArguments, "<identifier>:<version>", ...packageArguments]`
For `packageArguments`, resolve them as follows:
- `"positional"` args: append `value` directly
- `"named"` args: append `name` then `value` (e.g., `"--host", "localhost"`)
- If the argument has `isRequired: true` and no `value`, use `valueHint` as a placeholder comment or ask the user
### From `remotes[]` (HTTP/SSE servers)
| server.json field | mcp.json field | Notes |
|---|---|---|
| `title` | `title` | From top-level server.json |
| `description` | `description` | See [Writing descriptions](#writing-descriptions) |
| `remotes[N].type` | `type` | `"streamable-http"` or `"sse"` |
| `remotes[N].url` | `url` | Resolve any `{variable}` templates — ask user for values |
| `remotes[N].headers` | `headers` | Secret header values use `${ENV_VAR_NAME}` interpolation |
### Writing descriptions
Do NOT just copy the server.json `description` verbatim — it's often too generic (and capped at 100 chars). Instead, write a description that helps the user instantly understand **when to reach for this server** and **what it can actually do**, especially vs. similar servers.
A good description should answer: "If I'm scanning a list of 20 servers, what tells me *this* is the one I need right now?"
Guidelines:
- **Start with "Use when..."** to frame the description as a trigger — what situation should make the user think of this server
- **Name the concrete actions/tools** the server provides (e.g., "search logs, find error patterns, correlate across services" — not "provides access to logs")
- **Include the scope/platform** when it differentiates (e.g., "CloudWatch Logs" not just "logs")
- **Mention what makes it unique** vs. similar servers (e.g., "cross-service log correlation" is a differentiator vs. a generic log reader)
- Keep it to 1-2 sentences
Examples:
- Bad: `"GitHub API integration"` — too vague, could be anything
- Good: `"Use when you need to work with GitHub repos. Create/manage issues, PRs, branches, and files. Search code, review diffs, and merge PRs."`
- Bad: `"Provides access to AWS CloudWatch Logs"` — doesn't say what you can do with them
- Good: `"Use when debugging or investigating AWS services. Search and filter CloudWatch Logs, find error patterns, and correlate log events across multiple services."`
### Environment variable handling
**Bias towards being explicit.** Do not assume the user has CLIs, credentials, or cloud profiles pre-configured. Include ALL environment variables from the server.json — both required and optional — as `${ENV_VAR_NAME}` templated variables in the `env` block. This makes the configuration self-documenting and ensures the user knows exactly what needs to be set up.
- **All env vars** get included in `env`, using `${ENV_VAR_NAME}` interpolation — the variable name inside `${}` matches the env var key exactly (UPPER_SNAKE_CASE)
- **Secrets** (`isSecret: true`) always use `${ENV_VAR_NAME}` (e.g., `${AWS_SECRET_ACCESS_KEY}`)
- **Non-secrets** also use `${ENV_VAR_NAME}` by default (e.g., `${AWS_REGION}`, `${AWS_PROFILE}`) — don't hardcode values or silently omit them
- **Vars with a `default`** may use the default value directly only if the default is universally sensible; otherwise use `${ENV_VAR_NAME}`
- Examples: `${GITHUB_PERSONAL_ACCESS_TOKEN}`, `${AWS_ACCESS_KEY_ID}`, `${AWS_REGION}`, `${SENTRY_AUTH_TOKEN}`
### Applying user constraints from `$ARGUMENTS`
If the user specifies constraints, apply them:
- **"read only tools"** / **"read only"**: If the server supports tool filtering via `packageArguments` or env vars (e.g., `ENABLED_TOOLS`, `--read-only`), configure accordingly. Note this in the output.
- **"no env vars"**: Omit optional env vars, only include `isRequired: true` vars
- **"minimal"**: Only include required fields, skip `title` and `description`
- **Custom constraints**: Interpret and apply as best as possible, noting what was done
## Output Formats
### Flat mcp.json format (default)
The root object is a map of server names to configurations. This is the format defined in the mcp.json spec:
```json
{
"server-name": {
"title": "Human-Readable Name",
"type": "stdio",
"command": "npx",
"args": ["-y", "@scope/package-name"],
"env": {
"API_KEY": "${API_KEY}"
}
}
}
```
### Claude Code `.mcp.json` format
Wraps servers under an `mcpServers` key. Use this when the user is configuring Claude Code specifically:
```json
{
"mcpServers": {
"server-name": {
"command": "npx",
"args": ["-y", "@scope/package-name"],
"env": {
"API_KEY": "${API_KEY}"
}
}
}
}
```
Note: Claude Code defaults `type` to `"stdio"`, so the `type` field can be omitted for stdio servers. For `sse` or `streamable-http` servers it must be included.
## Examples
### npm package → mcp.json
Given this server.json:
```json
{
"name": "io.github.modelcontextprotocol/server-github",
"title": "GitHub",
"description": "GitHub API integration",
"packages": [{
"registryType": "npm",
"identifier": "@modelcontextprotocol/server-github",
"version": "0.6.2",
"transport": { "type": "stdio" },
"environmentVariables": [{
"name": "GITHUB_PERSONAL_ACCESS_TOKEN",
"description": "GitHub PAT",
"isRequired": true,
"isSecret": true
}]
}]
}
```
Produces:
```json
{
"github": {
"title": "GitHub",
"description": "Create/manage issues, PRs, branches, and files in GitHub repos. Search code, review diffs, and merge PRs.",
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github@0.6.2"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
}
}
```
### pypi package → mcp.json
Given a PyPI server.json:
```json
{
"name": "io.github.example/weather",
"title": "Weather",
"packages": [{
"registryType": "pypi",
"identifier": "weather-mcp-server",
"version": "0.5.0",
"runtimeHint": "uvx",
"transport": { "type": "stdio" },
"environmentVariables": [
{ "name": "WEATHER_API_KEY", "isRequired": true, "isSecret": true },
{ "name": "WEATHER_UNITS", "default": "celsius" }
]
}]
}
```
Produces:
```json
{
"weather": {
"title": "Weather",
"type": "stdio",
"command": "uvx",
"args": ["weather-mcp-server==0.5.0"],
"env": {
"WEATHER_API_KEY": "${WEATHER_API_KEY}",
"WEATHER_UNITS": "celsius"
}
}
}
```
### Remote server → mcp.json
Given a remote server.json:
```json
{
"name": "io.github.example/analytics",
"title": "Analytics",
"remotes": [{
"type": "streamable-http",
"url": "https://mcp.analytics.example.com/mcp",
"headers": [{
"name": "Authorization",
"isRequired": true,
"isSecret": true
}]
}]
}
```
Produces:
```json
{
"analytics": {
"title": "Analytics",
"type": "streamable-http",
"url": "https://mcp.analytics.example.com/mcp",
"headers": {
"Authorization": "Bearer ${ANALYTICS_AUTH_TOKEN}"
}
}
}
```
### OAuth remote → mcp.json (no auth config needed)
```json
{
"linear": {
"title": "Linear",
"description": "Create, update, and search issues, projects, and cycles in Linear. Manage labels, assignees, and workflow states.",
"type": "streamable-http",
"url": "https://mcp.linear.app/mcp"
}
}
```
OAuth is handled out-of-band by the MCP client via well-known metadata endpoints. No explicit auth config is needed in the mcp.json.
## Validation
After writing the mcp.json file, validate it against the schema at `docs/mcp.schema.json` in this repository:
```bash
# Install validator if needed (check first)
which ajv || npm install -g ajv-cli
# Validate the generated file against the schema
ajv validate -s docs/mcp.schema.json -d <path-to-generated-mcp.json> --spec=draft7 --strict=false
```
If validation fails, read the errors, fix the generated file, and re-validate until it passes. Do not consider the task complete until validation succeeds.
### Additional checks (not covered by schema)
Before writing the file, also verify:
- [ ] Secret values use `${ENV_VAR_NAME}` interpolation, not literal values
- [ ] Non-secret env vars with defaults use the default value directly
- [ ] User constraints from `$ARGUMENTS` have been applied and notedRelated Skills
create-target
Scaffold a new target type (e.g., Zed, Windsurf) for universal-ai-config
create-project
Initialize new projects with CAMI capabilities and recommended agent teams. Triggers on "create a new project", "start a new project", "initialize project", "set up project with agents", "what agents do I need for this project", "help me set up my project roster". Guides through project requirements, tech stack detection, agent team recommendations, and full CAMI initialization.
create-pr
JIRAチケットブランチからPRを自動作成するスキル。親ブランチ自動検出、JIRAリンク自動挿入、テンプレートに沿ったPR本文生成を行う。「PR作成」「PRを作って」「/create-pr」などのリクエストで使用。
create-plugin-scaffold
Create a new Cursor plugin scaffold with a valid manifest, component directories, and marketplace wiring. Use when starting a new plugin or adding a plugin to a multi-plugin repository.
create-my-tools-profile
Generate a personalized AI skill based on your configured Zapier MCP tools. Scans your enabled actions and creates instructions that help your AI assistant know when and how to use each tool. Use after setting up tools, or when you want to "create my tools profile", "personalize my assistant", or "make a skill from my tools".
create-issues
Systematic GitHub issue creation from requirements. Analyzes codebase, breaks down requirements into multiple issues with dependencies, proposes detailed issues for review, and creates them after user approval. Triggers: /create-issues, create issues, batch issue creation, requirement breakdown.
create-command
Guide for creating custom Claude Code slash commands with proper structure, argument handling, frontmatter configuration, and best practices. Use when the user wants to create slash commands, custom commands, reusable prompts, or mentions creating/designing/building commands.
--- name: create-book
description: Does a dev editor pass on files created from the create-story-bible skill
ccn:create-topic
Create a new topic file in .notes/ with frontmatter template
acc-create-test-builder
Generates Test Data Builder and Object Mother patterns for PHP 8.5. Creates fluent builders with sensible defaults and factory methods for test data creation.
acc-create-query
Generates CQRS Queries and Handlers for PHP 8.5. Creates read-only query DTOs with handlers that return data without side effects. Includes unit tests.
acc-create-psr18-http-client
Generates PSR-18 HTTP Client implementation for PHP 8.5. Creates ClientInterface with request sending and exception handling. Includes unit tests.