# MCP (/en/docs/guide/mcp)

A public Ziwei MCP: one URL for every client.



*For: someone connecting Ziwei to a chat client for the first time. No library to install, no code to write.*

On Cursor and Claude, install the plugin. The Skill calls `chart` / `to_text` first, then explains. ChatGPT imports a plugin marketplace under [B. Connectors](#b-connectors). Other clients use the same URL and the instructions in [C. When there is no Skill](#c-when-there-is-no-skill).

<Callout title="Address and guarantee">
  * Address: `https://ziwei.x-haose.com/mcp`. Streamable HTTP, no authentication.
  * `chart` and `to_text` are frozen, field-for-field with iztro v2.6.1. 716,314 golden cases, zero tolerated deviations. That is a reproduction target, not a ruling on schools. See [Accuracy](/en/docs/guide/about/accuracy).
</Callout>

A local stdio process does not apply: this is public HTTP, and there is no command to start. Names, required fields and response shapes are written in the second half of this page.

<Callout title="Opening it in a browser does not show an article">
  `/mcp` is the endpoint a client connects to, not a docs page. Read this page. Copy the address above.
</Callout>

## A. Install the plugin [#a-install-the-plugin]

On Cursor and Claude, install the plugin. The plugin ships the Skill, and the Skill calls `chart` or `to_text` before any reading.

<Callout title="The Skill forces a tool call first">
  The Skill is `plugin/shared/skills/ziwei/SKILL.md` in [x-ziwei](https://github.com/x-haose/x-ziwei). No tool result means no chart. Call `chart` and/or `to_text`, then interpret in plain language. Do not invent a third tool. There is no `lookup`. If a tool fails, say so. Do not fill in a fake chart, and do not guess the hour.
</Callout>

### Claude Code [#claude-code]

**This is the user install today.**

```bash title="Claude"
claude plugin install ziwei --marketplace x-haose/x-ziwei
```

<Steps>
  <Step>
    Run the command above. In a session: 

    `/plugin marketplace add x-haose/x-ziwei`

    , then 

    `/plugin install ziwei@x-ziwei`

    .
  </Step>

  <Step>
    Ask for a chart in plain language. The reply calls 

    `chart`

     or 

    `to_text`

     first.
  </Step>

  <Step>
    The tool list should show 

    `chart`

     and 

    `to_text`

    , and nothing else.
  </Step>
</Steps>

<Accordions>
  <Accordion title="Contributors only: --plugin-dir">
    Load the directory from [x-ziwei](https://github.com/x-haose/x-ziwei) without the marketplace. Contributors only:

    ```bash title="Claude"
    claude --plugin-dir ./plugin/claude
    ```
  </Accordion>
</Accordions>

The plugin's `.mcp.json` uses `type: http` (Claude Code also accepts the alias `streamable-http`). No authentication. Components stay at the plugin root. They do not go inside `.claude-plugin/`.

### Cursor [#cursor]

The user path is install, reload, then ask in plain language. No terminal.

The official Marketplace listing **is not submitted, so you cannot install from the store today**. Do not read the steps below as something you can finish in the store right now. Once it is listed, install it from the Marketplace.

Team and Enterprise can import from the repo today. That is still not the public store: Dashboard → Plugins & MCPs → Import. An admin imports the [x-ziwei](https://github.com/x-haose/x-ziwei) repository. Members then enable the plugin in Cursor.

<Steps>
  <Step>
    Install the plugin. Team and Enterprise use the repo import above. After the store listing exists, install it from the Marketplace.
  </Step>

  <Step>
    Reload the window (Developer: Reload Window).
  </Step>

  <Step>
    Ask in plain language, for example “阳历 2000-8-16 寅时女命，排紫微盘”. The reply calls 

    `chart`

     or 

    `to_text`

     first.
  </Step>
</Steps>

<Accordions>
  <Accordion title="Contributors / smoke test before the listing">
    On a personal machine, before the store listing exists, the only option is to copy the plugin into the local plugin folder. That is not the user install. Run this from the root of [x-ziwei](https://github.com/x-haose/x-ziwei). Copy the directory in. Do not point a symlink outside the repo:

    ```bash title="Cursor"
    mkdir -p ~/.cursor/plugins/local
    rm -rf ~/.cursor/plugins/local/ziwei
    cp -a plugin/cursor ~/.cursor/plugins/local/ziwei
    ```

    The install directory must contain its own `skills/ziwei/SKILL.md`. Cursor does not accept a path that leaves the plugin root. After the copy, reload the window. In Customize, confirm the `ziwei` plugin, the skill, and the MCP URL `https://ziwei.x-haose.com/mcp`.

    On Team or Enterprise, if Allow Local Plugin Imports is off, this directory is not loaded. If a marketplace plugin of the same name is installed, the marketplace copy wins over the local one.
  </Accordion>
</Accordions>

## B. Connectors [#b-connectors]

ChatGPT installs by importing a plugin marketplace. The steps are below. Clients without a plugin shell put the same public URL into the connector. Those connections do not ship this repo's Skill. After connecting, paste the [instructions in C](#c-when-there-is-no-skill) into the system prompt or custom instructions.

Only entry points that the current docs can check are written here. A product without an official plugin shell is not a published catalog plugin.

### ChatGPT [#chatgpt]

Today's install is **Plugins → Add → Import marketplace**. Set Source to the GitHub repository, authorize GitHub, import the marketplace, then install `ziwei`. A listing in the public plugin directory is a separate path, and it is not ready.

The same Add menu has three items. Each one does a different job:

* **Import marketplace** imports a marketplace from GitHub. This is how you install ziwei. The current Chinese client labels this item **添加插件市场**.
* **Create a plugin** scaffolds a plugin package. The ziwei install is Import marketplace.
* **Record a skill** records a skill. It does not install an MCP server.

<Steps>
  <Step>
    Open Plugins, select Add, then Import marketplace. On the Chinese client, that item reads 添加插件市场.
  </Step>

  <Step>
    On the official admin form, set Source to 

    `https://github.com/x-haose/x-ziwei`

     and leave Path empty. The repository root already has 

    `.claude-plugin/marketplace.json`

    . Codex and ChatGPT also look for 

    `.agents/plugins/marketplace.json`

    ; that file is being added to the repository. Do not enter the manifest filename. Leave Branch, tag, or commit empty to use the default branch.
  </Step>

  <Step>
    Select Import marketplace and authorize GitHub when prompted.
  </Step>

  <Step>
    After the import, install 

    `ziwei`

    . In a chat, type 

    `@`

     and select it.
  </Step>
</Steps>

The official write-up is a workspace admin import: Admin Console → Plugins → Add → **Import marketplace**, with the fields **Source** and **Path**, and the confirm control is also **Import marketplace**. The personal client's Chinese menu says 「添加插件市场」. Whether those two forms have the same fields is not confirmed on a real device. See [Importing and syncing plugin marketplaces from GitHub](https://help.openai.com/en/articles/20001504-importing-and-syncing-plugin-marketplaces-from-github).

<Callout type="warn" title="Web use still needs a real-device check">
  Official text: an imported plugin that declares MCP servers in `mcp.json` or `.mcp.json` may be marked **Desktop only**, even when the server is a remote HTTPS URL. A Desktop only plugin cannot run in ChatGPT on the web. The ziwei plugin ships `.mcp.json`. Whether the web client can use it still needs a real-device check.
</Callout>

<Accordions>
  <Accordion title="Backup: custom MCP">
    This is a separate path. Set the Server URL to `https://ziwei.x-haose.com/mcp`, choose No authentication, then Create as a plugin, install it, and select it in a chat with `@`. Import marketplace does not use this URL.

    This path has no plugin Skill. Paste the [instructions in C](#c-when-there-is-no-skill) into custom instructions. The documented entry is Add custom MCP server. Supported protocols are SSE and streaming HTTP. See [Add custom MCP server](https://developers.openai.com/api/docs/guides/custom-mcp-server).
  </Accordion>
</Accordions>

### Grok [#grok]

On the web, open [grok.com/connectors](https://grok.com/connectors), choose **New Connector**, then **Custom**, and set the URL to `https://ziwei.x-haose.com/mcp`. This service has no authentication. If the dialog asks for auth, leave it empty or skip OAuth. For Grok Business and Enterprise, a team admin must add the connector in the console before members can use it. See [Connectors](https://docs.x.ai/grok/connectors).

Grok Build can also write the config. The command records it in `~/.grok/config.toml`:

```bash title="Grok"
grok mcp add --transport http ziwei https://ziwei.x-haose.com/mcp
```

Or by hand:

```toml title="Grok"
[mcp_servers.ziwei]
url = "https://ziwei.x-haose.com/mcp"
```

See [MCP Servers](https://docs.x.ai/build/features/mcp-servers). Then paste the [instructions in C](#c-when-there-is-no-skill).

### Codex [#codex]

Codex stores a Streamable HTTP server in `~/.codex/config.toml`. A trusted project can use `.codex/config.toml` in the project instead. The ChatGPT desktop app, the Codex CLI and the IDE extension share this file.

```toml title="Codex"
[mcp_servers.ziwei]
url = "https://ziwei.x-haose.com/mcp"
```

The equivalent command:

```bash title="Codex"
codex mcp add ziwei --url https://ziwei.x-haose.com/mcp
```

Do not add a bearer token, and do not run `codex mcp login`. When no credential source resolves, Codex connects without authentication. In the desktop app or the IDE, choose Streamable HTTP and the same URL. See [Model Context Protocol](https://developers.openai.com/codex/mcp).

For the OpenAI Agents SDK on hosted Responses calls, use `HostedMCPTool` with `server_url` set to `https://ziwei.x-haose.com/mcp`. To connect inside the process, use `MCPServerStreamableHttp` with `params["url"]` set to the same address. Neither call should send an Authorization header.

## C. When there is no Skill [#c-when-there-is-no-skill]

Any client that can take a remote MCP URL uses `https://ziwei.x-haose.com/mcp`, with no auth header. When there is no Skill channel, paste one of the blocks below into the system prompt or custom instructions. The rules match the plugin Skill.

### English [#english]

```text title="Instructions"
You interpret Zi Wei Dou Shu charts. The only MCP endpoint is https://ziwei.x-haose.com/mcp. The only tools are chart and to_text.

Rules:
- Never invent a chart, star placement, mutagen, or decade from memory. No tool result means no chart.
- Always call chart and/or to_text first, then interpret in plain language.
- Do not invent a third tool. There is no lookup.
- Interpretation belongs to you. The engine only casts the chart and is gold-aligned with iztro. Do not rewrite the result into a different set of stars.
- If a tool fails, say so. Do not fill in a fake chart, and do not guess the hour.

Solar minimum for both tools: calendar=solar, date=YYYY-M-D, timeIndex=0-12, gender=male or female.
Ask when the hour is unknown. Lunar dates also require leap: notLeap, leap, or leapFixed.
Use chart for the structured chart and to_text for Markdown. For a horoscope, pass targetDate and targetTimeIndex to chart; set includeHoroscope=true on to_text with the same target date and hour.
```

### 中文 [#中文]

```text title="说明"
你是紫微斗数解读助手。公网 MCP 只有 https://ziwei.x-haose.com/mcp，工具只有 chart 与 to_text。

硬规则：
- 禁止凭记忆编造命盘、星曜、四化或大限。没有工具结果就没有盘。
- 先调用 chart 和/或 to_text，再用人话解释。
- 不要发明第三个工具，没有 lookup。
- 解释属于你。引擎只排盘，盘面与 iztro 金标对齐。不要改写成另一套星曜。
- 工具失败就说明错误，不要补假盘，也不要猜时辰。

阳历最短入参（chart 与 to_text 相同）：calendar=solar，date=YYYY-M-D，timeIndex=0-12，gender=male 或 female。
时辰不明先问。农历必须另给 leap：notLeap、leap 或 leapFixed。
要盘面用 chart；要 Markdown 用 to_text。运限时 chart 同时给 targetDate 与 targetTimeIndex；to_text 设 includeHoroscope=true 并带同样的目标日、时。
```

## Compatibility / debugging [#compatibility--debugging]

Pasting JSON only attaches the URL. It does not install the Skill. When a plugin exists, use [A](#a-install-the-plugin). These shapes are for a plugin that did not load, or for a client that only has a config file.

Cursor's user config is `~/.cursor/mcp.json`. For one project only, use `.cursor/mcp.json` in that project. The plugin's own `mcp.json` is this same object:

```json title="Cursor"
{
  "mcpServers": {
    "ziwei": {
      "url": "https://ziwei.x-haose.com/mcp"
    }
  }
}
```

Claude adds `"type": "http"`. For Claude Code, put it in `.mcp.json` at the project root, or under `mcpServers` in your user config. Claude Desktop and claude.ai custom connectors that ask for JSON use the same block:

```json title="Claude"
{
  "mcpServers": {
    "ziwei": {
      "type": "http",
      "url": "https://ziwei.x-haose.com/mcp"
    }
  }
}
```

Cascade (Windsurf / Devin Desktop) uses `serverUrl` for a remote HTTP entry. Open the config from the MCP menu and write it there. The current Devin docs default to `~/.config/devin/mcp_config.json` (or that directory under `XDG_CONFIG_HOME` when it is set):

```json title="Cascade"
{
  "mcpServers": {
    "ziwei": {
      "serverUrl": "https://ziwei.x-haose.com/mcp"
    }
  }
}
```

If other servers are already there, merge the `"ziwei"` entry. Do not replace the whole file. A local stdio MCP server does not apply.

## What to say once it is installed [#what-to-say-once-it-is-installed]

You do not need the parameter names. Say it in plain language and the model fills them in. With the plugin installed, “阳历 2000-8-16 寅时女命，排紫微盘” is enough. The reply must call the tool first.

| You say                                                   | The model calls |
| --------------------------------------------------------- | --------------- |
| "Chart this for me: solar 2000-8-16, Tiger hour, female." | `chart`         |
| "Explain this chart in plain language."                   | `to_text`       |

The first line casts the natal chart for 16 August 2000, Tiger hour, female. Tiger hour is time
index `2` (03:00–05:00). The model converts that itself.

The second line makes the model fetch the chart as Markdown and explain it from that text.
`to_text` returns the facts of the chart (with the built-in knowledge pack by default), not a
finished reading of "how is this person's career". The words are the model's. The numbers are the
tool's.

Say them as two turns, or in one message.

<Callout type="warn" title="Do not let the model place the stars itself">
  It cannot compute stems, branches and star placements reliably, and the mistakes do not look like
  mistakes. The chart comes only from `chart` / `to_text`. If it starts recalling stars from memory,
  tell it to call the tool again. The longer version of this rule is
  [Letting an AI read the chart](/en/docs/guide/guides/llm).
</Callout>

## The frozen contract [#the-frozen-contract]

There are two tools. The required fields and response keys below are the part you can pin: optional
fields may be added later; these names and keys will not be renamed or removed.

The shortest solar input, the one behind "solar 2000-8-16, Tiger hour, female":

```json title="Shortest chart / to_text input"
{
  "calendar": "solar",
  "date": "2000-8-16",
  "timeIndex": 2,
  "gender": "female"
}
```

Both tools share this set of birth parameters:

| Field       | Required           | Values                                                                                         |
| ----------- | ------------------ | ---------------------------------------------------------------------------------------------- |
| `calendar`  | yes                | `solar` or `lunar`                                                                             |
| `date`      | yes                | `YYYY-M-D`, such as `2000-8-16`. Solar years 1583–9999                                         |
| `timeIndex` | yes                | Integer 0–12. 0 is early Zi, 12 is late Zi. See [the table](#hours)                            |
| `gender`    | yes                | `male` or `female`                                                                             |
| `language`  | no                 | Default `zh-CN`. Also `zh-TW`, `en-US`, `ja-JP`, `ko-KR`, `vi-VN`                              |
| `fixLeap`   | no                 | Default `true`. Meaningful for solar dates only                                                |
| `leap`      | required for lunar | `notLeap`, `leap` or `leapFixed`                                                               |
| `config`    | no                 | The six boundary switches. Omit for iztro defaults. See [Config](/en/docs/guide/guides/config) |

The default chart language is simplified Chinese. Feeding the model a Chinese chart is more
reliable than feeding it iztro's English star glosses. See
[Letting an AI read the chart](/en/docs/guide/guides/llm#feed-the-model-a-chinese-chart).

### `chart` [#chart]

The chart as JSON. The response is `{ "astrolabe": { ... } }`, aligned with x-iztro's `to_dto()`.
Contract keys are the language-independent `*_key` fields.

For a horoscope, add a target date. Both fields together, or the response has no `horoscope`:

| Field             | Values                         |
| ----------------- | ------------------------------ |
| `targetDate`      | Solar `YYYY-M-D`               |
| `targetTimeIndex` | 0–12, paired with `targetDate` |

### `to_text` [#to_text]

The same birth parameters, and the response is `{ "text": "..." }`. `text` is Markdown. It is not
the instruction-bearing prompt from `astrolabe_to_prompt`. The format is documented on
[Semantic text](/en/docs/guide/guides/to-text).

| Field              | Default | Meaning                                                                                               |
| ------------------ | ------- | ----------------------------------------------------------------------------------------------------- |
| `knowledge`        | `true`  | `true` inlines the built-in knowledge pack next to the facts; `false` is facts only                   |
| `includeHoroscope` | `false` | When `true`, `targetDate` and `targetTimeIndex` are required. The body is natal chart, then horoscope |

## Hours [#hours]

`timeIndex` is not a clock hour. Zi is split into a head and a tail, so the index runs 0–12.

| Index | Hour        | Clock       | Index | Hour    | Clock       |
| ----- | ----------- | ----------- | ----- | ------- | ----------- |
| 0     | early Zi    | 00:00–01:00 | 7     | Wei     | 13:00–15:00 |
| 1     | Chou        | 01:00–03:00 | 8     | Shen    | 15:00–17:00 |
| 2     | Yin (Tiger) | 03:00–05:00 | 9     | You     | 17:00–19:00 |
| 3     | Mao         | 05:00–07:00 | 10    | Xu      | 19:00–21:00 |
| 4     | Chen        | 07:00–09:00 | 11    | Hai     | 21:00–23:00 |
| 5     | Si          | 09:00–11:00 | 12    | late Zi | 23:00–24:00 |
| 6     | Wu          | 11:00–13:00 |       |         |             |

<Callout type="warn" title="After 23:00 the index is 12, not 0">
  A birth at 23:00–24:00 is late Zi. Say "11pm" or "late Zi", not a bare "Zi".
  The two indexes produce different charts: under the default config, late Zi takes the next day's
  day pillar. See [Config · late Zi hour](/en/docs/guide/guides/config#late-zi-hour-attribution-day_divide).
</Callout>

## What it does not do [#what-it-does-not-do]

* It does not write the reading. `to_text` is the chart in words. The interpretation is what the model says after reading that text.
* It does not accept a chart the model placed itself, or stems and branches the model invented.
* It does not replace embedding the library in your own product. That path is still Rust, Python or Go — see [Getting started](/en/docs/guide/getting-started) and [Letting an AI read the chart](/en/docs/guide/guides/llm).
