← All developer projects

Make an authenticated MCP calculation

Send one authenticated tools/call request to the Cosmic Ephemeris MCP server and save the structured result. This example uses Node’s built-in fetch and needs no extra package.

Available on Free: 500 standard requests per UTC calendar month. No credit card required. This example makes 1 calculation request per run.

A real structured result

The script was run against the live MCP endpoint with the synthetic birth details below. These are selected fields from the returned chart.

{
  "Sun": {
    "lon": 281.0267,
    "sign": "Capricorn",
    "deg_in_sign": 11.0267,
    "speed_deg_per_day": 1.0195,
    "retrograde": false,
    "tropical_lon": 281.0267
  },
  "Moon": {
    "lon": 336.0783,
    "sign": "Pisces",
    "deg_in_sign": 6.0783,
    "speed_deg_per_day": 13.4126,
    "retrograde": false,
    "tropical_lon": 336.0783
  }
}

Download the complete example response. The response contains calculation data, not your API credential.

1. Set up your project

You need Node.js 22+ and a verified Cosmic Ephemeris account. Create a free account and verify your email if you have not already.

  1. Open API Keys and enter a Key label, such as Developer tutorial.
  2. Under Access scopes, select astro:birth-chart, then click Create API key. Selecting a specific scope replaces the default “All calculation endpoints”.
  3. Click Copy key and save the complete key privately. It is shown only once; the shortened prefix in the key list will not work.
mkdir mcp-birth-chart-demo
cd mcp-birth-chart-demo

Already have a key? Reuse it if it includes this tutorial’s scope. One key can serve several projects: select all their required scopes when creating it. You do not need a separate key for each tutorial.

Save your key in a private .env file

Inside the project folder you just created, use your text editor to create a file named .env (not .env.txt). Put this single line in it:

COSMICEPHEMERIS_KEY=PASTE_YOUR_FULL_API_KEY_HERE

Replace PASTE_YOUR_FULL_API_KEY_HERE with the full key you copied. This is a placeholder, not a working key. Keep .env in the same folder where you will run mcp-birth-chart.mjs; the command later uses --env-file=.env to load it.

Create or open .gitignore in that folder and add this line so Git will ignore the key file:

.env

Keep the key on your server or local development computer. Do not put it in browser JavaScript, URLs, screenshots or a public repository. Signing in to this website does not authenticate your Node.js script; it still needs the key. See the authentication guide.

2. Save the complete script

Save this as mcp-birth-chart.mjs, or download the script. It calls POST https://api.cosmicephemeris.com/mcp.

// Node.js 22+; server-side only. No package installation required.
// Set COSMICEPHEMERIS_KEY privately; use the astro:birth-chart scope.
import { mkdir, writeFile } from "node:fs/promises";

class GuideError extends Error {}
const output = "mcp-birth-chart-output";
try {
  const apiKey = process.env.COSMICEPHEMERIS_KEY;
  if (!/^[a-fA-F0-9]{64}$/.test(apiKey ?? "")) {
    throw new GuideError("Set a valid COSMICEPHEMERIS_KEY in your server environment.");
  }
  await mkdir(output, { mode: 0o700 });
  const protocol = "2026-07-28";
  const response = await fetch("https://api.cosmicephemeris.com/mcp", {
    method: "POST",
    redirect: "error",
    signal: AbortSignal.timeout(20_000),
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
      Accept: "application/json, text/event-stream",
      "MCP-Protocol-Version": protocol,
      "Mcp-Method": "tools/call",
      "Mcp-Name": "cosmicephemeris_calculate",
    },
    body: JSON.stringify({
      jsonrpc: "2.0", id: "tutorial-chart-1", method: "tools/call",
      params: {
        name: "cosmicephemeris_calculate",
        arguments: {
          operation: "birth-chart",
          input: {
            date: "1990-01-01", time: "12:00", timezone: "America/New_York",
            lat: 40.7128, lon: -74.006,
          },
        },
        _meta: {
          "io.modelcontextprotocol/protocolVersion": protocol,
          "io.modelcontextprotocol/clientCapabilities": {},
          "io.modelcontextprotocol/clientInfo": {
            name: "cosmicephemeris-tutorial", version: "1.0.0",
          },
        },
      },
    }),
  });
  if (!response.ok) throw new GuideError(`MCP returned HTTP ${response.status}. Check the key, scope and allowance.`);
  const message = await response.json();
  if (message.jsonrpc !== "2.0" || message.id !== "tutorial-chart-1" || message.error) {
    throw new GuideError("The server did not return a successful matching JSON-RPC response.");
  }
  const result = message.result;
  if (result?.isError !== false || result.structuredContent?.status !== 200
      || !result.structuredContent.response?.chart) {
    throw new GuideError("The tool returned a calculation error. No automatic retry was made.");
  }
  await writeFile(`${output}/mcp-response.json`, JSON.stringify(message, null, 2), {
    encoding: "utf8", flag: "wx", mode: 0o600,
  });
  console.log("Created mcp-birth-chart-output/mcp-response.json.");
} catch (error) {
  if (error instanceof GuideError) console.error(error.message);
  else if (error?.code === "EEXIST") console.error("Output folder already exists. Rename it before another run.");
  else console.error("Request or save failed. Check connectivity and folder permissions; do not retry automatically.");
  process.exitCode = 1;
}

3. Run it once

node --env-file=.env mcp-birth-chart.mjs

If your server already sets the environment variable, omit --env-file=.env. Results are saved in the private mcp-birth-chart-output folder. Rename an existing folder before another run; the script checks that before making a request. A failed run may leave an empty or partially completed folder.

Each admitted calculation uses one standard unit, including failed calculations. A successful run uses one unit. A timeout may still consume quota. The script makes no automatic retries. Viewing these sample results and downloading files makes no calculation request.

Read the two result layers

First check the HTTP status and any JSON-RPC error. Then check result.isError and result.structuredContent.status. A calculation can fail inside a completed MCP result even when HTTP returns 200.

The successful calculation is at result.structuredContent.response; its chart is under chart. The script saves the full MCP envelope, including both text and structured content, so you can inspect the exact result.

Connect it to a trusted agent host

This endpoint uses the stateless 2026-07-28 protocol. The protocol version and method headers must match the body, and Mcp-Name must match the selected tool. Legacy initialization and session-ID flows are not enabled. The example sends a direct tools/call request.

An agent host can inspect server/discover and tools/list using the discovery examples. For a calculation, the host supplies authentication outside the tool arguments and passes explicit inputs to cosmicephemeris_calculate. The separate cosmicephemeris_symbolic tool has its own operations and scopes.

The underlying birth-chart HTTP route is https://api.cosmicephemeris.com/api/astro/birth-chart. This tutorial calls the MCP endpoint instead; it is a complete tool request, not an AI chat interface.

Inputs and troubleshooting

If Node says it cannot find .env: run the command from the project folder and check that the filename is exactly .env. If the key is missing or invalid, replace the placeholder with your complete key. If you receive HTTP 403, check the key’s required scope above.

Modern civil dates cover 1800-01-01 through 2200-12-31, subject to route and derived-time limits. Use explicit timezones. Historical inputs require the separate historical date contract; do not substitute BCE years into these date strings. The birth details shown here are synthetic; keep real customer data private.

A missing or malformed key fails before the request. For HTTP 401/403, check your key, account and scope. For 400, check the documented input. For 429, check allowance, key budget and rate or concurrency limits. For a timeout or server error, check service status before deciding whether to rerun.

All developer projects · SDK quickstart · Postman collection